关于 self-inspect-mcp
self-inspect-mcp 是面向 Agent 的 MCP 服务:输入一段想法或任务描述,返回一个促使 Agent 检查自身假设的元问题。选择过程基于开放 CSV 和确定性启发式,不调用 LLM;支持托管服务及本地离线运行。
主要功能
- 01根据输入选择元问题
- 02每次调用都返回问题
- 03确定性、可审计的结果
- 04支持远程与离线运行
- 05提供 REST 和 Python 引擎
适用场景
- 01在采纳假设前检查依据
- 02提交计划或最终答复前复核
- 03长步骤推理中发现目标偏移
- 04对结论过度确信时重新审视
MCP 相关
MCP 服务提供一个 `self_inspect` 工具,接收 `thought` 并返回元问题文本。默认调用托管端点;设置 `SELF_INSPECT_LOCAL=1` 可在本地离线运行。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://api.ejentum.com/self-inspect-mcpclaude mcp add --transport http ejentum-self-inspect https://api.ejentum.com/self-inspect-mcp{"mcpServers":{"ejentum-self-inspect":{"type":"http","url":"https://api.ejentum.com/self-inspect-mcp"}}}在 Cursor 中打开{"servers":{"ejentum-self-inspect":{"type":"http","url":"https://api.ejentum.com/self-inspect-mcp"}}}在 VS Code 中打开{"mcpServers":{"ejentum-self-inspect":{"type":"http","url":"https://api.ejentum.com/self-inspect-mcp"}}}{"mcpServers":{"ejentum-self-inspect":{"serverUrl":"https://api.ejentum.com/self-inspect-mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
工具
详细介绍
Self-Inspect
一个你的 Agent 不会想到要自问的问题。
Agent 发送一个想法,或对当前任务的描述。它会收到一个元思考:一个简短、抽象的问题,让 Agent 在继续之前重新审视自己的任务和假设。不是建议,也不是答案,而是一个问题。
无需密钥,免费,结果确定。不使用大模型、嵌入或语义相似度。问题的选择依赖一个小型启发式算法,针对一份只需 5 分钟即可读完的开放 CSV 数据集;而负责响应 api.ejentum.com/self-inspect 的代码,就是本仓库中的代码。有一项测试可以证明二者不会出现偏差。
Agent 为什么需要它
Agent 总是在向前推进。这正是问题所在。任由 Agent 自行行动,它会:
- 坚持最初的解读,再也不重新审视;
- 累积从未明说的假设;
- 在漫长的步骤链中偏离最初目标;
- 停在第一个看似合理的答案上;
- 证据没有增加,信心却越来越强;
- 因为附和用户是条捷径而选择附和。
这些都不是知识上的缺陷。模型本来就知道更好的做法。这些是注意力上的缺陷:Agent 从不停下来问那个本可以及时发现问题的问题。
而它也无法可靠地自行提出这个问题。决定反思什么的,仍是那个已经做出承诺的过程,因此,Agent 所谓的“再次检查”往往只是重走自身偏见,并把它称作信心。承认陷阱的存在,并不等于跳出了陷阱。
Self-Inspect 会从外部提出问题。它返回一个 Agent 不会自行提出的元思考:哪些内容是基于假设的?哪些内容是固定不变的?哪些推论并不成立?缺少了什么?在什么情况下这不成立?应当有多大把握? 思考仍由 Agent 完成。这个工具只是让它开始审视。
何时调用
在 Agent 原本会一股脑继续推进的时刻,把它加入工作流:
- 形成假设后、采取行动前;
- 确定计划或最终答案前;
- 在漫长步骤链的每一步,及时发现偏移;
- Agent 察觉自己正在附和或确信不疑时。
发送一个想法,得到一个元思考,在心里回答它,再更清醒地继续。它总会返回一个问题(不存在“没有结果”的情况),只需调用一次,不会有大模型介入,也无需密钥。
如何使用元思考(具体方法)
Self-Inspect 会返回那个点明你的论断暗中依赖哪项假设的问题。用一个具体的反例来回答,并围绕经不起推敲的部分重建论断;不要只是承认这个问题,然后继续。只有在确实遇到自己无法突破的障碍时才调用它,绝不要按固定频率调用:强行在每一步都调用,只会制造虚假的修正,效果甚至不如完全不用。(在我们自己的评估中,正是这个方法区分出了表现最强和最弱的运行结果。)
评估结果
基于多轮基准测试(一个小型模型和一个前沿模型,40 轮开放式推理,采用盲测并交换顺序进行评判):
- 可靠且可审计。 元思考会以确定性方式返回;每次调用都会重新运行,结果逐字节一致,因此 Agent 检查过的内容会成为一份可验证、独立于模型的记录。这是它最突出、最站得住脚的特性。
- 只有它能让 Agent 质疑自己的假设。 不使用工具的对照组构建了自信的理论,却从未问过自己是否在编造内容;使用 self-inspect 后,Agent 提出了并指出了自身无法察觉、但对推理至关重要的假设;而在真正陷入瓶颈时,这个问题将调查引向新的方向,而不是证实原本已有的猜测。
- 提升是有条件的,并非自动发生。 只有当问题得到真实反例的回答,且主张据此重新构建时,才会产生提升;调用也必须发生在真正陷入瓶颈时,并且模型要有能力判断自己已陷入瓶颈。每一步都调用会产生负面效果:它会制造刻意安排的修正(先过度断言,再按计划收回),评判结果还不如完全不用工具。
- 把它用作有门槛的检查点,而不是包装层。 它能让推理在关键时刻变得清晰、可检查;但它无法让薄弱的推理者变强。
快速开始
发送一个 thought,获取一个 metathought。无需密钥。
REST(任何语言):
curl -s -X POST https://api.ejentum.com/self-inspect \
-H "Content-Type: application/json" \
-d '{"thought":"I am committing to this architecture and treating it as fixed"}'
# -> [{ "label": "commitment", "metathought": "What is fixed?" }]
MCP、Claude Code:
claude mcp add --transport http self-inspect https://api.ejentum.com/self-inspect-mcp
MCP、Claude Desktop / Cursor / 任何 HTTP-MCP 客户端:
{
"mcpServers": {
"self-inspect": {
"type": "http",
"url": "https://api.ejentum.com/self-inspect-mcp"
}
}
}
MCP 服务只提供一个工具 self_inspect,接收一个 thought 并返回元思考。无需安装,无需密钥。
Python(单文件,零依赖):
对于 Python 环境,dist/self_inspect.py 是一个包含完整引擎的单文件版本——CSV 数据已内嵌,仅使用标准库,无需安装任何内容。它会在本地运行与已发布版本完全一致的选择器(每次调用约 2 毫秒,无需网络):
python self_inspect.py "I am committing to this architecture and treating it as fixed"
# -> [{"label": "commitment", "metathought": "What is fixed?"}]
from self_inspect import self_inspect
self_inspect("I am about to assert the default timeout is 30s from memory")
# -> {"label": ..., "metathought": ...}
跨语言一致性测试(test/parity.python.test.mjs)确保其与 JS 引擎逐字节一致——无论在 Python、JS 中,还是通过托管端点使用,同一个 thought 都会得到同一个 metathought。
端点
| 接口 | 端点 | 认证 | 返回内容 |
|---|---|---|---|
| REST | POST https://api.ejentum.com/self-inspect | 无需密钥,按 IP 限流(120 次/分钟) | [{ label, metathought }] |
| HTTP 上的 MCP | https://api.ejentum.com/self-inspect-mcp (Streamable HTTP) | 无需密钥,按 IP 限流(60 次/分钟) | 工具 self_inspect -> 元思考文本 |
| MCP stdio / 离线 | mcp/ 包;SELF_INSPECT_LOCAL=1 可在本地运行选择器 | 无需密钥 | 工具 self_inspect(npx self-inspect-mcp) |
两个托管端点都无需密钥,并通过按 IP 限流和标准安全标头(HSTS、nosniff、拒绝框架嵌入)提供保护。
选择机制
select(thought, rows)(src/selector.js)会基于 selfinspect.csv 中的数据,以确定性的方式分两级进行路由:
- 规范化思考内容:转为小写,采用 Unicode NFKC 规范化,将非字母数字字符替换为空格,合并空白字符,并进行分词(
src/normalize.js)。 - 为每个视角(
input_type)评分:3 x (thought 中出现的类型名称词数) + 1 x (该视角的问题中出现的不同内容词数)。内容词是meta_thought中的词,减去一小组显式列出的停用词。证据会汇总该视角的所有问题,因此,一个视角可以凭分散在多行中的信号胜出。 - 选取得分最高的视角;平分时优先选择
strict而非booster,然后按视角名称的字典序决定。 - 在选定的视角内,返回本地内容匹配最多的问题;若平分,则选择
operator_rank最低的问题(规范问题)。matched: true。 - 如果所有视角都没有任何信号,则从一小组默认问题中,基于输入的稳定哈希,以确定性方式选出一个通用的自我检查问题(关于任务和假设),让不同输入得到不同的提示。
matched: false。
Self-Inspect 始终会返回一个元思考。 Agent 总能针对自己的任务和假设提出有价值的问题,因此该工具绝不会返回 null。matched 标志用于区分已路由到某个视角(true)和通用默认问题(false);metathought 永不为空。结果具有确定性:相同输入始终返回相同的元思考。(若要让更多输入路由到特定视角,应在 CSV 中添加措辞,或在未来添加 triggers 列,而不是使用模型。)
CSV 是事实来源
selfinspect.csv(约 50 个视角,137 个问题):
| 列 | 作用 | 是否发送给调用方 |
|---|---|---|
input_type | 认知视角;其名称词是路由键,权重为 x3 | 作为 id 的一部分 |
operator_rank | 视角内的顺序(1 = 规范问题);用于平分时决胜 | 作为 id 的一部分 |
runtime_tier | strict(核心)或 booster(感知);平分时优先选择 strict | 否 |
meta_thought | 返回的文本(原样)以及内容路由词的来源 | 是 |
返回的 id 为 input_type-operator_rank(例如 confidence-4)。如需添加或更改元思考,请编辑 CSV。不要手动编辑 dist/backend.cjs 或已部署的副本。
已发布 == 已部署(强制保证,而非承诺)
npm run build 会根据 selfinspect.csv + src/normalize.js + src/selector.js,重新生成 dist/backend.cjs(托管端点背后的引擎)和 dist/self_inspect.py(单文件 Python 移植版)(build/generate.mjs)。
如果任一已提交产物与生成器输出的字节不完全一致,test/drift.test.mjs 就会失败;如果 Python 移植版的结果与 JS 选择器在完整语料上的结果不一致,test/parity.python.test.mjs 就会失败。因此,无论使用哪种语言,只要引擎与 CSV 或选择器不一致,就无法通过 CI:每次推送和拉取请求都会运行完整测试套件(.github/workflows/ci.yml),并在安装了 Python 的运行器上执行,确保真正运行一致性测试。任何人都可以克隆此仓库,在本地和线上端点运行测试用例,并确认选择结果一致。
验证
npm test # selector fixtures + drift test
npm run build # regenerate dist/backend.cjs
git diff --exit-code dist/backend.cjs # clean == no drift
评估
元思考实际上带来了什么变化?在一段 30 轮的软件设计对话中,每轮调用一次 Self-Inspect 的 Agent 提出了 约 3.5 倍的决策分支(假设、边界情况、前置条件),相比之下,同一个 Agent 不使用工具时则少得多:使用相同模型(Claude Sonnet 4.6)、相同对话和相同提示词。
而且提出的问题是针对当下情境的,并非泛泛而谈:路由与对话时机相符。Agent 正要判断边界时,出现了 When would this not hold?;它正要持久化状态时,出现了 What is assumed?,它回答道:"I've been assuming persistence lives outside the module"——由此揭示了一个它从未明说的假设。
完整数据、原样的元思考,以及一条命令即可复现的方法(node evals/tools/analyze.mjs)都在 evals/ 中。
响应约定
REST 返回一个包含单个对象的数组,该对象恰好有两个字段:label(镜头,来自 input_type)和 metathought(问题)。对于无法路由的输入,仍会返回通用默认值(使用不同的镜头,但形状相同):
{"thought":"How much confidence is warranted in this result?"} -> [{ "label": "confidence", "metathought": "What confidence is warranted?" }]
{"thought":"order a pizza"} -> [{ "label": "sequence", "metathought": "What order is active?" }]
MCP 接口(self_inspect)仅返回 metathought 文本。
部署引擎(运维人员)
托管端在 Express 路由中运行 dist/backend.cjs(同一 CSV + 选择器的 CommonJS 构建),不使用密钥,并与任何身份验证或层级隔离。dist/backend.cjs 由 npm run build 重新生成,并会通过漂移测试与源文件进行核对。更新方法:编辑 selfinspect.csv,运行 npm run build,然后重新部署构建产物。切勿手动编辑已部署的副本。
MCP
mcp/ 是一个独立的 MCP 服务(self-inspect-mcp),提供一个工具 self_inspect。默认情况下,它会调用托管端点;设置 SELF_INSPECT_LOCAL=1 可使用随附的 CSV 副本,在离线状态下运行此选择器。参见 mcp/README.md。
故障排除
连接时出现 CRYPT_E_NO_REVOCATION_CHECK 或 TLS 撤销错误。 证书有效(Let's Encrypt、完整证书链、verify ok)。TLS 使用 Let's Encrypt,而它现在基于 CRL:CA 已于 2026 年停用 OCSP,因此没有可查询的 OCSP 响应器。无法在 OCSP 不可用时宽松处理撤销检查的严格客户端(某些 Windows/schannel 配置)可能会报告此错误,尽管证书本身没有问题。大多数客户端(Node、Python TLS)会软失败并正常连接。如果你的客户端无法软失败,请将撤销检查设为软失败;证书有效。
许可证
MIT。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。