Skill Library

expert Code Development

MCP Server Builder

Build high-quality Model Context Protocol (MCP) servers to integrate external APIs and services with AI assistants. Follow best practices for tool design, security, and cross-platform compatibility.

When to Use This Skill

  • Building custom tools for Claude or other MCP-compatible assistants
  • Integrating third-party APIs (Slack, GitHub, databases, etc.)
  • Creating domain-specific tooling for AI workflows
  • Extending Claude Code with custom capabilities
  • Building secure, sandboxed execution environments

How to use this skill

1. Copy the AI Core Logic from the Instructions tab below.

2. Paste it into your AI's System Instructions or as your first message.

3. Provide your raw data or requirements as requested by the AI.

#mcp#api-integration#claude#tool-building#server#protocol

System Directives

## MCP Development Framework ### Phase 1: Deep Research and Planning ``` Before building an MCP server, clarify: **Target Integration:** - What service/API are you connecting? - What operations should the AI be able to perform? - What data formats are involved? **Tool Design:** 1. List all tools the server will expose 2. Define input schemas (JSON Schema format) 3. Define expected outputs 4. Identify error conditions **Security Considerations:** - What credentials are needed? - How will secrets be managed? - What permissions/scopes are required? - Rate limiting requirements? ``` ### Phase 2: Server Structure #### Basic MCP Server Template ```python import asyncio from mcp.server import Server from mcp.server.stdio import stdio_server from mcp.types import Tool, TextContent app = Server("my-mcp-server") @app.list_tools() async def list_tools() -> list[Tool]: return [ Tool( name="my_tool", description="Clear description of what this tool does", inputSchema={ "type": "object", "properties": { "param1": { "type": "string", "description": "What this parameter controls" }, "param2": { "type": "integer", "description": "Numeric parameter with constraints", "minimum": 1, "maximum": 100 } }, "required": ["param1"] } ) ] @app.call_tool() async def call_tool(name: str, arguments: dict) -> list[TextContent]: if name == "my_tool": result = await process_my_tool(arguments) return [TextContent(type="text", text=result)] raise ValueError(f"Unknown tool: {name}") async def main(): async with stdio_server() as (read_stream, write_stream): await app.run(read_stream, write_stream) if __name__ == "__main__": asyncio.run(main()) ``` ### Phase 3: Tool Design Best Practices ``` Tool Design Principles: 1. **Clear Naming** - Use verb_noun format: get_user, create_issue, search_documents - Be specific: search_github_issues > search 2. **Descriptive Schemas** - Every parameter needs a description - Use constraints (min, max, enum, pattern) - Mark required vs optional clearly 3. **Graceful Error Handling** - Return structured error messages - Include actionable guidance - Don't expose internal implementation details 4. **Idempotency** - Design operations to be safely retryable - Use idempotency keys where appropriate - Document side effects clearly ``` #### Example: GitHub Integration ```python @app.list_tools() async def list_tools() -> list[Tool]: return [ Tool( name="search_github_issues", description="Search for issues in a GitHub repository by query string", inputSchema={ "type": "object", "properties": { "owner": { "type": "string", "description": "Repository owner (user or organization)" }, "repo": { "type": "string", "description": "Repository name" }, "query": { "type": "string", "description": "Search query (supports GitHub search syntax)" }, "state": { "type": "string", "enum": ["open", "closed", "all"], "default": "open", "description": "Filter by issue state" }, "limit": { "type": "integer", "default": 10, "minimum": 1, "maximum": 100, "description": "Maximum results to return" } }, "required": ["owner", "repo", "query"] } ), Tool( name="create_github_issue", description="Create a new issue in a GitHub repository", inputSchema={ "type": "object", "properties": { "owner": {"type": "string"}, "repo": {"type": "string"}, "title": { "type": "string", "description": "Issue title", "minLength": 1, "maxLength": 256 }, "body": { "type": "string", "description": "Issue description (Markdown supported)" }, "labels": { "type": "array", "items": {"type": "string"}, "description": "Labels to apply" } }, "required": ["owner", "repo", "title"] } ) ] ``` ### Phase 4: Security Implementation ``` Security Checklist: 1. **Credential Management** - Never hardcode secrets - Use environment variables - Support secure credential storage 2. **Input Validation** - Validate all inputs against schema - Sanitize before use - Reject malformed requests 3. **Rate Limiting** - Implement request throttling - Respect API rate limits - Provide clear feedback on limits 4. **Logging** - Log tool invocations (without secrets) - Track errors for debugging - Audit security-sensitive operations ``` ```python import os from functools import wraps def require_auth(func): """Decorator to ensure authentication is configured""" @wraps(func) async def wrapper(*args, **kwargs): token = os.environ.get("GITHUB_TOKEN") if not token: raise RuntimeError( "GITHUB_TOKEN environment variable not set. " "Please configure authentication before using this tool." ) return await func(*args, **kwargs) return wrapper @require_auth async def call_github_api(endpoint: str, method: str = "GET", **kwargs): """Secure API call with authentication""" headers = { "Authorization": f"Bearer {os.environ['GITHUB_TOKEN']}", "Accept": "application/vnd.github+json" } ``` ### Phase 5: Testing and Evaluation ``` Testing Strategy: 1. **Unit Tests** - Test each tool in isolation - Mock external API calls - Verify error handling 2. **Integration Tests** - Test actual API connectivity - Verify authentication flows - Test rate limiting behavior 3. **MCP Protocol Tests** - Verify tool listing - Test schema validation - Ensure proper response format ``` ```python import pytest from unittest.mock import AsyncMock, patch @pytest.mark.asyncio async def test_search_github_issues(): """Test GitHub issue search returns expected format""" mock_response = { "items": [ {"number": 1, "title": "Bug report", "state": "open"}, {"number": 2, "title": "Feature request", "state": "open"} ] } with patch("aiohttp.ClientSession.get") as mock_get: mock_get.return_value.__aenter__.return_value.json = AsyncMock( return_value=mock_response ) result = await search_github_issues( owner="anthropics", repo="claude-code", query="bug" ) assert len(result) == 2 assert result[0]["number"] == 1 ``` ## Project Structure ``` my-mcp-server/ ├── pyproject.toml # Dependencies and metadata ├── README.md # Documentation ├── src/ │ └── my_mcp_server/ │ ├── __init__.py │ ├── server.py # Main MCP server │ ├── tools/ # Tool implementations │ │ ├── __init__.py │ │ ├── github.py │ │ └── slack.py │ └── utils/ │ ├── auth.py │ └── rate_limit.py ├── tests/ │ ├── test_tools.py │ └── test_integration.py └── claude_desktop_config.json # Example config ``` ## Configuration Example ```json { "mcpServers": { "my-mcp-server": { "command": "python", "args": ["-m", "my_mcp_server"], "env": { "GITHUB_TOKEN": "${GITHUB_TOKEN}", "LOG_LEVEL": "INFO" } } } } ``` ## Best Practices 1. **Keep Tools Focused**: One tool, one purpose 2. **Fail Gracefully**: Helpful error messages over silent failures 3. **Document Everything**: Clear descriptions for AI understanding 4. **Version Your API**: Plan for backward compatibility 5. **Monitor Usage**: Log and track tool invocations 6. **Test Thoroughly**: Both unit and integration tests ## Related Resources - [MCP Specification](https://modelcontextprotocol.io/) - [MCP Python SDK](https://github.com/anthropics/mcp-python-sdk) - [MCP TypeScript SDK](https://github.com/anthropics/mcp-typescript-sdk) - [Example MCP Servers](https://github.com/anthropics/mcp-servers)

Procedural Integration

This skill is formatted as a set of persistent system instructions. When integrated, it provides the AI model with specialized workflows and knowledge constraints for Code Development.

Skill Actions


Model Compatibility
🤖 Claude Opus🤖 Claude 3.5 Sonnet
Code Execution: Required
MCP Tools: Required
Footprint ~2,510 tokens