Skip to content

app-bridge pulls in entire Zod library (~1.4MB pre-minified) - most of it unused #649

@jimchou-dev

Description

@jimchou-dev

Summary

When importing AppBridge and PostMessageTransport from @modelcontextprotocol/ext-apps/app-bridge, the bundle includes ~1.65MB of dependencies (pre-minified), resulting in a 377KB minified bundle for a minimal host app. The vast majority is Zod code that cannot be tree-shaken.

Image

Reproduction

 // Minimal import - just AppBridge for host-side integration
 import { AppBridge, PostMessageTransport } from '@modelcontextprotocol/ext-apps/app-bridge';

Expected bundle impact: ~50KB (bridge + protocol logic)
Actual bundle impact: ~377KB minified (1.65MB pre-minified)

Bundle Analysis (ext-apps@1.7.1)

Package Pre-minified Size Modules
zod@4.3.6 1,386 KB 139
@modelcontextprotocol/sdk@1.27.1 172 KB 6
zod-to-json-schema 53 KB 39
@modelcontextprotocol/ext-apps@1.7.1 42 KB 1
Total 1,653 KB 185

Zod Breakdown

The Zod library is the primary culprit at 1,386KB (84% of total):

Zod Component Size Notes
Locales (48 languages) 485 KB ar, bg, cs, da, de, en, es, fa, fi, fr, he, hu, id, it, ja, ko, nl, no, pl, pt, ru, sv, th, tr, uk, vi, zh-CN, zh-TW, etc.
v4 core + classic 982 KB Full v4 API
v3 compatibility 146 KB Legacy v3 API
v4-mini 33 KB Minimal v4

Why This Happens

  • Zod v4 bundles all locales by default - 48 locale files are included even though most apps only need 1-2
  • Multiple Zod versions included - v3, v4, v4-classic, v4-mini are all bundled
  • Cannot be tree-shaken - The MCP SDK imports from zod which pulls in the full package

Suggested Solutions

  • Use Zod v4-mini - If only runtime validation is needed (not JSON schema generation), v4-mini is ~33KB vs ~1MB
  • Externalize Zod as peer dependency - Let consumers provide Zod, enabling deduplication and locale subsetting:
"peerDependencies": {
 "zod": "^4.0.0"
}
  • Subset locales - Only bundle en locale by default, let consumers add others:
import { z } from 'zod/v4-mini';  // or zod/v4/core with manual locale
  • Lazy-load schema validation - If Zod is only needed for certain operations, dynamically import it

    Environment

  • @modelcontextprotocol/ext-apps: 1.7.1

  • @modelcontextprotocol/sdk: 1.27.1

  • zod: 4.3.6

  • Bundler: Webpack 5.x (production mode)

    Workaround

  • We implemented dynamic import() to lazy-load the app-bridge chunk only when MCP protocol is used, reducing our main bundle from 812KB to 358KB. The MCP chunk (377KB) loads on-demand.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions