9.1 KiB
9.1 KiB
Vikunja MCP usage guide.
This MCP server is your persistent memory and project management layer,
backed by a self-hosted Vikunja instance. You are the only user. Follow
these conventions exactly so that memories stored today remain findable
in six months.
VOCABULARY
project container of tasks. One per repo, one for general memory,
one per life area. Create once, reuse forever.
task a single unit of work, note, or memory entry. Fields: title,
description (markdown), done, priority (1-5), labels,
bucket_id, created, updated.
label a reusable tag. Cross-cutting across all projects. Labels
have a numeric id that filters require.
view a saved layout for a project (list, kanban, gantt, table).
bucket a column inside a kanban view (Todo, In Progress, Done, ...).
filter a saved query recallable by id.
TAGGING RULES (MANDATORY)
Labels are the primary recall mechanism. Without discipline here,
memory becomes unsearchable noise.
1. Always namespace labels as "namespace:value". The only exceptions
are the universal workflow tags listed below.
Good: topic:postgres, kind:decision, area:homelab
Bad: postgres, decision, homelab
2. Always lowercase. "topic:Postgres" and "topic:postgres" are two
labels and will fragment recall.
3. Before creating a label, search with get__labels s=. Only
create if no match exists. Reuse is the whole point.
4. Never invent synonyms. Once "topic:postgres" exists, never create
"topic:postgresql" or "topic:pg". One canonical form per concept.
5. Tag aggressively. Every memory gets two to five labels. A decision
about Postgres replication that you discovered reading the docs
should carry: topic:postgres, topic:replication, kind:decision,
source:docs. More angles means more recall paths.
6. Cache label ids within a session. Resolve each label once, build
a local name-to-id map, stop re-resolving on every write.
CANONICAL NAMESPACES
topic: Technical subjects, tools, concepts, systems,
protocols, anything you might want to recall by
subject matter.
Examples: topic:postgres, topic:docker, topic:auth,
topic:networking, topic:dns, topic:linux, topic:irc,
topic:nginx, topic:zfs, topic:wireguard, topic:bgp,
topic:python, topic:golang, topic:bash.
kind: The shape of the memory entry. What kind of thing
is this?
Examples: kind:fact, kind:decision, kind:preference,
kind:reference, kind:snippet, kind:question,
kind:lesson, kind:idea, kind:config, kind:howto,
kind:troubleshoot, kind:workaround.
repo: Cross-reference a memory to a specific codebase.
Use ONLY in the Memory project to link a general
memory back to a repo. Do NOT tag tasks inside a
repo project with their own repo name, that is
redundant since they already live in that project.
Examples: repo:dotfiles, repo:vikunja-mcp.
area: Broader life or work domain.
Examples: area:infra, area:homelab, area:networking,
area:security, area:learning.
source: Where the information originated, when it matters.
Examples: source:docs, source:manpage, source:rfc,
source:github, source:irc, source:experiment.
status: Temporal relevance markers for things that expire.
Examples: status:current, status:outdated,
status:blocked, status:wontfix.
Add new namespaces when you genuinely need one. Keep the format
namespace:value. If a candidate namespace would only ever have one
or two entries, it probably belongs under topic: instead.
Note on topic: scope. Programming languages, protocols, tools, and
services all go under topic:. Do not create separate namespaces for
languages or tools. topic:python, topic:go, topic:bash, topic:nginx
are all correct.
The following tags are allowed un-namespaced because they are
universal workflow labels in a repo context:
bug, feature, refactor, docs, breaking.
Do not use these outside code projects.
MEMORY CONVENTIONS
One project titled "Memory" holds general long-term knowledge: facts,
decisions, preferences, references, snippets, and anything that does
not belong to a specific repo. Create it on first use if missing.
Cache its id for the rest of the session.
Every memory is a single task:
title short headline, 3 to 10 words. Treat it like a filename.
description full markdown body, arbitrarily long. This is the content.
labels two to five tags following the rules above.
priority 1-5, default 2. Reserve 4-5 for truly critical info.
Evolving memories: add comments via put__tasks_taskID_comments rather
than rewriting the description. Comments preserve the timeline.
Superseded memories: set done=true. They stay searchable but are
excluded from default "active" queries.
NEVER store secrets, credentials, tokens, API keys, or private keys.
PER REPOSITORY PROJECT CONVENTIONS
One Vikunja project per code repository. Title must match the repo name.
On first touch:
1. get__projects s= to check for an existing project
2. If missing, put__projects with {"title": "",
"description": ""}
3. Ensure workflow labels exist: bug, feature, refactor, docs, breaking
Task workflow:
- Create tasks via put__projects_id_tasks
- Every task gets a type label (bug | feature | refactor | docs)
- Use the priority field (1-5) based on how critical the issue is.
5 = drop everything, 4 = important, 3 = normal, 2 = low, 1 = trivial.
Do NOT use label-based priority. The numeric field is sufficient.
- Mark done=true when complete. Never delete. History matters.
- Record implementation notes via put__tasks_taskID_comments
Session startup: call get__tasks with
filter="project = && done = false" to see what is in flight.
FILTER SYNTAX (CRITICAL)
Operators: = != > >= < <= like in
Combinators: && (and), || (or). Parentheses for grouping.
Strings are double-quoted. Numbers and booleans are bare.
Fields: title, description, done, priority, due_date, start_date,
end_date, created, updated, labels, assignees, project, bucket_id.
LABEL FILTERS USE NUMERIC IDS, NOT NAMES.
1. Resolve each tag name to its id via get__labels s=
2. Filter: labels = 3
3. Multiple: labels in 3,5,7
(comma separated, NO brackets, NO quotes, NO spaces after commas)
Wrong: labels in ["topic:postgres"]
Wrong: labels = "topic:postgres"
Right: labels = 3
Right: labels in 3,5,7
Text search with like against title or description:
title like "postgres"
description like "replication"
Dates are RFC3339 in double quotes:
created > "2026-01-01"
due_date < "2026-04-20" && done = false
Combined examples:
project = 5 && done = false
labels = 3 && priority >= 4
(labels = 3 || labels = 5) && done = false
title like "postgres" || description like "postgres"
project = 5 && labels in 8,9 && done = false
WRITE WORKFLOW (STORING A NEW MEMORY)
1. Decide the tag set. Aim for 2 to 5 labels.
2. For each tag, call get__labels s=. If missing, create with
put__labels using a hex_color by namespace:
topic=3b82f6 kind=8b5cf6 repo=10b981
area=f59e0b source=6b7280 status=ef4444
Cache ids for the session.
3. Resolve the Memory project id once via get__projects s=Memory.
4. Create the task via put__projects_id_tasks with
{title, description, priority}.
5. Attach each label via put__tasks_task_labels with {"label_id": }.
6. Confirm by echoing the stored title and tag set.
READ WORKFLOW (RECALLING MEMORIES)
1. Translate the question into candidate tags.
2. Resolve each tag to its id (cached when possible).
3. Build a filter: labels in 3,5,7. Add && done = false unless
historical entries are explicitly wanted.
4. Call get__tasks with the filter, per_page 5-15.
5. Zero hits? Fall back to text search:
title like "" || description like ""
6. Surface 1-3 matches concisely. Full descriptions only on request.
DEFAULTS
priority 1..5, 5 is highest. Set based on how critical the item is.
hex_color 6-char hex, no leading hash
done false by default
per_page keep <= 20 unless a full dump is requested
timezone UTC unless specified otherwise
SAFETY
- Always check-or-create for projects and labels. A duplicate Memory
project splits the memory store and is a critical failure.
- Confirm before destructive calls (delete, bulk update, label removal)
when the target is ambiguous.
- Verify ids by reading first when intent is vague.
- Never store secrets, credentials, tokens, or private keys.
- Security, password, token, migration, and test-fixture endpoints are
not exposed by this MCP.