mcpField
W
Wafeq

Wafeq

ローカル
github.com金融データ16 週間前に更新

Wafeq について

Wafeq は、Wafeq の会計データを扱う利用者向けの MCP サーバーです。公開 API を安全性ラベル付きのツールに変換し、リトライ、冪等性、アップロード、PDF 応答に対応して stdio と Streamable HTTP で動作します。

主な機能

  1. 01OpenAPI から Wafeq API ツールを生成
  2. 02操作に安全性カテゴリを付与
  3. 03書き込みリクエストに冪等性キーを追加
  4. 04ファイルアップロードとバイナリ PDF 応答
  5. 05組織の本人確認とヘルス状態の報告
  6. 06リトライ、レート制限、stdio、HTTP に対応

活用シーン

  1. 01損益レポートや未払い請求書を確認
  2. 02請求書の下書き作成や PDF のダウンロード
  3. 03経費記録に領収書を添付
  4. 04銀行明細と帳簿を照合

MCP 対応

Wafeq の公開 API を MCP クライアント向けのツールとして stdio または Streamable HTTP で公開し、起動時に認証情報の組織を確認します。

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

mcp.json · 共通設定
{
"mcpServers": {
"ohneben-wafeq": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"MCP_TRANSPORT",
"-e",
"WAFEQ_API_KEY",
"-e",
"WAFEQ_ACCESS_TOKEN",
"-e",
"WAFEQ_TOOL_GROUPS",
"-e",
"WAFEQ_API_BASE_URL",
"-e",
"MCP_AUTH_TOKEN",
"ghcr.io/ohneben/wafeq-mcp:2.1.0"
],
"env": {
"MCP_TRANSPORT": "<MCP_TRANSPORT>",
"WAFEQ_API_KEY": "<WAFEQ_API_KEY>",
"WAFEQ_ACCESS_TOKEN": "<WAFEQ_ACCESS_TOKEN>",
"WAFEQ_TOOL_GROUPS": "<WAFEQ_TOOL_GROUPS>",
"WAFEQ_API_BASE_URL": "<WAFEQ_API_BASE_URL>",
"MCP_AUTH_TOKEN": "<MCP_AUTH_TOKEN>"
}
}
}
}
起動コマンドdocker run -i --rm -e MCP_TRANSPORT -e WAFEQ_API_KEY -e WAFEQ_ACCESS_TOKEN -e WAFEQ_TOOL_GROUPS -e WAFEQ_API_BASE_URL -e MCP_AUTH_TOKEN ghcr.io/ohneben/wafeq-mcp:2.1.0
設定が必要な環境変数
MCP_TRANSPORTServer transport. Set to 'stdio' for local MCP clients; the image otherwise starts the Streamable HTTP transport.
WAFEQ_API_KEYシークレットPrivate organization API key, sent as `Authorization: Api-Key <key>`. Wafeq -> Settings -> Developer -> API keys. Required unless WAFEQ_ACCESS_TOKEN is set.
WAFEQ_ACCESS_TOKENシークレットOAuth2 app access token, sent as `Authorization: Bearer <token>`. Use instead of WAFEQ_API_KEY.
WAFEQ_TOOL_GROUPSComma-separated resource groups to expose, e.g. invoices,bills,reports. Empty exposes all 251 generated tools.
WAFEQ_API_BASE_URLOverrides the Wafeq API base URL. Defaults to https://api.wafeq.com/v1
MCP_AUTH_TOKENシークレットOnly for MCP_TRANSPORT=http: bearer token required on /mcp. Without it a non-loopback bind refuses to start.

ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。

パッケージ
ocighcr.io/ohneben/wafeq-mcp:2.1.0

ツール

ツール一覧はまだ取得されていません

ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。

詳細

ohneben's Wafeq MCP

Buy Me A Coffee


ライセンスとチェック

CI License: MIT

MCP レジストリ

MCP Registry Listed on mcpservers.org Wafeq-MCP MCP server

Claude、CursorなどのAIアシスタントや、その他のMCPクライアントから、自然な言葉でWafeqの帳簿を操作できます。

このModel Context Protocolサーバーは、Wafeq Public APIの全251エンドポイントを公開します。OpenAPI仕様から直接生成されたMCPツールに、手書きのツールを2つ加えています。すべてのツールには安全性カテゴリ(🟢読み取り専用/🟡書き込み/🟠状態変更/🔴取り消し不能または破壊的)が付いているため、アシスタントはアクションを実行する前にその内容を把握できます。これにより、請求書の保存と、税務当局への申告との違いも分かります。CRUD形式のラッパーでは、この違いを伝えられません。stdio(Claude Desktopなどのローカルランチャー)またはStreamable HTTP(Dockerでホスト)で動作し、リトライ、クライアント側のレート制限、リクエストタイムアウト、冪等性キー、マルチパートアップロード、バイナリPDFの処理に対応しているため、実際の帳簿を相手にしても安定して動作します。

これを使いたくなる理由

APIにリクエストを転送するだけのMCPサーバーもあります。このサーバーは、LLMが安全に利用でき、実際の会計データに対して簡単に実行できるように設計されています。

得られるもの重要な理由
仕様に基づく全251エンドポイント請求書、仕入請求書、見積書、貸方票・借方票、支払い、銀行業務、仕訳、給与計算、プロジェクト、在庫、レポートを完全にカバーします。恣意的に選んだ項目も、取りこぼした項目もありません。
4つではなく9つの安全カテゴリ 🟢 / 🟡 / 🟠 / 🔴WafeqのPOSTのうち12件は作成処理ではありません。プレビューでは何も書き込まれませんが、償却を早期に終了すると元に戻せない形で元帳に記帳されます。また、請求書を税務当局に申告すると、その組織から永久に離れられなくなります。それぞれを「作成」にひとまとめにせず、個別のバナーで示します。
接続時にサーバーの指示を送信クライアントには、安全性バナーの読み方や、日付形式、小数点の区切り文字、レポート範囲を期間全体にするなど、Wafeq固有のいくつかの規則をあらかじめ伝えます。まず誤った呼び出しをしてから把握する必要はありません。
機械可読なMCPアノテーション(readOnlyHint、destructiveHint)アノテーションに対応するホスト(Claudeを含む)は、98件の読み取り専用ツールを自動的に信頼し、削除を行う、または元に戻せない44件については確認を求められます。
レポートごとに正しいパラメーターを使用4つのレポートそれぞれに独自のスキーマがあります。貸借対照表ではdateとperiod_countを、損益計算書とキャッシュフローではdate_afterとdate_beforeを、試算表ではfrom_dateとto_dateを使用します。Wafeqは誤ったクエリパラメーターを黙って無視するため、名前を間違えても呼び出しが成功したように見えてしまいます。
送信前に期間全体を検証損益計算書とキャッシュフローでは、月または年の全期間に一致しない範囲は拒否されます。サーバーはローカルで検証し、HTTP 400を受け取るための往復通信を行う代わりに、最も近い有効な範囲を返します。
冪等性キーを自動生成X-Wafeq-Idempotency-Keyに対応する146件の書き込みエンドポイントすべてにUUID v4が自動的に割り当てられ、再試行時にも再利用されます。そのため、ネットワークの一時的な問題で請求書が重複することはありません。意図的な再実行を安全に行うには、独自のキーを指定してください。
実際に動作するファイルアップロードPOST /files/ではマルチパート形式のみが許可され、POST /files/raw/にはContent-Dispositionヘッダーが必要です。どちらにも対応しており、base64コンテンツとファイル名を渡すだけです。
バイナリPDFをバイト列として処理9つのPDFエンドポイントでは、PDFをテキストとして読み取って破損させる代わりに、サイズとコンテンツタイプを含む小さなエンベロープにbase64エンコードします。
バックオフ付きの自動再試行一時的な429/5xx応答は、ジッター付き指数バックオフで再試行し、Retry-Afterを尊重します。Wafeqの統合ガイドの要件どおり、同じ冪等性キーを使用します。
レート制限機能を内蔵ツール呼び出しが集中しても429が発生しないよう、自動的にリクエストを抑制します。Wafeqは具体的な上限値を公開していないため、デフォルト設定は意図的に保守的で、変更も可能です。
起動時にテナントを検証Wafeq APIキーは組織に紐付けられています。サーバーはサービス開始前にGET /organization/を呼び出し、その結果を/healthで公開します。そのため、キーの設定ミスは、誤った会社の帳簿への書き込みではなく、確認できる組織名として表れます。
2つのトランスポート:stdioとStreamable HTTPClaude Desktopでローカルに使用することも、常時稼働するサーバーを1つ起動して、任意の数のMCPクライアントからHTTP経由で接続することもできます。
Docker + docker-compose、ヘルスチェック、自動再起動docker compose upを実行すれば起動し、localhostのみにバインドされた状態で稼働し続けます。
HTTPエンドポイントのオプションのベアラートークン認証localhostの範囲外からアクセス可能になる場合は、共有シークレットの背後にサーバーを配置してください。
シークレットがモデルに届くことはありません認証情報はサーバーの環境変数に保存され、各リクエストに注入されます。パススルーツールからAuthorizationを上書きしたり、認証情報の送信先を別のホストに変更したりすることはできません。
仕様を差し替えるだけで更新Wafeqが新しい仕様を公開した場合は、ファイルを1つ置き換えて再ビルドするだけです。新しいエンドポイントが自動的に新しいツールになり、コードの変更は不要です。
比較
機能このプロジェクト汎用 OpenAPI→MCP ラッパー*
Wafeq の全 251 エンドポイントをツールとして提供✅✅
ツールごとの安全性カテゴリとバナー✅❌
税務当局への申告を「作成」ではなく取り消し不能として明示✅❌
readOnlyHint / destructiveHint MCP アノテーション✅➖
作成/更新のリクエストボディから読み取り専用フィールドを除外✅❌
スキーマから重複する列挙型の説明を削除✅❌
レポートごとに正しい日付パラメーター✅✅
送信前に期間全体の範囲を検証✅❌
X-Wafeq-Idempotency-Key を自動設定し、再試行しても同じ値を維持✅❌
マルチパートと生バイナリのファイルアップロード✅➖
バイナリの PDF レスポンスを破損させずに Base64 エンコード✅➖
仕訳明細の取引日を復元✅❌
429 / 5xx で自動再試行(Retry-After に対応)✅❌
クライアント側のレート制限✅❌
起動時に組織の識別情報を検証✅❌
stdio トランスポート✅✅
Streamable-HTTP トランスポート✅➖
Docker + docker-compose、ヘルスチェック、自動再起動✅❌
エンドポイントでの任意のベアラートークン認証✅❌
ライセンスMITツールによって異なります

*汎用 OpenAPI→MCP ラッパーは、任意の仕様を MCP ツールに変換します。同じエンドポイントにアクセスできますが、すべての操作を同じように扱います。特に Wafeq の仕様では、MIGRATION.md で説明している読み取り専用必須フィールドの問題を引き継ぎます。「➖」=ツールによって異なる/保証されません。

できること

接続すると、アシスタントに次のようなことを尋ねられます。

  • 「今年上半期の損益を教えてください。」
  • 「支払期限を30日以上過ぎた未払い請求書を、顧客名とともにすべて表示してください。」
  • 「Acme Ltd 宛てに、1日800ユーロで3日間のコンサルティングを行う請求書の下書きを作成してください。」
  • 「請求書 INV-2026-014 を PDF としてダウンロードしてください。」
  • 「1月の7,000ユーロの振込は、どの勘定科目に転記されましたか?」
  • 「この領収書を経費 EXP-118 に添付してください。」
  • 「3月の銀行取引明細の明細行を総勘定元帳と照合してください。」
  • 「見積書 QUO-31 を請求書に変換し、入金を記録してください。」

仕組み

Claude / Cursor / any MCP client  ──MCP──►  this server  ──HTTPS──►  Wafeq API (your organization)

起動時に、サーバーは同梱された OpenAPI 仕様を MCP ツールに変換します。$ref を解決し、再帰スキーマを防ぎ、リクエストボディからサーバーによって割り当てられるフィールド(readOnly)を除外したうえで、各ツールに安全性カテゴリを付与します。また、認証情報がどの Wafeq 組織に属するかを検証し、その後、送信するすべてのリクエストに認証情報を付加します。キーはサーバーの環境内に保持され、モデルがそのキーを参照したり扱ったりすることはありません。

要件

  • API にアクセスできる Wafeq 組織 — 専用のAPI キー(Wafeq → Settings → Developer → API keys)または OAuth2 アクセストークンが必要です。API 認証情報を取得するをご覧ください。
  • 以下のクイックスタートには Docker(macOS/Windows では Docker Desktop)が必要です。または、Node.js ≥ 20 を使用してソースから実行できます。

クイックスタート(Docker)

1. 認証情報を追加します。 サンプル設定をコピーして、必要な値を入力します。

cp .env.example .env

次に .env を編集し、WAFEQ_API_KEY を設定します。HOST がループバックアドレスでない場合、サーバーには MCP_AUTH_TOKEN も必要です。設定されていないと起動を拒否するため、長くランダムな文字列を設定してください。MCP_AUTH_TOKEN=$(openssl rand -hex 32) を実行します。

2. サーバーを起動します。

docker compose up -d --build

docker-compose.yml は 127.0.0.1:8765 のみにバインドするため、サーバーにはマシンからアクセスできますが、ネットワーク経由ではアクセスできません。

3. サーバーが起動していること、そして正しい帳簿を参照していることを確認します。

curl -s http://localhost:8765/health
{
  "status": "ok",
  "server": "wafeq-mcp",
  "version": "2.0.0",
  "tools": 253,
  "organization": {
    "status": "ok",
    "id": "org_...",
    "name": "Your Company FZCO",
    "base_currency": "EUR",
    "country": "AE"
  },
  "auth_required": false
}

name フィールドを確認してください。 これは、API キーで書き込みを行う組織です。想定した会社でない場合は、先に進む前に作業を中断し、キーを修正してください。認証情報を検証できない場合、/health は 503 と "status": "degraded" を返します。

4. MCP クライアントを接続します。 http://localhost:8765/mcp(Streamable HTTP)を指定します。

リモートエンドポイントは Claude のカスタムコネクター(Settings → Connectors)として追加するか、 mcp-remote でローカルにブリッジします。ブリッジを使う場合は、クライアント設定の mcpServers に以下を追加し、アプリを完全に再起動します。

{
  "mcpServers": {
    "wafeq": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "http://localhost:8765/mcp",
        "--header", "Authorization: Bearer YOUR_MCP_AUTH_TOKEN"
      ]
    }
  }
}

(サーバーがトークンなしで実行されている場合に限り、--header 行を削除できます。ループバックアドレスにバインドされている場合は、トークンなしで実行できます。)

すぐに使えるイメージを利用する場合

リリースごとに GitHub Container Registry にすぐに実行できるイメージが公開されるため、ローカルでのビルドを省略できます。

docker run -d --name wafeq-mcp -p 127.0.0.1:8765:8765 --env-file .env \
  ghcr.io/ohneben/wafeq-mcp:latest

リリースを自分で選んで適用したい場合は、latest ではなくバージョン(:2.0.0)を指定してください。

MCP Registry からインストールする

サーバーは io.github.ohneben/wafeq-mcp として MCP Registry に公開されているため、レジストリに対応したクライアントは名前を指定してインストールできます。レジストリエントリーはイメージを stdio 経由で起動します。同等の手書き設定については、 コンテナーを stdio 経由で実行するを参照してください。

curl -s "https://registry.modelcontextprotocol.io/v0.1/servers/io.github.ohneben%2Fwafeq-mcp/versions/latest"

API 認証情報を取得する

プライベート API キー(ほとんどの方はこちら): Wafeq で Settings → Developer → API keys に移動し、キーを作成します。キーは 1 つの組織にスコープが設定されています。.env に WAFEQ_API_KEY として設定してください。サーバーはこれを Authorization: Api-Key <key> として送信します。

OAuth2 アプリ: Wafeq OAuth2 アプリからアクセストークンを取得している場合は、代わりに .env に WAFEQ_ACCESS_TOKEN として設定してください。サーバーは自動的に Authorization: Bearer <token> に切り替えます。両方の変数が設定されている状態で、一方の方式を強制する必要がある場合にのみ WAFEQ_AUTH_SCHEME を設定してください。

設定

すべての設定は環境変数で行います。認証情報以外には、すべて動作可能なデフォルト値があります。

変数デフォルト値説明
WAFEQ_API_KEY—組織専用の API キーです。Api-Key <key> として送信されます。認証情報が 1 つ必要です。
WAFEQ_ACCESS_TOKEN—OAuth2 アクセストークンです。Bearer <token> として送信されます。WAFEQ_API_KEY より優先されます。
WAFEQ_AUTH_SCHEMEautoapi-key または bearer を強制します。通常は設定しないでください。
WAFEQ_API_BASE_URLhttps://api.wafeq.com/v1Wafeq API のベース URL です。
WAFEQ_OPENAPI_PATH同梱の仕様別の OpenAPI ドキュメント(JSON または YAML)を使用します。
MCP_TRANSPORTstdiostdio または http です。Docker では http が設定されます。
PORT8765HTTP の待ち受けポートです。
HOST0.0.0.0HTTP のバインドアドレスです。
MCP_HTTP_PATH/mcpMCP エンドポイントを提供するパスです。
MCP_AUTH_TOKEN—/mcp で必要となる Bearer トークンです。必須です。ただし、HOST がループバックアドレスの場合を除きます。それ以外では、サーバーは起動を拒否します。2.1.0 で MCP_SHARED_TOKEN から名称が変更されました。
MCP_ALLOWED_HOSTS—Host ヘッダーに指定できるホスト名をカンマ区切りで指定します。空の場合はサーバーが値を導出します。ループバックへのバインド時はループバック名が使われ、リバースプロキシの背後ではチェックされません。
MCP_ALLOW_INSECURE0ループバック以外へのバインド時に、トークンなしで起動します。他の人が実際にアクセスできないポートでのみ使用してください。
MCP_BODY_LIMIT25mb受け付けるリクエストボディの最大サイズです。
MCP_SESSION_TTL1800アイドル状態のセッションを破棄するまでの秒数です。
MCP_MAX_SESSIONS256同時に保持できるセッション数です。上限を超えると、最も長く使用されていないセッションが破棄されます。
WAFEQ_TOOL_GROUPS—公開するリソースグループをカンマ区切りで指定します。例:invoices,bills,reports。空の場合はすべて(251 個)が対象です。一覧を確認するには npm run list-tools を実行してください。
WAFEQ_MAX_REQUESTS20クライアント側のレート制限:1 ウィンドウあたりのリクエスト数です。0 にするとスロットリングが無効になります。
WAFEQ_RATE_WINDOW_MS10000レート制限のウィンドウをミリ秒で指定します。
WAFEQ_MAX_RETRIES3429/5xx/ネットワークエラー時の再試行回数です。
WAFEQ_TIMEOUT_MS300001 回のリクエスト試行ごとのタイムアウトです。
WAFEQ_ALLOW_LOCAL_FILE_UPLOADfalseアップロードツールが file_path を使ってこのマシンのファイルシステムを読み取ることを許可します。セキュリティを参照してください。
WAFEQ_MAX_UPLOAD_BYTES26214400デコード後のアップロードサイズの上限です(25 MiB)。
ツールが多すぎますか?

251 個のツールはかなりの数です。tools/list で取得する完全なカタログは約 0.5 MB の JSON(約 133k トークン) で、ツールが多いと動作が遅くなったり、精度が下がったりするホストもあります。対処方法は 2 つあります。

スキーマはすでにコンパクト化されています。 Wafeq の仕様では、各 enum の値が enum だけでなく説明にも出力されます。通貨の一覧だけでも約 4 KB あり、203 か所にインラインで含まれています。ジェネレーターは、メンバーが 1 つだけの allOf ラッパーをまとめ、重複する箇条書きを削除します。これにより、許可される値を 1 つも削除することなく、ペイロードを約 29% 削減しています。

カタログを絞り込むことで、さらに小さくできます。コードの変更は不要です。

WAFEQ_TOOL_GROUPS=invoices,bills,contacts,payments,reports,accounts,items,tax-rates

手書きのツール 2 つは常に利用できるため、到達不能になる機能はありません。フィルタリングで除外したものも、wafeq_request を通じて呼び出せます。

ツールの安全性カテゴリ

各ツールの説明はバナーで始まり、各ツールには対応する MCP アノテーションが付いています。個数は同梱の仕様に基づいています(生成された 251 個 + 手書きの 2 個 = 合計 253 個)。

バナーツールreadOnlyHintdestructiveHint対象範囲
🟢 READ-ONLY85✅❌すべての GET と、アカウント台帳の便利ツール。
🟢 READ-ONLY · returns a PDF9✅❌PDF のダウンロード:請求書、簡易請求書、クレジットノート、デビットノート、仕入請求書、見積書、発注書、支払い、給与明細。Base64 エンコードして返されます。
🟢 READ-ONLY · preview / simulation4✅❌償却と収益認識のプレビュー。POST ですが、何も書き込まないと説明されています。
🟡 WRITE · creates data39❌❌コレクションの作成、2 種類のファイルアップロード、2 種類の変換(見積書→請求書、発注書→仕入請求書)。本質的に冪等ではないため、自動冪等性キーが付与されます。
🟡 WRITE · updates data70❌❌すべての PUT と PATCH。
🟠 STATE CHANGE · moves a document in or out of the ledger2❌❌経費を記帳済み/下書きにします。元に戻せます。それぞれがもう一方を取り消します。
🔴 IRREVERSIBLE · files the document with an external tax authority3❌✅請求書/クレジットノート/簡易請求書を税務当局に申告します。組織の外部に送信され、取り消すことはできません。
🔴 IRREVERSIBLE · posts the remaining balance to the ledger2❌✅償却/収益認識を早期に終了します。API で元に戻すことはできません。先に対応するプレビューを実行してください。
🔴 DESTRUCTIVE · deletes39❌✅すべての DELETE と、影響を事前に把握できない wafeq_request パススルー。
2539844

3 つの 🔴 グループはいずれも destructiveHint: true を設定しているため、アノテーションを尊重するホストは、削除だけでなく、これらすべての操作の前に停止して確認を求めます。税務当局への請求書の申告は、削除と同等以上に重大であり、削除とは異なり、組織の外部に影響します。

認証情報なしで、いつでも最新のカタログを表示できます:

npm run list-tools
🟢 読み取り専用(85) | Tool | Endpoint | |---|---| | `wafeq_account_ledger` | _hand-written_ | | `wafeq_accounts_list` | `GET /accounts/` | | `wafeq_accounts_retrieve` | `GET /accounts/{id}/` | | `wafeq_amortizations_list` | `GET /amortizations/` | | `wafeq_amortizations_retrieve` | `GET /amortizations/{id}/` | | `wafeq_bank_accounts_ledger_transactions_list` | `GET /bank-accounts/{bank_account_id}/ledger-transactions/` | | `wafeq_bank_accounts_ledger_transactions_retrieve` | `GET /bank-accounts/{bank_account_id}/ledger-transactions/{id}/` | | `wafeq_bank_accounts_list` | `GET /bank-accounts/` | | `wafeq_bank_accounts_retrieve` | `GET /bank-accounts/{id}/` | | `wafeq_bank_accounts_statement_transactions_list` | `GET /bank-accounts/{bank_account_id}/statement-transactions/` | | `wafeq_bank_accounts_statement_transactions_retrieve` | `GET /bank-accounts/{bank_account_id}/statement-transactions/{id}/` | | `wafeq_beneficiaries_list` | `GET /beneficiaries/` | | `wafeq_beneficiaries_retrieve` | `GET /beneficiaries/{id}/` | | `wafeq_bills_line_items_list` | `GET /bills/{bill_id}/line-items/` | | `wafeq_bills_line_items_retrieve` | `GET /bills/{bill_id}/line-items/{id}/` | | `wafeq_bills_list` | `GET /bills/` | | `wafeq_bills_retrieve` | `GET /bills/{id}/` | | `wafeq_branches_list` | `GET /branches/` | | `wafeq_branches_retrieve` | `GET /branches/{id}/` | | `wafeq_contacts_list` | `GET /contacts/` | | `wafeq_contacts_retrieve` | `GET /contacts/{id}/` | | `wafeq_cost_centers_list` | `GET /cost-centers/` | | `wafeq_cost_centers_retrieve` | `GET /cost-centers/{id}/` | | `wafeq_credit_notes_line_items_list` | `GET /credit-notes/{credit_note_id}/line-items/` | | `wafeq_credit_notes_line_items_retrieve` | `GET /credit-notes/{credit_note_id}/line-items/{id}/` | | `wafeq_credit_notes_list` | `GET /credit-notes/` | | `wafeq_credit_notes_retrieve` | `GET /credit-notes/{id}/` | | `wafeq_custom_fields_list` | `GET /custom-fields/` | | `wafeq_custom_fields_retrieve` | `GET /custom-fields/{id}/` | | `wafeq_debit_notes_line_items_list` | `GET /debit-notes/{debit_note_id}/line-items/` | | `wafeq_debit_notes_line_items_retrieve` | `GET /debit-notes/{debit_note_id}/line-items/{id}/` | | `wafeq_debit_notes_list` | `GET /debit-notes/` | | `wafeq_debit_notes_retrieve` | `GET /debit-notes/{id}/` | | `wafeq_employees_list` | `GET /employees/` | | `wafeq_employees_retrieve` | `GET /employees/{id}/` | | `wafeq_expenses_list` | `GET /expenses/` | | `wafeq_expenses_retrieve` | `GET /expenses/{id}/` | | `wafeq_files_list` | `GET /files/` | | `wafeq_files_retrieve` | `GET /files/{id}/` | | `wafeq_invoices_line_items_list` | `GET /invoices/{invoice_id}/line-items/` | | `wafeq_invoices_line_items_retrieve` | `GET /invoices/{invoice_id}/line-items/{id}/` | | `wafeq_invoices_list` | `GET /invoices/` | | `wafeq_invoices_retrieve` | `GET /invoices/{id}/` | | `wafeq_item_units_of_measure_list` | `GET /item-units-of-measure/` | | `wafeq_item_units_of_measure_retrieve` | `GET /item-units-of-measure/{id}/` | | `wafeq_items_list` | `GET /items/` | | `wafeq_items_retrieve` | `GET /items/{id}/` | | `wafeq_journal_line_items_list` | `GET /journal-line-items/` | | `wafeq_journal_line_items_retrieve` | `GET /journal-line-items/{id}/` | | `wafeq_manual_journals_list` | `GET /manual-journals/` | | `wafeq_manual_journals_retrieve` | `GET /manual-journals/{id}/` | | `wafeq_organization_retrieve` | `GET /organization/` | | `wafeq_payment_requests_list` | `GET /payment_requests/` | | `wafeq_payment_requests_retrieve` | `GET /payment_requests/{id}/` | | `wafeq_payments_list` | `GET /payments/` | | `wafeq_payments_retrieve` | `GET /payments/{id}/` | | `wafeq_payslips_list` | `GET /payslips/` | | `wafeq_payslips_pay_items_list` | `GET /payslips/{payslip_id}/pay-items/` | | `wafeq_payslips_pay_items_retrieve` | `GET /payslips/{payslip_id}/pay-items/{id}/` | | `wafeq_payslips_retrieve` | `GET /payslips/{id}/` | | `wafeq_projects_list` | `GET /projects/` | | `wafeq_projects_retrieve` | `GET /projects/{id}/` | | `wafeq_purchase_orders_line_items_list` | `GET /purchase-orders/{purchase_order_id}/line-items/` | | `wafeq_purchase_orders_line_items_retrieve` | `GET /purchase-orders/{purchase_order_id}/line-items/{id}/` | | `wafeq_purchase_orders_list` | `GET /purchase-orders/` | | `wafeq_purchase_orders_retrieve` | `GET /purchase-orders/{id}/` | | `wafeq_quotes_line_items_list` | `GET /quotes/{quote_id}/line-items/` | | `wafeq_quotes_line_items_retrieve` | `GET /quotes/{quote_id}/line-items/{id}/` | | `wafeq_quotes_list` | `GET /quotes/` | | `wafeq_quotes_retrieve` | `GET /quotes/{id}/` | | `wafeq_reports_balance_sheet_list` | `GET /reports/balance-sheet/` | | `wafeq_reports_cash_flow_list` | `GET /reports/cash-flow/` | | `wafeq_reports_profit_and_loss_list` | `GET /reports/profit-and-loss/` | | `wafeq_reports_trial_balance_list` | `GET /reports/trial-balance/` | | `wafeq_revenue_recognitions_list` | `GET /revenue-recognitions/` | | `wafeq_revenue_recognitions_retrieve` | `GET /revenue-recognitions/{id}/` | | `wafeq_simplified_invoices_line_items_list` | `GET /simplified-invoices/{invoice_id}/line-items/` | | `wafeq_simplified_invoices_line_items_retrieve` | `GET /simplified-invoices/{invoice_id}/line-items/{id}/` | | `wafeq_simplified_invoices_list` | `GET /simplified-invoices/` | | `wafeq_simplified_invoices_retrieve` | `GET /simplified-invoices/{id}/` | | `wafeq_tax_rates_list` | `GET /tax-rates/` | | `wafeq_units_of_measure_list` | `GET /units-of-measure/` | | `wafeq_units_of_measure_retrieve` | `GET /units-of-measure/{id}/` | | `wafeq_warehouses_list` | `GET /warehouses/` | | `wafeq_warehouses_retrieve` | `GET /warehouses/{id}/` |
🟢 READ-ONLY (PDF) (9)
ToolEndpoint
wafeq_bills_download_retrieveGET /bills/{id}/download/
wafeq_credit_notes_download_retrieveGET /credit-notes/{id}/download/
wafeq_debit_notes_download_retrieveGET /debit-notes/{id}/download/
wafeq_invoices_download_retrieveGET /invoices/{id}/download/
wafeq_payments_download_retrieveGET /payments/{id}/download/
wafeq_payslips_download_retrieveGET /payslips/{id}/download/
wafeq_purchase_orders_download_retrieveGET /purchase-orders/{id}/download/
wafeq_quotes_download_retrieveGET /quotes/{id}/download/
wafeq_simplified_invoices_download_retrieveGET /simplified-invoices/{id}/download/
🟢 READ-ONLY (PREVIEW) (4)
ToolEndpoint
wafeq_amortizations_preview_createPOST /amortizations/preview/
wafeq_amortizations_preview_end_early_createPOST /amortizations/{id}/preview-end-early/
wafeq_revenue_recognitions_preview_createPOST /revenue-recognitions/preview/
wafeq_revenue_recognitions_preview_end_early_createPOST /revenue-recognitions/{id}/preview-end-early/
🟡 WRITE · CREATES (39)
ToolEndpoint
wafeq_accounts_createPOST /accounts/
wafeq_bank_accounts_createPOST /bank-accounts/
wafeq_bank_accounts_ledger_transactions_createPOST /bank-accounts/{bank_account_id}/ledger-transactions/
wafeq_bank_accounts_statement_transactions_createPOST /bank-accounts/{bank_account_id}/statement-transactions/
wafeq_beneficiaries_createPOST /beneficiaries/
wafeq_bills_createPOST /bills/
wafeq_bills_line_items_createPOST /bills/{bill_id}/line-items/
wafeq_branches_createPOST /branches/
wafeq_contacts_createPOST /contacts/
wafeq_cost_centers_createPOST /cost-centers/
wafeq_credit_notes_createPOST /credit-notes/
wafeq_credit_notes_line_items_createPOST /credit-notes/{credit_note_id}/line-items/
wafeq_custom_fields_createPOST /custom-fields/
wafeq_debit_notes_createPOST /debit-notes/
wafeq_debit_notes_line_items_createPOST /debit-notes/{debit_note_id}/line-items/
wafeq_employees_createPOST /employees/
wafeq_expenses_createPOST /expenses/
wafeq_invoices_createPOST /invoices/
wafeq_invoices_line_items_createPOST /invoices/{invoice_id}/line-items/
wafeq_item_units_of_measure_createPOST /item-units-of-measure/
wafeq_items_createPOST /items/
wafeq_manual_journals_createPOST /manual-journals/
wafeq_payment_requests_createPOST /payment_requests/
wafeq_payments_createPOST /payments/
wafeq_payslips_createPOST /payslips/
wafeq_payslips_pay_items_createPOST /payslips/{payslip_id}/pay-items/
wafeq_projects_createPOST /projects/
wafeq_purchase_orders_bill_createPOST /purchase-orders/{id}/bill/
wafeq_purchase_orders_createPOST /purchase-orders/
wafeq_purchase_orders_line_items_createPOST /purchase-orders/{purchase_order_id}/line-items/
wafeq_quotes_createPOST /quotes/
wafeq_quotes_invoice_createPOST /quotes/{id}/invoice/
wafeq_quotes_line_items_createPOST /quotes/{quote_id}/line-items/
wafeq_simplified_invoices_createPOST /simplified-invoices/
wafeq_simplified_invoices_line_items_createPOST /simplified-invoices/{invoice_id}/line-items/
wafeq_units_of_measure_createPOST /units-of-measure/
wafeq_upload_filePOST /files/
wafeq_upload_file_rawPOST /files/raw/
wafeq_warehouses_createPOST /warehouses/
🟡 WRITE · UPDATES (70)
ToolEndpoint
wafeq_accounts_partial_updatePATCH /accounts/{id}/
wafeq_accounts_updatePUT /accounts/{id}/
wafeq_bank_accounts_ledger_transactions_partial_updatePATCH /bank-accounts/{bank_account_id}/ledger-transactions/{id}/
wafeq_bank_accounts_ledger_transactions_updatePUT /bank-accounts/{bank_account_id}/ledger-transactions/{id}/
wafeq_bank_accounts_partial_updatePATCH /bank-accounts/{id}/
wafeq_bank_accounts_statement_transactions_partial_updatePATCH /bank-accounts/{bank_account_id}/statement-transactions/{id}/
wafeq_bank_accounts_statement_transactions_updatePUT /bank-accounts/{bank_account_id}/statement-transactions/{id}/
wafeq_bank_accounts_updatePUT /bank-accounts/{id}/
wafeq_beneficiaries_partial_updatePATCH /beneficiaries/{id}/
wafeq_beneficiaries_updatePUT /beneficiaries/{id}/
wafeq_bills_line_items_partial_updatePATCH /bills/{bill_id}/line-items/{id}/
wafeq_bills_line_items_updatePUT /bills/{bill_id}/line-items/{id}/
wafeq_bills_partial_updatePATCH /bills/{id}/
wafeq_bills_updatePUT /bills/{id}/
wafeq_branches_partial_updatePATCH /branches/{id}/
wafeq_branches_updatePUT /branches/{id}/
wafeq_contacts_partial_updatePATCH /contacts/{id}/
wafeq_contacts_updatePUT /contacts/{id}/
wafeq_cost_centers_partial_updatePATCH /cost-centers/{id}/
wafeq_cost_centers_updatePUT /cost-centers/{id}/
wafeq_credit_notes_line_items_partial_updatePATCH /credit-notes/{credit_note_id}/line-items/{id}/
wafeq_credit_notes_line_items_updatePUT /credit-notes/{credit_note_id}/line-items/{id}/
wafeq_credit_notes_partial_updatePATCH /credit-notes/{id}/
wafeq_credit_notes_updatePUT /credit-notes/{id}/
wafeq_custom_fields_partial_updatePATCH /custom-fields/{id}/
wafeq_custom_fields_updatePUT /custom-fields/{id}/
wafeq_debit_notes_line_items_partial_updatePATCH /debit-notes/{debit_note_id}/line-items/{id}/
wafeq_debit_notes_line_items_updatePUT /debit-notes/{debit_note_id}/line-items/{id}/
wafeq_debit_notes_partial_updatePATCH /debit-notes/{id}/
wafeq_debit_notes_updatePUT /debit-notes/{id}/
wafeq_employees_partial_updatePATCH /employees/{id}/
wafeq_employees_updatePUT /employees/{id}/
wafeq_expenses_partial_updatePATCH /expenses/{id}/
wafeq_expenses_updatePUT /expenses/{id}/
wafeq_invoices_line_items_partial_updatePATCH /invoices/{invoice_id}/line-items/{id}/
wafeq_invoices_line_items_updatePUT /invoices/{invoice_id}/line-items/{id}/
wafeq_invoices_partial_updatePATCH /invoices/{id}/
wafeq_invoices_updatePUT /invoices/{id}/
wafeq_item_units_of_measure_partial_updatePATCH /item-units-of-measure/{id}/
wafeq_item_units_of_measure_updatePUT /item-units-of-measure/{id}/
wafeq_items_partial_updatePATCH /items/{id}/
wafeq_items_updatePUT /items/{id}/
wafeq_manual_journals_partial_updatePATCH /manual-journals/{id}/
wafeq_manual_journals_updatePUT /manual-journals/{id}/
wafeq_payment_requests_partial_updatePATCH /payment_requests/{id}/
wafeq_payment_requests_updatePUT /payment_requests/{id}/
wafeq_payments_partial_updatePATCH /payments/{id}/
wafeq_payments_updatePUT /payments/{id}/
wafeq_payslips_partial_updatePATCH /payslips/{id}/
wafeq_payslips_pay_items_partial_updatePATCH /payslips/{payslip_id}/pay-items/{id}/
wafeq_payslips_pay_items_updatePUT /payslips/{payslip_id}/pay-items/{id}/
wafeq_payslips_updatePUT /payslips/{id}/
wafeq_projects_partial_updatePATCH /projects/{id}/
wafeq_projects_updatePUT /projects/{id}/
wafeq_purchase_orders_line_items_partial_updatePATCH /purchase-orders/{purchase_order_id}/line-items/{id}/
wafeq_purchase_orders_line_items_updatePUT /purchase-orders/{purchase_order_id}/line-items/{id}/
wafeq_purchase_orders_partial_updatePATCH /purchase-orders/{id}/
wafeq_purchase_orders_updatePUT /purchase-orders/{id}/
wafeq_quotes_line_items_partial_updatePATCH /quotes/{quote_id}/line-items/{id}/
wafeq_quotes_line_items_updatePUT /quotes/{quote_id}/line-items/{id}/
wafeq_quotes_partial_updatePATCH /quotes/{id}/
wafeq_quotes_updatePUT /quotes/{id}/
wafeq_simplified_invoices_line_items_partial_updatePATCH /simplified-invoices/{invoice_id}/line-items/{id}/
wafeq_simplified_invoices_line_items_updatePUT /simplified-invoices/{invoice_id}/line-items/{id}/
wafeq_simplified_invoices_partial_updatePATCH /simplified-invoices/{id}/
wafeq_simplified_invoices_updatePUT /simplified-invoices/{id}/
wafeq_units_of_measure_partial_updatePATCH /units-of-measure/{id}/
wafeq_units_of_measure_updatePUT /units-of-measure/{id}/
wafeq_warehouses_partial_updatePATCH /warehouses/{id}/
wafeq_warehouses_updatePUT /warehouses/{id}/
🟠 STATE CHANGE (2)
ToolEndpoint
wafeq_expenses_mark_as_draft_createPOST /expenses/{id}/mark-as-draft/
wafeq_expenses_mark_as_posted_createPOST /expenses/{id}/mark-as-posted/
🔴 IRREVERSIBLE · EXTERNAL FILING (3)
ToolEndpoint
wafeq_credit_notes_tax_authority_report_createPOST /credit-notes/{id}/tax-authority/report/
wafeq_invoices_tax_authority_report_createPOST /invoices/{id}/tax-authority/report/
wafeq_simplified_invoices_tax_authority_report_createPOST /simplified-invoices/{id}/tax-authority/report/
🔴 IRREVERSIBLE · LEDGER (2)
ToolEndpoint
wafeq_amortizations_end_early_createPOST /amortizations/{id}/end-early/
wafeq_revenue_recognitions_end_early_createPOST /revenue-recognitions/{id}/end-early/
🔴 DESTRUCTIVE · DELETES (39)
ToolEndpoint
wafeq_accounts_destroyDELETE /accounts/{id}/
wafeq_amortizations_destroyDELETE /amortizations/{id}/
wafeq_bank_accounts_destroyDELETE /bank-accounts/{id}/
wafeq_bank_accounts_ledger_transactions_destroyDELETE /bank-accounts/{bank_account_id}/ledger-transactions/{id}/
wafeq_bank_accounts_statement_transactions_destroyDELETE /bank-accounts/{bank_account_id}/statement-transactions/{id}/
wafeq_beneficiaries_destroyDELETE /beneficiaries/{id}/
wafeq_bills_destroyDELETE /bills/{id}/
wafeq_bills_line_items_destroyDELETE /bills/{bill_id}/line-items/{id}/
wafeq_branches_destroyDELETE /branches/{id}/
wafeq_contacts_destroyDELETE /contacts/{id}/
wafeq_cost_centers_destroyDELETE /cost-centers/{id}/
wafeq_credit_notes_destroyDELETE /credit-notes/{id}/
wafeq_credit_notes_line_items_destroyDELETE /credit-notes/{credit_note_id}/line-items/{id}/
wafeq_custom_fields_destroyDELETE /custom-fields/{id}/
wafeq_debit_notes_destroyDELETE /debit-notes/{id}/
wafeq_debit_notes_line_items_destroyDELETE /debit-notes/{debit_note_id}/line-items/{id}/
wafeq_employees_destroyDELETE /employees/{id}/
wafeq_expenses_destroyDELETE /expenses/{id}/
wafeq_files_destroyDELETE /files/{id}/
wafeq_invoices_destroyDELETE /invoices/{id}/
wafeq_invoices_line_items_destroyDELETE /invoices/{invoice_id}/line-items/{id}/
wafeq_item_units_of_measure_destroyDELETE /item-units-of-measure/{id}/
wafeq_items_destroyDELETE /items/{id}/
wafeq_manual_journals_destroyDELETE /manual-journals/{id}/
wafeq_payment_requests_destroyDELETE /payment_requests/{id}/
wafeq_payments_destroyDELETE /payments/{id}/
wafeq_payslips_destroyDELETE /payslips/{id}/
wafeq_payslips_pay_items_destroyDELETE /payslips/{payslip_id}/pay-items/{id}/
wafeq_projects_destroyDELETE /projects/{id}/
wafeq_purchase_orders_destroyDELETE /purchase-orders/{id}/
wafeq_purchase_orders_line_items_destroyDELETE /purchase-orders/{purchase_order_id}/line-items/{id}/
wafeq_quotes_destroyDELETE /quotes/{id}/
wafeq_quotes_line_items_destroyDELETE /quotes/{quote_id}/line-items/{id}/
wafeq_requesthand-written
wafeq_revenue_recognitions_destroyDELETE /revenue-recognitions/{id}/
wafeq_simplified_invoices_destroyDELETE /simplified-invoices/{id}/
wafeq_simplified_invoices_line_items_destroyDELETE /simplified-invoices/{invoice_id}/line-items/{id}/
wafeq_units_of_measure_destroyDELETE /units-of-measure/{id}/
wafeq_warehouses_destroyDELETE /warehouses/{id}/

対応範囲

領域ツール🟢 読み取り🟡 書き込み🔴 取り消し不可🔴 削除
売上・売掛金692531310
仕入・買掛金54192708
銀行業務186903
元帳・レポート3119624
給与計算197903
マスターデータ・ディメンション54182709
ファイル・組織63201
その他・利便性21001
合計25398111539

「書き込み」には、状態を変更する2つの🟠ツールが含まれます。各領域は次のWafeqリソースに対応します — 売上:請求書、簡易請求書、見積書、貸方票、支払い、支払い依頼 · 仕入:請求書、発注書、借方票、経費、受取人 · 銀行業務:元帳および明細取引を含む銀行口座 · 元帳・レポート:勘定科目、手動仕訳、仕訳明細、4種類のレポート、税率、償却、収益認識 · 給与計算:給与明細、従業員 · マスターデータ:取引先、品目、測定単位、倉庫、プロジェクト、コストセンター、支店、カスタムフィールド。

手書きのツールが2つあります

上記はすべて生成されます。手書きのツールは2つです。

  • wafeq_account_ledger(🟢)— 実際の取引日を含む仕訳明細です。Wafeqの/journal-line-items/の行にはcreated_ts(その行がWafeqに登録された日時)が含まれますが、これは取引日と異なる月になることがよくあり、日付フィールド自体もありません。このツールは、取引日に基づいて動作するエンドポイント独自のdate_after/date_beforeフィルターを使って日付を取得します。月単位で照会し、行がある場合のみ日単位の照会に分割するため、取引が少ない期間では1件のリクエストで済みます。結果にはrequests_madeが含まれます。
  • wafeq_request(🔴)— あらゆるメソッド、パスに加え、クエリ、本文、ヘッダーを指定できるその他の操作用ツールです。主なインターフェースではなく、同梱の仕様に含まれていないものに対するフォールバックです。事前に影響を把握できないため、破壊的操作に分類されています。

ソースから実行する(stdio、Docker 不要)

npm ci
npm run build

次に、MCP クライアントに登録します。Claude Desktopの場合は、claude_desktop_config.jsonに追加します。

{
  "mcpServers": {
    "wafeq": {
      "command": "node",
      "args": ["/absolute/path/to/Wafeq MCP/dist/index.js"],
      "env": {
        "MCP_TRANSPORT": "stdio",
        "WAFEQ_API_KEY": "your-key-here"
      }
    }
  }
}

Claude Codeの場合:

claude mcp add wafeq --env WAFEQ_API_KEY=your-key-here -- node /absolute/path/to/dist/index.js
stdio でコンテナを実行する

HTTP サーバーもローカルでのビルドも使わずに、クライアントから公開済みイメージを直接起動することもできます。

{
  "mcpServers": {
    "wafeq": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "MCP_TRANSPORT=stdio",
        "-e", "WAFEQ_API_KEY",
        "ghcr.io/ohneben/wafeq-mcp:latest"
      ],
      "env": {
        "WAFEQ_API_KEY": "your-key-here"
      }
    }
  }
}

ここではMCP_TRANSPORT=stdioが必須です。イメージのデフォルトはHTTPトランスポートです。

便利なスクリプト:

コマンド内容
npm run buildTypeScriptをdist/にコンパイルします。
npm testVitestのテストスイートを実行します。
npm run list-tools分類済みのカタログを出力します。認証情報は不要です。
npm run start:stdiostdio で実行します。
npm run start:httpStreamable HTTP サーバーを実行します。

仕様を最新の状態に保つ

ツールは起動時にspec/wafeq-public-api.jsonから生成されます。コード生成の手順も、手書きのツール一覧もありません。新しいOpenAPIドキュメント(JSONまたはYAML)に差し替えて再ビルドすると、新しいエンドポイントが新しいツールになります。同梱版の入手元と、更新後に再確認すべき項目については、spec/README.mdを参照してください。

実際の動作に基づく修正はsrc/overrides.tsにoperationIdをキーとして日付付きで記録されるため、該当するoperationがなくなると、そのエントリは適用されなくなります。

注意事項と規約

  • 日付は YYYY-MM-DD です。金額の小数点にはドットを使用します。
  • ページング:一覧ツールは limit と offset を受け取り、合計件数を返します。
  • レポートでは、レポート固有の日付パラメーターを使用します。貸借対照表では date + period_count、損益計算書とキャッシュフローでは date_after + date_before、試算表では from_date + to_date を使用します。Wafeq は誤ったクエリパラメーターを黙って無視するため、 名前を間違えても呼び出しが正常に動作しているように見えます。レポートごとのスキーマにより、 これを防げます。
  • 期間全体:損益計算書とキャッシュフローの範囲は、月または年全体を含む必要があります。 サーバーはローカルでチェックし、HTTP 400 の応答を待つ代わりに、最も近い有効な範囲を返します。
  • ファイルのアップロード(wafeq_files_*):base64 コンテンツとファイル名を渡します。 POST /files/ は multipart 専用で、POST /files/raw/ には Content-Disposition ヘッダーが必要ですが、どちらも自動的に処理されます。
  • PDF のダウンロードは、文字化けしたテキストではなく、サイズとコンテンツタイプを含む小さな エンベロープに格納され、base64 エンコードされて返されます。
  • 冪等性:X-Wafeq-Idempotency-Key に対応するすべての書き込みエンドポイントでは、 UUID v4 が自動的に付与され、再試行時にも再利用されます。意図した再実行を安全に行うには、 独自のキーを渡してください。
  • 再試行:一時的な 429 / 5xx 応答は、同じ冪等性キーを使って、Retry-After に従いながら ジッター付き指数バックオフで再試行されます。
  • レート制限:Wafeq は数値の上限を公開していないため、クライアント側のデフォルト値 (WAFEQ_MAX_REQUESTS=20、WAFEQ_RATE_WINDOW_MS=10000)は意図的に控えめに設定されています。 上限を把握している場合は引き上げてください。
  • 1つの認証情報につき1つの組織です。 Wafeq API キーは組織ごとにスコープが設定されています。 すべてのツール呼び出しはその組織に対して実行され、/health に組織名が表示されます。

CI とリリース

すべてのプッシュとプルリクエストで、Node 20 と 22 を使ったビルドとテストが実行され、認証情報が 存在しない状態でツールカタログが生成されます。これにより、重複したツール名やスキーマに違反する ツール名がリリース前に検出されます。.env が追跡対象になった場合も、CI は失敗します。

リリースは vX.Y.Z タグのみです。 バージョン番号を手動で管理することはありません。タグを プッシュすると、一連の処理が実行されます。

  1. バージョンはタグから一度だけ取得されます。
  2. イメージがビルドされ、ghcr.io/ohneben/wafeq-mcp にプッシュされます。タグにはバージョン、 MAJOR.MINOR、短縮 SHA が付けられ、main では latest も付けられます。
  3. エントリーが MCP Registry に公開され、 server.json にはその正確なイメージタグが固定されます。イメージの io.modelcontextprotocol.server.name ラベルによって所有権を証明します。このラベルは server.json の name と一致する必要があり、その一致はテストで検証されます。
  4. リリースしたバージョン番号が main の package.json と server.json に書き戻され、 タグもそのコミットに移動します。そのため、リポジトリには常に最後に公開されたバージョンが 記載され、コードを編集しなくてもサーバーは MCP 経由と /health でそのバージョンを報告します。
npm version 2.0.1 --no-git-tag-version   # optional; CI stamps it either way
git tag v2.0.1 && git push origin v2.0.1

workflow_dispatch は新しいタグを作成せずに、指定されたバージョンを再公開します。main への プッシュでは -dev.g<sha> イメージがビルドされるだけで、処理はそこで終了します。レジストリには 一切変更を加えません。

セキュリティ

  • 認証情報はサーバー側に保持されます。 環境変数から読み込まれ、リクエストごとに注入されます。モデルに見えるのはツールの入力と API のレスポンスだけで、キーは表示されません。パススルーツールで Authorization ヘッダーを上書きすることはできず、設定された API ベース以外のホストへの認証情報の送信も拒否されます。
  • .env は絶対にコミットしないでください。 Git の追跡対象から除外されており、追跡対象になった場合は CI が失敗します。.env.example に含まれるのはプレースホルダーのみです。
  • localhost にバインドするか、トークンを設定してください。 docker-compose.yml は 127.0.0.1 のみで公開します。さらに別の場所にバインドする場合、MCP_AUTH_TOKEN が設定されていないとサーバーは起動を拒否します。トークンは一定時間比較で照合されます。さらに Host ヘッダーのチェックも行うため、DNS リバインディングによってウェブページからループバックサーバーにアクセスすることはできません。
  • ローカルファイルのアップロードはデフォルトで無効です。 WAFEQ_ALLOW_LOCAL_FILE_UPLOAD=false の場合、サーバーは自身のファイルシステムからファイルを読み取りません。有効にすると、サーバーを呼び出せるものなら何でも、ローカルパスの読み取りを要求できるようになります。必要であり、すべてのクライアントを信頼できる場合を除き、無効のままにしてください。Base64 によるアップロードは、どちらの場合も利用できます。
  • 最初の書き込みを行う前に、/health で組織を確認してください。API キーは 1 つの組織に紐付いており、キーが間違っているとエラーになるのではなく、誤った会社に書き込まれます。
  • 🔴 ツールの警告は文字どおりに受け取ってください。 削除は取り消せず、スケジュールの早期終了には API による取り消し手段がなく、税務当局への申告も撤回できません。destructiveHint を含む操作については、ホスト側の確認を有効にしておいてください。

脆弱性の報告については、SECURITY.md をご覧ください。

クレジットとライセンス

MIT — LICENSE.md をご覧ください。Model Context Protocol TypeScript SDK を基盤としています。Wafeq とは提携しておらず、同社による承認も受けていません。

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。