oxml-mcp について
oxml-mcpは、XMLを検索・処理するAgent向けのRust製MCPサーバーです。XPathで正確に値を抽出し、ファイルシステムやネットワークにはアクセスしません。
主な機能
- 01XPath 1.0によるXML検索
- 02構造と整形式の検査
- 03XSDスキーマによる検証
- 04XMLの整形と圧縮
- 05stdio、HTTP、SSEトランスポート
活用シーン
- 01大きなXMLからノードを抽出
- 02XMLの構造と整形式を確認
- 03XML Schema違反の特定
MCP 対応
クエリ、検査、検証、整形、構造確認の5種類のXMLツールをMCPクライアントに公開します。stdio、Streamable HTTP、SSEに対応します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
docker run -i --rm ghcr.io/sebastienrousseau/oxml-mcp:0.0.11ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ghcr.io/sebastienrousseau/oxml-mcp:0.0.11stdioツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
oxml-mcp
モデルがXMLを読み取るのではなく、XMLに対してクエリを実行できるModel Context Protocolサーバーです。
oxmlを利用し、unsafeコードは一切ありません。
目次
はじめに
- モデルがこれを必要とする理由 — XMLツールがLLMのために解決する問題
- インストール — Cargo、ソースからのビルド
- トランスポート — stdio、ストリーム可能なHTTP、SSE
- クイックスタート — クライアント不要の3行
- 設定 — Claude Desktopおよび任意のMCPクライアント
oxmlエコシステム
- oxmlエコシステム — 7つのクレート、1つのバージョン
リファレンス
- ツール —
xml_query、xml_validate、xml_check、xml_inspect、xml_format - プロトコル — MCP
2025-11-25および2026-07-28、2種類の失敗 - エラー — 2種類のエラーとその違い
- 設計 — ツールが5つある理由と、ドキュメントを文字列にする理由
- 0.0.11の機能 — リリース内容
- エコシステム比較 — 代替手段との比較
- ベンチマーク — ペアで測定したリクエストごとのレイテンシー
実践
モデルがこれを必要とする理由
クライアントはXMLをツールの引数として直接渡し、選択した結果だけをモデルのプロンプトに含めることができます。count(//record)は、貼り付けられた断片から推測するのではなく、パーサーが計算した件数を返します。
サーバーが受け付けるXML文字列の上限は厳密に8 MiBです。パスを開いたり、URLを取得したりすることはありません。ツールの引数全体をモデル自身が構築する場合でも、XMLテキストが必要です。HTTPトランスポートには、これより厳しい独自のSDKリクエストボディ上限があります。
もう1つの理由は算術処理です。モデルに見えているドキュメント内の要素数を数えるよう依頼すると、概算になります。count(//record)を使うxml_queryなら、そうはなりません。
インストール
cargo install oxml-mcp --version 0.0.11 --locked
Rustツールチェーンがなくても、同じバイナリをGHCRのイメージとして利用できます(MCPレジストリのエントリからそのイメージにアクセスできます)。
docker run --rm -i ghcr.io/sebastienrousseau/oxml-mcp:0.0.11
トランスポート
1つのバイナリで、3通りの接続方法があります。スイート内のすべてのサーバーで同じフラグを使用します。
| コマンド | トランスポート | エンドポイント | プロトコルのリビジョン |
|---|---|---|---|
oxml-mcp | stdio | stdin および stdout | 2024-11-05 から 2026-07-28 |
oxml-mcp --transport streamable-http --host 127.0.0.1 --port 8000 | Streamable HTTP | http://127.0.0.1:8000/mcp | 2025-11-25 および 2026-07-28 |
oxml-mcp --transport sse --port 8001 | HTTP+SSE(レガシー) | http://127.0.0.1:8001/sse、/messages/ | 2024-11-05 |
Streamable HTTP は1つのエンドポイントで、現在の両方のリビジョンに対応します。initialize を送信するクライアントにはセッションと Mcp-Session-Id が割り当てられます。各リクエストの _meta で 2026-07-28 を指定するクライアントには、ハンドシェイクの代わりに server/discover を使用してステートレスに応答します。レスポンスはサーバー送信イベントとしてストリーミングされ、GET /mcp でサーバーからクライアントへのストリームが開きます。SSE トランスポートは旧式で、引き続き endpoint イベントとメッセージ URL を想定するホスト向けです。
HTTP トランスポートは、--host で別のアドレスを指定しない限りループバックインターフェイスにバインドされ、認証は行いません。ルーティング可能なアドレスにバインドする前に、信頼できるゲートウェイの背後にサーバーを配置してください。--version と --help は、それぞれの名前どおりに動作します。
クイックスタート
サーバーは stdio 経由で JSON-RPC 2.0 を使用します。動作を確認するには、ハンドシェイクと呼び出しの3行だけで十分です。クライアントも必要ありません。
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"me","version":"0"}}}' \
'{"jsonrpc":"2.0","method":"notifications/initialized"}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"xml_query","arguments":{"xml":"<library><book><title>Dune</title></book></library>","xpath":"//title"}}}' \
| oxml-mcp | tail -n 1
{"jsonrpc":"2.0","id":2,"result":{"resultType":"complete","content":[{"type":"text","text":"Dune"}],"structuredContent":{"count":1,"values":["Dune"]},"isError":false}}
日常的に使う場合は、クライアントに実行を任せると便利です。設定を参照してください。
設定
MCP クライアントのサーバー一覧に追加してください。Claude Desktop の場合は、claude_desktop_config.json に記述します。
{
"mcpServers": {
"oxml": {
"command": "oxml-mcp"
}
}
}
Claude Code の場合:
claude mcp add oxml -- oxml-mcp
引数を指定しない場合、サーバーは stdin と stdout 経由で JSON-RPC 2.0 を使用し、1行につき1つのメッセージを送信します。これは、これらのクライアントが想定する形式です。代わりに HTTP 経由で接続するクライアントは、--transport streamable-http を指定して起動したサーバーを指定します。トランスポートを参照してください。設定ファイルはありません。
oxml エコシステム
| クレート | 概要 |
|---|---|
oxml | ライブラリ:パーサー、ツリー、XPath 1.0 |
xmlschema | XSD 検証 |
oxml-cli | コマンドライン |
oxml-wasm | WebAssembly バインディング |
oxml-mcp | このクレート — MCP サーバー |
oxml-lsp | Language Server Protocol サーバー |
oxml-json | 言語サーバー向けの JSON サポート |
7つすべてで、0.0.1刻みの同じバージョン番号を使用しています。
ツール
xml_query
XPath 1.0 式を評価し、一致する値を返します。
| 引数 | 型 | |
|---|---|---|
xml | string | ドキュメント |
xpath | string | XPath 1.0 式 |
namespaces | object | 任意。式で使用するプレフィックスと URI の対応付け |
{"name":"xml_query","arguments":{"xml":"<r><t>Dune</t><t>Germinal</t></r>","xpath":"//t"}}
Dune
Germinal
値は1行につき1つです。数値、文字列、またはブール値を返す式は、その値を直接返します。そのため、count(//t) は 2 を返します。すべてのツールは、公開する outputSchema に沿って、回答を structuredContent としても返します。この場合は {"count": 2, "values": ["Dune", "Germinal"]} です。
xml_inspect
ドキュメントの構造を要約します。ルート要素、最大の深さ、各要素名とその出現回数、および使用されている名前空間を示します。
{"name":"xml_inspect","arguments":{"xml":"<r><t>x</t></r>"}}
Root element: r
Maximum depth: 3
Elements:
r: 1
t: 1
最初にこれを呼び出してください。 要素名がわかっていれば、モデルは動作するクエリを作成できます。要素名を推測すると、要素名が record のドキュメントに対して //item を実行することになります。
xml_check
ドキュメントが整形式かどうかを報告します。整形式でない場合は、行と列も示します。
{"name":"xml_check","arguments":{"xml":"<a/>"}}
The document is well-formed (2 nodes).
xml_validate
XML Schema に対して検証し、違反ごとに該当する要素へのパスを返します。
| 引数 | 型 | |
|---|---|---|
xml | string | ドキュメント |
xsd | string | スキーマ |
xml_format
インデント(スペース)と空要素のスタイルを指定して XML ドキュメントを整形するか、最小化します。
{"name":"xml_format","arguments":{"xml":"<root><item/></root>","indent":2}}
| 引数 | 型 | デフォルト | |
|---|---|---|---|
xml | string | (必須) | ドキュメント |
indent | integer | 0 | インデントレベルごとのスペース数(最小化する場合は 0) |
empty_elements | string | "self-closing" | "self-closing"(<a/>)、"spaced"(<a />)、または "expanded"(<a></a>) |
プロトコル
公式 Rust SDK の rmcp で実装された、JSON-RPC 2.0 による MCP です。現在は 2 つのリビジョンがあり、どちらも提供されています。initialize ハンドシェイクを行う 2025-11-25 と、ハンドシェイクを行わない 2026-07-28 です。各リクエストでは _meta にリビジョンを指定し、server/discover がサーバーの情報を記述します。クライアントから要求された場合は、2024-11-05 までの古いリビジョンも受け付けます。
| メソッド | |
|---|---|
initialize | 機能、サーバー情報、ネゴシエーションされたリビジョン |
server/discover | ステートレスリビジョン向けの同じ情報 |
tools/list | 5 つのツール:入力スキーマ、出力スキーマ、アノテーション |
tools/call | ツールを 1 つ実行 |
ping | 応答 |
すべてのツールには読み取り専用、冪等、閉世界のアノテーションが付いているため、クライアントは確認を求めずに呼び出せます。
MCP は 2 種類の失敗を区別しているため、これらを分けて扱います。モデルが目にするのは、そのうちの一方だけです。
ツールが実行されたものの、処理を完了できなかった場合 — 不正なドキュメントや無効な式など — は、isError: true を含む 成功 の JSON-RPC レスポンスになります。モデルはテキストを見て修正できます。
プロトコルが拒否するリクエスト — 不正な JSON、未知のメソッド、id はあるものの method がないリクエストなど — は、標準コードを含む JSON-RPC エラー、または HTTP の場合は HTTP ステータスになります。何も実行されず、モデルではなくクライアントが処理します。
| 状況 | 応答 |
|---|---|
| 不正なドキュメント | result、isError: true |
| 無効な XPath 式 | result、isError: true |
| スキーマ違反 | result、isError: true、違反内容は structuredContent に格納 |
| 引数の欠落または型の誤り | result、isError: true、該当するフィールドを明示 |
| 未知のツール | result、isError: true、存在する 5 つのツールを明示 |
| 未知のメソッド | error、-32601 |
method のない id | error |
| 不正な JSON | HTTP では HTTP 415、stdio ではスキップされ、セッションは継続 |
エラー
不正なドキュメントが原因でクラッシュしたり、プロトコルエラーになったりすることはありません。
{"name":"xml_check","arguments":{"xml":"<a>"}}
{"content":[{"text":"…not well-formed…","type":"text"}],"isError":true}
モデルはこのテキストを読んで、ドキュメントを修正するか、ユーザーに伝えることができます。
設計
ツールは 14 個ではなく 5 個です。 すべてのリクエストで、各ツールの説明がモデルのコンテキストに含まれます。用途の狭いツールを 20 個備えたサーバーでは、ドキュメントよりもサーバー自体の説明に多くのコンテキストを費やします。
ドキュメントはパスではなく文字列で渡します。 サーバーがファイルを開くことはありません。モデルが何を読み取れるかはクライアントが決定します。それを決めるのはクライアントの役割です。パスを受け取るサーバーでは、マシン上のあらゆるファイルを読み取れてしまいます。
独自実装ではなく、単一のプロトコル実装を使います。 JSON-RPC 層と MCP 層には公式 SDK を使用しています。3 つのプロトコルリビジョンと 3 つのトランスポートに対応するのはプロトコル自体のプロジェクトであり、手書き実装の正確性をそれらに照らして保つことは、XML サーバーの価値の中心ではありません。このクレート独自の価値は、5 つの関数とモデルが読むテキストにあります。
0.0.11 の機能
- 5 つのツール:query、inspect、check、validate、format
- XPath 1.0:10 個の軸、25 個の関数、4 種類すべての値型
- XSD 検証
- XML の整形と最小化(
xml_format) - stdio による JSON-RPC 2.0、MCP
2024-11-05、2025-11-25、2026-07-28 - ストリーム可能な HTTP と SSE によるストリーミング JSON-RPC 応答
- JSON 入力のエスケープされたサロゲートペアに対応しているため、Python クライアントから絵文字を含むドキュメントを扱えます
- ファイルシステムへのアクセスなし、ネットワークへのアクセスなし
未対応: リソース、プロンプト、パスまたは URI によるドキュメント指定。
エコシステムの比較
以下は競合するサーバーではなく、XML をモデルに渡す方法です。
| 方法 | ドキュメントのサイズ | 精度 | ネットワークに接続するか |
|---|---|---|---|
oxml-mcp | ツール呼び出しで制限され、コンテキストウィンドウには依存しません | 正確な回答を得られる XPath 式 | 決して接続しません |
| コンテキストに貼り付ける | 収まる必要があり、ターンごとにトークンを消費します | モデルが目視でパターンを照合します | いいえ |
| ファイルシステムまたはシェルサーバー | 無制限 | grep で得られる結果次第です | サーバーによります |
| 汎用 HTTP フェッチサーバー | 無制限 | なし | はい。設計上、接続します |
最後の行は、立ち止まって考える価値があります。ドキュメントの取得を依頼されたサーバーは、そのドキュメントによって内部ネットワークに向けられる可能性があります。ここにあるツールにはソケットを開くコードがありません。リスナーは --transport で起動するものだけで、応答を返すことしかありません。
ベンチマーク
cargo bench --bench protocol
MCP クライアントはリクエストを 1 つ送信して応答を待つため、リクエストあたりのレイテンシーを示しています。JSON-RPC 層によって、200 KB のペイロードでは生の解析に比べておよそ 10~25%増加し、小さなペイロードでは数マイクロ秒増加します。比較をペアで測定する必要がある理由も説明している doc/BENCHMARKS.md を参照してください。
例
examples/ は実際のバイナリを stdio 経由で実行して応答を検証するため、この README に記載された呼び出しが成立しなくなると CI が失敗します。
| 例 | 説明 |
|---|---|
session.sh | 初期化、一覧表示、各ツールの呼び出しを含む一連のセッション |
errors.sh | 不正なドキュメント、無効な式、プロトコルエラー |
oxml-mcp を使わない場合
- ドキュメントがコンテキストに収まる場合。 貼り付けてください。ツールを介する往復は遅く、利点もありません。
- XML の構造を編集する必要がある場合。
xml_formatはドキュメントをシリアライズして整形しますが、データの挿入、削除、変更は行いません。 - XSLT または XPath 2.0 が必要な場合。 どちらも利用できません。
- ドキュメントがメモリより大きい場合。 全体を解析します。
- サーバーにドキュメントを取得させたい場合。 その機能は今後も追加されません。それがこの設計の要点です。
よくある質問
モデルはなぜ毎回ドキュメント全体を渡す必要があるのですか?
サーバーは呼び出し間で状態を保持しないためです。これにより、複数のクライアントが 1 つのバイナリを共有しても正しく動作し、セッション間で無効化が必要なキャッシュや情報漏えいの可能性があるキャッシュも存在しません。
大きなドキュメントでは、実際に無駄が生じます。将来のリリースでハンドルベースのフローが追加される可能性はあります。それまでは、xml_inspect を一度実行してから、探索的なクエリを何度も行うより、正確な xml_query を実行するほうが効果的です。
ディスク上のファイルを読み込めますか?
いいえ。また、今後も読み込めるようにはなりません。サーバーが受け取るのはドキュメントの内容です。パスを受け取るサーバーでは、それにアクセスできるすべてのモデルが、サーバープロセスからアクセス可能な任意のファイルを読み取れてしまいます。その判断はクライアント側で行うべきです。
信頼できない XML を渡しても安全ですか?
はい。外部エンティティは参照されないため、<!ENTITY xxe SYSTEM "file:///etc/passwd"> を含むドキュメントによってサーバーがそのファイルを読み取ることはありません。エンティティ展開とネストの深さにも上限があります。
ツールが 5 つしかないのはなぜですか?
すべてのリクエストで各ツールの説明がコンテキストを占有します。幅広い機能を持つ 5 つのツールは、細分化された 20 のツールよりコストが少なく、同じ範囲をカバーできます。XPath 自体がすでにクエリ言語だからです。
Claude 以外のクライアントでも使えますか?
クライアント固有の動作はなく、stdio と両方の HTTP トランスポートで MCP を実装しているため、準拠しているクライアントであれば動作するはずです。Python SDK のクライアントを使って両方の HTTP トランスポートで検証されており、独立した MCP 監査ツールでは、現在の両方のプロトコル世代で 100 点満点を獲得しています。
ドキュメントに絵文字が含まれていると呼び出しに失敗します。
これはバグでしたが、0.0.3 で修正されました。Python の json.dumps は既定で ASCII 以外の文字をエスケープするため、絵文字はサロゲートペア(😀)として届きますが、JSON パーサーがエスケープされたサロゲートペアを拒否していました。絵文字を送信する Python クライアントは、すべてこの問題に遭遇していました。
名前空間を使ってドキュメントをクエリするにはどうすればよいですか?
クエリと一緒に渡します。
{"name":"xml_query","arguments":{
"xml":"…","xpath":"//m:item","namespaces":{"m":"urn:example"}}}
プレフィックスはドキュメントではなく、これらのバインディングに対して解決されます。そのため、プレフィックスの表記が異なるドキュメント間でも同じ式が使えます。一致する必要があるのは URI だけです。バインドされていないプレフィックスは、渡す引数の名前を示し、xml_inspect を案内するエラーになります。
xml_inspect はドキュメントで使われている名前空間を報告するため、この引数が利用可能になります。モデルは、確認できない URI をバインドできません。
Namespaces (pass these to xml_query as `namespaces`):
urn:example: 12 element(s)
プレフィックスのない名前テストは、名前空間に属さないノードにのみ一致します。これは XPath 1.0 の仕様どおりです。namespace-uri() は引き続き動作し、バインディングは不要です。
モデルが無効な JSON を送信するとどうなりますか?
SDK は、不正な形式の HTTP JSON をステータス 415 で拒否します。stdio では、不正な行を返信せずにスキップし、次の行の処理を続けます。プロトコルを参照してください。
不明なツールが JSON-RPC エラーではなく isError になるのはなぜですか?
0.0.8 までは -32602 でした。ステートレス HTTP の改訂では、SDK はこのコードを HTTP 400 として送信します。クライアントはこれをトランスポート障害として報告し、モデルはその内容を読み取れません。ツール名を誤記したモデルには、存在する 5 つのツールを名前で示すテキストを返すほうが有用です。プロトコルを参照してください。
開発
./scripts/gate.sh
このコマンドは、CI で実行されるすべての処理を、最も早く失敗する順に実行します。フォーマット、clippy、テスト、rustdoc、#![forbid(unsafe_code)] のチェック、サンプル、カバレッジの下限 95%、そして MSRV ビルドです。rust-toolchain.toml を信頼せず、ツールチェーンを固定しています。環境内の RUSTUP_TOOLCHAIN はこのファイルをひそかに上書きするため、あるリリースには存在し、別のリリースには存在しない lint によって、ローカルでは成功し CI では失敗する事態が起こり得るからです。
個別の手順を一つずつ実行する場合は、次のとおりです。
cargo test --all-features
cargo clippy --all-targets --all-features -- -D warnings
cargo fmt --all --check
cargo bench --bench protocol
OXML_MCP="$PWD/target/release/oxml-mcp" ./examples/run-all.sh
CI では Linux、macOS、Windows で同じセットを実行します。
セキュリティ
Scorecard のスキャンでは、ダイジェストで固定されたアップストリームイメージを使用します。結果は CI アーティファクトおよび GitHub コードスキャンのリポジトリ態勢に関する検出結果として保持され、Scorecard の公開サービスには公開されません。バッジが示すのはワークフローのステータスであり、セキュリティスコアではありません。スキャンが成功しても、検出結果が報告されることがあります。
ツールがファイルやソケットを開くことはありません。外部エンティティが参照先を解決されることもありません。ツールでの XML 解析には Limits::strict() を使用し、スキーマのソースサイズには 8 MiB の上限を設けています。XPath のコンパイルと呼び出しごとの評価には、明示的な予算を設定しています。SDK とデプロイ環境では、トランスポートのペイロード、同時リクエスト、セッションにそれぞれ上限を設定する必要があります。#![forbid(unsafe_code)]。HTTP リスナーはコマンドラインで要求された場合にのみ作成され、デフォルトではループバックにバインドされ、認証は行いません。トランスポートを参照してください。
脅威モデルでは、ドキュメントとそれを囲む JSON の両方が悪意あるものとして扱われます。ドキュメントは、モデルがインターネット上の何かを調べるよう求められたため、JSON はプログラムへの入力そのものであるためです。詳しくは https://github.com/sebastienrousseau/oxml/blob/main/doc/SECURITY-MODEL.mdを参照してください。
ドキュメント
- API ドキュメント
- BENCHMARKS.md
- PROTOCOL.md
- アーキテクチャ決定記録
- TOOL-DESIGN.md
- SECURITY-MODEL.md
- TESTING.md
- CHANGELOG.md
- CONTRIBUTING.md
- SECURITY.md
謝辞
oxml-mcp は、これまでの取り組みがあったからこそ存在しています。
- Anthropic — このサーバーが実装する Model Context Protocol の仕様を提供してくださったことに感謝します。
- lxml と libxml2 — XML ツールキットに求められる機能の指針と、何十年にもわたって積み重ねられた確かな品質に感謝します。
- W3C —
xml_queryが準拠する XPath 1.0 仕様を提供してくださったことに感謝します。
ライセンス
Apache License, Version 2.0 または MIT License のいずれかを、選択に応じて適用するデュアルライセンスです。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。