首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >给大模型装上「USB-C」口:MCP 协议入门与实战(TypeScript 示例)

给大模型装上「USB-C」口:MCP 协议入门与实战(TypeScript 示例)

原创
作者头像
用户11136834
发布于 2026-10-01 13:54:07
发布于 2026-10-01 13:54:07
220
举报

前言

过去两年,大模型从"能聊天的机器人"进化成"能干活的助手",但一直有个尴尬的问题:模型本身是座信息孤岛——它不知道你磁盘上的文件、公司数据库里的订单、日历上的会议。每接一个新工具,就要为"某个应用 × 某个工具"单独写一遍胶水代码:M 个应用、N 个工具,就是 M×N 份集成。

MCP(Model Context Protocol,模型上下文协议)就是为解决这件事而生的。它由 Anthropic 于 2024 年 11 月开源,如今已是广泛支持的开放标准:Claude、ChatGPT、VS Code、Cursor 等主流客户端都已支持,腾讯云开发者社区也有专门的 MCP 广场收录各类 Server。MCPMCP

一、MCP 是什么:AI 世界的 USB-C

官方文档有个很形象的类比:MCP 之于 AI 应用,就像 USB-C 之于电子设备。USB-C 出现之前,每个设备一种接口;USB-C 之后,一根线通用。MCP 之前,每个 AI 应用对接每个数据源都要单独开发;MCP 之后,工具方只需实现一次 MCP Server,所有支持协议的客户端都能直接使用——集成复杂度从 M×N 降到 M+N。

二、五分钟看懂架构

MCP 是典型的客户端-服务器架构,三个角色:

  • Host(宿主):AI 应用本体,比如 Claude Desktop、VS Code、Cursor,负责把 MCP 提供的工具注入给大模型;
  • Client(客户端):Host 内部为每个 Server 维护的连接对象,一对一。VS Code 同时连文件系统 Server 和 Sentry Server 时,就会创建两个 Client;
  • Server(服务器):真正提供上下文与能力的程序,可以跑在本机(本地进程),也可以跑在远端(HTTP 服务)。

协议本身分两层:

  • 数据层:基于 JSON-RPC 2.0 的消息协议,负责能力协商、版本发现和各类原语的 list / get / call 调用。以 2026-07-28 版规范为例,协议是无状态的,每个请求的 _meta 字段都携带协议版本与客户端能力,服务端通过 server/discover 上报自身支持的能力;
  • 传输层:负责字节怎么传。两种官方传输方式:stdio(标准输入输出,适合本机子进程,零网络开销)与 Streamable HTTP(HTTP POST + 可选 SSE 流式返回,适合远程服务,支持 Bearer Token、API Key、OAuth 等标准鉴权)。

一次典型的工具调用时序是这样的:

  1. Host 启动/连接 Server,完成能力协商;
  2. Client 调 tools/list 拿到工具清单(名称、描述、JSON Schema 参数);
  3. 大模型根据用户问题和工具描述,决定调用哪个工具、传什么参数;
  4. Client 发 tools/call,Server 执行后返回 content 数组;
  5. 结果回填给模型,模型组织成自然语言答复用户。

三、三大原语:Tools / Resources / Prompts

Server 能向 Host 暴露三种能力(原语),分工非常清晰:

  • Tools 工具:可执行函数,模型可调用(需用户批准)。例如发邮件、查数据库、创建工单。由模型主动调用。
  • Resources 资源:只读的上下文数据,类似文件。例如数据库 Schema、日志片段、API 文档。挂载给模型阅读。
  • Prompts 提示模板:预置的交互模板 / 工作流。例如"代码审查"模板、"周报生成"模板。由用户主动选用。

经验法则:想让模型"做事"就暴露 Tool;想让模型"知道"就暴露 Resource;想把一套用法固化成模板就暴露 Prompt。

四、实战:写一个待办清单 MCP Server

下面用 TypeScript 从零写一个能被 Claude Desktop / Cursor / VS Code 直接使用的待办清单 Server,包含增、查、完成三个工具。环境要求 Node.js 20 及以上版本。

4.1 初始化项目

代码语言:javascript
复制
mkdir todo-mcp && cd todo-mcp
npm init -y
npm install @modelcontextprotocol/server zod
npm install -D typescript @types/node

在 package.json 里加上 "type": "module" 和构建脚本,再放一份常规的 tsconfig.json(target ES2022、module Node16、strict 打开)。

4.2 核心代码 src/index.ts

代码语言:javascript
复制
import { McpServer } from "@modelcontextprotocol/server";
import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
import { z } from "zod";

interface Todo { id: number; text: string; done: boolean }
const todos: Todo[] = [];      // 内存存储,重启即失;生产可换 SQLite
let nextId = 1;

const server = new McpServer({ name: "todo", version: "1.0.0" });

server.registerTool(
  "add_todo",
  {
    description: "添加一条待办事项",
    inputSchema: z.object({
      text: z.string().min(1).describe("待办内容"),
    }),
  },
  async ({ text }) => {
    const todo = { id: nextId++, text: text, done: false };
    todos.push(todo);
    return { content: [{ type: "text", text: "已添加 #" + todo.id + ": " + text }] };
  }
);

server.registerTool(
  "list_todos",
  { description: "列出全部待办事项", inputSchema: z.object({}) },
  async () => {
    const text = todos.length
      ? todos.map(t => "#" + t.id + (t.done ? " [完成] " : " ") + t.text).join("\n")
      : "(清单为空)";
    return { content: [{ type: "text", text: text }] };
  }
);

server.registerTool(
  "complete_todo",
  {
    description: "把指定 id 的待办标记为完成",
    inputSchema: z.object({ id: z.number().int().positive() }),
  },
  async ({ id }) => {
    const t = todos.find(x => x.id === id);
    if (!t) return { content: [{ type: "text", text: "找不到 #" + id }], isError: true };
    t.done = true;
    return { content: [{ type: "text", text: "#" + id + " 已完成" }] };
  }
);

async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
  console.error("todo MCP server running on stdio");
}
main().catch(e => { console.error(e); process.exit(1); });

执行 npm run build 产出 build/index.js,Server 主体就完成了。

4.3 接入客户端

以 Claude Desktop 为例,编辑配置文件(macOS 在 ~/Library/Application Support/Claude/claude_desktop_config.json):

代码语言:javascript
复制
{
  "mcpServers": {
    "todo": {
      "command": "node",
      "args": ["/绝对路径/todo-mcp/build/index.js"]
    }
  }
}

保存后完全退出并重启 Claude Desktop(注意 macOS 要 Cmd+Q 彻底退出)。之后直接说"帮我把写周报加进待办,然后把 3 号勾掉",模型就会自动串起 add_todo → list_todos → complete_todo 一串调用。Cursor 和 VS Code 同样是 mcpServers 配置,格式几乎一致。

4.4 Python 用户的极简版

官方 Python SDK 用装饰器,类型注解和 docstring 会自动生成工具定义,几行就能跑:

代码语言:javascript
复制
from mcp.server import MCPServer

mcp = MCPServer("todo")

@mcp.tool()
async def add_todo(text: str) -> str:
    """添加一条待办事项。

    Args:
        text: 待办内容
    """
    ...  # 与 TypeScript 版逻辑相同

if __name__ == "__main__":
    mcp.run(transport="stdio")

五、踩坑清单(建议收藏)

  1. stdio 模式下千万不要往 stdout 打日志。stdout 就是 JSON-RPC 通道,一个 print / console.log 就能把协议流弄脏,Host 直接解析失败。日志一律走 stderr:Python 用 logging 模块,TypeScript 用 console.error。
  2. 工具的 description 是写给大模型看的,不是写给人看的。写得越准确——做什么、什么时候用、参数含义——模型选对工具的准确率越高;inputSchema 里每个字段都加上 describe()。
  3. 工具粒度要合适。太细(get_user_name 和 get_user_age 分开)会让对话轮次暴涨;太粗(一个 do_everything 万能工具)模型又不会用。一个工具做一件完整的事。
  4. 安全永远第一。Tools 是模型在替用户执行动作:客户端一侧保留"用户批准"弹窗;Server 一侧做最小权限(只读账号、目录白名单);远程 Server 该上的 OAuth / Bearer Token 一个都不能少。
  5. 排查问题先看 Host 的 MCP 日志。Claude Desktop 在 macOS 下是 ~/Library/Logs/Claude/ 目录,mcp-server-*.log 里能看到每个 Server 的 stderr 输出。

六、总结

MCP 把"AI 应用如何连接外部世界"这件事标准化了:工具开发者一次实现处处可用,应用开发者接入生态即插即用,用户手里的 AI 助手真正长出了手和眼。记住三张地图——Host / Client / Server 三角色、Tools / Resources / Prompts 三原语、stdio / Streamable HTTP 两传输——剩下的,就是把你手头那个"每天都手动做一遍"的流程,包成一个属于你自己的 Server。

参考资料

  1. MCP 官方文档:Architecture / Build a Server(modelcontextprotocol.io)
  2. MCP 规范 2026-07-28 版
  3. 腾讯云开发者社区 · MCP 广场测试标题二

这是普通加粗段落。

代码语言:javascript
复制
const a = 1;
  • 列表项一
  • 列表项二

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 前言
  • 一、MCP 是什么:AI 世界的 USB-C
  • 二、五分钟看懂架构
  • 三、三大原语:Tools / Resources / Prompts
  • 四、实战:写一个待办清单 MCP Server
    • 4.1 初始化项目
    • 4.2 核心代码 src/index.ts
    • 4.3 接入客户端
    • 4.4 Python 用户的极简版
  • 五、踩坑清单(建议收藏)
  • 六、总结
  • 参考资料
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档