Setting the file. One moment. MCP Best Practices · MCP Builder · anthropics/skills · Skills Docs
- Python:
{service}_mcp (e.g., slack_mcp)
- Node/TypeScript:
{service}-mcp-server (e.g., slack-mcp-server)
- Use snake_case with service prefix
- Format:
{service}_{action}_{resource}
- Example:
slack_send_message, github_create_issue
- Support both JSON and Markdown formats
- JSON for programmatic processing
- Markdown for human readability
- Always respect
limit parameter
- Return
has_more, next_offset, total_count
- Default to 20-50 items
- Streamable HTTP: For remote servers, multi-client scenarios
- stdio: For local integrations, command-line tools
- Avoid SSE (deprecated in favor of streamable HTTP)
Follow these standardized naming patterns:
Python: Use format {service}_mcp (lowercase with underscores)
- Examples:
slack_mcp, github_mcp, jira_mcp
Node/TypeScript: Use format {service}-mcp-server (lowercase with hyphens)
- Examples:
slack-mcp-server, github-mcp-server, jira-mcp-server
The name should be general, descriptive of the service being integrated, easy to infer from the task description, and without version numbers.
- Use snake_case:
search_users, create_project, get_channel_info
- Include service prefix: Anticipate that your MCP server may be used alongside other MCP servers
- Use
slack_send_message instead of just send_message
- Use
github_create_issue instead of just create_issue
- Be action-oriented: Start with verbs (get, list, search, create, etc.)
- Be specific: Avoid generic names that could conflict with other servers
- Tool descriptions must narrowly and unambiguously describe functionality
- Descriptions must precisely match actual functionality
- Provide tool annotations (readOnlyHint, destructiveHint, idempotentHint, openWorldHint)
- Keep tool operations focused and atomic
All tools that return data should support multiple formats:
- Machine-readable structured data
- Include all available fields and metadata
- Consistent field names and types
- Use for programmatic processing
- Human-readable formatted text
- Use headers, lists, and formatting for clarity
- Convert timestamps to human-readable format
- Show display names with IDs in parentheses
- Omit verbose metadata
For tools that list resources:
- Always respect the
limit parameter
- Implement pagination: Use
offset or cursor-based pagination
- Return pagination metadata: Include
has_more, next_offset/next_cursor, total_count
- Never load all results into memory: Especially important for large datasets
- Default to reasonable limits: 20-50 items is typical
Example pagination response:
Best for: Remote servers, web services, multi-client scenarios
- Bidirectional communication over HTTP
- Supports multiple simultaneous clients
- Can be deployed as a web service
- Enables server-to-client notifications
- Serving multiple clients simultaneously
- Deploying as a cloud service
- Integration with web applications
Best for: Local integrations, command-line tools
- Standard input/output stream communication
- Simple setup, no network configuration needed
- Runs as a subprocess of the client
- Building tools for local development environments
- Integrating with desktop applications
- Single-user, single-session scenarios
Note: stdio servers should NOT log to stdout (use stderr for logging)
- Use secure OAuth 2.1 with certificates from recognized authorities
- Validate access tokens before processing requests
- Only accept tokens specifically intended for your server
- Store API keys in environment variables, never in code
- Validate keys on server startup
- Provide clear error messages when authentication fails
- Sanitize file paths to prevent directory traversal
- Validate URLs and external identifiers
- Check parameter sizes and ranges
- Prevent command injection in system calls
- Use schema validation (Pydantic/Zod) for all inputs
- Don’t expose internal errors to clients
- Log security-relevant errors server-side
- Provide helpful but not revealing error messages
- Clean up resources after errors
For streamable HTTP servers running locally:
- Enable DNS rebinding protection
- Validate the
Origin header on all incoming connections
- Bind to
127.0.0.1 rather than 0.0.0.0
Provide annotations to help clients understand tool behavior:
Important: Annotations are hints, not security guarantees. Clients should not make security-critical decisions based solely on annotations.
- Use standard JSON-RPC error codes
- Report tool errors within result objects (not protocol-level errors)
- Provide helpful, specific error messages with suggested next steps
- Don’t expose internal implementation details
- Clean up resources properly on errors
Comprehensive testing should cover:
- Functional testing: Verify correct execution with valid/invalid inputs
- Integration testing: Test interaction with external systems
- Security testing: Validate auth, input sanitization, rate limiting
- Performance testing: Check behavior under load, timeouts
- Error handling: Ensure proper error reporting and cleanup
- Provide clear documentation of all tools and capabilities
- Include working examples (at least 3 per major feature)
- Document security considerations
- Specify required permissions and access levels
- Document rate limits and performance characteristics