Skip to content

Ordinath/taskwing

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TaskWing

Standalone MCP server for multi-tenant task and project management. SQLite + FTS5, no network deps, plug-and-play with any MCP-aware client (Claude Code, Claude Desktop, Cursor, Cline, …).

What you get

  • Workspaces auto-created from an env var — one per chat / agent / project, isolated by default.
  • Projects that can be shared across workspaces through a many-to-many join, so one project can live in multiple agents at once.
  • Tasks with status, priority, due dates, tags, subtasks, and full-text search via SQLite FTS5.
  • Server-side privilege model — structural ops (sharing, deletion) are gated by an env-var bit a trusted client controls.

Install

pip install git+https://github.com/Ordinath/taskwing.git
# or, in this checkout:
pip install -e ".[dev]"

Python 3.11+ required. The only runtime deps are mcp[cli] and pydantic>=2.

Run

TASKWING_WORKSPACE=my-chat \
TASKWING_PRIVILEGED=true \
taskwing-mcp

The server speaks MCP over stdio. Stop it with Ctrl+C.

Environment variables

var meaning default
TASKWING_WORKSPACE workspace name. Auto-created on first run if absent. default
TASKWING_PRIVILEGED "true" (literal) ⇒ structural ops allowed; anything else ⇒ blocked. unset → unprivileged
TASKWING_DB_PATH path to the SQLite file. ~/.taskwing/taskwing.db

TASKWING_PRIVILEGED is captured at workspace creation time and stored in the row. Flipping the env later does not retroactively elevate or downgrade an existing workspace — re-create it (workspace_delete then re-attach) to change the bit.

MCP-client config snippet

"taskwing": {
  "transport": "stdio",
  "command": "python3",
  "args": ["-m", "taskwing.mcp_server"],
  "env": {
    "TASKWING_WORKSPACE": "${TASKWING_WORKSPACE}",
    "TASKWING_PRIVILEGED": "${TASKWING_PRIVILEGED:-false}"
  }
}

Set TASKWING_WORKSPACE and TASKWING_PRIVILEGED per session/agent. The same DB file backs every workspace, so projects can be shared across them by name.

Tools

25 tools, grouped by entity:

group tool
workspace workspace_current, workspace_list*, workspace_create*, workspace_rename*, workspace_delete*
project project_list, project_create, project_get, project_update, project_archive, project_delete*, project_attach*, project_detach*, project_list_workspaces
task task_create, task_get, task_update, task_complete, task_uncomplete, task_delete
search task_search, task_today, task_overdue, task_upcoming, daily_digest

Tools marked * are privileged-only.

Full descriptions, args, and return shapes are baked into the FastMCP tool registrations — your LLM client surfaces them as JSON schema automatically. See DESIGN.md for the full list with types and semantics.

Security model

Two roles, decided once per workspace at creation:

  • Privileged workspace — can perform structural ops (share/unshare projects, delete projects, manage workspaces).
  • Unprivileged workspace — can do everything else inside projects it can already see (full task R/W, project create/update/archive in its own scope), but can't reach across workspaces or hard-delete.

The bit is set from TASKWING_PRIVILEGED and frozen in the DB row. The trusted client (the thing that spawns the server) decides which workspaces get it — TaskWing itself is unopinionated.

Pattern: privileged vs untrusted callers

If you run multiple agents/sessions/tenants against a shared TaskWing instance and only some of them should be allowed structural ops, set TASKWING_PRIVILEGED from a trusted source in your spawn pipeline — after reading any user-controlled config (.env, env-file, etc.) so the value cannot be overridden by the caller. Pseudocode:

// AFTER loading the agent's user config:
env.TASKWING_PRIVILEGED = isTrustedSession(agent) ? 'true' : 'false';

A common shape is "host process / sandboxed container" — the host gets true, the container gets false, and the host always overwrites whatever the container's own config tried to set. Same pattern works for "admin chat vs shared room", "owner workspace vs guest", etc.

Storage

Single SQLite file at ~/.taskwing/taskwing.db (override with TASKWING_DB_PATH). All workspaces live in the same file. Tables: workspaces, projects, workspace_projects (m2m join), tasks. Full-text search uses an FTS5 virtual table kept in sync via triggers.

Develop

pip install -e ".[dev]"
pytest -q --cov=taskwing

The suite covers schema/migration, all CRUD paths, search filters, FTS, isolation between workspaces, privilege enforcement on every privileged op, R/W on shared projects, and the FastMCP server smoke flow. Coverage gate: ≥90%.

License

MIT.

About

Standalone MCP server for multi-tenant task and project management. SQLite + FTS5, server-side privilege model, plug-and-play for any MCP-aware client.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors