Cursorなどで使える「サブエージェント」を擬似実現するMCPサーバーを作った話

こんにちは、かがわ(@shinpr_p)です。

私は、Agentic Codingをする際にはClaude Codeを使っています。最近挙動が不安定という声もありますが、当面はメインエージェントとしてClaude Codeを使うつもりです。
使い続ける理由は、Sub agents(サブエージェント)があることです。サブエージェントはコンテキストが分離され、一つの作業に集中します。サブエージェントをうまく活用することで、メインエージェントのコンテキストウィンドウ枯渇対策にもなりますし、不要なコンテキストが入らず精度の向上にも寄与します。
そのため、サブエージェント機能を重視する私としては、最近出てきたCursor CLIを使うことができないという訳です。

とはいえ、新しいツールが出たら実際に使ってみることは大切です。
「でもサブエージェントがほしい…」ということで、ないなら自分で作ろうという結論に至りました。

今回は、そんな経緯で生まれた擬似的なサブエージェントを実現するMCPについて紹介します。

github.com

MCPの設定

今回はCursorを例にして説明します。
IDEであれば、
Cursor > Cursor Settings > Tools & Integrations > New MCP Server
からMCPを追加できます。

ファイルを直接編集する場合は、~/.cursor/mcp.jsonMCPの定義ファイルがあるはずです。

これらに、以下のようなMCP定義を追加します。

{
  "mcpServers": {
    "sub-agents": {
      "command": "npx",
      "args": ["-y", "sub-agents-mcp"],
      "env": {
        "AGENTS_DIR": "/Users/username/projects/my-app/.cursor/agents",
        "AGENT_TYPE": "cursor"
      }
    }
  }
}

AGENT_TYPEcursorclaudeを指定できます。それぞれ、Cursor CLI(cursor-agent)とClaude Code(claude)です。サブエージェントとして挙動するエージェントを指定することができます。

Cursor CLI自体のインストールについては以下のコマンドで実行できます。
curl https://cursor.com/install -fsS | bash

Cursor CLIについての詳細はこちらを参照してください。

cursor.com

Cursor CLIを実際に使うときには事前にログインが必要です。また、定期的にセッションが切れるようなので、MCPが応答しなくなった時は再ログインを試してみてください

% cursor-agent login

AGENTS_DIR絶対パスで指定する必要があります
具体的にどのようなファイルを配置するかについては後述するサブエージェントの定義で詳しく説明しますが、各ツールのプロジェクト設定ディレクトリ(Cursorなら.cursor、Claude Codeなら.claude)配下に専用のディレクトリを配置することをお勧めします。
/Users/username/projects/my-app/.cursor/agents

サブエージェント定義の作成

サブエージェントについては各所で説明されているので詳細な説明は割愛します。
公式

docs.anthropic.com

※ 余談ですが、Anthropicの多くのWeb記事は末尾に.mdをつけるとMarkdownで記事の内容を返してくれます。AIに読ませる時は.mdをつけるとコンテキストの節約になるのでお勧めです。

私が以前書いた記事

zenn.dev

sub-agents-mcpは、Claude Codeのサブエージェント実装をインスパイアしています。
つまり、AGENTS_DIR配下にある、Markdownファイルを「エージェント定義ファイル」として解釈し、ファイルの内容全体をシステムコンテキストという位置付けでCursor CLI および Claude Codeに与え、ユーザープロンプトを実行してもらいます。

.claude
  ┗ agents
     ┣ code-reviewer.md      # code-reviewerとして呼び出すと、この定義に沿って動きます
     ┗ document-reviewer.md  # document-reviewerとして呼び出すと、この定義に沿って動きます

サブエージェント定義を作るコツについて、いくつかピックアップしておきます。上記私の記事の中にも、定義サンプルや実際動くサブエージェントをまとめたリポジトリのリンクがあるので、より詳しく知りたい方はそちらを参照ください。
※ 記事やリポジトリ(つまりClaude Codeのサブエージェント定義)からそのまま持ってくる場合、フロントマターはCC独自の定義を含むため本MCPでは不要です。削除したうえで使ってみてください。

  • 単一の責任を果たす単位でサブエージェントを定義する
  • 作業に必要な情報はサブエージェント定義で十分に与え、不必要な情報は極力排除し、タスクの完遂に集中させる
  • コンテキストウィンドウに収まる範囲で1タスクが終わるよう、適切にタスクを分解する

例えば、生成(ドキュメント作成・コード実装)とレビューは、タスクとして分けることを推奨します。
実装時に多くのコンテキストを取得しているため、レビュー時には不要となるコンテキストも存在しているためです。
また、生成からレビューまで1タスクでやろうとすると、レビュー時にはコンテキストが枯渇し始めていることがほとんどです。これではレビューの精度が出ません。

このように、一連の作業を眺め、どこでどういったコンテキストが必要か、どこに責任境界があるかを考えタスク分解し、タスクに合わせたサブエージェントを作ると実行精度が出てくるはずです。お試しください。

document-reviewer.mdのサンプル

あなたは技術ドキュメントのレビューを専門とするAIアシスタントです。

## 責務

1. 完成度と品質の評価
2. 改善提案の提供
3. 承認可否の判定
4. **技術的主張の出典確認と最新情報との照合**

## 入力パラメータ

- **target**: レビュー対象のドキュメントパス

## 作業フロー

### 1. 対象ドキュメントの収集
- targetで指定されたドキュメントを読み込み

### 2. 観点別レビューの実施
- 整合性チェック:ドキュメント内の矛盾を検出
- 完成度チェック:必須要素の有無を確認

### 3. レビュー結果の報告
- 観点に応じた形式で結果を出力
- 問題の重要度を明確に分類

## 出力フォーマット

### 構造化マークダウン形式

**基本仕様**:
- マーカー: `[SECTION_NAME]`...`[/SECTION_NAME]`
- 形式: セクション内でkey: value使用
- 重要度: critical(必須)、important(重要)、recommended(推奨)
- カテゴリ: consistency、completeness、compliance、clarity、feasibility

総合評価、スコア(整合性、完成度、明確性)、各チェック結果、改善提案(クリティカル/重要/推奨)、承認判定を含む形式。

## 重要な注意事項

**レビュー結果の提示**:
- 「Approved(承認推奨)」「Rejected(却下推奨)」等の判定を提示

### 出力フォーマットの厳守
**構造化マークダウン形式は必須**

**必須要素**:
- `[METADATA]``[VERDICT]`/`[ANALYSIS]``[ISSUES]`セクション
- 各ISSUEにID、severity、category
- セクションマーカーは大文字、正しく閉じる
- SUGGESTIONは具体的・実行可能に

実際に使ってみよう!

sub-agents-mcprun_agentツールを提供しています。
そのため、以下のように指示をすることでサブエージェントを呼び出すことができます。

run_agentツールを使ってdocument-reviewerエージェントにdocs/PRD/xxxx.mdのレビューを依頼して

毎回「run_agentツールを使って〜」と書くのは面倒なので、.cursor/rulesであったりAGENT.mdCLAUDE.mdに「サブエージェントを呼び出す時はrun_agentツールを必ず使うこと」といったルールを書いておくとより的確にツールを使ってくれるはずです。

以下のように動作し、結果を返してくれます。

実際のやり取り

注意点

Cursor CLIを実際に利用してみましたが、処理内容によっては応答時間が長くなり、タイムアウトしてしまうことが分かっています。 デフォルトタイムアウトは5分で設定しているので、複雑な処理をさせたい場合はMCP設定のenvに以下を追加してタイムアウトを延長してください。

  "EXECUTION_TIMEOUT_MS": "600000"  # 10分に延長(設定上限値です)

例えば上述しているdocument-reviewer.mdのサンプルを約14,000文字の文書に対して実行してもらった場合、Cursor CLIでは応答に10分以上時間がかかる場合がありました。
もし動作確認だけサクッと行いたい場合は、処理対象のファイルを小さくするか、サブエージェント定義(実行させたいこと)を簡略化してお試しください。

技術的な補足

1. MCP

Model Context Protocol (MCP) は、ホストアプリケーション(CursorやClaude Desktopなど)がサーバー(データソースやツール)と通信するための標準化されたプロトコルです。

export class McpServer {
  private setupHandlers(): void {
    // run_agentツールの実装
    this.server.setRequestHandler(
      CallToolRequestSchema,
      async (request): Promise<CallToolResult> => {
        if (request.params.name === 'run_agent') {
          const result = await this.runAgentTool.execute(request.params.arguments)
          return result as CallToolResult
        }
        throw new ValidationError(`Unknown tool: ${request.params.name}`)
      }
    )
    
    // リソース公開(エージェント定義をMCPリソースとして公開)
    this.server.setRequestHandler(
      ListResourcesRequestSchema,
      async (): Promise<ListResourcesResult> => {
        const resources = await this.agentResources.listResources()
        return { resources }
      }
    )
  }
}

MCPのメリット

  1. 標準化: 各種AIツールとの容易な統合
  2. 型安全性: TypeScript SDKによる型サポート
  3. 拡張性: ツールとリソースの両方を提供できる

2. Agentic Coding

sub-agents-mcpの実装では、サブエージェントを活用してLLMが書くコードの保守性をある程度担保できるよう工夫しました。

  1. 適応的なルール選択: タスク開始時(つまりTodoWriteを使ってタスク計画を立てる時)にrule-advisorサブエージェントがタスクを分析し、必要最小限のルールセットを自動選択
  2. 段階的な品質保証: quality-fixerサブエージェントが型チェックやテストを自動実行し、エラーを自己完結で修正
  3. 実装前の承認: コード編集前にユーザー承認を要求し、意図しない変更を防止(1の仕組みを組み込むことで、TodoWriteを変更させるので、作業中の暴走を抑止できる)

LLMによる調査・分析の後、実際のコード変更に入る前に計画を提示してもらい、人間(私)が承認する仕組みにしています。
また、メタ認知の考えを利用し、タスクの目的を理解し必要なルール(コンテキスト)をもとに計画を立てて進めるため、場当たり的な修正ではなく計画的な実装が行われる可能性を高めています。

※ 作り終わってから気づいたのですが、TypeScriptのベストプラクティスがコンテキストに不足していたことがわかったので、今後何か機能追加を行うタイミングでリファクタリングをする予定です。

3. run_agentツールの詳細仕様

run_agentツールは以下のパラメータを受け取ります

  • agent: 実行するエージェント名(必須)
  • prompt: エージェントへの指示内容(必須)
  • cwd: 作業ディレクトリ(optional)
  • extra_args: 追加のコマンドライン引数(optional)

sub-agents-mcpは、エージェント定義ファイルの内容全体をシステムコンテキストという位置付けでCursor CLIやClaude Codeに渡します。これにより、サブエージェントが独立したコンテキストで、定義に従いユーザープロンプトを処理します。

その他仕様

  • エージェント名は英数字、アンダースコア、ハイフンのみ使用可能
  • プロンプトは最大50,000文字まで
  • 存在しないエージェントを指定すると動作せず、利用可能なエージェント一覧が表示される

学んだこと・今後の展望

正直、当初はただCLIツールにプロンプトを投げて応答を受け取って返却するだけだと考えていたのですが、ストリーミングでのやり取りが必要だったり、当たり前ですがレスポンスデータの形式がLLMごとに違うので差異の吸収やどこまで対応するかの検討が必要でした。
ただ、Agentic Codingのための環境整備は趣味でやっていたため、想定より時間がかかったり中盤から手直しがそれなりに発生したものの、比較的短期間で作り切ることができました。
自分が使いたいものをサクッと作れるというのは良いことですね。

今回の開発を通じて、AIツールをより効果的に活用するには、適切なコンテキスト管理とタスク分解が重要だと改めて実感しました。

さいごに

私は、サブエージェントを積極的に活用することで自分がやろうとしている作業のタスク分解が進み、必要な言語化(コンテキストの整備)も進むので、Agentic Codingをする際にはぜひ利用してみてほしいと考えています。
コンテキストウィンドウの枯渇への対処にもなるので、精度向上にも寄与するはずです。