{"id":35094236,"url":"https://github.com/democratize-technology/vikunja-mcp","last_synced_at":"2026-01-16T10:37:06.547Z","repository":{"id":296210150,"uuid":"990842173","full_name":"democratize-technology/vikunja-mcp","owner":"democratize-technology","description":"Model Context Protocol server for Vikunja task management. Enables AI assistants to interact with Vikunja instances via MCP.","archived":false,"fork":false,"pushed_at":"2026-01-11T00:44:55.000Z","size":979,"stargazers_count":40,"open_issues_count":8,"forks_count":16,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-11T08:26:42.910Z","etag":null,"topics":["ai-tools","mcp","model-context-protocol","productivity","task-management","typescript","vikunja"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/democratize-technology.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY_IMPLEMENTATION.md","support":null,"governance":null,"roadmap":"docs/ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-05-26T18:12:33.000Z","updated_at":"2026-01-11T00:45:02.000Z","dependencies_parsed_at":"2025-09-04T02:15:00.045Z","dependency_job_id":"8574185d-f10a-47c6-82d9-52ef30cf8e23","html_url":"https://github.com/democratize-technology/vikunja-mcp","commit_stats":null,"previous_names":["democratize-technology/vikunja-mcp"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/democratize-technology/vikunja-mcp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/democratize-technology%2Fvikunja-mcp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/democratize-technology%2Fvikunja-mcp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/democratize-technology%2Fvikunja-mcp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/democratize-technology%2Fvikunja-mcp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/democratize-technology","download_url":"https://codeload.github.com/democratize-technology/vikunja-mcp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/democratize-technology%2Fvikunja-mcp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28478050,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-16T06:30:42.265Z","status":"ssl_error","status_checked_at":"2026-01-16T06:30:16.248Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-tools","mcp","model-context-protocol","productivity","task-management","typescript","vikunja"],"created_at":"2025-12-27T15:04:24.314Z","updated_at":"2026-01-16T10:37:06.538Z","avatar_url":"https://github.com/democratize-technology.png","language":"TypeScript","funding_links":[],"categories":["📚 Projects (1974 total)"],"sub_categories":["MCP Servers"],"readme":"# Vikunja MCP Server\n\nA Model Context Protocol (MCP) server that enables AI assistants to interact with Vikunja task management instances.\n\n## Features\n\n- **Subcommand-based tools** for intuitive AI interactions\n- **Session-based authentication** with automatic token management\n- **Full task management** operations implemented\n- **Complete project management** with CRUD operations\n- **Label management** for organizing tasks\n- **Team operations** for collaboration (get/update/members limited by API)\n- **User management** with settings and search\n- **Webhook management** for project automation\n- **Batch import** tasks from CSV or JSON files\n- **Input validation** for dates, IDs, and hex colors\n- **Efficient diff-based updates** for assignees\n- **TypeScript with strict mode** for type safety\n- **Comprehensive error handling** with typed errors and centralized utilities\n- **Production-ready retry logic** with opossum circuit breaker for resilience\n- **Enhanced security** with Zod-based input validation and DoS protection\n- **Rate limiting protection** against DoS attacks with configurable limits\n- **Memory protection** with pagination limits and usage monitoring\n- **Simplified architecture** with 90% code reduction for maintainability\n\n## 🚀 Major Architectural Improvements (v0.2.0)\n\nThis release represents a **massive architectural simplification** that eliminates technical debt while enhancing security and reliability:\n\n### Storage Architecture Refactoring (90% Code Reduction)\n- **Before**: 33 files, 9,803 lines of over-engineered storage system\n- **After**: 4 files, essential functionality only\n- **Eliminated**: Complex orchestrators, health monitors, statistics tracking, migration systems\n- **Result**: Same external API with dramatically improved maintainability\n\n### Zod-Based Filter System (850+ Lines Removed)\n- **Before**: Custom tokenizer, parser, and validator with security vulnerabilities\n- **After**: Secure Zod schema validation with production-ready parsing\n- **Enhanced**: DoS protection, input sanitization, and comprehensive error handling\n- **Result**: Faster parsing, better security, and enterprise-grade reliability\n\n### Production-Ready Retry System (580+ Lines Replaced)\n- **Before**: Custom retry logic with maintenance overhead\n- **After**: Battle-tested opossum circuit breaker library\n- **Features**: Circuit breaker state sharing, automatic recovery, comprehensive monitoring\n- **Result**: Production resilience with battle-tested patterns\n\n### Zero Breaking Changes\nAll improvements maintain **100% backward compatibility** with existing implementations while providing enhanced reliability and security.\n\n## Requirements\n\n- Node.js 20+ (LTS versions only)\n- Vikunja instance with API access\n- API token (starting with `tk_`) or JWT token for authentication\n\n## Installation\n\n### Option 1: Install from NPM (Recommended)\n\nThe easiest way to use vikunja-mcp is through npx in your Claude Desktop or other MCP-compatible client configuration:\n\n```json\n{\n  \"vikunja\": {\n    \"command\": \"npx\",\n    \"args\": [\"-y\", \"@democratize-technology/vikunja-mcp\"],\n    \"env\": {\n      \"VIKUNJA_URL\": \"https://your-vikunja-instance.com/api/v1\",\n      \"VIKUNJA_API_TOKEN\": \"your-api-token\"\n    }\n  }\n}\n```\n\n### Option 2: Local Development\n\nFor development or customization:\n\n```bash\ngit clone https://github.com/democratize-technology/vikunja-mcp.git\ncd vikunja-mcp\nnpm install\nnpm run build\n```\n\nThen configure your MCP client:\n\n```json\n{\n  \"vikunja\": {\n    \"command\": \"node\",\n    \"args\": [\"/path/to/vikunja-mcp/dist/index.js\"],\n    \"env\": {\n      \"VIKUNJA_URL\": \"https://your-vikunja-instance.com/api/v1\",\n      \"VIKUNJA_API_TOKEN\": \"your-api-token\"\n    }\n  }\n}\n```\n\n## Configuration\n\n### Logging Configuration\n\nThe server includes a structured logging system. Configure it via environment variables:\n\n```bash\n# Enable debug logging (default: false)\nDEBUG=true\n\n# Set specific log level (error, warn, info, debug)\n# If not set, defaults to 'info' (or 'debug' if DEBUG=true)\nLOG_LEVEL=debug\n```\n\nLog output includes timestamps and log levels:\n```\n[2025-05-25T17:00:00.000Z] [INFO] Vikunja MCP server started\n[2025-05-25T17:00:00.100Z] [DEBUG] Executing tasks tool { subcommand: 'list', args: {...} }\n```\n\nAll logs are written to stderr to keep stdout reserved for MCP protocol communication.\n\n## Authentication Methods\n\nThe Vikunja MCP server supports two authentication methods, each with different capabilities:\n\n### API Token Authentication (Default)\n\nAPI tokens are the standard authentication method for Vikunja:\n\n- **How to obtain:** Go to Vikunja Settings → API Tokens → Create new token\n- **Token format:** Starts with `tk_` (e.g., `tk_abc123def456`)\n- **Capabilities:** Full access to tasks, projects, labels, teams, and webhooks\n- **Limitations:** Cannot access user-specific endpoints (user profile, settings, export)\n- **Best for:** Automation, CI/CD, and general task management\n\n### JWT Authentication (Advanced)\n\nJWT (JSON Web Token) authentication provides full access to all Vikunja endpoints:\n\n- **How to obtain:** Extract from your browser session (see instructions below)\n- **Token format:** Long string starting with `eyJ` (standard JWT format)\n- **Capabilities:** Full access to all endpoints including user management and export\n- **Limitations:** Tokens expire (typically after 24 hours)\n- **Best for:** User management, data export, and operations requiring user context\n\n#### How to Extract Your JWT Token\n\n1. **Log into Vikunja** in your web browser\n2. **Open Developer Tools** (F12 or right-click → Inspect)\n3. **Go to the Application/Storage tab**\n4. **Find the JWT token:**\n   - Look in Local Storage → your Vikunja domain\n   - Find the key named `token` or similar\n   - The value is your JWT token\n5. **Copy the entire token value** (it's quite long)\n\n#### Using JWT Authentication\n\n```typescript\n// Connect with JWT token - automatically detected!\nvikunja_auth.connect({\n  apiUrl: \"https://your-vikunja-instance.com/api/v1\",\n  apiToken: \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\"\n})\n```\n\n**Important Notes:**\n- JWT tokens expire; you'll need to extract a new one when it expires\n- Token type is automatically detected based on format (no flag needed)\n- Some tools (users, export) are only available with JWT authentication\n\n## Quick Start\n\n1. **Set up authentication (if not using environment variables):**\n   ```typescript\n   vikunja_auth.connect({\n     apiUrl: \"https://your-vikunja-instance.com/api/v1\",\n     apiToken: \"your-api-token\"\n   })\n   ```\n\n2. **Create your first task:**\n   ```typescript\n   vikunja_tasks.create({\n     projectId: 1,\n     title: \"My first task via MCP!\"\n   })\n   ```\n\n3. **List all your tasks:**\n   ```typescript\n   vikunja_tasks.list({ allProjects: true })\n   ```\n\n## Usage\n\nThe MCP server exposes tools with subcommands. All operations require authentication first (either via environment variables or manual connection).\n\n### Authentication\n\n```typescript\n// Connect with API token (automatically detected)\nvikunja_auth.connect({\n  apiUrl: \"https://your-vikunja-instance.com/api/v1\",\n  apiToken: \"tk_your-api-token\"\n})\n\n// Connect with JWT token (automatically detected, enables additional tools: users, export)\nvikunja_auth.connect({\n  apiUrl: \"https://your-vikunja-instance.com/api/v1\",\n  apiToken: \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\"\n})\n\n// Check authentication status\nvikunja_auth.status()\n\n// Disconnect and clean up resources\nvikunja_auth.disconnect()\n```\n\n### Task Management Examples\n\n```typescript\n// List all tasks across all projects\nvikunja_tasks.list({ allProjects: true })\n\n// List tasks for a specific project with pagination\nvikunja_tasks.list({\n  projectId: 1,\n  page: 1,\n  perPage: 20,\n  sort: \"due_date\"\n})\n\n// List tasks with filters (high priority, not done)\nvikunja_tasks.list({\n  filter: \"(priority \u003e= 4 \u0026\u0026 done = false)\"\n})\n\n// List tasks with simple filter\nvikunja_tasks.list({\n  filter: \"priority \u003e= 3\"\n})\n\n// List tasks with complex filter conditions\nvikunja_tasks.list({\n  filter: \"(priority \u003e= 3 \u0026\u0026 priority \u003c= 5) || (done = true \u0026\u0026 updated \u003e '2024-01-01')\"\n})\n\n// Combine filter with search\nvikunja_tasks.list({\n  filter: \"priority \u003e= 4\",\n  search: \"urgent\"\n})\n\n// Create a new task with labels and assignees\nvikunja_tasks.create({\n  projectId: 1,\n  title: \"Complete documentation\",\n  description: \"Update README with examples\",\n  dueDate: \"2024-12-31T23:59:59Z\",\n  priority: 3,\n  labels: [1, 2],      // Label IDs\n  assignees: [1, 3]    // User IDs\n})\n\n// Create a recurring task (repeats every week)\nvikunja_tasks.create({\n  projectId: 1,\n  title: \"Weekly team meeting\",\n  description: \"Sync up with the team\",\n  dueDate: \"2024-12-01T10:00:00Z\",\n  repeatAfter: 7,      // Number of units\n  repeatMode: \"day\"    // Unit: \"day\", \"week\", \"month\", or \"year\"\n})\n\n// Create a monthly recurring task\nvikunja_tasks.create({\n  projectId: 1,\n  title: \"Monthly report\",\n  repeatAfter: 1,\n  repeatMode: \"month\"\n})\n\n// Get detailed information about a task\nvikunja_tasks.get({ id: 123 })\n\n// Update a task (partial updates supported)\nvikunja_tasks.update({\n  id: 123,\n  done: true,\n  priority: 5\n})\n\n// Update recurring settings on an existing task\nvikunja_tasks.update({\n  id: 123,\n  repeatAfter: 14,     // Change to bi-weekly\n  repeatMode: \"day\"\n})\n\n// Update task assignees (uses efficient diff-based approach)\nvikunja_tasks.update({\n  id: 123,\n  assignees: [1, 2, 4]  // Only adds/removes differences\n})\n\n// Delete a task\nvikunja_tasks.delete({ id: 123 })\n\n// Bulk assign users to a task\nvikunja_tasks.assign({\n  id: 123,\n  assignees: [2, 3, 4]\n})\n\n// Remove users from a task\nvikunja_tasks.unassign({\n  id: 123,\n  assignees: [2, 4]  // Removes only these users\n})\n\n// List all assignees for a task\nvikunja_tasks.list-assignees({ id: 123 })\n\n// Add a comment to a task\nvikunja_tasks.comment({\n  id: 123,\n  comment: \"This task is now complete!\"\n})\n\n// List all comments on a task\nvikunja_tasks.comment({ id: 123 })\n\n// Create a task relation (e.g., subtask, blocking, related)\nvikunja_tasks.relate({\n  id: 123,\n  otherTaskId: 124,\n  relationKind: \"subtask\"  // 124 is a subtask of 123\n})\n\n// Available relation kinds:\n// - subtask: Other task is a subtask of this task\n// - parenttask: Other task is the parent of this task\n// - related: Tasks are related\n// - duplicateof: This task is a duplicate of the other\n// - duplicates: Other task is a duplicate of this one\n// - blocking: This task blocks the other\n// - blocked: This task is blocked by the other\n// - precedes: This task precedes the other\n// - follows: This task follows the other\n// - copiedfrom: This task was copied from the other\n// - copiedto: Other task was copied from this one\n\n// Remove a task relation\nvikunja_tasks.unrelate({\n  id: 123,\n  otherTaskId: 124,\n  relationKind: \"subtask\"\n})\n\n// Get all relations for a task\nvikunja_tasks.relations({ id: 123 })\n\n// Add a reminder to a task\nvikunja_tasks.add-reminder({\n  id: 123,\n  reminderDate: \"2024-12-25T10:00:00Z\"\n})\n\n// List all reminders for a task\nvikunja_tasks.list-reminders({ id: 123 })\n\n// Remove a specific reminder from a task\nvikunja_tasks.remove-reminder({\n  id: 123,\n  reminderId: 1\n})\n\n// Bulk create multiple tasks at once (max 100)\nvikunja_tasks.bulk-create({\n  projectId: 1,\n  tasks: [\n    {\n      title: \"Task 1\",\n      description: \"First task\",\n      priority: 3,\n      labels: [1, 2]\n    },\n    {\n      title: \"Task 2\", \n      dueDate: \"2024-12-31T23:59:59Z\",\n      assignees: [1]\n    },\n    {\n      title: \"Weekly standup\",\n      repeatAfter: 7,\n      repeatMode: \"day\"\n    }\n  ]\n})\n\n// Bulk update multiple tasks with the same field value\nvikunja_tasks.bulk-update({\n  taskIds: [123, 124, 125],\n  field: \"done\",          // Field to update\n  value: true             // New value for all tasks\n})\n\n// Other bulk update examples\nvikunja_tasks.bulk-update({\n  taskIds: [123, 124, 125],\n  field: \"priority\",\n  value: 5\n})\n\nvikunja_tasks.bulk-update({\n  taskIds: [123, 124],\n  field: \"project_id\",\n  value: 2               // Move tasks to different project\n})\n\nvikunja_tasks.bulk-update({\n  taskIds: [123, 124, 125],\n  field: \"labels\",\n  value: [1, 3, 5]       // Set same labels on all tasks\n})\n\n// Bulk delete multiple tasks (max 100)\nvikunja_tasks.bulk-delete({\n  taskIds: [123, 124, 125]\n})\n\n// Batch import tasks from CSV or JSON\nvikunja_batch_import({\n  projectId: 1,\n  format: \"json\",\n  data: JSON.stringify([\n    {\n      title: \"Task 1\",\n      description: \"First imported task\",\n      priority: 3,\n      dueDate: \"2024-12-31T23:59:59Z\"\n    },\n    {\n      title: \"Task 2\",\n      labels: [\"bug\", \"urgent\"],  // Will look up label IDs by name\n      assignees: [\"john.doe\"]      // Will look up user IDs by username\n    }\n  ])\n})\n\n// Import from CSV with headers\nvikunja_batch_import({\n  projectId: 1,\n  format: \"csv\",\n  data: `title,description,priority,dueDate,labels,assignees\n\"Task 1\",\"Description with, comma\",3,2024-12-31T23:59:59Z,\"bug;feature\",\"john.doe\"\n\"Task 2\",\"Another task\",5,,\"urgent\",\"john.doe;jane.smith\"`\n})\n\n// Dry run to validate without creating tasks\nvikunja_batch_import({\n  projectId: 1,\n  format: \"json\",\n  data: JSON.stringify([...]),\n  dryRun: true  // Only validates, doesn't create tasks\n})\n\n// Continue on errors instead of stopping\nvikunja_batch_import({\n  projectId: 1,\n  format: \"csv\",\n  data: csvData,\n  skipErrors: true  // Skip invalid tasks and continue with valid ones\n})\n```\n\n### Data Export Examples\n\n```typescript\n// Export a project with all its data\nvikunja_export_project({\n  projectId: 1,\n  includeChildren: false  // Only export the specified project\n})\n\n// Export a project including all child projects\nvikunja_export_project({\n  projectId: 1,\n  includeChildren: true  // Recursively export child projects\n})\n\n// The export returns JSON data with the following structure:\n// {\n//   project: { ... },        // Project details\n//   tasks: [ ... ],          // All tasks in the project\n//   labels: [ ... ],         // All labels used in tasks\n//   child_projects: [ ... ], // Nested child project exports (if includeChildren: true)\n//   exported_at: \"...\",      // ISO timestamp of export\n//   version: \"1.0.0\"         // Export format version\n// }\n\n// Request a full user data export (sent via email)\nvikunja_request_user_export({\n  password: \"your-password\"  // Required for security\n})\n\n// Download a previously requested user data export\nvikunja_download_user_export({\n  password: \"your-password\"  // Required for security\n})\n```\n\n### Project Management Examples\n\n```typescript\n// List all projects\nvikunja_projects.list()\n\n// List projects with search and pagination\nvikunja_projects.list({\n  search: \"frontend\",\n  page: 1,\n  perPage: 10,\n  isArchived: false\n})\n\n// Get a specific project\nvikunja_projects.get({ id: 1 })\n\n// Create a new project\nvikunja_projects.create({\n  title: \"New Frontend Project\",\n  description: \"React-based web application\",\n  hexColor: \"#4287f5\"\n})\n\n// Update a project\nvikunja_projects.update({\n  id: 1,\n  title: \"Updated Project Name\",\n  isArchived: true\n})\n\n// Archive a project\nvikunja_projects.archive({ id: 1 })\n\n// Unarchive a project\nvikunja_projects.unarchive({ id: 1 })\n\n// Delete a project\nvikunja_projects.delete({ id: 1 })\n\n// --- Project Hierarchy Management ---\n\n// Create a child project\nvikunja_projects.create({\n  title: \"Frontend Module\",\n  description: \"React components\",\n  parentProjectId: 1,  // Will be a child of project 1\n  hexColor: \"#3498db\"\n})\n\n// Get all direct children of a project\nvikunja_projects.get-children({ id: 1 })\n// Returns: Array of projects that have parentProjectId = 1\n\n// Get complete project hierarchy as a tree\nvikunja_projects.get-tree({ id: 1 })\n// Returns: Project with nested children structure\n// {\n//   id: 1,\n//   title: \"Main Project\",\n//   children: [\n//     {\n//       id: 2,\n//       title: \"Frontend Module\",\n//       children: [\n//         { id: 4, title: \"Components\", children: [] },\n//         { id: 5, title: \"Styles\", children: [] }\n//       ]\n//     },\n//     {\n//       id: 3,\n//       title: \"Backend Module\",\n//       children: []\n//     }\n//   ]\n// }\n\n// Get breadcrumb path from root to a project\nvikunja_projects.get-breadcrumb({ id: 5 })\n// Returns: Array of projects from root to target\n// [\n//   { id: 1, title: \"Main Project\" },\n//   { id: 2, title: \"Frontend Module\" },\n//   { id: 5, title: \"Styles\" }\n// ]\n// Also includes a formatted path: \"Main Project \u003e Frontend Module \u003e Styles\"\n\n// Move a project to a new parent\nvikunja_projects.move({ \n  id: 5,              // Project to move\n  parentProjectId: 3  // New parent\n})\n// Validates against circular references and depth limits\n\n// Move a project to root level (no parent)\nvikunja_projects.move({ \n  id: 5,\n  parentProjectId: undefined\n})\n\n// --- Project Sharing ---\n\n// Create a read-only share link\nvikunja_projects.create-share({ \n  id: 1,\n  right: 0,  // 0=Read, 1=Write, 2=Admin\n  label: \"Public read-only access\"\n})\n\n// Create a password-protected share with write access\nvikunja_projects.create-share({ \n  id: 1,\n  right: 1,\n  password: \"securepassword123\",\n  label: \"Team collaboration link\"\n})\n\n// Create an expiring share link\nvikunja_projects.create-share({ \n  id: 1,\n  right: 0,\n  expires: \"2025-12-31T23:59:59Z\",\n  label: \"Temporary access until year end\"\n})\n\n// List all shares for a project\nvikunja_projects.list-shares({ id: 1 })\n\n// Get details of a specific share\nvikunja_projects.get-share({ \n  id: 1, \n  shareId: 123 \n})\n\n// Delete a share link\nvikunja_projects.delete-share({ \n  id: 1, \n  shareId: 123 \n})\n\n// Authenticate to access a shared project\nvikunja_projects.auth-share({ \n  shareHash: \"abc123def456\" \n})\n\n// Authenticate to a password-protected share\nvikunja_projects.auth-share({ \n  shareHash: \"abc123def456\",\n  password: \"securepassword123\"\n})\n```\n\n### Label Management Examples\n\n```typescript\n// List all labels\nvikunja_labels.list()\n\n// Search for labels\nvikunja_labels.list({\n  search: \"bug\",\n  page: 1,\n  perPage: 20\n})\n\n// Get a specific label\nvikunja_labels.get({ id: 1 })\n\n// Create a new label\nvikunja_labels.create({\n  title: \"Critical\",\n  description: \"Critical priority issues\",\n  hexColor: \"#ff0000\"\n})\n\n// Update a label\nvikunja_labels.update({\n  id: 1,\n  title: \"High Priority\",\n  hexColor: \"#ff6600\"\n})\n\n// Delete a label\nvikunja_labels.delete({ id: 1 })\n\n// --- Label Assignment to Tasks ---\n\n// Apply multiple labels to a task\nvikunja_tasks.apply-label({\n  id: 123,\n  labels: [1, 2, 3]  // Apply labels with IDs 1, 2, and 3\n})\n\n// Apply a single label\nvikunja_tasks.apply-label({\n  id: 123,\n  labels: [1]  // Apply just the \"research\" label\n})\n\n// Remove specific labels from a task\nvikunja_tasks.remove-label({\n  id: 123,\n  labels: [2, 3]  // Remove labels 2 and 3, keep others\n})\n\n// List all labels on a task\nvikunja_tasks.list-labels({ id: 123 })\n// Returns: Task info with detailed label data including colors and descriptions\n```\n\n### Team Management Examples\n\n```typescript\n// List all teams\nvikunja_teams.list()\n\n// Search for teams\nvikunja_teams.list({\n  search: \"frontend\",\n  page: 1,\n  perPage: 10\n})\n\n// Create a new team\nvikunja_teams.create({\n  name: \"Frontend Team\",\n  description: \"Responsible for UI/UX development\"\n})\n\n// Delete a team\nvikunja_teams.delete({ id: 1 })\n\n// Note: get, update, and members operations are not yet\n// implemented in the node-vikunja library\n```\n\n### User Management Examples\n\n\u003e ⚠️ **Known Issue**: User endpoints may fail with authentication errors even when using valid tokens. This is a known Vikunja API issue. The MCP server will provide helpful error messages when this occurs. If you encounter this issue, please contact your Vikunja server administrator.\n\n```typescript\n// Get current user information\nvikunja_users.current()\n\n// Search for users\nvikunja_users.search({\n  search: \"john\"\n})\n\n// Get current user settings\nvikunja_users.settings()\n\n// Update user settings\nvikunja_users.update-settings({\n  name: \"John Doe\",\n  language: \"en\",\n  timezone: \"America/New_York\",\n  weekStart: 1  // Monday\n})\n\n// Update notification preferences\nvikunja_users.update-settings({\n  emailRemindersEnabled: true,  // Enable email reminders for tasks\n  overdueTasksRemindersEnabled: true,  // Enable daily overdue task emails\n  overdueTasksRemindersTime: \"09:00\"  // Time to send overdue task summary\n})\n```\n\n### Webhook Management Examples\n\n```typescript\n// List all available webhook events\nvikunja_webhooks.list-events()\n// Returns: [\"task.created\", \"task.updated\", \"task.deleted\", \"task.assigned\", ...]\n\n// List webhooks for a project\nvikunja_webhooks.list({ projectId: 1 })\n\n// Create a webhook for task events\nvikunja_webhooks.create({\n  projectId: 1,\n  targetUrl: \"https://example.com/webhook\",\n  events: [\"task.created\", \"task.updated\"],\n  secret: \"my-secret-key\"  // Optional, for HMAC signing\n})\n\n// Create a webhook without secret\nvikunja_webhooks.create({\n  projectId: 1,\n  targetUrl: \"https://example.com/notifications\",\n  events: [\"task.assigned\", \"task.comment.created\"]\n})\n\n// Get a specific webhook\nvikunja_webhooks.get({\n  projectId: 1,\n  webhookId: 123\n})\n\n// Update webhook events\nvikunja_webhooks.update({\n  projectId: 1,\n  webhookId: 123,\n  events: [\"task.created\", \"task.updated\", \"task.deleted\"]\n})\n\n// Delete a webhook\nvikunja_webhooks.delete({\n  projectId: 1,\n  webhookId: 123\n})\n```\n\n### Advanced Filtering Examples\n\n```typescript\n// Create a saved filter for high priority tasks\nvikunja_filters.create({\n  name: \"High Priority Tasks\",\n  description: \"All undone tasks with priority 4 or 5\",\n  filter: \"done = false \u0026\u0026 priority \u003e= 4\",\n  isGlobal: true\n})\n\n// Alternative format using title and filters object\nvikunja_filters.create({\n  title: \"🔥 High Priority Tasks\",\n  description: \"All tasks with priority 4 or 5 that are not completed\",\n  filters: {\n    filter_by: [\"priority\"],\n    filter_value: [\"5\"],\n    filter_comparator: [\"\u003e=\"],\n    filter_concat: \"\"\n  },\n  is_favorite: true\n})\n\n// Create a filter with multiple conditions\nvikunja_filters.create({\n  title: \"Urgent \u0026 Incomplete\",\n  filters: {\n    filter_by: [\"priority\", \"done\"],\n    filter_value: [\"3\", \"false\"],\n    filter_comparator: [\"\u003e=\", \"=\"],\n    filter_concat: \"\u0026\u0026\"\n  }\n})\n\n// Create a project-specific filter\nvikunja_filters.create({\n  name: \"This Week's Tasks\",\n  filter: \"dueDate \u003e= now \u0026\u0026 dueDate \u003c now+7d\",\n  projectId: 1,\n  isGlobal: false\n})\n\n// List all saved filters\nvikunja_filters.list()\n\n// List filters for a specific project\nvikunja_filters.list({ projectId: 1 })\n\n// Apply a saved filter to task listing\nvikunja_tasks.list({\n  filterId: \"550e8400-e29b-41d4-a716-446655440000\"\n})\n\n// Build a filter programmatically\nvikunja_filters.build({\n  conditions: [\n    { field: \"done\", operator: \"=\", value: false },\n    { field: \"priority\", operator: \"\u003e=\", value: 3 },\n    { field: \"assignees\", operator: \"in\", value: [\"user1\", \"user2\"] }\n  ],\n  groupOperator: \"\u0026\u0026\"\n})\n// Returns: { filter: \"(done = false \u0026\u0026 priority \u003e= 3 \u0026\u0026 assignees in user1, user2)\", valid: true }\n\n// Update an existing filter\nvikunja_filters.update({\n  id: \"550e8400-e29b-41d4-a716-446655440000\",\n  name: \"Critical Tasks\",\n  filter: \"done = false \u0026\u0026 priority = 5\"\n})\n\n// Validate a filter string\nvikunja_filters.validate({\n  filter: \"done = false \u0026\u0026 priority \u003e= 3\"\n})\n// Returns: { valid: true, errors: [] }\n```\n\n#### Filter Syntax Reference\n\nThe Vikunja filter syntax supports SQL-like queries with the following:\n\n**Fields:**\n- `done` - Task completion status (boolean)\n- `priority` - Task priority (1-5)\n- `percentDone` - Completion percentage (0-100)\n- `dueDate` - Task due date\n- `assignees` - Task assignees\n- `labels` - Associated labels\n- `created` - Task creation time\n- `updated` - Task update time\n\n**Operators:**\n- Comparison: `=`, `!=`, `\u003e`, `\u003e=`, `\u003c`, `\u003c=`\n- Pattern matching: `like` (uses `%` wildcard)\n- List matching: `in`, `not in`\n\n**Date Math:**\n- `now` - Current time\n- `now+24h` - 24 hours from now\n- `now-7d` - 7 days ago\n- `now/d` - Start of current day\n- Supports: s (seconds), m (minutes), h (hours), d (days), w (weeks), M (months), y (years)\n\n**Examples:**\n- `priority = 4`\n- `dueDate \u003c now`\n- `done = false \u0026\u0026 priority \u003e= 3`\n- `assignees in user1, user2`\n- `dueDate \u003e= now \u0026\u0026 dueDate \u003c now+7d`\n- `title like \"%urgent%\"`\n\n**Smart Hybrid Filtering:** This MCP server implements an intelligent hybrid filtering approach that combines server-side and client-side filtering for optimal performance and reliability:\n- **Primary**: Attempts server-side filtering first for maximum performance\n- **Fallback**: Falls back to client-side filtering if server-side filtering fails or is unavailable\n- **Transparent**: Same filter syntax works regardless of which method is used\n- **Optimized**: Includes memory protection with pagination limits to prevent unbounded loading\n- **Metadata**: Response includes filtering method used (`serverSideFiltering` or `clientSideFiltering`)\n- **Performance**: Server-side filtering significantly reduces network traffic and processing time\n\n## Response Format\n\nAll operations in the Vikunja MCP server follow a standardized response format for consistency and predictability:\n\n```typescript\ninterface StandardResponse {\n  success: boolean;\n  operation: string;      // The operation performed (e.g., 'create', 'update', 'list')\n  message?: string;       // Human-readable description of the result\n  data?: any;            // The primary data returned (task, project, label, etc.)\n  metadata?: {\n    timestamp: string;    // ISO 8601 timestamp of the operation\n    [key: string]: any;  // Additional operation-specific metadata\n  };\n}\n```\n\n### Response Examples\n\n**Success:**\n```json\n{\n  \"success\": true,\n  \"operation\": \"create\",\n  \"message\": \"Task created successfully\",\n  \"data\": { \"id\": 123, \"title\": \"Complete documentation\" },\n  \"metadata\": { \"timestamp\": \"2025-05-25T12:00:00Z\" }\n}\n```\n\n**Error:**\n```json\n{\n  \"success\": false,\n  \"operation\": \"update\",\n  \"message\": \"Task not found\",\n  \"error\": { \"code\": \"TASK_NOT_FOUND\", \"details\": \"No task exists with ID 999\" }\n}\n```\n\nThis standardized format ensures:\n- **Consistency**: All tools return responses in the same structure\n- **Predictability**: Clients always know what fields to expect\n- **Debugging**: Metadata provides context for troubleshooting\n- **Error Handling**: Clear error information with codes and messages\n\n## Available Tools\n\n### Authentication\n- `vikunja_auth` - Authentication management\n  - `connect` - Initialize connection with API token\n  - `status` - Check authentication status\n  - `refresh` - Refresh authentication token\n\n### Task Management ✅\n- `vikunja_tasks` - Task operations (fully implemented)\n  - `list` - List tasks with filters\n    - Filter by project or get all tasks\n    - Support for pagination, search, sorting\n    - Filter by completion status\n    - Apply saved filters with `filterId` parameter\n  - `create` - Create a new task\n    - Required: title, projectId\n    - Optional: description, dueDate, priority, labels, assignees\n    - Validates date format (ISO 8601) and IDs\n  - `get` - Get task details by ID\n  - `update` - Update existing task\n    - Supports partial updates\n    - Can update title, description, dueDate, priority, done status\n    - Can update labels and assignees (uses efficient diff-based approach)\n  - `delete` - Delete a task by ID\n  - `assign` - Bulk assign users to tasks\n  - `unassign` - Remove users from tasks\n  - `comment` - List or add comments to tasks\n  - `bulk-update` - Update multiple tasks at once\n    - Required: taskIds array, field name, value\n    - Supported fields: done, priority, due_date, project_id, assignees, labels\n    - Validates field types and values\n    - ⚠️ Performance: Makes API calls to fetch each updated task\n  - `bulk-delete` - Delete multiple tasks at once\n    - Required: taskIds array\n    - Returns deleted task details for confirmation\n    - Handles partial failures gracefully\n    - ⚠️ Performance: Makes individual delete calls for each task\n    - Recommended: Process in batches of 20 or fewer tasks\n  - `attach` - Not implemented (file handling not available in MCP)\n\n### Batch Import ✅\n- `vikunja_batch_import` - Import multiple tasks from CSV or JSON (fully implemented)\n  - Required: projectId, format ('csv' or 'json'), data\n  - Optional: skipErrors (continue on errors), dryRun (validate only)\n  - **Batch Size Limit**: Maximum 100 tasks per import\n  - **CSV Format**:\n    - Requires header row with field names\n    - Supports quoted values and escaped quotes\n    - Fields: title, description, priority, dueDate, labels, assignees\n    - Labels and assignees as semicolon-separated values (semicolons used to avoid conflicts with CSV commas)\n  - **JSON Format**:\n    - Array of task objects\n    - Same fields as CSV, plus direct support for arrays\n  - **Features**:\n    - Automatic label lookup by name\n    - Automatic user lookup by username\n    - Validation before creation\n    - Detailed error reporting\n    - Dry run mode for testing\n    - Skip errors option for partial imports\n\n### Project Management ✅\n- `vikunja_projects` - Project operations (fully implemented)\n  - `list` - List all projects with filters\n    - Support for pagination and search\n    - Filter by archived status\n  - `get` - Get project details by ID\n  - `create` - Create new project\n    - Required: title\n    - Optional: description, parentProjectId, isArchived, hexColor (format: #RRGGBB)\n    - Validates parent project hierarchy depth (max 10 levels)\n  - `update` - Update existing project\n    - Supports partial updates\n    - Can update all project fields including hexColor (format: #RRGGBB)\n    - Validates parent project hierarchy depth when changing parent\n  - `delete` - Delete a project by ID\n  - `archive` - Archive a project\n  - `unarchive` - Unarchive a project\n  - **Hierarchy Management** (New!)\n    - `get-children` - List direct children of a project\n    - `get-tree` - Get complete project hierarchy as a tree\n    - `get-breadcrumb` - Get path from root to a project\n    - `move` - Move a project to a new parent\n      - Validates against circular references\n      - Enforces maximum depth of 10 levels\n  - **Project Sharing**\n    - `create-share` - Create share link with permissions\n    - `list-shares` - List all shares for a project\n    - `get-share` - Get share details\n    - `delete-share` - Remove a share link\n    - `auth-share` - Authenticate to access a shared project\n\n### Label Management ✅\n- `vikunja_labels` - Label operations (fully implemented)\n  - `list` - List all labels with filters\n    - Support for pagination and search\n  - `get` - Get label details by ID\n  - `create` - Create new label\n    - Required: title\n    - Optional: description, hexColor (format: #RRGGBB)\n  - `update` - Update existing label\n    - Supports partial updates\n    - Can update title, description, hexColor\n  - `delete` - Delete a label by ID\n  - `apply-label` - Apply one or more labels to a task\n    - Required: task id, labels array\n    - Supports bulk label application\n  - `remove-label` - Remove one or more labels from a task\n    - Required: task id, labels array\n    - Supports bulk label removal\n  - `list-labels` - List all labels assigned to a task\n    - Required: task id\n    - Returns detailed label information\n\n### Project Templates ✅\n- `vikunja_templates` - Template operations (fully implemented)\n  - `create` - Create a template from existing project\n    - Required: projectId, name\n    - Optional: description, tags\n    - Captures all project settings and tasks\n  - `list` - List all available templates\n    - Shows template name, tags, and author\n  - `get` - Get template details by ID\n  - `update` - Update template metadata\n    - Can update name, description, tags\n  - `delete` - Delete a template\n  - `instantiate` - Create new project from template\n    - Required: id (template ID), projectName\n    - Optional: parentProjectId, variables\n    - Supports variable substitution:\n      - `{{PROJECT_NAME}}` - The new project name\n      - `{{TODAY}}` - Current date (YYYY-MM-DD)\n      - `{{NOW}}` - Current timestamp\n      - Custom variables via the variables parameter\n    - Creates all tasks with labels from template\n\n### Team Management ✅\n- `vikunja_teams` - Team operations (partially implemented)\n  - `list` - List all teams with filters\n    - Support for pagination and search\n  - `create` - Create new team\n    - Required: name\n    - Optional: description\n  - `delete` - Delete a team by ID (with fallback API support)\n  - `get` - Not yet implemented in node-vikunja\n  - `update` - Not yet implemented in node-vikunja\n  - `members` - Not yet implemented in node-vikunja\n\n### User Management ✅\n- `vikunja_users` - User operations (fully implemented) **[Requires JWT authentication]**\n  - `current` - Get current authenticated user info\n  - `search` - Search for users\n    - Optional: search query, pagination\n  - `settings` - Get current user settings\n  - `update-settings` - Update user settings\n    - Optional: name, language, timezone, weekStart, frontendSettings\n  - **Note:** User operations require JWT authentication. When using API token authentication, these tools will not be available.\n\n### Webhook Management ✅\n- `vikunja_webhooks` - Webhook operations for project automation (fully implemented)\n  - `list-events` - Get all available webhook event types\n  - `list` - List webhooks for a project\n    - Required: projectId\n  - `get` - Get a specific webhook\n    - Required: projectId, webhookId\n  - `create` - Create a new webhook\n    - Required: projectId, targetUrl, events (array)\n    - Optional: secret (for HMAC signing)\n    - **Note**: Events are validated against available event types\n  - `update` - Update webhook events\n    - Required: projectId, webhookId, events (array)\n    - **Note**: Events are validated against available event types\n  - `delete` - Delete a webhook\n    - Required: projectId, webhookId\n  \n  **Event Validation**: When creating or updating webhooks, the provided events are automatically validated against the list of available events from the API. Invalid events will result in a clear error message showing which events are invalid and listing all valid options. Valid events are cached for 5 minutes to improve performance.\n\n### Filter Management ✅\n- `vikunja_filters` - Advanced filtering for tasks (fully implemented)\n  - `list` - List saved filters\n    - Optional: projectId (for project-specific filters), global flag\n  - `get` - Get a specific filter by ID\n  - `create` - Create a new saved filter\n    - Required: name, filter (query string)\n    - Optional: description, projectId, isGlobal\n  - `update` - Update an existing filter\n    - Required: id\n    - Optional: name, description, filter, projectId, isGlobal\n  - `delete` - Delete a saved filter\n  - `build` - Build a filter string from conditions\n    - Required: conditions array\n    - Optional: groupOperator (\u0026\u0026, ||)\n  - `validate` - Validate a filter string\n  \n  **Note:** Saved filters are currently stored in memory and will be lost when the MCP server restarts. For production use, consider implementing persistent storage.\n\n### Data Export ✅\n\n\u003e **⚠️ WARNING: Memory Usage**  \n\u003e Export operations load entire project hierarchies into memory. For very large projects with thousands of tasks or deeply nested structures, this may consume significant memory. Consider exporting smaller projects individually.\n- `vikunja_export_project` - Export project data **[Requires JWT authentication]**\n  - **Parameters:**\n    - `projectId` (required) - ID of the project to export\n    - `includeChildren` (optional) - Include child projects recursively (default: false)\n  - **Returns:** Complete project data including tasks, labels, and metadata\n  - **Features:**\n    - Exports all tasks with full details\n    - Includes all labels used in the project\n    - Optionally includes complete child project hierarchy\n    - Circular reference detection for nested projects\n    - Export metadata includes timestamp and version\n  - **Note:** Export operations require JWT authentication. When using API token authentication, this tool will not be available.\n  \n- `vikunja_request_user_export` - Request full user data export\n  - **Parameters:**\n    - `password` (required) - User password for security verification\n  - **Returns:** Confirmation that export has been requested\n  - **Note:** You will receive an email when the export is ready\n  \n- `vikunja_download_user_export` - Download previously requested user data export\n  - **Parameters:**\n    - `password` (required) - User password for security verification\n  - **Returns:** Complete user data export\n  - **Note:** Export must be requested first via `vikunja_request_user_export`\n\n\n\n\n## Known Limitations\n\n1. **File Attachments**: The `attach` subcommand is not implemented due to MCP protocol limitations\n2. **Team Operations**: Limited functionality due to incomplete node-vikunja API support:\n   - Cannot get team by ID\n   - Cannot update team information\n   - Cannot delete teams\n   - Cannot manage team members\n3. **Pagination**: Some endpoints may not fully support pagination parameters due to API limitations\n4. **Authentication Issues**: Some Vikunja API endpoints have known authentication issues:\n   - **User endpoints**: May fail with token errors even with valid tokens (known Vikunja API limitation)\n   - **Bulk operations**: May have authentication issues with certain Vikunja API versions\n   - **Label operations**: May fail with authentication errors on some server configurations\n   - **Assignee operations**: May fail with authentication errors when creating/updating tasks with assignees\n   - The server provides detailed error messages when these issues occur, suggesting workarounds\n\n## Security \u0026 Performance Features\n\n### Security Enhancements\n- **Zod Schema Validation**: Enterprise-grade input validation with comprehensive type checking\n- **DoS Protection**: Input sanitization, length limits, and character allowlisting\n- **Credential Protection**: Automatic masking of sensitive tokens and URLs in logs and error messages\n- **Entity Resolution Service**: Robust label and user mapping with defensive error handling for malformed API responses\n- **Rate Limiting**: Configurable request rate limits and payload size restrictions to prevent DoS attacks\n- **Memory Protection**: Pagination limits and memory usage monitoring to prevent resource exhaustion\n- **Error Handling**: Structured error responses that avoid exposing sensitive system information\n\n### Performance Optimizations\n- **Hybrid Filtering**: Smart server-side filtering with client-side fallback for optimal performance\n- **Connection Pooling**: Efficient session management with automatic client caching\n- **Request Batching**: Optimized bulk operations with efficient diff-based updates\n- **Memory Management**: Automatic cleanup and pagination to handle large datasets safely\n- **Thread-Safe Client Management**: Async-only ClientContext API eliminates race conditions in concurrent scenarios\n- **Opossum Circuit Breaker**: Production-ready retry logic with automatic failure detection and recovery\n- **Simplified Storage**: In-memory filter storage with 90% reduced complexity and overhead\n\n## Configuration\n\n### Environment Variables\n\nThe server supports various configuration options through environment variables:\n\n#### Basic Configuration\n```bash\n# Vikunja instance URL (required)\nVIKUNJA_URL=https://your-vikunja-instance.com/api/v1\n\n# Authentication token (required)\nVIKUNJA_API_TOKEN=your-api-token\n\n# Enable debug logging (default: false)\nDEBUG=true\n\n# Set log level (error, warn, info, debug)\nLOG_LEVEL=debug\n```\n\n#### Security \u0026 Performance Configuration\n```bash\n# Rate limiting (default: enabled)\nRATE_LIMIT_ENABLED=true\nRATE_LIMIT_PER_MINUTE=60        # Requests per minute (default: 60)\nRATE_LIMIT_PER_HOUR=1000        # Requests per hour (default: 1000)\n\n# Request size limits (default: 1MB)\nMAX_REQUEST_SIZE=1048576        # Maximum request payload size in bytes\nMAX_RESPONSE_SIZE=10485760      # Maximum response size in bytes (default: 10MB)\n\n# Execution timeout (default: 30 seconds)\nEXECUTION_TIMEOUT=30000         # Tool execution timeout in milliseconds\n\n# Memory protection (default: enabled)\nMEMORY_PROTECTION_ENABLED=true\nMAX_TASKS_PER_REQUEST=1000      # Maximum tasks to load per request\n\n# Circuit breaker configuration (opossum)\nCIRCUIT_BREAKER_ENABLED=true    # Enable circuit breaker for API calls\nCIRCUIT_BREAKER_TIMEOUT=60000   # Circuit breaker timeout in milliseconds (default: 60s)\nCIRCUIT_BREAKER_ERRORS_THROTTLE=10 # Errors before opening circuit (default: 10)\nCIRCUIT_BREAKER_RESET_TIMEOUT=30000 # Time to wait before trying half-open state (default: 30s)\n\n# Filter security (Zod validation)\nFILTER_MAX_LENGTH=1000          # Maximum filter string length (default: 1000)\nFILTER_MAX_VALUE_LENGTH=200     # Maximum individual value length (default: 200)\n```\n\nFor detailed rate limiting configuration, see [`docs/RATE_LIMITING.md`](docs/RATE_LIMITING.md).\n\n## Roadmap\n\n- [x] ✅ **Security hardening** - Comprehensive vulnerability fixes implemented\n- [x] ✅ **Performance optimization** - Hybrid filtering and memory protection\n- [x] ✅ **Error handling** - Centralized error utilities and structured responses\n- [x] ✅ **Test coverage** - 98.91% function coverage achieved\n- [x] ✅ **Architecture simplification** - 90% code reduction with enhanced maintainability\n- [x] ✅ **Production-ready resilience** - Opossum circuit breaker and Zod validation\n- [ ] Add webhook subscriptions for real-time updates\n- [ ] Add caching for frequently accessed data\n- [ ] Add integration tests with real Vikunja instance\n- [ ] Implement persistent storage for saved filters (optional - in-memory works well)\n\n## Contributing\n\nPlease see [CONTRIBUTING.md](CONTRIBUTING.md) for development guidelines and workflow.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdemocratize-technology%2Fvikunja-mcp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdemocratize-technology%2Fvikunja-mcp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdemocratize-technology%2Fvikunja-mcp/lists"}