AIエージェント入門

Claude Code MCP結果永続化|500K実装ガイド

Claude Code MCP結果永続化|500K実装ガイド

この記事の結論

Claude Code v2.1.91で追加されたMCPツール結果の永続化機能。_meta[anthropic/maxResultSizeChars]を使い、DBスキーマ等を切り詰めなしで渡すコード例を解説。

MCP(Model Context Protocol)のツール結果が途中で切れてしまう問題に悩んでいたら、2026年4月にリリースされたClaude Code v2.1.91で解決策が提供された。

これまでMCPツールが返す大きなデータ(DBスキーマ、大量のファイルインデックス、詳細なAPI仕様書など)は、デフォルトの文字数制限で無言のうちに切り詰められていた。開発者が「なぜClaude Codeがスキーマの後半を知らないのか」と首をかしげる場面が多かった。

この記事では、_meta["anthropic/maxResultSizeChars"]アノテーションを使ったMCPツール結果の永続化設定を、コピペ可能なコード例とともに解説する。

まず試したい「5分で設定できる」永続化の基本コード

既存のMCPサーバーに永続化アノテーションを追加する

既存のMCPツールにアノテーションを1行追加するだけで有効になる。以下はPythonのFastMCPを使った例だ。


# 動作環境: Python 3.11+, mcp>=1.0.0, fastmcp>=0.3.0
# 注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("database-schema-server")

@mcp.tool()
async def get_full_schema(database_name: str) -> dict:
    """
    データベースの完全なスキーマを返す。
    _meta アノテーションで500K文字まで切り詰めなしで返せる。
    """
    schema = await fetch_database_schema(database_name)

    # ここがポイント: _meta に maxResultSizeChars を設定
    return {
        "_meta": {
            "anthropic/maxResultSizeChars": 500000  # 最大500K文字
        },
        "schema": schema,
        "table_count": len(schema["tables"]),
        "database": database_name
    }

ポイント:

  • _metaはレスポンスオブジェクトのトップレベルに置く
  • 値は最大500000(500K文字)。これを超えた値を指定してもエラーにはならず500Kに丸められる
  • 実際のデータ量に応じた値を設定するのが望ましい。常に500K最大にするとコンテキストウィンドウを不必要に消費する

Node.js(TypeScript)での実装例

TypeScriptで書かれたMCPサーバーでの設定方法。


// 動作環境: Node.js 20+, @modelcontextprotocol/sdk>=1.0.0
// 注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";

const server = new McpServer({
  name: "large-result-server",
  version: "1.0.0",
});

server.tool(
  "get_codebase_index",
  "プロジェクト全体のファイルインデックスを返す",
  {
    project_path: z.string().describe("プロジェクトのルートパス"),
  },
  async ({ project_path }) => {
    const index = await buildCodebaseIndex(project_path);
    const indexJson = JSON.stringify(index, null, 2);

    return {
      content: [
        {
          type: "text",
          text: indexJson,
        },
      ],
      // _meta アノテーションでサイズ上限を上書き
      _meta: {
        "anthropic/maxResultSizeChars": 300000,  // 実態に合わせた値を設定
      },
    };
  }
);

v2.1.91の全体像 — MCPリザルト永続化だけじゃない

v2.1.91は2026年4月上旬にリリースされた。Claude CodeはこのわずかなperiodでなんとV2.1.90、v2.1.91、v2.1.92と3バージョンを連続リリースしている。それだけ機能追加のペースが速い。

機能 内容 対象ユーザー
MCP結果永続化(500K) _meta[anthropic/maxResultSizeChars]で切り詰め上限を上書き MCPサーバー開発者
disableSkillShellExecution スキルのシェル実行を無効化する設定 セキュリティ要件の高いチーム
プラグインexecutable bin/ディレクトリ経由でプラグインの実行ファイルを提供可能に プラグイン開発者
ディープリンクのマルチライン対応 ディープリンク内のプロンプトで複数行テキストが使えるように CI/CDとの連携ユーザー
Editツールの最適化 出力トークンを削減(コスト改善) 全ユーザー

どんなユースケースで使うべきか

ユースケース1: 大規模DBスキーマの一括参照

マイクロサービスのデータベースは50〜200テーブルになることも珍しくない。従来のMCPだとスキーマが途中で切れ、Claude Codeが「このテーブルは存在しない」という誤った判断をする場面があった。


# PostgreSQLスキーマを全件取得してClaude Codeに渡すMCPツール
# 動作環境: Python 3.11+, asyncpg>=0.29.0, mcp>=1.0.0

import asyncpg
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("postgres-schema")

@mcp.tool()
async def get_postgres_schema(connection_string: str) -> dict:
    """PostgreSQLの全テーブル・カラム・インデックス情報を返す"""
    conn = await asyncpg.connect(connection_string)
    try:
        # テーブル一覧
        tables = await conn.fetch("""
            SELECT table_name, table_schema
            FROM information_schema.tables
            WHERE table_schema NOT IN ('pg_catalog', 'information_schema')
        """)

        # カラム詳細
        columns = await conn.fetch("""
            SELECT table_name, column_name, data_type, is_nullable
            FROM information_schema.columns
            WHERE table_schema NOT IN ('pg_catalog', 'information_schema')
            ORDER BY table_name, ordinal_position
        """)

        schema_data = {
            "tables": [dict(t) for t in tables],
            "columns": [dict(c) for c in columns],
        }

        return {
            "_meta": {"anthropic/maxResultSizeChars": 500000},
            "schema": schema_data,
            "summary": f"{len(tables)}テーブル、{len(columns)}カラム"
        }
    finally:
        await conn.close()

ユースケース2: プロジェクト全体のファイルインデックス

大型モノレポでは数千ファイルのインデックスをClaude Codeに渡す必要がある場合がある。500K文字あれば数千ファイルのパス一覧+簡易サマリーを含められる。

【要注意】よくあるミスと対策

ミス1: maxResultSizeCHarsを常に最大値にする

❌ すべてのツールに"anthropic/maxResultSizeChars": 500000を設定する

⭕ 実際のデータ量に合わせた値を設定する(スキーマが通常100Kなら150000程度)

理由: コンテキストウィンドウは有限。不必要に大きな結果を渡すと、後続の処理で使えるトークン数が減り、出力品質が低下する。

ミス2: _metaをネストした場所に置く

❌ ツール結果のネストされたオブジェクト内に_metaを配置する

⭕ レスポンスオブジェクトのトップレベル_metaを置く

理由: MCPプロトコルは_metaをトップレベルでのみ認識する。ネストした場合は無視されてデフォルト制限が適用される。

ミス3: v2.1.91以前のClaude Codeで使おうとする

❌ Claude Code v2.1.90以下でanthropic/maxResultSizeCharsを指定する

⭕ まずClaude Codeを最新版にアップデートしてから使用する

確認方法: claude --versionでバージョン確認。v2.1.91以上が必要。

ミス4: 既存の切り詰め問題を「モデルの限界」と誤認する

❌ 「Claudeはこのスキーマを理解できない」と諦める

⭕ MCPツールの_meta設定を見直す

理由: 多くの場合、問題はモデルの能力ではなく、ツール結果がデフォルト制限で切り詰められていることにある。

コンテキスト最適化の戦略

正直に言うと、500Kを使えばすべて解決するわけではない。コンテキストウィンドウには上限があり、大きなツール結果を複数渡すとすぐに圧迫される。

現実的なアプローチ:

  • まず必要最小限のデータをMCPで渡し、Claude Codeに「何が追加で必要か」を判断させる
  • 詳細情報は別ツールとして分割し、オンデマンドで取得させる
  • maxResultSizeCHarsは「デフォルト制限が足りない場合の拡張手段」として使い、常用しない

MCPサーバーの最適化全般については、Python FastMCPでMCPサーバーを構築するガイドも参照してほしい。

参考・出典

まとめ: 今日から始める3つのアクション

  1. 今日やること: claude --versionでv2.1.91以上を確認し、大きな結果を返すMCPツールに_meta["anthropic/maxResultSizeChars"]を追加する
  2. 今週中: 既存のMCPサーバーで「なぜかClaudeが情報を知らない」場面を洗い出し、切り詰め問題が原因でないか確認する
  3. 今月中: ツールごとに適切なmaxResultSizeCHars値を設定し、コンテキスト消費を最適化する

あわせて読みたい:

著者: 佐藤傑(さとう・すぐる)
株式会社Uravation代表取締役。X(@SuguruKun_ai)フォロワー10万人超。
100社以上の企業向けAI研修・導入支援。著書累計3万部突破。
SoftBank IT連載7回執筆(NewsPicks最大1,125ピックス)。

ご質問・ご相談は お問い合わせフォーム からお気軽にどうぞ。

Need help moving from reading to rollout?

この記事を読んで導入イメージが固まってきた方へ

Uravationでは、AIエージェントの要件整理、PoC設計、社内導入、研修まで一気通貫で支援しています。

この記事をシェア

X Facebook LINE

※ 本記事の情報は2026年4月時点のものです。サービスの料金・仕様は変更される可能性があります。最新情報は各サービスの公式サイトをご確認ください。

関連記事