tieline について
tielineはフロントエンドのAPI呼び出しとバックエンドのルートを静的に照合し、パスやメソッドの不一致を検出します。両側を起動せずにCIで契約を確認したいチーム向けで、コードとOpenAPI仕様の差異も調べられます。
主な機能
- 01フロントエンドとバックエンドの静的照合
- 02不一致・判定不能・孤立ルートの検出
- 03対応するクライアント/サーバーアダプター
- 04CIゲートとJSON/HTMLレポート
- 05doctorによるコードとOpenAPIの照合
活用シーン
- 01CIで存在しないバックエンドルートへの呼び出しを検出
- 02フロントエンドから使われていないバックエンドルートを特定
- 03実装ルートとOpenAPI仕様を照合
MCP 対応
MCPサーバーは、ルートの確認・一覧表示、コードとOpenAPI仕様の比較、設定の初期化を行う5つのツールを提供します。結果はCLIと同じ決定論的なエンジンが生成します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
5掲載時のツール一覧 · 3 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| config | string | いいえ | tieline.config.json のパス。デフォルトではサーバーの作業ディレクトリから上位階層を検索します。 |
詳細
tieline
静的なフロントエンド↔バックエンドの契約ずれチェッカー。契約テストを1つも書かずに Pact を実現します。

tieline は、API 境界の両側ですでに書かれているコード、つまりフロントエンドが行う HTTP 呼び出しとバックエンドが公開するルートを読み取り、食い違いを報告します。作成する契約テストも、稼働させるブローカーも、起動するバックエンドも不要です。1秒もかからずに完了し、CI のゲートとして実行できるように設計されています。
LLM を取り除いても、開発者はこのツールをインストールします。
tielineはまず決定論的なツールであり、その出力をエージェントが読み取れるのはおまけです。
仕組み
frontend code backend code
(axios, rtk-query, …) (express, nestjs, openapi, …)
│ │
client adapter server adapter
│ normalize ${id} :id {id} → {} │
└───────────────► join on (METHOD, path) ◄──────┘
│
✅ matched ❌ drift ⚠️ unverifiable 🟡 dead
両側を正規化した (METHOD, path) に変換して結合します。マッチャーはアダプターに依存しないため、任意のクライアントアダプターと任意のサーバーアダプターを組み合わせられます。同じエンジンで、React アプリと Express、Angular アプリと Spring、または任意のアプリと OpenAPI 仕様を照合できます。
| 結果 | 意味 |
|---|---|
| ✅ 一致 | FE 呼び出しが実在する BE ルートに解決されます |
| ❌ ずれ | FE 呼び出しは解決されますが、BE に該当するルート/メソッドがありません — バグの検出対象 |
| ⚠️ 検証不能 | FE の URL が実行時に構築されます — 推測せずに報告します |
| 🟡 未使用 | 解決可能な FE 呼び出しから到達されない BE ルート(情報提供) |
tieline と代替ツールの比較
これらのツールは、近接する課題を解決します。利用できるものと保証したいことに応じて選んでください。
| ツール | 仕組み | 検出できること | 必要なもの | 選ぶ場面 |
|---|---|---|---|---|
| tieline | FE の呼び出し箇所と BE のルート宣言を静的に解析し、(METHOD, path) で結合します | バックエンドが公開していないルートをフロントエンドが呼び出している状態(パス/メソッドのずれ)、仕様に記載のない/実在しないルート | 両側のソースコード。稼働中のものも、作成済みのものも不要 | 作成・保守する契約テストなしで、1秒未満の CI ゲートを実現したいとき |
| Pact | コンシューマー駆動の契約テストを実行時に実行し、ブローカーを介して共有します | 特定のコンシューマーとプロバイダー間のリクエスト/レスポンスのペイロードの不一致 | 両側で作成した契約テスト、Pact ブローカー、プロバイダー検証ビルド | 独立したチーム間でペイロードレベルの保証とデプロイ可否を判断するワークフローが必要なとき |
| openapi-diff | 2つの OpenAPI ドキュメントの差分を取ります | 2つの仕様バージョン間の破壊的変更 | 両バージョンの正確な仕様。ソースコードは読み取りません | API の仕様を先に作成する運用で、仕様の変更をゲートしたいとき |
| Optic | OpenAPI 仕様を継続的に追跡し、CI ですべての変更の差分を取ります | 仕様の履歴における破壊的変更やスタイル/標準への違反 | リポジトリ内で管理される OpenAPI 仕様 | 進化する仕様を統制し、各 PR の API 変更をレビューしたいとき |
| Schemathesis | 稼働中の API を OpenAPI/GraphQL スキーマに照らしてプロパティベースでファジングします | サーバーのクラッシュ、スキーマ違反、実行時の未文書化レスポンス | 起動可能なバックエンドとスキーマ | 実装の実行時の適合性と堅牢性をテストしたいとき |
これらは組み合わせて使えます。tieline はすべての PR で FE↔BE のずれを静的に検出し、tieline doctor はコード↔仕様の整合性を保ち、Pact や Schemathesis などの実行時ツールは、その下のペイロード/動作レイヤーを保護します。
クイックスタート
インストールする(または npx で実行する):
npm install -g @nugehs/tieline
# or, from a clone: git clone … && cd tieline && npm link
t i e l i n e . c o n f i g . j s o n を生成します。init は周辺ディレクトリ(現在の作業ディレクトリ、その子ディレクトリ、兄弟ディレクトリ)を調べて既知のスタックを検出し、すぐに実行できる設定ファイルを書き出します。
tieline init
tieline · init
scanning ~/code for repos…
✔ client: rtk-query → web (roots: src/redux/apis)
✔ server: nestjs → api (roots: src)
📝 wrote tieline.config.json
package.json の依存関係(@reduxjs/toolkit、axios、@angular/core、@nestjs/core、express、fastify、next)、requirements.txt/pyproject.toml(fastapi、flask)、pom.xml/build.gradle(spring)、およびフォールバックとして任意の OpenAPI ドキュメントからアダプターを検出します。検出できないものは編集用のプレースホルダーとして書き出されます。ファイルは常に上書きされるため、ディレクトリ構成を変更したときは再実行してください。
手動で記述する場合は、リポジトリのルートまたはその上位に配置します。
{
"client": { "adapter": "rtk-query", "repo": "../web", "roots": ["src/redux/apis"], "basePath": "/api/v1" },
"server": { "adapter": "nestjs", "repo": "../api", "roots": ["src"], "globalPrefix": "api/v1" },
"failOn": ["drift"]
}
実行します。
tieline check
tieline · contract check
❌ 2 drift (FE calls a route the backend does not expose)
GET /users/{}
getUser · web/src/redux/apis/user-api.ts:42
→ did you mean "user/{}"? # plural vs singular — a guaranteed 404
PUT /orders/{}
updateOrder · web/src/redux/apis/order-api.ts:88
→ path exists but as GET, not PUT # method mismatch
✅ 274 matched ❌ 2 drift ⚠️ 6 unverifiable 🟡 31 unused backend routes
failOn のいずれかの分類に該当項目があると、check はゼロ以外の終了コードを返します。CI に追加すれば、2 つの側で不一致が見つかった時点でビルドが失敗します。
コマンド
tieline init # auto-detect nearby repos and write tieline.config.json
tieline check # FE↔BE drift; exits non-zero on drift (the CI gate)
tieline list # the full resolved contract map (every endpoint + status)
tieline orphans # backend routes no frontend call reaches
tieline doctor # code↔spec drift (see below)
| フラグ | 効果 |
|---|---|
--config <path> | tieline.config.json のパス(デフォルト:現在の作業ディレクトリから上位を検索) |
--json | 機械可読形式の出力 |
--html <file> | 自己完結型のビジュアルレポート(ビジュアルレポートを参照) |
--no-fail | 常に 0 で終了(レポートのみ) |
サポートされているスタック
クライアントアダプターとサーバーアダプターは自由に組み合わせられます。マッチャーが変わることはありません。
| クライアント(呼び出し元) | サーバー(ルート) |
|---|---|
rtk-query — Redux Toolkit Query | nestjs — デコレーター |
axios-fetch — axios/fetch、React Query と SWR の queryFn | express — app.use() のマウントグラフ、ファイルをまたいで解析 |
angular-http — Angular HttpClient | fastify — 動詞の短縮形と route({}) |
next — ファイルベース(app router と pages API) | |
fastapi — APIRouter のプレフィックスと include_router | |
flask — ブループリントと methods=[] | |
spring — @RequestMapping と @*Mapping | |
openapi — 汎用:任意の OpenAPI 2/3 ドキュメント(ファイルまたは URL) |
MERN(rtk/axios ↔ express)、MEAN(angular ↔ express)、MEVN
(axios ↔ express)、Next のフルスタック、Python(fastapi/flask)、
エンタープライズ(angular ↔ spring)をカバーします。さらに、仕様を出力する任意のバックエンド(Express+swagger-jsdoc、FastAPI、Spring springdoc、.NET Swashbuckle など)には openapi を利用できます。
注意事項:
expressはrequire/importの境界を越えてapp.use()のマウントグラフとネストされたルーターをたどります。到達できないルーターにはフラグが立ち、破棄されることはありません。nextはファイルシステムルーティングです。app-router ファイルはGET/POST/…をエクスポートし、pages-router のハンドラーは任意の動詞を処理します(ALLとして照合)。- 実行時に組み立てられる URL(例:
`users/${id}?x=${q}`)は推測せず、検証不能として表示されます。
設定
tieline.config.json — リポジトリのパスは設定ファイルを基準に解決されます。
{
"client": {
"adapter": "rtk-query", // rtk-query | axios-fetch | angular-http
"repo": "../web",
"roots": ["src/redux/apis"], // dirs to scan for call sites
"basePath": "/api/v1" // stripped from call sites before matching
},
"server": {
"adapter": "nestjs", // nestjs | express | fastify | next | fastapi | flask | spring | openapi
"repo": "../api",
"roots": ["src"],
"globalPrefix": "api/v1", // stripped from routes before matching
"spec": "openapi.json" // openapi adapter & `doctor` only — file path or URL
},
"ignore": ["internal/.*"], // regexes on the normalized path
"failOn": ["drift"] // buckets that make `check` exit non-zero
}
ビジュアルレポート
tieline check --html report.html は、任意のブラウザーで開いたり PR に添付したりできる、自己完結型のファイルを 1 つ(CSS/JS をインライン化し、外部アセットなし)書き出します。
- コントラクトフロー図 — 左にフロントエンドのリソース、右にバックエンドを配置し、一致を緑、不一致を赤の曲線で結びます。どこにも到達しない呼び出しを受け止める
∅ no routeノードも表示されます。リソースにカーソルを合わせると、そのリンクが強調表示されます。 - ヘルスリング、サマリーカード、ライブフィルター対応の不一致/検証不能/未使用テーブル
tieline doctor — コードは公開済みドキュメントと一致していますか?
doctor は、ソースから解析したルート(nestjs などのネイティブアダプター)と、OpenAPI 仕様(server.spec)で宣言されたルートを差分比較します。
tieline · doctor code (nestjs) ↔ spec (http://localhost:9999/doc-json)
❌ 4 undocumented (in code, missing from the published spec)
GET /billing/invoices src/billing/billing.controller.ts:54
POST /webhooks/stripe src/webhooks/webhooks.controller.ts:21
...
👻 1 phantom (in the spec, no matching route in code)
✅ 312 agree ❌ 4 undocumented 👻 1 phantom (316 code routes, 313 spec routes)
- ドキュメント未記載 — 動作しているルートが、仕様から SDK やパートナー連携を生成する人には見えません。
- 幻のルート — 仕様では提供されるとされているルートが、コードではすでに提供されていません(古いドキュメント)。
check と併せて実行すれば、仕様がコードから知らないうちに乖離することはありません。
MCP サーバーとして使用する
tieline にはMCPサーバーが組み込まれているため、エージェントが「この 2 つのリポジトリはまだ一致していますか?」と尋ねると、CLI が生成するものと同じ構造化された結果が返されます。分析を行うのは LLM ではなく、決定論的エンジンです。 SDK を使用しない、依存関係ゼロの構成はそのままです。サーバーは stdio JSON-RPC を手作業で実装しています。
任意の MCP クライアント(Claude Code、Claude Desktop、…)に登録します。
{
"mcpServers": {
"tieline": { "command": "npx", "args": ["-y", "-p", "@nugehs/tieline", "tieline-mcp"] }
}
}
または、グローバルインストール(npm i -g @nugehs/tieline)からは、単に "command": "tieline-mcp" と指定します。
JSON を返す 5 つのツールを公開します。
| ツール | 引数 | 戻り値 |
|---|---|---|
tieline_check | config? | 合計 + drift + unverifiable(ドリフトゲート) |
tieline_list | config? | 解決済みの完全なコントラクトマップ |
tieline_orphans | config? | フロントエンドから呼び出されていないバックエンドルート |
tieline_doctor | config? | undocumented + phantom(コード ↔ 仕様) |
tieline_init | cwd? | 近くにあるリポジトリを自動検出し、設定を書き込みます |
config は CLI とまったく同様に、サーバーの作業ディレクトリから上位へ検索するのがデフォルトです。そのため、tieline.config.json のあるリポジトリでエージェントを起動すれば、tieline_check を呼び出すだけで済みます。
アーキテクチャ
各側は単一のエクストラクターを実装し、それ以降の処理はすべて共有されます。
ClientAdapter.extract() → Endpoint[] { method, rawPath, resolvable, file, line }
ServerAdapter.extract() → Route[] { method, rawPath, file, line }
新しいフレームワークを追加する場合、新しいアダプター(約 80 行)を用意します。ノーマライザー、マッチャー、レポーター、CLI を変更する必要はありません。パスの存在確認によるドリフト検出は現在利用できます。OpenAPI のDTO 形状の差分検出(--deep)と SARIF/PR アノテーションはロードマップに含まれています。
テスト
npm test # node --test — zero dependencies, nothing to install
Node の組み込みランナーで 71 件のテストを実行します。
- normalize — すべてのパラメーター構文(
${id}/:id/<int:id>/[id]/{id})、クエリの除去、basePath、パスの結合 - matcher — 4 つすべてのバケット、ドリフトのヒント(method-mismatch、「もしかして」)、
ignore、任意の動詞を受け付けるALL/ANYルート、異なる構文間でのパラメーター照合 - adapters — フィクスチャを使ったすべてのクライアントおよびサーバーアダプターのテストに加え、一時的なリポジトリを使ったエッジケースのテスト(Express の
app.allと未マウントのルーター、Next のルートグループとキャッチオール、Spring の@RequestMapping(method=…)、Flask のデフォルト GET、実行時の URL → 検証不能、HttpClient 以外の.get()は無視) - openapi —
servers[].urlのプレフィックス、Swagger 2 のbasePath、stripPrefix - doctor — undocumented/phantom/matched とヒント
- init — スタックの自動検出(node の依存関係、Python、Spring、OpenAPI のフォールバック)、ディレクトリ名による優先判定、兄弟/子ディレクトリのスキャン、プレースホルダーへのフォールバック、設定の往復検証
- integration — 3 つの異なるスタック間の検証(RTK↔Express、Angular↔Spring、axios↔FastAPI)と実際の CLI(終了コード、
--json、--html、doctor) - mcp — stdio JSON-RPC サーバー:ハンドシェイク、
tools/list、フィクスチャに対する実際のtieline_check、インバンドのツールエラー、メソッドが見つからない場合の処理
ロードマップ
- SARIF 出力 — GitHub PR にドリフトをインラインで注釈
--deep— OpenAPI を使い、パスだけでなくリクエスト/レスポンスのDTO 形状を比較します(フィールド名の変更や列挙型の変更を検出します。こうした変更は大きなバグにつながります)- アダプターの追加 —
react-query/swrのファーストクラスクライアント、koa/djangoのサーバー - AST 抽出 — 特殊な宣言の正規表現による解析を置き換えます
現在の既知の制限:正規表現ベースの抽出(一般的なコードでは堅牢です)、1 ファイルにつき @Controller は 1 つ、パス/メソッドの存在確認のみです。GraphQL は対象外です。
ライセンス
MIT © Segun Olumbe
ツールチェーンの一部
tieline は、AI 支援開発のための決定論的な信頼レイヤーを構成する 4 つのツールの 1 つです。それぞれ、誰もが LLM に何度も尋ねている問いに、静的解析で答えます。
- repoctx — コンテキスト:この変更は実際に何に影響しますか?
- tieline(このツール)— コントラクト:フロントエンドとバックエンドの間で、いつの間にか合意が崩れていませんか?
- bouncer — コンプライアンス:この内容を Ofcom に弁明できますか?
- aiglare — ガバナンス:モデルが、取り消せない操作を実行できるのはどこですか?
詳しくは segunolumbe.com をご覧ください。モデルではなく、静的解析。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。