コンテンツにスキップ

MCP (Model Context Protocol)

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

MCP とは

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

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

Reyn が担う 2 つのロール

ロール 方向 仕組み
MCP クライアント — Reyn が外部サーバーを呼ぶ アウトバウンド Phase の mcp Control IR op + permissions.mcp: 宣言。ワークフローは「このサーバーのこのツールを呼んでほしい」と指示し、OS が MCPClient(stdio / http / sse)経由でディスパッチします。例:ワークフローが 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 chatmcp category の verb actions を自動的に使えます:

Action 何をするか
mcp__search_registry({text}) 公式 MCP registry で新規サーバーを検索
mcp__install_registry({server_id}) 公式 MCP registry の server を install
mcp__install_package({kind, identifier, version?}) npm / pypi / docker / GitHub URL から install
mcp__install_local({name, command, args}) local command (LLM 生成 script 等) を直接 MCP server として登録
mcp__list_servers() .reyn/mcp.yaml に設定された全サーバー名を返す
mcp__list_tools({server}) 1 サーバーが露出する tool 一覧を {name: "<server>__<tool>", description, inputSchema} 形式で返す
mcp__call_tool({tool, tool_args}) <server>__<tool> ID + tool の declared tool_args で tool を call
mcp__drop_server({server}) install 済サーバーを config から削除

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

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

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

phase frontmatter         LLM が Control IR を発行    OS がディスパッチ
  permissions:        →     {kind: mcp,           →   MCPClient
    mcp: [filesystem]        server: filesystem,        (stdio | http | sse)
                             tool: read_text_file,
                             args: {path: ...}}
  1. ワークフローの 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 と同一です。

境界が明確なのは意図的です。ワークフローは何が必要かを記述し、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 つのポイントでゲートされます:

インストール時ゲート: file.write + http.get

MCP サーバーを設定に追加する際、install op の書き込みは OS の標準 list-axis gate を通ります。 旧 permissions.mcp_install: ask | allow | deny bool 軸は collapse arc で撤去され、 install 制御は以下の経路に統一されました:

  • .reyn/mcp.yaml への file.write (= canonical mutation target)。 startup_guard が workflow+path ごとに 1 回 operator に prompt、 承認後の runtime は silent。
  • registry.modelcontextprotocol.io への http.get (= registry fetch)。 同じ prompt model。
  • registry が isSecret 指定する env-var key への secret.write (= key set が runtime 決定なので wildcard "*")。

エンタープライズチームは 2 つの等価な mechanism で private / corporate registry を指定:

A. reyn.yaml mcp.registries: list config — declarative、 project-scoped、 version-controlled:

# reyn.yaml (project scope — committed to git)
mcp:
  registries:
    - https://mcp-registry.internal.acme.com   # private registry (= 最初に試行)
    - https://registry.modelcontextprotocol.io  # public fallback
permissions:
  web.fetch: allow      # registry fetch の blanket allow
  file.write: allow     # .reyn/mcp.yaml 書き込みの blanket 承認

B. REYN_MCP_REGISTRY_URLS (plural) env var — explicit operator override、 CI / per-shell config 用途:

# operator shell rc / systemd unit / CI runner env
export REYN_MCP_REGISTRY_URLS="https://mcp-registry.internal.acme.com,https://registry.modelcontextprotocol.io"

両方 set されている場合 env var が勝つ (= explicit operator override が declarative config を override)。 legacy 単数形 REYN_MCP_REGISTRY_URL は単一要素 list として backward compat 維持。

async op-handler client (reyn.core.registry.client) と safe-mode skill-internal lookup (reyn.api.safe.mcp.registry) の両方が list を順次 iterate:

Operation 挙動
lookup(server_id) 順次試行、 first non-404 hit を返却、 全 404 → None、 404 後の non-404 error は re-raise
search(query) 順次試行、 first non-empty result を返却、 全 empty → []

「private first, public fallback」 pattern: private registry の同名 entry は public を shadow、 public は private に無い名前の discoverability fallback。

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

permissions.mcp_install: ... キーは reyn.yamlDeprecationWarning 付きで受理され、 migration window 期間中は等価な gate に translate されます。

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

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

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

これは reyn の一般的なパーミッションモデルと一致します(../runtime/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 でフィルタリングできます。

MCP を使う stdlib ワークフロー

Stdlib ワークフローでは Phase で permissions.mcp: [<server>] を宣言し、tool: <name>(サーバーが公開するツール名)で mcp op を発行し、あとは OS に任せます。独自の MCP バックエンドワークフローを作るときの完全なクイックスタートは 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 の場合はエージェントがまだ作業中です。続きを受け取るには再度呼び出してください。

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

ワークフローから見た「MCP 経由」の意味

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

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

MCP が適さない用途

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

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

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

関連項目