LLM上下文协议开发实战:MCP TypeScript SDK全栈指南
当你尝试为大语言模型构建上下文服务时,是否曾面临接口标准化、多模态数据处理、会话状态管理等挑战?MCP TypeScript SDK作为Model Context Protocol的官方实现,提供了一套完整的解决方案。本文将以"问题-方案-实践"三段式架构,带你从零掌握这个强大的TypeScript AI开发框架,构建专业级LLM上下文服务。
一、核心问题:LLM上下文服务开发的痛点与挑战
在构建LLM应用时,你是否遇到过这些问题:如何标准化工具调用接口?怎样高效管理会话状态?如何实现客户端与服务器的双向通信?这些挑战正是MCP协议旨在解决的核心问题。
📌 MCP核心价值:将上下文提供与LLM交互解耦,通过标准化协议实现工具、资源和提示的统一管理,让你专注于业务逻辑而非通信细节。
想象一下,MCP就像餐厅的服务系统:LLM是顾客,MCP服务器是餐厅,工具是厨师,资源是食材库,传输方式则是服务员——各司其职又协同工作,共同为顾客提供优质体验。
二、解决方案:MCP SDK核心组件解析
如何设计MCP服务器架构?
MCP服务器是整个系统的核心,负责管理工具、资源和会话。让我们通过一个文件处理工具的案例,了解服务器的基本架构:
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
import express from 'express';
import { z } from 'zod';
import fs from 'fs/promises';
import path from 'path';
// 创建服务器实例,就像开一家餐厅需要先注册营业执照
const server = new McpServer({
name: 'file-processing-server',
version: '1.0.0',
description: '提供文件读写和处理功能的MCP服务器'
});
// 注册文件读取工具 - 就像聘请一位专门负责取食材的厨师
server.registerTool(
'read-file', // 工具唯一标识
{
title: '文件读取工具',
description: '读取指定路径的文件内容',
inputSchema: z.object({
filePath: z.string().describe('要读取的文件路径')
}),
outputSchema: z.object({
content: z.string().describe('文件内容'),
size: z.number().describe('文件大小(字节)')
})
},
async ({ filePath }) => {
try {
// 实际执行文件读取操作
const fullPath = path.resolve(filePath);
const content = await fs.readFile(fullPath, 'utf8');
const stats = await fs.stat(fullPath);
return {
content: [{ type: 'text', text: `文件内容: ${content.substring(0, 100)}...` }],
structuredContent: { content, size: stats.size }
};
} catch (error) {
throw new Error(`读取文件失败: ${error.message}`);
}
}
);
// 注册用户资料资源 - 就像建立一个顾客信息数据库
server.registerResource(
'user-profile',
new ResourceTemplate('users://{userId}/profile', { list: undefined }),
{
title: '用户个人资料',
description: '获取指定用户的基本信息'
},
async (uri, { userId }) => {
// 在实际应用中,这里会从数据库获取真实用户数据
const mockUserData = {
userId,
name: '测试用户',
email: 'user@example.com',
joinDate: '2023-01-15'
};
return {
contents: [
{
uri: uri.href,
text: JSON.stringify(mockUserData, null, 2)
}
]
};
}
);
从零实现Streamable HTTP传输层
Streamable HTTP是MCP推荐的远程通信方式,支持双向数据流。以下是实现无会话管理模式的完整代码:
// 创建Express应用
const app = express();
app.use(express.json());
// 定义MCP端点 - 就像餐厅的点餐窗口
app.post('/mcp', async (req, res) => {
// 创建传输层实例
const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: undefined, // 禁用会话管理
enableJsonResponse: true // 支持JSON响应
});
// 当客户端断开连接时清理资源
res.on('close', () => {
transport.close();
});
// 连接服务器和传输层
await server.connect(transport);
// 处理请求
try {
await transport.handleRequest(req, res, req.body);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// 启动服务器
const port = parseInt(process.env.PORT || '3000');
app.listen(port, () => {
console.log(`MCP服务器运行在 http://localhost:${port}/mcp`);
console.log('支持的工具: read-file');
console.log('支持的资源: users://{userId}/profile');
});
三、实践指南:构建完整MCP应用
▶️ 环境准备与项目初始化
首先,确保你的开发环境满足要求:
# 检查Node.js版本 (需要v14+)
node -v
# 克隆项目仓库
git clone https://gitcode.com/GitHub_Trending/ty/typescript-sdk
cd typescript-sdk
# 安装依赖
npm install
# 安装示例所需依赖
npm install express zod
▶️ 实现文件处理服务器
创建examples/server/fileProcessingServer.ts文件,复制上述服务器代码。然后添加文件写入工具:
// 添加文件写入工具
server.registerTool(
'write-file',
{
title: '文件写入工具',
description: '将内容写入指定路径的文件',
inputSchema: z.object({
filePath: z.string().describe('要写入的文件路径'),
content: z.string().describe('要写入的内容'),
overwrite: z.boolean().optional().default(false).describe('是否覆盖现有文件')
}),
outputSchema: z.object({
success: z.boolean().describe('操作是否成功'),
message: z.string().describe('操作结果消息')
})
},
async ({ filePath, content, overwrite }) => {
try {
const fullPath = path.resolve(filePath);
// 检查文件是否存在
try {
await fs.access(fullPath);
if (!overwrite) {
return {
content: [{ type: 'text', text: `文件已存在,未覆盖` }],
structuredContent: { success: false, message: '文件已存在,未覆盖' }
};
}
} catch {
// 文件不存在,直接写入
}
await fs.writeFile(fullPath, content, 'utf8');
return {
content: [{ type: 'text', text: `文件写入成功: ${fullPath}` }],
structuredContent: { success: true, message: `文件写入成功: ${fullPath}` }
};
} catch (error) {
throw new Error(`写入文件失败: ${error.message}`);
}
}
);
▶️ 创建MCP客户端
创建examples/client/fileClient.ts文件,实现客户端代码:
import { StreamableHttpClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
import { McpClient } from '@modelcontextprotocol/sdk/client/index.js';
async function main() {
// 创建传输层 - 就像顾客打电话给餐厅
const transport = new StreamableHttpClientTransport({
url: 'http://localhost:3000/mcp'
});
// 创建客户端实例
const client = new McpClient(transport);
try {
// 连接服务器
console.log('连接到MCP服务器...');
await client.connect();
console.log('成功连接到服务器');
// 调用写文件工具
console.log('\n=== 调用写文件工具 ===');
const writeResult = await client.callTool('write-file', {
filePath: './test.txt',
content: '这是通过MCP客户端写入的文件内容',
overwrite: true
});
console.log('写文件结果:', writeResult.structuredContent);
// 调用读文件工具
console.log('\n=== 调用读文件工具 ===');
const readResult = await client.callTool('read-file', {
filePath: './test.txt'
});
console.log('文件内容:', readResult.structuredContent.content);
// 获取用户资源
console.log('\n=== 获取用户资源 ===');
const userResource = await client.getResource('users://123/profile');
console.log('用户资料:', userResource.contents[0].text);
} catch (error) {
console.error('操作失败:', error.message);
} finally {
// 断开连接
await client.disconnect();
console.log('\n已断开与服务器的连接');
}
}
main();
▶️ 运行与测试
分别打开两个终端窗口,执行以下命令:
# 终端1: 启动服务器
npx tsx examples/server/fileProcessingServer.ts
# 终端2: 运行客户端
npx tsx examples/client/fileClient.ts
四、常见错误排查
1. 传输层连接失败
症状:客户端无法连接到服务器,报"连接超时"或"拒绝连接"错误。
排查步骤:
- 确认服务器是否已启动并监听正确端口
- 检查防火墙设置是否阻止端口访问
- 验证客户端使用的URL是否正确
解决方案:
// 增加连接超时和错误处理
const transport = new StreamableHttpClientTransport({
url: 'http://localhost:3000/mcp',
timeout: 5000 // 设置5秒超时
});
// 增加错误处理
try {
await client.connect();
} catch (error) {
console.error('连接失败:', error);
// 提供用户友好的错误提示
if (error.code === 'ECONNREFUSED') {
console.error('请确保服务器已启动并在指定端口运行');
}
}
2. 工具调用参数验证失败
症状:调用工具时收到"输入验证失败"错误。
排查步骤:
- 检查工具定义的inputSchema
- 验证客户端传递的参数是否符合schema要求
- 查看错误消息中的具体验证失败原因
解决方案:
// 调用工具时增加参数验证
try {
const result = await client.callTool('read-file', {
filePath: './test.txt'
});
} catch (error) {
if (error.name === 'ValidationError') {
console.error('参数验证失败:', error.details);
}
}
五、生产环境最佳实践
1. 会话状态管理
在生产环境中,建议使用持久化存储来管理会话状态:
// 使用数据库存储会话状态
import { DatabaseEventStore } from '@modelcontextprotocol/sdk/server/stores/database.js';
// 创建带会话管理的传输层
const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: () => crypto.randomUUID(),
eventStore: new DatabaseEventStore({
connectionString: process.env.DATABASE_URL
})
});
2. 安全加固
- 输入验证:对所有输入进行严格验证
- 权限控制:为工具和资源添加访问控制
- 传输加密:使用HTTPS加密传输数据
- 速率限制:防止DoS攻击
// 添加请求速率限制
import rateLimit from 'express-rate-limit';
const apiLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15分钟
max: 100, // 每个IP限制100请求
standardHeaders: true,
legacyHeaders: false,
});
app.use('/mcp', apiLimiter);
3. 监控与日志
集成监控和日志系统,及时发现和解决问题:
// 添加请求日志
app.use((req, res, next) => {
console.log(`[${new Date().toISOString()}] ${req.method} ${req.originalUrl}`);
next();
});
// 服务器错误监控
server.on('error', (error) => {
console.error('服务器错误:', error);
// 可以集成错误报告服务,如Sentry
});
总结
通过本文,你已经学会了如何使用MCP TypeScript SDK构建完整的LLM上下文服务,包括服务器设计、工具和资源开发、客户端实现以及生产环境部署。MCP协议为LLM应用开发提供了标准化框架,使你能够专注于业务逻辑而非通信细节。
下一步,你可以探索更高级的功能:动态服务器配置、多节点部署、高级授权机制等。MCP SDK的灵活性和扩展性将支持你构建更复杂的AI应用系统。
官方文档:docs/capabilities.md 示例代码:examples/ 核心实现:packages/server/src/server/mcp.ts
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust098- DDeepSeek-V4-ProDeepSeek-V4-Pro(总参数 1.6 万亿,激活 49B)面向复杂推理和高级编程任务,在代码竞赛、数学推理、Agent 工作流等场景表现优异,性能接近国际前沿闭源模型。Python00
MiMo-V2.5-ProMiMo-V2.5-Pro作为旗舰模型,擅⻓处理复杂Agent任务,单次任务可完成近千次⼯具调⽤与⼗余轮上 下⽂压缩。Python00
GLM-5.1GLM-5.1是智谱迄今最智能的旗舰模型,也是目前全球最强的开源模型。GLM-5.1大大提高了代码能力,在完成长程任务方面提升尤为显著。和此前分钟级交互的模型不同,它能够在一次任务中独立、持续工作超过8小时,期间自主规划、执行、自我进化,最终交付完整的工程级成果。Jinja00
Kimi-K2.6Kimi K2.6 是一款开源的原生多模态智能体模型,在长程编码、编码驱动设计、主动自主执行以及群体任务编排等实用能力方面实现了显著提升。Python00
MiniMax-M2.7MiniMax-M2.7 是我们首个深度参与自身进化过程的模型。M2.7 具备构建复杂智能体应用框架的能力,能够借助智能体团队、复杂技能以及动态工具搜索,完成高度精细的生产力任务。Python00