Skip to main content
Glama
Wosh-i
by Wosh-i
README.md
# Vikunja MCP Server

A Model Context Protocol server for managing Vikunja projects and tasks.

## Quick Start

Run directly with npx (no installation required):

```bash
npx vikunja-mcp --token YOUR_VIKUNJA_TOKEN
```

With custom Vikunja URL:

```bash
npx vikunja-mcp --url https://your-vikunja.com/api/v1 --token YOUR_TOKEN
```

Or using environment variables:

```bash
export VIKUNJA_TOKEN=your_token
export VIKUNJA_URL=https://your-vikunja.com/api/v1
npx vikunja-mcp
```

## Features

- Full CRUD operations for projects
- Full CRUD operations for tasks
- Task comments management
- Task relations (subtasks, blocking, etc.)
- Task attachments listing
- Task assignees management
- Task labels management
- Project hierarchy (epics) management

## Available Tools

### Projects

| Tool                    | Description                               |
| ----------------------- | ----------------------------------------- |
| `list_projects`         | List all projects the user has access to  |
| `get_project`           | Get a specific project by ID              |
| `create_project`        | Create a new project                      |
| `update_project`        | Update an existing project                |
| `delete_project`        | Delete a project by ID                    |
| `list_project_children` | List child projects under a project       |
| `move_project`          | Move project to different parent/position |

### Tasks

| Tool                 | Description                           |
| -------------------- | ------------------------------------- |
| `list_tasks`         | List all tasks across all projects    |
| `list_project_tasks` | List all tasks for a specific project |
| `get_task`           | Get a specific task by ID             |
| `create_task`        | Create a new task in a project        |
| `update_task`        | Update an existing task               |
| `delete_task`        | Delete a task by ID                   |

### Task State & Movement

| Tool            | Description                             |
| --------------- | --------------------------------------- |
| `complete_task` | Mark a task as done                     |
| `reopen_task`   | Reopen a completed task                 |
| `move_task`     | Move task to different project/position |

### Assignees

| Tool                   | Description                      |
| ---------------------- | -------------------------------- |
| `add_task_assignee`    | Add a user as assignee to a task |
| `remove_task_assignee` | Remove assignee from a task      |
| `list_task_assignees`  | List all assignees for a task    |

### Labels

| Tool                | Description                          |
| ------------------- | ------------------------------------ |
| `add_task_label`    | Add a label to a task                |
| `remove_task_label` | Remove a label from a task           |
| `list_task_labels`  | List all labels on a task            |
| `list_labels`       | List all available labels (globally) |

### Comments

| Tool             | Description                  |
| ---------------- | ---------------------------- |
| `list_comments`  | List all comments for a task |
| `create_comment` | Add a comment to a task      |
| `update_comment` | Update a comment             |
| `delete_comment` | Delete a comment             |

### Relations

| Tool                  | Description                         |
| --------------------- | ----------------------------------- |
| `create_relation`     | Create a relation between two tasks |
| `delete_relation`     | Delete a relation between tasks     |
| `list_task_relations` | List all relations for a task       |

### Subtasks

| Tool             | Description                            |
| ---------------- | -------------------------------------- |
| `create_subtask` | Create a subtask linked to parent task |
| `list_subtasks`  | List all subtasks for a task           |

### Attachments

| Tool                     | Description                      |
| ------------------------ | -------------------------------- |
| `list_task_attachments`  | List all attachments for a task  |
| `delete_task_attachment` | Delete an attachment from a task |

> See below for complete parameter documentation for all tools.

## Tool Reference

### Parameter Types

- **string**: Text value
- **number**: Numeric value (integer)
- **boolean**: true/false value
- **required**: This parameter must be provided
- **optional**: This parameter can be omitted

> **Note**: All ID parameters (e.g., `projectId`, `taskId`) accept both number and string values. The MCP server uses `z.coerce.number()` to automatically convert string IDs (like "123") to numbers. This means you can pass either `123` or `"123"` for any ID parameter. See [Using String IDs](#using-string-ids) for examples.

### Projects

#### list_projects

List all projects the user has access to.

- **Parameters**: None required
- **Optional**:
  - `page` (number): Page number for pagination
  - `per_page` (number): Number of items per page (default: 25)

#### get_project

Get a specific project by ID.

- **Parameters**:
  - `projectId` (number, required): The project ID

#### create_project

Create a new project.

- **Parameters**:
  - `title` (string, required): The project title
- **Optional**:
  - `description` (string): Project description
  - `hex_color` (string): Hex color code (e.g., "#FF5733")
  - `identifier` (string): Unique identifier for the project
  - `parent_project_id` (number): ID of parent project (for epics/hierarchy)
  - `is_archived` (boolean): Whether the project is archived

#### update_project

Update an existing project.

- **Parameters**:
  - `projectId` (number, required): The project ID
- **Optional**:
  - `title` (string): New title
  - `description` (string): New description
  - `hex_color` (string): New hex color code
  - `identifier` (string): New identifier
  - `parent_project_id` (number): New parent project ID
  - `is_archived` (boolean): Archive status

#### delete_project

Delete a project by ID.

- **Parameters**:
  - `projectId` (number, required): The project ID

#### list_project_children

List child projects under a project.

- **Parameters**:
  - `projectId` (number, required): The parent project ID

#### move_project

Move project to different parent or position.

- **Parameters**:
  - `projectId` (number, required): The project ID
- **Optional**:
  - `parent_project_id` (number): New parent project ID (null to remove from parent)
  - `position` (number): New position in the parent project

### Tasks

#### list_tasks

List all tasks across all projects.

- **Parameters**: None required
- **Optional**:
  - `page` (number): Page number for pagination
  - `per_page` (number): Number of items per page
  - `status` (string): Filter by status (open, done, done_lte, done_gte)
  - `priority` (number): Filter by priority
  - `due_date` (string): Filter by due date
  - `label` (string): Filter by label

#### list_project_tasks

List all tasks for a specific project.

- **Parameters**:
  - `projectId` (number, required): The project ID
- **Optional**:
  - `page` (number): Page number for pagination
  - `per_page` (number): Number of items per page

#### get_task

Get a specific task by ID.

- **Parameters**:
  - `taskId` (number, required): The task ID

#### create_task

Create a new task in a project.

- **Parameters**:
  - `projectId` (number, required): The project ID
- **Required**:
  - `task` (object): The task object
    - `title` (string, required): The task title
- **Optional**:
  - `task` (object): The task object
    - `description` (string): Task description
    - `done` (boolean): Whether task is completed
    - `due_date` (string): Due date (ISO 8601 format)
    - `start_date` (string): Start date
    - `end_date` (string): End date
    - `hex_color` (string): Task color
    - `priority` (number): Priority (1-5, where 5 is highest)
    - `percent_done` (number): Progress (0-100)
    - `repeat_after` (number): Repeat after X minutes
    - `repeat_mode` (number): Repeat mode (0=relative, 1=absolute)

#### update_task

Update an existing task.

- **Parameters**:
  - `taskId` (number, required): The task ID
  - `taskUpdates` (object, required): The task fields to update
- **Optional**:
  - `taskUpdates` (object):
    - `title` (string): New title
    - `description` (string): New description
    - `done` (boolean): Completion status
    - `due_date` (string): New due date
    - `start_date` (string): New start date
    - `end_date` (string): New end date
    - `hex_color` (string): New color
    - `priority` (number): New priority
    - `percent_done` (number): Progress (0-100)
    - `repeat_after` (number): New repeat interval
    - `repeat_mode` (number): Repeat mode (0=relative, 1=absolute)

#### delete_task

Delete a task by ID.

- **Parameters**:
  - `taskId` (number, required): The task ID

### Task State & Movement

#### complete_task

Mark a task as done.

- **Parameters**:
  - `taskId` (number, required): The task ID

#### reopen_task

Reopen a completed task.

- **Parameters**:
  - `taskId` (number, required): The task ID

#### move_task

Move task to different project or position.

- **Parameters**:
  - `taskId` (number, required): The task ID
  - `project_id` (number, required): Target project ID
- **Optional**:
  - `position` (number): New position

### Assignees

#### add_task_assignee

Add a user as assignee to a task.

- **Parameters**:
  - `taskId` (number, required): The task ID
  - `userId` (number, required): The user ID to add

#### remove_task_assignee

Remove assignee from a task.

- **Parameters**:
  - `taskId` (number, required): The task ID
  - `userId` (number, required): The user ID to remove

#### list_task_assignees

List all assignees for a task.

- **Parameters**:
  - `taskId` (number, required): The task ID

### Labels

#### add_task_label

Add a label to a task.

- **Parameters**:
  - `taskId` (number, required): The task ID
  - `label_id` (number, required): The label ID to add

#### remove_task_label

Remove a label from a task.

- **Parameters**:
  - `taskId` (number, required): The task ID
  - `label_id` (number, required): The label ID to remove

#### list_task_labels

List all labels on a task.

- **Parameters**:
  - `taskId` (number, required): The task ID

#### list_labels

List all available labels (globally).

- **Parameters**: None required
- **Optional**:
  - `project_id` (number): Filter by project ID
  - `page` (number): Page number
  - `per_page` (number): Items per page

### Comments

#### list_comments

List all comments for a task.

- **Parameters**:
  - `taskId` (number, required): The task ID
- **Optional**:
  - `page` (number): Page number
  - `per_page` (number): Items per page

#### create_comment

Add a comment to a task.

- **Parameters**:
  - `taskId` (number, required): The task ID
  - `comment` (string, required): The comment text

#### update_comment

Update a comment.

- **Parameters**:
  - `taskId` (number, required): The task ID
  - `commentId` (number, required): The comment ID
  - `comment` (string, required): New comment text

#### delete_comment

Delete a comment.

- **Parameters**:
  - `taskId` (number, required): The task ID
  - `commentId` (number, required): The comment ID to delete

### Relations

#### create_relation

Create a relation between two tasks.

- **Parameters**:
  - `taskId` (number, required): The source task ID
  - `otherTaskId` (number, required): The related task ID
  - `relationKind` (string, required): Relation type (unknown, subtask, parenttask, related, duplicateof, duplicates, blocking, blocked, precedes, follows, copiedfrom, copiedto)

#### delete_relation

Delete a relation between tasks.

- **Parameters**:
  - `taskId` (number, required): The source task ID
  - `otherTaskId` (number, required): The related task ID
  - `relationKind` (string, required): Relation type (unknown, subtask, parenttask, related, duplicateof, duplicates, blocking, blocked, precedes, follows, copiedfrom, copiedto)

#### list_task_relations

List all relations for a task.

- **Parameters**:
  - `taskId` (number, required): The task ID

### Subtasks

#### create_subtask

Create a subtask linked to parent task.

- **Parameters**:
  - `projectId` (number, required): The project ID
  - `parent_task_id` (number, required): The parent task ID
  - `task` (object, required): The subtask object
- **Required**:
  - `task` (object):
    - `title` (string, required): The subtask title
- **Optional**:
  - `task` (object):
    - `description` (string): Subtask description
    - `done` (boolean): Whether subtask is completed
    - `due_date` (string): Due date
    - `start_date` (string): Start date
    - `end_date` (string): End date
    - `hex_color` (string): Subtask color
    - `priority` (number): Priority
    - `percent_done` (number): Progress (0-100)
    - `repeat_after` (number): Repeat after X minutes
    - `repeat_mode` (number): Repeat mode (0=relative, 1=absolute)

#### list_subtasks

List all subtasks for a task.

- **Parameters**:
  - `taskId` (number, required): The parent task ID

### Attachments

#### list_task_attachments

List all attachments for a task.

- **Parameters**:
  - `taskId` (number, required): The task ID
- **Optional**:
  - `page` (number): Page number
  - `per_page` (number): Items per page

#### delete_task_attachment

Delete an attachment from a task.

- **Parameters**:
  - `taskId` (number, required): The task ID
  - `attachmentId` (number, required): The attachment ID

## Examples

### Listing Projects and Tasks

```
list my vikunja projects
```

Returns all projects you have access to.

```
list_project_tasks projectId: 1
```

Returns all tasks in project ID 1.

```
list_tasks per_page: 50
```

Lists up to 50 tasks across all projects.

### Creating Projects and Tasks

```
create_project title: "My Project" description: "A new project" hex_color: "#FF5733"
```

Creates a new project with a title, description, and color.

```
create_task projectId: 1 title: "Buy groceries" priority: 3 due_date: "2024-12-25"
```

Creates a task in project ID 1 with priority and due date.

### Managing Task State

```
complete_task taskId: 5
```

Marks task 5 as done.

```
reopen_task taskId: 5
```

Reopens task 5.

### Working with Assignees

```
add_task_assignee taskId: 3 userId: 7
```

Adds user 7 as assignee to task 3.

```
list_task_assignees taskId: 3
```

Lists all assignees for task 3.

### Comments

```
create_comment taskId: 3 comment: "This should be done by Friday"
```

Adds a comment to task 3.

### Relations

```
create_relation taskId: 1 otherTaskId: 2 relationKind: "blocking"
```

Creates a "blocks" relation from task 1 to task 2 (task 1 blocks task 2).

### Using String IDs

All ID parameters accept strings, so these are equivalent:

```
get_project projectId: 1
get_project projectId: "1"
```

This is useful when working with data from external sources:

```
list_project_tasks projectId: "123"
```

## Installation

### Prerequisites

- Node.js 18+
- npm or bun
- A Vikunja instance (self-hosted or cloud)
- Vikunja API token

### Getting a Vikunja API Token

1. Log into your Vikunja instance
2. Go to Settings → API Tokens
3. Create a new token

### Build from Source

```bash
git clone https://github.com/Wosh-i/vikunja-mcp.git
cd vikunja-mcp
npm install
npm run build
```

## OpenCode Configuration

### Option 1: Using npx (Recommended)

The easiest way to configure Vikunja MCP is using npx. Add this to your OpenCode config (`~/.config/opencode/opencode.jsonc`):

```jsonc
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "vikunja": {
      "type": "local",
      "command": ["npx", "-y", "vikunja-mcp"],
      "environment": {
        "VIKUNJA_URL": "https://your-vikunja-instance.com/api/v1",
        "VIKUNJA_TOKEN": "your-api-token-here",
      },
    },
  },
}
```

Using npx with `-y` skips the confirmation prompt and automatically downloads the package.

### Option 2: Build from Source

If you prefer to run locally without npx, build from source:

```bash
git clone https://github.com/Wosh-i/vikunja-mcp.git
cd vikunja-mcp
npm install
npm run build
```

Then configure OpenCode:

```jsonc
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "vikunja": {
      "type": "local",
      "command": ["node", "/path/to/vikunja-mcp/dist/index.js"],
      "environment": {
        "VIKUNJA_URL": "https://your-vikunja-instance.com/api/v1",
        "VIKUNJA_TOKEN": "your-api-token-here",
      },
    },
  },
}
```

### Configuration Options

| Option          | Required | Default                       | Description               |
| --------------- | -------- | ----------------------------- | ------------------------- |
| `VIKUNJA_URL`   | No       | https://try.vikunja.io/api/v1 | Your Vikunja API base URL |
| `VIKUNJA_TOKEN` | Yes      | -                             | Your Vikunja API token    |

### Environment Variables

You can also set environment variables globally in your shell:

```bash
export VIKUNJA_URL="https://your-vikunja-instance.com/api/v1"
export VIKUNJA_TOKEN="your-api-token-here"
```

Then the OpenCode config can be simpler:

```jsonc
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "vikunja": {
      "type": "local",
      "command": ["node", "/path/to/vikunja-mcp/dist/index.js"],
    },
  },
}
```

## Claude Code Desktop App Configuration

### Option 1: Using npx (Recommended)

The easiest way to configure Vikunja MCP is using npx. Add this to your Claude Code desktop config file:

**macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
**Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
**Linux:** `~/.config/Claude/claude_desktop_config.json`

```jsonc
{
  "mcpServers": {
    "vikunja": {
      "command": "npx",
      "args": ["-y", "vikunja-mcp"],
      "env": {
        "VIKUNJA_URL": "https://your-vikunja-instance.com/api/v1",
        "VIKUNJA_TOKEN": "your-api-token-here",
      },
    },
  },
}
```

Using npx with `-y` skips the confirmation prompt and automatically downloads the package.

### Option 2: Build from Source

If you prefer to run locally without npx, build from source:

```bash
git clone https://github.com/Wosh-i/vikunja-mcp.git
cd vikunja-mcp
npm install
npm run build
```

Then configure Claude Code:

**macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
**Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
**Linux:** `~/.config/Claude/claude_desktop_config.json`

```jsonc
{
  "mcpServers": {
    "vikunja": {
      "command": "node",
      "args": ["/path/to/vikunja-mcp/dist/index.js"],
      "env": {
        "VIKUNJA_URL": "https://your-vikunja-instance.com/api/v1",
        "VIKUNJA_TOKEN": "your-api-token-here",
      },
    },
  },
}
```

### Configuration Options

| Option          | Required | Default                       | Description               |
| --------------- | -------- | ----------------------------- | ------------------------- |
| `VIKUNJA_URL`   | No       | https://try.vikunja.io/api/v1 | Your Vikunja API base URL |
| `VIKUNJA_TOKEN` | Yes      | -                             | Your Vikunja API token    |

### Environment Variables

You can also set environment variables globally in your shell:

```bash
export VIKUNJA_URL="https://your-vikunja-instance.com/api/v1"
export VIKUNJA_TOKEN="your-api-token-here"
```

Then the Claude Code config can be simpler:

```jsonc
{
  "mcpServers": {
    "vikunja": {
      "command": "node",
      "args": ["/path/to/vikunja-mcp/dist/index.js"],
    },
  },
}
```

## Claude Code TUI Configuration

The Claude Code TUI (terminal user interface) uses the `claude mcp add` command to configure MCP servers.

### Option 1: Using npx (Recommended)

The easiest way to configure Vikunja MCP is using npx:

```bash
claude mcp add --transport stdio --env VIKUNJA_URL=https://your-vikunja-instance.com/api/v1 --env VIKUNJA_TOKEN=your-api-token-here vikunja -- npx -y vikunja-mcp
```

### Option 2: Build from Source

If you prefer to run locally without npx, build from source:

```bash
git clone https://github.com/Wosh-i/vikunja-mcp.git
cd vikunja-mcp
npm install
npm run build
```

Then configure Claude Code:

```bash
claude mcp add --transport stdio --env VIKUNJA_URL=https://your-vikunja-instance.com/api/v1 --env VIKUNJA_TOKEN=your-api-token-here vikunja -- /path/to/vikunja-mcp/dist/index.js
```

### Configuration Scopes

Claude Code TUI supports different scopes for MCP server configuration:

| Scope             | Config Location                     | Description                                            |
| ----------------- | ----------------------------------- | ------------------------------------------------------ |
| `user`            | `~/.claude.json`                    | Available to you across all projects                   |
| `local` (default) | `~/.claude.json` under project path | Available only in the current project                  |
| `project`         | `.mcp.json` in project root         | Shared with team members (checked into source control) |

```bash
# Add with user scope (available across all projects)
claude mcp add --transport stdio --scope user --env VIKUNJA_TOKEN=... vikunja -- npx -y vikunja-mcp

# Add with project scope (shared with team via .mcp.json)
claude mcp add --transport stdio --scope project --env VIKUNJA_TOKEN=... vikunja -- npx -y vikunja-mcp
```

### Managing MCP Servers

```bash
# List all configured servers
claude mcp list

# Get details for a specific server
claude mcp get vikunja

# Remove a server
claude mcp remove vikunja

# Within Claude Code, check server status
/mcp
```

### Configuration Options

| Option          | Required | Default                       | Description               |
| --------------- | -------- | ----------------------------- | ------------------------- |
| `VIKUNJA_URL`   | No       | https://try.vikunja.io/api/v1 | Your Vikunja API base URL |
| `VIKUNJA_TOKEN` | Yes      | -                             | Your Vikunja API token    |

### Environment Variables

You can also set environment variables globally in your shell:

```bash
export VIKUNJA_URL="https://your-vikunja-instance.com/api/v1"
export VIKUNJA_TOKEN="your-api-token-here"
```

Then the configuration is simpler:

```bash
claude mcp add --transport stdio vikunja -- npx -y vikunja-mcp
```

---

## Usage

### CLI Options

| Option    | Alias | Description               |
| --------- | ----- | ------------------------- |
| `--token` | `-t`  | Your Vikunja API token    |
| `--url`   | `-u`  | Your Vikunja API base URL |
| `--help`  | `-h`  | Show help                 |

### Using with OpenCode

After configuration, you can use Vikunja tools in OpenCode:

```
list my vikunja projects
```

```
create a project called "My Tasks" with color #FF5733
```

```
add a task titled "Buy groceries" to project "My Tasks" with priority 3
```

```
show me all tasks in the Inbox project
```

## Development

```bash
# Install dependencies
npm install

# Build
npm run build

# Run in development mode
npm run dev

# Run tests (when available)
npm test
```

## License

MIT License - see LICENSE file for details.

## Contributing

Contributions welcome! Please open an issue or pull request.

TDQS

B3.3/5.0

Scored across 33 tools

Disambiguation5/5

Every tool has a clearly distinct purpose with no ambiguity. Tools are precisely scoped to specific actions on specific resources (e.g., add_task_assignee vs. remove_task_assignee, create_task vs. update_task vs. delete_task). The descriptions reinforce this clarity, making misselection unlikely.

Naming Consistency5/5

Tool names follow a highly consistent verb_noun pattern throughout (e.g., create_project, list_tasks, update_task). All names use snake_case uniformly, and verbs are predictable (create, get, list, update, delete, add, remove, move, complete, reopen). This consistency enhances readability and predictability.

Tool Count3/5

With 33 tools, the count feels heavy for a task management server, bordering on excessive. While the tools cover many operations, a more streamlined set might improve usability. This is borderline, as it could overwhelm agents but is not extreme.

Completeness5/5

The tool surface is complete for the Vikunja task management domain. It covers full CRUD/lifecycle operations for projects, tasks, comments, attachments, labels, assignees, and relations, with no obvious gaps. Agents can perform all expected workflows without dead ends.

Maintenance

ActivityInactive
ResponsivenessNo issues