todo-mcp-server
by janvavrina
README.md
# MCP Todo Server
A distributed MCP server for task prioritization with AI-powered analysis.
## Quick Start
```bash
# Set your OpenRouter API key
echo "OPENROUTER_API_KEY=your-api-key" > .env
# Start the stack
docker compose up --build -d
```
Server runs at `http://localhost:3000/mcp`
## Example Usage
### Adding TODOs

### Analyzing TODOs

### Marking TODO as done

### Removing TODO


### Clearing TODOs

## Architecture
- **2 Node instances** behind Caddy load balancer (round-robin)
- **Redis** for shared state (no sticky sessions required)
- **OpenRouter** for AI-powered task analysis
## MCP Tools
| Tool | Description |
|------|-------------|
| `todo_add` | Add a new task |
| `todo_list` | List all tasks |
| `todo_remove` | Remove a task by ID |
| `todo_clear` | Clear all tasks |
| `todo_mark_done` | Mark task as completed |
| `todo_analyze` | AI analysis for task prioritization |
## Client Setup
⚠️ **User Isolation**: Set the `x-user-id` header to isolate your todos. Without it, todos are shared with all users.
⚠️ **Important**: Before starting your full conversation at any given client, you should start by sending message that you want to use MCP tools from this MCP server.
For example in OpenCode the tools have the prefix `todo-mcp` due to the name of the MCP server in the config. See example first message would be: `For this conversation I want you to use MCP tools starting with todo-mcp`.
Reason why is that because most of the clients will have their TODO implementation already and it could mix up.
### Cursor
#### Disclaimer
After adding the MCP server to Cursor, Cursor will be saying that the server is not available and there is error. The logs show that it is looking for SSE connections but still manages to connect and use the tools. Ignore that for now. It might be Cursor bug, could be reported to them.
<details>
<summary>With user isolation (recommended)</summary>
[](cursor://anysphere.cursor-deeplink/mcp/install?name=todo-mcp&config=eyJ0eXBlIjoiaHR0cCIsInVybCI6Imh0dHA6Ly9sb2NhbGhvc3Q6MzAwMC9tY3AiLCJoZWFkZXJzIjp7IngtYXBpZnktdXNlci1pZCI6InlvdXItdW5pcXVlLXVzZXItaWQifX0=)
Or manually add to `~/.cursor/mcp.json`:
```json
{
"mcpServers": {
"todo-mcp": {
"type": "http",
"url": "http://localhost:3000/mcp",
"headers": {
"x-user-id": "your-unique-user-id"
}
}
}
}
```
</details>
<details>
<summary>Without user isolation (todos shared with all users)</summary>
[](cursor://anysphere.cursor-deeplink/mcp/install?name=todo-mcp&config=eyJ0eXBlIjoiaHR0cCIsInVybCI6Imh0dHA6Ly9sb2NhbGhvc3Q6MzAwMC9tY3AifQ==)
Or manually add to `~/.cursor/mcp.json`:
```json
{
"mcpServers": {
"todo-mcp": {
"type": "http",
"url": "http://localhost:3000/mcp"
}
}
}
```
</details>
### VS Code
<details>
<summary>With user isolation (recommended)</summary>
```json
{
"servers": {
"todo-mcp": {
"type": "http",
"url": "http://localhost:3000/mcp",
"headers": {
"x-user-id": "your-unique-user-id"
}
}
}
}
```
</details>
<details>
<summary>Without user isolation (todos shared with all users)</summary>
```json
{
"servers": {
"todo-mcp": {
"type": "http",
"url": "http://localhost:3000/mcp"
}
}
}
```
</details>
### OpenCode
<details>
<summary>With user isolation (recommended)</summary>
```json
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"todo-mcp": {
"type": "remote",
"url": "http://localhost:3000/mcp",
"headers": {
"x-user-id": "your-unique-user-id"
},
"enabled": true
}
}
}
```
</details>
<details>
<summary>Without user isolation (todos shared with all users)</summary>
```json
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"todo-mcp": {
"type": "remote",
"url": "http://localhost:3000/mcp",
"enabled": true
}
}
}
```
</details>
## Endpoints
- `POST /mcp` - MCP protocol endpoint
- `GET /health` - Health check
## Environment Variables
| Variable | Description | Default |
|----------|-------------|---------|
| `OPENROUTER_API_KEY` | OpenRouter API key | required |
| `REDIS_URL` | Redis connection URL | `redis://redis:6379` |
| `PORT` | Server port | `3000` |
## Development
```bash
npm install
npm run dev
```
## User Isolation
Todos are isolated per user via the `x-user-id` header:
- Redis keys: `todo:{userId}:{id}` and `todos:{userId}`
- No sticky sessions required - any node can handle any request
- Without the header, requests are associated with a shared `default` user (no 401 is returned)
The user isolation is implemented in a dummy manner. Usage of API key would be better and preferred but I wanted to keep it simple and focus on the MCP server implementation.
### Load Balancing
Caddy distributes requests round-robin across both nodes. All state is in Redis.
## Testing
Unit and integration tests.
```bash
npm test
```This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues