这是一个全面的教程项目,将教授你从入门到进阶的模型上下文协议(Model Context Protocol,MCP)开发。你将学习服务器端(后端)和客户端(前端)的开发。
# 创建项目目录
mkdir mcp-learning-project
cd mcp-learning-project
# 初始化npm项目
npm init -y
# 安装依赖
npm install @modelcontextprotocol/sdk
# 安装开发依赖
npm install --save-dev typescript @types/node tsx
{
"name": "mcp-learning-project",
"version": "1.0.0",
"description": "Learn MCP development from beginner to advanced",
"main": "dist/server.js",
"type": "module",
"scripts": {
"build": "tsc",
"start:server": "node dist/server.js",
"start:client": "node dist/client.js dist/server.js",
"dev:server": "tsx src/server.ts",
"dev:client": "tsx src/client.ts dist/server.js",
"demo": "npm run build && npm run start:client"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^0.4.0"
},
"devDependencies": {
"@types/node": "^20.0.0",
"tsx": "^4.0.0",
"typescript": "^5.0.0"
}
}
创建 tsconfig.json:
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "node",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"outDir": "./dist",
"rootDir": "./src",
"declaration": true,
"skipLibCheck": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
src/server.tssrc/client.ts# 构建项目
npm run build
# 运行交互式客户端(这也将启动服务器)
npm run demo
见快速开始部分的步骤,包含项目设置、依赖安装、配置文件创建等内容。
// 服务器设置
const server = new Server({
name: 'my-server',
version: '1.0.0'
}, {
capabilities: {
tools: {}, // Functions AI can call
resources: {}, // Data AI can read
prompts: {} // Templates AI can use
}
});
// 工具注册
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: 'my_tool',
description: 'What this tool does',
inputSchema: { /* JSON Schema */ }
}
]
}));
// 工具实现
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
// Process the tool call and return results
return {
content: [{
type: 'text',
text: 'Tool response'
}]
};
});
// 客户端设置
const client = new Client({
name: 'my-client',
version: '1.0.0'
}, {
capabilities: { /* client capabilities */ }
});
// 连接到服务器
const transport = new StdioClientTransport(/* server process */);
await client.connect(transport);
// 发现服务器功能
const tools = await client.listTools();
const resources = await client.listResources();
// 使用服务器工具
const result = await client.callTool({
name: 'tool_name',
arguments: { /* tool parameters */ }
});
// 以下是一些高级场景的代码示例
// 例如创建自定义工具、资源和提示等
// 创建自定义工具 - 天气工具
{
name: 'weather',
description: 'Get weather information',
inputSchema: {
type: 'object',
properties: {
city: { type: 'string', description: 'City name' },
units: { type: 'string', enum: ['celsius', 'fahrenheit'], default: 'celsius' }
},
required: ['city']
}
}
// 创建自定义资源 - 配置资源
{
uri: 'config://app-settings',
name: 'Application Settings',
description: 'Current application configuration',
mimeType: 'application/json'
}
// 创建交互式提示 - 代码审查提示
{
name: 'code-review',
description: 'Start a code review session',
arguments: [
{
name: 'language',
description: 'Programming language',
required: true
},
{
name: 'focus',
description: 'Review focus (security, performance, style)',
required: false
}
]
}
启动交互式客户端:
npm run demo
尝试基本命令:
mcp-learning> help
mcp-learning> tools
mcp-learning> call hello_world {"name": "Alice"}
了解资源:
mcp-learning> resources
mcp-learning> read mcp-concepts
运行入门级演示:
mcp-learning> demo beginner
练习工具调用:
mcp-learning> call calculator {"operation": "add", "a": 5, "b": 3}
mcp-learning> call calculator {"operation": "divide", "a": 10, "b": 0}
理解状态管理:
mcp-learning> call counter {"action": "get"}
mcp-learning> call counter {"action": "increment", "amount": 5}
mcp-learning> call counter {"action": "get"}
运行中级演示:
mcp-learning> demo intermediate
处理复杂数据:
mcp-learning> call data_processor {"data": [5, 2, 8, 1, 9], "operation": "sort"}
mcp-learning> call data_processor {"data": [5, 2, 8, 1, 9], "operation": "average"}
CRUD操作:
mcp-learning> call task_manager {"action": "create", "task": {"title": "Learn MCP", "priority": "high"}}
mcp-learning> call task_manager {"action": "list"}
运行高级演示:
mcp-learning> demo advanced
学习错误处理:
mcp-learning> call error_demo {"error_type": "none"}
mcp-learning> call error_demo {"error_type": "validation"}
研究最佳实践:
mcp-learning> read best-practices
服务器为AI模型提供功能:
// 服务器设置
const server = new Server({
name: 'my-server',
version: '1.0.0'
}, {
capabilities: {
tools: {}, // Functions AI can call
resources: {}, // Data AI can read
prompts: {} // Templates AI can use
}
});
// 工具注册
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: 'my_tool',
description: 'What this tool does',
inputSchema: { /* JSON Schema */ }
}
]
}));
// 工具实现
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
// Process the tool call and return results
return {
content: [{
type: 'text',
text: 'Tool response'
}]
};
});
客户端连接到服务器并使用其功能:
// 客户端设置
const client = new Client({
name: 'my-client',
version: '1.0.0'
}, {
capabilities: { /* client capabilities */ }
});
// 连接到服务器
const transport = new StdioClientTransport(/* server process */);
await client.connect(transport);
// 发现服务器功能
const tools = await client.listTools();
const resources = await client.listResources();
// 使用服务器工具
const result = await client.callTool({
name: 'tool_name',
arguments: { /* tool parameters */ }
});
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ AI Model │ ───▶ │ MCP Client │ ───▶ │ MCP Server │
│ │ │ (Frontend) │ │ (Backend) │
│ │ ◀─── │ │ ◀─── │ │
└─────────────┘ └─────────────┘ └─────────────┘
▲ │ │
│ │ │
└──────────────────────┴──────────────────────┘
Uses server capabilities
天气工具:
{
name: 'weather',
description: 'Get weather information',
inputSchema: {
type: 'object',
properties: {
city: { type: 'string', description: 'City name' },
units: { type: 'string', enum: ['celsius', 'fahrenheit'], default: 'celsius' }
},
required: ['city']
}
}
文件系统工具:
{
name: 'file_operations',
description: 'Basic file system operations',
inputSchema: {
type: 'object',
properties: {
action: { type: 'string', enum: ['list', 'read', 'write'] },
path: { type: 'string', description: 'File or directory path' },
content: { type: 'string', description: 'Content to write' }
},
required: ['action', 'path']
}
}
数据库工具:
{
name: 'database',
description: 'Simple in-memory database operations',
inputSchema: {
type: 'object',
properties: {
action: { type: 'string', enum: ['create', 'read', 'update', 'delete'] },
table: { type: 'string', description: 'Table name' },
data: { type: 'object', description: 'Data to store/update' },
id: { type: 'string', description: 'Record ID' }
},
required: ['action', 'table']
}
}
配置资源:
{
uri: 'config://app-settings',
name: 'Application Settings',
description: 'Current application configuration',
mimeType: 'application/json'
}
文档资源:
{
uri: 'docs://api-reference',
name: 'API Reference',
description: 'Complete API documentation',
mimeType: 'text/markdown'
}
{
name: 'code-review',
description: 'Start a code review session',
arguments: [
{
name: 'language',
description: 'Programming language',
required: true
},
{
name: 'focus',
description: 'Review focus (security, performance, style)',
required: false
}
]
}
服务器无法启动:
# 检查TypeScript是否正确编译
npm run build
# 查找编译错误
npx tsc --noEmit
# 检查是否缺少依赖
npm install
客户端无法连接:
# 确保服务器路径正确
node dist/client.js dist/server.js
# 检查服务器进程是否启动
node dist/server.js
工具调用失败:
// 在服务器中添加调试信息
console.error(`[DEBUG] Tool called: ${name}`, JSON.stringify(args));
// 仔细验证输入参数
if (typeof args.requiredParam === 'undefined') {
throw new McpError(ErrorCode.InvalidParams, 'Missing required parameter');
}
在服务器和客户端启用详细日志记录:
// 在服务器中
console.error('[SERVER]', 'Detailed log message');
// 在客户端
console.log('[CLIENT]', 'Connection status:', connected);
用实际有用的功能替换演示工具:
// 示例:实际的文件系统访问
private async handleFileOperations(args: any) {
const { action, path, content } = args;
switch (action) {
case 'read':
return {
content: [{
type: 'text',
text: await fs.readFile(path, 'utf-8')
}]
};
case 'write':
await fs.writeFile(path, content);
return {
content: [{
type: 'text',
text: `File written: ${path}`
}]
};
}
}
// 示例:HTTP API集成
private async handleApiCall(args: any) {
const { url, method, data } = args;
const response = await fetch(url, {
method,
headers: { 'Content-Type': 'application/json' },
body: data ? JSON.stringify(data) : undefined
});
return {
content: [{
type: 'text',
text: JSON.stringify({
status: response.status,
data: await response.json()
}, null, 2)
}]
};
}
import * as fs from 'fs/promises';
class PersistentMCPServer {
private dataFile = './mcp-data.json';
async loadState(): Promise<Map<string, any>> {
try {
const data = await fs.readFile(this.dataFile, 'utf-8');
return new Map(Object.entries(JSON.parse(data)));
} catch {
return new Map();
}
}
async saveState(state: Map<string, any>): Promise<void> {
const data = Object.fromEntries(state);
await fs.writeFile(this.dataFile, JSON.stringify(data, null, 2));
}
}
private validateAuth(headers: any): boolean {
const token = headers['authorization'];
return token === 'Bearer your-secret-token';
}
private async handleSecureTool(args: any, headers: any) {
if (!this.validateAuth(headers)) {
throw new McpError(ErrorCode.InvalidParams, 'Authentication required');
}
// 继续工具逻辑...
}
服务器端通过 Server 类初始化,设置名称、版本和功能(工具、资源、提示)。使用 setRequestHandler 方法注册工具和处理工具调用请求。客户端通过 Client 类初始化,连接到服务器后可以发现服务器的功能并调用工具。
AI模型通过MCP客户端与MCP服务器进行交互。客户端负责连接服务器、发现功能和调用工具,服务器负责提供功能和处理工具调用请求。
在服务器和客户端中,通过捕获异常和验证输入参数来处理错误。例如,在工具调用时检查输入参数是否合法,若不合法则抛出 McpError 异常。
添加更多操作:power、sqrt、factorial、sin、cos
创建用于创建、编辑、搜索和组织带标签笔记的工具。
与真实的API(天气、新闻、股票价格)集成并创建相应的工具。
创建一个全面的项目管理系统,包含任务、截止日期、优先级和进度跟踪。
实现可以向客户端发送通知或更新的工具。
现在你已经从前端和后端的角度全面了解了MCP开发。你可以:
本项目中的交互式学习环境让你亲身体验所有MCP概念。以此为基础,为任何领域或用例构建你自己的专业MCP服务器!
编码愉快!🚀