一、MCP 是什么

Model Context Protocol(MCP) 是一套开放协议,用于把 AI 助手和外部能力(数据库、API、文件系统等)标准化地连接起来。MCP 服务端可以对外提供:

  • Tools(工具):AI 可调用的动作,如计算、查接口、写文件等
  • Resources(资源):只读数据,类似 GET 接口
  • Prompts(提示模板):可复用的提示模板

客户端(如 Cursor)通过协议与 MCP 服务通信:先 tools/list 拉取工具列表,再通过 tools/call 传入工具名和参数执行调用。


二、示例:两个工具的定义

下文实现的 MCP 将提供两个工具,其参数与 MCP 的 inputSchema 对应关系如下。

2.1 工具一:add(计算两数之和)

描述:计算两数之和。

参数 Schema(与 MCP 的 inputSchema 对应):

参数 类型 必填 说明
a number 第一个数
b number 第二个数

对应 JSON Schema 示例:

{
  "name": "add",
  "description": "计算两数之和",
  "arguments": {
    "type": "object",
    "properties": {
      "a": { "type": "number", "description": "第一个数" },
      "b": { "type": "number", "description": "第二个数" }
    },
    "required": ["a", "b"],
    "additionalProperties": false
  }
}

2.2 工具二:greet(根据名字返回问候语)

描述:根据名字返回一句问候语。

参数 Schema

参数 类型 必填 说明
name string 对方的名字

对应 JSON Schema 示例:

{
  "name": "greet",
  "description": "根据名字返回一句问候语",
  "arguments": {
    "type": "object",
    "properties": {
      "name": { "type": "string", "description": "对方的名字" }
    },
    "required": ["name"],
    "additionalProperties": false
  }
}

以上 arguments 即 MCP 中工具的 inputSchema,Cursor 会据此生成工具描述并做参数校验。


三、MCP 服务端怎么写(第一个 MCP 的写法)

下面用 Node.js + TypeScript + 官方 MCP SDK 实现一个提供 add 和 greet 的 MCP 服务。

3.1 环境准备

mkdir first-mcp && cd first-mcp
npm init -y
npm install @modelcontextprotocol/sdk
npm install -D typescript @types/node tsx

(若使用 Zod 做参数校验,可再安装 zod。)

3.2 用 TypeScript 实现服务端

协议层面,MCP 要求服务端:

  1. 声明支持 tools 能力
  2. 在 tools/list 中返回工具列表(含 name、description、inputSchema)
  3. 在 tools/call 中根据 name 和 arguments 执行逻辑并返回 content(如文本)

以下示例使用 stdio 传输(标准输入/输出),适合 Cursor 通过“命令行启动子进程”的方式连接。

// index.ts
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";

const server = new Server(
  {
    name: "demo-mcp",
    version: "1.0.0",
  },
  {
    capabilities: {
      tools: {},
    },
  }
);

// 注册工具列表:add、greet
server.setRequestHandler(ListToolsRequestSchema, async () => ({
  tools: [
    {
      name: "add",
      description: "计算两数之和",
      inputSchema: {
        type: "object",
        properties: {
          a: { type: "number", description: "第一个数" },
          b: { type: "number", description: "第二个数" },
        },
        required: ["a", "b"],
        additionalProperties: false,
      },
    },
    {
      name: "greet",
      description: "根据名字返回一句问候语",
      inputSchema: {
        type: "object",
        properties: {
          name: { type: "string", description: "对方的名字" },
        },
        required: ["name"],
        additionalProperties: false,
      },
    },
  ],
}));

// 处理 tools/call:根据 name 执行并返回 content
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;

  if (name === "add") {
    const a = Number((args as { a?: number }).a);
    const b = Number((args as { b?: number }).b);
    if (Number.isNaN(a) || Number.isNaN(b)) {
      return {
        content: [{ type: "text", text: "参数 a、b 须为数字" }],
        isError: true,
      };
    }
    const sum = a + b;
    return {
      content: [{ type: "text", text: `${a} + ${b} = ${sum}` }],
      isError: false,
    };
  }

  if (name === "greet") {
    const nameArg = (args as { name?: string }).name ?? "";
    return {
      content: [{ type: "text", text: `你好,${nameArg}` }],
      isError: false,
    };
  }

  return {
    content: [{ type: "text", text: `未知工具: ${name}` }],
    isError: true,
  };
});

// 使用 stdio 传输,便于 Cursor 以子进程方式启动
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("demo-mcp 已就绪(stdio)");

要点小结:

  • ListToolsRequestSchema:对应协议的 tools/list,返回的 inputSchema 与 Cursor 里看到的 arguments 一致。
  • CallToolRequestSchema:对应 tools/call,根据 name 和 arguments 执行,返回 content(文本)和可选的 isError。
  • StdioServerTransport:通过标准输入/输出与 Cursor 通信,无需自己起 HTTP 服务。

3.3 运行方式

在 package.json 里可加:

"scripts": {
  "start": "tsx index.ts"
}

Cursor 的 MCP 配置里会通过类似 npx tsx index.ts 或 node dist/index.js 启动该进程,并通过 stdio 与它通信。

3.4 在 Cursor 中配置该 MCP 服务

在 Cursor 的 MCP 配置(如全局或项目级设置)中增加一项,例如:

{
  "mcpServers": {
    "demo-mcp": {
      "command": "node",
      "args": ["path/to/demo-mcp/dist/index.js"]
    }
  }
}

若用 tsx 直接跑 TS:

"demo-mcp": {
  "command": "npx",
  "args": ["tsx", "path/to/demo-mcp/index.ts"]
}

配置完成后,Cursor 会启动该进程,发送 tools/list 拿到工具列表,并在需要时发送 tools/call。Cursor 会根据 tools/list 的返回生成或缓存工具描述,供 AI 与调用方使用。


四、在 Cursor 里如何调用(调用方式)

在 Cursor 中,AI 助手不是在终端里输入命令,而是通过内置的 MCP 调用工具 与已配置的 MCP 服务通信。

4.1 使用的“命令”实质:call_mcp_tool

调用方式不是 shell 命令,而是 Cursor 提供的工具调用:

  • 工具名:call_mcp_tool
  • 参数
    • server:MCP 服务标识,即你在配置里填写的服务名(如 “demo-mcp”)
    • toolName:工具名,如 “add” 或 “greet”
    • arguments:该工具需要的参数对象,必须符合该工具的 inputSchema

4.2 调用示例

调用 add(计算 10 + 20):

  • server: “demo-mcp”
  • toolName: “add”
  • arguments: { “a”: 10, “b”: 20 }

返回示例:“10 + 20 = 30”(以 MCP 的 text content 形式返回)。

调用 greet(问候「你」):

  • server: “demo-mcp”
  • toolName: “greet”
  • arguments: { “name”: “你” }

返回示例:“你好,你!”。

4.3 协议层面的对应关系

Cursor 内部会大致完成:

  1. 发现工具:向已配置的 MCP 服务发 tools/list,得到 add、greet 及各自的 inputSchema。
  2. 调用工具:当 AI 决定调用某个工具时,发 tools/call,例如:
    • name: “add”
    • arguments: { “a”: 10, “b”: 20 }
  3. 解析结果:把返回的 content[].text 交给 AI 或展示给用户。

也就是说,“调用命令” 在实现上 = Cursor 根据 AI 的决策,对 MCP 服务发 tools/call,而你在对话里看到的是“通过 call_mcp_tool 调用了 add / greet”。

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐