mCP 2.0
无状态 MCP,有状态应用
一个最小的 JavaScript 项目,演示 MCP 2026-07-28 的主要请求/响应模式,使用 MCP TypeScript SDK v2。
该演示涵盖:
无
Mcp-Session-Id的无状态 HTTP 请求。通过显式句柄寻址的应用管理状态。
用于用户确认的多轮往返请求。
限定于单个操作的进度更新。
带 TTL 和共享范围的可缓存工具发现。
运行
需要 Node.js 20 或更高版本。
npm install
npm run demo该命令在可用的本地端口上启动服务器,执行每个场景,打印结果,然后关闭服务器。删除示例使用内存中的虚拟文件集,绝不会触碰磁盘上的文件。
运行集成测试:
npm test要让服务器保持运行以供另一个 MCP 客户端使用:
npm run server端点是 http://127.0.0.1:3000/mcp。设置 PORT 可覆盖端口。
Related MCP server: MCP RC Long-Running Task Prototype
1. 无状态请求
MCP 2026-07-28 移除了协议级别的 HTTP 会话。此项目为每个请求创建一个全新的 McpServer,因此任何请求都可以到达任何服务器实例:
const mcpHandler = createMcpHandler(
() => createStateServer(demoFiles),
{
legacy: "reject",
onerror: (error) => console.error("MCP error:", error),
},
);客户端显式选择现代协议版本:
const client = new Client(
{ name: "state-demo-client", version: "0.1.0" },
{
capabilities: { elicitation: { form: {} } },
versionNegotiation: {
mode: { pin: "2026-07-28" },
},
},
);因此,存储在单个 McpServer 实例内的状态会在该请求结束后消失。调用演示的临时计数器两次,会从两个不同的服务器实例各产生 1。
2. 有状态应用数据
无状态 MCP 并不要求应用也是无状态的。持久状态属于每次请求的 MCP 服务器之外,并通过显式句柄来选择:
const countersById = new Map();
server.registerTool(
"create-counter",
{
outputSchema: z.object({ counterId: z.uuid(), value: z.number() }),
},
async () => {
const counterId = randomUUID();
countersById.set(counterId, 0);
const structuredContent = { counterId, value: 0 };
return {
content: [{ type: "text", text: JSON.stringify(structuredContent) }],
structuredContent,
};
},
);客户端在原本独立的调用之间携带该句柄:
const created = await client.callTool({ name: "create-counter" });
const { counterId } = created.structuredContent;
await client.callTool({
name: "increment-counter",
arguments: { counterId },
});内存中的 Map 只是临时替代。生产服务器应使用数据库或共享存储,将句柄绑定到已认证的主体,并在每次查找时强制授权和过期检查。
3. 多轮往返确认
需要更多输入的工具会返回 input_required。客户端获取答案后,用 inputResponses 重试原始请求,因此服务器不会在操作流上发起第二个 JSON-RPC 请求。
server.registerTool(
"delete-files",
{
inputSchema: z.object({ files: z.array(z.string()).min(1) }),
annotations: { destructiveHint: true },
},
async ({ files }, ctx) => {
const confirmation = acceptedContent(
ctx.mcpReq.inputResponses,
"confirm",
confirmationSchema,
);
if (confirmation === undefined) {
return inputRequired({
inputRequests: {
confirm: inputRequired.elicit({
message: `Delete ${files.length} virtual files?`,
requestedSchema: confirmationSchema,
}),
},
});
}
if (!confirmation.confirm) {
return {
content: [{ type: "text", text: "Cancelled" }],
structuredContent: { status: "cancelled", deleted: [] },
};
}
const deleted = files.filter((file) => demoFiles.delete(file));
return {
content: [{ type: "text", text: `Deleted: ${deleted.join(", ")}` }],
structuredContent: { status: "deleted", deleted },
};
},
);SDK 可以使用正常的提示处理程序自动完成请求并重试:
client.setRequestHandler("elicitation/create", async (request) => {
const confirm = await askUser(request.params.message);
return {
action: "accept",
content: { confirm },
};
});确认是用户体验,不是授权。服务器仍必须对调用者进行身份验证,并独立地强制删除文件的权限。
4. 请求范围的进度
进度仍然附着在发起工作的请求上。并发操作只接收各自的更新,而不是共享一个全局事件流。
server.registerTool(
"run-work",
{ inputSchema: z.object({ job: z.string() }) },
async ({ job }, ctx) => {
const progressToken = ctx.mcpReq._meta?.progressToken;
for (const progress of [10, 30, 70]) {
if (progressToken !== undefined) {
await ctx.mcpReq.notify({
method: "notifications/progress",
params: {
progressToken,
progress,
total: 100,
message: `${job}: ${progress}%`,
},
});
}
}
return {
content: [{ type: "text", text: `${job}: complete` }],
structuredContent: { job, status: "complete" },
};
},
);每个客户端调用都提供自己的进度回调:
await Promise.all([
client.callTool(
{ name: "run-work", arguments: { job: "alpha" } },
{ onprogress: (update) => alphaProgress.push(update) },
),
client.callTool(
{ name: "run-work", arguments: { job: "beta" } },
{ onprogress: (update) => betaProgress.push(update) },
),
]);5. 可缓存性
可缓存的响应包含新鲜度生命周期和共享策略。当一个代理连接到许多 MCP 服务器时,这减少了重复的发现流量。
此服务器将其工具目录标记为可复用五分钟:
const server = new McpServer(
{ name: "mcp-state-demo", version: "0.1.0" },
{
cacheHints: {
"tools/list": {
ttlMs: 300_000,
cacheScope: "public",
},
},
},
);客户端自动使用新鲜条目:
await client.listTools(); // network request; stores the result
await client.listTools(); // cache hit; no network request
await client.listTools(undefined, {
cacheMode: "refresh",
}); // forces a network request and updates the cache这些字段适用于 tools/list、prompts/list、resources/list、resources/templates/list 和 resources/read 的结果。
public允许客户端和共享中间层跨用户复用结果。private将复用限制在请求的授权上下文中。当缓存存储被共享时,将客户端的cachePartition设置为稳定的主体标识符。
TTL 是新鲜度估计。列表变更通知可以在 TTL 过期之前使缓存的目录失效。
项目结构
src/server.js MCP server and tool implementations
src/demo.js Client exercising all five scenarios
test/state.test.js Integration tests for every scenarioMCP 包被固定为 2.0.0,包括此处使用的 inputRequired、acceptedContent、缓存和请求范围进度 API。
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceA reference implementation demonstrating proper MCP server patterns with HTTP transport, featuring session management, progress notifications, and example tools for testing server functionality. Serves as a clean template for building MCP servers with streamable responses and comprehensive error handling.7
- FlicenseNot gradedqualityCmaintenanceDemonstrates MCP 2026-07-28 behavior for long-running tool calls, task lifecycle (get, update, cancel), and elicitation clarification during async tasks.
- AlicenseNot gradedqualityCmaintenanceEducational MCP server demonstrating the 2026-07-28 stateless protocol with raw Starlette, no SDK, featuring tools, request state handles, MRTR elicitation, and subscriptions.MIT
- AlicenseNot gradedqualityBmaintenanceDemo MCP server for ACEL, a runtime verification middleware that blocks a rule-violating tool call before it executes. 5 tools (authenticate, read/validate/delete records, send payment) showing ACEL enforcing call ordering and state preconditions live via the official MCP SDK's middleware hook.MIT
Related MCP Connectors
AI Reasoning Cache & Consensus Layer with 11 MCP tools via Streamable HTTP.
Hash-chained HMAC-signed audit log MCP for A2A (agent-to-agent) calls. Every tool-call, agent-ha...
Workflow diagnostics, capability routing, and x402 settlement for MCP-compatible agents.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/weijianzhg/mcp-2-0'
If you have feedback or need assistance with the MCP directory API, please join our Discord server