mcpField
O
oxml-mcp

oxml-mcp

本地服务
github.com/sebastienrousseau开发工具03 天前更新

关于 oxml-mcp

oxml-mcp 是基于 Rust 的 MCP 服务,为 Agent 提供 XML 查询与处理工具。它通过 XPath 精确提取结果,并且不访问文件系统或网络。

主要功能

  1. 01XPath 1.0 查询 XML
  2. 02检查文档结构与格式良好性
  3. 03按 XSD 验证并报告错误
  4. 04格式化或压缩 XML
  5. 05支持 stdio、HTTP 与 SSE 传输

适用场景

  1. 01从大型 XML 中筛选指定节点
  2. 02确认 XML 文档结构与有效性
  3. 03按 XML Schema 查找不符合项

MCP 相关

它通过 MCP 向客户端提供五种 XML 工具:查询、检查、验证、格式化和结构检查。支持 stdio、Streamable HTTP 与 SSE。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"sebastienrousseau-oxml": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"ghcr.io/sebastienrousseau/oxml-mcp:0.0.11"
]
}
}
}
启动命令docker run -i --rm ghcr.io/sebastienrousseau/oxml-mcp:0.0.11

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
ocighcr.io/sebastienrousseau/oxml-mcp:0.0.11

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

oxml-mcp

一个模型上下文协议服务,让模型能够查询 XML,而不是阅读 XML——由 oxml 提供支持,不含任何 unsafe 代码。

构建 Crates.io Docs.rs Scorecard 扫描工作流状态 OpenSSF 最佳实践 Glama MCP 服务评分

oxml-mcp 演示


目录

开始使用

oxml 生态系统

参考

  • 工具 — xml_query、xml_validate、xml_check、xml_inspect、xml_format
  • 协议 — MCP 2025-11-25 和 2026-07-28,以及两种失败类型
  • 错误 — 两种错误,以及如何区分
  • 设计 — 为何有五种工具,以及为何文档采用字符串
  • 0.0.11 中的功能 — 版本功能清单
  • 生态系统对比 — 与其他方案的比较
  • 基准测试 — 每次请求的延迟,成对测量

实用信息


模型为何需要它

客户端可以直接将 XML 作为工具参数提供,并仅将选定的结果放入模型提示词中。count(//record) 返回解析器计算出的计数,而非根据粘贴的片段估算的结果。

服务接受长度不超过严格 8 MiB 源码限制的 XML 字符串;它不会打开路径或获取 URL。若由模型自行构造完整的工具参数,仍然需要 XML 文本。HTTP 传输方式还有自身更严格的 SDK 请求正文限制。

另一个原因是算术。让模型对它能看到的文档中的元素计数,它会给出近似值。使用 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

传输方式

一个二进制文件,三种访问方式。套件中的每个服务都使用 相同的标志。

命令传输方式端点协议修订版本
oxml-mcpstdiostdin 和 stdout2024-11-05 至 2026-07-28
oxml-mcp --transport streamable-http --host 127.0.0.1 --port 8000Streamable HTTPhttp://127.0.0.1:8000/mcp2025-11-25 和 2026-07-28
oxml-mcp --transport sse --port 8001HTTP+SSE(旧版)http://127.0.0.1:8001/sse、/messages/2024-11-05

Streamable HTTP 在同一个端点上提供两个当前修订版本:发送 initialize 的客户端会获得一个会话和一个 Mcp-Session-Id; 在每个请求的 _meta 中指定 2026-07-28 的客户端则以无状态方式提供服务, 并使用 server/discover 代替握手。 响应以服务器发送事件的形式流式传输,GET /mcp 会打开 服务器到客户端的流。SSE 传输方式较旧,适用于仍然需要 endpoint 事件和消息 URL 的宿主。

除非通过 --host 指定其他地址,否则 HTTP 传输方式会绑定到环回接口, 且不进行身份验证。在绑定到可路由地址之前,请将服务置于 可信的网关之后。--version 和 --help 的功能顾名思义。

快速开始

该服务通过 stdio 使用 JSON-RPC 2.0,因此只需三行就能看到它运行—— 先握手,再调用——且无需客户端:

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,每行一条消息,这正是这些客户端的预期方式。 通过 HTTP 连接的客户端则应指向使用 --transport streamable-http 启动的服务——请参阅传输方式。这里没有 配置文件。

oxml 生态系统

Crate说明
oxml库:解析器、树、XPath 1.0
xmlschemaXSD 验证
oxml-cli命令行工具
oxml-wasmWebAssembly 绑定
oxml-mcp此 crate — MCP 服务
oxml-lspLanguage Server Protocol 服务
oxml-json语言服务的 JSON 支持

这七个项目使用同一个版本号,按 0.0.1 递增。

工具

xml_query

计算 XPath 1.0 表达式,并返回匹配的值。

参数类型
xmlstring文档
xpathstringXPath 1.0 表达式
namespacesobject可选。表达式的前缀到 URI 的绑定
{"name":"xml_query","arguments":{"xml":"<r><t>Dune</t><t>Germinal</t></r>","xpath":"//t"}}
Dune
Germinal

每行一个值。返回数字、字符串或布尔值的表达式会直接返回该值, 因此 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 验证文档,并返回每个违规项及其所涉及元素的路径。

参数类型
xmlstring文档
xsdstring架构
xml_format

使用可配置的缩进(空格)和空元素样式格式化 XML 文档,或将其压缩。

{"name":"xml_format","arguments":{"xml":"<root><item/></root>","indent":2}}
参数类型默认值
xmlstring(必填)文档
indentinteger0每级缩进的空格数(0 表示压缩)
empty_elementsstring"self-closing""self-closing"(<a/>)、"spaced"(<a />)或 "expanded"(<a></a>)

协议

MCP over JSON-RPC 2.0,由官方 Rust SDK rmcp 实现。目前有两个版本,均受支持:2025-11-25,带有 initialize 握手;以及 2026-07-28,无需握手——每个请求都会在 _meta 中指定其版本, 而 server/discover 会描述此服务。客户端请求时,也接受早至 2024-11-05 的旧版本。

方法
initialize能力、服务信息、协商后的版本
server/discover无状态版本对应的相同信息
tools/list五个工具:输入架构、输出架构、注解
tools/call调用一个工具
ping返回应答

每个工具都标注为只读、幂等且封闭世界,因此客户端可以直接调用,无需询问。

两种失败会分别处理,因为 MCP 会区分它们,而模型每次只会看到其中一种。

工具已运行,但无法完成任务——例如文档格式错误或表达式无效——会返回携带 isError: true 的成功 JSON-RPC 响应。模型会看到文本并自行修正。

协议拒绝的请求——例如 JSON 格式错误、方法未知,或请求带有 id 但没有 method——会返回带标准错误代码的 JSON-RPC 错误,或通过 HTTP 返回状态码。请求未执行,由客户端处理,而不是由模型处理。

情况响应
文档格式错误result,isError: true
XPath 表达式无效result,isError: true
架构违反result,isError: true,并将违反项作为 structuredContent
缺少参数或参数类型错误result,isError: true,指出字段名称
工具未知result,isError: true,列出五个现有工具
方法未知error,-32601
有 id 但没有 methoderror
JSON 格式错误通过 HTTP 返回 415;通过 stdio 时跳过该请求,会话继续

错误

文档格式错误既不会导致崩溃,也不是协议错误:

{"name":"xml_check","arguments":{"xml":"<a>"}}
{"content":[{"text":"…not well-formed…","type":"text"}],"isError":true}

模型会读取这段文本,并可修正文档或告知用户。

设计

五个工具,而不是十四个。 每次请求中,模型的上下文都会包含所有工具的描述。拥有二十个狭窄工具的服务,在描述自身上耗费的上下文比文档本身还多。

文档以字符串传递,而非路径。 服务绝不会打开文件。模型可以读取什么由客户端决定,这正是应该由客户端做出的决定——如果服务接收路径,就可能读取计算机上的任意文件。

使用一个协议实现,而不是自行实现。 JSON-RPC 和 MCP 层由官方 SDK 提供。三个协议版本和三种传输方式本身就是一个协议项目;要确保手写实现始终符合这些标准并非易事,而 XML 服务的价值并不在此。这个 crate 自己实现的是五个函数,以及模型读取的文本。

0.0.11 中的功能

  • 五个工具:查询、检查、校验、验证、格式化
  • XPath 1.0:十个轴、25 个函数、全部四种值类型
  • 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 表达式获得精确答案绝不会
粘贴到上下文中必须能放进上下文,而且每轮都会消耗 token模型通过目测匹配模式否
文件系统或 shell 服务不受限grep 能给出什么就是什么取决于服务端
通用 HTTP 获取服务不受限无会,这是其设计用途

最后一行值得停下来想一想。能够获取内容的服务端,可能会被它受命读取的文档引向你的内部网络。这里的工具没有打开套接字的代码;唯一的监听器是你通过 --transport 启动的那个,而且它只会响应请求。

基准测试

cargo bench --bench protocol

每个请求的延迟,因为 MCP 客户端发送一个请求后会等待响应。在 200 KB 负载下,JSON-RPC 层的开销约为纯解析的 10–25%;对于较小的负载,则只有几微秒。请参阅 doc/BENCHMARKS.md,其中也解释了为什么必须成对进行比较。

示例

examples/ 会通过 stdio 调用实际二进制文件并断言响应,因此当 README 中的调用不再有效时,CI 会失败。

示例展示内容
session.sh完整会话:初始化、列出工具、调用每个工具
errors.sh格式错误的文档、错误的表达式、协议错误

何时不应使用 oxml-mcp

  • 文档能放进上下文。 直接粘贴;工具往返更慢,也没有额外收益。
  • 你需要编辑 XML 结构。 xml_format 会序列化并格式化文档;它不会插入、删除或更改其中的数据。
  • 你需要 XSLT 或 XPath 2.0。 这两者都不可用。
  • 文档大于可用内存。 文档会被完整解析。
  • 你希望服务端获取文档。 它绝不会这样做;这正是设计目的。

常见问题

为什么模型每次都必须传入整个文档?

因为服务端不会在调用之间保留状态。这样可以确保多个客户端共享同一个二进制文件时仍能正确运行,也意味着无需使缓存失效,或担心会话间发生信息泄漏。

对于大型文档,这确实很浪费;未来版本可能会加入基于句柄的流程。在此之前,调用一次 xml_inspect,再进行一次精准的 xml_query,胜过多次探索性查询。

它能读取磁盘上的文件吗?

不能,也不会支持。服务端接收的是文档内容。如果服务端接收路径,任何有权访问它的模型都可以读取服务端进程有权读取的任意文件——是否允许读取,应由客户端决定。

将不可信 XML 交给它安全吗?

安全。它绝不会解析外部实体,因此,包含 <!ENTITY xxe SYSTEM "file:///etc/passwd"> 的文档无法让服务端读取该文件。实体展开和嵌套深度都有上限。

为什么只有五个工具?

每个工具的描述都会占用每次请求的上下文。五个覆盖面广的工具比二十个范围狭窄的工具开销更小,而且能覆盖相同的需求,因为 XPath 本身就是查询语言。

它能否与 Claude 以外的客户端配合使用?

它通过 stdio 和两种 HTTP 传输方式实现了 MCP,且不包含针对特定客户端的行为,因此任何兼容的客户端都应能正常使用。它已通过 Python SDK 客户端在两种 HTTP 传输方式下的测试,并在当前两个协议阶段中都获得独立 MCP 审计工具 100/100 的评分。

我的文档包含 emoji,调用失败了。

这是一个已在 0.0.3 中修复的错误。Python 的 json.dumps 默认会转义非 ASCII 字符,因此 emoji 会以代理项对的形式传入——😀——而 JSON 解析器拒绝了转义后的代理项对。任何发送 emoji 的 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 传输时,它会跳过格式错误的行,不作回复,并继续处理下一行。参见协议。

为什么未知工具会返回 isError,而不是 JSON-RPC 错误?

在 0.0.8 之前,它返回的是 -32602。在无状态 HTTP 修订版中,SDK 会将该代码作为 HTTP 400 返回,客户端会将其报告为传输故障,而模型永远不会读取到它。对于拼错工具名称的模型,返回说明现有五个工具的文本更有帮助。参见协议。

开发

./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 监听器仅在通过命令行请求时才会启用,默认绑定到 loopback 地址,且不进行身份验证——参见传输。

威胁模型假设文档及其周围的 JSON 都是恶意的:文档可能有害,因为模型被要求查看来自互联网的内容;JSON 可能有害,因为它是程序的全部输入。参见 https://github.com/sebastienrousseau/oxml/blob/main/doc/SECURITY-MODEL.md。

文档

致谢

oxml-mcp 的诞生离不开此前的工作:

  • Anthropic — 感谢其制定了本服务所实现的模型上下文协议规范。
  • lxml 和 libxml2 — 为 XML 工具包应具备的功能树立了标杆,并积累了数十年来对正确性的持续打磨。
  • W3C — 感谢其制定了 xml_query 所遵循的 XPath 1.0 规范。

许可证

可根据你的选择,采用 Apache License, Version 2.0 或 MIT License 进行双重许可。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。