Vikunja MCP Server について
Vikunja MCP Server は、Vikunja タスク管理インスタンスを AI アシスタントから操作するための MCP サーバーです。タスク、プロジェクト、ラベル、チーム、ユーザー、Webhook を扱えます。TypeScript で実装され、入力検証には Zod を使用しています。
主な機能
- 01サブコマンド単位で構成されたツール
- 02トークン管理を伴うセッションベースの認証
- 03プロジェクト、ラベル、チームの管理
- 04Webhook の管理
- 05CSV または JSON ファイルからのタスク一括インポート
- 06opossum を用いたサーキットブレーカー型のリトライ処理
活用シーン
- 01AI アシスタントによる Vikunja タスクの検索と作成
- 02Webhook を使ったプロジェクトの自動化設定
- 03タスクデータの一括インポート
MCP 対応
このプロジェクトは MCP サーバーであり、Vikunja のタスク、プロジェクト、ラベルなどの操作を、vikunja_tasks や vikunja_projects などサブコマンド付きのツールとして MCP クライアントに公開します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
9掲載時のツール一覧 · 3 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| subcommand | enum | はい | connect | status | refresh | disconnect |
| apiUrl | string | いいえ | |
| apiToken | string | いいえ |
詳細
Vikunja MCP サーバー
AI アシスタントが Vikunja のタスク管理インスタンスとやり取りできるようにする、Model Context Protocol(MCP)サーバーです。
特徴
- 直感的に AI とやり取りできるサブコマンドベースのツール
- トークンを自動管理するセッションベースの認証
- タスク管理の全操作を実装
- CRUD 操作を備えたプロジェクト管理
- タスクを整理するためのラベル管理
- チーム操作によるコラボレーション(API の制限により、取得/更新/メンバー操作のみ)
- 設定と検索機能を備えたユーザー管理
- プロジェクトを自動化するWebhook 管理
- CSV または JSON ファイルからのタスクの一括インポート
- 日付、ID、16 進カラーコードの入力検証
- 担当者向けの効率的な差分ベースの更新
- 型安全性を確保する厳格モードの TypeScript
- 型付きエラーと一元化されたユーティリティによる包括的なエラー処理
- 回復性を高める opossum サーキットブレーカーを用いた本番環境対応のリトライロジック
- Zod ベースの入力検証と DoS 保護によるセキュリティ強化
- 設定可能な制限による DoS 攻撃へのレート制限保護
- ページネーション制限と使用状況の監視によるメモリ保護
- 保守性を高めるため、コードを 90%削減したシンプルなアーキテクチャ
🚀 主なアーキテクチャの改善(v0.2.0)
このリリースでは、技術的負債を解消しながらセキュリティと信頼性を強化する、大幅なアーキテクチャの簡素化を実施しました。
ストレージアーキテクチャのリファクタリング(コードを90%削減)
- 変更前:過剰に複雑なストレージシステムで、33ファイル、9,803行
- 変更後:4ファイルに集約し、必要な機能のみを実装
- 削除したもの:複雑なオーケストレーター、ヘルスモニター、統計追跡、移行システム
- 結果:外部 API を維持しながら、保守性を大幅に向上
Zod ベースのフィルターシステム(850行以上を削減)
- 変更前:セキュリティ上の脆弱性を含む、独自のトークナイザー、パーサー、バリデーター
- 変更後:本番環境対応の解析機能を備えた、安全な Zod スキーマ検証
- 強化内容:DoS 保護、入力のサニタイズ、包括的なエラー処理
- 結果:解析の高速化、セキュリティの向上、エンタープライズ水準の信頼性
本番環境対応のリトライシステム(580行以上を置き換え)
- 変更前:保守の負担が大きい独自のリトライロジック
- 変更後:実績のある opossum サーキットブレーカーライブラリ
- 機能:サーキットブレーカー状態の共有、自動復旧、包括的な監視
- 結果:実績のあるパターンによる、本番環境での回復性
破壊的変更なし
既存の実装との100%の後方互換性を維持しながら、信頼性とセキュリティを強化しています。
要件
- Node.js 20 以降(LTS バージョンのみ)
- API にアクセスできる Vikunja インスタンス
- 認証用の API トークン(
tk_で始まるもの)または JWT トークン
インストール
オプション 1:NPM からインストール(推奨)
vikunja-mcp を使用する最も簡単な方法は、Claude Desktop やその他の MCP 対応クライアントの設定で npx を利用することです。
{
"vikunja": {
"command": "npx",
"args": ["-y", "@democratize-technology/vikunja-mcp"],
"env": {
"VIKUNJA_URL": "https://your-vikunja-instance.com/api/v1",
"VIKUNJA_API_TOKEN": "your-api-token"
}
}
}
オプション 2:ローカル開発
開発またはカスタマイズを行う場合:
git clone https://github.com/democratize-technology/vikunja-mcp.git
cd vikunja-mcp
npm install
npm run build
次に、MCP クライアントを設定します。
{
"vikunja": {
"command": "node",
"args": ["/path/to/vikunja-mcp/dist/index.js"],
"env": {
"VIKUNJA_URL": "https://your-vikunja-instance.com/api/v1",
"VIKUNJA_API_TOKEN": "your-api-token"
}
}
}
設定
ロギングの設定
このサーバーには、構造化ロギングシステムが含まれています。環境変数を使って設定してください。
# Enable debug logging (default: false)
DEBUG=true
# Set specific log level (error, warn, info, debug)
# If not set, defaults to 'info' (or 'debug' if DEBUG=true)
LOG_LEVEL=debug
ログ出力には、タイムスタンプとログレベルが含まれます。
[2025-05-25T17:00:00.000Z] [INFO] Vikunja MCP server started
[2025-05-25T17:00:00.100Z] [DEBUG] Executing tasks tool { subcommand: 'list', args: {...} }
MCP プロトコルの通信に標準出力を使用できるよう、すべてのログは標準エラー出力に書き込まれます。
認証方式
Vikunja MCP サーバーは、機能がそれぞれ異なる2種類の認証方式に対応しています。
API トークン認証(デフォルト)
API トークンは、Vikunja の標準的な認証方法です。
- 取得方法: Vikunja の「設定」→「API トークン」→「新しいトークンを作成」に進みます
- トークン形式:
tk_で始まります(例:tk_abc123def456) - 機能: タスク、プロジェクト、ラベル、チーム、Webhook に完全にアクセスできます
- 制限事項: ユーザー固有のエンドポイント(ユーザープロフィール、設定、エクスポート)にはアクセスできません
- 最適な用途: 自動化、CI/CD、一般的なタスク管理
JWT 認証(高度)
JWT(JSON Web Token)認証を使用すると、Vikunja のすべてのエンドポイントに完全にアクセスできます。
- 取得方法: ブラウザーセッションから抽出します(手順は以下を参照)
- トークン形式:
eyJで始まる長い文字列(標準的な JWT 形式) - 機能: ユーザー管理やエクスポートを含む、すべてのエンドポイントに完全にアクセスできます
- 制限事項: トークンには有効期限があります(通常は 24 時間後)
- 最適な用途: ユーザー管理、データのエクスポート、ユーザーコンテキストが必要な操作
JWT トークンの抽出方法
- Web ブラウザーで Vikunja にログインします
- 開発者ツールを開きます(F12 または右クリック →「検証」)
- 「アプリケーション」/「ストレージ」タブに移動します
- JWT トークンを見つけます:
- 「ローカルストレージ」→ご利用の Vikunja ドメインを確認します
tokenなどの名前のキーを見つけます- その値が JWT トークンです
- トークンの値全体をコピーします(かなり長い文字列です)
JWT 認証の使用
// Connect with JWT token - automatically detected!
vikunja_auth.connect({
apiUrl: "https://your-vikunja-instance.com/api/v1",
apiToken: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
})
重要な注意事項:
- JWT トークンには有効期限があるため、期限が切れたら新しいトークンを抽出する必要があります
- トークンの種類は形式に基づいて自動的に検出されます(フラグは不要です)
- 一部のツール(ユーザー、エクスポート)は JWT 認証でのみ利用できます
クイックスタート
-
認証を設定します(環境変数を使用しない場合):
vikunja_auth.connect({ apiUrl: "https://your-vikunja-instance.com/api/v1", apiToken: "your-api-token" }) -
最初のタスクを作成します:
vikunja_tasks.create({ projectId: 1, title: "My first task via MCP!" }) -
すべてのタスクを一覧表示します:
vikunja_tasks.list({ allProjects: true })
使用方法
MCP サーバーはサブコマンドを含むツールを公開します。すべての操作では、まず認証が必要です(環境変数を使用するか、手動で接続します)。
認証
// Connect with API token (automatically detected)
vikunja_auth.connect({
apiUrl: "https://your-vikunja-instance.com/api/v1",
apiToken: "tk_your-api-token"
})
// Connect with JWT token (automatically detected, enables additional tools: users, export)
vikunja_auth.connect({
apiUrl: "https://your-vikunja-instance.com/api/v1",
apiToken: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
})
// Check authentication status
vikunja_auth.status()
// Disconnect and clean up resources
vikunja_auth.disconnect()
タスク管理の例
// List all tasks across all projects
vikunja_tasks.list({ allProjects: true })
// List tasks for a specific project with pagination
vikunja_tasks.list({
projectId: 1,
page: 1,
perPage: 20,
sort: "due_date"
})
// List tasks with filters (high priority, not done)
vikunja_tasks.list({
filter: "(priority >= 4 && done = false)"
})
// List tasks with simple filter
vikunja_tasks.list({
filter: "priority >= 3"
})
// List tasks with complex filter conditions
vikunja_tasks.list({
filter: "(priority >= 3 && priority <= 5) || (done = true && updated > '2024-01-01')"
})
// Combine filter with search
vikunja_tasks.list({
filter: "priority >= 4",
search: "urgent"
})
// Create a new task with labels and assignees
vikunja_tasks.create({
projectId: 1,
title: "Complete documentation",
description: "Update README with examples",
dueDate: "2024-12-31T23:59:59Z",
priority: 3,
labels: [1, 2], // Label IDs
assignees: [1, 3] // User IDs
})
// Create a recurring task (repeats every week)
vikunja_tasks.create({
projectId: 1,
title: "Weekly team meeting",
description: "Sync up with the team",
dueDate: "2024-12-01T10:00:00Z",
repeatAfter: 7, // Number of units
repeatMode: "day" // Unit: "day", "week", "month", or "year"
})
// Create a monthly recurring task
vikunja_tasks.create({
projectId: 1,
title: "Monthly report",
repeatAfter: 1,
repeatMode: "month"
})
// Get detailed information about a task
vikunja_tasks.get({ id: 123 })
// Update a task (partial updates supported)
vikunja_tasks.update({
id: 123,
done: true,
priority: 5
})
// Update recurring settings on an existing task
vikunja_tasks.update({
id: 123,
repeatAfter: 14, // Change to bi-weekly
repeatMode: "day"
})
// Update task assignees (uses efficient diff-based approach)
vikunja_tasks.update({
id: 123,
assignees: [1, 2, 4] // Only adds/removes differences
})
// Delete a task
vikunja_tasks.delete({ id: 123 })
// Bulk assign users to a task
vikunja_tasks.assign({
id: 123,
assignees: [2, 3, 4]
})
// Remove users from a task
vikunja_tasks.unassign({
id: 123,
assignees: [2, 4] // Removes only these users
})
// List all assignees for a task
vikunja_tasks.list-assignees({ id: 123 })
// Add a comment to a task
vikunja_tasks.comment({
id: 123,
comment: "This task is now complete!"
})
// List all comments on a task
vikunja_tasks.comment({ id: 123 })
// Create a task relation (e.g., subtask, blocking, related)
vikunja_tasks.relate({
id: 123,
otherTaskId: 124,
relationKind: "subtask" // 124 is a subtask of 123
})
// Available relation kinds:
// - subtask: Other task is a subtask of this task
// - parenttask: Other task is the parent of this task
// - related: Tasks are related
// - duplicateof: This task is a duplicate of the other
// - duplicates: Other task is a duplicate of this one
// - blocking: This task blocks the other
// - blocked: This task is blocked by the other
// - precedes: This task precedes the other
// - follows: This task follows the other
// - copiedfrom: This task was copied from the other
// - copiedto: Other task was copied from this one
// Remove a task relation
vikunja_tasks.unrelate({
id: 123,
otherTaskId: 124,
relationKind: "subtask"
})
// Get all relations for a task
vikunja_tasks.relations({ id: 123 })
// Add a reminder to a task
vikunja_tasks.add-reminder({
id: 123,
reminderDate: "2024-12-25T10:00:00Z"
})
// List all reminders for a task
vikunja_tasks.list-reminders({ id: 123 })
// Remove a specific reminder from a task
vikunja_tasks.remove-reminder({
id: 123,
reminderId: 1
})
// Bulk create multiple tasks at once (max 100)
vikunja_tasks.bulk-create({
projectId: 1,
tasks: [
{
title: "Task 1",
description: "First task",
priority: 3,
labels: [1, 2]
},
{
title: "Task 2",
dueDate: "2024-12-31T23:59:59Z",
assignees: [1]
},
{
title: "Weekly standup",
repeatAfter: 7,
repeatMode: "day"
}
]
})
// Bulk update multiple tasks with the same field value
vikunja_tasks.bulk-update({
taskIds: [123, 124, 125],
field: "done", // Field to update
value: true // New value for all tasks
})
// Other bulk update examples
vikunja_tasks.bulk-update({
taskIds: [123, 124, 125],
field: "priority",
value: 5
})
vikunja_tasks.bulk-update({
taskIds: [123, 124],
field: "project_id",
value: 2 // Move tasks to different project
})
vikunja_tasks.bulk-update({
taskIds: [123, 124, 125],
field: "labels",
value: [1, 3, 5] // Set same labels on all tasks
})
// Bulk delete multiple tasks (max 100)
vikunja_tasks.bulk-delete({
taskIds: [123, 124, 125]
})
// Batch import tasks from CSV or JSON
vikunja_batch_import({
projectId: 1,
format: "json",
data: JSON.stringify([
{
title: "Task 1",
description: "First imported task",
priority: 3,
dueDate: "2024-12-31T23:59:59Z"
},
{
title: "Task 2",
labels: ["bug", "urgent"], // Will look up label IDs by name
assignees: ["john.doe"] // Will look up user IDs by username
}
])
})
// Import from CSV with headers
vikunja_batch_import({
projectId: 1,
format: "csv",
data: `title,description,priority,dueDate,labels,assignees
"Task 1","Description with, comma",3,2024-12-31T23:59:59Z,"bug;feature","john.doe"
"Task 2","Another task",5,,"urgent","john.doe;jane.smith"`
})
// Dry run to validate without creating tasks
vikunja_batch_import({
projectId: 1,
format: "json",
data: JSON.stringify([...]),
dryRun: true // Only validates, doesn't create tasks
})
// Continue on errors instead of stopping
vikunja_batch_import({
projectId: 1,
format: "csv",
data: csvData,
skipErrors: true // Skip invalid tasks and continue with valid ones
})
データエクスポートの例
// Export a project with all its data
vikunja_export_project({
projectId: 1,
includeChildren: false // Only export the specified project
})
// Export a project including all child projects
vikunja_export_project({
projectId: 1,
includeChildren: true // Recursively export child projects
})
// The export returns JSON data with the following structure:
// {
// project: { ... }, // Project details
// tasks: [ ... ], // All tasks in the project
// labels: [ ... ], // All labels used in tasks
// child_projects: [ ... ], // Nested child project exports (if includeChildren: true)
// exported_at: "...", // ISO timestamp of export
// version: "1.0.0" // Export format version
// }
// Request a full user data export (sent via email)
vikunja_request_user_export({
password: "your-password" // Required for security
})
// Download a previously requested user data export
vikunja_download_user_export({
password: "your-password" // Required for security
})
プロジェクト管理の例
// List all projects
vikunja_projects.list()
// List projects with search and pagination
vikunja_projects.list({
search: "frontend",
page: 1,
perPage: 10,
isArchived: false
})
// Get a specific project
vikunja_projects.get({ id: 1 })
// Create a new project
vikunja_projects.create({
title: "New Frontend Project",
description: "React-based web application",
hexColor: "#4287f5"
})
// Update a project
vikunja_projects.update({
id: 1,
title: "Updated Project Name",
isArchived: true
})
// Archive a project
vikunja_projects.archive({ id: 1 })
// Unarchive a project
vikunja_projects.unarchive({ id: 1 })
// Delete a project
vikunja_projects.delete({ id: 1 })
// --- Project Hierarchy Management ---
// Create a child project
vikunja_projects.create({
title: "Frontend Module",
description: "React components",
parentProjectId: 1, // Will be a child of project 1
hexColor: "#3498db"
})
// Get all direct children of a project
vikunja_projects.get-children({ id: 1 })
// Returns: Array of projects that have parentProjectId = 1
// Get complete project hierarchy as a tree
vikunja_projects.get-tree({ id: 1 })
// Returns: Project with nested children structure
// {
// id: 1,
// title: "Main Project",
// children: [
// {
// id: 2,
// title: "Frontend Module",
// children: [
// { id: 4, title: "Components", children: [] },
// { id: 5, title: "Styles", children: [] }
// ]
// },
// {
// id: 3,
// title: "Backend Module",
// children: []
// }
// ]
// }
// Get breadcrumb path from root to a project
vikunja_projects.get-breadcrumb({ id: 5 })
// Returns: Array of projects from root to target
// [
// { id: 1, title: "Main Project" },
// { id: 2, title: "Frontend Module" },
// { id: 5, title: "Styles" }
// ]
// Also includes a formatted path: "Main Project > Frontend Module > Styles"
// Move a project to a new parent
vikunja_projects.move({
id: 5, // Project to move
parentProjectId: 3 // New parent
})
// Validates against circular references and depth limits
// Move a project to root level (no parent)
vikunja_projects.move({
id: 5,
parentProjectId: undefined
})
// --- Project Sharing ---
// Create a read-only share link
vikunja_projects.create-share({
id: 1,
right: 0, // 0=Read, 1=Write, 2=Admin
label: "Public read-only access"
})
// Create a password-protected share with write access
vikunja_projects.create-share({
id: 1,
right: 1,
password: "securepassword123",
label: "Team collaboration link"
})
// Create an expiring share link
vikunja_projects.create-share({
id: 1,
right: 0,
expires: "2025-12-31T23:59:59Z",
label: "Temporary access until year end"
})
// List all shares for a project
vikunja_projects.list-shares({ id: 1 })
// Get details of a specific share
vikunja_projects.get-share({
id: 1,
shareId: 123
})
// Delete a share link
vikunja_projects.delete-share({
id: 1,
shareId: 123
})
// Authenticate to access a shared project
vikunja_projects.auth-share({
shareHash: "abc123def456"
})
// Authenticate to a password-protected share
vikunja_projects.auth-share({
shareHash: "abc123def456",
password: "securepassword123"
})
ラベル管理の例
// List all labels
vikunja_labels.list()
// Search for labels
vikunja_labels.list({
search: "bug",
page: 1,
perPage: 20
})
// Get a specific label
vikunja_labels.get({ id: 1 })
// Create a new label
vikunja_labels.create({
title: "Critical",
description: "Critical priority issues",
hexColor: "#ff0000"
})
// Update a label
vikunja_labels.update({
id: 1,
title: "High Priority",
hexColor: "#ff6600"
})
// Delete a label
vikunja_labels.delete({ id: 1 })
// --- Label Assignment to Tasks ---
// Apply multiple labels to a task
vikunja_tasks.apply-label({
id: 123,
labels: [1, 2, 3] // Apply labels with IDs 1, 2, and 3
})
// Apply a single label
vikunja_tasks.apply-label({
id: 123,
labels: [1] // Apply just the "research" label
})
// Remove specific labels from a task
vikunja_tasks.remove-label({
id: 123,
labels: [2, 3] // Remove labels 2 and 3, keep others
})
// List all labels on a task
vikunja_tasks.list-labels({ id: 123 })
// Returns: Task info with detailed label data including colors and descriptions
チーム管理の例
// List all teams
vikunja_teams.list()
// Search for teams
vikunja_teams.list({
search: "frontend",
page: 1,
perPage: 10
})
// Create a new team
vikunja_teams.create({
name: "Frontend Team",
description: "Responsible for UI/UX development"
})
// Delete a team
vikunja_teams.delete({ id: 1 })
// Note: get, update, and members operations are not yet
// implemented in the node-vikunja library
ユーザー管理の例
⚠️ 既知の問題:有効なトークンを使用している場合でも、ユーザーのエンドポイントで認証エラーが発生することがあります。これは Vikunja API の既知の問題です。この問題が発生すると、MCP サーバーは役立つエラーメッセージを表示します。この問題が発生した場合は、Vikunja サーバーの管理者にお問い合わせください。
// Get current user information
vikunja_users.current()
// Search for users
vikunja_users.search({
search: "john"
})
// Get current user settings
vikunja_users.settings()
// Update user settings
vikunja_users.update-settings({
name: "John Doe",
language: "en",
timezone: "America/New_York",
weekStart: 1 // Monday
})
// Update notification preferences
vikunja_users.update-settings({
emailRemindersEnabled: true, // Enable email reminders for tasks
overdueTasksRemindersEnabled: true, // Enable daily overdue task emails
overdueTasksRemindersTime: "09:00" // Time to send overdue task summary
})
Webhook 管理の例
// List all available webhook events
vikunja_webhooks.list-events()
// Returns: ["task.created", "task.updated", "task.deleted", "task.assigned", ...]
// List webhooks for a project
vikunja_webhooks.list({ projectId: 1 })
// Create a webhook for task events
vikunja_webhooks.create({
projectId: 1,
targetUrl: "https://example.com/webhook",
events: ["task.created", "task.updated"],
secret: "my-secret-key" // Optional, for HMAC signing
})
// Create a webhook without secret
vikunja_webhooks.create({
projectId: 1,
targetUrl: "https://example.com/notifications",
events: ["task.assigned", "task.comment.created"]
})
// Get a specific webhook
vikunja_webhooks.get({
projectId: 1,
webhookId: 123
})
// Update webhook events
vikunja_webhooks.update({
projectId: 1,
webhookId: 123,
events: ["task.created", "task.updated", "task.deleted"]
})
// Delete a webhook
vikunja_webhooks.delete({
projectId: 1,
webhookId: 123
})
高度なフィルタリングの例
// Create a saved filter for high priority tasks
vikunja_filters.create({
name: "High Priority Tasks",
description: "All undone tasks with priority 4 or 5",
filter: "done = false && priority >= 4",
isGlobal: true
})
// Alternative format using title and filters object
vikunja_filters.create({
title: "🔥 High Priority Tasks",
description: "All tasks with priority 4 or 5 that are not completed",
filters: {
filter_by: ["priority"],
filter_value: ["5"],
filter_comparator: [">="],
filter_concat: ""
},
is_favorite: true
})
// Create a filter with multiple conditions
vikunja_filters.create({
title: "Urgent & Incomplete",
filters: {
filter_by: ["priority", "done"],
filter_value: ["3", "false"],
filter_comparator: [">=", "="],
filter_concat: "&&"
}
})
// Create a project-specific filter
vikunja_filters.create({
name: "This Week's Tasks",
filter: "dueDate >= now && dueDate < now+7d",
projectId: 1,
isGlobal: false
})
// List all saved filters
vikunja_filters.list()
// List filters for a specific project
vikunja_filters.list({ projectId: 1 })
// Apply a saved filter to task listing
vikunja_tasks.list({
filterId: "550e8400-e29b-41d4-a716-446655440000"
})
// Build a filter programmatically
vikunja_filters.build({
conditions: [
{ field: "done", operator: "=", value: false },
{ field: "priority", operator: ">=", value: 3 },
{ field: "assignees", operator: "in", value: ["user1", "user2"] }
],
groupOperator: "&&"
})
// Returns: { filter: "(done = false && priority >= 3 && assignees in user1, user2)", valid: true }
// Update an existing filter
vikunja_filters.update({
id: "550e8400-e29b-41d4-a716-446655440000",
name: "Critical Tasks",
filter: "done = false && priority = 5"
})
// Validate a filter string
vikunja_filters.validate({
filter: "done = false && priority >= 3"
})
// Returns: { valid: true, errors: [] }
フィルター構文リファレンス
Vikunja のフィルター構文では、次のような SQL 風のクエリを使用できます。
フィールド:
done- タスクの完了状態(ブール値)priority- タスクの優先度(1~5)percentDone- 完了率(0~100)dueDate- タスクの期限assignees- タスクの担当者labels- 関連付けられたラベルcreated- タスクの作成日時updated- タスクの更新日時
演算子:
- 比較:
=、!=、>、>=、<、<= - パターンマッチング:
like(ワイルドカード%を使用) - リスト照合:
in、not in
日付の計算:
now- 現在の時刻now+24h- 現在から24時間後now-7d- 7日前now/d- 今日の開始時刻- 対応単位:s(秒)、m(分)、h(時間)、d(日)、w(週)、M(月)、y(年)
例:
priority = 4dueDate < nowdone = false && priority >= 3assignees in user1, user2dueDate >= now && dueDate < now+7dtitle like "%urgent%"
スマートなハイブリッドフィルタリング: この MCP サーバーは、パフォーマンスと信頼性を最適化するために、サーバー側とクライアント側のフィルタリングを組み合わせたインテリジェントなハイブリッドフィルタリング方式を実装しています。
- 優先処理:パフォーマンスを最大化するため、まずサーバー側のフィルタリングを試します
- フォールバック:サーバー側のフィルタリングが失敗した場合、または利用できない場合は、クライアント側のフィルタリングに切り替えます
- 透過性:どちらの方法が使用されても、同じフィルター構文を使用できます
- 最適化:無制限の読み込みを防ぐため、ページネーションの上限によるメモリ保護を備えています
- メタデータ:レスポンスには使用されたフィルタリング方式(
serverSideFilteringまたはclientSideFiltering)が含まれます - パフォーマンス:サーバー側のフィルタリングにより、ネットワークトラフィックと処理時間が大幅に削減されます
レスポンス形式
Vikunja MCP サーバーのすべての操作では、一貫性と予測可能性を確保するため、標準化されたレスポンス形式を使用します。
interface StandardResponse {
success: boolean;
operation: string; // The operation performed (e.g., 'create', 'update', 'list')
message?: string; // Human-readable description of the result
data?: any; // The primary data returned (task, project, label, etc.)
metadata?: {
timestamp: string; // ISO 8601 timestamp of the operation
[key: string]: any; // Additional operation-specific metadata
};
}
レスポンス例
成功:
{
"success": true,
"operation": "create",
"message": "Task created successfully",
"data": { "id": 123, "title": "Complete documentation" },
"metadata": { "timestamp": "2025-05-25T12:00:00Z" }
}
エラー:
{
"success": false,
"operation": "update",
"message": "Task not found",
"error": { "code": "TASK_NOT_FOUND", "details": "No task exists with ID 999" }
}
この標準化された形式により、次のことが実現します。
- 一貫性:すべてのツールが同じ構造でレスポンスを返します
- 予測可能性:クライアントは常に、どのフィールドが返されるかを把握できます
- デバッグ:メタデータにより、トラブルシューティングに役立つコンテキストが得られます
- エラー処理:コードとメッセージを含む明確なエラー情報が得られます
利用可能なツール
認証
vikunja_auth- 認証管理connect- API トークンを使用して接続を初期化しますstatus- 認証状態を確認しますrefresh- 認証トークンを更新します
タスク管理 ✅
vikunja_tasks- タスク操作(完全に実装済み)list- フィルターを使ってタスクを一覧表示します- プロジェクトで絞り込むか、すべてのタスクを取得します
- ページネーション、検索、並べ替えに対応しています
- 完了状態で絞り込めます
filterIdパラメーターを使用して、保存済みフィルターを適用できます
create- 新しいタスクを作成します- 必須:title、projectId
- 任意:description、dueDate、priority、labels、assignees
- 日付形式(ISO 8601)と ID を検証します
get- ID でタスクの詳細を取得しますupdate- 既存のタスクを更新します- 部分更新に対応しています
- タイトル、説明、期限、優先度、完了状態を更新できます
- ラベルと担当者も更新できます(効率的な差分ベースの方式を使用)
delete- ID でタスクを削除しますassign- 複数のユーザーをタスクに一括割り当てしますunassign- タスクからユーザーを削除しますcomment- タスクのコメントを一覧表示または追加しますbulk-update- 複数のタスクを一度に更新します- 必須:taskIds 配列、フィールド名、値
- 対応フィールド:done、priority、due_date、project_id、assignees、labels
- フィールドの型と値を検証します
- ⚠️ パフォーマンス:更新した各タスクを取得するために API 呼び出しを行います
bulk-delete- 複数のタスクを一度に削除します- 必須:taskIds 配列
- 確認用に削除したタスクの詳細を返します
- 一部の処理が失敗した場合も適切に処理します
- ⚠️ パフォーマンス:タスクごとに個別の削除呼び出しを行います
- 推奨:20件以下のタスク単位で処理してください
attach- 未実装(MCP ではファイルを扱えません)
一括インポート ✅
vikunja_batch_import- CSV または JSON から複数のタスクをインポートします(完全に実装済み)- 必須:projectId、format('csv' または 'json')、data
- 任意:skipErrors(エラー時も続行)、dryRun(検証のみ)
- バッチサイズの上限:1 回のインポートにつき最大 100 件のタスク
- CSV 形式:
- フィールド名を含むヘッダー行が必要です
- 引用符付きの値とエスケープされた引用符に対応しています
- フィールド:title、description、priority、dueDate、labels、assignees
- labels と assignees はセミコロン区切りの値です(CSV のカンマとの競合を避けるため、セミコロンを使用します)
- JSON 形式:
- タスクオブジェクトの配列
- CSV と同じフィールドに加え、配列を直接サポートします
- 機能:
- 名前によるラベルの自動検索
- ユーザー名によるユーザーの自動検索
- 作成前の検証
- 詳細なエラー報告
- テスト用のドライランモード
- 部分的なインポートを可能にするエラーのスキップオプション
プロジェクト管理 ✅
vikunja_projects- プロジェクト操作(完全に実装済み)list- フィルターを指定してすべてのプロジェクトを一覧表示します- ページネーションと検索に対応しています
- アーカイブ状態によるフィルタリング
get- ID を指定してプロジェクトの詳細を取得しますcreate- 新しいプロジェクトを作成します- 必須:title
- 任意:description、parentProjectId、isArchived、hexColor(形式:#RRGGBB)
- 親プロジェクトの階層の深さを検証します(最大 10 階層)
update- 既存のプロジェクトを更新します- 部分更新に対応しています
- hexColor(形式:#RRGGBB)を含む、すべてのプロジェクトフィールドを更新できます
- 親プロジェクトを変更する際に、階層の深さを検証します
delete- ID を指定してプロジェクトを削除しますarchive- プロジェクトをアーカイブしますunarchive- プロジェクトのアーカイブを解除します- 階層管理(新機能!)
get-children- プロジェクトの直下の子プロジェクトを一覧表示しますget-tree- プロジェクトの階層全体をツリーとして取得しますget-breadcrumb- ルートからプロジェクトまでのパスを取得しますmove- プロジェクトを新しい親の下に移動します- 循環参照がないか検証します
- 最大 10 階層の制限を適用します
- プロジェクトの共有
create-share- 権限を指定して共有リンクを作成しますlist-shares- プロジェクトのすべての共有を一覧表示しますget-share- 共有の詳細を取得しますdelete-share- 共有リンクを削除しますauth-share- 共有プロジェクトにアクセスするための認証を行います
ラベル管理 ✅
vikunja_labels- ラベル操作(完全に実装済み)list- フィルターを指定してすべてのラベルを一覧表示します- ページネーションと検索に対応しています
get- ID を指定してラベルの詳細を取得しますcreate- 新しいラベルを作成します- 必須:title
- 任意:description、hexColor(形式:#RRGGBB)
update- 既存のラベルを更新します- 部分更新に対応しています
- title、description、hexColor を更新できます
delete- ID を指定してラベルを削除しますapply-label- 1 つ以上のラベルをタスクに適用します- 必須:task id、labels 配列
- ラベルの一括適用に対応しています
remove-label- タスクから 1 つ以上のラベルを削除します- 必須:task id、labels 配列
- ラベルの一括削除に対応しています
list-labels- タスクに割り当てられたすべてのラベルを一覧表示します- 必須:task id
- 詳細なラベル情報を返します
プロジェクトテンプレート ✅
vikunja_templates- テンプレート操作(完全に実装済み)create- 既存のプロジェクトからテンプレートを作成- 必須:projectId、name
- 任意:description、tags
- プロジェクトのすべての設定とタスクを取り込みます
list- 利用可能なすべてのテンプレートを一覧表示- テンプレート名、タグ、作成者を表示します
get- ID でテンプレートの詳細を取得update- テンプレートのメタデータを更新- name、description、tags を更新できます
delete- テンプレートを削除instantiate- テンプレートから新しいプロジェクトを作成- 必須:id(テンプレート ID)、projectName
- 任意:parentProjectId、variables
- 変数の置換に対応しています:
{{PROJECT_NAME}}- 新しいプロジェクト名{{TODAY}}- 現在の日付(YYYY-MM-DD){{NOW}}- 現在のタイムスタンプ- variables パラメーターによるカスタム変数
- テンプレートからラベル付きのすべてのタスクを作成します
チーム管理 ✅
vikunja_teams- チーム操作(部分的に実装済み)list- フィルターを指定してすべてのチームを一覧表示- ページネーションと検索に対応
create- 新しいチームを作成- 必須:name
- 任意:description
delete- ID でチームを削除(フォールバック API に対応)get- node-vikunja では未実装ですupdate- node-vikunja では未実装ですmembers- node-vikunja では未実装です
ユーザー管理 ✅
vikunja_users- ユーザー操作(完全に実装済み)[JWT 認証が必要]current- 現在認証されているユーザーの情報を取得search- ユーザーを検索- 任意:検索クエリ、ページネーション
settings- 現在のユーザー設定を取得update-settings- ユーザー設定を更新- 任意:name、language、timezone、weekStart、frontendSettings
- 注: ユーザー操作には JWT 認証が必要です。API トークン認証を使用している場合、これらのツールは利用できません。
Webhook 管理 ✅
-
vikunja_webhooks- プロジェクトの自動化向け Webhook 操作(完全に実装済み)list-events- 利用可能なすべての Webhook イベントタイプを取得list- プロジェクトの Webhook を一覧表示- 必須:projectId
get- 特定の Webhook を取得- 必須:projectId、webhookId
create- 新しい Webhook を作成- 必須:projectId、targetUrl、events(配列)
- 任意:secret(HMAC 署名用)
- 注: イベントは利用可能なイベントタイプと照合して検証されます
update- Webhook イベントを更新- 必須:projectId、webhookId、events(配列)
- 注: イベントは利用可能なイベントタイプと照合して検証されます
delete- Webhook を削除- 必須:projectId、webhookId
イベントの検証: Webhook の作成時または更新時に、指定されたイベントは API から取得した利用可能なイベントの一覧と自動的に照合されます。無効なイベントがある場合、どのイベントが無効かを示し、有効な選択肢をすべて一覧表示する明確なエラーメッセージが返されます。パフォーマンス向上のため、有効なイベントは 5 分間キャッシュされます。
フィルター管理 ✅
-
vikunja_filters- タスクの高度なフィルタリング(完全に実装済み)list- 保存済みフィルターを一覧表示- 任意:projectId(プロジェクト固有のフィルター用)、global フラグ
get- ID で特定のフィルターを取得create- 新しい保存済みフィルターを作成- 必須:name、filter(クエリ文字列)
- 任意:description、projectId、isGlobal
update- 既存のフィルターを更新- 必須:id
- 任意:name、description、filter、projectId、isGlobal
delete- 保存済みフィルターを削除build- 条件からフィルター文字列を構築- 必須:conditions 配列
- 任意:groupOperator(&&、||)
validate- フィルター文字列を検証
注: 保存済みフィルターは現在メモリ上に保存されており、MCP サーバーを再起動すると失われます。本番環境で使用する場合は、永続ストレージの実装をご検討ください。
データのエクスポート ✅
⚠️ WARNING: メモリ使用量
エクスポート操作では、プロジェクト階層全体をメモリに読み込みます。数千件のタスクや深くネストされた構造を持つ非常に大規模なプロジェクトでは、大量のメモリを消費する可能性があります。小規模なプロジェクトごとに個別にエクスポートすることを検討してください。
-
vikunja_export_project- プロジェクトデータをエクスポートします [JWT 認証が必要です]- パラメーター:
projectId(必須)- エクスポートするプロジェクトの IDincludeChildren(任意)- 子プロジェクトを再帰的に含めます(デフォルト: false)
- 戻り値: タスク、ラベル、メタデータを含む完全なプロジェクトデータ
- 機能:
- すべてのタスクを詳細情報付きでエクスポートします
- プロジェクトで使用されているすべてのラベルを含めます
- オプションで子プロジェクト階層全体を含めます
- ネストされたプロジェクトの循環参照を検出します
- エクスポートのメタデータにはタイムスタンプとバージョンが含まれます
- 注: エクスポート操作には JWT 認証が必要です。API トークン認証を使用する場合、このツールは利用できません。
- パラメーター:
-
vikunja_request_user_export- ユーザーデータ全体のエクスポートをリクエストします- パラメーター:
password(必須)- セキュリティ確認用のユーザーパスワード
- 戻り値: エクスポートがリクエストされたことを示す確認
- 注: エクスポートの準備が完了すると、メールが届きます
- パラメーター:
-
vikunja_download_user_export- 以前リクエストしたユーザーデータのエクスポートをダウンロードします- パラメーター:
password(必須)- セキュリティ確認用のユーザーパスワード
- 戻り値: ユーザーデータ全体のエクスポート
- 注: 先に
vikunja_request_user_exportからエクスポートをリクエストする必要があります
- パラメーター:
既知の制限事項
- ファイル添付: MCP プロトコルの制限により、
attachサブコマンドは実装されていません - チーム操作: node-vikunja API のサポートが不完全なため、機能が制限されています:
- ID によるチームの取得はできません
- チーム情報の更新はできません
- チームの削除はできません
- チームメンバーの管理はできません
- ページネーション: API の制限により、一部のエンドポイントではページネーションパラメーターが完全にサポートされない場合があります
- 認証の問題: 一部の Vikunja API エンドポイントには、既知の認証問題があります:
- ユーザーエンドポイント: 有効なトークンを使用していても、トークンエラーで失敗する場合があります(既知の Vikunja API の制限)
- 一括操作: 特定の Vikunja API バージョンでは、認証の問題が発生する場合があります
- ラベル操作: 一部のサーバー構成では、認証エラーで失敗する場合があります
- 担当者の操作: 担当者を指定してタスクを作成または更新する際、認証エラーで失敗する場合があります
- これらの問題が発生すると、サーバーは回避策を示す詳細なエラーメッセージを返します
セキュリティとパフォーマンスの機能
セキュリティ強化
- Zod スキーマ検証: 包括的な型チェックによるエンタープライズグレードの入力検証
- DoS 保護: DoS 攻撃を防ぐための入力サニタイズ、長さ制限、文字許可リスト
- 認証情報の保護: ログやエラーメッセージ内の機密トークンと URL を自動的にマスキングします
- エンティティ解決サービス: 不正な API レスポンスに対する防御的なエラー処理を備えた、堅牢なラベルとユーザーのマッピング
- レート制限: DoS 攻撃を防ぐための、設定可能なリクエストレート制限とペイロードサイズ制限
- メモリ保護: リソースの枯渇を防ぐためのページネーション制限とメモリ使用量の監視
- エラー処理: 機密性の高いシステム情報の漏えいを避ける、構造化されたエラーレスポンス
パフォーマンスの最適化
- ハイブリッドフィルタリング:最適なパフォーマンスを実現する、スマートなサーバーサイドフィルタリングとクライアントサイドのフォールバック
- コネクションプーリング:クライアントの自動キャッシュによる効率的なセッション管理
- リクエストのバッチ処理:差分ベースの更新による、最適化された効率的な一括操作
- メモリ管理:大規模なデータセットを安全に扱うための自動クリーンアップとページネーション
- スレッドセーフなクライアント管理:非同期専用の ClientContext API により、並行処理のシナリオで発生する競合状態を解消
- Opossum サーキットブレーカー:自動的な障害検出と復旧を備えた、本番環境対応の再試行ロジック
- シンプルなストレージ:複雑さとオーバーヘッドを 90% 削減するインメモリのフィルターストレージ
設定
環境変数
サーバーは、環境変数を通じてさまざまな設定オプションをサポートしています。
基本設定
# Vikunja instance URL (required)
VIKUNJA_URL=https://your-vikunja-instance.com/api/v1
# Authentication token (required)
VIKUNJA_API_TOKEN=your-api-token
# Enable debug logging (default: false)
DEBUG=true
# Set log level (error, warn, info, debug)
LOG_LEVEL=debug
セキュリティとパフォーマンスの設定
# Rate limiting (default: enabled)
RATE_LIMIT_ENABLED=true
RATE_LIMIT_PER_MINUTE=60 # Requests per minute (default: 60)
RATE_LIMIT_PER_HOUR=1000 # Requests per hour (default: 1000)
# Request size limits (default: 1MB)
MAX_REQUEST_SIZE=1048576 # Maximum request payload size in bytes
MAX_RESPONSE_SIZE=10485760 # Maximum response size in bytes (default: 10MB)
# Execution timeout (default: 30 seconds)
EXECUTION_TIMEOUT=30000 # Tool execution timeout in milliseconds
# Memory protection (default: enabled)
MEMORY_PROTECTION_ENABLED=true
MAX_TASKS_PER_REQUEST=1000 # Maximum tasks to load per request
# Circuit breaker configuration (opossum)
CIRCUIT_BREAKER_ENABLED=true # Enable circuit breaker for API calls
CIRCUIT_BREAKER_TIMEOUT=60000 # Circuit breaker timeout in milliseconds (default: 60s)
CIRCUIT_BREAKER_ERRORS_THROTTLE=10 # Errors before opening circuit (default: 10)
CIRCUIT_BREAKER_RESET_TIMEOUT=30000 # Time to wait before trying half-open state (default: 30s)
# Filter security (Zod validation)
FILTER_MAX_LENGTH=1000 # Maximum filter string length (default: 1000)
FILTER_MAX_VALUE_LENGTH=200 # Maximum individual value length (default: 200)
レート制限の詳細な設定については、docs/RATE_LIMITING.md を参照してください。
ロードマップ
- ✅ セキュリティ強化 - 包括的な脆弱性修正を実装済み
- ✅ パフォーマンスの最適化 - ハイブリッドフィルタリングとメモリ保護
- ✅ エラー処理 - 集中管理されたエラーユーティリティと構造化されたレスポンス
- ✅ テストカバレッジ - 関数カバレッジ 98.91% を達成
- ✅ アーキテクチャの簡素化 - 保守性を向上させながらコードを 90% 削減
- ✅ 本番環境に対応した耐障害性 - Opossum サーキットブレーカーと Zod バリデーション
- リアルタイム更新のための Webhook サブスクリプションを追加
- 頻繁にアクセスされるデータのキャッシュを追加
- 実際の Vikunja インスタンスを使った統合テストを追加
- 保存済みフィルター用の永続ストレージを実装(任意。インメモリでも十分に機能します)
コントリビューション
開発ガイドラインとワークフローについては、CONTRIBUTING.md を参照してください。
ライセンス
MIT
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。