mcp tanstack启动
MCP(模型上下文协议)集成 TanStack启动构建可由LLM使用标准化MCP协议调用的AI驱动工具。
安装
npm install mcp-tanstack-start @modelcontextprotocol/sdk zod或与您首选的软件包管理器联系:
pnpm add mcp-tanstack-start @modelcontextprotocol/sdk zod
yarn add mcp-tanstack-start @modelcontextprotocol/sdk zod快速开始
使用单个文件启动并运行。这是一个完整的MCP服务器,在一个API路由中包含工具:
// src/routes/api/mcp.ts
import { createFileRoute } from '@tanstack/react-router'
import { createMcpServer, defineTool } from 'mcp-tanstack-start'
import { z } from 'zod'
// Define a tool
const echoTool = defineTool({
name: 'echo',
description: 'Echo back a message',
parameters: z.object({
message: z.string().describe('The message to echo back'),
}),
execute: async ({ message }) => {
return `You said: ${message}`
},
})
// Create the MCP server
const mcp = createMcpServer({
name: 'my-tanstack-app',
version: '1.0.0',
instructions: `This is my TanStack Start app with MCP tools.
You can use the available tools to interact with the application.`,
tools: [echoTool],
})
// Wire up all HTTP methods with a single handler
export const Route = createFileRoute('/api/mcp')({
server: {
handlers: {
all: async ({ request }) => mcp.handleRequest(request),
} as Record Promise>,
},
})就是这样!您的MCP服务器现在位于 /api/mcp.
注: 我们使用小写 all 由于TanStack Start的处理程序查找中存在区分大小写的怪癖。类型断言可以解决TypeScript类型(需要大写)和运行时行为(需要小写)之间的不匹配问题。分解它
设置API路线
API路由是MCP服务器所在的位置。它处理:
- 发布 -JSON-RPC请求(初始化、工具/列表、工具/调用等)
- 获取 -服务器到客户端通知的SSE流
- 删除 -会话终止
最简单的方法是使用单个 all 处理程序:
// src/routes/api/mcp.ts
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/api/mcp')({
server: {
handlers: {
all: async ({ request }) => mcp.handleRequest(request),
} as Record Promise>,
},
})如果您更愿意明确说明API支持哪些方法,则可以单独定义每个处理程序:
// src/routes/api/mcp.ts
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/api/mcp')({
server: {
handlers: {
GET: async ({ request }) => mcp.handleRequest(request),
POST: async ({ request }) => mcp.handleRequest(request),
DELETE: async ({ request }) => mcp.handleRequest(request),
},
},
})这两种方法都是一样的——选择你喜欢的风格。
创建MCP服务器
MCP服务器管理您的工具并处理协议通信:
const mcp = createMcpServer({
name: 'my-tanstack-app', // Server name
version: '1.0.0', // Server version
instructions: `Optional instructions for AI assistants about how to use your tools.`,
tools: [echoTool], // Array of tools
})定义工具
工具是LLM可以调用的函数。每个工具都有一个名称、描述、参数(用Zod定义)和一个执行函数:
import { defineTool } from 'mcp-tanstack-start'
import { z } from 'zod'
const echoTool = defineTool({
name: 'echo',
description: 'Echo back a message',
parameters: z.object({
message: z.string().describe('The message to echo back'),
}),
execute: async ({ message }) => {
return `You said: ${message}`
},
})这 parameters 对象使用Zod模式进行类型安全验证。这 execute 函数接收已验证的参数并返回字符串响应。
安全
原产地验证
默认情况下,服务器只接受来自localhost源的请求,以防止 DNS重新绑定攻击.配置允许的生产来源:
const mcp = createMcpServer({
name: 'my-app',
version: '1.0.0',
tools: [...],
transport: {
allowedOrigins: [
'https://my-app.com',
'https://api.my-app.com',
],
},
})⚠️ 警告:设置 allowedOrigins: ["*"] 完全禁用源验证。不建议将其用于生产部署。认证
通过身份验证保护您的MCP端点:
// src/routes/api/mcp.ts
import { createFileRoute } from '@tanstack/react-router'
import { withMcpAuth } from 'mcp-tanstack-start'
import { mcp } from '../../mcp'
import { verifyJWT } from '../../lib/auth'
const authenticatedHandler = withMcpAuth(
async (request, auth) => {
return mcp.handleRequest(request, { auth })
},
async (request) => {
const token = request.headers.get('Authorization')?.replace('Bearer ', '')
if (!token) return null
try {
const claims = await verifyJWT(token)
return { token, claims }
} catch {
return null
}
}
)
export const Route = createFileRoute('/api/mcp')({
server: {
handlers: {
all: async ({ request }) => authenticatedHandler(request),
} as Record Promise>,
},
})工具中的访问身份验证:
const userDataTool = defineTool({
name: 'get_user_data',
description: 'Get data for the authenticated user',
parameters: z.object({}),
execute: async (params, context) => {
const userId = context.auth?.claims?.sub
if (!userId) {
return { content: [{ type: 'text', text: 'Not authenticated' }], isError: true }
}
const userData = await fetchUserData(userId)
return JSON.stringify(userData)
},
})api参考
createMcpServer(config)
创建MCP服务器实例。
const mcp = createMcpServer({
name: string, // Server name
version: string, // Server version
tools?: ToolDefinition[], // Array of tools
instructions?: string, // Optional instructions for AI
transport?: { // Transport configuration
stateful?: boolean, // Enable stateful sessions (default: false)
sessionStore?: SessionStore, // Custom session store (for stateful mode)
allowedOrigins?: string[], // Allowed origins for CORS/DNS rebinding protection
sessionTimeout?: number, // Session timeout in ms (default: 1 hour)
requestTimeout?: number, // Request timeout in ms (default: 30 seconds)
maxBodySize?: number, // Max request body size (default: 1MB)
enableJsonResponse?: boolean, // Use JSON instead of SSE for responses
enableResumability?: boolean, // Enable SSE event IDs for resumability
}
})
// Returns
mcp.handleRequest(request: Request, options?: { auth?, signal? }): Promise
mcp.addTool(tool: ToolDefinition): void
mcp.getInfo(): { name: string; version: string }运输方式
无状态模式(默认) -适用于任何地方:无服务器、边缘、容器和分布式环境。如果未找到会话,则请求将得到妥善处理,不会出现错误。非常适合Vercel、Netlify、Railway、Cloudflare Workers等。
状态模式 -为SSE推送通知启用持久会话。分布式部署需要内存存储(仅限单个实例)或自定义会话存储。
// Stateless (default) - works on serverless/edge/distributed
const mcp = createMcpServer({
name: 'my-app',
version: '1.0.0',
tools: [...],
});
// Stateful with in-memory sessions (single instance only)
const mcp = createMcpServer({
name: 'my-app',
version: '1.0.0',
tools: [...],
transport: {
stateful: true,
sessionTimeout: 3600000, // 1 hour
}
});
// Stateful with custom session store (distributed deployments)
const mcp = createMcpServer({
name: 'my-app',
version: '1.0.0',
tools: [...],
transport: {
stateful: true,
sessionStore: myRedisSessionStore,
}
});自定义会话存储
实施 SessionStore 用于在Redis、DynamoDB或任何其他存储中持久化会话的接口:
import type { SessionStore, SessionData } from 'mcp-tanstack-start';
const redisSessionStore: SessionStore = {
async get(id: string): Promise {
const data = await redis.get(`mcp:session:${id}`);
return data ? JSON.parse(data) : null;
},
async set(id: string, session: SessionData, ttlMs: number): Promise {
await redis.set(`mcp:session:${id}`, JSON.stringify(session), 'PX', ttlMs);
},
async delete(id: string): Promise {
await redis.del(`mcp:session:${id}`);
},
};运输选项
| 选项 | 默认值 | 描述 |
|---|---|---|
stateful | false | 启用有状态会话模式。如果为false,则以适用于无服务器/边缘/分布式的无状态模式运行。 |
sessionStore | 内存中 | 自定义会话存储(仅在以下情况下使用 stateful: true). |
allowedOrigins | ["http://localhost", ...] | CORS允许的起源。设置为 ["*"] 允许所有(不建议用于生产)。 |
sessionTimeout | 3600000 (1小时) | 清理非活动会话需要多长时间(仅限状态模式)。 |
requestTimeout | 30000 (30秒) | 单个请求超时。 |
maxBodySize | 1048576 (1MB) | 最大请求正文大小(以字节为单位)。 |
enableJsonResponse | false | POST响应返回JSON而不是SSE。 |
enableResumability | true | 包括用于客户端重新连接支持的SSE事件ID(仅限状态模式)。 |
defineTool(config)
定义具有类型安全参数的工具。
defineTool({
name: string,
description: string,
parameters: ZodSchema,
execute: (params, context) => Promise
})withMcpAuth(handler, verifyToken, options?)
用身份验证包裹处理程序。
withMcpAuth(handler, verifyToken, {
realm?: string, // WWW-Authenticate realm
requiredScopes?: string[], // Required scopes
allowUnauthenticated?: boolean,
})内容助手
text(content: string)-创建文本内容image(data: string, mimeType: string)-创建图像内容(base64)resource(uri: string, options?)-创建嵌入式资源
协议
端点
| 方法 | 目的 |
|---|---|
| 发布 | JSON-RPC请求(每个请求一条消息,无批处理) |
| 获取 | 服务器到客户端通知的SSE流(仅限状态模式) |
| 删除 | 会话终止 |
特性
- 默认无状态 -适用于无服务器、边缘和分布式环境
- 可选状态模式 -为SSE推送通知启用持久会话
- 可插拔会话存储 -为分布式部署带来自己的Redis、DynamoDB或其他存储
- 优雅的会话恢复 -在无状态模式下,丢失的会话会得到妥善处理,不会出错
- 原产地验证 -DNS重新绑定攻击防护
- SSE可恢复性 -事件ID
Last-Event-ID标头支持(有状态模式) - 协议版本控制 -
MCP-Protocol-Version带有回退功能的标头2025-03-26
支持的方法
initialize, initialized, tools/list, tools/call, ping
所需标题
客户必须包括:
Accept: application/json, text/event-stream(两者都需要)Content-Type: application/jsonMcp-Session-Id:(初始化后)MCP-Protocol-Version:(推荐)
例子
看看 博客实现示例 要查看mcp tanstack的实际操作,请执行以下操作:
- 博客文章列表和检索
- 内容搜索
- 服务器信息工具
许可证
麻省理工学院
