laver-mcp について
laver-mcpは、エージェントがLaverのワークスペースを読み取り、操作するためのMCP サーバーです。ボード、チケット、Wikiページを扱い、公開REST APIを直接呼び出して、バージョン競合やAPIエラーをエージェントに返します。
主な機能
- 01ボード、チケット、コメント、Wikiページの読み取りと検索
- 02チケット、コメント、サブタスク、ボードの作成と更新
- 03ボードの列、グループ、ラベル、カスタムフィールドの管理
- 04チケット添付ファイルのアップロードと取得
- 05チケットのバージョンによる同時書き込みの検出
活用シーン
- 01ワークスペース全体の期限超過・未割り当てチケットを確認
- 02同時変更を検出しながらチケットを更新
- 03ワークスペースのボード、チケット、Wikiを検索
- 04チケットにファイルや画像を添付
MCP 対応
MCP サーバーとして、Laverのワークスペース操作をMCP クライアント向けのツールとして公開します。ワークスペース単位のAPIキーを使い、Laverの公開REST APIへリクエストを転送します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
npx -y @laver/mcpLAVER_API_KEYシークレットA workspace-scoped API key, created in Laver under Admin → API keys. It acts as the person who created it, so it holds exactly their access and can be revoked without touching their account. Supply this or LAVER_API_KEY_FILE.LAVER_API_KEY_FILEシークレットAlternative to LAVER_API_KEY: a path to a file holding nothing but the key, or a .env-style file carrying a LAVER_API_KEY= line. Use this to keep the key out of your client's config file.LAVER_API_URLOverrides the API host. Defaults to https://api.laver.app, and must be https except for localhost.ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
59掲載時のツール一覧 · 3 週間前に更新
このツールにパラメーターはありません。
詳細
@laver/mcp
Laver 用の MCP サーバーです。エージェントに、カンバンボード、チケット、ワークスペースの Wiki を読み取り、操作するためのツールを提供します。
各ツールは、ウェブアプリが使用するものと同じ公開 REST API を呼び出す薄いラッパーです。ローカル状態もキャッシュもなく、機能を別途実装しているわけでもありません。Laver が書き込みを拒否した場合、その拒否がそのまま返されます。エージェントは「409、読み直して再試行」には対応できますが、「問題が発生しました」では対応できないためです。
セットアップ
Laver の Admin → API keys で、ワークスペーススコープの API キーを作成します。そのキーは作成者本人として動作するため、作成者にできることだけを実行でき、それ以上のことはできません。また、作成者のアカウントに影響を与えずにキーを無効化できます。
{
"mcpServers": {
"laver": {
"command": "npx",
"args": ["-y", "@laver/mcp"],
"env": { "LAVER_API_KEY": "your key here" }
}
}
}
LAVER_API_URL を設定すると API ホストを変更できます。デフォルトは https://api.laver.app です。
LAVER_API_KEY_FILE は LAVER_API_KEY の代わりに使用できます。キーだけが記載されたファイル、または複数の行の中に LAVER_API_KEY=… の行がある .env 形式のファイルへのパスを指定します(代入行が優先されます。引用符と export 接頭辞はいずれも使用できます)。この方法により、このリポジトリの .mcp.json では、追跡対象のファイルに秘密情報を含めずにサーバーを登録しています。
代入行がなく、トークンが複数含まれるファイルの場合、キーは一切取得されず、「key is not set」というエラーになります。以前はファイル全体がトークンとして送信されていました。キーだけを含むファイルなら問題ありませんが、それ以外の場合は情報漏えいにつながります。
LAVER_API_URL は、localhost を除いて https である必要があります。
このリポジトリでの作業
リポジトリのルートにある .mcp.json は、プロジェクトを開いたすべての人がこのサーバーを使えるよう登録し、gitignore 対象の .env からキーを読み込みます。エクスポートは不要です。
この設定では、隣にある mcp/server.js ではなく、公開済みパッケージの npx -y @laver/mcp を実行します。意図的な設定です。ローカルファイルを指定すると、ここにいる全員がユーザーの使わないコードパスを実行することになります。実際、そのために 0.1.0 は bin 経由で起動したときにトランスポートを接続しないエントリーポイントを公開してしまいました。実際のクライアントがサーバーを起動する方法は、これだけです。公開しているものを実行することで、ユーザーが使うものと同じものを使えます。
このサーバーを編集している場合は、同じ設定が原因で変更が反映されないことがあります。公開するまで変更は反映されません。作業中は、クライアントが作業コピーを参照するように変更してください —
{ "command": "node", "args": ["mcp/server.js"] }
— そしてコミット前に元に戻してください。npm run check と
frontend/tests/check-mcp-bin-entrypoint.mjs はどちらも常に作業コピーに対して実行されるため、テストが公開に依存することはありません。
クライアントが MCP サーバーに接続するのは起動時だけです。 セッションの実行中に claude mcp add を実行しても、そのセッションにツールが追加されることはありません。サーバーが起動する前にツール一覧が作成されているためです。新しいセッションを開始するか、クライアントの MCP パネルから再接続すると、ツールが表示されます。
ツール
読み取り
| ツール | 得られる情報 |
|---|---|
list_workspaces | UUID がない場合に、どこから始めればよいか |
list_boards | ワークスペース内のボード |
get_board | ステータス列、ラベル、メンバー、チケットを含むボード |
list_tickets | ボード上のチケット。フィルターとページ分割に対応 — ボードを追跡するには updated_since を使います |
list_workspace_tickets | すべてのボードを一度に横断してトリアージ — overdue、unassigned、またはフリーテキスト |
get_ticket | サブタスクを含むチケットの全情報、version も含みます |
get_ticket_comments | コメントとアクティビティ履歴 |
get_ticket_flow | チケットが各列に滞在した時間 |
list_custom_fields | ボードのカスタムフィールド定義 — update_ticket が書き込む UUID |
list_labels | ワークスペース内のすべてのラベル。特定のボードですでに使われているものに限りません |
search | ワークスペース全体のボード、チケット、Wiki ページ、コメントを一度に検索 |
list_workspace_tickets はスタンドアップ時の確認に使います。board_uuid は不要で、すべてのボードを巡回せずに「期限を過ぎているもの」と「担当者がいないもの」に答えられるのは、ここにあるツールの中でこれだけです。意図的に list_tickets の小規模版として設計されており、1 ページで、デフォルトは 50 件、最大 200 件、カーソルはありません。そのため、ページ分割するのではなく、絞り込んでください。
get_ticket_flow は、チケットの履歴に記録された移動から数値を算出します。複数のチケットを合計する場合は、by_status の合計ではなく visits を確認してください。同じバッチで作業したチケットの時間は重複し、合計値は実際の所要時間にはなりません。gaps は、履歴とチケットの現在の列が一致しない場合を示します。そのため、合計値は実測値ではなく下限値になります。
ボードを追跡するには、前回の呼び出しで返された server_time を updated_since に設定して、再度 list_tickets を呼び出します。変更されたチケットだけが返されます。GET /boards/:uuid/events のサーバー送信イベントストリーム用のツールはありません。ツールの呼び出しは 1 回のリクエストと 1 回の応答であり、終わらないストリームはどちらにも当てはまらないからです。
取得する情報を絞る。 ツールの結果はモデルのコンテキストを消費します。また、回避できない呼び出しは 3 つあります。status_uuid または label_uuid は get_board から、page_uuid は get_wiki_tree から取得します。負荷の高いボードでは、それぞれ 154 kB、119 kB、180 kB でした。現在はどの呼び出しにも応答を絞り込むパラメーターがあり、いずれも明示的に指定する必要があります。パラメーターを指定しない呼び出しの動作は変わりません。
| 呼び出し | 得られる情報 | 実測値 |
|---|---|---|
get_board(include_tasks: false) | 構造のみ — ステータス、ラベル、フィールド | 155 kB → 17 kB |
get_wiki_tree(depth: 1) | トップレベルのみ。配下の項目は含まれません | 119 kB → 1.8 kB |
get_wiki_tree(parent_page_uuid: …) | 1 ページと、その配下すべて | 119 kB → 9.8 kB |
list_tickets(include_descriptions: false) | 本文を除いたタイトルと UUID | 167 kB → 45 kB |
チケットではなく UUID を取得するために呼び出す場合は、get_board(include_tasks: false) を使ってください。チケットが必要な場合は list_tickets を使います。こちらは status と limit も指定できます。
書き込み
| ツール | 注記 |
|---|---|
create_ticket | status には列名を指定するか、status_uuid を渡します。description 内の Markdown は解析されます |
update_ticket | version が必要です。description 内の Markdown は解析されます。custom_fields はフィールド UUID をキーとし、オブジェクト全体を置き換えます |
move_ticket | version と列が必要です。どちらかがない場合は 400 になります |
comment_on_ticket | body 内の Markdown は解析されます。version は不要なため、409 にはなりません |
update_comment | 自分のコメントのみ対象です。本文全体を置き換え、編集済みとしてマークされます |
delete_comment | 自分のコメントのみ対象です。ゴミ箱に移動します。ここには復元する機能はありません |
mark_comments_read | キーが操作するユーザーの、このチケットの未読バッジを消去します |
add_subtask | チェックリスト項目を 1 つ追加します。末尾に追加されます。プレーンテキストであり、Markdown ではありません |
update_subtask | 完了にする(is_done)、名前を変更する、またはリスト内で上に移動します |
delete_subtask | 復元できません。チェックリスト項目にはゴミ箱がありません |
archive_ticket | ゴミ箱に移動します。30 日間は復元できます |
delete_ticket | ゴミ箱にあるチケットを完全に削除します。復元できません |
create_board | オプションでテンプレートから作成できます。crm または sales-leads |
link_tickets | 「こちらを先に、その後にあちら」——方向は blocks または blocked_by です |
unlink_tickets | どちら側からでも実行でき、チケットの組み合わせにあるすべての種類のリンクを削除します |
コメントにはバージョン管理がないため、3 種類のコメント書き込みはいずれも
version を指定せず、409 にもなりません。最後の編集が優先されます。編集または削除できるのは作成者のみです。他のユーザーのコメントは、存在しないコメントと区別できない 404 になるため、誰が何を書いたかが報告されることはありません。
get_ticket_comments は意図的に既読状態を変更しません。既読状態を変更するのは
mark_comments_read だけです。この操作は、購読するのではなく、その時点で存在する最新のコメントまでを既読にします。
サブタスクはチケット上のチェックリストです。カードに進捗数が表示され、受け入れ基準を一つずつチェックする場合に記載する場所です。
get_ticket は項目そのものを返すため、個別の一覧取得ツールはありません。
ボードの構造
| ツール | 備考 |
|---|---|
create_status | 新しい列を右端に追加します |
update_status | 名前や色を変更するか、is_complete を設定します — ボードごとに設定できるのは最大 1 つです |
reorder_statuses | 並び順に並べた完全な UUID のリストが必要です。古いリストを渡すと 409 になります |
delete_status | 列が空である必要があり、ボードには 1 つ残す必要があります |
create_group | スイムレーンです。名前を変更するルートはないため、名前を間違えた場合は削除して作り直します |
reorder_groups | reorder_statuses と同じく、完全なリストを指定する必要があります |
delete_group | チケットはグループなしの状態で残り、すべてのバージョンが変更されます |
create_custom_field | ワークスペースのオーナーまたは管理者が実行できます。type は後から変更できません |
update_custom_field | 名前や順序を変更するか、選択肢の options リスト全体を置き換えます |
delete_custom_field | そのフィールドの全チケットの値も一緒に削除されます — ゴミ箱や復元機能はありません |
エージェントが作成したボードをテンプレートのデフォルト設定から変更するには、これらを使います。2 つの並べ替えツールがリスト全体を要求するのは、一部だけを指定すると、2 つの並べ替えが同時に行われた際に列がひっそりと失われることがあるためです。呼び出す直前に get_board から UUID を読み取り、409 が返されたら再度読み取ってください。
ラベル
| ツール | 備考 |
|---|---|
list_labels | ワークスペース全体のラベルをアルファベット順で返します — get_board には、そのボードで使われているものだけが表示されます |
create_label | 16 進数カラーが必要です。名前は大文字小文字と空白を区別せず一意です |
update_label | ラベルの名前を すべての場所で 変更します — ボードごとにコピーが作られるわけではありません |
delete_label | そのラベルが付いているすべてのチケットから削除します |
ラベルはすべてのボードで共有されるワークスペースオブジェクトです。名前を変更する前に必ず確認してください。変更は全員に反映されます。これらのツールが返す UUID を update_ticket の label_uuids に渡します。
添付ファイル
| ツール | 備考 |
|---|---|
list_ticket_attachments | 名前、種類、サイズ、UUID を返します — ファイルの内容は返しません |
get_ticket_attachment | テキストはインラインで、画像は画像ブロックで、それ以外は save_to 経由で返します |
upload_ticket_attachment | ディスク上のファイルには file_path、作成した内容には text と filename を指定します |
delete_ticket_attachment | 30 日間ゴミ箱に移動します。復元ツールはありません |
get_ticket は attachment_total を返すため、一覧を取得するためにラウンドトリップする価値があるかどうかを判断できます。
バイナリコンテンツはツール境界を 越えない 形で受け渡されます。ツールの結果はテキストであり、Laver ではファイルごとに 25 MB まで許可されています。25 MB の Base64 はおよそ 900 万トークンに相当するため、インラインで返されるのはテキスト、CSV、4 MB 未満の画像だけです。それ以外はすべて save_to が必要です。save_to は、このサーバーを実行しているマシン上のパスにファイルを書き込みます(通常は、クライアントがサブプロセスとしてサーバーを起動するため、エージェント自身のマシンです)。アップロードも同じ仕組みで、file_path はそのマシンから読み取るため、コンテキストを消費しません。
画像はテキストではなく MCP の画像ブロックとして返されます。モデルが実際に確認できるのはこの形式だけです。誰かが添付したスクリーンショットはたいてい仕様そのものなので、これがこのツールの重要な役割です。
Wiki
list_wikis、search_wiki、get_wiki_tree、get_wiki_page、
get_wiki_page_version、append_wiki_page、update_wiki_page、
create_wiki_page — 本文を Markdown として受け取り、parent_page_uuid の下に
ネストするもの — と restore_wiki があります。
Wiki をアーカイブすると(ブラウザーで行います。ここにはそのためのツールはありません)、その Wiki と配下のすべてのページが list_wikis から完全に除外されます。代わりに表示するには、list_wikis に archived: true を指定します。アーカイブ済みの wiki_uuid を確認できる場所はここだけです。また、ここでそれを扱えるのは restore_wiki だけです。このツールを呼び出すと、Wiki と配下のすべてのページのアーカイブが一度に解除されます。
上書きされた内容を読むには get_wiki_page_version を使います。これは読み取り専用で、ページは移動しません。古いバージョンを戻すツールは意図的に用意されていません。内容を読んだうえで、update_wiki_page を使って必要な文面を書き込んでください。その操作自体も新しいバージョンとして残ります。
append_wiki_page はページ末尾に追記し、update_wiki_page はページの内容を置き換えます。追記の場合は、前者には version の指定が不要で、2 つのエージェントが同時に追記しても両方のテキストが残るため、前者を優先してください。置き換えには get_wiki_page で取得した version が必要です。その間に誰かがページに書き込んでいた場合は、上書きされる代わりに現在のバージョンを含む 409 が返されます。Wiki ページはリアルタイムの共同編集エディター上にあるため、このガードがあることで置き換えが可能になっています。置き換えると、書き込んだ内容を基にそのエディターが再初期化されるため、ページを開いている同僚には古い内容が戻されるのではなく、新しいテキストが表示されます。また、以前の保存内容はすべて get_wiki_page_version から引き続き読み取れます。ページを削除するツールはありません。
Markdown は、チケットの説明と同じパーサーで処理されます。見出し、リスト、表、コードブロック、引用、水平線、リンクは保持されます。 形式の画像も、その URL への参照として保持されます。ここには添付ファイルをアップロードするツールがないため、URL はあらかじめ公開されている必要があります。生の HTML は解釈されず、文字列として保持されます。
自動化
| ツール | 注記 |
|---|---|
list_automations | ボード上のルール。各ルールには version があります |
get_automation | 1 つのルール全体。編集時に置き換えられる条件とアクションを確認できます |
list_automation_runs | ルールが実際に行った処理。新しい順に表示されます |
create_automation | オーナーまたは管理者のみ。呼び出す前に以下を確認してください |
update_automation | version が必要です。enabled: false で元に戻せる停止が可能です |
delete_automation | version が必要です。ルールの実行履歴全体も削除されます |
自動化ルールは、トリガー、任意の条件、最大 20 個のアクションからなり、ボードに保存されます。エージェントがこれらのツールを使う前に知っておくべきことが 3 つあります。
- ここで作成したルールは、ただちに有効になります。 トリガーが発生すると数秒以内に実行されるため、動作を確かめる目的で見込みだけで作成するのではなく、作成後に
list_automation_runsで確認してください。 - ルールは継続的な権限付与です。 このサーバー上の他の書き込みとは異なり、1 回限りではなく、存在する限りトリガーのたびに、このキーが使うユーザーとして実行されます。キーを無効にしても停止しません。停止するには、ルールを無効化または削除する必要があります。
- 削除する前に一時停止してください。
enabled: falseを指定してupdate_automationを呼び出すと、問題のあるルールをただちに停止し、履歴を保持できます。削除すると、ルールとともに履歴も消去されます。conditionsとactionsは保存済みのリストに追加されるのではなく、リスト全体を置き換えます。そのため、記憶を頼りにせず、get_automationの結果を基に内容を作成してください。
どちらの書き込みにもルールの version が必要で、チケットへの書き込みと同じ仕様で、現在のバージョンを含む 409 が返されます。
公開リンク
list_published_links はインベントリを読み取ります。このワークスペースのうち、現在インターネット上に公開されているものを確認でき、各行には共有トークン、公開者、公開日時、見知らぬ人が閲覧した回数が表示されます。live は見知らぬ人が実際に閲覧する内容を示し、dark_reason はその行が公開されていない理由を示します。これにより、現在アーカイブされていて、誰かが復元すればすぐに再公開される公開ページを見つけることができます。ワークスペースのオーナーまたは管理者のみが利用でき、一般メンバーには 403 が返されます。リンクを非公開に戻す機能は、意図的にツールとして提供していません。公開されているものを報告し、どれを取り下げるかは人が判断できるようにします。
対象外
REST API はこのサーバーより大規模で、その差は意図的なものであり、偶然ではありません。mcp/route-coverage.js には、バックエンドのすべてのルートと、それを呼び出すツール、またはツールがない理由が記載されています。また、どのルートもそのどちらにも該当しない場合、npm run check は失敗します。これによって、このセクションの内容を正確に保っています。以前は気付かないうちに古くなり、その結果、チェックがすべて成功したまま、サーバーがチケットの添付ファイルを読み取れない状態がずっと続いていました。
未対応 — 必要とされていますが、まだ実装されていません。
- 通知。 依然として最大のギャップですが、今ではツールでは解決できない問題が障壁になっています。エージェントは、自分がメンションされたことや割り当てられたことを確認できません。また、
backend/notifications/index.jsはプラグイン全体にsession_onlyを設定しているため、どれほど優れたツールでも、そこにあるすべてのルートはキーに対して 401 を返します。追加するにはまず、他の人のメッセージを含む受信箱をキーで読めるようにするかどうかを決める必要があります。これは提供作業ではなく、プロダクトとセキュリティに関する判断です。それまでは、list_workspace_ticketsがトリアージの半分をカバーする、最も近い代替手段です。 - サブタスクだけを一覧表示する機能。 不足しているのはツールではなく、その必要性です。
get_ticketはチェックリストの項目そのもの(uuid、タイトル、完了状態)をすでに返すため、専用の一覧ルートを作ると、同じ質問をする方法が二つになってしまいます。作成機能はカバーされています。 - ボードテンプレート。 ワークスペースでは、独自のボードをテンプレートとして保存し、次のボードをそこから作成できます。一覧表示するツールがないため、保存済みのテンプレートにアクセスできません。
create_boardのスキーマには組み込みの ID が二つ記載されていますが、保存済みテンプレートの ID は uuid であり、ここにある機能では見つけられません。保存と削除は未対応なのではなく、意図的に含めていません。テンプレートは、全員のボード作成フォームで使われるワークスペース全体の要素であり、その一覧への追加や削除は、ボードの前で行うべき判断だからです。 - 添付ファイルのサムネイル。 ギャップではなく、意図的なものです。サムネイルルートは、カードのカバー画像のサイズをメガバイトではなくキロバイトに抑えるため、縮小した webp をウェブクライアントに提供します。エージェントが必要とするのは、誰かが実際にアップロードしたファイルです。
get_ticket_attachmentはすでに、元の形式のままフル解像度で返します。 - 前回の続きから再開する機能。 ⌘K パレットで、何も入力する前にユーザーに提示される五つの項目、つまり最後に開いた、または作業したチケットとページです。キーを使って行った作業は意図的にここから除外されています。この機能を追加すると、キーの所有者がどのチケットを読んでいたかを尋ねることになります。次に取り掛かる対象を選ぶには
list_workspace_ticketsのほうが適しており、より具体的な対象にはsearchが適しています。 - ボード分析。 トリアージの半分を
list_workspace_ticketsがカバーするようになった現在では、少し物足りない部分です。残る機能は判断材料というよりチャート向けです。統計とボード全体の進行状況は画面で読む集計値であり、アクティビティはフィード、search-text は入力中の検索、エクスポートはファイルを返します。エージェントが実際に判断に使う唯一の数値、つまり個々のチケットの値は、関連付け可能なget_ticket_flowで取得できます。 - ボードの対象となっている Wiki ページ。 回答に必要な情報がすでにすべて取得可能で、ルートの役割が単なる結合にすぎないため、意図的に含めていません。
get_boardはボードのwiki_page_uuidを返し、get_wiki_pageとget_wiki_treeは同じアクセスルールのもと、そのページと配下のすべてを読み取ります。しかも、より多くの内容を取得できます。このルートは、ボードを見ている人が名前を覚えていなくてもハンドブックにたどり着けるようにするものです。uuid を持っているエージェントには、そのような近道は必要ありません。 - 指揮役向けのスコアボード。 ツールの実装が簡単かどうかにかかわらず、決して追加しません。このルートは、エージェントが引き受けた後に、ある一人が作成したチケットがどうなったかを、その人だけに読み返すものです。エージェントが自分に説明を依頼する人たちのスコアを読むのは、順序が逆です。また、それを読めるエージェントは、スコアを意識した行動を取る可能性があります。
- 自動化ボタンを押す機能。 未対応なのではなく、意図的に含めていません。
manualルールは、実行するタイミングを人が決めるために存在します。それを押すツールを追加すれば、その判断を人から取り上げることになります。安全な範囲であるルールの作成機能はカバーされています。 - チケットの履歴、複製、繰り返し。
- スプリント。 通知と同じ理由で障壁があります。
backend/sprints/index.jsはプラグインにsession_onlyを設定しているため、POST /boards/:uuid/sprintsを含め、そのすべてのルートでキーに 401 が返されます。キーに公開するかどうかは、チームの計画サイクルにキーが何を行えるかという判断です(ロールオーバーでは、未完了のチケットすべてが新しいボードに移行されます)。ツールを書くかどうかの問題ではありません。 - Wiki ページの削除と並べ替え。
update_wiki_pageによって、ページの編集はすでにカバーされています。アーカイブ、移動、複製はカバーされていません。これらはページの内容ではなく、同僚がページを見つけられるかどうかを変える操作であり、誰にも見つけられないページには参照できるバージョン履歴もありません。Wiki 全体の削除(DELETE /wikis/:wiki_uuid。Wiki とその配下にあるすべてのページをアーカイブします)も同じ分類です。Wiki の公開ページをアーカイブすると同時にインターネットから取り下げる操作であり、編集ではなく同意に関わるものです。代わりに、list_wikisでアーカイブ済みの uuid を見つけられるようになったため、restore_wikiによる復元ルートはカバーされています。 - Wiki ページへのコメント。 呼び出しの形式ではなく、アンカーの仕組みが理由で未対応です。コメントは、対象となる文章(引用と、その文章が複数回出てくる場合はどの箇所か)に紐付けられます。ページは共同編集されるため、保存済みの文書内の位置は、同僚がその上に文字を入力した瞬間に別の文章を指すようになります。クライアントは、直前にレンダリングした文書から引用を再検索します。エージェントは文書を保持していないため、ページにあると考えている引用を送ることになります。そして、最もよく起きる失敗は、気づかれないことです。両端で数え方が異なるために、二度出てくるフレーズが間違った文にコメントを紐付けてしまいます。役に立つツールを作るなら、ページと引用を受け取り、引用が見つからなかった場合は明確に伝えるものにするべきです。エージェントにページのレビューを依頼することがあるなら、次に取り組むべきなのはこれです。それまでは、ページについて伝えるための誠実な方法がすでにキーに用意されています。
append_wiki_pageとupdate_wiki_pageを使えば、他のツールでは読み返せない余白ではなく、読む人に見えるページの中に内容を書き込めます。編集、取り消し、解決も同じ理由で未対応です。コメントできない以上、キーが編集するものはありません。特に解決は、他の人の文章についたハイライトを外し、人同士の会話が終わったことを宣言する操作です。スレッドの読み取りも、それ自体の理由で未対応です。コメントは下書きについての議論であり、ページの内容を知りたいエージェントにはget_wiki_pageが適しています。 - インポートとフィードバックフォーム。 キーからでは決してありません:
- デプロイを報告する。
POST /tasks/:task_uuid/deploymentsは、ビルドパイプラインが Laver に、チケットのプルリクエストがある環境に到達したか、または到達に失敗したかを伝え、担当者に知らせる方法です。呼び出すのはシークレットにキーを保持する CI ジョブで、モデルが動作していないタイミングです。これをツールにすると、パイプラインが実施していないデプロイをアシスタントが通知できてしまいます。通知の価値は、主張ではなく事実を報告することにあります。エージェントが必要とする可能性のある読み取り機能は、すでに用意されています。デプロイはチケットイベントなので、get_ticket_flowとタイムラインから、何がいつ起き、どのキーが報告したかを確認できます。 - プルリクエストのマージを報告する。
POST /tasks/:task_uuid/pull-requests/mergedも同じ考え方です。CI ジョブがチケットのプルリクエストがマージされたと伝えると、ボード上でチケットがマージ済みを示す列に移動します。ツールにすると、カードを移動するもう一つの手段になります。エージェントにはmove_ticketがありますが、この方法は、タイムラインに「このチケットのプルリクエストがマージされた」と記録する点だけが異なります。何もマージしていないアシスタントが、そう主張するのは適切ではありません。読み取りには対応しています。マージはチケットイベントなので、get_ticket_flowから確認できます。 - 公開リンクと公開。 公開すると、非公開の情報が URL を知っている人なら誰でも読める状態になります。これは同意を伴う行為であり、ツール呼び出しには適しません。
- 公開済みリンクを取り下げる。 読み取り機能はリリースされましたが、2 つの DELETE はリリースされませんでした。これは同じ考え方によるものです。ツールでは同意を示せません。ただし、何が公開されているかを尋ねることまで禁じるものではありません。
list_published_linksはその質問に答えるもので、呼び出し元に既存以上の権限を与えません。名前が挙がるリンクはすべて、定義上公開されているためです。リンクを取り下げるのは、何が見えなくなるかを画面で確認したうえで行使する、範囲の限られた管理者権限です。そのため、エージェントは一覧を報告し、何を取り下げるかは人が判断します。 - 人に署名を依頼する。 これは未実装というだけではなく、ルートで拒否されます。3 つのルートすべてが、何も読み取る前にキーに対して 401 を返します。リクエストを送ると、SPF と DKIM を付けて、見知らぬ人の受信トレイにメッセージが届きます。また、ある宛先に署名を依頼するべきかどうかは、人が判断することです。キーは発行した人として動作し、その人の編集権限を引き継ぐため、権限で阻止することはできません。未処理のリクエストの一覧表示は、このやり取りに固有の読み取り機能です。添付先となる可能性のある、最新のドキュメントから算出したセクションとともにリクエストを返します。また、本文はすでに
get_wiki_pageから確認できます。リクエストの取り消しも、反対側から見た同じ判断です。 - ボードを取り除くことと、その見た目。 このグループの構造に関する部分には対応済みです。ステータス、グループ、カスタムフィールドにはすべてツールがあります。残っているのは削除と装飾です。ボードのアーカイブと削除は、呼び方が異なるだけで、どちらも書き込み操作です。いずれかをツールにすると、キーによる 1 回の呼び出しで、ボード全体とその上のすべてのチケットをワークスペースの表示から消せてしまいます。その結果、復元にも対応できません。エージェントがボードをアーカイブする方法がなく、
list_boardsでは意図的にアーカイブ済みの UUID を見つけられないためです。完全削除はさらに重大です。行、チケット、その添付ファイルのデータがすべて削除されます。何を失うかを画面で確認したうえで、人が 2 回判断する操作です。ボードの色や背景画像は、ボードを見ながら選ぶ装飾であり、エージェントにはできないことの一つです。列の受け入れ要件もここに含まれます。get_boardはすでに各列のentry_requirementsを返し、拒否されたmove_ticketはチケットが満たしていない要件をすべて示すため、読み取り用のツールは必要ありません。しかし、それらを設定できるキーがあれば要件を取り除いてからチケットを移動できるため、ゲートの強度は、それに対するツールのうち最も弱いものと同程度にしかなりません。 - ボードを別のワークスペースに移動する。 これは影響範囲に関する判断の問題ではありません。キーでは、この呼び出し自体ができません。キーの権限は発行先の 1 つのワークスペースに限定されますが、
POST /boards/:board_uuid/move-workspaceでは 2 つのワークスペースを指定します。ボードが現在あるワークスペースと、移動先のワークスペースです。この操作をツールにするには、両方にアクセスできるキーが必要となり、そうすると権限の限定が失われます。そうでなければ、ツールは渡されたすべての呼び出しを拒否することになります。この操作はエージェントが行うものでもありません。2 つのワークスペースの管理者が、チケット、コメント、添付ファイル、履歴を含むボード全体をどちらに所属させるか決めます。また、このルートでは、何かを移動する前に移動元と移動先の両方でオーナーまたは管理者であることが求められます。 - ワークスペースとメンバーシップの管理。 キーは作成した人として動作します。その人のワークスペースの名前変更や削除、あるいはその人に代わって招待に回答することは、ボードのタスクを委任する意図を超える操作です。
- ワークスペース全体のエクスポート。
POST /workspaces/:uuid/exportsとその関連ルートは、ワークスペース内のすべてのチケット、コメント、Wiki ページを含む 1 つのファイルを作成します。また、ほかの情報を確認する前にキーを拒否します。CI 変数に保存されたキーからエクスポートを要求できるようにすると、そのキーが漏えいした場合、付与された範囲内のアクセスではなく、データ全体の侵害につながります。会社のデータのコピーを取得するのは、サインインして Admin から人が行う操作で、監査証跡には操作した人が記録されます。 - チケットの一括書き込み。
POST /tasks/archiveは、1 回の呼び出しで複数のチケットをゴミ箱に入れます。archive_ticketを 1 件ずつ実行するのが、慎重な選択です。 - ゴミ箱。 意図的に一方通行になっています。エージェントはアーカイブでき、すでにアーカイブしたものを削除できますが、元に戻すのは人です。
- ボードイベントストリーム。 サーバー送信イベントです。ツール呼び出しは 1 回のリクエストと 1 回の応答で構成されます。代わりに
updated_sinceを指定したlist_ticketsを使います。 - スケジューラのエンドポイント。 デプロイ用の cron フックです。
チケットの削除
意図的に2段階にしています。1回の呼び出しだけで何かが破棄されることはありません。
archive_ticket task_uuid → the workspace trash, recoverable for 30 days
delete_ticket workspace_uuid + task_uuid → gone, and nothing brings it back
delete_ticket は、すでにアーカイブされているもの以外を受け付けないため、慣例ではなくサーバーによって順序が強制されます。ここには復元ツールはありません。ゴミ箱に入ったチケットはウェブアプリから戻す必要があります。そのため、自分でできるのは archive_ticket までだと考えてください。
チケットを破棄するつもりなら、アーカイブする前に読み取ってください。delete_ticket には workspace_uuid が必要で、それを取得できるのは get_ticket です。また、アーカイブ済みのチケットは読み取れなくなります。
次に何をすべきかを判断する
チケットを読み取るたびに、blocked_by、blocks、is_blocked が含まれます。すべてのブロッカーが完了列に到達すると is_blocked は false になるため、ボードで作業を開始できるチケットは is_blocked が false のものです。link_tickets は依存関係を記録します。循環を作るリンクは、順序を判断できなくなるため、409 で拒否されます。
知っておくべき唯一のルール
チケットには version が含まれます。すべての書き込みで、読み取ったバージョンを送信する必要があります。古いバージョンに対する書き込みは、先に更新した人の変更を黙って上書きするのではなく、409 で拒否されます。サーバーはこれを指示文に変換します。また、Laver の拒否応答には現在のバージョンが含まれるため、2回目の呼び出しをせずに指示文にそのバージョンを含められます。
Laver 409: Task was updated by another request.
先に誰かが書き込んだため、送信したバージョンは古くなっています。現在のバージョンは12です。変更が読み取った内容に依存しない場合(たとえば、チケットを指定した列に移動する場合)は、そのバージョンで再試行してください。依存する場合は、
get_ticketを再度呼び出し、現在のチケットの状態を確認して判断してください。そうしないと、他の人の変更を知らないうちに取り消すことになります。
読み取ってから書き込んでください。長いやり取りの間、バージョンをキャッシュしてはいけません。
キーが拒否された場合
401 はキーに関するエラーです。キーが見つからない、入力を間違えた、取り消された、期限切れになった、または未入力のままのプレースホルダーである場合に発生します。元のメッセージが実際に起きたことを正確に説明しているとは限りません。JWT レイヤーで解析できないキーの場合、通常の原因は単にキーが置き換えられただけでも、「Authorization token is invalid: The token is malformed」 と返されます。これは文字列が破損したように聞こえます。サーバーは、見落とされやすい点も含めて、対処方法を追加します。
MCP クライアントはサーバーの起動時に環境変数を一度だけ読み取るため、その後は再起動が必要です。実行中のセッションで設定を編集しても何も変わりません。
403 はこれとは異なり、再試行しても意味がありません。キーは受け付けられたものの、この特定の操作が拒否されています。別のワークスペースに限定されたキーであるか、キーを使って操作するユーザーのロールが読み取り専用であるか、またはそのボードにアクセスできないゲストである可能性があります。
キー自体は決まった1か所でのみ読み取られ、ベアラートークンとして送信されます。ログに記録されたり、出力されたり、エラーテキストに含まれたりすることはありません。
チェック方法
node check.js # schema, then every read-only tool actually called
node check.js --require-live # …and a skipped sweep is a failure, for CI
# the same calls against the API the published package actually talks to
LAVER_API_KEY_FILE=../.env node check.js --live-api
2つの部分で構成されています。1つ目は静的チェックです。登録されたすべてのツールについて、読み取りまたは書き込みに分類し、説明とスキーマを設定します。2つ目は、空いているポートで ../backend からバックエンドを起動し、専用のワークスペースを作成して、そのワークスペースに対するキーを発行し、すべての読み取り専用ツールを呼び出します。各ツールが宣言しているすべてのパラメーターを送信し、ツール独自の zod スキーマを通した後にハンドラーを実行します。
この後半の処理があるのは、前半のチェックを通過した list_wikis が、workspace_uuid を必要とするルートに ?workspace= を送信していたからです。このツールは呼び出すたびに 400 エラーを返していました。また、wiki_uuid を返す唯一のツールだったため、このサーバーの Wiki 機能全体が、登録、説明、スキーマの形状は完璧なまま、リリース当初から利用できない状態でした。
このチェックには、backend/ での npm test に必要なものと同じものが必要です。つまり、そのディレクトリ、node_modules、.env、およびそれらが接続する Postgres です。API キーは不要で、localhost 以外のネットワークも必要ありません。環境内に実際の LAVER_API_KEY があっても無視されます。バックエンドがない場合は、ツールが呼び出されなかったことを示すバナーを表示し、スキーマチェックのみを実行します。--require-live を指定すると、その状態は失敗になります。
ただし、実行範囲がローカルにとどまるかどうかは backend/.env 次第です。実行すると、そのファイルが指定するデータベースに書き込みます。ワークスペース、ボード、チケット2件、コメント、Wiki、ページ、API キーを作成し、最後にそれらを削除します。また、バックエンドを独自のプロセスに読み込みます。app.listen ではなく app.server.listen でリッスンします。これは collab と board-events の統合テストで使われているのと同じ方法で、Fastify の onListen フックは実行されず、7つのスケジューラーも起動しません。この処理がなければ、請求の一括処理だけでも、そのデータベース内のすべてのワークスペースに対して実行されてしまいます。backend/.env がステージングを指していれば、ステージングに書き込みを行うチェックになります。
この 一括チェック は読み取り専用であり、今後もその状態を維持します。実行のたびに誰かのワークスペースにチケットを作成するチェックは、やがて使われなくなるからです。書き込みツールはスキーマチェックのみでカバーされます。書き込みを行わずにカバーする方法については、check.js の末尾にある注記をご覧ください。
Ctrl-C を押しても安全です。一括チェックは実行中の呼び出しが終わった後に停止し、プロセス終了前にフィクスチャのワークスペースを削除します。実行中の呼び出しが停止しない場合は、Ctrl-C をもう一度押すとプロセスを強制終了できます。
デプロイ済み API に対して
--live-api を指定すると、同じ呼び出しが LAVER_API_URL に送られます。特に指定がない場合は https://api.laver.app です。実際のキーは、サーバー自身と同じ方法で、LAVER_API_KEY または LAVER_API_KEY_FILE が示すファイルから取得します。
ローカルでの実行が成功することと、公開済みパッケージが動作することは、別のことだからです。ローカルの検証では、ツールが目の前のコードと整合していることを確認できます。このパッケージはデプロイ済み API と通信するため、パッケージより先にルート名が変更されてリリースされると、ローカルの検証は成功したまま、現場のすべてのエージェントが動かなくなります。ツールとルートは同じリポジトリにあり、一緒に更新されるので、その期間は限られています。しかし、npm への公開によって生じるのは、まさにこの期間です。
どちらのモードも cases.js の同じテーブルを実行し、すべてのケースに両方のモードでの期待値が設定されています。フィクスチャが既知のローカル環境では正確な件数を、ワークスペースが実際のもので、シード作成も後片付けもできないライブ環境では、形式と不変条件を確認します。どちらか一方の期待値しかないケースは失敗します。そのため、新しい呼び出しで片方のトランスポートだけを検証し、もう片方を飛ばすことはできません。
**何も作成せず、何も削除しません。**これは単なる約束ではなく、仕組みで保証されています。ライブモードでは fetch を、GET 以外のメソッドを拒否するものに置き換えるため、書き込みツールが誤って呼び出されても、ネットワークにアクセスすることはできません。frontend/tests/check-mcp-live-api-mode.mjs はスタブ API に対してモード全体を実行し、プロセス外に送信されたすべてのリクエストが GET であることを検証します。
フィクスチャの代わりに、検証対象を探しに行きます。少なくとも 2 つの列にそれぞれ少なくとも 2 つのチケットがあり、ページを 1 つ以上含む Wiki を備えたワークスペース内のボードが必要です。条件を満たさない環境では、何も言わずに成功とするのではなく、実行を拒否します。空のボードに対するフィルターのケースは、フィルターが適用されたかどうかにかかわらず成功してしまいます。このファイル全体が防ごうとしているのは、まさにこの問題です。
明示的に有効にした場合のみ実行され、npm run check:all にも CI にも含まれません。キーとネットワークが必要ですが、どちらもシークレットがない環境で実行されるチェックに含めるべきではありません。
公開
**0.1.0 は公開済みですが、壊れています。誰にもインストールするよう勧めないでください。**起動して 20 個のツールをすべて登録しますが、トランスポートには接続せず、stdout にも stderr にも何も出力せずに 0 で終了します。そのため、クライアントからはプロセスが終了したことしか分からず、それ以外は何も起きません。エントリーポイントのガードは process.argv[1] の ベース名 をこのファイル名と比較していましたが、これは node mcp/server.js の場合にしか一致しません。bin 用の npm のシムでは argv[1] が node_modules/.bin/laver-mcp になるため、この README で誰もが実行するよう案内している npx -y @laver/mcp では一致しませんでした。0.1.1 で修正済みです。また、tests/check-mcp-bin-entrypoint.mjs はシンボリックリンク経由でサーバーを起動して MCP で通信するため、同じ種類のバグが再びリリースされることはありません。
0.1.1 を公開したら、誰も壊れたバージョンを使わないようにするため、次のようにマークしてください。
npm deprecate @laver/[email protected] "Never connects its stdio transport when run via npx or the bin shim. Use 0.1.1 or later."
もう 1 つの選択肢は 0.1.0 の公開取り消しですが、こちらのほうが望ましくありません。72 時間以内ならバージョンは削除できますが、どちらにしても番号は再利用できず、すでにそのバージョンを固定しているものは警告されるのではなく、壊れてしまいます。
公開作業はオーナーが行います。これは公開され、実質的に取り消せないものであり、他の誰も使えなくなる名前を取得するためです。
名前について。 npm の laver は使用済みです。無関係のメンテナーによって 2021 年に v1.0.0 が公開されているため、名前だけの使用はできず、今後もできません。そのため、このパッケージ名は @laver/mcp です。ブランド名はスコープとして維持し、汎用的な部分は適切な場所に置いています。2026 年 8 月 6 日にレジストリを確認したところ、@laver/mcp は空いており、旧名のスコープなしの laver-mcp も一度も公開されていませんでした。そのため、名前の変更による損失はありません。
スコープはすでに存在し、初回公開も完了しています。 0.1.0 と 0.1.1 は @laver/mcp としてレジストリに公開されており、作成日時は 2026-08-06T22:14Z です。スコープが解決され、公開アカウントに書き込み権限があることを証明する唯一の方法が、これです。この段落は以前、スコープはまだ存在しないと書いていました。当時は事実でしたが、現在は違います。
https://registry.npmjs.org/-/org/laver で再テストしないでください。この URL は組織が存在するかどうかにかかわらず、未認証では 404 を返すため、両者を判別できません。代わりにパッケージのドキュメントを確認してください。
curl -s 'https://registry.npmjs.org/@laver%2Fmcp' | python3 -m json.tool
独自のスコープで公開するセルフホスト可能なフォークの場合、最初の公開前に https://www.npmjs.com/org/create でそのスコープを作成する必要があります(公開パッケージなら無料です)。または、そのスコープがアカウント自身のユーザー名であることを確認し、npm whoami でメンバーシップを確認してください。スコープが存在しない場合、npm publish は 404 Not Found - PUT https://registry.npmjs.org/@<scope>%2fmcp で失敗します。このエラーは、組織が存在しないことよりもネットワーク障害のように見えます。
実行ファイル名は laver-mcp のままです。 パッケージ名は @laver/mcp ですが、bin の名前を意図的に mcp に変更していません。グローバルインストールすると PATH に mcp というコマンドが追加されますが、名前が一般的すぎて、インストールするあらゆる MCP サーバーと衝突するためです。npx -y @laver/mcp はどちらの名前でも動作します。npx はパッケージの唯一の bin を、名前にかかわらず実行するため、上記の設定スニペットはコマンド名に依存しません。
repository と bugs は公開ミラーを指しています。 github.com/Developyn/laver だけが置き場所だった間は、これらの項目はありませんでした。ここは非公開で、npm はパッケージページに両方の項目をリンクとして表示するため、「これはどこから来たのか」を示す唯一のリンクが 404 を指すより、どちらもないほうがましだからです。2026 年 8 月以降、公開ファイルは公開リポジトリである github.com/Developyn/laver-mcp にミラーされているため、どちらのリンクも現在は有効です。"directory" キーがない点に注意してください。ミラーではルートがパッケージですが、こちらでは同じファイルが mcp/ の下にあります。
すべての MCP ディレクトリが掲載情報の参照先とするのがこのミラーなので、常に最新の状態にしておく必要があります。公開するたびに、公開された tarball の内容をミラーにコピーしてコミットしてください。npm pack @laver/mcp && tar xzf laver-mcp-<version>.tgz。Dockerfile、glama.json、CI ワークフローはミラー専用であり、files には含まれていないため、npm には公開されません。
mcpName は公式 MCP レジストリ用です。 ここでは、パッケージと公開するサーバー名が照合されます。値は mcp-publisher login github で実際に付与された名前空間と一致している必要があります。組織が認可された場合は io.github.developyn/…、個人アカウントのみの場合は io.github.melvyn-developyn/… です。間違えても致命的ではありませんが、修正するにはもう一度バージョンを上げる必要があります。
公開のたびに、事前に確認すること
- 公開アカウントで 2FA が有効になっている場合は、公開時に 2FA が必須かどうかを確認してください(npm は一部のアカウントやパッケージでこれを必須にし、それ以外では入力を求めます)。
--otpを渡すと、対話なしの実行でプロンプトが原因で失敗するのを防げます。2FA に登録していない場合は省略してください。 npm whoamiがそのアカウント名を返すこと。そうでない場合はnpm loginを実行してください。- ノート PC ではなく CI を使う場合は、
NPM_TOKENに automation トークンを設定してください(パッケージに対する書き込み権限を持つ、きめ細かなスコープのトークン)。automation トークンは 2FA プロンプトを回避しますが、従来の読み書きトークンでは回避できません。 - レジストリにまだ存在しないバージョンであること。 npm は既存バージョンの再公開を拒否するため、これは整理のためではなく、公開そのものに必要です。公開前に現在のバージョンを確認してください。リポジトリとレジストリのバージョン番号が同じでも内容が異なることがあり、その場合も警告は表示されません。
npm view @laver/mcp version。新しいツールにはマイナーバージョン、既存ツールの修正にはパッチバージョンを使用してください。
公開
cd mcp
npm ci # the lockfile, not whatever resolves today
npm run check # schema + every read-only tool actually called
npm pack --dry-run # confirm the file list is LICENSE, README.md, package.json, server.js
npm publish --access public --otp=<code-from-your-authenticator>
npm ciはmcp/node_modulesを削除して再インストールします。共有開発チェックアウトでは、このディレクトリを、そこで実行しているすべてのエージェントと共有しています。実行中に削除するとエージェントのテストが壊れるため、エージェント向けの指示ではこれを禁止しており、リリースの準備をするエージェントはこのブロックの前で停止します。実際に公開する担当者が実行する分には正しく、想定どおりです。ただし、同じツリーで他の人が作業している間は実行しないでください。--access publicは必須です。スコープ付きパッケージはデフォルトで制限付きとなり、無料アカウントで制限付きの公開を試みると拒否されます。package.json のpublishConfigで既に設定されているため、このフラグは念のためのものであり、非公開パッケージになるかどうかを左右する唯一の設定ではありません。
その後
npx -y @laver/mcp # should start and wait on stdio, not exit
npm view @laver/mcp
間違いを取り消せるのは短期間だけです。npm unpublish @laver/mcp@<version> は 72 時間以内であれば実行できますが、その後はバージョン番号が使用済みとなり、再利用できません。バージョンを非公開にしても、パッケージの 名前 は再利用可能にはなりません。
ライセンス
MIT — パッケージに同梱されている LICENSE を参照してください。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。