MCP Best Practices
Design principles, security checklist, performance optimization, testing strategies, and frequently asked questions.
Server Design Principles
-
Single Responsibility
Each MCP server should focus on one domain. A filesystem server handles files. A database server handles queries. Do not combine unrelated functionality.
-
Minimal Permissions
Request only the access your server needs. A read-only analytics server should not have write permissions to the database.
-
Clear Tool Descriptions
Write tool names and descriptions that the AI model can understand. The model uses these to decide when and how to call your tools.
-
Graceful Error Handling
Return helpful error messages with
isError: truerather than crashing. The AI model can use error messages to adjust its approach. -
Idempotent Operations
Where possible, design tools so calling them multiple times with the same arguments produces the same result.
Tool Naming Conventions
| Pattern | Example | Notes |
|---|---|---|
verb_noun |
read_file, create_issue |
Preferred: clear action + target |
get_noun |
get_weather, get_user |
For read operations |
list_nouns |
list_files, list_channels |
For returning collections |
search_nouns |
search_repos, search_docs |
For query-based lookups |
Security Checklist
- Input validation on all tool arguments
- Path traversal protection for file operations
- SQL injection protection for database tools
- Rate limiting on HTTP/SSE endpoints
- Authentication for remote servers
- TLS/HTTPS for all network transport
- Minimal file system access (specific directories only)
- Read-only database credentials where possible
- No secrets in logs or error messages
- Regular dependency updates
Error Handling Patterns
// Good: Return descriptive errors the AI can act on server.tool("query_db", "Execute SQL query", schema, async (args) => { try { const result = await db.query(args.sql); return { content: [{ type: "text", text: JSON.stringify(result) }] }; } catch (err) { if (err.code === "42P01") { return { content: [{ type: "text", text: `Table not found. Available tables: ${await listTables()}` }], isError: true }; } return { content: [{ type: "text", text: `Query error: ${err.message}` }], isError: true }; } });
Performance Optimization
- Connection pooling: Reuse database connections rather than opening new ones for each tool call.
- Caching: Cache resource responses that change infrequently. Invalidate on resource update notifications.
- Pagination: For tools that return large result sets, support
limitandoffsetparameters. - Timeouts: Set reasonable timeouts for external API calls and database queries. Return an error rather than hanging.
- Lazy loading: Only initialize heavy dependencies (database connections, API clients) when first needed.
Testing Strategies
-
Unit Tests
Test tool handler functions in isolation. Mock external dependencies (databases, APIs). Verify input validation and error handling.
-
Integration Tests
Test the full MCP protocol flow. Use the MCP SDK's test client to send requests and verify responses.
-
MCP Inspector
Use
npx @modelcontextprotocol/inspectorfor interactive testing during development. Verify tools, resources, and prompts work correctly. -
End-to-End Tests
Connect your server to Claude Desktop or another client and verify it works in a real conversation.
Documentation Standards
Good documentation helps users and AI models understand your server:
- README: Include installation, configuration, and quick start instructions.
- Tool descriptions: Write as if explaining to someone who has never seen your API. Include examples of valid inputs.
- Parameter descriptions: Explain what each parameter does, its format, valid values, and defaults.
- Error documentation: List common errors and how to resolve them.
Frequently Asked Questions
Can an MCP server access the internet?
Yes, MCP servers are regular processes that can make HTTP requests, connect to APIs, and access network resources. However, for security, limit outbound connections to only the services your server needs.
Can I use MCP with models other than Claude?
MCP is an open standard. Any AI application can implement the MCP client protocol. While Anthropic created it for Claude, other models and applications are adopting MCP as well.
How many tools can a server expose?
There is no hard protocol limit, but keep it reasonable. AI models work best when they have a focused set of well-described tools (5-20) rather than hundreds. If you need many tools, consider splitting into multiple focused servers.
Can MCP servers communicate with each other?
Not directly through the protocol. Each MCP server operates independently. However, you can build an MCP server that internally calls other services (including other MCP servers) through their APIs.
Is MCP suitable for production use?
Yes, but follow the security and deployment guidelines in this course. Use authentication for remote servers, validate all inputs, implement proper logging, and monitor server health.
How do I handle long-running operations?
MCP supports progress notifications. For operations that take more than a few seconds, send progress updates to the client so the user knows work is being done. For very long operations, consider returning immediately with a job ID and providing a separate tool to check status.
What happens if an MCP server crashes?
For stdio servers, the host detects the process exit and can attempt to restart it. For HTTP/SSE servers, the client detects the broken connection and can reconnect. Design your server to recover gracefully from crashes.
Community Contribution Guidelines
If you build an MCP server for the community:
- Follow the naming convention:
mcp-server-{domain}(e.g.,mcp-server-weather). - Publish to npm (
@your-org/mcp-server-{domain}) or PyPI (mcp-server-{domain}). - Include a clear README with installation, configuration, and usage examples.
- Add the
mcpandmodel-context-protocolkeywords/tags for discoverability. - Test with the MCP Inspector and at least one real client (Claude Desktop, Cline, etc.).
- Include a LICENSE file (MIT is common in the ecosystem).