Skip to main content
Glama
bensonaddo

FastAPI Todo MCP Server

by bensonaddo

Todo Manager — FastAPI + MCP

A full-stack todo list application built with FastAPI, SQLite, and fastapi-mcp. It provides a REST API for CRUD operations, an interactive web UI, auto-generated OpenAPI documentation, and MCP tool exposure for AI assistants (e.g. Cursor).

Live demo: https://fastapi-mcp-todo-ykjl.onrender.com


Table of Contents


Related MCP server: Cold's MCP Server - Project Management System

Features

  • REST API — Full CRUD for todo items with typed request/response schemas

  • Web frontend — Responsive grid UI with add, edit, complete, delete, and filter actions

  • SQLite persistence — Local file-based database (todos.db)

  • OpenAPI docs — Interactive Swagger UI and ReDoc generated automatically by FastAPI

  • MCP server — Exposes API operations as tools for AI clients via fastapi-mcp

  • Production-ready — Deployable to Render with a single render.yaml blueprint


Tech Stack

Layer

Technology

Backend

FastAPI, Uvicorn

ORM / DB

SQLAlchemy, SQLite

Validation

Pydantic v2

Frontend

HTML, CSS, vanilla JavaScript

AI Tools

fastapi-mcp, MCP

Deployment

Render (Python web service)


Project Structure

fastapi-mcp-todo/
├── main.py              # FastAPI app, routes, MCP mount
├── database.py          # SQLite engine, session, init
├── models.py            # SQLAlchemy Todo ORM model
├── schemas.py           # Pydantic request/response schemas
├── static/
│   ├── index.html       # Frontend shell
│   ├── css/style.css    # UI styles
│   └── js/app.js        # Client-side CRUD logic
├── requirements.txt     # Python dependencies
├── render.yaml          # Render deployment config
├── todos.db             # SQLite database (created at runtime, gitignored)
└── readme.md

Getting Started

Prerequisites

  • Python 3.9+

  • pip (or uv)

Installation

# Clone the repository and enter the project directory
cd fastapi-mcp-todo

# Create and activate a virtual environment
python -m venv .venv
source .venv/bin/activate        # macOS / Linux
# .venv\Scripts\activate         # Windows

# Install dependencies
pip install -r requirements.txt

Running the Application

Development (with auto-reload)

# Option A — FastAPI CLI
fastapi dev main.py

# Option B — Uvicorn directly
uvicorn main:app --reload

Production

uvicorn main:app --host 0.0.0.0 --port 8000

The app starts on http://127.0.0.1:8000 by default. The SQLite database and tables are created automatically on first startup.


Web UI

URL (local)

Description

http://127.0.0.1:8000/

Todo Manager web interface

http://127.0.0.1:8000/static/

Static assets (CSS, JS)

The frontend communicates with the /todos API and supports:

  • Adding todos (instant grid update)

  • Marking todos complete / incomplete

  • Editing todo content (modal)

  • Deleting todos (with confirmation)

  • Filtering by All / Active / Completed

  • Live stats (total, active, completed)


API Reference

Base URL (local): http://127.0.0.1:8000
Base URL (production): https://fastapi-mcp-todo-ykjl.onrender.com

All todo endpoints are tagged Todos in OpenAPI. Responses use application/json.

Endpoints Summary

Method

Path

Operation ID

Description

Success

GET

/todos

get_all_todos

List all todos

200

GET

/todos/{todo_id}

get_todo

Get one todo by ID

200

POST

/todos

create_todo

Create a new todo

201

PUT

/todos/{todo_id}

update_todo

Update a todo

200

DELETE

/todos/{todo_id}

delete_todo

Delete a todo

204


GET /todos — List all todos

Returns every todo ordered by todo_id.

Response 200

[
  {
    "todo_id": 1,
    "content": "Buy groceries",
    "completed": false
  },
  {
    "todo_id": 2,
    "content": "Schedule dentist appointment",
    "completed": true
  }
]

Example

curl http://127.0.0.1:8000/todos

GET /todos/{todo_id} — Get a single todo

Path parameters

Name

Type

Description

todo_id

integer

Unique todo ID

Response 200

{
  "todo_id": 1,
  "content": "Buy groceries",
  "completed": false
}

Response 404 — Todo not found

{
  "detail": "Todo with id 99 not found"
}

Example

curl http://127.0.0.1:8000/todos/1

POST /todos — Create a todo

Request body

{
  "content": "Finish reading chapter 5"
}

Field

Type

Required

Description

content

string

yes

Task description (min length: 1)

completed defaults to false and cannot be set on create.

Response 201

{
  "todo_id": 3,
  "content": "Finish reading chapter 5",
  "completed": false
}

Example

curl -X POST http://127.0.0.1:8000/todos \
  -H "Content-Type: application/json" \
  -d '{"content": "Finish reading chapter 5"}'

PUT /todos/{todo_id} — Update a todo

Partial updates are supported — include only the fields you want to change.

Request body (all fields optional)

{
  "content": "Updated task text",
  "completed": true
}

Field

Type

Required

Description

content

string

no

Updated description

completed

boolean

no

Updated completion state

Response 200

{
  "todo_id": 1,
  "content": "Updated task text",
  "completed": true
}

Response 404 — Todo not found

Example

curl -X PUT http://127.0.0.1:8000/todos/1 \
  -H "Content-Type: application/json" \
  -d '{"completed": true}'

DELETE /todos/{todo_id} — Delete a todo

Response 204 — No content (success)

Response 404 — Todo not found

Example

curl -X DELETE http://127.0.0.1:8000/todos/1

OpenAPI / Swagger Documentation

FastAPI auto-generates interactive API documentation from route decorators, type hints, and Pydantic schemas.

Local

Production

Use Swagger UI (/docs) to explore endpoints, view schemas, and send test requests directly from the browser.


Data Models

Todo (database)

Column

Type

Constraints

todo_id

integer

Primary key, auto-increment

content

string

Not null

completed

boolean

Not null, default false

Pydantic schemas

Schema

Purpose

TodoCreate

Request body for POST /todos

TodoUpdate

Request body for PUT /todos/{todo_id}

TodoResponse

Response body for all todo read/write ops


MCP Integration

This app exposes selected API operations as MCP tools using fastapi-mcp, allowing AI assistants to manage todos programmatically.

Exposed tools

MCP Tool

Maps to API endpoint

get_all_todos

GET /todos

get_todo

GET /todos/{todo_id}

create_todo

POST /todos

update_todo

PUT /todos/{todo_id}

delete_todo

DELETE /todos/{todo_id}

Tools are registered via operation_id on each route and mounted at /mcp.

Setup in main.py

from fastapi_mcp import FastApiMCP

mcp = FastApiMCP(
    app,
    include_operations=[
        "get_all_todos",
        "get_todo",
        "create_todo",
        "update_todo",
        "delete_todo",
    ],
)
mcp.mount()

Connect from Cursor

  1. Open Cursor Settings → Tools & MCP → Add MCP Server

  2. Add the following to your MCP configuration:

{
  "fastapi-mcp-todo": {
    "url": "http://127.0.0.1:8000/mcp"
  }
}

For the deployed app, replace the URL with:

{
  "fastapi-mcp-todo": {
    "url": "https://fastapi-mcp-todo-ykjl.onrender.com/mcp"
  }
}
  1. Restart Cursor if needed, then use natural language prompts such as:

    • "List all todos"

    • "Add a todo to call mum today"

    • "Mark todo 2 as completed"


Deployment

The project includes a Render blueprint (render.yaml):

services:
  - type: web
    name: fastapi-mcp-todo
    env: python
    buildCommand: uv pip install -r requirements.txt
    startCommand: uvicorn main:app --host 0.0.0.0 --port 8000
    plan: free

Note: On Render's free tier, the filesystem is ephemeral. SQLite data may reset on redeploy or spin-down. For persistent production storage, consider an external database (e.g. PostgreSQL).


External Resources


License

This project is for learning and demonstration purposes.

Related MCP Connectors

Related MCP Servers