Todo MCP
README.md
# Todo MCP
A persistent todo list accessible from any AI assistant that supports
[MCP](https://modelcontextprotocol.io). One server, every client.
Works with **Claude** (chat, Code, Cowork), **Codex**, and any MCP-compatible tool.
ChatGPT support is possible too, with one current auth caveat noted below.
---
## Quick start (local)
```bash
git clone https://github.com/YOUR_USER/todo-mcp.git
cd todo-mcp
cp .env.example .env
docker compose up -d
```
MCP endpoint: `http://localhost:8000/mcp`
---
## Deploy on a remote server
```bash
# 1. Copy the folder to your server
scp -r ~/Downloads/todo-mcp user@YOUR_SERVER:~/todo-mcp
# 2. SSH in and configure
ssh user@YOUR_SERVER
cd ~/todo-mcp
cp .env.example .env
# 3. Generate an auth token and add it to .env
python3 -c "import secrets; print(secrets.token_urlsafe(32))"
# → paste the output as AUTH_TOKEN=... in .env
# 4. Start
docker compose up -d
```
HTTP endpoint: `http://YOUR_SERVER:8000/mcp`
---
## Add HTTPS (recommended for remote servers)
Self-signed certs are blocked by many corporate firewalls (e.g. FortiGuard).
Use Let's Encrypt for a free, trusted certificate.
**1. Point a DNS A record at your server:**
| Type | Name | Value |
|------|------|-------|
| A | `todo` | `YOUR_SERVER_IP` |
**2. Get a certificate** (requires port 80 free temporarily):
```bash
certbot certonly --standalone -d todo.yourdomain.com
```
> If port 80 is occupied: stop whatever is using it, run certbot, then restart it.
**3. Edit `nginx.conf`** — replace `yourdomain.com` with your actual domain in:
- `server_name`
- `ssl_certificate`
- `ssl_certificate_key`
**4. Start with HTTPS:**
```bash
docker compose --profile https up -d
```
> If port 443 is already taken, set `HTTPS_PORT=8443` in `.env`.
> Your endpoint becomes `https://todo.yourdomain.com:8443/mcp`.
**5. Open the firewall** if needed:
```bash
ufw allow 443/tcp # or 8443/tcp if using a custom port
```
> **Note:** The nginx container mounts all of `/etc/letsencrypt` (not just `live/`),
> because Let's Encrypt certs are symlinks into `archive/`. Mounting only `live/`
> breaks symlink resolution inside the container.
HTTPS endpoint: `https://todo.yourdomain.com/mcp`
---
## Connect your AI clients
Use the full MCP endpoint URL here: `https://todo.yourdomain.com/mcp`
For the companion slash commands / skill in `skills/`, use the base server URL
without `/mcp`, for example: `https://todo.yourdomain.com`
### Claude (claude.ai)
Settings → Integrations → Add custom integration
- URL: `https://todo.yourdomain.com/mcp`
- If auth is enabled, add header: `Authorization: Bearer YOUR_TOKEN`
### Claude Code
Add to `~/.claude.json`:
```json
{
"mcpServers": {
"todo": {
"type": "url",
"url": "https://todo.yourdomain.com/mcp",
"headers": {
"Authorization": "Bearer YOUR_TOKEN"
}
}
}
}
```
### Codex (CLI, app, IDE extension)
Codex uses `~/.codex/config.toml` (or project-local `.codex/config.toml`).
The Codex CLI and app share this config.
No auth:
```toml
[mcp_servers.todo]
url = "https://todo.yourdomain.com/mcp"
```
Bearer token auth:
```toml
[mcp_servers.todo]
url = "https://todo.yourdomain.com/mcp"
bearer_token_env_var = "TODO_MCP_TOKEN"
```
Then export the token before starting Codex:
```bash
export TODO_MCP_TOKEN="YOUR_TOKEN"
```
You can also use static headers with `http_headers` or environment-backed
headers with `env_http_headers`.
### ChatGPT
As of **March 26, 2026**, OpenAI's ChatGPT developer mode supports remote MCP
servers over streaming HTTP, but the documented auth modes are **OAuth**, **no
authentication**, and **mixed auth**. This server currently supports **no auth**
or **bearer token auth**.
That means:
- `AUTH_TOKEN` empty: easiest path for ChatGPT testing
- `AUTH_TOKEN` set: works in Claude / Codex, but ChatGPT may not connect unless
you add OAuth support
This is an inference from OpenAI's current docs: bearer-only remote MCP servers
do not appear to be the smooth path in ChatGPT today.
If you want ChatGPT support right now, leave `AUTH_TOKEN` empty during testing
or place the server behind another trusted access layer. If you want secure
internet-facing ChatGPT access, the next step is adding OAuth.
### Any other MCP client
Streamable HTTP transport, URL `https://todo.yourdomain.com/mcp`.
Include header `Authorization: Bearer YOUR_TOKEN` if auth is enabled.
---
## Slash commands and skill triggers
Install the companion skill from the `skills/` folder:
| Command | Also triggers on |
|---------|-----------------|
| `/setup-todo <url>` | "setup todo", "configure todo", "set todo url" |
| `/todo <text>` | "add todo", "remind me to", "note to self", "don't let me forget" |
| `/next-todo` | "what's next", "what should I work on", "most urgent", "what's overdue" |
| `/list-todo [filter]` | "show my todos", "what's on my plate", "todo stats", "show ASF todos" |
```bash
cd skills && chmod +x install.sh && ./install.sh
/setup-todo https://todo.yourdomain.com
```
For Codex, see:
- `codex-config.toml.example`
- `skills/AGENTS.md.example`
---
## MCP tools
| Tool | What it does |
|------|-------------|
| `todo_list` | List todos with short `#1`, `#2`, `#3` references for follow-up actions |
| `todo_add` | Add a todo with optional tag, priority, and due date |
| `todo_update` | Edit text, toggle done, change priority / tag / due using a short reference or internal ID |
| `todo_complete` | Mark a todo done using a short reference or internal ID |
| `todo_delete` | Permanently delete a todo using a short reference or internal ID |
| `todo_stats` | Summary counts by status, tag, priority, and overdue |
Example flow:
```text
Found 3 todos — 3 open, 0 done, 0 overdue
Use the `#` number to refer to an item in follow-up commands.
#1 ○ Buy groceries
priority:high due:2026-03-27
#2 ○ Review pages and letter of HubX
#3 ○ Read MCP spec (streamable HTTP section)
priority:med tag:dev
```
That lets the assistant say things like `complete 1` or `delete 2` without
surfacing the long internal storage IDs in the normal presentation.
---
## Authentication
Set `AUTH_TOKEN` in `.env` to require a bearer token on all requests.
Leave it empty to disable auth (fine for local, not recommended for remote).
Compatibility summary:
- Claude / Claude Code: works with bearer auth
- Codex: works with bearer auth
- ChatGPT: easiest with no auth today; OAuth would be needed for the cleanest
authenticated setup
```bash
# Generate a token
python3 -c "import secrets; print(secrets.token_urlsafe(32))"
```
The `/health` endpoint is always public (used by Docker healthchecks).
---
## Architecture
- **Protocol**: MCP over [streamable HTTP](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#streamable-http)
- **Runtime**: Python 3.12 + FastMCP
- **Storage**: JSON file in a Docker named volume (`/data/todos.json`)
- **Auth**: Optional bearer token middleware
- **TLS**: Optional nginx reverse proxy (`--profile https`)
---
## Notes for OpenAI clients
I verified the current OpenAI docs before writing this section:
- Codex supports streamable HTTP MCP servers, bearer tokens, `http_headers`,
and `env_http_headers`
- ChatGPT developer mode supports streaming HTTP MCP servers, but its docs
currently describe OAuth / no auth / mixed auth rather than arbitrary bearer
header entry in the UI
Sources:
- [Codex MCP docs](https://developers.openai.com/codex/mcp)
- [ChatGPT developer mode docs](https://help.openai.com/en/articles/12584461-developer-mode-apps-and-full-mcp-connectors-in-chatgpt-beta)
---
## Backup & restore
```bash
# Backup
docker cp $(docker compose ps -q todo-mcp):/data/todos.json ./backup.json
# Restore
docker cp ./backup.json $(docker compose ps -q todo-mcp):/data/todos.json
```
---
## License
MIT
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues