☰
Arai MCP 服务说明文档:从 CLAUDE.md 到 stdio 的 Rust 实现路径
2026/10/10 11:47:30 网站建设 项目流程

1. 为什么 CLAUDE.md 写了却像没写:Arai MCP 服务要解决的规则失效问题

如果你用 Claude Code 或 Cursor 写过项目级指令文件,大概率遇到过这种尴尬:CLAUDE.md 里明明写了「Never force-push to main」,结果某次对话里助手还是把git push --force拼了出来;你写了「Always run tests before pushing」,它照样直接推。问题不在于模型不听话,而在于 CLAUDE.md 本质上是一份被动上下文——它随会话增长被塞进 prompt,然后被后续几十轮对话稀释、遗忘,最后变成一段没人执行的建议文本。

Arai 这个 MCP 服务想干的事,就是把「建议」变成「可执行规则」。它读取你的 CLAUDE.md、.cursorrules、.windsurfrules 等指令文件,用模式匹配把祈使句(never / always / must / don't)抽成结构化规则,再通过 MCP 协议暴露给 AI 工具链。当模型准备调用某个工具时,Arai 会在 PreToolUse 阶段判断这条调用是否踩了规则;踩了禁止性规则(never、forbids、must_not),它直接返回permissionDecision: "deny",让 Claude Code 拒绝这次工具调用,而不是事后提醒。

一句话概括:Arai 是一个本地运行的 MCP 服务,把 CLAUDE.md 从「写给模型看的散文」变成「能被程序判定和拦截的规则集」。它适合三类人:一是项目里有多条硬性编码规范、希望 AI 别越线的团队开发者;二是想给 Agent 加一层本地护栏、又不想把代码传到云端的隐私敏感用户;三是正在研究 MCP stdio 传输怎么落地、想找一个真实 Rust 实现参考的工程师。本文聚焦最后一类,同时把前两类的接入路径讲清楚。

需要先说明的是,Arai 本身是本地 stdio 服务,零云端依赖,数据落在~/.arai/目录。而如果你希望把这类本地 MCP 服务统一接入一个可管理的模型网关、方便切换模型和集中看调用日志,可以配合 TaoToken 这类平台使用——它提供兼容 OpenAI 风格的 API 入口,模型对话、Coding Plan、API Keys 都有对应页面,后面第 2 节会给出具体地址和配置方式。两者不冲突:Arai 管规则,TaoToken 管模型接入。

2. 接入前的环境准备:Rust 工具链、CLAUDE.md 与 TaoToken 模型入口

在动手配 Arai 之前,先把三样东西备齐:Rust 环境、一份能被解析的 CLAUDE.md、以及一个可用的模型调用入口。前两样是 Arai 的运行前提,第三样决定你的 AI 工具链能不能真正跑起来。

Rust 环境是硬要求。Arai 是 Rust 实现,安装脚本会拉取预编译二进制,但如果你想从源码构建或调试 stdio 行为,需要cargo和rustc。检查命令:

rustc --version cargo --version

如果提示 command not found,去 rustup 官网按系统装即可,装完重开终端。实测下来,Rust 1.75 以上版本都能正常编译 Arai 的依赖树,低于这个版本可能在 tree-sitter 相关 crate 上卡住。

CLAUDE.md 是 Arai 的规则来源。它支持的文件不止 CLAUDE.md 一个,完整清单如下:

指令文件对应工具Arai 执行方式
CLAUDE.mdClaude CodeHooks(block + advise)
~/.claude/CLAUDE.mdClaude Code 全局Hooks(block + advise)
~/.claude/projects//memory/.mdClaude Code memoryHooks(block + advise)
.cursorrules / .cursor/rulesCursorMCP(advise)
.windsurfrulesWindsurfMCP(advise)
.github/copilot-instructions.mdGitHub Copilot仅摄取

注意最后一行:Copilot 的指令文件只被摄取、不参与拦截,因为 Copilot 目前没有对应的 hook 机制。真正能「拒绝工具调用」的是 Claude Code 这条链路。

第三样是模型入口。Arai 负责规则判定,但模型本身还是要通过某个 API 调用。如果你用 Claude Code,它默认走 Anthropic 官方;如果你想把模型调用统一到一个可管理的入口,可以用 TaoToken 的 API:

  • 官网入口:https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=
  • API 基址:https://taotoken.net/api
  • 模型对话页:https://taotoken.net/api?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=model-chat
  • Coding Plan 页:https://taotoken.net/api?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=coding-plan
  • API Keys 页:https://taotoken.net/api?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=api-keys
  • 接入文档:https://taotoken.net/api?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=doc

这里要强调一个配置原则:无论你接的是 Arai 还是别的 MCP 服务,只要涉及模型调用,三件套必须写全——Base URL、API Key、Model ID。少任何一个,客户端都会在启动时报错,最常见的表现就是 401 或local proxy failed。后面第 3 节会给出完整的可复制配置片段。

环境备齐后,先跑一次安装和初始化,确认 Arai 能识别你的项目:

# 安装 Arai curl -sSf https://arai.taniwha.ai/install | sh # 进入你的项目目录 cd your-project # 初始化:发现指令文件、提取规则、设置 hooks arai init

arai init做完后,用arai status看当前生效的规则数量,用arai guardrails列出所有活动规则。如果这两条命令输出为空,说明你的 CLAUDE.md 里没有可被识别的祈使句,或者文件路径不在 Arai 的扫描范围内。

3. 可复制的配置:CLAUDE.md 规则写法与 stdio 启动命令

这一节是全文最需要动手的部分。我会给出三段可直接复制的配置:CLAUDE.md 的规则写法、Arai 的 MCP 服务声明(JSON 格式)、以及 stdio 启动命令。三段配好,服务就能被 Claude Code 发现。

先看 CLAUDE.md 的规则写法。Arai 靠模式匹配祈使语言来抽规则,所以句子结构越明确,抽取越准。推荐用「谓词 + 动作 + 对象」的短句:

# 项目规则 - Never force-push to main - Always run tests before pushing - Never hand-write migration files - Must not delete files under src/core - Prefer the new payment SDK over the legacy one (until 2027-06-30) - Never touch the old auth module (expires 2026-09-01)

几个细节值得注意。第一,never、forbids、must_not这类禁止性谓词会被推断为 block 级别,触发时返回permissionDecision: "deny";always、requires是 warn 级别,返回 allow 但附带上下文;prefers、learned_from是 inform 级别,只记录不拦截。第二,行尾的(expires YYYY-MM-DD)或(until YYYY-MM-DD)是规则过期注解,解析时会被剥离并单独存储,到期后load_guardrails自动过滤,规则停止触发——这对临时性约束特别有用,不用手动回来删。第三,Arai 不是纯关键词匹配,它会做意图分类和代码图分析。比如「never hand-write migration files」只在 Write 工具上触发,不会误伤 Edit;写入migrations/versions/目录时会触发 alembic 相关规则,哪怕文件里没提 alembic。

写完 CLAUDE.md,先别急着接 MCP,用arai lint预览一下抽取结果:

arai lint CLAUDE.md

这条命令会解析文件并打印提取出的规则三元组(主体/谓词/客体)。如果某条规则没被抽出来,多半是句子太口语化,改成上面的短句结构即可。想预览规则集增量,用arai diff CLAUDE.md。

接下来是 MCP 服务声明。Claude Code 的 MCP 配置通常写在项目根目录的.mcp.json,或者用户级的~/.claude.json。Arai 是 stdio 服务,所以配置里command指向arai,args是mcp:

{ "mcpServers": { "arai": { "command": "arai", "args": ["mcp"], "env": { "ARAI_HOME": "/Users/yourname/.arai" } } } }

如果你同时用 TaoToken 作为模型入口,Claude Code 侧的模型配置需要写全三件套。以 settings 片段为例:

{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_API_KEY": "sk-your-taotoken-key", "ANTHROPIC_MODEL": "claude-sonnet-4-20250514" } }

注意ANTHROPIC_BASE_URL填的是https://taotoken.net/api,不要带 UTM 参数,UTM 只用于网页跳转归因。API Key 去 TaoToken 的 API Keys 页生成,Model ID 按你实际要用的模型填。这三项缺一不可,缺 Base URL 会走默认官方地址导致鉴权失败,缺 Key 直接 401,缺 Model ID 客户端可能报模型不存在。

最后是 stdio 启动命令。Arai 的 MCP 服务不需要你手动常驻,Claude Code 会在需要时按配置拉起。但调试阶段建议手动跑一次,确认 stdio 通道正常:

# 直接启动 MCP 服务器(stdio 模式) arai mcp

启动后进程会阻塞等待 stdin 输入,这是正常的——stdio 传输就是靠标准输入输出通信。你可以手动发一条 JSON-RPC 初始化消息测试,但更推荐用第 4 节的连通性验证方法。

4. 验证服务可被发现与调用:一次完整的本地连通性测试

配置写完不代表服务能用。这一节给出一套可复现的验证流程,从「服务能否启动」到「工具能否被调用」逐层确认。

第一步,确认 Arai 二进制在 PATH 里,且 MCP 子命令存在:

which arai arai mcp --help

如果which arai没输出,说明安装脚本把二进制放在了非 PATH 目录,手动加一下或重装。arai mcp --help能打印用法,说明子命令注册正常。

第二步,用 MCP 的 initialize 握手验证 stdio 通道。最直接的办法是往arai mcp的 stdin 里灌一条初始化请求:

echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' | arai mcp

正常情况会返回一段 JSON,包含serverInfo和capabilities,其中capabilities.tools应该存在。如果返回空或报错,检查 Arai 版本(arai --version),v0.2.3 以上才完整支持工具接口。

第三步,列出工具。MCP 协议里列工具用tools/list:

echo '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' | arai mcp

你应该能看到三个核心工具:arai_add_guard、arai_list_guards、arai_recent_decisions。这三个是 Arai MCP 的对外接口,分别对应注册规则、列出规则、检索最近触发记录。如果只看到一个或没有,说明服务声明里的args写错了,或者 CLAUDE.md 解析失败导致工具注册中断。

第四步,实际调用一次arai_list_guards,确认规则被正确加载:

echo '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"arai_list_guards","arguments":{}}}' | arai mcp

返回内容里应该包含你在 CLAUDE.md 里写的规则,以主体/谓词/客体三元组形式呈现,并标注来源文件。这一步通过,说明「CLAUDE.md → 规则抽取 → MCP 工具暴露」这条链路是通的。

第五步,在 Claude Code 里做端到端验证。重启 Claude Code,让它重新读取.mcp.json。然后在对话里输入/mcp查看已连接的服务,应该能看到arai。接着故意触发一条禁止性规则,比如让助手执行git push --force,观察它是否被拒绝。如果返回permissionDecision: "deny"并附带规则来源,说明拦截生效。

验证过程中,arai why是个好帮手,它能在不写审计日志的前提下解释哪些规则会触发:

arai why "git push --force"

这条命令是 dry-run,适合在改规则前预判影响。另外arai audit可以查看本地审计日志,arai stats聚合统计顶级规则、合规性和 token 经济学——后者对评估规则是否真的被遵守很有用。

5. 常见报错排查:401、local proxy failed 与 reading choices 的对照处理

接入 MCP 服务时,报错信息往往指向配置的某个具体字段。这一节按真实报错分类,给出对照排查路径。

401 Unauthorized。这个几乎总是 API Key 问题。如果你在 Claude Code 里配了 TaoToken 作为模型入口,检查ANTHROPIC_API_KEY是否填了完整的sk-开头字符串,有没有多余空格或换行。另一个常见原因是 Base URL 写成了带路径的形式,比如https://taotoken.net/api/v1,而客户端又自动拼了一次/v1,导致鉴权端点错位。正确写法是https://taotoken.net/api,让客户端自己补全路径。如果 Key 确认无误仍报 401,去 TaoToken 的 API Keys 页确认这个 Key 是否被禁用或额度耗尽。

local proxy failed。这个报错通常出现在客户端尝试连接本地 MCP 服务时。Arai 是 stdio 服务,不走网络端口,所以如果你在配置里写了url字段而不是command,客户端会尝试当 HTTP 服务连,自然失败。检查.mcp.json,确保 Arai 的配置块用的是command+args,而不是url。另外,如果command填的是相对路径或~开头的路径,某些客户端不会展开,建议填绝对路径,或者确保arai在系统 PATH 里。

reading choices 相关报错。这类错误一般出现在模型返回结构不符合预期时,比如客户端期望choices数组但拿到的是错误对象。根因往往是模型 ID 写错,或者 Base URL 指向了一个不兼容 OpenAI 格式的端点。排查顺序:先确认ANTHROPIC_MODEL或对应的模型字段填的是有效 Model ID;再确认 Base URL 是https://taotoken.net/api;最后看客户端日志里实际发出的请求体,确认字段名没写错。如果用的是 Claude Code 的 Anthropic 兼容模式,注意它读的是ANTHROPIC_*系列环境变量,不是OPENAI_*。

OAuth 相关报错。如果你在配置里同时启用了需要 OAuth 的 MCP 服务,而 Arai 是本地 stdio 不需要认证,两者混在一起可能导致客户端在启动阶段卡住。处理办法是把 Arai 的配置块单独隔离,确认它不依赖任何 token 字段。Arai 完全本地运行,env里只需要ARAI_HOME指向数据目录,不需要任何认证信息。

工具列表为空。如果/mcp能看到 arai 服务但工具列表是空的,先跑第 4 节的tools/list手动验证。如果手动也空,检查 CLAUDE.md 是否存在且可读,以及arai init是否成功执行过。arai status会显示当前正在执行的规则数量,为 0 就说明抽取阶段就失败了。

规则不触发。规则写进去了但拦截不生效,先确认谓词级别。只有never、forbids、must_not会返回 deny,always系列只 warn。如果你写的是「should not」,Arai 可能识别为 inform 级别,不会拦截。改成never或must not再试。另外检查规则是否已过期,行尾的(expires ...)到期后规则会被自动过滤。

排查时善用arai audit和arai stats,前者看每次触发的详细记录,后者看聚合合规率。如果某条规则频繁被 ignored,说明模型确实在违反,这时候要么加强规则措辞,要么检查是不是规则本身太模糊导致误判。

6. 把 Arai 接进你的工具链:从规则管理到模型入口的完整路径

走到这里,Arai 的 stdio 服务应该已经能在本地被正确发现和调用了。最后说一下怎么把它用顺,以及模型入口这块怎么配。

规则管理上,Arai 提供了几个实用命令。arai add "Never X"可以手动加规则,不用改 CLAUDE.md;arai scan重新扫描指令文件,适合你刚编辑完 CLAUDE.md 想立即生效;arai severity用来固定规则的严重性,支持增量拒绝推出——你可以先让一批规则处于 advise 模式观察一段时间,确认误报率低再切到 block。arai test scenarios.json能针对规则重放合成 hook 场景,适合在 CI 里做规则回归。

合规追踪这块,每次 PostToolUse 后 Arai 会把调用与同一会话的 PreToolUse 触发关联,发出 Compliance 事件,状态分三种:obeyed(禁止短语不在执行的命令里,或所需证据存在)、ignored(禁止短语仍在命令里,模型还是执行了)、unclear(信号不足)。arai stats会聚合这些事件,你能看到哪些规则被真正遵守、哪些形同虚设。

模型入口方面,如果你用 Claude Code 配合 TaoToken,记住三件套写全:Base URL 用https://taotoken.net/api,API Key 去 API Keys 页生成,Model ID 按实际模型填。需要长期跑编码任务或 Agent 的,可以看 Coding Plan 页;只是想验证模型连通性的,用模型对话页最快;接入细节和字段说明在接入文档里。这几个入口按需取用,不用全配。

一个实际经验:Arai 的规则抽取对句子结构敏感,我试过把「不要直接改数据库」这种中文祈使句写进 CLAUDE.md,抽取效果不如英文短句稳定。如果你的项目规则是中文的,建议在 CLAUDE.md 里用英文谓词开头、中文补充说明,比如Never modify production database directly(不要直接改生产库),这样既能被稳定抽取,又保留了可读性。

最后,Arai 是本地 stdio 服务,数据全在~/.arai/,审计日志是 JSONL 格式,配置在~/.arai/config.toml。想深入定制的话,直接读这两个路径下的文件比翻文档快。服务本身零云端依赖,不需要认证,这也是它适合接进本地 AI 工具链的原因——规则判定不出机器,模型调用走你选的入口,两边解耦,各管各的。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询