$npx -y skills add jezweb/claude-skills --skill mcp-builderBuild MCP servers in Python with FastMCP. Define tools / resources / prompts, build the server, test locally, deploy to FastMCP Cloud or Docker. Use whenever the user mentions building an MCP server, exposing tools to LLMs, FastMCP, building a Claude integration, or troubleshooti
| 1 | # MCP Builder |
| 2 | |
| 3 | Build a working MCP server from a description of the tools you need. Produces a deployable Python server using FastMCP. |
| 4 | |
| 5 | ## Workflow |
| 6 | |
| 7 | ### Step 1: Define What to Expose |
| 8 | |
| 9 | Ask what the server needs to provide: |
| 10 | |
| 11 | - **Tools** -- Functions Claude can call (API wrappers, calculations, file operations) |
| 12 | - **Resources** -- Data Claude can read (database records, config, documents) |
| 13 | - **Prompts** -- Reusable prompt templates with parameters |
| 14 | |
| 15 | A brief like "MCP server for querying our customer database" is enough. |
| 16 | |
| 17 | ### Step 2: Scaffold the Server |
| 18 | |
| 19 | ```bash |
| 20 | pip install fastmcp |
| 21 | ``` |
| 22 | |
| 23 | Create the server file. The server instance MUST be at module level: |
| 24 | |
| 25 | ```python |
| 26 | from fastmcp import FastMCP |
| 27 | |
| 28 | # MUST be at module level for FastMCP Cloud |
| 29 | mcp = FastMCP("My Server") |
| 30 | |
| 31 | @mcp.tool() |
| 32 | async def search_customers(query: str) -> str: |
| 33 | """Search customers by name or email.""" |
| 34 | # Implementation here |
| 35 | return f"Found customers matching: {query}" |
| 36 | |
| 37 | @mcp.resource("customers://{customer_id}") |
| 38 | async def get_customer(customer_id: str) -> str: |
| 39 | """Get customer details by ID.""" |
| 40 | return f"Customer {customer_id} details" |
| 41 | |
| 42 | if __name__ == "__main__": |
| 43 | mcp.run() |
| 44 | ``` |
| 45 | |
| 46 | ### Step 3: Add Companion CLI Scripts (Optional) |
| 47 | |
| 48 | For Claude Code terminal use, add scripts alongside the MCP server: |
| 49 | |
| 50 | ``` |
| 51 | my-mcp-server/ |
| 52 | ├── src/index.ts # MCP server (for Claude.ai) |
| 53 | ├── scripts/ |
| 54 | │ ├── search.ts # CLI version of search tool |
| 55 | │ └── _shared.ts # Shared auth/config |
| 56 | ├── SCRIPTS.md # Documents available scripts |
| 57 | └── package.json |
| 58 | ``` |
| 59 | |
| 60 | CLI scripts provide file I/O, batch processing, and richer output that MCP can't. |
| 61 | See `assets/SCRIPTS-TEMPLATE.md` and `assets/script-template.ts` for TypeScript templates. |
| 62 | |
| 63 | ### Step 4: Test Locally |
| 64 | |
| 65 | **Quick test -- run directly:** |
| 66 | |
| 67 | ```bash |
| 68 | python server.py |
| 69 | ``` |
| 70 | |
| 71 | **Dev mode with inspector UI (recommended):** |
| 72 | |
| 73 | ```bash |
| 74 | fastmcp dev server.py |
| 75 | # Opens inspector at http://localhost:5173 |
| 76 | # Hot reload, detailed logging, tool/resource inspection |
| 77 | ``` |
| 78 | |
| 79 | **HTTP mode for remote clients:** |
| 80 | |
| 81 | ```bash |
| 82 | python server.py --transport http --port 8000 |
| 83 | ``` |
| 84 | |
| 85 | **Automated test script using FastMCP Client:** |
| 86 | |
| 87 | ```python |
| 88 | import asyncio |
| 89 | from fastmcp import Client |
| 90 | |
| 91 | async def test_server(server_path): |
| 92 | async with Client(server_path) as client: |
| 93 | # List everything |
| 94 | tools = await client.list_tools() |
| 95 | resources = await client.list_resources() |
| 96 | prompts = await client.list_prompts() |
| 97 | |
| 98 | print(f"Tools: {[t.name for t in tools]}") |
| 99 | print(f"Resources: {[r.uri for r in resources]}") |
| 100 | print(f"Prompts: {[p.name for p in prompts]}") |
| 101 | |
| 102 | # Call first tool |
| 103 | if tools: |
| 104 | result = await client.call_tool(tools[0].name, {}) |
| 105 | print(f"Tool result: {result}") |
| 106 | |
| 107 | # Read first resource |
| 108 | if resources: |
| 109 | data = await client.read_resource(resources[0].uri) |
| 110 | print(f"Resource data: {data}") |
| 111 | |
| 112 | asyncio.run(test_server("server.py")) |
| 113 | ``` |
| 114 | |
| 115 | ### Step 5: Pre-Deploy Checklist |
| 116 | |
| 117 | Run these checks before deploying. All required checks must pass. |
| 118 | |
| 119 | **Required (will cause deploy failure):** |
| 120 | |
| 121 | 1. Server file exists |
| 122 | 2. Python syntax valid: `python3 -m py_compile server.py` |
| 123 | 3. Module-level server object (not inside a function): |
| 124 | ```bash |
| 125 | grep -q "^mcp = FastMCP\|^server = FastMCP\|^app = FastMCP" server.py |
| 126 | ``` |
| 127 | 4. `requirements.txt` exists with PyPI packages only (no `git+`, `-e`, `.whl`, `.tar.gz`) |
| 128 | 5. No hardcoded secrets (check for `api_key = "..."` patterns excluding `os.getenv`/`os.environ`) |
| 129 | |
| 130 | **Advisory (warnings):** |
| 131 | |
| 132 | 6. `fastmcp` listed in requirements.txt |
| 133 | 7. `.gitignore` includes `.env` |
| 134 | 8. No circular imports |
| 135 | 9. Git repository initialised with remote |
| 136 | 10. Server can load: `timeout 5 fastmcp inspect server.py` |
| 137 | |
| 138 | ### Step 6: Deploy |
| 139 | |
| 140 | **FastMCP Cloud (simplest):** |
| 141 | |
| 142 | ```bash |
| 143 | git add . && git commit -m "Ready for deployment" |
| 144 | git push -u origin main |
| 145 | # Visit https://fastmcp.cloud, connect repo, add env vars, deploy |
| 146 | # URL: https://your-project.fastmcp.app/mcp |
| 147 | ``` |
| 148 | |
| 149 | Cloud requirements: |
| 150 | - Module-level server object named `mcp`, `server`, or `app` |
| 151 | - PyPI dependencies only in `requirements.txt` |
| 152 | - Public GitHub repository |
| 153 | - Environment variables for secrets (no hardcoded values) |
| 154 | - Auto-deploys on push to main, PR preview deployments |
| 155 | |
| 156 | **Docker (self-hosted):** |
| 157 | |
| 158 | ```dockerfile |
| 159 | FROM python:3.12-slim |
| 160 | WORKDIR /app |
| 161 | COPY requirements.txt . |
| 162 | RUN pip install -r requirements.txt |
| 163 | COPY . . |
| 164 | EXPOSE 8000 |
| 165 | CMD ["python", "server.py", "--transport", "http", "--port", "8000"] |
| 166 | ``` |
| 167 | |
| 168 | **Cloudflare Workers (edge):** |
| 169 | See the cloudflare-worker-bui |