vikunja-mcp
This server provides a workflow-driven task management interface for Vikunja, guiding an AI agent through a fixed pipeline (Backlog → Queue → Design → Build → Review → Done).
next_task()— Retrieve your active task in Design/Build, or the top-priority free task from the Queue. Never surfaces Backlog or blocked tasks; only one task at a time.claim(task_id)— Claim a task from the Queue, assigning it to yourself and moving it to Design. Includes race-condition protection.get_task(task_id)— Fetch full details of a task: description, current stage, assignees, labels, and complete comment thread.comment(task_id, text)— Add a progress note or decision log to a task's comment thread.advance(task_id, to, spec, worklog, evidence)— Move your task forward: Design → Build (requires aspec), or Build → Review (requiresworklog+evidence). Advancing directly to Done is blocked — only humans can sign off.call_human(task_id, question)— Escalate to a human for a decision or input. Posts your question as a comment and moves the task to "Call to Human" while preserving your assignment.return_task(task_id, reason)— Return a task due to an external blocker (missing access, broken dependency, etc.). Unassigns you, adds ablockedlabel, and moves it back to Backlog for human re-triage.decompose(task_id, subtasks)— Break a large task into 2+ subtasks (each with a title, optional description, and priority). Subtasks are created in Queue with a parent relation; the parent is labeledepicand moved to Backlog.
Provides optional Slack notifications via a webhook when tasks are moved to 'Your Call' status, alerting humans about pending questions.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@vikunja-mcpGet me the next task I should work on."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.

What this is
Most task-tracker integrations are CRUD wrappers: they hand an agent create_task,
update_task, delete_task and hope the prompt keeps it honest. This one does the opposite.
It exposes twelve narrow tools, and each one refuses the moves that would break the process:
Backlog → Queue → Design → Build → Review → [human] → Done
↕ ↕
Your Call (+ independent review of every task in Review)BacklogandDoneare human territory. Triage in at one end, sign off at the other. There is no argument toadvancethat reachesDone— an agent that tries is told only a human moves a task to Done after review.Queue → Design → Build → Reviewis the agent loop. Claim a task, write a spec to leave Design, produce a worklog and an evidence sha to leave Build.Your Callis the side branch for when an agent needs a decision it should not make alone. It keeps its assignment and its context; the human answers on the card.
Gates are guardrails for agents, not a security boundary — the real boundary is the scoped API token Vikunja mints. See SECURITY.md.
Related MCP server: Accordo
Why
An autonomous agent left running against a plain task API drifts in ways that are individually reasonable and collectively useless: it marks its own work done, it starts the next thing before finishing this one, it "fixes" a bug by deleting the test, and the only record of any of it is a chat log that scrolled away three hours ago.
None of that is fixed by a longer prompt. The prompt is advice; the tool call is the decision point. So the process is enforced where the decision happens:
Instead of hoping the agent… | …the tool refuses |
doesn't grade its own homework |
|
writes down a plan before coding |
|
says what it did and where |
|
works on one thing at a time |
|
escalates instead of guessing |
|
leaves a trail a human can audit | every transition writes a marked comment on the card |
What you get back is a board where each card carries its own history — the claim, the plan, the work, the independent verdict — in the order it happened.
What it looks like in practice
A card that has been all the way through the loop. Nothing here was typed by a human: the markers, the labels and the stage are what the tools wrote as the agents moved it.
Read top to bottom, that is claim → advance(to="build", spec=…) → advance(to="review", worklog=…, evidence=…) → a different agent's review_task(verdict="approve", report=…).
The reviewed label is what the verdict left behind; the card now sits in Review waiting for
a human to sign it off. Every task gets that review, not just bug fixes — only an epic
container is exempt, because its code lives in its children.
And when the agent hits a decision that isn't its to make, it parks the card instead of guessing:
The card keeps its assignee, so it comes back to the same agent when you answer. Set
VIKUNJA_NOTIFY_WEBHOOK and you also get a Slack-shaped ping with a deep link, so parking a
question doesn't mean waiting for someone to notice a board.
Quick start
1. Install — no clone needed, uvx runs it straight from the repo:
uvx --from git+https://github.com/ufna/vikunja-mcp@stable vikunja-mcp --version2. Create the board. With an admin token, this creates the project if it's missing and
reconciles the seven canonical columns (it also migrates a default Vikunja board's
Todo/Doing columns, and prints ready-to-commit config snippets):
VIKUNJA_TOKEN=<admin token> uvx --from git+https://github.com/ufna/vikunja-mcp@stable \
vikunja-mcp setup --project "My Project" --share agent-bot:write --url https://vikunja.example.com3. Point the repo at it. Commit .vikunja-mcp.toml; keep the token out of it:
[tracker]
url = "https://vikunja.example.com"
project_id = 12
wip_limit = 3 # how many Design/Build tasks one token may claim into at once
language = "en" # "en" | "ru" — what language cards are written in# .vikunja-mcp.env — same directory, gitignored, NEVER committed
VIKUNJA_TOKEN=tk_xxxxxxxxxxxx4. Register the server with Claude Code (.mcp.json) or opencode
(opencode.json). Both subscribe to the moving stable branch, so releases roll out on the
next session start with no per-repo bumps:
{ "mcpServers": { "tracker": {
"command": "uvx",
"args": ["--refresh-package", "vikunja-mcp",
"--from", "git+https://github.com/ufna/vikunja-mcp@stable", "vikunja-mcp"]
} } }{ "$schema": "https://opencode.ai/config.json", "mcp": { "tracker": {
"type": "local",
"command": ["uvx", "--refresh-package", "vikunja-mcp",
"--from", "git+https://github.com/ufna/vikunja-mcp@stable", "vikunja-mcp"],
"enabled": true
} } }5. Teach the agent the process — vikunja-mcp install-skill installs the packaged
tracker skill (queue discipline, when to escalate, what a worklog owes a reviewer) for both
Claude Code and opencode. For Claude Code it also provisions a conditional SessionStart
hook so that inside a tracker-configured project a bare /loop drains the queue instead of
falling back to the generic "don't start work on your own" default. Outside such a project
the hook emits nothing.
Then run the loop. /loop 10m for unattended work, plain /loop when you're watching.
The twelve tools
Tool | Gate / behavior |
| One thing, in order: your active Design/Build card (including one bounced back from Your Call), then a Queue card already assigned to you, then a card in Review awaiting an independent verdict, then the top free Queue card. Never offers Backlog, a |
| Queue → Design only, and only under the WIP limit. Assign-then-verify: it assigns you, re-reads the card, and backs off if someone else won the same window. |
| The dossier: description, stage, assignees, labels, attachments, full comment thread. |
| A progress note on the card. |
|
|
|
|
| Design/Build → Your Call, keeping your assignment. Posts the question and, if configured, pings a webhook. |
| For external blockers (no access, a dependency missing, someone else's service down). Unassigns you, adds |
| Splits your own oversized task into ≥2 Queue subtasks linked to the parent; the parent becomes an |
| Files an out-of-scope finding into Backlog for human triage — never straight into Queue. Optionally linked to the card you found it on. |
| Attaches a local file — typically a screenshot of the finished work — so the reviewer can see the result. Journals itself on the card. |
| Returns a path to read, not base64, so a screenshot never bloats the agent's context. |
Beyond the tools
Three commands round out the loop; none of them speak MCP, and the SDK is imported lazily so they don't pay for it.
vikunja-mcp claimable — one JSON line answering "is there claimable work for this token
right now?", exit 0 if the check ran. It calls the real next_task(), so it cannot drift from
the gates, and it is read-only by contract. Built for a supervisor that would otherwise boot a
paid agent session every poll tick just to discover there was nothing to do.
vikunja-mcp workspace <id> — a per-task git worktree on a throwaway task/<id> branch,
so several agents can drain the queue in parallel without fighting over one checkout.
--release pushes and cleans up; --gc reaps orphans and fast-forwards your main checkout.
Its safety rule is one line: push OK → remove, push FAIL → keep. Dirty, unpushed or
unreachable work is reported, never destroyed. (One real exception, documented rather than
papered over: git-ignored files are invisible to the dirty check. Carry screenshots out of
the worktree before you release it — see the dossier.)
vikunja-mcp setup / install-skill — idempotent board reconcile, and the agent-facing
skill install described above. Both are safe to re-run; the MCP server also self-heals the
installed skill on start, so a moving stable refreshes it automatically.
Configuration
Four layers, highest priority first:
Environment —
VIKUNJA_URL,VIKUNJA_TOKEN,VIKUNJA_PROJECT_ID,VIKUNJA_NOTIFY_WEBHOOK.vikunja-mcp.env— repo-localKEY=VALUEfile beside the toml, gitignored. The per-project token for a machine that works across several repos..vikunja-mcp.toml— committed, found by walking up from the cwd. Safe to commit because it holds no secret.~/.config/vikunja-mcp/env— the usual home for a personalVIKUNJA_TOKEN(chmod 600).
Two rules make that split matter, and they run in opposite directions:
A secret is never read from the toml. Not the token, not the webhook URL. So the committed file cannot leak one even by accident.
Team policy is never read from the environment.
wip_limit,require_review_independenceandlanguageare toml-only, because they describe how the project works, not which machine you're on. Unset,wip_limitis 3 — not "unlimited";wip_limit = 0is a config error, because "no limit" is deliberately not expressible. Unset,languageis"en", and an unrecognised value is a config error for the same reason.
worktree_root sits on the machine side of that line, so there the environment does win.
language governs more than the tool's own output. The spec, the worklog and the review report
are the bulk of a card's text and the tool does not write them — the agent does — so the value
also rides in every next_task response, and the packaged rulebook tells the agent to write in
it. What it never touches is the comment markers ([worklog], [review], …): two of them are
matched with startswith to decide whether a card is offered for review, so they are frozen in
every language.
Full reasoning, including why the WIP limit gates one transition rather than policing a count: docs/dossier/config.md.
Releases
Consumers subscribe to the moving stable branch. Every green push to main auto-bumps the
patch version, tags vX.Y.Z, and moves stable onto it — so a fix reaches every consuming
repo at their next session start, with no PR bots and no per-repo version bumps. Immutable
tags remain the history and the rollback points:
git branch -f stable vX.Y.Z && git push -f origin stable # rollback to a known-good tagMinor and major bumps are a hand-edited commit; CI resumes auto-patching from the new baseline. docs/dossier/releases.md has the race analysis behind the atomic push and the forward-only channel.
Development
uv sync
uv run ruff check .
uv run pytest tests/unit -qIntegration tests run against a real Vikunja container and skip themselves without
VIKUNJA_TEST_URL — the recipe is in CONTRIBUTING.md, along with the
house rules that are less obvious than they look (why line length is two numbers, and why a
mutation sweep without a control round measures nothing).
Documentation
docs/ — the rules live in CLAUDE.md; the evidence lives in nine dossiers, one
per subsystem. If you are about to change a guard, its dossier is where the measurement that
put it there is written down.
License
MIT — see LICENSE.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceServer-enforced workflow discipline for AI agents. An MCP server providing persistent work items, dependency graphs, quality gates, and actor attribution. Schemas define what agents must produce — the server blocks the call if they don't. Works with any MCP-compatible client.199MIT
- AlicenseNot gradedqualityDmaintenanceA YAML-driven workflow guidance MCP server that enables AI coding agents to follow structured development workflows with real-time state tracking and progression control.5MIT
- AlicenseNot gradedqualityCmaintenanceMCP server for task management that enables AI agents to read, create, update tasks, and track work sessions, allowing agents and humans to collaborate on the same task board.27MIT
- FlicenseAqualityBmaintenanceAn agent-native workflow MCP server that enables AI agents to execute text-defined, versionable workflows with checkpointing and state management.1015
Related MCP Connectors
Control plane for autonomous software labor. Agents claim objectives over MCP with audit trail.
MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.
MCP server for secureFlows: token-free URL builders and integration-linting tools for AI agents.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/ufna/vikunja-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server