Token导航 LogoToken导航

Agent Skill · 开发规范

mcp-best-practices(MCP 最佳实践)

mcp-best-practices 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

mcp-best-practices 是开发规范类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为调用外部服务;许可证信息还不明确,第三方扫描有提醒项,按安装量在开发规范类的 1,265 个 Skill 里排第 703。

总安装 563周安装 23GitHub Stars 24下载 182核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
unknown

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:mcp-best-practices(MCP 最佳实践)
来源仓库:https://github.com/tenequm/skills
仓库路径:skills/mcp-best-practices
安装命令:
npx skills add https://github.com/tenequm/skills --skill mcp-best-practices
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/tenequm/skills --skill mcp-best-practices

这个 Skill 是做什么的

开发规范类 Skill 用来统一代码风格、目录结构和评审口径,产出多为检查清单或改写建议。

mcp-best-practices 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合整理项目状态与变更。适用于围绕仓库状态、代码变更或协作事项进行信息梳理的场景。通过 npx skills add 命令从 GitHub 安装,需结合原始 README 确认具体用法。

安装前建议确认权限范围、维护状态及是否触发联网或文件操作。适用宿主包括 Codex、Claude、Cursor、Gemini CLI,接入前应确认版本、权限和运行环境要求。

来源仓库内路径:skills/mcp-best-practices

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/tenequm/skills --skill mcp-best-practices;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要调用外部服务,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

mcp-best-practices 怎么安装?

在终端执行 npx skills add https://github.com/tenequm/skills --skill mcp-best-practices。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

mcp-best-practices 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

mcp-best-practices 需要什么权限?

权限级别是调用外部服务。该 Skill 可能调用第三方服务、云服务或外部模型 API,使用前需要确认账号、额度、数据发送范围和服务条款。

mcp-best-practices 是免费的吗?

公开资料没有标注明确许可证,收费和商用限制都无法确认。正式使用前请到来源仓库核对授权说明。

mcp-best-practices 用的人多吗?

公开数据是累计安装 563 次,近一周安装 23 次,下载 182 次,GitHub 24 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

mcp-best-practices 安全吗?

第三方扫描有提醒项,说明存在需要人工确认的行为。安装前请打开源码看清它读了什么、联网到哪里。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。

先想清楚的地方

  • 许可证没有明确标注,能不能商用、能不能再分发都不确定。
  • 第三方扫描存在提醒项或未通过项,需要人工逐条确认。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理开发规范类任务、又不想每次都手写提示词的人。

不太适合

  • 需要明确授权才能用到公司项目里的场景。
  • 需要厂商级技术支持和 SLA 的生产系统。

开发规范类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
vercel-react-best-practices

Vercel React 最佳实践 · Codex、Claude

8,490,72025,918操作浏览器MIT通过
web-design-guidelines

网页设计指南 · Codex、Claude

6,686,01625,885需要联网MIT有提醒
remotion-best-practices

Remotion 最佳实践 · Codex、Claude

6,505,6323,027操作浏览器MIT有提醒
supabase-postgres-best-practices

Supabase Postgres 最佳实践 · Codex、Claude

3,175,5232,030需要联网MIT通过
next-best-practices

Next.js 最佳实践 · Codex、Claude

1,848,240841操作浏览器MIT通过
mcp-best-practices

MCP 最佳实践 · 本页

56324调用外部服务未明确有提醒

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

MCP Best Practices

Decision reference for building production MCP servers with the TypeScript SDK. Not a tutorial - assumes you already have a working server and need to make it correct, fast, and secure.

Quick Reference

ComponentCurrentNext
Spec2025-11-25 (spec.modelcontextprotocol.io)-
TS SDK (stable)v1.29.0 (@modelcontextprotocol/sdk)v2 alpha published
TS SDK (v2)Alpha (2.0.0-alpha.2 on npm, Apr 2026): /server, /client, /core, /hono, /express, /node, /fastifyQ3 2026 stable target
JSON Schema2020-12 default (explicit $schema supported)-
TransportStreamable HTTP (remote), stdio (local)SSE + WebSocket removed in v2
ExtensionsMCP Apps (Stable, SEP-1865), Auth Extensions (official)Domain-specific WGs
RegistryPreview with v0.1 API freeze since 2025-10-24 (registry)GA pending

v1 imports (production today):

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";

v2 imports (when stable):

import { McpServer } from "@modelcontextprotocol/server";
import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/server";

Server Setup

Transport Decision

ScenarioTransportKey Config
Remote, stateless (K8s, CF Workers)WebStandardStreamableHTTPServerTransportsessionIdGenerator: undefined, enableJsonResponse: true
Remote, stateful (long tasks, SSE)WebStandardStreamableHTTPServerTransportsessionIdGenerator: () => randomUUID()
Local CLI / Claude DesktopStdioServerTransportDefault
Legacy SSE clientsSSE removed in v2 - migrate to Streamable HTTP-

Stateless Pattern (recommended for remote deployment)

Per-request server+transport creation is the canonical pattern. Maintainer @ihrpr confirms: "each transport should have an instance of MCPServer" (#343). Sharing instances leaks cross-client data (GHSA-345p-7cg4-v4c7).

app.post("/mcp", async (c) => {
  const server = new McpServer({ name: "my-server", version: "1.0.0" });
  // Register tools, resources, prompts...
  registerTools(server);

  const transport = new WebStandardStreamableHTTPServerTransport({
    sessionIdGenerator: undefined,   // stateless - no session tracking
    enableJsonResponse: true,        // JSON responses, no SSE streaming
  });

  // All tools/resources must be registered before connect() (#893)
  try {
    await server.connect(transport);
    return transport.handleRequest(c.req.raw);
  } finally {
    await transport.close();
    await server.close();
  }
});

What to hoist to module level (don't recreate per request):

  • Zod schemas (they never change)
  • Annotation objects ({readOnlyHint: true,...})
  • Tool description strings
  • Payment configs, upstream API clients

The McpServer itself must be per-request, but its constant inputs should not be.

For deep dive on transports, sessions, HTTP/2 gotchas, and K8s deployment: see references/transport-patterns.md

Framework Integration

Hono (web-standard):

import { Hono } from "hono";
const app = new Hono();
app.post("/mcp", handleMcpRequest);  // WebStandardStreamableHTTPServerTransport
app.get("/mcp", handleMcpSse);       // Optional: SSE for server notifications
app.delete("/mcp", handleMcpDelete); // Optional: session termination

Cloudflare Workers: Same pattern - WebStandardStreamableHTTPServerTransport works natively in Workers runtime.

Express/Node (v2): Use @modelcontextprotocol/express middleware with NodeStreamableHTTPServerTransport (wraps the Web Standard transport for IncomingMessage/ServerResponse).

Tool Design

Registration API

v1 (current stable) - server.tool() works but has ambiguous overloads. Prefer the config-object form when possible:

server.tool("search_docs", "Search documents", {
  query: z.string().describe("Search query"),
  max_results: z.number().optional().describe("Max results (default 20)"),
}, { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
  async ({ query, max_results }) => { /* handler */ }
);

v2 (migration target) - registerTool() with config object:

server.registerTool("search_docs", {
  title: "Document Search",
  description: "Search documents by keyword or phrase",
  inputSchema: z.object({
    query: z.string().describe("Search query"),
    max_results: z.number().optional().describe("Max results (default 20)"),
  }),
  outputSchema: z.object({
    results: z.array(z.object({ id: z.string(), text: z.string() })),
    has_more: z.boolean(),
  }),
  annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
}, async ({ query, max_results }) => {
  const result = await fetchDocs(query, max_results);
  return {
    structuredContent: result,
    content: [{ type: "text", text: JSON.stringify(result) }],
  };
});

Naming

Spec (2025-11-25): 1-128 chars, case-sensitive. Allowed: A-Za-z0-9_-.

DO: search_docs, get_user_profile, admin.tools.list DON'T: search (too generic, collides across servers), Search Docs (spaces not allowed)

Service-prefix your tools (github_*, jira_*) when multiple servers are active - LLMs confuse generic names across servers.

Schema Rules

.describe() on every field - this is what LLMs use for argument generation.

For complete Zod-to-JSON-Schema conversion rules, what breaks silently, outputSchema/structuredContent patterns: see references/tool-schema-guide.md

Critical bugs:

  • z.union() / z.discriminatedUnion() silently produce empty schemas on v1.x (#1643, fixed on main 2026-03-30). Use flat z.object() with z.enum() discriminator field instead until v1 ships the fix.
  • Plain JSON Schema objects silently dropped before v1.28.0. Fixed in v1.28 - now throws at registration (#1596).
  • z.transform() stripped during conversion - JSON Schema can't represent transforms (#702).
  • Client-side AJV strict-mode rejection: Zod v4 z.object() produces JSON Schema with additionalProperties: false. The SDK's client validates structuredContent against outputSchema with AJV strict mode and rejects extra fields. Server-side .parse() strips extras silently, but the original structuredContent is sent to the client unchanged - so the server thinks it's fine and the client errors. Fix: explicitly .parse() upstream data before assigning to structuredContent, or use .passthrough() on schemas that intentionally pass through extra fields.

Annotations

All are optional hints (untrusted from untrusted servers per spec):

AnnotationDefaultMeaning
readOnlyHintfalseTool doesn't modify its environment
destructiveHinttrueMay perform destructive updates (only when readOnly=false)
idempotentHintfalseRepeated calls with same args have no additional effect
openWorldHinttrueInteracts with external entities (APIs, web)

Set them accurately - clients use them for consent prompts and auto-approval decisions.

Open SEPs expanding annotations:

  • #1913 Trust and Sensitivity - data classification hints
  • #1984 Comprehensive annotations for governance/UX
  • #1561 unsafeOutputHint - output may contain untrusted content
  • #1560 secretHint - tool handles secrets/credentials
  • #1487 trustedHint - server attestation of tool trustworthiness

The "Lethal Trifecta": Combining (1) access to private data + (2) exposure to untrusted content + (3) external communication ability creates data theft conditions. Researchers demonstrated this with a malicious calendar event, an MCP calendar server, and a code execution tool. Design tool sets to avoid granting all three simultaneously.

Evaluation framework for new annotation proposals:

  1. What client behavior changes? (No concrete action = don't add it)
  2. Does it require trust to be useful? (If yes, doesn't help against untrusted servers)
  3. Could _meta handle it? (Namespaced metadata better for single-deployment needs)
  4. Does it help reason about tool combinations?
  5. Is it a hint or contract? (Contracts belong in auth/transport/runtime layer)

Error Handling

Two distinct mechanisms with different LLM visibility:

TypeLLM Sees It?Use For
Tool error (isError: true in CallToolResult)Yes - enables self-correctionInput validation, API failures, business logic errors
Protocol error (JSON-RPC error response)Maybe - clients MAY exposeUnknown tool, malformed request, server crash

Per SEP-1303 (merged into spec 2025-11-25): input validation errors MUST be tool execution errors, not protocol errors. The LLM needs to see "date must be in the future" to self-correct.

// DO: Tool execution error - LLM can self-correct
return {
  isError: true,
  content: [{ type: "text", text: "Date must be in the future. Current date: 2026-03-25" }],
};

// DON'T: Protocol error for validation - LLM can't see this
throw new McpError(ErrorCode.InvalidParams, "Invalid date");

Known SDK behavior: When the SDK converts an McpError thrown from a tool handler into a CallToolResult, the error.data field is dropped. If you embed structured data in McpError's data field, it may not reach the client. The x402/MPP MCP ecosystem standardized on isError: true tool results with structuredContent for this reason. (One exception: code -32042 "Payment Required" survives McpServer end-to-end with error.data intact - see references/error-handling.md.)

For full error taxonomy, code examples, and payment error patterns: see references/error-handling.md

Resources and Instructions

Server Instructions

Set in the initialization response - acts as a system-level hint to the LLM about how to use your server:

const server = new McpServer({
  name: "docs-api",
  version: "1.0.0",
  instructions: "Knowledge base API. Use search_docs for full-text search, get_doc for retrieval by ID. All tools are read-only.",
});

Resource Registration

Expose documentation or structured data via docs:// URI scheme:

server.resource("search-operators", "docs://search-operators", {
  title: "Search Operators Guide",
  description: "Supported search operators and syntax",
  mimeType: "text/markdown",
}, async () => ({
  contents: [{ uri: "docs://search-operators", text: operatorsMarkdown }],
}));

Performance

Module-Level Caching

The McpServer must be per-request, but everything else can be shared:

// Module-level (created once)
const SCHEMAS = {
  search: z.object({ query: z.string().describe("Search query") }),
  fetch: z.object({ id: z.string().describe("Resource ID") }),
};
const READ_ONLY_ANNOTATIONS = {
  readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true,
} as const;

// Per-request (created each time)
function createMcpServer(ctx: Context) {
  const server = new McpServer({ name: "my-server", version: "1.0.0" });
  server.tool("search", "Search", SCHEMAS.search, READ_ONLY_ANNOTATIONS, handler);
  return server;
}

Token Bloat Mitigation

Tool definitions consume context window before any conversation starts. GitHub MCP: 20,444 tokens for 80 tools (SEP-1576).

Strategies:

  1. 5-15 tools per server - community sweet spot. Split beyond that.
  2. Outcome-oriented tools - bundle multi-step operations into single tools (e.g., track_order(email) not get_user + list_orders + get_status).
  3. Response granularity - return curated results, not raw API dumps. 800-token user object vs 20-token summary.
  4. outputSchema + structuredContent - lets clients process data programmatically without LLM parsing overhead.
  5. Dynamic tool loading - register only relevant tool subsets based on request context (e.g., ?tools=search,fetch query parameter).

No-Parameter Tools

For tools with no inputs, use explicit empty schema:

inputSchema: { type: "object" as const, additionalProperties: false }

Security

Top Threats (real-world incidents, 2025-2026)

AttackExampleMitigation
Tool poisoningHidden instructions in descriptions (WhatsApp MCP, Apr 2025)Review tool descriptions; clients should display them
Supply chainMalicious npm packages (Smithery breach, Oct 2025)Pin versions, audit dependencies
Command injectionchild_process.exec with unsanitized input (CVE-2025-53967)Never interpolate user input into shell commands
Stdio config injectionUser-controlled input reaches StdioServerParameters without sanitization (OX Security disclosure, 2026-04-15)Sanitize stdio config inputs in client code; prefer first-party servers; treat by Anthropic as "by design" - not patched in SDK
Cross-server shadowingMalicious server overrides legitimate tool namesService-prefix tool names; validate tool sources
Token theftOver-privileged PATs with broad scopesMinimal scopes; OAuth 2.1 Resource Indicators (RFC 8707)
Token passthroughServer accepts/forwards tokens not issued for itValidate audience claim; never transit client tokens to upstream APIs
SSRFMalicious OAuth metadata URLs targeting internal servicesHTTPS enforcement, block private IPs, validate redirect targets
Confused deputyProxy server consent cookies exploited via DCRPer-client consent before forwarding to third-party auth
Session hijackingStolen/guessed session IDs for impersonationCryptographically random IDs, bind to user identity, never use for auth
Cross-client response leakShared McpServer/transport reused across clients (CVE-2026-25536, affects v1.10.0-1.25.3)Require SDK ≥ v1.26.0; per-request server+transport
UriTemplate ReDoSMalicious URI patterns (CVE-2026-0621)Upgrade to v1.25.2+ / v2.0.0-alpha.1+

Server-Side Requirements (spec normative)

  • Validate all inputs at tool boundaries
  • Implement access controls per user/session
  • Rate limit tool invocations
  • Sanitize outputs before returning to client
  • Validate Origin header - respond 403 for invalid origins (2025-11-25 requirement)
  • Require MCP-Protocol-Version header on all requests after initialization (spec 2025-06-18+)
  • Bind local servers to localhost (127.0.0.1) only

Auth (OAuth 2.1)

MCP normatively requires OAuth 2.1 (draft-ietf-oauth-v2-1-13). The spec states: "Authorization servers MUST implement OAuth 2.1." PKCE is mandatory, implicit flow is removed. Always build against OAuth 2.1 - not 2.0.

MCP servers are OAuth 2.1 Resource Servers. Clients MUST include Resource Indicators (RFC 8707) binding tokens to specific servers. Key requirements:

  • Validate audience - reject tokens not issued for your server (token passthrough is explicitly forbidden)
  • PKCE mandatory - use S256 code challenge method
  • Short-lived tokens - reduce blast radius of leaked credentials
  • Scope minimization - start with minimal scopes, elevate incrementally via WWW-Authenticate challenges
  • Don't implement token validation yourself - use tested libraries (Keycloak, Auth0, etc.)
  • Don't log credentials - never log Authorization headers, tokens, or secrets
For full security attack/mitigation patterns and auth implementation details: see references/security-auth.md

Known SDK Bugs

IssueSeverityStatusWorkaround
#1643 - z.union()/z.discriminatedUnion() silently droppedHighFixed on main (closed 2026-03-30); pending v1 releaseUse flat z.object() + z.enum() until v1 ships the fix
#1699 - Transport closure stack overflow (15-25+ concurrent)HighFixed in PR #1788 (closed 2026-04-02)Upgrade to ≥ v1.29.0 / v2 alpha
#1619 - HTTP/2 + SSE Content-Length errorMediumClosed (reclassified to upstream @hono/node-server#266)Use enableJsonResponse: true or avoid HTTP/2 upstream
#893 - Dynamic registration after connect blockedMediumOpenRegister all tools/resources before connect()
#1596 - Plain JSON Schema silently droppedFixedv1.28.0Upgrade to v1.28+
Client AJV strict rejects unstripped structuredContent extrasHighBehavior, not bugServer .parse() upstream data before returning, or use .passthrough()
GHSA-345p-7cg4-v4c7 / CVE-2026-25536 - Shared instances leak cross-client dataCriticalFixed v1.26.0Require ≥ v1.26.0 (or v2.0.0-alpha.1+); per-request server+transport
CVE-2026-0621 - UriTemplate ReDoSMediumFixed v1.25.2 / v2.0.0-alpha.1Upgrade

V2 Migration

For comprehensive migration guide with all breaking changes and before/after code: see references/v2-migration.md

Key breaking changes:

  1. Package split: @modelcontextprotocol/sdk -> @modelcontextprotocol/server + /client + /core
  2. ESM only, Node.js 20+
  3. Zod v4 required (or any Standard Schema library)
  4. McpError -> ProtocolError (from @modelcontextprotocol/core)
  5. extra parameter -> structured ctx with ctx.mcpReq
  6. server.tool() -> registerTool() (config object, not positional args)
  7. SSE server transport removed (clients can still connect to legacy SSE servers)
  8. @modelcontextprotocol/hono and @modelcontextprotocol/express middleware packages
  9. DNS rebinding protection enabled by default for localhost servers

v1.x gets 6 more months of support after v2 stable ships. No rush, but write new code with v2 patterns in mind.

Extensions

MCP extensions are optional, strictly additive capabilities on top of the core protocol. Both sides negotiate support during initialization via extensions in capabilities.

Identifiers: {vendor-prefix}/{extension-name}. Official: io.modelcontextprotocol/*. Third-party: reversed domain (e.g., com.example/my-ext).

Official Extensions

ExtensionIdentifierPurpose
MCP Appsio.modelcontextprotocol/uiInteractive HTML UIs in chat (charts, forms, dashboards)
OAuth Client Credentialsio.modelcontextprotocol/oauth-client-credentialsMachine-to-machine auth (CI/CD, daemons, server-to-server)
Enterprise-Managed Authio.modelcontextprotocol/enterprise-managed-authorizationCentralized access control via enterprise IdP

Client support: Claude (web + Desktop), ChatGPT, VS Code Copilot, Goose, Postman, MCPJam all support MCP Apps. Auth extensions not yet widely adopted.

For MCP Apps architecture, ext-apps SDK, and build patterns: see references/mcp-apps.md For extensions system, auth extensions, and MCP Registry: see references/extensions-registry.md

Server Capabilities Beyond Tools

CapabilityPurposev2 API
ElicitationRequest structured user input mid-toolctx.mcpReq.elicitInput()
SamplingRequest LLM completion from clientctx.mcpReq.requestSampling()
Tasks (SEP-1686)Long-running ops with lifecycle managementPending
ProgressIncremental progress on requestsctx.mcpReq.sendProgress()

平台分布

Codex

36.63%
按下载量换算67

Claude

32.36%
按下载量换算59

Cursor

16.32%
按下载量换算30

Gemini CLI

9.32%
按下载量换算17

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

可疑

权限和风险

调用外部服务

该 Skill 可能调用第三方服务、云服务或外部模型 API,使用前需要确认账号、额度、数据发送范围和服务条款。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。来源安全扫描存在提醒或未通过项,安装前请自行复核。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills