mcp-creator
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseMCP Creator
MCP Creator
Expert in building production-ready Model Context Protocol servers. Creates safe, performant MCPs with proper security boundaries, robust error handling, and excellent developer experience.
专注于构建可用于生产环境的Model Context Protocol(MCP)服务器。能够创建具备完善安全边界、健壮错误处理能力和优秀开发者体验的安全、高性能MCP服务器。
When to Use This Skill
何时使用本技能
Use MCP when you need:
- External API integration with authentication
- Stateful connections (databases, WebSockets, sessions)
- Multiple related tools sharing configuration
- Security boundaries between Claude and external services
- Connection pooling and resource management
Do NOT use MCP for:
- Pure domain expertise (use Skill)
- Multi-step orchestration (use Agent)
- Local stateless operations (use Script)
- Simple file processing (use Claude's built-in tools)
在以下场景中使用MCP:
- 带认证的外部API集成
- 有状态连接(数据库、WebSocket、会话)
- 共享配置的多个关联工具
- Claude与外部服务之间的安全边界
- 连接池和资源管理
请勿在以下场景中使用MCP:
- 纯领域专业能力(使用Skill)
- 多步骤编排(使用Agent)
- 本地无状态操作(使用Script)
- 简单文件处理(使用Claude内置工具)
Quick Start
快速开始
bash
undefinedbash
undefinedScaffold new MCP server
Scaffold new MCP server
npx @modelcontextprotocol/create-server my-mcp-server
npx @modelcontextprotocol/create-server my-mcp-server
Install SDK
Install SDK
npm install @modelcontextprotocol/sdk
npm install @modelcontextprotocol/sdk
Test with inspector
Test with inspector
npx @modelcontextprotocol/inspector
undefinednpx @modelcontextprotocol/inspector
undefinedMCP Architecture Overview
MCP 架构概述
┌─────────────────────────────────────────────────────────────┐
│ Claude │
└─────────────────────────┬───────────────────────────────────┘
│ MCP Protocol (JSON-RPC)
┌─────────────────────────┴───────────────────────────────────┐
│ MCP Server │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ Tools │ │ Resources │ │ Prompts │ │
│ │ (actions) │ │ (read-only) │ │ (templates) │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
│ │ │
│ ┌───────────────────────┴──────────────────────────────┐ │
│ │ Auth / Rate Limiting / Caching │ │
│ └───────────────────────┬──────────────────────────────┘ │
└──────────────────────────┼──────────────────────────────────┘
│
┌──────────────────────────┴──────────────────────────────────┐
│ External Services │
│ APIs │ Databases │ File Systems │ WebSockets │
└─────────────────────────────────────────────────────────────┘┌─────────────────────────────────────────────────────────────┐
│ Claude │
└─────────────────────────┬───────────────────────────────────┘
│ MCP Protocol (JSON-RPC)
┌─────────────────────────┴───────────────────────────────────┐
│ MCP Server │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ Tools │ │ Resources │ │ Prompts │ │
│ │ (actions) │ │ (read-only) │ │ (templates) │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
│ │ │
│ ┌───────────────────────┴──────────────────────────────┐ │
│ │ Auth / Rate Limiting / Caching │ │
│ └───────────────────────┬──────────────────────────────┘ │
└──────────────────────────┼──────────────────────────────────┘
│
┌──────────────────────────┴──────────────────────────────────┐
│ External Services │
│ APIs │ Databases │ File Systems │ WebSockets │
└─────────────────────────────────────────────────────────────┘Core MCP Server Template
核心MCP服务器模板
typescript
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
ErrorCode,
McpError,
} from "@modelcontextprotocol/sdk/types.js";
const server = new Server(
{ name: "my-mcp-server", version: "1.0.0" },
{ capabilities: { tools: {} } }
);
// Tool definitions
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: "my_tool",
description: "Clear description of what this tool does",
inputSchema: {
type: "object",
properties: {
input: { type: "string", description: "Input description" },
},
required: ["input"],
},
},
],
}));
// Tool implementation
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
if (name === "my_tool") {
try {
const result = await processInput(args.input);
return { content: [{ type: "text", text: JSON.stringify(result) }] };
} catch (error) {
throw new McpError(ErrorCode.InternalError, error.message);
}
}
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
});
// Start server
const transport = new StdioServerTransport();
await server.connect(transport);typescript
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
ErrorCode,
McpError,
} from "@modelcontextprotocol/sdk/types.js";
const server = new Server(
{ name: "my-mcp-server", version: "1.0.0" },
{ capabilities: { tools: {} } }
);
// Tool definitions
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: "my_tool",
description: "Clear description of what this tool does",
inputSchema: {
type: "object",
properties: {
input: { type: "string", description: "Input description" },
},
required: ["input"],
},
},
],
}));
// Tool implementation
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
if (name === "my_tool") {
try {
const result = await processInput(args.input);
return { content: [{ type: "text", text: JSON.stringify(result) }] };
} catch (error) {
throw new McpError(ErrorCode.InternalError, error.message);
}
}
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
});
// Start server
const transport = new StdioServerTransport();
await server.connect(transport);Tool Design Principles
工具设计原则
1. Clear Naming
1. 清晰命名
typescript
// ✅ Good: Action-oriented, specific
"get_user_profile"
"create_issue"
"analyze_sentiment"
// ❌ Bad: Vague, generic
"process"
"do_thing"
"handle"typescript
// ✅ Good: Action-oriented, specific
"get_user_profile"
"create_issue"
"analyze_sentiment"
// ❌ Bad: Vague, generic
"process"
"do_thing"
"handle"2. Precise Input Schemas
2. 精准的输入Schema
typescript
// ✅ Good: Typed, constrained, documented
{
type: "object",
properties: {
userId: { type: "string", pattern: "^[a-f0-9]{24}$" },
action: { type: "string", enum: ["read", "write", "delete"] },
limit: { type: "integer", minimum: 1, maximum: 100, default: 10 }
},
required: ["userId", "action"],
additionalProperties: false
}
// ❌ Bad: Untyped, unconstrained
{ type: "object" }typescript
// ✅ Good: Typed, constrained, documented
{
type: "object",
properties: {
userId: { type: "string", pattern: "^[a-f0-9]{24}$" },
action: { type: "string", enum: ["read", "write", "delete"] },
limit: { type: "integer", minimum: 1, maximum: 100, default: 10 }
},
required: ["userId", "action"],
additionalProperties: false
}
// ❌ Bad: Untyped, unconstrained
{ type: "object" }3. Structured Outputs
3. 结构化输出
typescript
// ✅ Good: Consistent structure
return {
content: [{
type: "text",
text: JSON.stringify({
success: true,
data: result,
metadata: { requestId, timestamp }
}, null, 2)
}]
};
// ❌ Bad: Inconsistent, unstructured
return { content: [{ type: "text", text: "done" }] };typescript
// ✅ Good: Consistent structure
return {
content: [{
type: "text",
text: JSON.stringify({
success: true,
data: result,
metadata: { requestId, timestamp }
}, null, 2)
}]
};
// ❌ Bad: Inconsistent, unstructured
return { content: [{ type: "text", text: "done" }] };Security Hardening (CRITICAL)
安全加固(至关重要)
Input Validation
输入验证
typescript
import { z } from "zod";
const UserInputSchema = z.object({
userId: z.string().regex(/^[a-f0-9]{24}$/),
email: z.string().email(),
query: z.string().max(1000).refine(
(q) => !q.includes("--") && !q.includes(";"),
{ message: "Invalid characters in query" }
),
});
async function handleTool(args: unknown) {
const validated = UserInputSchema.parse(args); // Throws on invalid
// Safe to use validated data
}typescript
import { z } from "zod";
const UserInputSchema = z.object({
userId: z.string().regex(/^[a-f0-9]{24}$/),
email: z.string().email(),
query: z.string().max(1000).refine(
(q) => !q.includes("--") && !q.includes(";"),
{ message: "Invalid characters in query" }
),
});
async function handleTool(args: unknown) {
const validated = UserInputSchema.parse(args); // Throws on invalid
// Safe to use validated data
}Secret Management
密钥管理
typescript
// ✅ Good: Environment variables
const API_KEY = process.env.SERVICE_API_KEY;
if (!API_KEY) throw new Error("SERVICE_API_KEY required");
// ✅ Good: Secret manager integration
const secret = await secretManager.getSecret("service-api-key");
// ❌ NEVER: Hardcoded secrets
const API_KEY = "sk-abc123..."; // SECURITY VULNERABILITYtypescript
// ✅ Good: Environment variables
const API_KEY = process.env.SERVICE_API_KEY;
if (!API_KEY) throw new Error("SERVICE_API_KEY required");
// ✅ Good: Secret manager integration
const secret = await secretManager.getSecret("service-api-key");
// ❌ NEVER: Hardcoded secrets
const API_KEY = "sk-abc123..."; // SECURITY VULNERABILITYRate Limiting
速率限制
typescript
class RateLimiter {
private requests: Map<string, number[]> = new Map();
canProceed(key: string, limit: number, windowMs: number): boolean {
const now = Date.now();
const timestamps = this.requests.get(key) || [];
const recent = timestamps.filter(t => now - t < windowMs);
if (recent.length >= limit) return false;
recent.push(now);
this.requests.set(key, recent);
return true;
}
}
const limiter = new RateLimiter();
// In tool handler
if (!limiter.canProceed(userId, 100, 60000)) {
throw new McpError(ErrorCode.InvalidRequest, "Rate limit exceeded");
}typescript
class RateLimiter {
private requests: Map<string, number[]> = new Map();
canProceed(key: string, limit: number, windowMs: number): boolean {
const now = Date.now();
const timestamps = this.requests.get(key) || [];
const recent = timestamps.filter(t => now - t < windowMs);
if (recent.length >= limit) return false;
recent.push(now);
this.requests.set(key, recent);
return true;
}
}
const limiter = new RateLimiter();
// In tool handler
if (!limiter.canProceed(userId, 100, 60000)) {
throw new McpError(ErrorCode.InvalidRequest, "Rate limit exceeded");
}Authentication Boundaries
认证边界
typescript
// Validate credentials before any operation
async function withAuth<T>(
credentials: Credentials,
operation: () => Promise<T>
): Promise<T> {
if (!await validateCredentials(credentials)) {
throw new McpError(ErrorCode.InvalidRequest, "Invalid credentials");
}
return operation();
}typescript
// Validate credentials before any operation
async function withAuth<T>(
credentials: Credentials,
operation: () => Promise<T>
): Promise<T> {
if (!await validateCredentials(credentials)) {
throw new McpError(ErrorCode.InvalidRequest, "Invalid credentials");
}
return operation();
}Error Handling Patterns
错误处理模式
Structured Error Responses
结构化错误响应
typescript
// Define error types
enum ServiceError {
NOT_FOUND = "NOT_FOUND",
UNAUTHORIZED = "UNAUTHORIZED",
RATE_LIMITED = "RATE_LIMITED",
VALIDATION_ERROR = "VALIDATION_ERROR",
EXTERNAL_SERVICE_ERROR = "EXTERNAL_SERVICE_ERROR",
}
// Map to MCP errors
function toMcpError(error: unknown): McpError {
if (error instanceof z.ZodError) {
return new McpError(
ErrorCode.InvalidParams,
`Validation error: ${error.errors.map(e => e.message).join(", ")}`
);
}
if (error instanceof ServiceError) {
return new McpError(ErrorCode.InternalError, error.message);
}
return new McpError(ErrorCode.InternalError, "Unknown error occurred");
}typescript
// Define error types
enum ServiceError {
NOT_FOUND = "NOT_FOUND",
UNAUTHORIZED = "UNAUTHORIZED",
RATE_LIMITED = "RATE_LIMITED",
VALIDATION_ERROR = "VALIDATION_ERROR",
EXTERNAL_SERVICE_ERROR = "EXTERNAL_SERVICE_ERROR",
}
// Map to MCP errors
function toMcpError(error: unknown): McpError {
if (error instanceof z.ZodError) {
return new McpError(
ErrorCode.InvalidParams,
`Validation error: ${error.errors.map(e => e.message).join(", ")}`
);
}
if (error instanceof ServiceError) {
return new McpError(ErrorCode.InternalError, error.message);
}
return new McpError(ErrorCode.InternalError, "Unknown error occurred");
}Graceful Degradation
优雅降级
typescript
async function fetchWithFallback<T>(
primary: () => Promise<T>,
fallback: () => Promise<T>,
options: { retries?: number; timeout?: number } = {}
): Promise<T> {
const { retries = 3, timeout = 5000 } = options;
for (let i = 0; i < retries; i++) {
try {
return await Promise.race([
primary(),
new Promise<never>((_, reject) =>
setTimeout(() => reject(new Error("Timeout")), timeout)
),
]);
} catch (error) {
if (i === retries - 1) {
console.error("Primary failed, trying fallback:", error);
return fallback();
}
await new Promise(r => setTimeout(r, 1000 * (i + 1))); // Backoff
}
}
throw new Error("All retries exhausted");
}typescript
async function fetchWithFallback<T>(
primary: () => Promise<T>,
fallback: () => Promise<T>,
options: { retries?: number; timeout?: number } = {}
): Promise<T> {
const { retries = 3, timeout = 5000 } = options;
for (let i = 0; i < retries; i++) {
try {
return await Promise.race([
primary(),
new Promise<never>((_, reject) =>
setTimeout(() => reject(new Error("Timeout")), timeout)
),
]);
} catch (error) {
if (i === retries - 1) {
console.error("Primary failed, trying fallback:", error);
return fallback();
}
await new Promise(r => setTimeout(r, 1000 * (i + 1))); // Backoff
}
}
throw new Error("All retries exhausted");
}Performance Optimization
性能优化
Connection Pooling
连接池
typescript
// PostgreSQL pool
import { Pool } from "pg";
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
max: 20,
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 2000,
});
// Reuse connections
async function query(sql: string, params: unknown[]) {
const client = await pool.connect();
try {
return await client.query(sql, params);
} finally {
client.release();
}
}typescript
// PostgreSQL pool
import { Pool } from "pg";
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
max: 20,
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 2000,
});
// Reuse connections
async function query(sql: string, params: unknown[]) {
const client = await pool.connect();
try {
return await client.query(sql, params);
} finally {
client.release();
}
}Caching Layer
缓存层
typescript
class Cache<T> {
private store: Map<string, { value: T; expires: number }> = new Map();
get(key: string): T | undefined {
const entry = this.store.get(key);
if (!entry) return undefined;
if (Date.now() > entry.expires) {
this.store.delete(key);
return undefined;
}
return entry.value;
}
set(key: string, value: T, ttlMs: number): void {
this.store.set(key, { value, expires: Date.now() + ttlMs });
}
}
const cache = new Cache<ApiResponse>();
async function fetchWithCache(url: string): Promise<ApiResponse> {
const cached = cache.get(url);
if (cached) return cached;
const response = await fetch(url);
const data = await response.json();
cache.set(url, data, 300000); // 5 min TTL
return data;
}typescript
class Cache<T> {
private store: Map<string, { value: T; expires: number }> = new Map();
get(key: string): T | undefined {
const entry = this.store.get(key);
if (!entry) return undefined;
if (Date.now() > entry.expires) {
this.store.delete(key);
return undefined;
}
return entry.value;
}
set(key: string, value: T, ttlMs: number): void {
this.store.set(key, { value, expires: Date.now() + ttlMs });
}
}
const cache = new Cache<ApiResponse>();
async function fetchWithCache(url: string): Promise<ApiResponse> {
const cached = cache.get(url);
if (cached) return cached;
const response = await fetch(url);
const data = await response.json();
cache.set(url, data, 300000); // 5 min TTL
return data;
}Anti-Patterns
反模式
Anti-Pattern: No Input Validation
反模式:无输入验证
What it looks like: Passing user input directly to APIs/databases
Why wrong: SQL injection, command injection, data corruption
Instead: Validate with Zod, sanitize inputs, use parameterized queries
表现:直接将用户输入传递给API/数据库
危害:SQL注入、命令注入、数据损坏
正确做法:使用Zod进行验证,清理输入,使用参数化查询
Anti-Pattern: Secrets in Code
反模式:代码中嵌入密钥
What it looks like: Hardcoded API keys, tokens in source
Why wrong: Secrets leak via git, logs, error messages
Instead: Environment variables, secret managers, encrypted config
表现:在源代码中硬编码API密钥、令牌
危害:密钥会通过Git、日志、错误信息泄露
正确做法:使用环境变量、密钥管理工具、加密配置
Anti-Pattern: No Rate Limiting
反模式:无速率限制
What it looks like: Unlimited API calls to external services
Why wrong: Cost explosion, API bans, resource exhaustion
Instead: Token bucket, sliding window, or adaptive rate limiting
表现:对外部服务的API调用无限制
危害:成本激增、API被封禁、资源耗尽
正确做法:使用令牌桶、滑动窗口或自适应速率限制
Anti-Pattern: Synchronous Blocking
反模式:同步阻塞
What it looks like: , blocking I/O in async handlers
Why wrong: Blocks all requests, causes timeouts
Instead: Proper async/await, non-blocking patterns
sleep()表现:在异步处理程序中使用、阻塞I/O
危害:阻塞所有请求,导致超时
正确做法:使用正确的async/await、非阻塞模式
sleep()Anti-Pattern: Silent Failures
反模式:静默失败
What it looks like: Empty catch blocks, swallowed errors
Why wrong: Debugging impossible, data corruption undetected
Instead: Structured error handling, logging, proper propagation
表现:空catch块、吞掉错误
危害:无法调试、无法检测数据损坏
正确做法:结构化错误处理、日志记录、正确的错误传播
Anti-Pattern: No Timeouts
反模式:无超时设置
What it looks like: Waiting indefinitely for external services
Why wrong: Hung connections, resource leaks
Instead: Explicit timeouts on all external calls, circuit breakers
表现:无限期等待外部服务响应
危害:连接挂起、资源泄漏
正确做法:对所有外部调用设置明确超时,使用断路器模式
Testing Your MCP
测试你的MCP
Using MCP Inspector
使用MCP Inspector
bash
undefinedbash
undefinedStart inspector
Start inspector
npx @modelcontextprotocol/inspector
npx @modelcontextprotocol/inspector
In another terminal, start your server
In another terminal, start your server
node dist/index.js
node dist/index.js
Connect inspector to your server
Connect inspector to your server
Test tool invocations manually
Test tool invocations manually
undefinedundefinedUnit Testing
单元测试
typescript
import { describe, it, expect } from "vitest";
describe("my_tool", () => {
it("should validate input", async () => {
await expect(
handleTool({ userId: "invalid" })
).rejects.toThrow("Invalid userId format");
});
it("should return structured output", async () => {
const result = await handleTool({ userId: "507f1f77bcf86cd799439011" });
expect(result).toHaveProperty("success", true);
expect(result).toHaveProperty("data");
});
});typescript
import { describe, it, expect } from "vitest";
describe("my_tool", () => {
it("should validate input", async () => {
await expect(
handleTool({ userId: "invalid" })
).rejects.toThrow("Invalid userId format");
});
it("should return structured output", async () => {
const result = await handleTool({ userId: "507f1f77bcf86cd799439011" });
expect(result).toHaveProperty("success", true);
expect(result).toHaveProperty("data");
});
});Decision Tree: When to Add to MCP
决策树:何时将功能加入MCP
Does this tool need...
├── External API with auth? → Add to MCP
├── Persistent state/connection? → Add to MCP
├── Rate limiting for external service? → Add to MCP
├── Shared credentials with other tools? → Add to MCP
├── Security boundary from Claude? → Add to MCP
└── None of the above? → Consider Script insteadDoes this tool need...
├── External API with auth? → Add to MCP
├── Persistent state/connection? → Add to MCP
├── Rate limiting for external service? → Add to MCP
├── Shared credentials with other tools? → Add to MCP
├── Security boundary from Claude? → Add to MCP
└── None of the above? → Consider Script insteadSuccess Metrics
成功指标
| Metric | Target |
|---|---|
| Tool latency P95 | < 500ms |
| Error rate | < 1% |
| Input validation coverage | 100% |
| Secret exposure | 0 |
| Rate limit violations | 0 |
| 指标 | 目标 |
|---|---|
| 工具延迟P95 | < 500ms |
| 错误率 | < 1% |
| 输入验证覆盖率 | 100% |
| 密钥暴露 | 0 |
| 速率限制违规 | 0 |
Reference Files
参考文件
| File | Contents |
|---|---|
| Transport layers, server lifecycle, resource management |
| Schema patterns, naming conventions, output formats |
| Complete OWASP-aligned security checklist |
| Error types, recovery strategies, logging |
| Inspector usage, unit/integration tests |
| Caching, pooling, async patterns |
| Production-ready server templates |
Creates: Safe, performant MCP servers | Robust tool interfaces | Security-hardened integrations
Use with: security-auditor (security review) | site-reliability-engineer (deployment) | agent-creator (when MCP supports agents)
| 文件 | 内容 |
|---|---|
| 传输层、服务器生命周期、资源管理 |
| Schema模式、命名规范、输出格式 |
| 符合OWASP标准的完整安全检查表 |
| 错误类型、恢复策略、日志记录 |
| Inspector使用方法、单元/集成测试 |
| 缓存、连接池、异步模式 |
| 生产级服务器模板 |
可创建:安全、高性能的MCP服务器 | 健壮的工具接口 | 经过安全加固的集成
搭配使用:security-auditor(安全审查)| site-reliability-engineer(部署)| agent-creator(当MCP支持Agent时)