🚀 使用Model Context Protocol构建一个简单的服务器
本项目展示了如何借助 TypeScript SDK 搭建一个基础的 MCP 服务器。此服务器具备资源管理、工具交互和提示指导等功能,能有效辅助 AI 客户端与工具、资源进行交互。
🚀 快速开始
运行服务器
-
克隆项目仓库到本地:
git clone https://github.com/yourusername/css-tutor-server.git
cd css-tutor-server
-
安装依赖项:
npm install
-
启动服务器:
npm start
调试工具
为了帮助开发者调试,项目提供了以下调试工具:
npx @modelcontextprotocol/inspector
运行上述命令后,将在浏览器中打开一个界面,允许您查看和测试服务器的状态、资源、工具以及提示。
✨ 主要特性
- 资源管理:定义了一个简单的资源 (
css_knowledge_memory
) 来存储已知的 CSS 概念。
- 工具交互:实现了三个工具,分别为
read_from_memory
(从内存中读取数据)、write_to_memory
(向内存中写入数据)和 get_latest_updates
(调用 OpenRouter API 获取最新的更新)。
- 提示指导:定义了一个静态提示 (
css-tutor-guidance
) 来指导 AI 客户端如何有效地与工具和资源交互。
📦 安装指南
环境变量
为了使服务器正常运行,您需要在环境中设置以下变量:
OPENROUTER_API_KEY=your_api_key_here
可以将此环境变量添加到 .env
文件中,或者直接设置在操作系统环境中。
项目配置
package.json
配置
{
"name": "css_tutor_server",
"version": "1.0.0",
"description": "CSS 教学辅助服务器,基于Model Context Protocol构建。",
"scripts": {
"start": "ts-node src/index.ts"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^0.5.0",
"ts-node": "^10.9.2",
"typescript": "^5.3.3",
"zod": "^1.24.0"
}
}
tsconfig.json
配置
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true
},
"include": ["**/*.ts"],
"exclude": ["node_modules"]
}
💻 使用示例
基础用法
const server = await createServer({
prompts: [css_tutor_guidance],
tools: [
read_from_memory,
write_to_memory,
get_latest_updates
],
});
await server.start();
📚 详细文档
项目结构
项目的文件结构如下:
project-root/
├── data/ # 数据目录,包含memory.json数据库文件
├── src/
│ ├── resources/ # 资源定义目录
│ ├── tools/ # 工具定义目录
│ ├── prompts/ # 提示定义目录
│ └── index.ts # 主程序入口文件
├── package.json # 项目依赖和脚本配置
├── tsconfig.json # TypeScript编译器配置
└── .gitignore # 代码库忽略规则
项目文件结构说明
data/memory.json
:存储已知的 CSS 概念。
src/resources/
:包含内存资源的读写逻辑。
src/tools/
:包含可执行的具体功能工具。
src/prompts/
:定义了教学提示内容。
src/index.ts
:服务器入口文件,负责初始化和启动服务。
代码实现
资源定义 (src/resources/index.ts
)
import { readFileSync, writeFileSync } from 'fs';
import { resource, ResourceHandler } from '@modelcontextprotocol/sdk';
const memorySchema = z.object({
concepts: z.record(z.string()),
});
export async function readMemory(): Promise<unknown> {
try {
const data = readFileSync('./data/memory.json', 'utf8');
return JSON.parse(data);
} catch (error) {
console.error('读取内存错误:', error);
throw error;
}
}
export async function writeMemory(data: unknown): Promise<void> {
try {
const isValid = memorySchema.safeParse(data).success;
if (!isValid) {
throw new Error('数据格式无效');
}
writeFileSync('./data/memory.json', JSON.stringify(data, null, 2));
} catch (error) {
console.error('写入内存错误:', error);
throw error;
}
}
resource({
name: 'css_knowledge_memory',
uriPrefix: 'memory://',
readHandler: async () => await readMemory(),
writePermission: true,
writeHandler: async (data) => await writeMemory(data),
});
工具定义 (src/tools/index.ts
)
import { resource } from '@modelcontextprotocol/sdk';
import { readMemory, writeMemory } from './resources';
import { z } from 'zod';
export const read_from_memory = tool({
name: 'read_from_memory',
description: '读取内存中的知识库数据',
handler: async () => await readMemory(),
});
export const write_to_memory = tool({
name: 'write_to_memory',
description: '向内存中写入新的知识',
parameters: {
concept: z.string().describe('要标记为已知的CSS概念'),
known: z.boolean().describe('指示该概念是否已知')
},
handler: async ({ concept, known }) => {
const currentData = await readMemory();
if (known) {
currentData.concepts[concept] = true;
} else {
delete currentData.concepts[concept];
}
return await writeMemory(currentData);
},
});
export const get_latest_updates = tool({
name: 'get_latest_updates',
description: '获取最新的CSS更新信息',
handler: async () => {
try {
return {
updates: ['新增了 CSS Grid 的新布局模式', '修复了 Flexbox 中的一个已知问题']
};
} catch (error) {
console.error('获取更新失败:', error);
throw error;
}
},
});
提示定义 (src/prompts/index.ts
)
import { prompt } from '@modelcontextprotocol/sdk';
export const css_tutor_guidance = prompt({
name: 'css_tutor_guidance',
description: '指导学习者如何掌握CSS核心概念',
content: `作为经验丰富的CSS开发者,帮助学习者理解和掌握关键的CSS概念。请以清晰、有条理的方式进行教学。`
});
主程序 (src/index.ts
)
import { createServer } from '@modelcontextprotocol/sdk';
import { css_tutor_guidance } from './prompts';
import { read_from_memory, write_to_memory, get_latest_updates } from './tools';
async function main() {
try {
const server = await createServer({
prompts: [css_tutor_guidance],
tools: [
read_from_memory,
write_to_memory,
get_latest_updates
],
});
console.log('服务器已启动,监听地址:', server.url);
await server.start();
} catch (error) {
console.error('服务器启动失败:', error);
}
}
main().catch(console.error);
🔧 技术细节
错误处理
在 src/tools/index.ts
中,我们已经为每个工具添加了错误捕获和处理机制。生产环境中建议增加额外的错误监控和报告功能。
扩展功能
未来可以考虑以下扩展:
- 数据持久化:使用数据库替代本地文件存储。
- 日志系统:集成专业的日志管理工具。
- 认证授权:为不同的用户角色分配权限。
- 国际化支持:支持多语言教学内容。
- 进度跟踪:记录学习者的学习进展和成果。
📄 许可证
文档未提及相关信息,故跳过该章节。
🔗 参考资料