A generic, client-agnostic MCP server for managing tasks, checkpoints, and agent handoffs. Communicates via STDIO (JSON-RPC 2.0) or HTTP/SSE and works with any MCP-capable client.
Use case: Agent A hits its context limit or needs to hand off work. It saves a checkpoint with all relevant state. Agent B (same or different AI system) picks up the task and continues exactly where A left off — with full context, completed steps, remaining steps, and a resume prompt.
Agent A → save_checkpoint() → handoff_task() → [task-server]
↓
Agent B ← get_task() ←────────────────────────────────────
- Task management — create, read, update tasks with full lifecycle tracking
- Checkpoint system — agents save progress (completed steps, remaining steps, test results)
- Handoff — transfer tasks between any agents with ownership tracking
- Artifacts — attach files, diffs, and logs to tasks
- Resources — read tasks via
task://<id>as MCP resources - Dual transport — STDIO for direct subprocess use, HTTP/SSE for persistent service
- SQLite — persistent storage, no external database required
- Zero dependencies beyond
pydantic
- Python 3.11+
pydantic >= 2.0
git clone https://github.com/Mr-Websaint/mcp-task-server.git
cd mcp-task-server
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtpython3 server.pyThe server reads JSON-RPC messages from stdin and writes responses to stdout. Debug logging goes to stderr:
MCP_DEBUG=1 python3 server.pypython3 server.py --http --port 8766Endpoints:
| Endpoint | Description |
|---|---|
GET /health |
Health check → {"status": "ok"} |
GET /sse |
SSE stream (MCP SSE transport) |
POST /message?clientId=<id> |
Send JSON-RPC message |
A bundled admin script lets you inspect and manage the MCP task server directly from the terminal.
python3 /home/websaint/mcp-task-server/admin.pyIf you want a shorter command, add this Bash alias for the websaint user:
alias mcptask='python3 /home/websaint/mcp-task-server/admin.py'After adding the alias, reload your shell configuration:
source ~/.bashrcThe admin CLI provides:
- browse tasks in read-only menus
- search and filter tasks
- open a task detail menu for one task
- update status, owners, checkpoints, and handoffs
- read task data as JSON or as an MCP resource
Status values can be entered by name or by number (1 to 5) in the menus and direct CLI commands.
{
"mcpServers": {
"task-handoff": {
"command": "python3",
"args": ["/path/to/mcp-task-server/server.py"],
"env": {
"MCP_TASK_DB_PATH": "/path/to/tasks.db",
"MCP_TASK_ARTIFACTS_DIR": "/path/to/artifacts"
}
}
}
}{
"mcpServers": {
"task-handoff": {
"command": "/path/to/mcp-task-server/.venv/bin/python3",
"args": ["/path/to/mcp-task-server/server.py"]
}
}
}mcp_servers:
task_handoff:
command: "/path/to/mcp-task-server/.venv/bin/python3"
args: ["/path/to/mcp-task-server/server.py"]
env:
MCP_TASK_DB_PATH: "/path/to/mcp-task-server/tasks.db"
MCP_TASK_ARTIFACTS_DIR: "/path/to/mcp-task-server/artifacts"
timeout: 60
connect_timeout: 30mcp_servers:
task_handoff:
url: "http://127.0.0.1:8766/sse"| Variable | Default | Description |
|---|---|---|
MCP_TASK_DB_PATH |
./tasks.db |
Path to the SQLite database |
MCP_TASK_ARTIFACTS_DIR |
./artifacts/ |
Directory for artifacts |
MCP_TASK_BASE_DIR |
Directory of server.py |
Base path |
MCP_TASK_PORT |
8766 |
HTTP port (overridden by --port) |
MCP_DEBUG |
(unset) | Enable debug logging when set |
| Tool | Description |
|---|---|
create_task |
Create a new task |
get_task |
Read a task by ID |
save_checkpoint |
Save agent progress (steps, tests, resume prompt) |
handoff_task |
Transfer task from one agent to another |
mark_exhausted |
Mark task as "agent cannot proceed" |
attach_artifact |
Attach a file, diff, or log to a task |
list_tasks |
List tasks with optional filters |
update_task |
Update a task with partial field updates |
search_tasks |
Search tasks by text in the goal and title fields |
- URI:
task://<task_id> - Type:
application/json - Returns the full task as JSON (read-only)
open → in_progress → handoff_ready → in_progress → done
↘ agent_exhausted
→ {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"my-agent","version":"1.0"}}}
← {"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2024-11-05","capabilities":{"tools":{"listChanged":false},"resources":{"subscribe":false,"listChanged":false}},"serverInfo":{"name":"mcp-task-server","version":"1.0.0"}}}
→ {"jsonrpc":"2.0","method":"notifications/initialized"}→ {"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"create_task","arguments":{"task_id":"task-001","title":"Fix login bug","goal":"Resolve auth error on /login","repo_path":"/home/dev/myapp"}}}→ {"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"save_checkpoint","arguments":{"task_id":"task-001","agent":"claude-code","completed_steps":["Reproduced bug","Found root cause in auth/login.py:42"],"remaining_steps":["Implement fix","Write tests"],"resume_prompt":"Fix null check in auth/login.py line 42"}}}→ {"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"handoff_task","arguments":{"task_id":"task-001","from_agent":"claude-code","to_agent":"hermes","reason":"Context limit reached, fix not yet implemented"}}}→ {"jsonrpc":"2.0","id":5,"method":"tools/call","params":{"name":"get_task","arguments":{"task_id":"task-001"}}}Or via resource:
→ {"jsonrpc":"2.0","id":6,"method":"resources/read","params":{"uri":"task://task-001"}}→ {"jsonrpc":"2.0","id":7,"method":"tools/call","params":{"name":"update_task","arguments":{"task_id":"task-001","title":"Fix login bug","goal":"Implementing solution for auth error","status":"in_progress","current_owner":"hermes","completed_steps":["Reproduced bug","Found root cause","Implemented fix"],"remaining_steps":["Write tests","Deploy to staging"]}}}A service template is provided in systemd/mcp-task-server.service.template.
# 1. Copy and adapt the template
cp systemd/mcp-task-server.service.template /etc/systemd/system/mcp-task-server.service
# Edit User=, WorkingDirectory=, ExecStart= and Environment= paths
# 2. Enable and start
systemctl daemon-reload
systemctl enable --now mcp-task-server
# 3. Check status
systemctl status mcp-task-server
journalctl -u mcp-task-server -f# Run the bundled health check script
./healthcheck.sh
# Or hit the HTTP endpoint directly (HTTP mode only)
curl http://127.0.0.1:8766/healthThe health check verifies: venv, pydantic import, DB write access, artifacts directory, STDIO response, and HTTP service status.
mcp-task-server/
├── admin.py # Interactive admin CLI for browsing and managing tasks
├── server.py # Main server (STDIO + HTTP/SSE transport, MCP protocol)
├── config.py # Configuration via environment variables
├── models.py # Pydantic data models (Task, Artifact, TestRun, ...)
├── store.py # SQLite persistence layer
├── healthcheck.sh # Health check script
├── requirements.txt # Python dependencies
├── systemd/
│ └── mcp-task-server.service.template # systemd unit file template
└── artifacts/ # Runtime artifact storage (gitignored)
MIT — do whatever you want with it.