Skip to main content
Glama
kanaparthikiran

mcp-tasks-server

README.md
# mcp-tasks-server

A small **Model Context Protocol** server that exposes a personal task tracker
to any MCP-compatible client (Claude Desktop, Claude Code, custom agents).
Tasks live in a local SQLite database; no cloud, no surprises.

This is a reference implementation of an MCP server that takes **real
write-actions** on persistent state — the kind of integration you build
between an agentic AI platform and an enterprise system, scaled down to a
laptop.

## Tools exposed

| Tool                    | Effect on state |
|-------------------------|-----------------|
| `add_task`              | Insert a new task |
| `list_tasks`            | Read; optional status filter |
| `complete_task`         | Update `status='done'` |
| `delete_task`           | Hard-delete a task |
| `summarize_by_status`   | Read; aggregate counts |

Each tool has a JSON schema declared in code, validated on every call.

## Quick start

```bash
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
python server.py
```

### Wire into Claude Desktop

Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "tasks": {
      "command": "python",
      "args": ["/absolute/path/to/server.py"]
    }
  }
}
```

Then restart Claude Desktop. The tools appear in the MCP picker.

## Sandbox / safety notes

- Database file lives at `~/.local/share/mcp-tasks/tasks.db` by default;
  override with `MCP_TASKS_DB`. The path is normalized and confined to the
  user's home directory.
- `delete_task` requires the task ID to be an integer; no SQL is built from
  string concatenation. All queries use parameterized statements.
- The server has no network listeners — communication is over stdio per the
  MCP spec.

## Sample tool calls

The full request/response shapes for every tool are in
[`examples/tool-call-examples.md`](./examples/tool-call-examples.md).
Highlights:

| Tool | Example call | Example result |
|------|--------------|----------------|
| `add_task` | `{"title": "Review RFC", "notes": "..."}` | `{"id": 1, "title": "...", "status": "open"}` |
| `list_tasks` | `{"status": "open"}` | `{"tasks": [...]}` |
| `complete_task` | `{"id": 1}` | `{"id": 1, "status": "done"}` |
| `summarize_by_status` | `{}` | `{"counts": {"open": 2, "done": 1}}` |

## Design notes

- **Why SQLite?** Embedded, transactional, present on every Python install. A
  real enterprise integration would target a service API; the contract on the
  agent side is identical.
- **Why explicit JSON schemas?** Some MCP clients display the schemas to the
  user before approving a tool call. Putting them inline in the server makes
  tool surfaces self-documenting and gives the LLM unambiguous parameter
  contracts.
- **Why no auth?** Personal/local server. For an enterprise MCP server you'd
  add OIDC token verification at the tool boundary and scope each tool to
  the calling principal's permissions.

## License

MIT — see `LICENSE`.