项目简介
XMCP (eXtensible Model Context Protocol) 是一个强大的 TypeScript 框架,用于构建符合 Model Context Protocol (MCP) 规范的服务器。它提供了一套完整的工具和约定,使开发者能够高效地创建和管理 LLM 应用所需的上下文信息、可调用工具和 Prompt 模板。该框架通过文件系统路由自动注册组件,支持热重载、自定义中间件和多种部署方式,极大地提升了开发体验。
主要功能点
- 资源托管与数据访问: 以标准化方式管理和提供数据资源,允许 LLM 客户端按需访问。你可以通过在 'src/resources' 目录下创建文件来定义和暴露数据。
- 工具注册与执行: 自动从指定目录注册外部功能(工具),供 LLM 调用以执行特定任务。这些工具通常定义了输入 Schema 和执行逻辑,位于 'src/tools' 目录下。
- Prompt 模板定义: 支持定义和渲染可定制的 Prompt 模板,灵活控制 LLM 的交互模式。Prompt 模板定义在 'src/prompts' 目录下,并可以接受参数。
- 文件系统路由: 工具、Prompt 和资源自动从 'tools'、'prompts' 和 'resources' 目录注册,简化配置和管理。
- 中间件支持: 提供身份验证和其他自定义逻辑的中间件机制,增强服务器功能和安全性。
- 多传输协议支持: 支持 Stdio、HTTP 等多种传输协议,适应不同的部署场景和客户端连接方式。
- 灵活配置: 允许通过项目根目录下的 'xmcp.config.ts' 文件进行高度定制化的服务器配置。
安装步骤
要开始你的第一个 XMCP 应用,请运行以下命令:
npx create-xmcp-app@latest
或者,如果你想在一个现有的 Next.js 或 Express 项目中初始化 XMCP:
npx init-xmcp@latest
这些命令将引导你完成项目设置,并创建必要的目录和配置文件。
服务器配置 (MCP 客户端所需)
XMCP 服务器通过 JSON-RPC 协议与客户端通信。MCP 客户端连接 XMCP 服务器时,需要提供服务器的启动信息。以下是一个典型的配置示例,它展示了如何通过命令行启动一个使用 HTTP 传输协议的 XMCP 服务器:
{ "name": "MyXmcpServer", "command": "npm", "args": ["run", "xmcp", "start", "--port", "3000", "--http"], "description": "连接到运行在本地3000端口的XMCP HTTP服务器。如果服务器使用其他端口或传输协议,请修改相关参数。" }
参数说明:
- 'name': 服务器的显示名称,用于客户端识别。
- 'command': 启动 XMCP 服务器所执行的命令。例如,如果你的项目在 'package.json' 中定义了 'xmcp start' 脚本,此处通常为 'npm' 或 'yarn'。
- 'args': 传递给 'command' 的参数列表。
- 'run xmcp start': 执行 'xmcp' 启动命令。
- '--port 3000': 指定 HTTP 服务器监听的端口号为 3000。
- '--http': 启用 HTTP 传输协议。
- 请根据你的具体 XMCP 项目配置和运行环境调整 'command' 和 'args'。例如,如果你的 XMCP 配置启用了 Stdio 传输,则 'args' 可能不包含 '--port' 和 '--http'。
基本使用方法
XMCP 服务器启动后,MCP 客户端可以连接到它,并通过其声明的 API 访问资源、调用工具或获取 Prompt。例如,一个 LLM 客户端可以向 XMCP 服务器发送 JSON-RPC 请求,来:
- 读取特定用户配置文件资源,如通过 'user-profile' 资源获取用户 'userId' 的信息。
- 调用一个 'greet' 工具来向用户发送问候语。
- 获取一个 'review-code' Prompt 模板,用于指导 LLM 进行代码审查。
开发者在 XMCP 项目的 'src/resources'、'src/tools' 和 'src/prompts' 目录下创建相应的 TypeScript 文件,框架会自动将其注册为可用的 MCP 组件。例如,一个简单的 'greet' 工具可能如下所示:
// src/tools/greet.ts import { z } from "zod"; import { type InferSchema, type ToolMetadata } from "xmcp"; export const schema = { name: z.string().describe("The name of the user to greet"), }; export const metadata: ToolMetadata = { name: "greet", description: "Greet the user", }; export default async function greet({ name }: InferSchema<typeof schema>) { return { content: [{ type: "text", text: 'Hello, ${name}!' }], }; }
信息
分类
开发者工具