Back to skills
SkillHub ClubAnalyze Data & AIFull StackBackendData / AI

fastmcp-server-setup

Create MCP (Model Context Protocol) servers using FastMCP Python SDK. Define tools that AI agents can call to perform task operations. Use when building MCP servers for Phase 3 AI chatbot integration.

Packaged view

This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.

Stars
0
Hot score
74
Updated
March 20, 2026
Overall rating
C2.3
Composite score
2.3
Best-practice grade
S100.0

Install command

npx @skill-hub/cli install maneeshanif-todo-spec-driven-fastmcp-server-setup

Repository

maneeshanif/todo-spec-driven

Skill path: .claude/skills/fastmcp-server-setup

Create MCP (Model Context Protocol) servers using FastMCP Python SDK. Define tools that AI agents can call to perform task operations. Use when building MCP servers for Phase 3 AI chatbot integration.

Open repository

Best for

Primary workflow: Analyze Data & AI.

Technical facets: Full Stack, Backend, Data / AI, Integration.

Target audience: everyone.

License: Unknown.

Original source

Catalog source: SkillHub Club.

Repository owner: maneeshanif.

This is still a mirrored public skill entry. Review the repository before installing into production workflows.

What it helps with

  • Install fastmcp-server-setup into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
  • Review https://github.com/maneeshanif/todo-spec-driven before adding fastmcp-server-setup to shared team environments
  • Use fastmcp-server-setup for development workflows

Works across

Claude CodeCodex CLIGemini CLIOpenCode

Favorites: 0.

Sub-skills: 0.

Aggregator: No.

Original source / Raw SKILL.md

---
name: fastmcp-server-setup
description: Create MCP (Model Context Protocol) servers using FastMCP Python SDK. Define tools that AI agents can call to perform task operations. Use when building MCP servers for Phase 3 AI chatbot integration.
allowed-tools: Bash, Write, Read, Edit, Glob
---

# FastMCP Server Setup

Quick reference for creating MCP servers using FastMCP for the Todo AI Chatbot Phase 3.

**Reference Repository**: https://github.com/panaversity/learn-agentic-ai

---

## Architecture Overview

```
┌─────────────────────────────────────────────────────────────┐
│                      FastMCP Server                         │
├─────────────────────────────────────────────────────────────┤
│  ┌─────────────────┐     ┌─────────────────────────────┐   │
│  │  @mcp.tool      │     │  Database Operations        │   │
│  │  add_task       │────▶│  SQLModel + Session         │   │
│  │  list_tasks     │     │                             │   │
│  │  complete_task  │     │  Task CRUD Operations       │   │
│  │  delete_task    │     │                             │   │
│  │  update_task    │     └─────────────────────────────┘   │
│  └─────────────────┘                                       │
│                                                             │
│  Transport Options: stdio | http | sse                      │
└─────────────────────────────────────────────────────────────┘
                              ▲
                              │ FastMCP Client calls
                              │
┌─────────────────────────────┴───────────────────────────────┐
│  OpenAI Agents SDK (Agent with MCP Tools)                   │
│  @function_tool wrappers → Client.call_tool()               │
└─────────────────────────────────────────────────────────────┘
```

**Key Insight**: The MCP server handles ALL database operations. The OpenAI Agent uses FastMCP Client to call these tools.

---

## Quick Start

### 1. Install Dependencies

```bash
cd backend
uv add fastmcp
```

### 2. Create Basic MCP Server

Create `backend/src/mcp_server/server.py`:

```python
from fastmcp import FastMCP

# Create MCP server
mcp = FastMCP("Todo MCP Server")

@mcp.tool
def hello(name: str = "World") -> str:
    """Say hello to someone."""
    return f"Hello, {name}!"

# Run server
if __name__ == "__main__":
    mcp.run()  # Default: stdio transport
```

### 3. Run the Server

```bash
# Default stdio transport (for CLI integration)
uv run python -m src.mcp_server.server

# HTTP transport (for web deployment) - RECOMMENDED for Phase 3
uv run python -m src.mcp_server.server  # modify server to use http

# SSE transport (legacy, for backward compatibility)
# Modify server: mcp.run(transport="sse", host="127.0.0.1", port=8001)
```

---

## Transport Options

| Transport | Use Case | Code | URL Pattern |
|-----------|----------|------|-------------|
| `stdio` | CLI, desktop apps, local dev | `mcp.run()` | N/A (spawned process) |
| `http` | Web deployment, API access | `mcp.run(transport="http", host="0.0.0.0", port=8001)` | `http://localhost:8001` |
| `sse` | Legacy SSE clients | `mcp.run(transport="sse", host="127.0.0.1", port=8001)` | `http://localhost:8001/sse` |

**Recommended for Phase 3**: Use `http` transport for agent integration. No `path` parameter needed for HTTP transport.

---

## Defining Tools

### Basic Tool (No Parentheses)

```python
@mcp.tool
def add_numbers(a: int, b: int) -> int:
    """Add two numbers together."""
    return a + b
```

### Tool with Custom Name

```python
@mcp.tool(name="custom_tool_name")
def my_function(x: int) -> str:
    """This tool has a custom name."""
    return str(x)
```

### Tool with Tags and Metadata

```python
@mcp.tool(
    name="find_products",
    description="Search the product catalog.",
    tags={"catalog", "search"},
    meta={"version": "1.2", "author": "team"}
)
def search_products(query: str, category: str | None = None) -> list[dict]:
    """Internal docstring (ignored if description provided above)."""
    return [{"id": 1, "name": "Product"}]
```

### Tool with Optional Parameters

```python
@mcp.tool
def create_task(
    title: str,
    description: str | None = None,
    priority: str = "medium"
) -> dict:
    """Create a new task.

    Args:
        title: The task title (required)
        description: Optional task description
        priority: Task priority (low, medium, high)
    """
    return {
        "status": "created",
        "title": title,
        "description": description,
        "priority": priority
    }
```

### Disabled Tool (Feature Flag)

```python
@mcp.tool(enabled=False)
def maintenance_tool() -> str:
    """This tool is currently under maintenance."""
    return "Disabled"
```

---

## Project Structure

```
backend/src/
├── mcp_server/
│   ├── __init__.py           # Package init
│   └── server.py             # FastMCP server with all tools
│
├── models/
│   └── task.py               # SQLModel Task model
│
├── database.py               # Database engine & session
│
└── agents/                   # OpenAI Agents (separate from MCP)
    ├── mcp_tools.py          # @function_tool wrappers for MCP
    └── ...
```

---

## Complete Todo MCP Server

```python
# backend/src/mcp_server/server.py
"""
FastMCP Server for Todo operations.
This server handles ALL database operations - the Agent just calls these tools.
"""
from fastmcp import FastMCP
from sqlmodel import Session, select
from src.database import engine
from src.models.task import Task

# Create MCP server
mcp = FastMCP("Todo MCP Server")


@mcp.tool
def add_task(user_id: str, title: str, description: str | None = None) -> dict:
    """Add a new task for a user.

    Args:
        user_id: The user's unique identifier
        title: The task title (required)
        description: Optional task description
    """
    with Session(engine) as session:
        task = Task(user_id=user_id, title=title, description=description)
        session.add(task)
        session.commit()
        session.refresh(task)
        return {
            "status": "created",
            "task_id": task.id,
            "title": task.title
        }


@mcp.tool
def list_tasks(user_id: str, status: str = "all") -> list[dict]:
    """List tasks for a user with optional status filter.

    Args:
        user_id: The user's unique identifier
        status: Filter by 'all', 'pending', or 'completed'
    """
    with Session(engine) as session:
        query = select(Task).where(Task.user_id == user_id)

        if status == "pending":
            query = query.where(Task.completed == False)
        elif status == "completed":
            query = query.where(Task.completed == True)

        tasks = session.exec(query).all()
        return [
            {
                "id": t.id,
                "title": t.title,
                "description": t.description,
                "completed": t.completed
            }
            for t in tasks
        ]


@mcp.tool
def complete_task(user_id: str, task_id: int) -> dict:
    """Mark a task as completed.

    Args:
        user_id: The user's unique identifier
        task_id: The ID of the task to mark complete
    """
    with Session(engine) as session:
        task = session.exec(
            select(Task).where(Task.id == task_id, Task.user_id == user_id)
        ).first()

        if not task:
            return {"status": "error", "message": "Task not found"}

        task.completed = True
        session.add(task)
        session.commit()
        return {"status": "completed", "task_id": task.id}


@mcp.tool
def delete_task(user_id: str, task_id: int) -> dict:
    """Delete a task permanently.

    Args:
        user_id: The user's unique identifier
        task_id: The ID of the task to delete
    """
    with Session(engine) as session:
        task = session.exec(
            select(Task).where(Task.id == task_id, Task.user_id == user_id)
        ).first()

        if not task:
            return {"status": "error", "message": "Task not found"}

        session.delete(task)
        session.commit()
        return {"status": "deleted", "task_id": task_id}


@mcp.tool
def update_task(
    user_id: str,
    task_id: int,
    title: str | None = None,
    description: str | None = None
) -> dict:
    """Update a task's title and/or description.

    Args:
        user_id: The user's unique identifier
        task_id: The ID of the task to update
        title: New title for the task (optional)
        description: New description for the task (optional)
    """
    with Session(engine) as session:
        task = session.exec(
            select(Task).where(Task.id == task_id, Task.user_id == user_id)
        ).first()

        if not task:
            return {"status": "error", "message": "Task not found"}

        if title is not None:
            task.title = title
        if description is not None:
            task.description = description

        session.add(task)
        session.commit()
        return {
            "status": "updated",
            "task_id": task.id,
            "title": task.title
        }


if __name__ == "__main__":
    # HTTP transport for web integration (no path parameter needed)
    mcp.run(
        transport="http",
        host="0.0.0.0",
        port=8001,
    )
```

---

## FastMCP Client (for testing or Agent integration)

```python
# Test the MCP server with FastMCP Client
import asyncio
from fastmcp import Client

async def test_mcp_server():
    # Connect to HTTP server (no /mcp path needed)
    async with Client("http://localhost:8001") as client:
        # List available tools
        tools = await client.list_tools()
        print("Available tools:")
        for tool in tools:
            print(f"  - {tool.name}")

        # Call a tool
        result = await client.call_tool(
            "add_task",
            {
                "user_id": "test-user",
                "title": "Test task",
                "description": "Created via MCP client"
            }
        )
        print(f"Result: {result}")

if __name__ == "__main__":
    asyncio.run(test_mcp_server())
```

---

## Environment Variables

```env
# Database
DATABASE_URL=postgresql://user:pass@host/db

# MCP Server
MCP_SERVER_HOST=0.0.0.0
MCP_SERVER_PORT=8001
MCP_SERVER_PATH=/mcp
```

---

## Verification Checklist

- [ ] `fastmcp` package installed (`uv add fastmcp`)
- [ ] MCP server created with `FastMCP("name")`
- [ ] All 5 task tools implemented (add, list, complete, delete, update)
- [ ] Tools handle database operations correctly
- [ ] Server runs without errors
- [ ] Tools return proper dict/list responses
- [ ] HTTP transport configured for agent integration
- [ ] Can test with FastMCP Client

---

## See Also

- [REFERENCE.md](./REFERENCE.md) - Detailed FastMCP API reference
- [TOOLS.md](./TOOLS.md) - Tool definition patterns
- [examples.md](./examples.md) - More code examples
- [openai-agents-setup](../openai-agents-setup/) - Agent setup with MCP tools
- [FastMCP GitHub](https://github.com/jlowin/fastmcp)
fastmcp-server-setup | SkillHub