入门案例
用官方 @modelcontextprotocol/sdk 写出第一个可运行的 MCP Server,理解 Transport、工具注册、内容返回三层设计,并在 Cursor 中完成配置调用。
从协议实现视角看,MCP 服务本质上是基于事件流的总线式中间件,其开发模式可以类比 HTTP 服务框架,但需遵循特定的消息交换协议。以 @modelcontextprotocol/sdk 为例,它的架构呈现三个核心设计特征:
-
协议栈实现抽象:通过 Transport 层(如
StdioServerTransport)解耦物理传输与业务逻辑,支持进程间通信、HTTP 等多种通讯方式:const transport = new StdioServerTransport(); // 标准输入输出传输层 await server.connect(transport); // 协议绑定 -
声明式能力注册:采用声明式编程范式定义工具端点,通过 Zod 模式校验实现强类型约束:
server.tool( 'add', // 工具标识符 { a: z.number(), b: z.number() }, // 输入模式 async ({ a, b }) => ({ // 执行闭包 content: [{ type: 'text', text: String(a + b) }], }) ); -
上下文序列化规范:响应体需构造多模态内容流,
content数组支持 text/markdown/code 等 MIME 类型,并支持分块流式传输。
1. 完整示例
import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { z } from 'zod';
const main = async () => {
// Create an MCP server
const server = new McpServer({
name: 'Demo',
version: '1.0.0',
});
// Add an addition tool
server.tool('add', { a: z.number(), b: z.number() }, async ({ a, b }) => ({
content: [{ type: 'text', text: String(a + b) }],
}));
// Start receiving messages on stdin and sending messages on stdout
const transport = new StdioServerTransport();
await server.connect(transport);
console.log('Server started');
};
main();代码逻辑很简单,核心两步:
- 创建
McpServer实例对象,之后调用server.tool增加 MCP 服务能力;在tool回调中可以接受参数、做任意逻辑调用,之后通过{content: [{type: 'xxx', text: ''}]}格式返回数据。 - 创建
StdioServerTransport对象,实现传输通讯能力。
就是这么简单,此后只需在工具上正确配置 MCP 服务细节即可。以 Cursor 为例:
2. 在 Cursor 中配置
-
进入配置页面,点击 features => add new mcp server:
🖼️ 配图待补:Nok6bLv5MozrFVxHThrctl0TnoD
-
在弹出的 JSON 文件中添加配置:
🖼️ 配图待补:EPjJbD5ulokNOgxgcjNcsfaCnJb
注意:
- 在我们的 demo 中,type 类型必须选择为
command; - Command 中必须提供文件的绝对路径。
- 在我们的 demo 中,type 类型必须选择为
-
配置完成并执行成功后,MCP servers 配置节会显示所有可用 MCP,注意观察左边的状态是否为绿色点:
🖼️ 配图待补:Emo8boR0NoOFo5x23oIcHnlQnTh
之后在使用 Cursor 的 chat 或 Composer 过程中,Cursor 会根据具体问题有选择性地调用 MCP 服务,完成交互。
