新闻详情

新闻详情

首页 / 资讯中心 / 详情

在 TypeScript 中构建剪刀石头布 MCP App:registerAppTool 与 registerAppResource 实战

发布时间:2026/10/2 13:46:16来源:尧图网络
在 TypeScript 中构建剪刀石头布 MCP App:registerAppTool 与 registerAppResource 实战
教程文档人工智能【免费下载链接】mcp-for-beginnersThis open-source curriculum introduces the fundamentals of Model Context Protocol (MCP) through real-world, cross-language examples in .NET, Java, TypeScript, JavaScript, Rust and Python. Designed for developers, it focuses on practical techniques for building modular, scalable, and secure AI workflows from session setup to service orchestration.项目地址https://gitcode.com/GitHub_Trending/mc/mcp-for-beginners点击查看免费下载MCP Apps 是 Model Context Protocol 的一个新范式工具调用返回的不再只是纯数据而是携带了数据应如何被呈现与交互的 UI 组件信息。本篇以mcp-for-beginners课程中的剪刀石头布Rock Paper Scissors实战作业为主线从 15-mcp-apps 章节的作业说明出发逐行讲解 TypeScript 实现中server.ts、src/mcp-app.ts、mcp-app.html三部分各司其职的完整链路。读完本文你将掌握如何用registerAppTool注册带 UI 元数据的工具、用registerAppResource注册组件资源、在前端通过app.callServerTool()调用服务端工具并把整个 App 跑起来在 Visual Studio Code 中验证。MCP Apps为什么工具结果可以携带 UI传统方式下消费 MCP Server 的数据通常需要自己编写并维护一套前端来展示结果。MCP Apps 的设想是服务器不仅回答数据是什么还回答这份数据应该怎么被交互——工具结果的载体是一个自带视觉与交互按钮点击、用户输入等的自包含组件。在 15-mcp-apps 章节说明中这种组件被拆成两个通过resourceUri绑定的半边工具Tool由registerAppTool()注册负责业务逻辑应用资源App Resource由registerAppResource()注册返回打包后的 HTML/JavaScript 作为可渲染 UI。前端方面MCP App 出于安全原因运行在父页面Host 应用的 IFrame 容器中Host 注入 MCP App UI 到 IFrameIFrame 内的事件处理器通过消息与父页面通信父页面再去调用 MCP Server。作业结构只保留有价值的代码作业 README 明确说明解决方案只包含关键代码部分即 markup、事件绑定和服务器特性其结构为my-app server.ts -- the server functionality src mcp-app.ts -- UI, event wire up mcp-app.html -- UI markupserver.ts服务端功能注册工具与组件 UI 资源src/mcp-app.ts前端事件绑定与工具调用mcp-app.html用户界面 markup。作业要求实现一个剪刀石头布游戏UI 需要一个下拉选项列表、一个提交按钮、一个显示双方选择与胜负结果的标签服务端需要一个接收choice输入的剪刀石头布工具由服务端生成电脑选择并判定胜负。服务端注册 play-rps 工具在 作业的 server.ts 中首先通过modelcontextprotocol/sdk的McpServer创建服务实例并引入modelcontextprotocol/ext-apps/server提供的registerAppTool、registerAppResource、RESOURCE_MIME_TYPEimport { registerAppResource, registerAppTool, RESOURCE_MIME_TYPE, } from modelcontextprotocol/ext-apps/server; import { McpServer } from modelcontextprotocol/sdk/server/mcp.js; import fs from node:fs/promises; import path from node:path; import zod from zod; const DIST_DIR path.join(import.meta.dirname, dist); export function createServer(): McpServer { const server new McpServer({ name: Quickstart MCP App Server, version: 1.0.0, });工具与 UI 资源通过资源 URI 绑定作业中定义了ui://get-time/mcp-app.html作为两者之间的纽带const resourceUri ui://get-time/mcp-app.html;registerAppTool是注册带 UI 的工具的关键入口其签名包含服务器实例、工具名、配置标题、描述、inputSchema、_meta.ui.resourceUri以及执行回调registerAppTool( server, play-rps, { title: Play Rock-Paper-Scissors, description: Play a game of rock-paper-scissors with the server., inputSchema: zod.object({ choice: zod.enum([rock, paper, scissors]), }), _meta: { ui: { resourceUri } }, // Links this tool to its UI resource }, async ({ choice }) { const options [rock, paper, scissors] as const; const serverChoice options[Math.floor(Math.random() * options.length)]; let result: string; if (choice serverChoice) { result Its a tie! We both chose ${choice}.; } else if ( (choice rock serverChoice scissors) || (choice paper serverChoice rock) || (choice scissors serverChoice paper) ) { result You win! You chose ${choice} and I chose ${serverChoice}.; } else { result I win! You chose ${choice} and I chose ${serverChoice}.; } return { content: [ { type: text, text: result }, ], }; }, );这里值得注意的两个细节inputSchema用 zod 描述参数zod.enum([rock, paper, scissors])声明choice只能是三个合法取值之一非法输入会在参数校验阶段被拒绝在 完整示例的 FAQ 工具 中zod.string().default(shipping)则演示了可选参数 默认值的写法_meta.ui.resourceUri是 UI 绑定的核心Host 调用该工具后会依据_meta.ui.resourceUri去获取并渲染对应的 UI 资源——这正是 MCP Apps数据 呈现方式一体化的实现机制。服务端注册返回 UI 的组件资源与工具配套服务端必须把组件本身注册为资源。作业中的registerAppResource读取dist目录下由 Vite 打包出的mcp-app.html以RESOURCE_MIME_TYPE返回registerAppResource( server, resourceUri, resourceUri, { mimeType: RESOURCE_MIME_TYPE }, async () { const html await fs.readFile(path.join(DIST_DIR, mcp-app.html), utf-8); return { contents: [ { uri: resourceUri, mimeType: RESOURCE_MIME_TYPE, text: html, _meta: { ui: {} }, }, ], }; }, );注意前端文件是打包后从dist目录读取的DIST_DIR path.join(import.meta.dirname, dist)这意味着运行前必须完成vite build——这也是 package.json 中build与start脚本都包含vite build的原因。前端mcp-app.html 用户界面作业的 mcp-app.html 是纯 HTML包含剪刀石头布所需的三个 UI 元素下拉框、提交按钮、结果展示并通过script typemodule引入事件绑定脚本!DOCTYPE html html langen head meta charsetUTF-8 / titleRock paper scissor/title /head body div classrock-paper-scissors h1Rock Paper Scissors/h1 select idrps-options valuerock option valuerockRock/option option valuepaperPaper/option option valuescissorsScissors/option /select button classselect idrps-button Select/button pResult: code idrps-result.../code/p /div script typemodule src/src/mcp-app.ts/script /body /html前端mcp-app.ts 事件绑定与工具调用src/mcp-app.ts 是前端的大脑创建modelcontextprotocol/ext-apps的App实例将 DOM 元素与事件处理器绑定通过app.callServerTool()调用服务端工具并读取返回内容渲染到页面import { App } from modelcontextprotocol/ext-apps; // Get element references const serverTimeEl document.getElementById(server-time)!; // rps const getRpsBtn document.getElementById(rps-button)!; const rpsResponseEl document.getElementById(rps-result)!; const rpsOptions document.getElementById(rps-options) as HTMLSelectElement; // Create app instance const app new App({ name: Get Time App, version: 1.0.0 }); // Handle tool results from the server. Set before app.connect() to avoid // missing the initial tool result. app.ontoolresult (result) { const time result.content?.find((c) c.type text)?.text; serverTimeEl.textContent time ?? [ERROR]; }; getRpsBtn.addEventListener(click, async () { const userChoice rpsOptions.value; const result await app.callServerTool({ name: play-rps, arguments: { choice: userChoice } }); const rpsResult result.content?.find((c) c.type text)?.text; rpsResponseEl.textContent rpsResult ?? [ERROR]; }); // Connect to host app.connect();关键调用链值得展开说明app.ontoolresult必须在app.connect()之前设置以避免错过初始化阶段的工具结果app.callServerTool({ name, arguments })发送消息到父窗口由父窗口Host代为调用 MCP Server 上的play-rps工具——这正是 MCP Apps 前端与服务器解耦的机制IFrame 内的代码从不直接持有传输层连接返回结果通过result.content?.find((c) c.type text)?.text取出文本内容渲染到code idrps-result。如何运行作业 README 指明参见 code/typescript 的 README并把作业文件中的内容放入对应文件。完整可运行版本位于 code/typescript/my-app运行步骤如下进入my-app目录执行npm install安装前后端依赖校验后端可编译npx tsc --noEmit无输出即通过启动npm start该命令用concurrently同时启动 Vite 构建watch 模式与tsx watch main.ts服务端监听http://localhost:3001/mcp。Windows 用户需要注意package.json 的启动脚本使用了concurrently与cross-env可能需要寻找替代方案start: concurrently \cross-env NODE_ENVdevelopment INPUTmcp-app.html vite build --watch\ \tsx watch main.ts\在 Codespace 环境中需要把端口可见性设为 public并通过https://Codespace 名称.app.github.dev/mcp验证端点可达同时 code/typescript 的 README 提示若使用 basic-host 测试需将serve.ts中的http://localhost:3001/mcp替换为 Codespace 对应的 URL。服务端入口逻辑位于 main.ts默认以 Streamable HTTP 传输模式stateless启动 Express 应用并监听POST /mcp传入--stdio参数则改用 stdio 传输便于命令行调试。在 Visual Studio Code 中测试VS Code 是对 MCP Apps 支持极佳的测试环境。在项目根目录的mcp.json中添加如下服务端条目然后点击start按钮启动{ servers: { my-mcp-server-7178eca7: { url: http://localhost:3001/mcp, type: http } }, inputs: [] }启动后在聊天窗口中输入#play-rps之类的提示词需安装 GitHub Copilot即可触发工具调用并在 VS Code 中看到与浏览器中一致的组件渲染效果。小结围绕 作业 README 定义的三文件结构剪刀石头布 MCP App 完整示范了 MCP Apps 的核心闭环服务端两段式注册registerAppTool注册带_meta.ui.resourceUri的工具registerAppResource注册同一 URI 对应的打包 HTML二者由资源 URI 串联前端解耦调用IFrame 内的App实例通过callServerTool经父窗口间接调用服务端工具ontoolresult负责渲染结果安全沙箱UI 组件在 IFrame 中运行与服务器通信必须经由父页面转发。这种数据 呈现方式一体化的范式让服务器能够携带自包含的交互片段进入任意 Host从而省去为每个 MCP Server 单独编写前端的维护成本。想继续深入实践可以参考章节 04-PracticalImplementation 的后续内容。赞分享教程文档人工智能【免费下载链接】mcp-for-beginnersThis open-source curriculum introduces the fundamentals of Model Context Protocol (MCP) through real-world, cross-language examples in .NET, Java, TypeScript, JavaScript, Rust and Python. Designed for developers, it focuses on practical techniques for building modular, scalable, and secure AI workflows from session setup to service orchestration.项目地址https://gitcode.com/GitHub_Trending/mc/mcp-for-beginners点击查看免费下载相关推荐Mastering GitHub Copilot 实战在 Codespaces 中用配对接手编程构建 Python 石头剪刀布小游戏Mastering GitHub Copilot 实战在 Codespaces 中用配对接手编程构建 Python 石头剪刀布小游戏 本文是 Masterin教程文档人工智能abogen 完整指南把 EPUB 和 PDF 变成带字幕的有声书abogen 完整指南把 EPUB 和 PDF 变成带字幕的有声书 abogen 名字取自 audiobook generator是一款文本转有声书工具AI 应用语音音频媒体生成本地部署从零开始学习CNN用Machine Learning Experiments打造智能石头剪刀布识别系统从零开始学习CNN用Machine Learning Experiments打造智能石头剪刀布识别系统 Machine Learning Experiment上一篇基于 Rube MCP 与 Composio 实现 Zoho Inventory 库存自动化Awesome Codex Skills 实战指南下一篇Haystack 集成指南用 SnowflakeTableRetriever 把 Snowflake 表查询接入 LLM 管线创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

XXL-AI:基于MCP协议的AI工程操作系统 2026/10/2 16:50:18

XXL-AI:基于MCP协议的AI工程操作系统

1. 项目概述:这不是又一个LLM封装工具,而是一套面向真实交付的AI工程操作系统XXL-AI不是把ChatGLM或Qwen简单套个网页壳就叫“平台”的玩具项目。我去年在三个客户现场落地AI应用时,反复被同一个问题卡住:前端要调用通义千问做摘要…

阅读更多 →
Java自学笔记Day1 2026/10/2 16:50:12

Java自学笔记Day1

一、Java简介:1.1 Java简述Java是一门面向对象、编译型 解释型、跨平台的后端编程语言。1.2 简单原理你写的 .java 源代码,通过 javac 编译器,编译成字节码(.class 文件);字节码不直接跑在操作系统上&…

阅读更多 →
芯片‘悄悄话’:从物理异常到系统失效的链路解码 2026/10/2 16:50:12

芯片‘悄悄话’:从物理异常到系统失效的链路解码

1. 标题里的“悄悄话”到底在说什么?“从沙子到车辙(4.1):芯片内部的‘悄悄话’”——这个标题乍看像一句诗,甚至有点文艺,但如果你在半导体产线待过三个月以上,或者拆过三块以上失效的MCU板子&…

阅读更多 →
128K长上下文大模型实战:效果、成本与结构化推理 2026/10/2 16:50:12

128K长上下文大模型实战:效果、成本与结构化推理

1. 项目概述:当“上下文长度”不再是PPT参数,而是真实业务的呼吸节奏“超长上下文大模型哪家好?”——这个问题最近在技术团队晨会、客户方案评审、甚至产品经理的OKR对齐会上,出现频率高得有点反常。它不再是个纯学术讨论&#x…

阅读更多 →
小家电复位电路为何淘汰RC?EY404智能复位IC实战解析 2026/10/2 16:50:05

小家电复位电路为何淘汰RC?EY404智能复位IC实战解析

1. 为什么小家电的复位电路正在集体“淘汰RC”?你拆过手边那台电饭煲、空气炸锅或者智能咖啡机的主板吗?十有八九,在主控芯片(通常是某款国产32位MCU)的RESET引脚旁边,会看到一个不起眼的RC网络&#xff1a…

阅读更多 →
物联网设备批量创建的四大实战方法与避坑指南 2026/10/2 16:50:05

物联网设备批量创建的四大实战方法与避坑指南

1. 项目概述:为什么批量创建设备不是“点几下鼠标”的事,而是云平台落地的第一道硬门槛物联网云平台批量创建设备,听起来就是上传个表格、点个按钮、等几分钟的事——但我在过去三年里帮二十多家制造、能源、农业类客户做平台接入&#xff0c…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉