Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Guides creation of high-quality MCP servers in TypeScript or Python (FastMCP) to connect LLMs with external services.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
reference/mcp_best_practices.md
1# MCP Server Best Practices23## Quick Reference45### Server Naming6- **Python**: `{service}_mcp` (e.g., `slack_mcp`)7- **Node/TypeScript**: `{service}-mcp-server` (e.g., `slack-mcp-server`)89### Tool Naming10- Use snake_case with service prefix11- Format: `{service}_{action}_{resource}`12- Example: `slack_send_message`, `github_create_issue`1314### Response Formats15- Support both JSON and Markdown formats16- JSON for programmatic processing17- Markdown for human readability1819### Pagination20- Always respect `limit` parameter21- Return `has_more`, `next_offset`, `total_count`22- Default to 20-50 items2324### Transport25- **Streamable HTTP**: For remote servers, multi-client scenarios26- **stdio**: For local integrations, command-line tools27- Avoid SSE (deprecated in favor of streamable HTTP)2829---3031## Server Naming Conventions3233Follow these standardized naming patterns:3435**Python**: Use format `{service}_mcp` (lowercase with underscores)36- Examples: `slack_mcp`, `github_mcp`, `jira_mcp`3738**Node/TypeScript**: Use format `{service}-mcp-server` (lowercase with hyphens)39- Examples: `slack-mcp-server`, `github-mcp-server`, `jira-mcp-server`4041The name should be general, descriptive of the service being integrated, easy to infer from the task description, and without version numbers.4243---4445## Tool Naming and Design4647### Tool Naming48491. **Use snake_case**: `search_users`, `create_project`, `get_channel_info`502. **Include service prefix**: Anticipate that your MCP server may be used alongside other MCP servers51- Use `slack_send_message` instead of just `send_message`52- Use `github_create_issue` instead of just `create_issue`533. **Be action-oriented**: Start with verbs (get, list, search, create, etc.)544. **Be specific**: Avoid generic names that could conflict with other servers5556### Tool Design5758- Tool descriptions must narrowly and unambiguously describe functionality59- Descriptions must precisely match actual functionality60- Provide tool annotations (readOnlyHint, destructiveHint, idempotentHint, openWorldHint)61- Keep tool operations focused and atomic6263---6465## Response Formats6667All tools that return data should support multiple formats:6869### JSON Format (`response_format="json"`)70- Machine-readable structured data71- Include all available fields and metadata72- Consistent field names and types73- Use for programmatic processing7475### Markdown Format (`response_format="markdown"`, typically default)76- Human-readable formatted text77- Use headers, lists, and formatting for clarity78- Convert timestamps to human-readable format79- Show display names with IDs in parentheses80- Omit verbose metadata8182---8384## Pagination8586For tools that list resources:8788- **Always respect the `limit` parameter**89- **Implement pagination**: Use `offset` or cursor-based pagination90- **Return pagination metadata**: Include `has_more`, `next_offset`/`next_cursor`, `total_count`91- **Never load all results into memory**: Especially important for large datasets92- **Default to reasonable limits**: 20-50 items is typical9394Example pagination response:95```json96{97"total": 150,98"count": 20,99"offset": 0,100"items": [...],101"has_more": true,102"next_offset": 20103}104```105106---107108## Transport Options109110### Streamable HTTP111112**Best for**: Remote servers, web services, multi-client scenarios113114**Characteristics**:115- Bidirectional communication over HTTP116- Supports multiple simultaneous clients117- Can be deployed as a web service118- Enables server-to-client notifications119120**Use when**:121- Serving multiple clients simultaneously122- Deploying as a cloud service123- Integration with web applications124125### stdio126127**Best for**: Local integrations, command-line tools128129**Characteristics**:130- Standard input/output stream communication131- Simple setup, no network configuration needed132- Runs as a subprocess of the client133134**Use when**:135- Building tools for local development environments136- Integrating with desktop applications137- Single-user, single-session scenarios138139**Note**: stdio servers should NOT log to stdout (use stderr for logging)140141### Transport Selection142143| Criterion | stdio | Streamable HTTP |144|-----------|-------|-----------------|145| **Deployment** | Local | Remote |146| **Clients** | Single | Multiple |147| **Complexity** | Low | Medium |148| **Real-time** | No | Yes |149150---151152## Security Best Practices153154### Authentication and Authorization155156**OAuth 2.1**:157- Use secure OAuth 2.1 with certificates from recognized authorities158- Validate access tokens before processing requests159- Only accept tokens specifically intended for your server160161**API Keys**:162- Store API keys in environment variables, never in code163- Validate keys on server startup164- Provide clear error messages when authentication fails165166### Input Validation167168- Sanitize file paths to prevent directory traversal169- Validate URLs and external identifiers170- Check parameter sizes and ranges171- Prevent command injection in system calls172- Use schema validation (Pydantic/Zod) for all inputs173174### Error Handling175176- Don't expose internal errors to clients177- Log security-relevant errors server-side178- Provide helpful but not revealing error messages179- Clean up resources after errors180181### DNS Rebinding Protection182183For streamable HTTP servers running locally:184- Enable DNS rebinding protection185- Validate the `Origin` header on all incoming connections186- Bind to `127.0.0.1` rather than `0.0.0.0`187188---189190## Tool Annotations191192Provide annotations to help clients understand tool behavior:193194| Annotation | Type | Default | Description |195|-----------|------|---------|-------------|196| `readOnlyHint` | boolean | false | Tool does not modify its environment |197| `destructiveHint` | boolean | true | Tool may perform destructive updates |198| `idempotentHint` | boolean | false | Repeated calls with same args have no additional effect |199| `openWorldHint` | boolean | true | Tool interacts with external entities |200201**Important**: Annotations are hints, not security guarantees. Clients should not make security-critical decisions based solely on annotations.202203---204205## Error Handling206207- Use standard JSON-RPC error codes208- Report tool errors within result objects (not protocol-level errors)209- Provide helpful, specific error messages with suggested next steps210- Don't expose internal implementation details211- Clean up resources properly on errors212213Example error handling:214```typescript215try {216const result = performOperation();217return { content: [{ type: "text", text: result }] };218} catch (error) {219return {220isError: true,221content: [{222type: "text",223text: `Error: ${error.message}. Try using filter='active_only' to reduce results.`224}]225};226}227```228229---230231## Testing Requirements232233Comprehensive testing should cover:234235- **Functional testing**: Verify correct execution with valid/invalid inputs236- **Integration testing**: Test interaction with external systems237- **Security testing**: Validate auth, input sanitization, rate limiting238- **Performance testing**: Check behavior under load, timeouts239- **Error handling**: Ensure proper error reporting and cleanup240241---242243## Documentation Requirements244245- Provide clear documentation of all tools and capabilities246- Include working examples (at least 3 per major feature)247- Document security considerations248- Specify required permissions and access levels249- Document rate limits and performance characteristics250