跳到主要内容

MCP开发与应用

Model Context Protocol (MCP) 是 Anthropic 于 2024 年 11 月开源的开放标准,用于让 AI 应用以统一、安全、可控的方式连接外部数据源与工具。2025 年它已成为事实标准:OpenAI(Agents SDK 与 Responses API)、Google(ADK / Gemini)等主流厂商相继采纳。本文基于 2026 年的真实协议与官方 SDK 介绍 MCP 的核心概念、架构、开发实践与安全要点,可直接作为面试回答。

目录

📦 唯一官方 Node.js SDK

MCP 生态里 不存在 @mcp/core@mcp/resources@mcp/toolsmcp-express 这类包(历史教程中常见的虚构示例)。Node/TypeScript 唯一官方 SDK 是

npm install @modelcontextprotocol/sdk zod

核心导出(按子路径导入):

用途导入路径关键类/对象
服务器@modelcontextprotocol/sdk/server/mcp.jsMcpServer
stdio 传输(服务端)@modelcontextprotocol/sdk/server/stdio.jsStdioServerTransport
Streamable HTTP 传输(服务端)@modelcontextprotocol/sdk/server/streamableHttp.jsStreamableHTTPServerTransport
客户端@modelcontextprotocol/sdk/client/index.jsClient
stdio 传输(客户端)@modelcontextprotocol/sdk/client/stdio.jsStdioClientTransport
Streamable HTTP 传输(客户端)@modelcontextprotocol/sdk/client/streamableHttp.jsStreamableHTTPClientTransport

服务端高层 API 主要是:server.tool()(或 registerTool)、server.resource()(或 registerResource)、server.prompt()(或 registerPrompt),并用 Zod 描述入参 Schema。其他语言官方还提供 Python (mcp / modelcontextprotocol)、TypeScript、Java、Kotlin、C#、Go 等 SDK。

官方站点:https://modelcontextprotocol.io,协议规范仓库:modelcontextprotocol/specification

🚀 快速开始:30 行写一个 MCP Server

下面用 stdio 传输暴露一个「查询天气」的工具,可被 Claude Desktop / Cursor 等宿主直接拉起:

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

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

// 注册一个工具:模型可控(model-controlled)
server.tool(
"get_weather",
"获取指定城市的实时天气",
{ city: z.string().describe("城市名称,如北京、上海") },
async ({ city }) => {
// 实际项目中替换为真实天气 API 调用
const text = `${city}】当前天气:晴朗,25℃`;
return { content: [{ type: "text", text }] };
}
);

// stdio 传输:宿主以子进程方式启动本进程,stdin/stdout 上收发 JSON-RPC
const transport = new StdioServerTransport();
await server.connect(transport);
// 注意:日志必须走 stderr,stdout 仅用于 JSON-RPC,否则会污染协议
console.error("weather MCP server ready");

要点:工具返回值的 content块数组[{ type: "text", text }]),不是单个对象;这是真实 SDK 的约定。

🎯 学习目标

通过本文学习,你将掌握:

  • MCP 的核心概念与 Host / Client / Server 三层架构
  • 三种能力原语 Tools / Resources / Prompts 的语义与控制方主体
  • 基于 JSON-RPC 2.0initialize 握手与消息模型
  • 两种主流传输:stdio(本地)与 Streamable HTTP(2025 远程标准)
  • 用官方 SDK @modelcontextprotocol/sdk 开发 Server 与 Client
  • MCP 安全风险与最佳实践(提示注入、工具投毒、最小权限、HITL、供应链审计、OAuth 2.1)

🔍 MCP 核心概念

MCP 解决什么问题

在 MCP 之前,每个 AI 应用要接一个数据源/工具,就得写一套私有适配(M 个应用 × N 个工具 = M×N 个集成)。MCP 把它标准化为「一次实现、处处可用」:工具方实现一个 MCP Server,任何兼容 MCP 的宿主都能直接接入,复杂度从 M×N 降为 M+N。它常被类比为「AI 应用的 USB-C 接口」。

三种能力原语:Tools / Resources / Prompts

MCP Server 对外暴露三类能力,区别在于「由谁来控制调用」:

原语控制方语义类比
Tools(工具)模型控制模型在推理中自行决定调用,有副作用(查询、写库、发请求)函数调用 / POST
Resources(资源)应用控制由宿主应用决定把哪些只读上下文喂给模型(文件、记录、文档)只读数据 / GET
Prompts(提示)用户控制预置的提示模板/工作流,通常由用户显式触发(如斜杠命令)模板 / 快捷指令

这套「谁控制」的划分是面试高频考点:Tools 是模型主动调,Resources 是应用主动喂,Prompts 是用户主动选

MCP vs 传统集成方式

特性传统私有集成MCP
标准化各自实现、互不通用统一协议、跨宿主复用
集成复杂度M×NM+N
能力发现文档约定运行时 tools/list 等动态发现
传输各自约定标准化 stdio / Streamable HTTP
生态封闭开放,官方与社区大量现成 Server

🏗️ MCP 架构设计

Host / Client / Server 三层模型

MCP 采用清晰的三层职责划分:

  • Host(宿主):用户直接使用的 AI 应用,如 Claude Desktop、Cursor、ChatGPT、各类 IDE/Agent 运行时。Host 负责承载大模型、管理会话与权限,并在内部为每个外部 Server 创建一个 Client。
  • Client(客户端):由 Host 内嵌、与某个 Server 保持 1:1 连接的协议组件,负责能力协商、消息收发。
  • Server(服务器):独立进程/服务,对外暴露 Tools / Resources / Prompts,对接真实数据源与工具。

记忆点:一个 Host 内可有多个 Client,每个 Client 1:1 连一个 Server;Server 之间彼此隔离、互不感知。

JSON-RPC 2.0 与 initialize 握手

MCP 的线协议是 JSON-RPC 2.0,三种消息:请求(带 id,需响应)、响应(带 id,含 resulterror)、通知(无 id,不需响应)。

连接建立时先进行 initialize 握手:Client 发送自己支持的 protocolVersioncapabilities,Server 回应自己的版本与能力,Client 再发 notifications/initialized 通知确认。协议版本采用日期串(截至 2026 年常见为 2025-06-18)。

// Client -> Server:初始化请求
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-06-18",
"capabilities": { "tools": {}, "resources": {}, "prompts": {} },
"clientInfo": { "name": "my-host", "version": "1.0.0" }
}
}
// Server -> Client:初始化响应(声明自身能力)
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2025-06-18",
"capabilities": {
"tools": { "listChanged": true },
"resources": { "subscribe": true, "listChanged": true },
"prompts": { "listChanged": true }
},
"serverInfo": { "name": "weather-server", "version": "1.0.0" }
}
}

握手完成后,常用方法包括 tools/listtools/callresources/listresources/readprompts/listprompts/get 等。

数据流程


🔌 传输层:stdio 与 Streamable HTTP

MCP 把「消息语义」与「传输方式」解耦。2026 年官方主推两种传输:

传输适用场景形态说明
stdio本地子进程(首选)宿主拉起 Server 子进程,stdin/stdout 收发 JSON-RPC无网络、低延迟、最简单,适合 IDE/本地工具
Streamable HTTP远程服务(2025 远程标准)单一 /mcp 端点,POST 发请求,必要时以 SSE 流式返回防火墙友好、可水平扩展、支持鉴权

⚠️ 重要:旧的 HTTP+SSE「双端点」传输(一个 GET /sse 建流 + 一个 POST /messages 发消息)已在 2025-03-26 版本被 Streamable HTTP 取代并标记为 deprecated。新项目远程传输一律用 Streamable HTTP,不要再新接 deprecated 的 SSE transport。

Streamable HTTP 服务端最小示例:

import express from "express";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import { randomUUID } from "node:crypto";
import { z } from "zod";

const app = express();
app.use(express.json());

function buildServer() {
const server = new McpServer({ name: "remote-weather", version: "1.0.0" });
server.tool("get_weather", "查询天气", { city: z.string() }, async ({ city }) => ({
content: [{ type: "text", text: `${city}:晴 25℃` }],
}));
return server;
}

// 单一 /mcp 端点同时承载请求与(按需的)SSE 流
app.all("/mcp", async (req, res) => {
const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: () => randomUUID(),
});
const server = buildServer();
await server.connect(transport);
await transport.handleRequest(req, res, req.body);
});

app.listen(3000, () => console.error("MCP Streamable HTTP on :3000/mcp"));

🖥️ MCP 服务器开发

注册工具(Tools)

工具是「模型可控、可能有副作用」的能力,入参用 Zod 声明:

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";

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

server.tool(
"create_issue",
"在项目中创建一个 issue(高危:会写入外部系统)",
{
title: z.string().describe("标题"),
body: z.string().optional().describe("正文"),
},
async ({ title, body }) => {
const issue = await createIssueInTracker({ title, body }); // 你的真实实现
return { content: [{ type: "text", text: `已创建 #${issue.id}` }] };
}
);

工具出错时,推荐返回带 isError: true 的结果而非抛异常,让模型能感知并自我纠正:

return { content: [{ type: "text", text: "数据库连接失败" }], isError: true };

注册资源(Resources)

资源是「应用可控的只读上下文」,用 URI 标识;可以是静态 URI,也可以用模板:

import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";

// 静态资源
server.resource("readme", "file:///app/README.md", async (uri) => ({
contents: [{ uri: uri.href, mimeType: "text/markdown", text: await readReadme() }],
}));

// 模板资源:动态参数
server.resource(
"user-profile",
new ResourceTemplate("users://{userId}/profile", { list: undefined }),
async (uri, { userId }) => ({
contents: [{ uri: uri.href, mimeType: "application/json", text: JSON.stringify(await getUser(userId)) }],
})
);

注册提示(Prompts)

提示是「用户可控的模板化工作流」,常映射为宿主里的斜杠命令:

server.prompt(
"code-review",
"对给定代码做结构化审查",
{ code: z.string().describe("待审查代码") },
({ code }) => ({
messages: [
{
role: "user",
content: { type: "text", text: `请从可读性、性能、安全三方面审查:\n\n${code}` },
},
],
})
);

💻 MCP 客户端开发

宿主侧通过 Client 连接 Server。下面演示以 stdio 拉起本地 Server 并调用工具:

import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";

const transport = new StdioClientTransport({
command: "node",
args: ["./weather-server.js"],
});

const client = new Client({ name: "my-host", version: "1.0.0" });
await client.connect(transport); // 内部完成 initialize 握手

// 1) 发现工具
const { tools } = await client.listTools();
console.log("可用工具:", tools.map((t) => t.name));

// 2) 调用工具
const result = await client.callTool({
name: "get_weather",
arguments: { city: "北京" },
});
console.log(result.content);

// 3) 读取资源
const res = await client.readResource({ uri: "file:///app/README.md" });

连接远程 Server 时,把传输换成 StreamableHTTPClientTransport(new URL("https://host/mcp")) 即可,其余调用方式一致。


🔐 安全性:面试必答

MCP 把外部世界引入模型,安全是核心考点。要点如下:

  1. 提示注入(Prompt Injection)与工具投毒(Tool Poisoning)

    • 工具返回的内容、资源文本可能藏有恶意指令,诱导模型执行越权动作。
    • 工具的 description / 参数说明本身也可能被投毒(让模型误用工具)。
    • 缓解:对 Server 返回内容做不可信处理、隔离展示、必要时做内容审查;固定/审计工具描述。
  2. 最小权限(Least Privilege)

    • Server 只暴露必要的工具与资源;数据库账号、文件目录、API scope 都按最小集授予。
    • 为高危工具与只读工具分离凭据。
  3. 高危工具的人工确认(HITL,Human-in-the-Loop)

    • 删除、转账、发邮件、写生产库等有副作用的工具,应在宿主侧弹出确认。
    • 设计工具时标注危险等级,宿主据此决定是否需要人工批准。
  4. Server 供应链审计

    • 第三方 MCP Server 等同于在你环境里运行第三方代码。安装前审查来源、权限、依赖;锁定版本;优先官方/可信发布者。
    • 把「MCP Server 审查」纳入安全评审与发布清单。
  5. 远程 OAuth 2.1 授权

    • 远程(Streamable HTTP)Server 的鉴权采用 OAuth 2.1:基于 token 的授权、PKCE、scope 限定;Server 充当资源服务器,校验访问令牌。
    • 切忌把长效密钥硬编码进客户端配置。
  6. 传输与隔离

    • 远程一律 HTTPS;校验 Origin、绑定会话;对 stdio Server 控制其可访问的本地资源边界。

🌐 生态与采纳现状

  • Anthropic:2024.11 开源 MCP,Claude Desktop / Claude Code 原生支持。
  • OpenAIResponses API 支持 MCP(可直接挂远程 MCP Server),Agents SDK 亦内置 MCP 接入。
  • GoogleADK(Agent Development Kit)/ Gemini 生态采纳 MCP。
  • IDE / 工具:Cursor、VS Code、各类 Agent 运行时广泛支持。
  • 官方与社区 Server:filesystem、git、github、postgres、sqlite、slack、puppeteer 等大量现成实现可直接复用。

到 2026 年,MCP 已是连接「模型 ↔ 工具/数据」的通用标准;掌握它的三层架构、三种原语、两种传输与安全实践,是 AI 工程面试的必备项。

📚 延伸阅读


💡 面试提示:被问到 MCP,先用一句话定位——「MCP 是 AI 应用连接外部工具/数据的开放标准,Anthropic 2024.11 开源、2025 成事实标准」;再展开 Host/Client/Server 三层Tools/Resources/Prompts 三原语stdio/Streamable HTTP 两传输JSON-RPC 2.0 + initialize 握手,最后落到 安全(提示注入、最小权限、HITL、供应链、OAuth 2.1)。代码层面强调唯一官方 SDK @modelcontextprotocol/sdk