Skip to content

feat: add build app-with-deps target#221

Merged
ochafik merged 1 commit intomainfrom
ochafik/build-app-with-deps
Jan 9, 2026
Merged

feat: add build app-with-deps target#221
ochafik merged 1 commit intomainfrom
ochafik/build-app-with-deps

Conversation

@ochafik
Copy link
Contributor

@ochafik ochafik commented Jan 9, 2026

Summary

Add a new build target app-with-deps that bundles the MCP Apps SDK with all dependencies for standalone use.

Changes:

  • Add build:app-with-deps script to package.json
  • Add bundling logic in build.bun.ts

This should allow module imports from inlined apps, e.g.:

import {
  RESOURCE_MIME_TYPE,
  registerAppResource,
  registerAppTool,
} from "@modelcontextprotocol/ext-apps/server";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";

export function getExampleInlinedAppServerInstance(): McpServer {
  const server = new McpServer({name: 'Example Server', version: '1.0.0'});
  const uiHtml = `
    <html>
      <head>
        <script type="module">
          import { App } from "https://unpkg.com/@modelcontextprotocol/ext-apps@0.3.1/dist/src/app-with-deps.js";

          window.onload = async () => {
            const app = new App({name: "Example UI", version: "1.0.0"});
            app.ontoolresult = params => {
              document.getElementById("tool-result").innerText = JSON.stringify(params, null, 2);
            }
            document.getElementById("open-link-button").onclick = () => {
              app.openLink({url: "https://modelcontextprotocol.io"});
            }
            await app.connect();
          };
        </script>
      </head>
      <body>
        <div id="tool-result"></div>
        <button id="open-link-button">Open Link</button>
      </body>
    </html>
  `;
  const resourceUri = "ui://page";

  registerAppResource(
    server,
    "page",
    resourceUri,
    { 
      mimeType: RESOURCE_MIME_TYPE,
      _meta: {
        ui: {}
      },
    },
    () => ({
      contents: [
        {
          mimeType: RESOURCE_MIME_TYPE,
          text: uiHtml,
          uri: resourceUri,
          _meta: {
            ui: {
              csp: {
                connectDomains: ["https://unpkg.com"],
                resourceDomains: ["https://unpkg.com"],
              },
            },
          },
        },
      ],
    }),
  );

  registerAppTool(
    server,
    "show-example",
    {
      inputSchema: { message: z.string() },
      outputSchema: { message: z.string() },
      _meta: {
        ui: { resourceUri },
      },
    },
    ({ message }: { message: string }) => ({
      content: [],
      structuredContent: { message: `Server received message: ${message}` },
      _meta: { info: "example metadata" },
    }),
  );

  return server;
}

async function main() {
  const server = getExampleInlinedAppServerInstance();
  await server.server.connect(new StdioServerTransport());
}

main().catch((err) => {
  console.error("Error running example MCP server:", err);
  process.exit(1);
});

🤖 Generated with Claude Code

@pkg-pr-new
Copy link

pkg-pr-new bot commented Jan 9, 2026

Open in StackBlitz

@modelcontextprotocol/ext-apps

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/ext-apps@221

@modelcontextprotocol/server-basic-react

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-basic-react@221

@modelcontextprotocol/server-basic-vanillajs

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-basic-vanillajs@221

@modelcontextprotocol/server-budget-allocator

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-budget-allocator@221

@modelcontextprotocol/server-cohort-heatmap

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-cohort-heatmap@221

@modelcontextprotocol/server-customer-segmentation

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-customer-segmentation@221

@modelcontextprotocol/server-scenario-modeler

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-scenario-modeler@221

@modelcontextprotocol/server-system-monitor

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-system-monitor@221

@modelcontextprotocol/server-threejs

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-threejs@221

@modelcontextprotocol/server-wiki-explorer

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-wiki-explorer@221

commit: f89303d

@ochafik ochafik merged commit e078250 into main Jan 9, 2026
19 checks passed
@ochafik ochafik mentioned this pull request Jan 9, 2026
@ochafik ochafik deleted the ochafik/build-app-with-deps branch January 12, 2026 21:29
ochafik added a commit that referenced this pull request Mar 6, 2026
The react-with-deps build entry was introduced in PR #221 (e078250) as a
sibling to app-with-deps for CDN/unpkg no-bundler use. But its external
array was duplicated without editing — it never dropped @modelcontextprotocol/sdk
from externals, so it has shipped byte-identical to ./react for 10 releases
(v0.3.1 → v1.2.0).

After #534 merged, both entries use ['react', 'react-dom', ...PEER_EXTERNALS]
— still identical, just smaller.

Delete rather than fix: React apps always use a bundler; the CDN/unpkg
use case (HTML-string apps like qr-server) doesn't apply to React hooks.
Zero consumers verified (examples/docs/tests/plugins).
ochafik added a commit that referenced this pull request Mar 6, 2026
Reverts the deletion from the previous commit and applies the actual fix.

The react-with-deps external array was copy-pasted in PR #221 without
dropping PEER_EXTERNALS — now it mirrors app-with-deps: bundles
@modelcontextprotocol/sdk + zod for CDN/import-map consumers.

React and react-dom MUST remain external — bundling them would cause
dual-React-instance hooks errors. Consumer provides them via import map.

Before: index.js 26KB == react-with-deps.js 26KB (identical MD5)
After:  index.js 26KB != react-with-deps.js 323KB (SDK+zod bundled)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant