Skip to main content
skill CX Codex

mcp-builder · jezweb — Claude Code skill: FastMCP servers in Python

A skill that takes a short brief and turns it into a deployable MCP server on Python with FastMCP, complete with local tests and a pre-deploy checklist.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add jezweb/claude-skills --skill mcp-builder -a claude-code
Open on GitHub

What mcp-builder does

You describe what the server should expose and the skill scaffolds it. First it pins down the surface: tools the model can call, resources it can read, and prompt templates with parameters. Then it writes the FastMCP server file, sets up local runs, and walks through deployment.

There are six steps. Defining the surface, installing fastmcp, generating the server, optional companion CLI scripts for terminal work in Claude, local testing, and the pre-deploy checks. Testing has three routes: run python server.py, open the inspector with fastmcp dev server.py for hot reload and tool inspection, or write an automated test using FastMCP's Client that lists tools, resources and prompts and calls the first tool.

Before deploying, the skill runs required checks: valid syntax via python3 -m py_compile server.py, a module-level server object, requirements.txt with PyPI packages only, and no hardcoded secrets. If FastMCP Cloud reports that it cannot find the server, the cause is almost always the same — the instance was created inside a function. For the factory pattern the skill advises exporting mcp = create_server() at module level. Cloud also wants a public GitHub repository and environment variables instead of keys in code.

What it helps with

  • scaffold a Python MCP server from a description of needed tools
  • expose resources and parameterised prompt templates
  • test the server locally with the inspector or a Client script
  • run the pre-deploy checklist without breaking the deploy
  • fix the error where the server is not at module level

Example prompts for the agent

  • build an MCP server for querying our customer database
  • add a search tool by email and a customer resource to the server
  • check the server before deploying to FastMCP Cloud

How to install mcp-builder

1Skills CLI (Vercel)

npx skills add jezweb/claude-skills --skill mcp-builder -a claude-code

2Manually: put the files in place

~/.claude/skills/mcp-builder/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/mcp-builder/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about mcp-builder

How do I install mcp-builder in Claude?

Run npx skills add jezweb/claude-skills --skill mcp-builder -a claude-code. The skill lands in ~/.claude/skills/mcp-builder/SKILL.md.

What does mcp-builder do?

It walks through building a Python MCP server with FastMCP: defining tools, resources and prompts, scaffolding the server, testing locally, running checks and deploying to FastMCP Cloud or Docker.

Why can't FastMCP Cloud find my server?

The FastMCP instance has to sit at module level. If it is created inside a function, Cloud throws the missing-server error — export mcp = create_server() outside instead.

Source text

SKILL.md · MIT
---
name: mcp-builder
description: "Build 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 troubleshooting FastMCP module-level server, storage, lifespan, middleware, OAuth, or deployment errors."
compatibility: claude-code-only
---

# MCP Builder

Build a working MCP server from a description of the tools you need. Produces a deployable Python server using FastMCP.

## Workflow

### Step 1: Define What to Expose

Ask what the server needs to provide:

- **Tools** -- Functions Claude can call (API wrappers, calculations, file operations)
- **Resources** -- Data Claude can read (database records, config, documents)
- **Prompts** -- Reusable prompt templates with parameters

A brief like "MCP server for querying our customer database" is enough.

### Step 2: Scaffold the Server

```bash
pip install fastmcp
```

Create the server file. The server instance MUST be at module level:

```python
from fastmcp import FastMCP

# MUST be at module level for FastMCP Cloud
mcp = FastMCP("My Server")

@mcp.tool()
async def search_customers(query: str) -> str:
    """Search customers by name or email."""
    # Implementation here
    return f"Found customers matching: {query}"

@mcp.resource("customers://{customer_id}")
async def get_customer(customer_id: str) -> str:
    """Get customer details by ID."""
    return f"Customer {customer_id} details"

if __name__ == "__main__":
    mcp.run()
```

### Step 3: Add Companion CLI Scripts (Optional)

For Claude Code terminal use, add scripts alongside the MCP server:

```
my-mcp-server/
├── src/index.ts          # MCP server (for Claude.ai)
├── scripts/
│   ├── search.ts         # CLI version of search tool
│   └── _shared.ts        # Shared auth/config
├── SCRIPTS.md            # Documents available scripts
└── package.json
```

CLI scripts provide file I/O, batch processing, and richer output that MCP can't.
See `assets/SCRIPTS-TEMPLATE.md` and `assets/script-template.ts` for TypeScript templates.

### Step 4: Test Locally

**Quick test -- run directly:**

```bash
python server.py
```

**Dev mode with inspector UI (recommended):**

```bash
fastmcp dev server.py
# Opens inspector at http://localhost:5173
# Hot reload, detailed logging, tool/resource inspection
```

**HTTP mode for remote clients:**

```bash
python server.py --transport http --port 8000
```

**Automated test script using FastMCP Client:**

```python
import asyncio
from fastmcp import Client

async def test_server(server_path):
    async with Client(server_path) as client:
        # List everything
        tools = await client.list_tools()
        resources = await client.list_resources()
        prompts = await client.list_prompts()

        print(f"Tools: {[t.name for t in tools]}")
        print(f"Resources: {[r.uri for r in resources]}")
        print(f"Prompts: {[p.name for p in prompts]}")

        # Call first tool
        if tools:
            result = await client.call_tool(tools[0].name, {})
            print(f"Tool result: {result}")

        # Read first resource
        if resources:
            data = await client.read_resource(resources[0].uri)
            print(f"Resource data: {data}")

asyncio.run(test_server("server.py"))
```

### Step 5: Pre-Deploy Checklist

Run these checks before deploying. All required checks must pass.

**Required (will cause deploy failure):**

1. Server file exists
2. Python syntax valid: `python3 -m py_compile server.py`
3. Module-level server object (not inside a function):
   ```bash
   grep -q "^mcp = FastMCP\|^server = FastMCP\|^app = FastMCP" server.py
   ```
4. `requirements.txt` exists with PyPI packages only (no `git+`, `-e`, `.whl`, `.tar.gz`)
5. No hardcoded secrets (check for `api_key = "..."` patterns excluding `os.getenv`/`os.environ`)

**Advisory (warnings):**

6. `fastmcp` listed in requirements.txt
7. `.gitignore` includes `.env`
8. No circular imports
9. Git repository initialised with remote
10. Server can load: `timeout 5 fastmcp inspect server.py`

### Step 6: Deploy

**FastMCP Cloud (simplest):**

```bash
git add . && git commit -m "Ready for deployment"
git push -u origin main
# Visit https://fastmcp.cloud, connect repo, add env vars, deploy
# URL: https://your-project.fastmcp.app/mcp
```

Cloud requirements:
- Module-level server object named `mcp`, `server`, or `app`
- PyPI dependencies only in `requirements.txt`
- Public GitHub repository
- Environment variables for secrets (no hardcoded values)
- Auto-deploys on push to main, PR preview deployments

**Docker (self-hosted):**

```dockerfile
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["python", "server.py", "--transport", "http", "--port", "8000"]
```

**Cloudflare Workers (edge):**
Build it in TypeScript with Cloudflare's `agents` SDK (`McpAgent`); Cloudflare's remote MCP server docs carry the current template.

---

## Critical Patterns

### Module-Level Server Instance

FastMCP Cloud requires the server instance at module level:

```python
# CORRECT
mcp = FastMCP("My Server")

@mcp.tool()
def my_tool(): ...

# WRONG -- Cloud can't find the server
def create_server():
    mcp = FastMCP("My Server")
    return mcp

# FIX for factory pattern -- export at module level
def create_server() -> FastMCP:
    mcp = FastMCP("server")
    return mcp
mcp = create_server()
```

### Type Annotations Required

FastMCP uses type annotations to generate tool schemas:

```python
@mcp.tool()
async def search(
    query: str,           # Required parameter
    limit: int = 10,      # Optional with default
    tags: list[str] = []  # Complex types supported
) -> str:
    """Docstring becomes the tool description."""
    ...
```

### Error Handling

Return errors as strings, don't raise exceptions:

```python
@mcp.tool()
async def get_data(id: str) -> str:
    try:
        result = await fetch_data(id)
        return json.dumps(result)
    except NotFoundError:
        return f"Error: No data found for ID {id}"
```

### Cloud-Ready Server Pattern

```python
import os
from fastmcp import FastMCP

mcp = FastMCP("production-server")
API_KEY = os.getenv("API_KEY")

@mcp.tool()
async def production_tool(data: str) -> dict:
    if not API_KEY:
        return {"error": "API_KEY not configured"}
    return {"status": "success", "data": data}

if __name__ == "__main__":
    mcp.run()
```

---

## Common Errors and Fixes

These are the errors you will hit. Fix them before deploying.

| Error | Cause | Fix |
|-------|-------|-----|
| `RuntimeError: No server object found at module level` | Server inside a function | Export `mcp = FastMCP(...)` at module level |
| `RuntimeError: no running event loop` | Missing async/await | Use `async def` for async operations |
| `TypeError: missing required argument 'context'` | Context not type-hinted | Add `context: Context` with type hint |
| `ValueError: Invalid resource URI` | Missing URI scheme | Use `data://`, `file://`, `info://`, `api://` |
| Resource template parameter mismatch | Name mismatch | `user://{user_id}` needs `def get_user(user_id: str)` |
| Pydantic validation error | Wrong type hints | Ensure hints match actual data types |
| Transport mismatch | Client/server protocol differ | Match both to stdio or both to http |
| Import errors with editable package | Package not installed | `pip install -e .` or add to PYTHONPATH |
| `DeprecationWarning: mcp.settings` | Old API | Use `os.getenv()` instead |
| Port already in use | Stale process | `lsof -ti:8000 \| xargs kill -9` |
| Schema generation failure | Non-JSON types | Use JSON-compatible types (no NumPy arrays) |
| JSON serialization error | datetime/bytes in response | Convert to `.isoformat()` or string |
| Circular import | Factory in `__init__.py` | Use direct imports, avoid factory pattern |
| Python 3.12+ datetime warning | `datetime.utcnow()` deprecated | Use `datetime.now(timezone.utc)` |
| Import-time execution | Async resource at module level | Use lazy init pattern |

---

## Production Patterns

### Self-Contained Server

Keep all utilities in one file to avoid circular imports:

```python
from fastmcp import FastMCP
import os

mcp = FastMCP("my-server")

# Config
class Config:
    API_KEY = os.getenv("API_KEY", "")
    BASE_URL = os.getenv("BASE_URL", "https://api.example.com")

# Helpers
def format_success(data): return {"status": "success", "data": data}
def format_error(msg): return {"status": "error", "message": msg}

@mcp.tool()
async def my_tool(query: str) -> dict:
    if not Config.API_KEY:
        return format_error("API_KEY not configured")
    return format_success({"query": query})
```

### Lazy Initialisation

Don't create async resources at module level. Initialise on first use:

```python
_db = None

async def get_db():
    global _db
    if _db is None:
        _db = await create_connection(Config.DB_URL)
    return _db
```

### Health Check Resource

```python
@mcp.resource("health://status")
async def health_check() -> dict:
    return {
        "status": "healthy",
        "version": "1.0.0",
        "checks": {
            "api": "connected",
            "database": "connected"
        }
    }
```

### Connection Pooling

```python
import httpx

_client = None

def get_client() -> httpx.AsyncClient:
    global _client
    if _client is None:
        _client = httpx.AsyncClient(
            base_url=Config.BASE_URL,
            headers={"Authorization": f"Bearer {Config.API_KEY}"},
            limits=httpx.Limits(max_connections=20, max_keepalive_connections=5),
            timeout=30.0
        )
    return _client
```

### Retry with Backoff

```python
async def retry_with_backoff(func, max_retries=3, initial_delay=1.0):
    for attempt in range(max_retries):
        try:
            return await func()
        except Exception as e:
            if attempt == max_retries - 1:
                raise
            delay = initial_delay * (2 ** attempt)
            await asyncio.sleep(delay)
```

---

## Context Features (Advanced)

### Context Injection

```python
from fastmcp import Context

@mcp.tool()
async def tool_with_context(param: str, context: Context) -> dict:
    # Context parameter MUST have type hint
    pass
```

### Progress Tracking

```python
@mcp.tool()
async def long_task(items: list[str], context: Context) -> str:
    for i, item in enumerate(items):
        await context.report_progress(i + 1, len(items), f"Processing {item}")
        await process(item)
    return "Done"
```

### Sampling (LLM from within tools)

```python
@mcp.tool()
async def summarise(text: str, context: Context) -> str:
    result = await context.request_sampling(
        messages=[{"role": "user", "content": f"Summarise: {text}"}],
        max_tokens=200
    )
    return result
```

---

## CLI Quick Reference

```bash
fastmcp dev server.py              # Dev mode with inspector UI
fastmcp run server.py              # Run (stdio)
fastmcp run server.py --transport http --port 8000  # Run (HTTP)
fastmcp inspect server.py          # Inspect without running
fastmcp install server.py          # Install to Claude Desktop
fastmcp deploy server.py --name my-server  # Deploy to Cloud
```

Environment variables: `FASTMCP_LOG_LEVEL` (DEBUG/INFO/WARNING/ERROR), `FASTMCP_ENV` (development/staging/production).

---

## Integration Patterns (Optional)

For specific integration approaches, see `references/integration-patterns.md`:
- **Manual API** -- `httpx.AsyncClient` with reusable client
- **OpenAPI auto-generation** -- `FastMCP.from_openapi(spec, client, route_maps=[...])`
- **FastAPI conversion** -- `FastMCP.from_fastapi(app)`

---

## Asset Files

- `assets/basic-server.py` -- Minimal FastMCP server template
- `assets/self-contained-server.py` -- Server with storage and middleware
- `assets/tools-examples.py` -- Tool patterns and type annotations
- `assets/resources-examples.py` -- Resource URI patterns
- `assets/prompts-examples.py` -- Prompt template patterns
- `assets/client-example.py` -- MCP client usage
- `assets/SCRIPTS-TEMPLATE.md` -- CLI companion docs template
- `assets/script-template.ts` -- TypeScript CLI script template

© jezweb · MIT · jezweb/claude-skills

Similar skills

All skills for Agent setup: memory, context, orchestration →

mcp-builder by other authors comes first.

mcp-builder official anthropics This skill walks through building an MCP server in TypeScript or Python, from reading the protocol spec to writing tests and evaluation questions. 130,949installs mcp-builder microsoft Guide for building Model Context Protocol servers in TypeScript, Python, or C# to connect LLMs with custom APIs. 108installs mcp-builder shareAI-lab A skill that walks you through writing MCP servers in Python and TypeScript: tools, resources, testing and config registration. CX Codex +1 ★ 79,238repo stars cuopt-install NVIDIA cuOpt Team Installs NVIDIA cuOpt for Python, C, or as a REST server via pip, conda, or Docker, then verifies the setup. Helpful when configuring GPU-accelerated routing environments. CX Codex +1 2,500installs cuopt-server-api-python NVIDIA cuOpt Team Deploys the NVIDIA cuOpt REST server and guides client requests via Python or curl. Useful for solving routing, LP, and MILP optimization problems on GPUs. CX Codex +1 2,200installs backend-developer VoltAgent Community Subagent for building backend APIs and microservices in Node.js, Python, and Go. Helps implement relational schemas, caching, and OWASP security rules. 2,724installs devcontainer-setup trailofbits Creates a sandboxed devcontainer with Claude Code, persistent volumes, and tooling for Python, Node, Rust, or Go. Helpful when setting up isolated development workspaces. CX Codex +1 5,200installs neo4j-docker-client-generator official github Generates a clean Python client library for Neo4j from a GitHub issue, creating Pydantic models and repository classes. 183installs capture-environment pedrohcgs This skill snapshots language and package versions, seeds and RNG kind into lockfiles so a rerun matches on another machine. Reach for it before releasing a replication package. CX Codex +1 ★ 1,668repo stars

From the same set54

wordpress-setup The skill checks WP-CLI, tests SSH or the REST API, sets up auth and saves a verified connection config for a WordPress site. CX Codex +1 1,500installs ai-image-generator A skill that tells your agent which Gemini or Claude model to pick and how to build prompts in five parts. Useful when a site needs hero banners, icons or OG images. CX Codex +1 1,400installs shopify-products Creates and updates Shopify products using the Admin GraphQL API or generates CSV files for bulk catalog import. CX Codex +1 1,400installs social-media-posts Creates posts for LinkedIn, Facebook, Instagram and Reddit in each platform’s format. Use it for a new announcement, existing content or a coordinated campaign. CX Codex +1 1,400installs cloudflare-worker-builder Scaffolds Cloudflare Worker projects with Hono routing, Vite dev server, and Static Assets. It configures D1, R2, and KV bindings and fixes deployment routing conflicts. CX Codex +1 1,400installs design-review Reviews the visual quality of a web page or app and produces a findings report with screenshots. Use it when an interface looks off and the cause is hard to spot. CX Codex +1 1,400installs react-patterns A skill that checks React 19 components for waterfalls, bundle bloat and re-renders, and suggests composition fixes. Useful while writing or reviewing code. CX Codex +1 1,300installs react-native Performance guidelines and architecture patterns for React Native and Expo apps. Helps coding agents handle list virtualization, UI-thread animations, and navigation. CX Codex +1 1,300installs

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor