重要前提
安装AI Skills的关键前提是:必须科学上网,且开启TUN模式,这一点至关重要,直接决定安装能否顺利完成,在此郑重提醒三遍:科学上网,科学上网,科学上网。查看完整安装教程 →
mcp-creator by erichowens/some_claude_skills
npx skills add https://github.com/erichowens/some_claude_skills --skill mcp-creator精通构建生产就绪的 Model Context Protocol 服务器的专家。创建安全、高性能的 MCP,具备适当的安全边界、稳健的错误处理和出色的开发者体验。
在以下情况使用 MCP:
以下情况请勿使用 MCP:
# 脚手架新建 MCP 服务器
npx @modelcontextprotocol/create-server my-mcp-server
# 安装 SDK
npm install @modelcontextprotocol/sdk
# 使用检查器测试
npx @modelcontextprotocol/inspector
┌─────────────────────────────────────────────────────────────┐
│ 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 │
└─────────────────────────────────────────────────────────────┘
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
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: {} } }
);
// 工具定义
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: "my_tool",
description: "此工具功能的清晰描述",
inputSchema: {
type: "object",
properties: {
input: { type: "string", description: "输入描述" },
},
required: ["input"],
},
},
],
}));
// 工具实现
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, `未知工具: ${name}`);
});
// 启动服务器
const transport = new StdioServerTransport();
await server.connect(transport);
// ✅ 良好:面向操作、具体
"get_user_profile"
"create_issue"
"analyze_sentiment"
// ❌ 不佳:模糊、通用
"process"
"do_thing"
"handle"
// ✅ 良好:类型化、受约束、有文档说明
{
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
}
// ❌ 不佳:无类型、无约束
{ type: "object" }
// ✅ 良好:一致的结构
return {
content: [{
type: "text",
text: JSON.stringify({
success: true,
data: result,
metadata: { requestId, timestamp }
}, null, 2)
}]
};
// ❌ 不佳:不一致、非结构化
return { content: [{ type: "text", text: "done" }] };
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: "查询中包含无效字符" }
),
});
async function handleTool(args: unknown) {
const validated = UserInputSchema.parse(args); // 无效时抛出异常
// 可以安全使用已验证的数据
}
// ✅ 良好:环境变量
const API_KEY = process.env.SERVICE_API_KEY;
if (!API_KEY) throw new Error("需要 SERVICE_API_KEY");
// ✅ 良好:密钥管理器集成
const secret = await secretManager.getSecret("service-api-key");
// ❌ 绝对禁止:硬编码密钥
const API_KEY = "sk-abc123..."; // 安全漏洞
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();
// 在工具处理程序中
if (!limiter.canProceed(userId, 100, 60000)) {
throw new McpError(ErrorCode.InvalidRequest, "超出速率限制");
}
// 在任何操作之前验证凭据
async function withAuth<T>(
credentials: Credentials,
operation: () => Promise<T>
): Promise<T> {
if (!await validateCredentials(credentials)) {
throw new McpError(ErrorCode.InvalidRequest, "无效凭据");
}
return operation();
}
// 定义错误类型
enum ServiceError {
NOT_FOUND = "NOT_FOUND",
UNAUTHORIZED = "UNAUTHORIZED",
RATE_LIMITED = "RATE_LIMITED",
VALIDATION_ERROR = "VALIDATION_ERROR",
EXTERNAL_SERVICE_ERROR = "EXTERNAL_SERVICE_ERROR",
}
// 映射到 MCP 错误
function toMcpError(error: unknown): McpError {
if (error instanceof z.ZodError) {
return new McpError(
ErrorCode.InvalidParams,
`验证错误: ${error.errors.map(e => e.message).join(", ")}`
);
}
if (error instanceof ServiceError) {
return new McpError(ErrorCode.InternalError, error.message);
}
return new McpError(ErrorCode.InternalError, "发生未知错误");
}
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)
),
]);
} catch (error) {
if (i === retries - 1) {
console.error("主方法失败,尝试备用方法:", error);
return fallback();
}
await new Promise(r => setTimeout(r, 1000 * (i + 1))); // 退避
}
}
throw new Error("所有重试已用尽");
}
// PostgreSQL 连接池
import { Pool } from "pg";
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
max: 20,
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 2000,
});
// 重用连接
async function query(sql: string, params: unknown[]) {
const client = await pool.connect();
try {
return await client.query(sql, params);
} finally {
client.release();
}
}
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 分钟 TTL
return data;
}
表现:将用户输入直接传递给 API/数据库
为何错误:SQL 注入、命令注入、数据损坏
替代方案:使用 Zod 验证、清理输入、使用参数化查询
表现:硬编码的 API 密钥、源代码中的令牌
为何错误:密钥通过 git、日志、错误消息泄露
替代方案:环境变量、密钥管理器、加密配置
表现:对外部服务的无限 API 调用
为何错误:成本激增、API 封禁、资源耗尽
替代方案:令牌桶、滑动窗口或自适应速率限制
表现:在异步处理程序中使用 sleep()、阻塞 I/O
为何错误:阻塞所有请求、导致超时
替代方案:正确的 async/await、非阻塞模式
表现:空的 catch 块、吞没错误
为何错误:无法调试、数据损坏未被发现
替代方案:结构化的错误处理、日志记录、正确传播
表现:无限期等待外部服务
为何错误:连接挂起、资源泄漏
替代方案:所有外部调用设置显式超时、断路器
# 启动检查器
npx @modelcontextprotocol/inspector
# 在另一个终端,启动你的服务器
node dist/index.js
# 将检查器连接到你的服务器
# 手动测试工具调用
import { describe, it, expect } from "vitest";
describe("my_tool", () => {
it("应验证输入", async () => {
await expect(
handleTool({ userId: "invalid" })
).rejects.toThrow("无效的 userId 格式");
});
it("应返回结构化输出", async () => {
const result = await handleTool({ userId: "507f1f77bcf86cd799439011" });
expect(result).toHaveProperty("success", true);
expect(result).toHaveProperty("data");
});
});
此工具是否需要...
├── 带身份验证的外部 API? → 添加到 MCP
├── 持久状态/连接? → 添加到 MCP
├── 对外部服务的速率限制? → 添加到 MCP
├── 与其他工具共享凭据? → 添加到 MCP
├── 与 Claude 的安全边界? → 添加到 MCP
└── 以上都不是? → 考虑使用 Script 替代
| 指标 | 目标 |
|---|---|
| 工具延迟 P95 | < 500ms |
| 错误率 | < 1% |
| 输入验证覆盖率 | 100% |
| 密钥暴露 | 0 |
| 速率限制违规 | 0 |
| 文件 | 内容 |
|---|---|
references/architecture-patterns.md | 传输层、服务器生命周期、资源管理 |
references/tool-design.md | 模式模式、命名约定、输出格式 |
references/security-hardening.md | 完整的 OWASP 对齐安全清单 |
references/error-handling.md | 错误类型、恢复策略、日志记录 |
references/testing-debugging.md | 检查器使用、单元/集成测试 |
references/performance.md | 缓存、池化、异步模式 |
templates/ | 生产就绪的服务器模板 |
创建:安全、高性能的 MCP 服务器 | 稳健的工具接口 | 安全加固的集成
配合使用:security-auditor(安全审查) | site-reliability-engineer(部署) | agent-creator(当 MCP 支持代理时)
每周安装
55
仓库
GitHub 星标
78
首次出现
2026年1月24日
安全审计
安装于
cursor47
codex47
gemini-cli46
opencode46
github-copilot43
claude-code41
Expert in building production-ready Model Context Protocol servers. Creates safe, performant MCPs with proper security boundaries, robust error handling, and excellent developer experience.
Use MCP when you need:
Do NOT use MCP for:
# Scaffold new MCP server
npx @modelcontextprotocol/create-server my-mcp-server
# Install SDK
npm install @modelcontextprotocol/sdk
# Test with inspector
npx @modelcontextprotocol/inspector
┌─────────────────────────────────────────────────────────────┐
│ 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 │
└─────────────────────────────────────────────────────────────┘
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);
// ✅ Good: Action-oriented, specific
"get_user_profile"
"create_issue"
"analyze_sentiment"
// ❌ Bad: Vague, generic
"process"
"do_thing"
"handle"
// ✅ 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" }
// ✅ 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" }] };
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
}
// ✅ 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 VULNERABILITY
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");
}
// 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();
}
// 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");
}
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");
}
// 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();
}
}
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;
}
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
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
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
What it looks like : sleep(), blocking I/O in async handlers Why wrong : Blocks all requests, causes timeouts Instead : Proper async/await, non-blocking patterns
What it looks like : Empty catch blocks, swallowed errors Why wrong : Debugging impossible, data corruption undetected Instead : Structured error handling, logging, proper propagation
What it looks like : Waiting indefinitely for external services Why wrong : Hung connections, resource leaks Instead : Explicit timeouts on all external calls, circuit breakers
# Start inspector
npx @modelcontextprotocol/inspector
# In another terminal, start your server
node dist/index.js
# Connect inspector to your server
# Test tool invocations manually
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");
});
});
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 instead
| Metric | Target |
|---|---|
| Tool latency P95 | < 500ms |
| Error rate | < 1% |
| Input validation coverage | 100% |
| Secret exposure | 0 |
| Rate limit violations | 0 |
| File | Contents |
|---|---|
references/architecture-patterns.md | Transport layers, server lifecycle, resource management |
references/tool-design.md | Schema patterns, naming conventions, output formats |
references/security-hardening.md | Complete OWASP-aligned security checklist |
references/error-handling.md | Error types, recovery strategies, logging |
references/testing-debugging.md | Inspector usage, unit/integration tests |
references/performance.md |
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)
Weekly Installs
55
Repository
GitHub Stars
78
First Seen
Jan 24, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykWarn
Installed on
cursor47
codex47
gemini-cli46
opencode46
github-copilot43
claude-code41
agent-browser 浏览器自动化工具 - Vercel Labs 命令行网页操作与测试
172,600 周安装
| Caching, pooling, async patterns |
templates/ | Production-ready server templates |