MCP Fusion/Core concepts/ルーティング

ルーティング

VinkiusについてAIに質問

Next.jsがページをルーティングするように、ファイルツリーからツールを自動検出します。フォルダはドット区切りの名前になり、exportは規約で解決され、巨大なAPIサーフェスは少数のスマートなツールに集約されます。

MCP Fusionは、Next.jsがページを検出するのと同じように、ファイルツリーからツールを検出します。1ファイル1ツール、パスがそのまま名前になります。

ファイルベースのツール

src/tools/
  billing/
    get-invoice.ts    →  billing.get_invoice
    refund.ts         →  billing.refund
  support/
    tickets/
      search.ts       →  support.tickets.search

起動時に一度だけ登録します:

typescript
import { initMCPFusion, autoDiscover } from '@mcpfusion/core';

const f = initMCPFusion();
await autoDiscover(f, './src/tools');

各ファイルはビルダーをdefault exportし、export解決のカスケードはdefault export、名前付きのtool export、または自分の名前を報告する任意のexport済みビルダーを受け付けます。

グループ化されたツール

数百のエンドポイントを持つAPIが数百のツールに対応するわけではありません。ツールの名前、スキーマ、説明はすべてコンテキストウィンドウを消費し、リストが増えるほどエージェントの精度は低下します。GroupedToolBuilderは、関連するアクションを1つのディスクリミネーター付きツールに統合します:

typescript
f.group('billing')
  .describe('Invoice operations')
  .action('get', (a) => a
    .withString('id', 'Invoice ID')
    .requiredFor('get', ['id']))
  .action('refund', (a) => a
    .withString('id', 'Invoice ID')
    .withNumber('amount_cents', 'Amount in CENTS')
    .requiredFor('refund', ['id', 'amount_cents']))
  .returns(InvoicePresenter);

エージェントはディスクリミネーター引数付きでbillingを呼び出し、「Required for」アノテーションが各アクションに必要なパラメータを伝えます。500のエンドポイントのフラットなサーフェスが、少数のスマートなツールになります。これは大規模なコネクタで得られる最大のトークン削減です。ツールごとのビルダーについてはToolsを、グループ化されたサーフェスの監査可能性についてはGovernanceを参照してください。

ミドルウェアチェーン

ミドルウェアはディレクトリツリー単位とツール単位でグローバルに適用されます:

typescript
// A middleware derives context; its return object merges into ctx.
const withTenant = f.middleware(async (ctx) => ({
  tenantId: resolveTenant(ctx.request),
}));

f.query('billing.get_invoice').use(withTenant);
  • グローバルなf.middleware()はすべてのツールで実行されます
  • ビルダー上の.use()はツール固有のミドルウェアを追加します
  • チェーンはビルド時にO(1)パイプラインへプリコンパイルされるため、ミドルウェアを追加してもリクエストパスは遅くなりません

ミドルウェアが返すコンテキストはctxにマージされ、initMCPFusion<AppContext>()ジェネリクスで型付けされます。下流のすべてのハンドラー、ミドルウェア、Presenterが同じ型付きコンテキストを受け取るため、テナント分離がコネクタ全体で一貫します。

起動とコンテキスト

typescript
f.registry.attachToServer(server, {
  contextFactory: async (extra) => ({
    db: await pool.acquire(),
    tenantId: resolveTenant(extra),
  }),
});

contextFactoryはリクエストごとに実行されるため、データベース接続やテナント識別情報のようなリクエスト単位のリソースは毎回新しく分離されます。返されたすべてが、ハンドラーが受け取るctxです。

次のステップ

  • Tools: ビルダー本体、パラメータ、ステートゲーティング
  • Quickstart: 最小限の動作するコネクタ
  • Deploy: ツリー全体をVinkius Cloudへデプロイ