For AI agents: the complete documentation index is available at https://scriptedalchemy.github.io/agent-bundle/zh/llms.txt, the full documentation bundle is available at https://scriptedalchemy.github.io/agent-bundle/zh/llms-full.txt, and this page is available as Markdown at https://scriptedalchemy.github.io/agent-bundle/zh/examples/mcp-app.md.
跳至主要内容
  • 简体中文
  • MCP App

    一条服务就绪度工作流,只表达一次,却输出为宿主能触达的每一种表面:一个真实的本地 MCP 服务器、一个带 类型的工具、一个交互式 MCP App 资源、一个 Skill、一个 session-start 钩子、一个夹具检查脚本,以及一个 确定性 eval。当你想看清这些表面如何拼在一起、而不是单独研究其中之一时,就该读这个示例。

    • 在仓库根目录运行: pnpm example:mcp-app
    • 包名: @agent-bundle-example/mcp-app
    • 公开依赖: agent-bundle(workspace:*)、@agent-bundle/runtime、react、zod;浏览器端 App 测试还用到 @rstest/browser、@rstest/core 与 playwright
    • Target: portable、codex、claude,每个 target 都带有 status 服务器及其 App
    • 凭据: 不需要,eval 与夹具检查只读取签入的数据
    • 源码: examples/mcp-app

    它证明什么

    • 路由就是注册。 配置里没有写任何服务器、工具、资源或 App。status 服务器之所以存在,是因为 src/mcp/status/** 下有三个路由模块:tools/show-status.tsx(一个服务的健康状况)、 resources/readiness-policy.tsx(位于 policy://mcp-app-example/readiness 的发布规则),以及 apps/status.ts + status.html(工具通过 _meta.ui.resourceUri 打开的 App,用 appResourceUri('status') 只拼写一次)。show-status 使用 defineTool,让 App 绑定、schema 与 处理器留在同一个定义中。没有手写的 McpServer、没有 registerTool,也不依赖 @modelcontextprotocol/server。见MCP 服务器与 MCP App。

    • 生成的 stdio 生命周期不由你来写。 构建输出服务器入口及其生命周期外壳:console 重定向到 stderr 的 守卫、信号处理、stdin EOF 退出、有界关停与心跳。

    • MCP App 是编译出来的资源,不是被服务的页面。 App 只编译一次,位于产物根目录的 mcp-apps/status.html,带有稳定的 resourceUri,并被内联进生成的 status 服务器入口,而所有选中 宿主都从同一个根目录启动这个入口。

    • 降级证据是一等公民。 src/service-status.ts 持有 schema 以及 compiler 与 payments-api 健康记录,而 payments-api 故意返回降级的延迟数据。有意思的输出是一项被如实报告的失败检查,而不是 一张全绿截图。

    • 浏览器表面自成一个证明级别。 tests/browser-app/status-panel.browser.test.ts 通过 agent-bundle/test/browser 把生产编译出的 App HTML 挂载到产品桥接之上,也就是 测试中的 browser-app 级别。

    • App 是桥接的客户端,而不是自带 transport。 src/mcp/status/apps/status.ts 从 agent-bundle/app 创建客户端,通过 onToolInput / onToolResult 接收打开 App 的 show-status 输入与结构化结果,并用 注册在 tool:status/show-status 上的 onToolError 展示失败或缺少结构化数据的打开结果; 当宿主的 initialize 结果指定 show-status 为打开工具时,这些路由监听器才会触发; onToolCancelled 则独立展示被宿主取消的开场调用。Refresh status 为屏幕上的服务再次调用同一个 show-status 工具,Read policy 通过 request('resources/read', …) 读取 readiness-policy 资源。路由 id、输入与结果由生成的 .agent-bundle/routes.d.ts 提供类型,因此 App 自己不声明任何契约 表。视图中不再保留 JSON-RPC id、pending map、postMessage('*') 或 structuredContent 解包逻辑。详见 带类型的 App 客户端。

    • web 表面装在产物里。 该示例配置了 web: { apps: [{ app: 'status/status', tool: 'show-status', allow: ['call-tool'] }] }, 因此即使没有 src/cli/**,组合根目录的 agent-bundle.manifest.json 也会带上 web 节,并输出 bin/mcp-app-example.mjs。从已构建产物运行:

      node artifact/bin/mcp-app-example.mjs web --no-open

      它会打印就绪行,并在 loopback 上提供 status App。agent-bundle dev 在 /web/status/status 提供同一页面。见在浏览器中暴露 App。

    编写了什么

    路径是什么
    src/service-status.ts服务 schema 与两条健康记录。
    src/mcp/status/tools/show-status.tsxdefineTool 路由;其内联 _meta.ui.resourceUri 打开 App。
    src/mcp/status/resources/readiness-policy.tsxpolicy://mcp-app-example/readiness 资源路由。
    src/mcp/status/apps/status.ts / status.html编译为 mcp-apps/status.html 的 MCP App 入口与模板。
    src/skills/service-readiness/做出服务就绪度判断所需的证据、检查与报告。
    src/hooks/session-start.ts把就绪度工作流加入兼容宿主的会话。
    src/scripts/check-service-fixture.ts在发布演练之前校验签入的编译器夹具。
    evals/status.eval.ts确定性的 mcp-app-status 套件及其 status-is-healthy 用例。

    在 Workbench 中操作

    1. 在 Application → Skills 下选中 service-readiness。它的文档默认渲染;用检查器查看源码/生成 输出、资源与 eval 覆盖。
    2. 在 Application → Events / Hooks 下选中已配置的 sessionStart 钩子,并选择 Claude 夹具。运行它 以检视规范输入、返回的上下文,以及 Claude 投影。
    3. 在 Application → Scripts 下选中 check-service-fixture 并运行。输出的检查器会解析自己输出模块 旁边打包好的状态夹具,因此它的成功与 shell 的工作目录无关。
    4. 在 Application → MCP → status → Apps 下选中 status App。工作区会针对已发布的构建打开一个会话, 并把 show-status 绑定到该 App;选择一个服务并点击 Call tool and preview,面板就会渲染在工具结果 旁边。Advanced → Artifact 显示复合插件根目录,无论选中哪个 target,mcp-apps/status.html 都出现在 这里。
    5. 在存在两次 eval 运行之前,Advanced → Evals → Compare 会刻意显示 At least two recorded runs are needed before a comparison can be aligned.,这是精确的空状态, 不是错误。
    6. 打开 Advanced → Protocol,选择 portable 与 status 服务器,打开会话、列出工具、选择 show-status、选中 payments-api 并调用它。调用历史会显示降级摘要,以及标注了 Availability 与 P95 latency 的检查,其中后者失败。打开 App 预览:渲染出的面板通过 MCP Apps 桥接展示同一条记录, 并带一个以文字标注的琥珀色 degraded 指示;Refresh status 与 Read policy 调用的是真实的工具 与资源。检视协议轨迹、使用 Restart MCP session,然后关闭、 重置并重新打开会话,以演练整个生命周期。 随后打开 Trace,查看通过会话 id 与 JSON-RPC 请求 id 关联起来的 MCP 请求、响应、通知与会话活动。
    7. 在 Advanced → Evals → Runs 中选中 mcp-app-status,运行 status-is-healthy,查看归属于 service-readiness 的那次已完成且通过的试次。

    如果你修改了某个源文件,请重建并等到 Failed 或 Idle 状态再判断结果;Building 状态仍在进行中。

    非交互检查

    在仓库级 pnpm build 之后:

    cd examples/mcp-app
    pnpm validate
    pnpm build
    pnpm typecheck
    pnpm exec agent-bundle eval --case status-is-healthy --trials 1

    pnpm check 在不打开 Workbench 的情况下依次运行校验、构建和类型检查。

    在 stdio 上运行服务器

    pnpm exec agent-bundle mcp run --server status --target portable

    mcp run 会从 portable target 的 MCP 清单解析出生成的入口,并先构建一份临时产物;传入 --artifact artifact 可改为复用 pnpm build 的输出。关闭 stdin 以 0 退出,Ctrl-C 以 130 退出, 每个服务器的状态持久化在 .agent-bundle/mcp-run/portable/status 下。

    该命令默认会加载项目根目录的 .env 集合,包括所选 --mode 的变体。启动环境的优先级是清单 env, 然后是 .env 文件,最后是导出的操作者变量。可重复的 --env-file <path> 会替换那些约定文件, --no-env 跳过它们,而 --plugin-root <path> 只用于复制产物后的演练。完整契约见 运行时环境。