Redmine MCP Server について
Redmine MCP Serverは、企業のRedmine環境でプロジェクト、課題、Wiki、添付ファイル、作業時間を扱うAIエージェント向けサーバーです。幅広い読み取り機能とリリース分析を備え、書き込みツールは設定で制御できます。
主な機能
- 01プロジェクト、課題、メンバーの閲覧
- 02課題、Wiki、Redmine全体の検索
- 03添付ファイルと対応文書のテキスト取得
- 04作業時間と参照データの確認
- 05作業負荷とリリースリスクの分析
- 06書き込み機能とツールグループの切り替え
活用シーン
- 01プロジェクト課題の確認と優先順位付け
- 02Wikiページや添付資料からの情報検索
- 03ユーザーの作業負荷と期限超過の確認
- 04プロジェクトリリースのリスク評価
MCP 対応
stdio経由でRedmineのデータと操作をMCPツールおよびプロンプトとして提供します。書き込みツールは既定で7つあり、REDMINE_MCP_WRITE_ENABLED=falseで無効化できます。ツールグループも個別に無効化できます。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
docker run -i --rm -e REDMINE_URL -e REDMINE_API_KEY -e REDMINE_MCP_WRITE_ENABLED ghcr.io/igorolv/redmine-mcp-server:0.1.1REDMINE_URLBase URL of the Redmine instance, e.g. https://redmine.example.comREDMINE_API_KEYシークレットRedmine API key of the user the server acts as (My account -> API access key)REDMINE_MCP_WRITE_ENABLEDSet to true to also expose the issue, note, attachment, time-entry and wiki write toolsローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ghcr.io/igorolv/redmine-mcp-server:0.1.1stdioツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
Redmine MCP サーバー
企業向けRedmineインスタンスにアクセスするためのローカルMCP サーバーです。読み取りツールに加えて、チケット、作業時間、Wikiに対する限定的な書き込み操作を提供します。完全な読み取り専用で実行するには、REDMINE_MCP_WRITE_ENABLED=falseを設定します。AI エージェント(Claude Code、Cursor、VS Code Copilotなど)から、チケット、プロジェクト、メンバー、バージョン、Wiki、添付ファイル、作業時間、参照データを操作できます。
クイックスタート
このドキュメントでは、Redmine MCP Server自体のインストールと接続について説明します。AIクライアント自体のインストールと設定は対象外です。
- JDK 25以降をインストールします。
- 最新リリースから
redmine-mcp-server.jarをダウンロードするか、自分でビルドします:./gradlew bootJar(ビルドを参照)。Dockerイメージも公開されています。 REDMINE_URLとREDMINE_API_KEYを取得します(設定を参照)。- JARが起動することを確認します(スモークテストを参照)。
- クライアントのMCP設定にJARを追加します(AIクライアントへの接続を参照)。
Claude Codeの場合、コマンドは1つだけです:
claude mcp add --scope user -e REDMINE_URL=https://redmine.example.com -e REDMINE_API_KEY=your_key -- redmine java -jar /path/to/redmine-mcp-server.jar
アーキテクチャ
サーバーはstdioトランスポートのみをサポートします。
Stdio
┌─────────────┐ stdio ┌──────────────────┐ REST API ┌──────────┐
│ AI agent │ <------------> │ redmine-mcp- │ -------------> │ Redmine │
│ (Claude Code│ stdin/stdout │ server (Java) │ HTTP + API │ (corp.) │
│ Cursor...) │ │ │ Key │ │
└─────────────┘ └──────────────────┘ └──────────┘
AIクライアントはサーバーを子プロセスとして起動し、stdin/stdoutを介してMCPプロトコルで通信します。
ツール
サーバーはデフォルトで32個の読み取り専用MCPツールと7個の書き込みツールをエクスポートします。書き込みツールを無効にして完全な読み取り専用で実行するには、REDMINE_MCP_WRITE_ENABLED=falseを設定します。
ユーザー
| ツール | 説明 |
|---|---|
getCurrentUser | 現在のユーザー:ID、ログイン名、グループ、プロジェクト。「自分のチケット」で絞り込む際に便利です |
プロジェクト
| ツール | 説明 |
|---|---|
listProjects | アクセス可能なすべてのプロジェクトの一覧 |
getProject | プロジェクトの詳細:トラッカー、モジュール、説明 |
listProjectMembers | プロジェクトのメンバーと役割 |
listVersions | プロジェクトのバージョン(マイルストーン) |
課題
| ツール | 説明 |
|---|---|
listIssues | フィルター(プロジェクト、ステータス、トラッカー、担当者、優先度、バージョン、保存済みクエリ、カスタムフィールド(cf_<id>=value 形式の customFieldFilters))を指定して課題を一覧表示します。並べ替えにも対応しています |
searchIssues | 詳細な結果を含む、課題の全文検索 |
getIssue | 課題の詳細:説明、ステータス、担当者、日付、注記、関連情報、カスタムフィールド、添付ファイル、リンクされたリビジョン(changesets)。パラメーター:issueId、focus(default、implementation、timeline、full。省略可能) |
getIssueJournal | 圧縮せずに、課題のジャーナルにある単一の完全な注記/イベントを取得します。パラメーター:issueId、journalId |
getMyIssues | 現在のユーザーの課題。パラメーター:projectId、statusId、sort、limit、offset |
getIssueTree | 親課題の連鎖とサブタスク。root と ancestors は Issue の JSON 形式を保ちますが、コンテキストは簡潔です。詳細または関連情報を取得するには getIssue を呼び出してください。パラメーター:issueId、depth(デフォルトは 2、最大は 5) |
getIssueHistory | 作成時と各ジャーナルイベントを、ステータスの期間とともに取得します。長いテキストは短縮されます。journalId は getIssueJournal で全文を取得するエントリーを特定します。nextOffset がなくなるまで、省略可能な offset パラメーターに次の値を指定して取得してください。 |
課題、作業時間記録、Wiki の書き込み(省略可能)
これらのツールはデフォルトで tools/list に表示されます。削除するには REDMINE_MCP_WRITE_ENABLED=false を設定してください。
| ツール | 説明 |
|---|---|
createIssue | 課題を作成します。Redmine の標準フィールドと、customFieldsJson によるカスタムフィールドに対応しています |
updateIssue | 既存の課題の指定フィールドを部分的に更新します |
addIssueNote | 課題のジャーナルに注記を追加します |
attachFileToIssue | 読み取り可能な任意のローカルパスからファイルをアップロードし、課題に添付します |
createTimeEntry | REDMINE_API_KEY のユーザーの作業時間記録を作成します。issueId/projectId のいずれか一方、時間数、日付、作業分類、コメント、カスタムフィールドを受け付けます |
createWikiPage | Wiki ページを作成します。ページがすでに存在する場合、リクエストを拒否します |
updateWikiPage | Wiki ページのテキストを完全に置き換えます。getWikiPage が返す楽観ロックのバージョンが必要です |
Redmine 自体が、REDMINE_API_KEY ユーザーの権限、ワークフロー、必須フィールドのルールを適用します。MCP サーバーは、「自分の」課題や注記について独自のモデルを導入しません。AI が作成した課題を識別できるようにするため、createIssue で作成した課題の説明には、デフォルトで AI_EDIT: が接頭辞として付与されます(updateIssue では付与されません)。注記、作業時間記録のコメント、Wiki リビジョンのコメント、アップロードしたファイル名には、デフォルトではマーカーが付与されません。それぞれのマーカーは個別の REDMINE_MCP_WRITE_*_PREFIX 変数で設定します(設定を参照)。値を空にすると無効になります。課題の説明と注記では、接頭辞の後に改行と空行が入ります。1 行のフィールド(作業時間記録と Wiki リビジョンのコメント)では、接頭辞の後にスペースが入ります。ファイル名では、区切り文字なしで接頭辞が付与されます。Wiki ページのマークアップ自体は変更されません。
既存の注記の編集と削除には対応していません。対象の Redmine 4.0.4 には、これに対応する REST API がありません。作業時間記録の編集と削除、Wiki ページの削除、名前変更、保護、および他のユーザーに代わって作業時間記録を作成することは、現在の操作範囲に含まれません。
検索
| ツール | 説明 |
|---|---|
searchAll | Redmine 全体の検索:課題、Wiki、ニュース、ドキュメント、コミットなど。パラメーター:searchQuery、projectId、types、limit、offset |
添付ファイルと Wiki
| ツール | 説明 |
|---|---|
getAttachment | 元の添付ファイルをローカルのスナップショットディレクトリにダウンロードし、localPath/fileUriを返します。また、対応形式(txt/log/xml/json/csv、PDF、Word(.docx)、Excel(.xlsx)、PowerPoint(.pptx)、ZIP)の場合は、テキストコンテキストを直ちにparts[]に追加します。ZIPでは、エントリーごとに個別のパートが生成される場合があります。.docxでは、テキストパートが1つ生成されます。pandocが利用可能な場合はpandoc形式のMarkdown、それ以外の場合はPOI形式のプレーンテキストになります。パラメーター:issueId、attachmentId、maxChars、partLimit(処理制限を参照) |
getWikiPage | プロジェクトの Wiki ページの内容 |
listWikiPages | プロジェクトのすべての Wiki ページの一覧 |
searchWikiPages | Wiki ページ全体の全文検索。パラメーター:searchQuery、projectId、limit、offset |
時間エントリー
| ツール | 説明 |
|---|---|
listTimeEntries | 記録された作業時間。プロジェクト、チケット、ユーザー、期間で絞り込み可能 |
getMyTimeEntries | 現在のユーザーの記録済み作業時間。パラメーター:projectId、issueId、from、to、limit、offset |
参照データ
| ツール | 説明 |
|---|---|
listQueries | 保存済みクエリ(カスタムフィルター)— ID と名前。カスタムフィールドのフィルターを含め、フィルターを適用するには、listIssues(queryId)でIDを使用します |
listStatuses | すべてのチケットのステータス(ID と名前)— listIssuesでの絞り込みに使用 |
listTrackers | すべてのトラッカー(ID と名前)— listIssuesでの絞り込みに使用 |
listPriorities | すべての優先度(ID と名前)— listIssuesでの絞り込みに使用 |
listIssueCategories | プロジェクトのチケットカテゴリ(ID と名前) |
listTimeEntryActivities | 既存の時間エントリーの解釈に使用する作業種別(ID と名前) |
分析
| ツール | 説明 |
|---|---|
getProjectSummary | プロジェクトの集計サマリー:未完了/完了の総数、ステータス、トラッカー、優先度、担当者別に分析した未完了チケット、期限超過チケット、見積もり時間/実績時間。最大500件の未完了チケットを分析し、結果が省略されたことを示すフラグを返します。パラメーター:projectId、versionId(任意) |
getUserWorkload | 作業負荷の分析:プロジェクトと優先度別の未完了チケット、期限超過チケット、優先度の高いチケット。最大500件の未完了チケットを分析し、結果が省略されたことを示すフラグを返します。パラメーター:userId(任意。既定値は現在のユーザー)、projectId(任意) |
getVersionChangelog | トラッカー別に分類したバージョンのチケットと、未完了/完了の統計。最大500件のチケットを分析し、結果が省略されたことを示すフラグを返します。パラメーター:projectId、versionId |
getBlockerChain | ブロック関係(blocks/blocked_by)を上方向および下方向に再帰的にたどります。深さは最大10、読み込むチケットは最大30件です。パラメーター:issueId |
getStaleIssues | N日間更新されていない未完了チケットを、古いものから順に取得します。パラメーター:projectId、daysSinceUpdate(既定値は30)、limit |
getReleaseRisks | リリースリスクの評価:ブロッカー、期限超過項目、優先度の高いチケット、未割り当てチケット。最大500件の未完了チケットを分析し、結果が省略されたことを示すフラグを返します。パラメーター:projectId、versionId |
compareVersions | 2つのバージョンを比較します:固有のチケット、共通のチケット、完了率。バージョンごとに最大500件のチケットを分析し、結果が省略されたことを示すフラグを返します。パラメーター:projectId、versionId1、versionId2 |
REDMINE_MCP_WRITE_ENABLED=falseの場合、すべてのツールは読み取り専用となり、Redmineのデータは変更されません。
ツールグループ(有効化/無効化)
ツールはドメイン別にグループ化されており、各グループは環境変数で無効化できます。
デフォルトではすべてのグループが有効で、標準状態のツールマニフェストに変更はありません。グループを無効化すると、セッション開始時にクライアントがモデルコンテキストに読み込む MCP の tools/list マニフェストを縮小できます。小規模なコンテキストの(ローカル)モデルでは、不要なグループを無効化して、モデルが実際に必要とするツールだけを残すと役立ちます。
| 変数 | グループ(ツール) |
|---|---|
REDMINE_MCP_TOOLS_ISSUE | チケット(コア):listIssues、searchIssues、getIssue、getMyIssues、getIssueJournal |
REDMINE_MCP_TOOLS_ISSUE_STRUCTURE | チケットの構造/履歴:getIssueTree、getIssueHistory |
REDMINE_MCP_TOOLS_PROJECT | プロジェクト:listProjects、getProject、listProjectMembers、listVersions |
REDMINE_MCP_TOOLS_SEARCH | 検索:searchAll |
REDMINE_MCP_TOOLS_ATTACHMENT | 添付ファイル:getAttachment |
REDMINE_MCP_TOOLS_WIKI | Wiki:getWikiPage、listWikiPages、searchWikiPages |
REDMINE_MCP_TOOLS_TIME_ENTRY | 作業時間エントリー:listTimeEntries、getMyTimeEntries |
REDMINE_MCP_TOOLS_REFERENCE_DATA | 参照データ:listQueries、listStatuses、listTrackers、listPriorities、listIssueCategories、listTimeEntryActivities |
REDMINE_MCP_TOOLS_USER | ユーザー:getCurrentUser |
REDMINE_MCP_TOOLS_ISSUE_ANALYTICS | チケット分析:getBlockerChain、getStaleIssues |
REDMINE_MCP_TOOLS_RELEASE_ANALYTICS | リリース/プロジェクト分析:getProjectSummary、getUserWorkload、getVersionChangelog、getReleaseRisks、compareVersions |
各変数には true(デフォルト)または false を指定します。例:チケットとプロジェクト関連の機能だけを残すには、残りのグループを無効にします。REDMINE_MCP_TOOLS_RELEASE_ANALYTICS=false、REDMINE_MCP_TOOLS_WIKI=false などを指定してください。MCP プロンプトはこれらのフラグの影響を受けません。プロンプトは、ツールが無効な場合にその手順をスキップするようモデルに指示します。
MCP プロンプト
このサーバーは、一般的なチケット対応シナリオ向けの MCP プロンプト も提供します。各プロンプトには、Redmine のチケット番号(12345 または #12345)である必須引数 issueId を指定します。
| プロンプト | 説明 |
|---|---|
incident-brief | インシデントの簡易概要:getIssue でチケットを取得し、短いプレビュー付きで getAttachment を使ってすべての添付ファイルをダウンロードして、簡潔な Markdown レポートを作成します |
incident-implementation | 実装コンテキスト:focus=implementation を指定してチケットを取得し、名前、説明、日付に基づいて関連する添付ファイルを選び、必要な場合にのみ圧縮されたジャーナルデータを復元して、要件、改訂の根拠、検証チェックリストを作成します |
incident-timeline | インシデントの時系列:getIssue(focus=timeline) でチケットとチェンジセットのコンテキストを取得し、その後、getIssueHistory のすべてのページを読み込んでジャーナルイベントとステータスの期間を確認します |
issue-remaining-work | 未完了の作業:getIssue、(必要に応じて兄弟チケットを含む)getIssueTree、getBlockerChain、必要に応じて getIssueHistory を組み合わせ、ステータスだけを鵜呑みにせず、未完了の項目を報告します |
プレースホルダー引数を指定してプロンプトをリクエストすることでコマンドテンプレートを構築するクライアント(たとえば、$1 を送信する opencode 1.x)は、プレースホルダーをそのまま残したテンプレートを取得するため、クライアント側での置換を引き続き利用できます。
技術スタック
- Java 25、Spring Boot 4.2.0-M2、Spring AI MCP 2.1.0-M1(stdio トランスポート)
- Apache PDFBox 3.0.5 — PDF からのテキスト抽出
- Apache POI 5.4.0 — Word、Excel、PowerPoint からのテキスト抽出
- Apache Tika 3.2.0(core + parsers-standard)— フォールバックパーサーおよびメタデータ抽出
- Pandoc(任意の外部バイナリ)—
PATH上で利用可能な場合、DOCX からテキスト/Markdown への変換を改善します。利用できない場合、サーバーは POI を使用します - バージョンカタログ(
gradle/libs.versions.toml)を使用する Gradle 9.3.1
ビルド
Linux/macOS:
# Point to JDK 25+ if it is not the default JDK:
export JAVA_HOME="$HOME/.jdks/jdk-25.0.2"
./gradlew build
Windows PowerShell:
# Point to JDK 25+ if it is not the default JDK:
$env:JAVA_HOME="C:\Program Files\Java\jdk-25"
.\gradlew.bat build
生成物:build/libs/redmine-mcp-server.jar
設定
サーバーには REDMINE_URL と REDMINE_API_KEY が必要です。それ以外の変数はすべて任意です:
| 変数 | 説明 |
|---|---|
REDMINE_URL | Redmine インスタンスのベース URL(例:https://redmine.example.com) |
REDMINE_API_KEY | Redmine ユーザーの API キー |
REDMINE_MCP_WRITE_ENABLED | createIssue、updateIssue、addIssueNote、attachFileToIssue、createTimeEntry、createWikiPage、updateWikiPage ツールを tools/list に追加します。読み取り専用で実行するには false に設定してこれらのツールを削除します。デフォルトは true です |
REDMINE_MCP_WRITE_ISSUE_DESCRIPTION_PREFIX | createIssue で作成する課題の説明文の先頭に付加するマーカーです。デフォルトは AI_EDIT: です。無効にするには空の値を設定します |
REDMINE_MCP_WRITE_ISSUE_NOTE_PREFIX | addIssueNote で追加する注記の先頭に付加するマーカーです。デフォルトでは空(無効)です |
REDMINE_MCP_WRITE_TIME_ENTRY_COMMENT_PREFIX | createTimeEntry のコメントの先頭に付加するマーカーです。Redmine の 1024 文字制限に含まれます。デフォルトでは空(無効)です |
REDMINE_MCP_WRITE_WIKI_COMMENT_PREFIX | createWikiPage / updateWikiPage の Wiki 改訂コメントの先頭に付加するマーカーです。デフォルトでは空(無効)です |
REDMINE_MCP_WRITE_ATTACHMENT_FILENAME_PREFIX | attachFileToIssue でアップロードするファイル名に付加するプレフィックスです(例:AI_EDIT__)。/ \ ? % * : | " ' < > を含めることはできません。デフォルトでは空(無効)です |
REDMINE_MCP_DATA_DIR | サーバーのローカルデータディレクトリです。デフォルトは ~/.redmine-mcp-server です |
REDMINE_MCP_HTTP_CONNECT_TIMEOUT_SECONDS | Redmine への接続を確立するまでのタイムアウトです。デフォルトは 10 秒です |
REDMINE_MCP_HTTP_READ_TIMEOUT_SECONDS | Redmine が 1 件のリクエストに応答するまでのタイムアウトです(リクエストのアップロードを含みます)。デフォルトは 30 秒です。ツール呼び出しは一度に 1 件ずつ処理されるため、リクエストが停滞すると、その後のすべての呼び出しが遅延します |
REDMINE_MCP_HTTP_SLOW_REQUEST_WARN_MILLIS | Redmine リクエストがこの時間を超えると、警告としてログに記録されます。デフォルトは 5000 ms です |
REDMINE_MCP_ATTACHMENT_PER_PART_CHARS | 制限なしの getAttachment 呼び出しにおける、単一の part(例:ZIP 内の 1 ファイル)ごとのテキスト上限です。デフォルトは 30000 文字です。ツールの partLimit パラメーターで上書きでき、partLimit を省略した場合は maxChars でも上書きできます。 |
REDMINE_MCP_ATTACHMENT_PER_ATTACHMENT_CHARS | maxChars を指定しない getAttachment 呼び出しで、添付ファイル 1 件から抽出するテキストの合計上限です。デフォルトは 40000 文字で、デフォルトのレスポンスが REDMINE_MCP_RESPONSE_MAX_CHARS を下回るようにします。 |
REDMINE_MCP_ATTACHMENT_MAX_REQUEST_CHARS | 呼び出し元が getAttachment に指定できる maxChars と partLimit の上限です。デフォルトは 200000 文字です。これより大きい値は上限まで減らされ、その旨がレスポンスの limits.note に記載されます。 |
REDMINE_MCP_RELATED_MAX_SIBLINGS | 課題の読み込み時に related に追加する兄弟課題の最大数です。デフォルトは 20 です |
REDMINE_MCP_RELATED_MAX_CHILDREN | 課題の読み込み時に related に追加する子課題の最大数です。デフォルトは 20 です |
REDMINE_MCP_RELATED_MAX_RELATED | 課題の読み込み時に、関連から related に追加する関連課題の最大数です。デフォルトは 10 です |
getIssue は、親を軽量に 1 回読み取り、兄弟、子、関連先をまとめて検索して、関連コンテキストを解決します。関連する課題のスナップショットは取得しません。timeline と changesets のフォーカスモードでは related を省略し、これらのリクエストをすべてスキップします。 | |
REDMINE_MCP_RESPONSE_MAX_CHARS | getIssue と getAttachment の段階的な圧縮を行う前の応答サイズの目標上限です。デフォルトは 50000 文字です |
REDMINE_MCP_RESPONSE_JOURNAL_TAIL_KEEP | より強い削減を行う前に、getIssue の予算圧縮で保持する最新のジャーナルエントリ数です。デフォルトは 30 です |
REDMINE_MCP_RESPONSE_ATTACHMENT_TEXT_PART_CHARS | maxChars/partLimit を指定せずに getAttachment を呼び出した場合の、応答圧縮中における添付ファイルの各パートのテキスト上限です。デフォルトは 10000 文字です。明示的な上限を指定した呼び出しで、その上限を下回るように切り詰められることはありません。 |
REDMINE_MCP_RESPONSE_JOURNAL_NOTE_CHARS | getIssue の応答圧縮中における、各ジャーナルノートのテキスト上限です。デフォルトは 5000 文字です |
REDMINE_MCP_RESPONSE_IMAGE_PARTS_KEEP | getAttachment の応答圧縮で保持する画像パートの数です。デフォルトは 5 です |
REDMINE_MCP_PAGINATION_DEFAULT_LIMIT | リスト/検索ツールのデフォルトのページサイズです。デフォルトは 25 です |
REDMINE_MCP_PAGINATION_DEFAULT_OFFSET | リスト/検索ツールのデフォルトのオフセットです。デフォルトは 0 です |
REDMINE_MCP_PAGINATION_MEMBERS_DEFAULT_LIMIT | listProjectMembers のデフォルトのページサイズです。デフォルトは 100 です |
REDMINE_MCP_TREE_DEFAULT_DEPTH | getIssueTree のデフォルトの深さです。デフォルトは 2 です |
REDMINE_MCP_TREE_MAX_DEPTH | getIssueTree の最大の深さです。デフォルトは 5 です |
REDMINE_MCP_TREE_MAX_ISSUES | getIssueTree で読み込む課題の最大数です。デフォルトは 50 です |
REDMINE_MCP_ANALYSIS_MAX_PAGES | 分析ツールが読み込む Redmine ページの最大数です。デフォルトは 5 です |
REDMINE_MCP_ANALYSIS_PAGE_SIZE | 分析ツールで使用する Redmine のページサイズです。デフォルトは 100 です |
REDMINE_MCP_ANALYSIS_TOP_ISSUES_LIMIT | 分析レスポンスの上位リストに含める課題の最大数です。デフォルトは 10 です |
REDMINE_MCP_ANALYSIS_MAX_BLOCKER_DEPTH | getBlockerChain の走査の最大深度です。デフォルトは 10 です |
REDMINE_MCP_ANALYSIS_MAX_BLOCKER_ISSUES | getBlockerChain で読み込む課題の最大数です。デフォルトは 30 です |
REDMINE_MCP_ANALYSIS_STALE_ISSUES_DEFAULT_DAYS_SINCE_UPDATE | getStaleIssues のデフォルトの daysSinceUpdate です。デフォルトは 30 です |
REDMINE_MCP_ANALYSIS_STALE_ISSUES_DEFAULT_LIMIT | getStaleIssues のデフォルトの結果上限です。デフォルトは 25 です |
REDMINE_MCP_ANALYSIS_STALE_ISSUES_MAX_LIMIT | getStaleIssues の結果の最大上限です。デフォルトは 100 です |
REDMINE_MCP_EXTRACTION_PANDOC_ENABLED | PATH 上でバイナリが見つかった場合に、DOCX で Pandoc を使用できるようにします。デフォルトは true です |
REDMINE_MCP_EXTRACTION_PANDOC_PROBE_TIMEOUT_SECONDS | 起動時に Pandoc の利用可否を確認する際のタイムアウトです。デフォルトは 2 秒です |
REDMINE_MCP_EXTRACTION_PANDOC_CONVERSION_TIMEOUT_SECONDS | Pandoc による 1 回の DOCX 変換のタイムアウトです。デフォルトは 30 秒です |
REDMINE_MCP_EXTRACTION_LIMITS_MAX_DEPTH | 入れ子になったドキュメントやアーカイブを処理する際の再帰の最大深度です。デフォルトは 1 です |
REDMINE_MCP_EXTRACTION_LIMITS_MAX_TOTAL_PARTS | 抽出 1 回あたりのテキスト/メタデータパートの最大数です。デフォルトは 100 です |
REDMINE_MCP_EXTRACTION_LIMITS_MAX_TOTAL_BYTES | 抽出 1 回あたりの読み込みバイト数の合計上限です。デフォルトは 52428800 バイトです |
REDMINE_MCP_EXTRACTION_LIMITS_MAX_ENTRY_BYTES | アーカイブ内の 1 エントリあたりの上限です。デフォルトは 10485760 バイトです |
REDMINE_MCP_EXTRACTION_ZIP_MAX_ENTRIES_PER_ARCHIVE | ZIP アーカイブあたりのエントリの最大数です。デフォルトは 100 です |
REDMINE_MCP_EXTRACTION_TIKA_BODY_LIMIT_BYTES | Tika フォールバックパーサーに渡す本文サイズの上限です。デフォルトは 5242880 バイトです |
REDMINE_MCP_EXTRACTION_TIKA_METADATA_MAX_FIELDS | レスポンスに含める Tika メタデータフィールドの最大数です。デフォルトは 40 です |
REDMINE_URL の取得方法
ブラウザーで Redmine を開き、パスを含めずに、アドレスバーの値をコピーします。スキームとドメインのみを使用してください。
例:
| ブラウザーのアドレスバー | REDMINE_URL の値 |
|---|---|
https://redmine.example.com/projects/myproject | https://redmine.example.com |
http://192.168.1.50:3000/issues/123 | http://192.168.1.50:3000 |
http://10.0.0.5/redmine/projects | http://10.0.0.5/redmine |
Redmine に IP アドレスでのみアクセスできる場合(ドメイン名がない場合)は、そのまま IP アドレスを使用してください。標準ポート(80/443)と異なる場合は、ポートも含めます。Redmine がサブパス(例:
/redmine)の下に配置されている場合は、URL にも含めてください。
REDMINE_API_KEY の取得方法
- 自分のアカウントで Redmine にログインします
- 「My account」(右上)をクリックします
- 右側の列にある 「API access key」 ブロックを見つけます
- 「Show」 をクリックすると、個人用 API キーが表示されます
- キーをコピーし、
REDMINE_API_KEYの値として使用します
「API access key」ブロックが表示されない場合は、Redmine 管理者にお問い合わせください。設定で REST API が無効になっている可能性があります。
スモークテスト
AI クライアントに接続する前に、後でクライアント設定に追加するものと同じ環境変数を使って、JAR が正常に起動することを確認しておくとよいでしょう。
Linux/macOS:
REDMINE_URL=https://redmine.example.com REDMINE_API_KEY=your_key \
java -jar build/libs/redmine-mcp-server.jar
Windows PowerShell:
$env:REDMINE_URL="https://redmine.example.com"
$env:REDMINE_API_KEY="your_key"
java -jar .\build\libs\redmine-mcp-server.jar
サーバーは stdio 経由で動作し、HTTP ポートは開きません。正常に起動すると、stdin/stdout で MCP リクエストを待機します。ログにエラーがなく、プロセスがすぐに終了しなければ、起動は成功です。停止するには Ctrl+C を押してください。
Docker
イメージはリリースごとに GHCR に公開されます:
docker run -i --rm -e REDMINE_URL=https://redmine.example.com -e REDMINE_API_KEY=your_key ghcr.io/igorolv/redmine-mcp-server:latest
同じコマンドを MCP クライアントから起動します(-i を指定すると、stdio トランスポート用に stdin が開いたままになります)。実行間でログと issue スナップショットを保持するには、ホストのディレクトリを /data にマウントしてください。
イメージをローカルでビルドするには、次のコマンドを実行します:docker build -t redmine-mcp-server .
ログ
ログは ${REDMINE_MCP_DATA_DIR:-~/.redmine-mcp-server}/logs/redmine-mcp-server.log に書き込まれます。
ファイルは日付とサイズに基づいてローテーションされます。サイズ上限は 10MB、保存期間は 30 日、合計サイズ上限は 512MB です。
Issue スナップショット
issue を読み込むと、サーバーは ${REDMINE_MCP_DATA_DIR:-~/.redmine-mcp-server}/issues/<issue-id>/ の下にスナップショットをディスク上に保存します。保存されるのは issue.json、スナップショットのメタデータを含む snapshot.json、attachments.json、および派生ファイル用の extracted/<attachment-id>/ ディレクトリです。添付ファイルは attachments/ の下に <attachment-id>__<filename> のような名前で保存されます。ローカルファイルがすでに存在し、そのサイズが Redmine のメタデータと一致する場合は、スナップショット間で再利用できます。
AI クライアントへの接続
クライアント設定に追加します:
{
"command": "java",
"args": ["-jar", "<absolute-path>/redmine-mcp-server.jar"],
"env": {
"REDMINE_URL": "https://redmine.example.com",
"REDMINE_API_KEY": "your_api_key"
}
}
設定場所:
| クライアント | 接続方法 |
|---|---|
| Claude Code | claude mcp add --scope user -e REDMINE_URL=... -e REDMINE_API_KEY=... -- redmine java -jar /path/to/redmine-mcp-server.jar |
| Qwen Code | ~/.qwen/settings.json -> "mcpServers" -> "redmine" |
| VS Code | .vscode/mcp.json -> "servers" -> "redmine" |
| Cursor | .cursor/mcp.json -> "mcpServers" -> "redmine" |
| Claude Desktop | claude_desktop_config.json -> "mcpServers" -> "redmine" |
その後、クライアントを再起動してください。
運用とセキュリティ
この MCP サーバーは、AI クライアントと並行してローカルで動作するように設計されています。HTTP ポートは開かず、外部からのネットワーク接続も受け付けません。クライアントが JAR を子プロセスとして起動し、stdin/stdout 経由で通信します。
アクセスモデル
- サーバーは、
REDMINE_API_KEYに設定された API キーを所有する Redmine ユーザーの権限を使用します。 - チケット、作業時間、Wiki に関する、明示的に列挙された 7 つの書き込みツールはデフォルトで利用できます。完全な読み取り専用で実行するには、
REDMINE_MCP_WRITE_ENABLED=falseを設定してください。サーバーが API ユーザーの権限を拡張したり、Redmine のワークフローを迂回したりすることはありません。 - アクセス可能なプロジェクト、チケット、添付ファイル、作業時間は、Redmine におけるユーザーの権限によって決まります。ユーザーが Redmine でオブジェクトを表示できない場合、サーバーもそのオブジェクトにアクセスできてはなりません。
REDMINE_MCP_WRITE_*_PREFIXマーカー(作成したチケットに付くデフォルトのAI_EDIT:など)は検索ラベルであり、認可の仕組みではありません。変更を行ったユーザーは、API キーを所有する Redmine アカウントによって確実に特定されます。attachFileToIssueは、ディレクトリの許可リストを設けず、読み取り可能な任意のローカルパスを意図的に受け付けます。書き込みツールはデフォルトで有効なため、信頼できる AI クライアントの隣でのみサーバーを実行してください。クライアントは、プロセスが読み取り可能な任意のファイルの内容を Redmine に渡せる点に留意してください。- API キーは秘密情報として扱ってください。リポジトリ、シェルスクリプト、
.vscode/mcp.json、.cursor/mcp.json、その他のプロジェクト共有ファイルにコミットしないでください。
書き込み操作の開発と検証には、専用のテスト用 Redmine と API キーを使用してください。書き込みはデフォルトで有効なため、integrationTest または手動のスモークテストを本番環境に対して実行する場合は、REDMINE_MCP_WRITE_ENABLED=false を設定してください。
AI クライアントに渡されるデータ
AI クライアントは、MCP ツールを通じて要求したデータのみを受け取ります。
- チケットカード:件名、説明、ステータス、優先度、担当者、作成者、日付、関連、サブタスク、履歴/コメント、カスタムフィールド
- プロジェクト、バージョン、メンバー、参照データ、作業時間に関する情報
- Wiki ページ
- 添付ファイルのメタデータ
- 元の添付ファイルのローカルパス、および
getAttachmentを通じて PDF、DOCX、XLSX、PPTX、ZIP、テキストファイルから抽出されたテキスト
外部またはクラウドの AI クライアントに接続する前に、自社の社内ポリシーを確認してください。Redmine のデータには、企業秘密、個人データ、ログ、キー、エラーダンプ、文書の内容が含まれている場合があります。
処理上限
単一の大きな文書や、関連するチケットのネットワークによって MCP クライアントに過度な負荷がかからないよう、コードには保護上限が設けられています。
| 領域 | 上限 |
|---|---|
getAttachment.parts[] の各テキスト部分 | デフォルトで最大 30,000 文字。それを超える場合はテキストが切り詰められます |
getAttachment 内の添付ファイル全体 | デフォルトで最大 40,000 文字 |
getAttachment の明示的な maxChars / partLimit | それぞれ最大 200,000 文字まで適用されます |
| ZIP の深さ | 1 レベル |
| ZIP アーカイブ | 最大 100 エントリ |
| アーカイブ内の ZIP ファイル | 最大 10 MB |
| ZIP アーカイブ全体 | 展開データが最大 50 MB |
getIssueTree | 深さは最大 5、チケット数は最大 50 |
getIssueHistory | 各 JSON ページは、文字数と UTF-8 バイト数の両方で REDMINE_MCP_RESPONSE_MAX_CHARS 以内です。すべてのイベントは nextOffset を通じて引き続き取得できます |
getAttachment は、適用した上限を limits(maxChars、partLimit、要求値が上限値まで引き下げられた場合の note)で報告します。切り詰められた部分には、元の全長を示す totalChars が含まれます。明示的な上限が指定されていない場合でも、レスポンスが REDMINE_MCP_RESPONSE_MAX_CHARS を超えると(たとえば ZIP エントリが多数ある場合)、圧縮されます。まず追加の画像部分がまとめられ、次にテキスト部分が REDMINE_MCP_RESPONSE_ATTACHMENT_TEXT_PART_CHARS まで切り詰められます。明示的な上限が指定されている場合は、画像部分のみがまとめられます。元のファイルは localPath に保存されたままです。pandoc による DOCX 抽出では、Markdown 部分も保存されたテキストファイルを指します。その他の文書部分は、個別に抽出されたテキストファイルではなく、PDF または Office の元ファイルを指す場合があります。
getIssue は focus パラメーターをサポートしています。default は通常のレスポンス形式を維持し、レスポンス予算を超えた場合にのみ圧縮を適用します。implementation は課題の実装作業を対象とします。課題全体は引き続きディスクに保存され、ツールのレスポンスには説明、人間によるメモ、添付ファイルのメタデータ、およびすべての変更セットのリビジョンが含まれます。詳細な履歴とコミットメッセージ本文は省略されます。timeline は「誰が、いつ、何をしたか」という質問を対象とします。ジャーナルと変更セットは保持されますが、添付ファイル、カスタムフィールド、関連コンテキストは省略されます。full は、保護的な予算圧縮を適用した完全形式を明示的に選択します。
getIssueTree は引き続き取得したすべての課題を完全な状態で読み込み、スナップショットを作成しますが、root と ancestors についてはコンパクトな Issue コンテキストのみを返します。このビューでは、説明、ジャーナル、カスタムフィールド、添付ファイル、変更セットは省略されます。subtree は引き続き階層ビューです。これにより、既存の Issue フィールドの内容が変わります。これまでツリーから完全な詳細を読み取っていたクライアントは、代わりに getIssue(id) を呼び出してください。getIssueTree には直接の関連は含まれません。
getIssueHistory には、作成イベントと各ジャーナルイベントが含まれます。メモがないジャーナルや、認識可能なフィールド変更がないジャーナルも対象です。必要に応じて長いメモやフィールドの変更前後の値を短縮し、各更新の journalId を保持して、削減内容を compressionNotes で説明します。正確な文言や変更前後の値の全体が必要な場合は、getIssueJournal(issueId, journalId) を呼び出してください。まず getIssueHistory(issueId) を呼び出します。nextOffset がある場合は、次の呼び出しでその数値を offset として渡してください。nextOffset がなくなるまで続けます。totalEvents には作成イベントが含まれます。statusDurations のステータス期間は、そのページのイベントに対応します。ページをまたいで組み合わせてください。ページ間で sourceUpdatedOn を比較し、値が変わった場合は最初からやり直してください。サーバーは既存の REDMINE_MCP_RESPONSE_MAX_CHARS 設定を使用するため、新しい環境変数は必要ありません。テキストを短縮しても単一のイベントが収まらない場合、そのページにはイベントと journalId が保持されますが、イベントはメタデータに縮小されます。省略されたステータス期間は compressionNotes で示され、完全なエントリーの取得先として getIssueJournal が案内されます。
必要なメモが予算圧縮によって getIssue のレスポンスから削除された場合、またはメモが短縮された場合は、getIssueJournal(issueId, journalId) を呼び出してください。課題のスナップショットを再取得し、レスポンス圧縮なしで選択したジャーナルエントリーを返します。
一部の通常のリストツール(listIssues、listProjects、listTimeEntries、listQueries)では、limit と offset を直接指定できます。安定した動作のため、過度に大きなページを要求しないでください。1 回の呼び出しにつき 25~100 件が実用的な範囲です。
診断
環境チェック:
java -version
echo "$REDMINE_URL"
test -n "$REDMINE_API_KEY" && echo "REDMINE_API_KEY is set"
Redmine REST API のアクセスチェック:
curl -H "X-Redmine-API-Key: <key>" <url>/users/current.json
ビルドチェック:
./gradlew test
./gradlew build
稼働中の Redmine に対する統合テスト:
REDMINE_URL=<url> REDMINE_API_KEY=<key> ./gradlew integrationTest
統合テストには、接続可能な Redmine と実際のテストデータが必要です。ユニットテストでは、integration タグが付いたテストはデフォルトで除外されます。
既知の運用上の制限事項
- HTTP タイムアウトと再試行ポリシーは、現在個別に設定できません。Redmine の応答が遅い場合、MCP 呼び出しが AI クライアントにとって不便なほど長く待機することがあります。
- Redmine のエラー(
401、403、404、5xx)は、現在ほとんどが Spring のRestClientレベルで処理されます。AI クライアントのユーザーに表示されるメッセージは、専用の MCP ツールエラーほどわかりやすくない場合があります。 - ノートや添付ファイルの書き込みが成功しても、確認の読み取りの間に Redmine または別のユーザーがチケットを変更すると、新しい
journalId/attachmentIdが未定義のままになることがあります。操作自体は完了したものとして扱われます。 - 検索結果は Redmine の設定に依存します。管理者が
/search.jsonを無効にしている場合、searchAll、searchIssues、searchWikiPagesは期待どおりの結果を返さないことがあります。 - PDF からのテキスト抽出は、テキストレイヤーがある PDF でのみ機能します。OCR がないスキャン文書は、抽出可能なテキストのない PDF として検出されます。
- 画像は再エンコードされません。
getAttachmentは元のファイルへのパスを返し、画像のテキストparts[]は空のままです。
プロジェクト構成
├── src/main/java/ru/it_spectrum/ai/redmine/mcp/
│ ├── RedmineMcpServerApplication.java — Spring Boot entry point
│ ├── api/ — stable MCP wire format: records returned by tools/services
│ │ ├── Issue.java
│ │ ├── AttachmentContent.java
│ │ ├── Project.java
│ │ ├── IssueMutationResult.java — stable result of issue write operations
│ │ ├── TimeEntryMutationResult.java — stable result of time-entry creation
│ │ ├── WikiMutationResult.java — stable result of wiki-page writes
│ │ └── ... — tool response DTOs and analytics DTOs
│ ├── client/
│ │ ├── RedmineClient.java — read-only wrapper over the Redmine REST API
│ │ ├── RedmineMutationClient.java — optional POST/PUT for issues, time entries, and wiki
│ │ └── model/ — raw Redmine REST API DTOs, never exported directly to MCP
│ │ ├── RedmineIssue.java
│ │ ├── RedmineAttachment.java
│ │ ├── RedmineProject.java
│ │ └── ...
│ ├── config/
│ │ ├── RedmineClientProperties.java — url + apiKey from env
│ │ ├── RedmineMcpProperties.java — all redmine-mcp.* runtime settings
│ │ ├── RedmineConfig.java — RestClient
│ │ ├── McpServerConfig.java — stdio MCP customizer with immediateExecution(true)
│ │ └── JsonConfig.java — ObjectMapper for MCP JSON
│ ├── extraction/
│ │ ├── ExtractionPipeline.java — document-to-text pipeline
│ │ ├── DocumentParser.java — parser interface
│ │ ├── FileTypeDetector.java — file type detection
│ │ ├── PandocAvailability.java — external pandoc probe at startup
│ │ └── parser/
│ │ ├── PlainTextParser.java — txt/log/csv/json/xml
│ │ ├── PdfTextParser.java — PDF via PDFBox
│ │ ├── DocxTextParser.java — DOCX via POI
│ │ ├── DocxPandocParser.java — DOCX via Pandoc when available
│ │ ├── XlsxTextParser.java — XLSX via POI
│ │ ├── PptxTextParser.java — PPTX via POI
│ │ ├── ZipParser.java — ZIP with bounded recursion
│ │ ├── ImagePassthroughParser.java
│ │ ├── TikaTextFallbackParser.java
│ │ ├── TikaMetadataParser.java
│ │ └── BinaryFallbackParser.java
│ ├── service/
│ │ ├── IssueService.java — issue business logic and mapping client.model -> api
│ │ ├── IssueMutationService.java — optional issue writing and AI marking
│ │ ├── TimeEntryMutationService.java — optional time-entry creation
│ │ ├── WikiMutationService.java — safe wiki writing with optimistic locking
│ │ ├── AttachmentService.java — attachment snapshot, download, and extraction
│ │ ├── IssueSnapshotService.java — local issue and attachment snapshots
│ │ ├── AnalysisService.java — analytics, risks, blocker chain
│ │ └── ... — services for projects, wiki, search, reference data, time entries
│ └── tools/
│ ├── AttachmentTools.java — 1 MCP tool for files and attachment context
│ ├── IncidentPrompts.java — 4 MCP prompts for issue investigation
│ ├── IssueAnalyticsTools.java — 2 issue-analytics MCP tools (blocker chain, stale)
│ ├── IssueStructureTools.java — 2 MCP tools: issue tree and change history
│ ├── IssueTools.java — 5 core issue MCP tools
│ ├── IssueWriteTools.java — 4 optional issue-write MCP tools
│ ├── ProjectTools.java — 4 project MCP tools
│ ├── ReferenceDataTools.java — 6 reference-data MCP tools
│ ├── ReleaseAnalyticsTools.java — 5 release/project analytics MCP tools
│ ├── SearchTools.java — 1 global-search MCP tool
│ ├── TimeEntryTools.java — 2 time-entry MCP tools
│ ├── TimeEntryWriteTools.java — 1 optional time-entry creation MCP tool
│ ├── UserTools.java — 1 current-user MCP tool
│ ├── WikiTools.java — 3 wiki MCP tools
│ └── WikiWriteTools.java — 2 optional wiki-write MCP tools
└── src/main/resources/
├── application.yml — MCP server configuration (stdio)
└── logback-spring.xml — logging configuration
トラブルシューティング
- 「Gradle には JVM 17 以降が必要です」 —
JAVA_HOMEが JDK 25 以降を指すように設定してください - 接続拒否/401 —
REDMINE_URLとREDMINE_API_KEYを確認してください。テスト:curl -H "X-Redmine-API-Key: <key>" <url>/users/current.json - 検索結果がありません — Redmine で
/search.jsonが利用可能であることを確認してください(管理者が無効にしている場合があります)
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。