现有 10,000 台 MCP 服务器:这就是区分好服务器的标准
2026 年 4 月,MCP 生态系统覆盖了 10,000 台服务器。将有用的 MCP 服务器与废弃的服务器区分开来的七种做法,并以包含 49 个工具的生产服务器为例。
2026 年 4 月,MCP 生态系统跨越 10,000 台公共服务器。TypeScript、Python、Java、Kotlin、 C# 和 Swift SDK 的每月下载量合计达到 9700 万次。 OAuth 2.1 和可流式 HTTP 传输 是稳定的。 Linux 基金会负责监督治理。 克劳德桌面,光标,风帆冲浪,Zed,继续, Sourcegraph Cody 和 Taskade Genesis 均附带 MCP 客户端支持。
这 10,000 台服务器中的大多数都是废弃的实验服务器。 工具名称模糊,无输入验证,已转储 API 界面和通用错误消息。 开发人员不断回来分享七个的少数 做法。
这篇文章涵盖了这七种实践以及生产代码
Botoi 的 MCP 服务器,它公开了来自 150 多个 API 端点的 49 个精选工具。 每个
代码示例来自正在运行的服务器 api.botoi.com/mcp。
1. 策划工具; 不要转储你的整个 API
最大的一个错误:将每个 API 端点注册为 MCP 工具。 Botoi 拥有 150 多个端点。 如果它们都是 MCP 工具,则工具清单在对话之前将消耗 30,000 多个令牌 开始。 这为用户的实际问题留下了更少的空间,增加了模型选择问题的机会 错误的工具,并减慢每个请求,因为模型必须读取数百个工具 定义。
Botoi 注册 49。选择标准:开发人员在编码会话期间使用的工具(DNS 查找、JWT 解码、哈希生成),生成结构化输出模型的工具可以推理 (JSON 验证、PII 检测)以及保存上下文切换的工具(Base64 编码、URL 元数据) 提取)。
// curated-tools.ts - 49 tools from 150+ endpoints
export const CURATED_TOOLS: Record<string, CuratedTool> = {
lookup_dns: {
path: "/v1/dns/lookup",
method: "post",
title: "DNS Lookup",
description:
"Query DNS records (A, AAAA, MX, TXT, CNAME, NS) for a domain. " +
"Use when you need to check DNS configuration or troubleshoot domain resolution.",
annotations: { readOnlyHint: true, openWorldHint: true },
},
dev_hash: {
path: "/v1/hash",
method: "post",
title: "Hash Text",
description:
"Generate a hash (MD5, SHA-1, SHA-256, SHA-512) of input text. " +
"Use for checksums, data integrity, or fingerprinting.",
annotations: { readOnlyHint: true },
},
// ... 47 more curated tools
};
未能晋级的工具:具有大负载的批处理操作(从 HTML 生成 PDF)、 返回二进制数据的工具(二维码图像、屏幕截图)以及重叠的工具 功能(三个不同的哈希端点合并为一个)。 您添加的每个工具都需要花费代币。 将您的 MCP 清单视为产品,而不是 API 文档的镜像。
经验法则:如果您有超过 50 个工具,模型会花费更多时间读取工具定义 而不是做有用的工作。 每季度审核您的清单并删除零调用的工具。
2. 编写帮助模型正确选择的工具描述
该模型会读取您的工具描述来决定是否调用它。 诸如“是否 DNS 的东西”迫使模型进行猜测。 充满实现细节的描述会浪费令牌 模型不需要的信息。
有效的模式:一个句子以动词开头,说明该工具的用途,然后是 第二句以“Use when”开头,描述触发条件。
错误的描述
// Bad: vague, no trigger condition
{
name: "dns",
description: "Does DNS stuff"
}
// Bad: too long, includes implementation details
{
name: "dns_lookup_tool",
description: "This tool uses the DNS-over-HTTPS protocol to query Cloudflare's 1.1.1.1 resolver via a GET request to https://cloudflare-dns.com/dns-query with an Accept header of application/dns-json. It supports A, AAAA, MX, TXT, CNAME, and NS record types and returns the raw DNS response parsed into JSON format."
}
好的描述
// Good: verb-first, one sentence what + one sentence when
{
name: "lookup_dns",
description:
"Query DNS records (A, AAAA, MX, TXT, CNAME, NS) for a domain. " +
"Use when you need to check DNS configuration or troubleshoot domain resolution."
}
// Good: specific about capabilities and trigger condition
{
name: "security_pii_detect",
description:
"Scan text for personal identifiable information (emails, phones, SSNs, credit cards). " +
"Use when you need to audit user input or log output for sensitive data before storage."
}
第一句话是工具选择:它告诉模型该工具做什么以及输入什么 accepts. 第二句话是为了消除歧义:当两个工具可以匹配时,“使用何时”子句 帮助模型选择正确的一个。
Botoi 的 MCP 服务器中的所有 49 个工具都遵循此模式。 结果:模型始终选择
即使多个工具具有重叠的功能(例如,
lookup_email 与 lookup_dns 用于检查 MX 记录)。
3.使用工具注释
MCP 规范定义了四种注释提示: readOnlyHint, destructiveHint,
idempotentHint, 和 openWorldHint。 大多数服务器都会忽略它们。 型号和
尊重这些提示的客户会做出更安全的决定:如果没有,他们不会调用破坏性工具
确认后,他们会在失败时重试幂等工具,并且会在使用工具之前警告用户
联系外部服务。
// Annotations from Botoi's curated-tools.ts
lookup_dns: {
path: "/v1/dns/lookup",
annotations: {
readOnlyHint: true, // reads data, changes nothing
openWorldHint: true, // contacts external DNS servers
},
},
storage_paste_create: {
path: "/v1/paste/create",
annotations: {
destructiveHint: true, // creates new data
idempotentHint: false, // each call creates a new paste
},
},
dev_hash: {
path: "/v1/hash",
annotations: {
readOnlyHint: true, // pure computation
idempotentHint: true, // same input = same output
},
},
| 注解 | 意义 | 例子 |
|---|---|---|
readOnlyHint: true |
读取数据,不改变任何内容 | DNS 查找、SSL 检查、IP 地理定位 |
destructiveHint: true |
创建、更新或删除数据 | 创建粘贴,生成短URL |
idempotentHint: true |
使用相同的输入可以安全地多次调用 | 哈希生成、JSON 格式化 |
openWorldHint: true |
联系外部服务 | DNS over HTTPS、WHOIS、URL 元数据 |
就清单大小而言,注释几乎不需要花费任何成本,但它们为客户和模型提供了 他们需要安全地规划多步骤工作流程的元数据。 将它们设置在每个工具上。
4. 使用 Streamable HTTP 实现无状态
MCP 规范中已弃用 SSE(服务器发送事件)传输。 需要坚持不懈 连接、会话管理和重新连接逻辑。 Streamable HTTP 将其替换为标准 携带 JSON-RPC 2.0 负载的 HTTP POST 请求。 没有持久连接。 无会话状态。 作品 每个 HTTP 基础设施:CDN、负载均衡器、边缘运行时、无服务器平台。
Botoi 的 MCP 服务器在 Cloudflare Workers 上运行。 每个请求都会创建一个新的 McpServer
实例,注册所有 49 个工具,处理请求,然后返回。 无会话 ID,无法重连
处理程序,请求之间没有可管理的状态。
// MCP server on Cloudflare Workers with Streamable HTTP
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import {
WebStandardStreamableHTTPServerTransport
} from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
app.all("/mcp", async (c) => {
const apiKey =
c.req.header("X-API-Key") ||
c.req.header("Authorization")?.replace("Bearer ", "");
const server = createMcpServer(apiKey, c.env);
const transport = new WebStandardStreamableHTTPServerTransport();
await server.connect(transport);
return transport.handleRequest(c.req.raw);
});
这 WebStandardStreamableHTTPServerTransport 来自 MCP SDK 的适用于任何运行时
支持 Web 标准 Request/Response API:Cloudflare 工作人员,
Deno Deploy、Bun、Vercel Edge Functions 和 Node.js 18+。 如果您要在以下位置启动新的 MCP 服务器
2026 年,使用 Streamable HTTP。 如果您正在运行 SSE 服务器,请在客户端放弃支持之前进行迁移。
无状态服务器可以水平扩展,无需协调。 Botoi 的 MCP 端点在 Cloudflare 上运行 边缘网络; 请求路由到最近的数据中心。 仅计算工具(散列、Base64、 JSON 格式)在 50 毫秒内响应。
5. 使用模式验证输入
MCP 工具从模型接收任意 JSON。 模型可以发
在您需要字符串的地方,包含未知字段或省略必需的参数。 验证输入
在执行之前尽早捕获这些错误并返回模型可用于的结构化反馈
自我纠正。
Botoi 的方法: schema-builder.ts 模块读取 OpenAPI 路径定义
注册时间并将每个属性转换为 Zod 类型。 MCP SDK 验证输入
工具处理程序运行之前的 Zod 架构。
// schema-builder.ts - OpenAPI to Zod conversion
import { z } from "zod";
import { paths } from "../../openapi-paths";
function mapPropertyToZod(
prop: OpenApiProperty,
isRequired: boolean
): z.ZodTypeAny {
let schema: z.ZodTypeAny;
if (prop.enum && prop.enum.length > 0) {
schema = z.enum(prop.enum as [string, ...string[]]);
} else {
switch (prop.type) {
case "number":
case "integer":
schema = z.number(); break;
case "boolean":
schema = z.boolean(); break;
default:
schema = z.string(); break;
}
}
if (!isRequired) schema = schema.optional();
return schema;
}
export function buildZodSchema(
apiPath: string,
method: "get" | "post"
): Record<string, z.ZodTypeAny> {
const operation = getOperation(apiPath, method);
if (!operation) return {};
const schema = operation.requestBody?.content?.["application/json"]?.schema;
if (!schema?.properties) return {};
const required = new Set(schema.required ?? []);
const result: Record<string, z.ZodTypeAny> = {};
for (const [key, prop] of Object.entries(schema.properties)) {
result[key] = mapPropertyToZod(prop, required.has(key));
}
return result;
}
注册循环将生成的模式传递为 inputSchema 对于每个工具:
// server.ts - register tools with Zod schemas
for (const [toolName, tool] of Object.entries(CURATED_TOOLS)) {
const zodSchema = buildZodSchema(tool.path, tool.method);
server.registerTool(toolName, {
title: tool.title,
description: tool.description,
inputSchema: zodSchema,
annotations: tool.annotations,
}, async (args: Record<string, unknown>) => {
return callApi(tool.path, tool.method, args, apiKey, env);
});
}
这意味着每个工具都可以免费获得输入验证。 如果模型发送一个整数,其中一个字符串 预计,MCP SDK 在处理程序代码运行之前返回结构化错误。 模型看到 错误,更正输入,然后重试。
6. 返回模型可以推理的结构化错误
当工具发生故障时,模型需要足够的信息来恢复。 “出了点问题”是没有用的。 字段名称、预期内容和收到内容的结构化错误为模型提供了 清除路径以使用更正的输入重试。
错误响应错误
// Bad: the model can't fix this
{
"content": [{ "type": "text", "text": "Something went wrong" }],
"isError": true
}
良好的错误响应
// Structured error the model can reason about
{
"content": [
{
"type": "text",
"text": "{\\n \\"error\\": \\"validation_error\\",\\n \\"message\\": \\"Invalid record type\\",\\n \\"field\\": \\"type\\",\\n \\"expected\\": [\\"A\\", \\"AAAA\\", \\"MX\\", \\"TXT\\", \\"CNAME\\", \\"NS\\"],\\n \\"received\\": \\"INVALID\\"\\n}"
}
],
"isError": true
}
波托伊的 callApi 包装器从底层 REST API 捕获结构化错误并
将其传递给 MCP 响应 isError: true:
// server.ts - API call wrapper with structured errors
async function callApi(
path: string,
method: string,
body: unknown,
apiKey: string | undefined,
env: Env
) {
const headers: Record<string, string> = {
"Content-Type": "application/json",
};
if (apiKey) headers["X-API-Key"] = apiKey;
const req = new Request(\`http://internal\${path}\`, {
method: method.toUpperCase(),
headers,
body: method === "post" ? JSON.stringify(body) : undefined,
});
const res = await appFetcher(req, env);
const json = await res.json();
if (!json.success) {
return {
content: [{
type: "text",
text: JSON.stringify(json.error, null, 2),
}],
isError: true,
};
}
return {
content: [{
type: "text",
text: JSON.stringify(json.data, null, 2),
}],
};
}
关键细节: isError: true 标志告诉模型工具调用失败。
中的结构化 JSON text 字段告诉它原因。 根据工具使用模式训练的模型
将读取错误,识别问题字段,并使用更正的值重试。 一般错误
字符串迫使模型猜测或放弃。
7.在不破坏开发者体验的情况下添加auth
MCP 服务器需要身份验证。 该规范支持 OAuth 2.1 来实现完整的授权流程,但大多数 开发人员工具与 API 密钥转发配合良好。 开发人员将其密钥添加到 MCP 客户端 配置一次; 服务器从请求标头中提取它并将其传递给每个 API 调用。
以下是带有 API 密钥的 Claude Desktop 客户端配置:
// Client config: Claude Desktop
{
"mcpServers": {
"botoi": {
"type": "streamable-http",
"url": "https://api.botoi.com/mcp",
"headers": {
"Authorization": "Bearer YOUR_API_KEY"
}
}
}
}
服务器从以下任意一个中提取密钥 Authorization 标头或
X-API-Key header,然后将其转发到每个内部 API 调用:
// server.ts - extract API key from MCP request headers
app.all("/mcp", async (c) => {
const apiKey =
c.req.header("X-API-Key") ||
c.req.header("Authorization")?.replace("Bearer ", "");
// Pass the key through to every API call
const server = createMcpServer(apiKey, c.env);
const transport = new WebStandardStreamableHTTPServerTransport();
await server.connect(transport);
return transport.handleRequest(c.req.raw);
});
没有密钥,服务器仍然可以工作。 Botoi 允许每分钟 5 个请求的匿名访问,并且 每天 100 个,足够在编码期间随意使用。 通过按键,将规模限制为 开发商的计划等级。 这种方法意味着零摩擦入职(无需注册即可尝试) 当使用量增长时有清晰的升级路径。
开发人员的 API 密钥永远不会离开 MCP 服务器。 它从客户端配置到 MCP 内部 API 调用的请求标头。 该模型永远不会在对话上下文中看到它。
好的 MCP 服务器与坏的 MCP 服务器
| 特征 | 服务器不好 | 良好的服务器 |
|---|---|---|
| 刀具数量 | 转储每个端点(100+) | 策划高价值工具(50 岁以下) |
| 工具说明 | “DNS 是否有作用”或 200 字墙 | 动词+它的作用+“何时使用”触发器 |
| 注释 | 所有工具均缺失 | 在每个工具上设置:只读、破坏性、幂等、openWorld |
| 运输 | 具有会话管理功能的 SSE | 无状态流式 HTTP |
| 输入验证 | 没有任何; 输入错误时崩溃 | 根据 OpenAPI 规范生成的 Zod 模式 |
| 错误响应 | “出了点问题” | 包含字段、预期和接收的结构化 JSON |
| 验证 | 无,或完全阻止匿名使用 | 具有匿名回退和速率限制的 API 密钥转发 |
10,000 台服务器的格局
由于协议稳定,MCP 服务器在六个月内从 1,000 台增长到 10,000 台。 OAuth 2.1 取代了临时身份验证模式。 可流式 HTTP 取代了 SSE。 Linux基金会 治理让企业有信心构建生产服务器。 六种语言的 SDK 降低 进入壁垒。
但数量并没有带来质量。 这些服务器中的大多数都是周末实验,从未过去 “注册我的所有端点并看看会发生什么”阶段。 开发者日常使用的服务器 投资于管理、描述、模式、错误处理和验证。 这五个领域占90% 可用性差距的寿命。
如果您要在 2026 年构建 MCP 服务器,那么问题就不是“它是否有效”。 酒吧是“模型吗? 选择正确的工具,在选择错误时了解错误,并在无需人工干预的情况下恢复。” 上述七种做法可以帮助您实现这一目标。
Botoi 的 MCP 服务器已开放测试。 从 Claude Desktop、Claude Code、Cursor、VS Code 连接, 或使用 Windsurf 上的配置 MCP 设置页面。 完整的工具清单是 在 api.botoi.com/v1/mcp/tools.json, 和 API文档 覆盖工具背后的每个端点。
FAQ
- 2026 年有多少台 MCP 服务器?
- MCP 生态系统的公共服务器数量从 2025 年末的约 1,000 台增加到 2026 年 4 月。这一增长是由稳定的 OAuth 2.1 支持、取代 SSE 的 Streamable HTTP 传输以及 Claude Desktop、Cursor、Windsurf、Zed、Continue、Sourcegraph Cody 和 Taskade Genesis 中的客户端集成推动的。
- MCP 服务器应该公开多少个工具?
- 没有硬性限制,但越少越好。 每个工具定义都会消耗模型上下文窗口中的标记。 在对话开始之前,包含 150 个工具的清单可能会花费 30,000 多个代币。 Botoi 从 150 多个 API 端点中精选了 49 种工具。 除非您的用例需要更多工具,否则目标是使用 50 个以下的详细描述的工具。
- 2026 年我应该使用哪种 MCP 交通工具?
- Streamable HTTP 是稳定的、推荐的传输方式。 MCP 规范中不推荐使用 SSE(服务器发送事件)传输。 Streamable HTTP 使用带有 JSON-RPC 2.0 有效负载的标准 HTTP POST,可与任何 HTTP 基础设施(CDN、负载均衡器、边缘运行时)配合使用,并且不需要持久连接。
- 什么是 MCP 工具注释以及它们为何重要?
- 工具注释是 MCP 规范中定义的元数据提示:readOnlyHint、 DestructiveHint、idempotencyHint 和 openWorldHint。 它们告诉人工智能模型工具是否读取数据、写入数据、重试是否安全或联系外部服务。 模型使用这些提示来规划更安全的多步骤工作流程,并避免未经用户确认的破坏性调用。
- MCP 服务器需要身份验证吗?
- 是的。 MCP 规范现在包括用于身份验证的 OAuth 2.1。 即使对于更简单的设置,每个请求都需要持有者令牌或 API 密钥。 匿名访问应该有严格的速率限制。 Botoi 允许匿名访问,每分钟 5 个请求,每天 100 个,对经过身份验证的密钥有更高的限制。
开始使用 botoi 构建
150+ 个 API 端点,涵盖查询、文本处理、图片生成和开发者工具。免费套餐,无需信用卡。