コンテンツにスキップ

MCP (Model Context Protocol)

reyn は MCP を双方向で実装しています。外部の MCP サーバーを呼び出すクライアントとして機能し、かつ自分自身のエージェントを外部の LLM クライアントに公開するサーバーとしても機能します。この 2 つのロールは独立しており、どちらも実装済みです。

MCP とは

MCP は AI エージェントがツールを公開する「サーバー」に接続するための JSON-RPC プロトコルです。仕様は Anthropic が modelcontextprotocol.io で公開しています。公式のサーバー実装(filesystemgitgithubfetchbrave-search など)が多数あり、サードパーティも多数提供しています。サーバーはツールリスト(tools/list)を公開し、呼び出し(tools/call)を実行します。エージェント側はベンダー非依存のままです。

要点:Skill は「filesystem サーバーの read_text_file ツールを呼んでほしい」と宣言するだけです。「cat を実行してほしい」とは言いません。バックエンドを差し替えるのは設定変更であり、コード変更ではありません。

Reyn が担う 2 つのロール

ロール 方向 仕組み
MCP クライアント — Reyn が外部サーバーを呼ぶ アウトバウンド Phase の mcp Control IR op + permissions.mcp: 宣言。Skill は「このサーバーのこのツールを呼んでほしい」と指示し、OS が MCPClient(stdio / http / sse)経由でディスパッチします。例:Skill が filesystem MCP サーバーを通じてファイルを読む。
MCP サーバー — 外部クライアントが Reyn を呼ぶ インバウンド reyn mcp serve --project . を実行すると Reyn が JSON-RPC サーバーになります。Claude Code、Cursor、OpenAI Agents SDK など MCP に対応した任意のクライアントが、list_agents()send_to_agent(agent_name, message) の 2 つのツールを通じて Reyn のエージェントを呼び出せます。

このページでは以降、各ロールを順に解説します。

クイックスタート: 3 つのコマンドでゼロから MCP を動かす

初回利用時の推奨フローは reyn mcp install です。YAML の手動編集は不要です:

# 1. 利用可能なサーバーを検索
reyn mcp search "github"

# 2. インストール(設定 + 認証情報 + パーミッションゲートを一括処理)
reyn mcp install io.github.modelcontextprotocol/server-github

# 3. すぐに使い始める
reyn chat
> このリポジトリの最近の PR を一覧して

reyn mcp install は MCP レジストリからサーバーマニフェストを取得し、必要なランタイム(npxuvx など)がインストールされているか確認し、認証情報をプロンプト(~/.reyn/secrets.env に安全に保存)し、シークレットを ${VAR} 参照として設定に書き込みます。これらをすべて 1 ステップで実行します。

レジストリに未登録のサーバー (= Anthropic 公式 reference servers @modelcontextprotocol/server-filesystem 等) は --source を使います:

reyn mcp install --source npm:@modelcontextprotocol/server-filesystem
reyn mcp install --source pypi:mcp-server-fetch
reyn mcp install --source docker:mcp/playwright
reyn mcp install --source https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem

--source はレジストリ取得を skip し、 ソース指定子から install metadata を直接解決します。 パーミッションゲート / 認証情報 / 設定書込 / 監査 event はレジストリ path と同一です。

完全な reyn mcp CLI リファレンスは Reference: reyn mcp を参照してください。

クイックスタート: reyn chat から MCP を試す(手動設定パス)

手動でサーバーを設定したい場合や、公開レジストリにないサーバーを追加する場合は、reyn.yaml に直接追加します。サーバーを設定すると、reyn chat は自動的に 3 つの router tool を使えます:

Tool 何をするか
list_mcp_servers reyn.yaml に設定された全サーバー名を返す
list_mcp_tools(server) 1 つのサーバーが露出する tool 一覧を返す
call_mcp_tool(server, tool, args) サーバー上の tool を呼び出して結果を返す

LLM router がチャット turn 内で直接これらを呼べます。 初回利用の典型 flow:

# 1. reyn.yaml にサーバーエントリを追加 (1 回のみ)
mcp:
  servers:
    filesystem:
      type: stdio
      command: npx
      args: ["-y", "@modelcontextprotocol/server-filesystem", "."]

# 2. reyn.yaml で事前承認、 もしくは初回プロンプトで承認
permissions:
  mcp:
    filesystem: allow

# 3. あとは普通にチャット
reyn chat
> このディレクトリにある README.md を要約して

router が自動的に list_mcp_toolscall_mcp_tool を呼び出します。 どの skill にも permissions.mcp: 宣言を書く必要はありません。 Skill 作成は、 繰り返し使うワークフローを形式化したい時 (= phase graph / validation / retry policy が必要になった時) に検討するものであって、 MCP を使う前提条件ではありません。 以下の deep-dive はその場合の話で、 ad-hoc 利用だけならここで読み終えて問題ありません。

ロール 1:MCP クライアント — Reyn が外部サーバーを呼ぶ

Skill が外部ツールを必要とするときの流れは次のとおりです:

phase frontmatter         LLM が Control IR を発行    OS がディスパッチ
  permissions:        →     {kind: mcp,           →   MCPClient
    mcp: [filesystem]        server: filesystem,        (stdio | http | sse)
                             tool: read_text_file,
                             args: {path: ...}}
  1. Skill の Phase は frontmatter で permissions.mcp: [server_name] を宣言します。宣言がなければ、ランタイムはそのサーバーへのすべての呼び出しを拒否します。
  2. LLM は mcp Control IR op として {server, tool, args} を発行します。サーバー名を勝手に作ることはできません。reyn.yaml で設定され Phase のパーミッションに宣言されたサーバーだけが到達可能です。
  3. OS はサーバーのトランスポート(stdiohttpsse)を解決し、MCPClient 経由でディスパッチして、ツールの結果を Phase ループに返します。
  4. 呼び出しごとに event が発行されます。呼び出し前に mcp_called、正常終了後に mcp_completed(またはエラー時に mcp_failed)。監査証跡は他の op と同一です。

境界が明確なのは意図的です。Skill は何が必要かを記述し、OS がどう取得するかを決めます。新しい MCP サーバーを追加しても OS コードには一切触れません(P7)。

トランスポートの選択(stdio vs HTTP)

公式の MCP サーバーの大多数は stdio 経由で起動するローカルプロセスです。一部のホスト型サービスは HTTP エンドポイントを公開しています。SSE トランスポートは将来のリリース向けです。

トランスポート 用途 reyn の起動方法
stdio ローカル CLI サーバー(大多数の公式サーバー — filesystemgitgithubfetch commandargsenv 付きで起動し、stdin/stdout 越しに JSON-RPC を話す
http ホスト型サービス(自前バックエンド、組織内ツールレジストリ) urlheaders 付きで POST し、実行中はセッションを再利用
sse HTTP のストリーミング変種。用途はまれ http と同様にイベントストリームを追加

npxpip install でローカル実行するものには stdio を選んでください。サーバーを他者が運用していて URL を渡されている場合は http を選んでください。

設定

MCP サーバーは reyn.yamlmcp.servers: 配下で宣言します。各エントリには type が必須で、残りはトランスポートによって異なります。

# reyn.yaml
mcp:
  servers:
    # stdio: ローカルプロセス、stdin/stdout 越しに JSON-RPC を話す
    filesystem:
      type: stdio
      command: npx
      args: ["-y", "@modelcontextprotocol/server-filesystem", "."]
      env:
        # 任意。${VAR} は起動時に os.environ から展開されます。
        FS_LOG_LEVEL: "info"

    # http: ホスト型サーバー、Streamable HTTP 越しの JSON-RPC
    internal_tools:
      type: http
      url: https://tools.example.internal/mcp
      headers:
        Authorization: "Bearer ${INTERNAL_TOOLS_TOKEN}"
フィールド stdio http 説明
type 必須 必須 stdio | http | sse
command 必須 起動する実行ファイル(例:npxpython、絶対パス)
args 任意 command に渡す引数リスト
env 任意 起動プロセスへの追加環境変数
url 必須 エンドポイント URL
headers 任意 静的ヘッダー。値は ${VAR} 展開に対応

${VAR} の展開は os.environ から解決されます(起動時に ~/.reyn/secrets.env から事前ロードされています。詳細は コンセプト: シークレット管理 参照)。変数が存在しない場合は "" に展開され警告が出ますが、ハードエラーにはなりません。オプショナルなトークンが欠けていても実行はクラッシュしません。

${VAR} 構文は mcp.servers だけでなく、すべての YAML 文字列フィールドで使えます。models.<name>.api_keylitellm.api_base などすべてが同じ仕組みを使います。全体像は Reference: reyn.yaml${VAR} interpolation を参照してください。

API キーとトークンは ~/.reyn/secrets.envreyn secret set で管理)に置き、reyn.yaml では ${VAR} として参照してください。リテラルの値をインラインで書かないでください。詳細は コンセプト: シークレット管理 を参照してください。

セキュリティモデル

MCP の操作は 2 つのポイントでゲートされます:

インストール時ゲート: permissions.mcp_install

MCP サーバーを設定に追加する前に、mcp_install パーミッションゲートが実行されます。これは reyn mcp install と、skill が発行する mcp_install Control IR op の両方に適用されます。デフォルトは ask — 初回インストール時にインタラクティブプロンプトが表示されます。

エンタープライズチームは、プロジェクトスコープの reyn.yamlpermissions.mcp_install: deny を設定してすべてのサーバー追加を防ぐか、mcp_install: allow とプライベートレジストリを組み合わせて「承認済みサーバーのみ」ポリシーを強制できます:

# enterprise reyn.yaml — チーム全体のポリシー
mcp:
  registries:
    - https://mcp-registry.internal.acme.com/    # プライベートレジストリ(承認済みサーバーのみ)
    - https://registry.modelcontextprotocol.io/   # パブリックフォールバック
permissions:
  mcp_install: allow    # チームはインストール可能だが、プライベートレジストリのサーバーのみ事実上限定

詳細は コンセプト: パーミッションモデル — mcp_install を参照してください。

ランタイムゲート: permissions.mcp

MCP 呼び出しはプロセスを離れる前に 2 つのチェックを通過します:

  1. Phase 宣言。 Phase は frontmatter の permissions.mcp に使用したいサーバーを必ずリストアップしなければなりません。ランタイムは require_mcp(decl, server, ...) を呼び出し、server not in decl.mcp の場合は宣言欠落を明示したエラーで失敗します。
  2. 承認。 他のケイパビリティと同様に、Skill ごとの初回呼び出しでプロンプトが表示されます(y / j / r / N)。永続的な承認は .reyn/approvals.yaml<skill>/mcp.<server> キーで保存されます。プロジェクト全体を信頼できる場合は reyn.yamlpermissions.mcp: allow と設定して事前承認できます。

これは reyn の一般的なパーミッションモデルと一致します(permission-model.md 参照)。ある Skill の MCP 承認が別の Skill に漏れることはなく、run_skill 経由で起動したサブスキルは独自にパーミッションを要求します。

呼び出しごとに 3 つの監査 event が発行されます:

Event タイミング ペイロード
mcp_called リクエストがプロセスを離れる前 servertoolargs
mcp_completed 正常返却時 servertoolis_error
mcp_failed トランスポート / プロトコルエラー時 servertoolerror

reyn events tail | grep mcp_ または grep '"mcp_called"' .reyn/events.jsonl でフィルタリングできます。

最初の stdlib Skill:read_local_files

read_local_files は MCP サーバーを中心に構築された Skill の典型例です。filesystem MCP サーバーと組み合わせてプロジェクト内のファイルを読み、セクションを要約し、内容に関する質問に答えます。普通の cat がすることをすべてパーミッションシステムと監査ログ経由で行います。

独自の MCP バックエンド Skill を作るときのテンプレートとして使ってください。Phase で permissions.mcp: [filesystem] を宣言し、tool: read_text_file(またはサーバーが公開するツール名)で mcp op を発行し、あとは OS に任せます。

Phase の形については リファレンスページ、完全なクイックスタートは how-to を参照してください。

ロール 2:MCP サーバー — 外部クライアントが Reyn を呼ぶ

reyn mcp serve を実行すると Reyn が MCP サーバーになります。Claude Code、Cursor、OpenAI Agents SDK など MCP プロトコルに対応した任意の外部クライアントが、Reyn のエージェントにメッセージを送れるようになります。

サーバーの起動

reyn mcp serve --project /path/to/your/project

--projectreyn.yaml が置かれているディレクトリを指します。MCP クライアントはサーバープロセスを cwd=/ で起動することが多いため、ほとんどのクライアント設定でこのフラグが必須になります。これがないとサーバーはプロジェクトを見つけられません。--timeout(デフォルト 60 秒)は send_to_agent が部分的な返答を返すまでブロックする最大時間を制御します。エージェントはタイムアウト後もバックグラウンドで作業を継続します。

サーバーは stdio 越しに JSON-RPC を話します。ポートはありません。MCP クライアント自身がプロセスを起動してトランスポートを所有します。

公開されるツール

2 つのツールが登録されます:

ツール シグネチャ 動作
list_agents () reyn.yaml に登録されたエージェントの {name, role} 配列を JSON で返します。
send_to_agent (agent_name, message) 指定したエージェントにユーザー形式のメッセージを 1 件送信し、最終の返答テキストを(--timeout 秒まで)ブロックして返します。{reply, partial, agent} を返します。partial=true の場合はエージェントがまだ作業中です。続きを受け取るには再度呼び出してください。

マルチターンの継続性は自動で保たれます。各エージェントの ChatSession は呼び出し間も history.jsonl を保持するため、Claude Code で始めた会話を reyn chat で再開することも、その逆も可能です。

Skill から見た「MCP 経由」の意味

外部クライアントはエージェントを見るのみで、Skill グラフは見えません。外部から操作できるのは「エージェント一覧の取得」と「メッセージ送信」だけです。Reyn 側では OS コントラクトが通常通り適用されます。パーミッションのチェック、event の発行、バリデーションはすべて実行されます。MCP サーバーは stdin に人間がいない状態で動作するため、対話的なプロンプトは無限にブロックします。reyn.yamlpermissions: allow を設定すれば非対話的に事前承認できます。

これは Reyn の「外に話しかける + 話しかけられる」マルチエージェントサーフェスの一部です。単一の Reyn プロセス内でエージェント同士がどう関連するかは multi-agent.md を参照してください。

MCP が適さない用途

MCP は 外部ケイパビリティへのアクセス に適したツールです。以下のケースでは使わないでください:

  • 重い計算が必要な場合。 Python プリプロセッサー(python op)を使ってください。MCP 呼び出しは毎回プロセス境界を越えます。インラインの NumPy ステップの方がはるかに高速です。
  • 再利用可能なワークフローを実現したい場合。 それは MCP サーバーではなく Skill です。skill_builder で新しい Skill を作ってください。
  • エージェント間メッセージングが必要な場合。 messages_to_agents とトポロジールールを使ってください。MCP はエージェントのアイデンティティやチェーンをモデル化しません。
  • 呼び出し間の状態が必要な場合。 MCP サーバーはステートレスにもステートフルにもできますが、reyn は各呼び出しを独立したものとして扱います。永続的な状態はワークスペースに置いてください。

これらの用途で MCP を使いたいと思ったら、レイヤーを間違えています。

関連項目