目录
整体架构概览
MCP (Model Context Protocol) TypeScript SDK 采用分层架构设计,主要包含以下几个核心层次:
┌─────────────────────────────────────┐
│ 应用层 (Application) │
│ ┌─────────┬─────────┬─────────┐ │
│ │ Tools │Resources│ Prompts │ │
│ └─────────┴─────────┴─────────┘ │
├─────────────────────────────────────┤
│ 协议层 (Protocol) │
│ McpServer / Server │
├─────────────────────────────────────┤
│ 传输层 (Transport) │
│ Stdio / StreamableHTTP / SSE │
└─────────────────────────────────────┘
关键设计理念
- 分离关注点: 将数据提供 (Resources)、功能执行 (Tools) 和交互模式 (Prompts) 完全分离
- 可插拔传输: 支持多种传输协议 (stdio, HTTP, SSE)
- 类型安全: 基于 Zod 的完整类型系统
- 异步优先: 所有操作都是异步的,支持流式处理
核心类详解
1. McpServer 类
McpServer 是高级封装类,提供了简化的 API 来注册和管理 MCP 功能。
export class McpServer {
public readonly server: Server; // 底层 Server 实例
private _registeredResources: { [uri: string]: RegisteredResource } = {};
private _registeredResourceTemplates: { [name: string]: RegisteredResourceTemplate } = {};
private _registeredTools: { [name: string]: RegisteredTool } = {};
private _registeredPrompts: { [name: string]: RegisteredPrompt } = {};
}
核心特性:
- 提供高级 API (
registerTool,registerResource,registerPrompt) - 自动处理协议协商和能力注册
- 内部管理所有注册的功能组件
2. Server 类
Server 是底层协议处理类,继承自 Protocol,负责处理 MCP 协议的具体实现。
export class Server<
RequestT extends Request = Request,
NotificationT extends Notification = Notification,
ResultT extends Result = Result,
> extends Protocol<...> {
private _clientCapabilities?: ClientCapabilities;
private _capabilities: ServerCapabilities;
private _instructions?: string;
}
主要职责:
- 处理初始化流程 (
initialize,initialized) - 管理客户端能力协商
- 提供底层请求/通知处理机制
三大功能模块深入分析
1. Tools 模块 - 功能执行引擎
Tools 是 MCP 中执行具体操作的组件,类似于 REST API 中的 POST 端点。
核心实现机制
// Tool 注册流程
server.setRequestHandler(CallToolRequestSchema, async (request, extra): Promise<CallToolResult> => {
const tool = this._registeredTools[request.params.name];
// 1. 参数验证
if (tool.inputSchema) {
const parseResult = await tool.inputSchema.safeParseAsync(request.params.arguments);
if (!parseResult.success) {
throw new McpError(ErrorCode.InvalidParams, `Invalid arguments...`);
}
}
// 2. 执行回调
const result = await Promise.resolve(tool.callback(args, extra));
// 3. 错误处理
return result;
});
Tool 类型定义
export type ToolCallback<
InputArgs extends undefined | ZodRawShape = undefined,
OutputArgs extends undefined | ZodRawShape = undefined
> = InputArgs extends ZodRawShape
? (args: z.objectOutputType<InputArgs, ZodTypeAny>, extra: RequestHandlerExtra) =>
| TypedCallToolResult<OutputArgs>
| Promise<TypedCallToolResult<OutputArgs>>
: (extra: RequestHandlerExtra) =>
| TypedCallToolResult<OutputArgs>
| Promise<TypedCallToolResult<OutputArgs>>;
高级功能特性
- 输入/输出架构验证: 基于 Zod 的完整类型验证
- 工具注释系统: 支持
readOnlyHint,openWorldHint等元数据 - 错误处理: 自动捕获异常并转换为标准错误响应
- 通知发送: 通过
extra.sendNotification发送进度通知
实际使用示例
// 基础工具
server.registerTool(
"greet",
{
title: "问候工具",
description: "生成个性化问候语",
inputSchema: {
name: z.string().describe("要问候的人名"),
language: z.enum(["zh", "en"]).default("zh")
}
},
async ({ name, language }) => ({
content: [{
type: "text",
text: language === "zh" ? `你好,${name}!` : `Hello, ${name}!`
}]
})
);
// 带通知的长时间运行工具
server.registerTool(
"batch-process",
{
title: "批处理工具",
description: "批量处理数据",
inputSchema: { items: z.array(z.string()) }
},
async ({ items }, { sendNotification }) => {
for (let i = 0; i < items.length; i++) {
await sendNotification({
method: "notifications/message",
params: {
level: "info",
data: `处理进度: ${i + 1}/${items.length}`
}
});
// 处理逻辑...
await processItem(items[i]);
}
return {
content: [{ type: "text", text: `成功处理 ${items.length} 个项目` }]
};
}
);
2. Resources 模块 - 数据访问层
Resources 提供对数据的只读访问,相当于 REST API 中的 GET 端点。
核心架构
Resources 支持两种模式:
- 静态资源: 固定 URI 的资源
- 动态资源: 基于 URI 模板的参数化资源
ResourceTemplate 深入解析
export class ResourceTemplate {
private _uriTemplate: UriTemplate;
private _callbacks: {
list: ListResourcesCallback | undefined;
complete?: {
[variable: string]: CompleteResourceTemplateCallback;
};
};
}
关键特性:
- URI 模板: 支持 RFC 6570 标准的 URI 模板
- 列表回调: 用于枚举模板匹配的所有资源
- 自动补全: 为模板变量提供智能补全
资源处理流程
// 读取资源的处理流程
this.server.setRequestHandler(ReadResourceRequestSchema, async (request, extra) => {
const uri = new URL(request.params.uri);
// 1. 首先查找精确匹配的静态资源
const resource = this._registeredResources[uri.toString()];
if (resource) {
return resource.readCallback(uri, extra);
}
// 2. 然后查找匹配的资源模板
for (const template of Object.values(this._registeredResourceTemplates)) {
const variables = template.resourceTemplate.uriTemplate.match(uri.toString());
if (variables) {
return template.readCallback(uri, variables, extra);
}
}
throw new McpError(ErrorCode.InvalidParams, `Resource ${uri} not found`);
});
实际使用示例
// 静态资源
server.registerResource(
"app-config",
"config://app",
{
title: "应用配置",
description: "应用程序配置信息",
mimeType: "application/json"
},
async (uri) => ({
contents: [{
uri: uri.href,
text: JSON.stringify({
version: "1.0.0",
features: ["auth", "logging"]
}, null, 2),
mimeType: "application/json"
}]
})
);
// 动态资源模板
server.registerResource(
"user-profile",
new ResourceTemplate("users://{userId}/profile", {
list: async () => ({
resources: [
{ name: "用户 123", uri: "users://123/profile" },
{ name: "用户 456", uri: "users://456/profile" }
]
}),
complete: {
userId: (value) => ["123", "456", "789"].filter(id => id.startsWith(value))
}
}),
{
title: "用户资料",
description: "用户详细信息"
},
async (uri, { userId }) => ({
contents: [{
uri: uri.href,
text: JSON.stringify({
id: userId,
name: `用户${userId}`,
email: `user${userId}@example.com`
}, null, 2)
}]
})
);
// 文件系统资源
server.registerResource(
"file-content",
new ResourceTemplate("file://{path}", {
list: async () => {
const files = await fs.readdir("./docs");
return {
resources: files.map(file => ({
name: file,
uri: `file://${file}`
}))
};
}
}),
{
title: "文件内容",
description: "读取文件系统中的文件"
},
async (uri, { path }) => {
const content = await fs.readFile(`./docs/${path}`, 'utf-8');
return {
contents: [{
uri: uri.href,
text: content,
mimeType: "text/plain"
}]
};
}
);
3. Prompts 模块 - 交互模式定义
Prompts 定义了 LLM 交互的可重用模板,提供标准化的对话起点。
核心实现
// Prompt 处理器
this.server.setRequestHandler(GetPromptRequestSchema, async (request, extra) => {
const prompt = this._registeredPrompts[request.params.name];
// 参数验证
if (prompt.argsSchema) {
const parseResult = await prompt.argsSchema.safeParseAsync(request.params.arguments);
if (!parseResult.success) {
throw new McpError(ErrorCode.InvalidParams, `Invalid arguments...`);
}
}
return prompt.callback(args, extra);
});
Prompt 类型定义
export type PromptCallback<
Args extends undefined | PromptArgsRawShape = undefined,
> = Args extends PromptArgsRawShape
? (args: z.objectOutputType<Args, ZodTypeAny>, extra: RequestHandlerExtra) =>
GetPromptResult | Promise<GetPromptResult>
: (extra: RequestHandlerExtra) =>
GetPromptResult | Promise<GetPromptResult>;
实际使用示例
// 基础 Prompt
server.registerPrompt(
"code-review",
{
title: "代码审查",
description: "生成代码审查提示词",
argsSchema: {
language: z.string().describe("编程语言"),
code: z.string().describe("要审查的代码")
}
},
async ({ language, code }) => ({
messages: [{
role: "user",
content: {
type: "text",
text: `请审查以下 ${language} 代码,关注:
1. 代码质量和最佳实践
2. 潜在的bug和安全问题
3. 性能优化建议
代码:
\`\`\`${language}
${code}
\`\`\`
请提供详细的审查意见和改进建议。`
}
}]
})
);
// 带资源链接的复杂 Prompt
server.registerPrompt(
"documentation-helper",
{
title: "文档助手",
description: "基于项目文档生成帮助提示",
argsSchema: {
topic: z.string().describe("需要帮助的主题"),
context: z.string().optional().describe("额外上下文")
}
},
async ({ topic, context }) => ({
messages: [{
role: "user",
content: {
type: "text",
text: `我需要关于"${topic}"的帮助。${context ? `额外信息:${context}` : ''}`
}
}],
// 引用相关文档资源
resources: [
{ type: "resource_link", uri: "docs://api-reference" },
{ type: "resource_link", uri: "docs://tutorials" }
]
})
);
传输层实现
MCP SDK 支持多种传输协议,实现了完全可插拔的传输层架构。
1. Stdio Transport
// 标准输入输出传输,适用于命令行工具
const transport = new StdioServerTransport();
await server.connect(transport);
2. StreamableHTTP Transport
// HTTP 传输,支持流式处理
const transport = new StreamableHTTPServerTransport();
// 配置 Express 路由
app.post('/mcp', (req, res) => transport.handleRequest(req, res));
3. SSE (Server-Sent Events)
// 服务器推送事件,适用于实时通信
const transport = new SSEServerTransport();
app.get('/mcp/sse', (req, res) => transport.handleSSE(req, res));
认证与安全
OAuth 2.0 集成
MCP SDK 提供了完整的 OAuth 2.0 支持:
// 设置 OAuth 认证
const authMiddleware = requireBearerAuth(tokenVerifier);
app.use('/mcp', authMiddleware);
// 在处理器中访问认证信息
server.registerTool("secure-operation", {}, async (args, { authInfo }) => {
if (!authInfo?.scopes?.includes('write')) {
throw new McpError(ErrorCode.InvalidParams, "Insufficient permissions");
}
// 执行需要授权的操作...
});
资源访问控制
// 基于认证信息的资源访问控制
server.registerResource(
"private-data",
new ResourceTemplate("private://{userId}/data", { list: undefined }),
{},
async (uri, { userId }, { authInfo }) => {
// 检查用户是否有权访问指定用户的数据
if (authInfo?.sub !== userId && !authInfo?.scopes?.includes('admin')) {
throw new McpError(ErrorCode.InvalidParams, "Access denied");
}
return {
contents: [{ uri: uri.href, text: `Private data for ${userId}` }]
};
}
);
最佳实践与使用建议
1. 合理使用三大功能模块
- Tools: 用于执行有副作用的操作(创建、更新、删除、计算)
- Resources: 用于提供只读数据访问(配置、文档、状态查询)
- Prompts: 用于定义标准化的 LLM 交互模式
2. 错误处理策略
// 在 Tool 中进行优雅的错误处理
server.registerTool("file-operation", {}, async ({ action, path }) => {
try {
const result = await performFileOperation(action, path);
return {
content: [{ type: "text", text: `操作成功: ${result}` }]
};
} catch (error) {
// 返回结构化错误信息而不是抛出异常
return {
content: [{
type: "text",
text: `操作失败: ${error.message}`
}],
isError: true
};
}
});
3. 性能优化建议
// 使用缓存提高资源访问性能
const cache = new Map();
server.registerResource("expensive-data", "data://expensive", {},
async (uri) => {
const cacheKey = uri.href;
if (cache.has(cacheKey)) {
return cache.get(cacheKey);
}
const result = await expensiveDataComputation();
cache.set(cacheKey, result);
return result;
}
);
// 定期清理缓存
setInterval(() => cache.clear(), 300000); // 5分钟清理一次
4. 监控和日志
// 添加请求监控
server.server.setRequestHandler = ((originalMethod) => {
return function(schema, handler) {
const wrappedHandler = async (request, extra) => {
const startTime = Date.now();
try {
const result = await handler(request, extra);
console.log(`请求处理成功: ${request.method} (${Date.now() - startTime}ms)`);
return result;
} catch (error) {
console.error(`请求处理失败: ${request.method}`, error);
throw error;
}
};
return originalMethod.call(this, schema, wrappedHandler);
};
})(server.server.setRequestHandler);
5. 开发调试技巧
// 添加调试中间件
if (process.env.NODE_ENV === 'development') {
server.server.fallbackRequestHandler = async (request, extra) => {
console.log('未处理的请求:', JSON.stringify(request, null, 2));
throw new McpError(ErrorCode.MethodNotFound, `Method ${request.method} not found`);
};
}
总结
MCP TypeScript SDK 提供了一个强大而灵活的框架来构建 LLM 应用的上下文提供者。通过合理使用 Tools、Resources 和 Prompts 三大模块,可以构建出功能丰富、性能优良的 MCP 服务器。
关键要点:
- 分层架构: 清晰的职责分离,便于维护和扩展
- 类型安全: 基于 Zod 的完整类型系统确保运行时安全
- 传输无关: 支持多种传输协议,适应不同部署场景
- 认证集成: 内置 OAuth 2.0 支持,满足企业级安全需求
- 扩展性强: 可插拔的架构设计,支持自定义扩展