🤔什么是 MCP?
官网原文:MCP is an open protocol that standardizes how applications provide context to LLMs. Think of MCP like a USB-C port for AI applications. Just as USB-C provides a standardized way to connect your devices to various peripherals and accessories, MCP provides a standardized way to connect AI models to different data sources and tools.
MCP是一个开放协议,它规范了应用程序如何向大型语言模型(LLM)提供上下文。你可以将MCP想象成AI应用程序的USB-C端口。就像USB-C为设备与各种外围设备和配件的连接提供了标准化方式一样,MCP也为AI模型与不同数据源和工具的连接提供了标准化方式。
MCP的意义
在 MCP 推出之前,AI 应用依赖于各种方法与外部工具交互,例如手动 API 连接、基于插件的接口以及代理框架。如图 1 所示,这些方法需要将每个外部服务与特定的 API 集成,这增加了复杂性并限制了可扩展性。MCP 通过提供标准化协议来应对这些挑战,该协议支持与多种工具进行无缝且灵活的交互。
MCP 架构
MCP 架构由三个核心组件组成:MCP 主机、MCP 客户端和 MCP 服务器。这些组件协同工作,实现 AI 应用、外部工具和数据源之间的无缝通信,确保操作安全且得到妥善管理。
以上两张图片来自:MCP Research Paper:
🥇优秀项目
awesome-mcp-servers
Github 上必须出现的,又必然很火的 awesome-xx
系列🤭,收藏精品 MCP 服务端。
playwright-mcp
微软出品,使用 Playwright 提供浏览器自动化功能,能够通过结构化可访问性快照与网页进行交互,无需截图或视觉调优模型。
github-mcp-server
Github 官方出品的 MCP 服务,提供与GitHub API的无缝集成,为开发人员和工具赋予高级自动化和交互能力。
Awesome-MCP-ZH
一个专为中文用户打造的 MCP(模型上下文协议)资源合集! 这里有 MCP 的基础介绍、玩法、客户端、服务器和社区资源,帮你快速上手这个 AI 界的“万能插头”。
MCP Server资源站
- Mcp.so:收录超多的 MCP Server
👨💻一套简单的MCP交互程序
其实对程序员来说,MCP 交互不是什么新玩意,都可以简单拿 HTTP 协议套过来进行理解😄。一个支持发送 MCP 请求的客户端,向 MCP 服务器发起调用。
MCP 官方代码库为 https://github.com/modelcontextprotocol,里面有文档以及主流语言的 SDK,这里我们选择 typescript-sdk
进行客户端/服务端的开发。里面有一个inspector的库,是用于测试 MCP Server 的。
注意:MCP 需要 node.js v18+
。
开始做 MCP 开发前,有些术语需要了解下。
术语概要
- resource(资源):是向 LLM 公开数据的方式。它们类似于 REST API 中的 GET 端点——它们提供数据,但不应执行大量计算或对服务端产生影响;
- tool(工具):允许 LLM 通过你的服务器执行操作。与资源不同,工具需要执行计算并产生副作用;
- prompt(提示):可重复使用的模板,帮助 LLM 有效地与服务器交互。
参考资料
- pentest-mcp:适用于专业渗透测试人员的 MCP 服务器,包括 STDIO/HTTP/SSE 支持、nmap、go/dirbuster、nikto、JtR、hashcat、单词表构建等。
- fastify-mcp:用于运行 MCP 服务器的 Fastify 插件
🖥️ 服务端
使用 node.js 自带的 http 模块处理请求
import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js"
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js"
import { z } from "zod"
import dayjs from "dayjs"
import { randomUUID } from "node:crypto"
import { createServer, ServerResponse } from 'node:http'
import pc from 'picocolors'
const log = (msg, level="INFO")=> console.debug(`${pc.cyan(dayjs().format("MM-DD HH:mm:ss:SSS"))} ${pc.gray(level)} ${msg}`)
const buildServer = ()=>{
const mcpServer = new McpServer({ name: "demo-mcp-server", version:"1.0.0" })
mcpServer.registerTool(
"add",
{
title: "数值相加",
description: "将参数累加",
inputSchema: { a: z.number(), b: z.number() }
},
async ({ a, b })=>{
log(`${pc.magenta("[TOOL]")} add a=${a} b=${b}`)
return {
content: [{ type:'text', text: `${a+b}` }]
}
}
)
mcpServer.registerResource(
"greeting",
new ResourceTemplate("greeting://{name}", { list: null }),
{
title: "Greeting Resource",
description: "Dynamic greeting generator"
},
async (uri, { name })=>{
log(`${pc.magenta("[RESOURCE]")} GREETING ${name}`)
return {
contents:[{ uri: uri.href, text:`Hello ${name}` }]
}
}
)
return mcpServer
}
/**
* @type {Map<String, StreamableHTTPServerTransport>}
*/
const transports = new Map()
/**
*
* @param {ServerResponse} res
* @param {String} message - 描述信息
* @param {Number} code - 错误代码,默认-32000
*/
const sendError = (res, statusCode=400, message, code=-32000)=>{
res.writeHead(statusCode, { 'content-type':'application/json' })
res.end(JSON.stringify({
jsonrpc: "2.0",
error: { code, message },
id: null,
}))
}
const httpServer = createServer(async (req, res)=>{
const { url, method, headers } = req
if(url == '/favicon.ico')
return
const sessionId = headers['mcp-session-id']
// 请求体(需要手动拼接)
let body = '';
req.on('data', chunk => body += chunk)
req.on('end', async ()=>{
log(`${pc.magenta(method.padEnd(4, " "))} | ${req.url} SESSION=${sessionId} TYPE=${headers['content-type']}`)
if(method == 'POST'){
/**@type {StreamableHTTPServerTransport} */
let transport = transports.get(sessionId)
if(transport == null || transport.closed == true){
let server = buildServer()
transport = new StreamableHTTPServerTransport({
sessionIdGenerator: ()=> randomUUID(),
onsessioninitialized: id=> {
log(`MCP Session 已创建,ID=${id}`)
transports.set(id, transport)
}
})
transport.onclose = function(){
log(`transport 关闭 onclose...`)
if(this.sessionId)
transports.delete(this.sessionId)
else
this.closed = true
}
await server.connect(transport)
log(`StreamableHTTPServerTransport 创建成功...`)
}
const postBody = JSON.parse(body)
await transport.handleRequest(req, res, postBody)
log("处理 POST 请求...")
console.debug(postBody)
}
else {
sendError(res, 405, "Method not allowed.")
}
})
})
const PORT = 8080
httpServer.listen(PORT, ()=>{
log(`SERVER RUNNING ON ${PORT} ...`)
})
🤖 客户端
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
const client = new Client({
name: "demo-mcp-client",
version: "1.0.0"
})
let transport = new StreamableHTTPClientTransport("http://localhost:8080")
await client.connect(transport)
console.debug("MCP Server 连接成功...")
try{
//列出全部的 resource
const resources = await client.listResources()
console.debug("资源列表", resources)
console.debug(await client.readResource({uri:"greeting://0604hx"}))
const tools = await client.listTools()
console.debug("工具列表", tools)
console.debug(await client.callTool({
name: 'add',
arguments:{
a: 100,
b: 300
}
}))
}catch(e){
console.debug("出错啦", e)
}
await transport.close()
await client.close()
StreamableHTTP客户端初始化流程
- 发起初始化
{
method: 'initialize',
params: {
protocolVersion: '2025-06-18',
capabilities: {},
clientInfo: { name: 'demo-mcp-client', version: '1.0.0' }
},
jsonrpc: '2.0',
id: 0
}
- 第二次请求
{ method: 'notifications/initialized', jsonrpc: '2.0' }
📷 运行截图
🛠️ 使用 MCP Inspector
后续会单独写一篇博文介绍如何使用😄
❓ 问题集锦
MCP error -32603: keyValidator._parse is not a function
经排查,是由于zod
版本过高(一开始用的是4.x
),改成3.x
就正常了。参考:McpError: MCP error -32603: keyValidator._parse is not a function。"Bad Request: Server not initialized
Server 并未初始化,请先调用server.connect(transport)
。Invalid Request: Server already initialized
Server 已经初始化,sessionId 已经重复。
📚 推荐书籍
《MCP协议与AI Agent开发:标准、应用与实现》
是清华大学出版社出版的图书,系统地阐述了MCP的技术原理、协议机制与工程应用,提供了从底层协议设计到项目部署的全流程的应用指南。全书从结构上分为基础理论、协议规范、开发工具链、应用构建4部分,共9章。具体内容包括大模型基础、MCP基本原理、MCP标准与规范体系、MCP与LLM的互联机制、MCP开发环境与工具链、MCP与多模态大模型集成,以及MCP的状态流转机制、Prompt构建规范、上下文调度策略及其与模型推理引擎的协同工作,同时涉及流式响应、函数调用、模块化Prompt设计等前沿技术,并结合基于DeepSeek
平台的真实应用项目(人格共创AI剧本工坊、自演化智能议程会议系统与深梦编导器),助力读者理解MCP在多元领域的可拓展性与工程实践