内容
# 开放思维MCP服务器
**Open Mind的MCP集成层:它加载Open Mind的验证优先代码库工件,并将它们作为工具暴露给AI代理——每个答案都带有`文件:行`证据,声称来源无法支持的答案会被拒绝,而不是即兴发挥。**





```
代理:validate_claim_against_sources
{ "claim": "PaymentGateway 将信用卡数据写入 Postgres。" }
服务器:{ "status": "unsupported",
"matchedTerms": ["PaymentGateway"],
"evidence": [],
"reason": "工件描述了 PaymentGateway 但从未提及:
writes, cardholder, data, Postgres. ..." }
```
无API密钥。无网络。执行`npm install && npm run demo`,您将看到所有五个工具的答案——并且拒绝回答——来自捆绑的示例工件。
---
相关项目:
- [Open Mind](https://github.com/HelloThisWorld/open-mind):生成可源头追溯的代码库工件
- [open-mind-mcp-server](https://github.com/HelloThisWorld/open-mind-mcp-server):将这些工件作为MCP工具暴露给代理
- [agent-skill-verification-template](https://github.com/HelloThisWorld/agent-skill-verification-template):使用评估、指标、轨迹和重放工件测试代理技能/工具
## 这是什么(以及不是什么)
本项目是Open Mind的**可选集成层**:
- 它**不**取代Open Mind,也**不**自行分析仓库。
- 它加载Open Mind生成的`.openmind`工件目录,并将其暴露为五个MCP工具。
- Open Mind独立运行,永远不需要这个服务器。
- 该服务器也独立运行:它附带示例工件(真正的Open Mind输出,已检查),因此演示和测试可以独立运行。
两个项目之间的集成边界故意设计得很窄: **`manifest.json` 加上版本化的工件模式**(目前为`1.0.0`)。该服务器永远不会导入Open Mind的内部实现。
```
源代码仓库
│
▼
Open Mind ────────────── 验证优先分析(Python,独立)
│
▼
.openmind 工件 ────── manifest.json + 词汇表 / 架构 /
│ 流程 / 源索引(文件:行证据)
▼
open-mind-mcp-server ───── 本仓库(TypeScript,独立)
│
▼
Claude / Cursor / AI 代理 五个MCP工具,通过stdio,结构化JSON
```
## 代理为什么需要这个
在代码库上工作的LLM代理会以可预测的方式失败:它们流畅地回答,无论它们是否真正了解。声称“记住”不存在的重试策略的代理将自信地在此基础上进行构建,而错误将在三步之后以损坏的代码或错误的架构决策的形式出现。
Open Mind从源头解决这个问题:它从仓库中生成**确定性工件**——词汇表、架构组件、入口点流程、源符号索引——其中每个语句都带有`文件:行`证据和逐字摘录以及置信度。这个服务器在工具边界强制执行相同的纪律:
- **证据优先于流畅性。** 每个事实输出都引用`文件:行`证据。解释直接从工件中提供,而不是生成。
- **拒绝是一种功能。** 未知符号、未知组件和无法支持的声明返回`insufficient_evidence`或`unsupported`——并命名缺失的术语,以便代理知道**它**无法验证的内容。
- **所有内容都是机器可读的。** 所有工具输出都是结构化的JSON,具有声明的MCP输出模式。
- **确定性。** 相同的工件集和相同的输入产生相同的输出,字节对字节。有针对此的测试。
## 工具
| 工具 | 输入 | 输出 |
|---|---|---|
| `list_available_artifacts` | `{}` | 加载的工件类型、支持文件、条目计数、仓库名称 + 提交 |
| `search_codebase_context` | `query`, `limit?` | 排名词汇表/架构/流程/源条目,带有`文件:行`证据,或`no_results` |
| `get_symbol_evidence` | `symbol` | `supported`,带有证据记录,或`insufficient_evidence`,带有空证据 |
| `explain_architecture_component` | `component` | `supported`,带有逐字描述、职责、证据——或`insufficient_evidence`,命名**描述**的组件 |
| `validate_claim_against_sources` | `claim` | `supported` \| `unsupported` \| `insufficient_evidence`,带有匹配术语、引用和原因 |
## 工具输出示例
`npm run demo`(修剪)的实际输出。更多信息请参见[examples/demo-queries.md](examples/demo-queries.md)。
**`list_available_artifacts {}`**:
```json
{
"status": "ok",
"artifacts": [
{ "type": "glossary", "file": "glossary.json", "entryCount": 10 },
{ "type": "architecture", "file": "architecture.json", "entryCount": 4 },
{ "type": "flows", "file": "flows.json", "entryCount": 2 },
{ "type": "source-index", "file": "source-index.json", "entryCount": 12 }
],
"repository": { "name": "sample-repo", "commit": null }
}
```
**`get_symbol_evidence { "symbol": "RetryPolicy" }`**:
```json
{
"status": "supported",
"symbol": "RetryPolicy",
"evidence": [
{
"file": "docs/GLOSSARY.md",
"line": 11,
"snippet": "- **RetryPolicy**: 针对失败事件传递的指数退避计划:尝试等待 1s、4s、16s、64s,然后在事件被放入死信队列(DLQ)之前等待 256s。"
}
],
"confidence": "high"
}
```
**`validate_claim_against_sources`** — 来源支持的声明:
```json
{
"status": "supported",
"claim": "EventPublisher 重试失败的交付并将耗尽的事件放入死信队列。",
"matchedTerms": ["EventPublisher", "retries", "failed", "deliveries", "parks", "exhausted", "events", "dead", "letter", "queue"],
"evidence": [
{ "file": "docs/GLOSSARY.md", "line": 8, "snippet": "- **EventPublisher**: 将域事件传递给订阅者,确保至少一次语义;..." }
],
"reason": "10 个声明术语出现在描述 EventPublisher、RetryPolicy、parkInDeadLetterQueue 的工件中。参见引用的文件:行证据。",
"confidence": "high"
}
```
— 以及一个它们不支持的声明:
```json
{
"status": "unsupported",
"claim": "PaymentGateway 将信用卡数据写入 Postgres。",
"matchedTerms": ["PaymentGateway"],
"evidence": [],
"reason": "工件描述了 PaymentGateway 但从未提及:writes、cardholder、data、Postgres。加载的源不支持此声明。",
"confidence": "medium"
}
```
来源中完全没有声明的请求返回 `"status": "insufficient_evidence"` — 服务器区分**来源描述了该主题但不是该行为**和**来源根本没有涉及该主题**。
## 快速开始
### 选项 1:使用捆绑的示例工件
```bash
npm install
npm run build
npm test
npm run demo
```
[examples/sample-open-mind-artifacts/](examples/sample-open-mind-artifacts/)中捆绑的示例是Open Mind的真实输出,来自其fixture仓库(一个小型订单处理服务)。
### 选项 2:使用真实的Open Mind工件
```bash
cd ../open-mind
npm install # 可选;npm脚本只是Python的包装
npm run analyze -- --repo ./fixtures/sample-repo --output ./.openmind
# 等效于:python -m openmind.artifacts --repo ./fixtures/sample-repo --output ./.openmind
cd ../open-mind-mcp-server
npm install
npm run demo -- --artifacts ../open-mind/.openmind
# 或快捷方式,如果缺少工件,则打印设置说明:
npm run demo:openmind
```
将 `--repo` 指向任何本地仓库,以提供您自己的代码库的工件。
### 从Claude Code使用
```bash
claude mcp add open-mind -- node /absolute/path/to/open-mind-mcp-server/dist/server.js
```
### 从Claude Desktop(或任何MCP客户端)使用
```json
{
"mcpServers": {
"open-mind": {
"command": "node",
"args": ["/absolute/path/to/open-mind-mcp-server/dist/server.js"],
"env": {
"OPEN_MIND_ARTIFACTS_DIR": "/absolute/path/to/your/.openmind"
}
}
}
}
```
### 交互式检查
```bash
npx @modelcontextprotocol/inspector node dist/server.js
```
## 配置
| 环境变量 | 默认值 | 含义 |
|---|---|---|
| `OPEN_MIND_ARTIFACTS_DIR` | 捆绑的示例 | 加载的 `.openmind` 目录(必须包含 `manifest.json`) |
| `OPEN_MIND_SOURCE_ROOT` | 未设置 | 分析的源树的根目录;设置后,引用检查在加载时针对真实文件进行验证(仅警告) |
| `OPEN_MIND_MAX_RESULTS` | `5` | `search_codebase_context` 的默认结果上限 |
| `LOG_LEVEL` | `info` | `debug` \| `info` \| `warn` \| `error`(stderr上的JSON日志) |
如果配置的目录无法加载,服务器会记录结构化的警告并回退到捆绑的示例,因此零配置启动始终有效。具有`2.x`模式的工件将被拒绝并显示清晰的错误。
## 工件合约
服务器读取 **1.x模式**下的 `.openmind` 目录:
```
.openmind/
manifest.json 生成器、时间戳、仓库 { name, root, commit }、工件文件映射
metadata.json 汇总计数
glossary.json [{ term, kind, description, evidence[], confidence }]
architecture.json [{ name, kind, description, responsibilities[], evidence[], confidence }]
flows.json [{ name, description, steps[{ order, description, component, evidence[] }], confidence }]
source-index.json [{ path, language, symbols[{ name, kind, line, snippet }] }]
```
每个 `evidence` 记录都是 `{ file, line, snippet }`,带有仓库相对路径;每个条目都带有 `high` / `medium` / `low` 的置信度。验证发生在加载时的三个层次:zod结构模式、模式版本门控(接受`1.x`,拒绝其他主版本)和引用策略(相对无遍历路径;可选地通过 `OPEN_MIND_SOURCE_ROOT` 验证对抗真实源树)。
## 遥测
结构化JSON日志输出到stderr(stdout属于MCP传输)。每个工具调用都会记录:
```json
{"time":"...","level":"info","event":"tool_calls","tool_name":"validate_claim_against_sources","artifacts_dir":"...","repository_name":"sample-repo","status":"unsupported"}
```
失败添加 `failure_reason`。工件加载记录 `artifacts_loaded` / `artifact_citation_warning` / `artifacts_fallback_to_samples` 事件,并带有相同的字段。
## 项目结构
```
src/
├── server.ts # MCP 接线(stdio 传输、工具注册、示例回退)
├── config.ts # 环境驱动的配置,离线默认值
├── demo.ts # 离线演示运行器 (--artifacts <dir>,--openmind)
├── artifacts/
│ ├── artifact-types.ts # 1.x 工件合约的 zod 模式 + 搜索索引类型
│ └── artifact-loader.ts # 清单驱动的加载、版本门控、索引构建
├── tools/ # 每个 MCP 工具一个文件(纯逻辑 + 注册 + 遥测)
├── validation/
│ ├── citation-validator.ts # 引用策略 + 可选地对抗本地源的验证
│ └── claim-validator.ts # 确定性支持/不支持/证据不足逻辑
└── telemetry/logger.ts # stderr上的 JSON 日志(stdout 属于 MCP)
examples/
├── sample-open-mind-artifacts/ # 来自其fixture仓库的Open Mind实际输出(离线演示数据)
└── demo-queries.md # 复制粘贴工具调用及预期输出
tests/ # vitest:加载器、引用策略、工具、确定性、MCP往返
```
## 限制(MVP范围)
- **读取预生成的工件。** 它不运行Open Mind分析;当代码更改时,请使用Open Mind重新生成工件。
- **默认情况下只读。** 它不执行shell命令,不访问配置的工件目录(加上可选的,仅限读取的引用检查在`OPEN_MIND_SOURCE_ROOT`下)。
- **声明验证是词法验证,不是语义验证。** 裁决来自确定性的术语覆盖率评分。它无法检测否定——示例词汇表表示PaymentGateway“*从不*存储原始卡号”,而声明它“存储原始卡号”仍将与这些词匹配。真正的部署将在相同的工具合约后添加NLI/蕴涵检查。
- **搜索是关键词评分,不是嵌入。** 为了演示:确定性,离线,零重依赖。
- **只有在存在源时才验证引用。** 没有`OPEN_MIND_SOURCE_ROOT`,引用检查仅限于形状(通常分析的仓库在运行时不可用)。
## 路线图
- [ ] 更多客户端的真实MCP stdio服务器注册示例(Cursor配置示例)
- [ ] 发布的工件模式包,由生成器和消费者共享
- [ ] 更丰富的语义声明验证(蕴涵在相同的工具合约下)
- [ ] 可选的`refresh_artifacts`工具,按需调用Open Mind
- [ ] 与[agent-skill-verification-template](https://github.com/HelloThisWorld/agent-skill-verification-template)集成以评估工具表面
- [ ] 现有结构化日志字段后的OpenTelemetry指标/轨迹
## 开发
```bash
npm run dev # 从源代码运行服务器(tsx,stdio)
npm test # vitest(加载器、验证器、工具、MCP往返、确定性)
npm run build # tsc → dist/
npm run clean # 删除dist/
```
CI在Node 20和22上运行安装 → 构建 → 测试 → 演示,仅使用捆绑的示例工件——无需Open Mind检查-out ([.github/workflows/ci.yml](.github/workflows/ci.yml))。
## 许可证
[MIT](LICENSE)