内容
# LoreMCP
一个本地的、只读的MCP服务器,为AI编码代理提供实时访问配置的兄弟仓库中[nWave](https://github.com/nWave-ai/nWave)结构化文档的能力。
**问题**: 在代码库中工作的AI代理每次会话都从盲状态开始。它们无法在行动之前查询之前的架构决策、领域约束或功能级上下文 - 因此它们会重新发明模式、与上一周期的决策相矛盾或忽略领域规则,而任何有经验的团队成员都应该知道这些。
**LoreMCP的作用**: 暴露四个MCP工具 - `list_concerns`、`list_features`、`query_context`和`resolve_concern` - 直接从本地文件系统读取波浪决策、ADR和`CLAUDE.md`,并以结构化的JSON返回。无需守护进程,无需同步,无需远程调用。指向一个文件夹,您的代理可以询问“已经决定了哪些主题?”,“功能X做出了哪些决策?”,或“平台使用什么进行身份验证?”在编写一行代码之前。
---
## 安装
```bash
npx @koed00/lore-mcp
```
或全局安装:
```bash
npm install -g @koed00/lore-mcp
```
---
## 配置
在磁盘上任意位置创建`lore-mcp.config.json`:
```json
[
{ "repo-name": "my-api", "doc-path": "/Users/you/code/my-api/docs" },
{ "repo-name": "shared-libs", "doc-path": "/Users/you/code/shared-libs/docs" },
{ "repo-name": "lore-mcp", "doc-path": "/Users/you/code/LoreMCP/docs" }
]
```
每个条目都将逻辑名称映射到兄弟仓库的`docs/`目录。服务器期望在该路径下具有nWave文档结构:
```
docs/
feature/{feature_id}/{phase}/wave-decisions.md ← 功能级决策
product/architecture/*.md ← ADR
CLAUDE.md ← 仓库根级指导
```
通过`LORE_MCP_CONFIG`环境变量指向服务器配置(默认为工作目录中的`lore-mcp.config.json`):
```bash
LORE_MCP_CONFIG=/absolute/path/to/lore-mcp.config.json npx @koed00/lore-mcp
```
---
## MCP工具
### `list_concerns`
扫描所有配置的仓库,获取候选关注点/主题字符串(功能目录名称、ADR标题、决策标题文本),代理可以在调用`resolve_concern`之前浏览。无参数。
**输入**: 无
**输出**:
```json
{
"concerns": ["auth-flow", "rate-limiting", "Concern Matching Strategy"],
"searched_repos": ["my-api", "shared-libs"]
}
```
跨仓库去重。限制200条记录(如果截断,则添加`warnings`项)。`warnings`仅在非空时存在。永远不会返回错误形状 - 空的`concerns`数组是有效响应,当没有配置的仓库具有nWave结构时。
---
### `list_features`
枚举配置仓库的`docs/feature/*/`和阶段子目录。
**输入**: `repo_name`(字符串)
**输出**(成功):
```json
{
"repo_name": "my-api",
"doc_path": "/Users/you/code/my-api/docs",
"features": [
{ "feature_id": "auth", "phases": ["discover", "design", "deliver"] },
{ "feature_id": "payments", "phases": ["discover"] }
],
"has_architecture_adrs": true,
"has_claude_md": true
}
```
---
### `query_context`
为给定的仓库和功能返回波浪决策、ADR和/或`CLAUDE.md`的实时读取片段。
**输入**: `repo_name`(字符串),`feature_id`(字符串)
**输出**(完整结构):
```json
{
"repo_name": "my-api",
"feature_id": "auth",
"results": [
{
"source_file": "docs/feature/auth/design/wave-decisions.md",
"phase": "design",
"snippet": "# Auth Decisions\n\nD-auth-1: Use JWT with RS256..."
},
{
"source_file": "docs/product/architecture/adr-001-auth-strategy.md",
"phase": "architecture",
"snippet": "# ADR-001: Auth Strategy\nStatus: Accepted\n..."
}
],
"retrieved_at": "live (uncached) read at 2026-06-16T10:07:33.412Z"
}
```
**部分结构**(功能目录不存在,但有ADR/CLAUDE.md - 返回最佳可用上下文,并附警告):
```json
{
"repo_name": "my-api",
"feature_id": "nonexistent-feature",
"results": [{ "source_file": "docs/product/architecture/adr-001.md", ... }],
"warnings": ["Repo has architecture ADRs but no feature-level wave-decisions.md for the requested feature."],
"retrieved_at": "live (uncached) read at ..."
}
```
**结构化错误**(从不返回原始异常):
| 错误 | 何时发生 |
|-------|------|
| `REPO_NOT_CONFIGURED` | `repo_name`不在配置中 |
| `REPO_PATH_NOT_FOUND` | 配置的`doc-path`不存在或不可读 |
| `FEATURE_NOT_FOUND` | 功能目录不存在,且无ADR/CLAUDE.md可 fallback |
| `NO_NWAVE_STRUCTURE` | 仓库完全没有nWave结构 |
---
### `resolve_concern`
搜索所有配置的仓库中提及关注点关键词的nWave工件,返回按相关性等级排序的匹配项、被拒绝的替代方案和部分结构警告。无需`repo_name` - 扫描所有内容。
**输入**: `concern`(字符串)- 普通语言主题,例如`"auth"`、`"data persistence"`、`"rate-limiting"`
**输出**(成功):
```json
{
"concern": "auth",
"matches": [
{
"repo_name": "my-api",
"source_file": "docs/feature/auth-flow/design/wave-decisions.md",
"phase": "design",
"snippet": "## D-auth: JWT strategy...",
"relevance": "feature-level"
},
{
"repo_name": "my-api",
"source_file": "docs/product/architecture/ADR-0007-auth-strategy.md",
"phase": "architecture",
"snippet": "# ADR-0007: Auth Strategy\nStatus: Accepted\n...",
"relevance": "architecture-level"
}
],
"rejected_paths": [
{
"repo_name": "my-api",
"source_file": "docs/product/architecture/ADR-0007-auth-strategy.md",
"snippet": "Rejected: OAuth2 — too complex for current scale.",
"type": "rejected_alternative"
}
],
"retrieved_at": "live (no cache)"
}
```
匹配项按顺序排列:`feature-level`优先,然后是`architecture-level`,然后是`repo-conventions`。`rejected_paths`始终存在(如果未找到,则为空数组)。
**结构化错误**:
| 错误 | 何时发生 |
|-------|------|
| `INVALID_CONCERN` | 关注点为空或不包含字母数字字符 |
| `CONCERN_NOT_FOUND` | 没有文件在任何配置的仓库中提及关注点 |
---
## Claude Code 设置
将以下内容添加到您的Claude Code MCP配置(`~/.claude/claude_desktop_config.json`或`.mcp.json`)中:
```json
{
"mcpServers": {
"lore-mcp": {
"command": "npx",
"args": ["@koed00/lore-mcp"],
"env": {
"LORE_MCP_CONFIG": "/absolute/path/to/lore-mcp.config.json"
}
}
}
}
```
---
## 在架构过程中使用LoreMCP
LoreMCP在基于波浪的工作流程(例如[nWave](https://github.com/nWave-ai/nWave))的`DISCUSS`和`DESIGN`阶段中最有价值 - 在编写代码之前,当代理需要知道其他地方已经做出了什么决定时。仅`resolve_concern`如果代理已经知道要询问的关键词,则有所帮助;首先使用`list_concerns`进行“查询前浏览”操作,跨所有配置的仓库进行:
1. **广泛浏览**:调用`list_concerns()`,无需参数,查看所有配置的仓库中每个候选关注点/主题字符串 - 功能目录名称、ADR标题、决策标题文本 - 无需事先了解仓库名称或关键词。
2. **浏览已知仓库**:在您已经了解的特定兄弟仓库上调用`list_features(repo_name)`,查看其文档的功能/阶段。
3. **广泛搜索**:为可能与您要设计的主题相关的每个主题调用`resolve_concern(concern)`(例如`"auth"`、`"rate-limiting"`、`"caching"`)- 它扫描所有配置的仓库,不需要`repo_name`,并显示已接受的决策和被拒绝的替代方案。
4. **深入探索**:一旦`resolve_concern`、`list_concerns`或`list_features`指向特定的仓库+功能,请为该功能的历史记录调用`query_context(repo_name, feature_id)`,涵盖所有波浪,而不仅仅是与关键词匹配的片段。
**示例提示到代理**:*“在设计此服务的速率限制策略之前,请使用lore-mcp的list_concerns查看兄弟仓库中已经记录了哪些主题,然后使用resolve_concern检查是否已经决定了如何进行速率限制,并检查被拒绝的替代方案,然后再提出新方法。”*
---
## 在团队范围内强制使用LoreMCP
单个开发人员记住提示他们的代理是很脆弱的 - 它无法在入职、忙碌的一周或不同的代理会话中幸存。可靠的解决方案是将指令放在每个代理会话都已经查看的仓库中:`CLAUDE.md`。任何团队负责人或DevOps经理都可以将下面的代码块粘贴到项目的`CLAUDE.md`中,一次完成,每个开发人员的代理都会自动采用工作流程,无需每个提示都提醒。
```markdown
## 跨仓库上下文(LoreMCP)
此仓库是多仓库平台的一部分。在设计或架构任何非琐碎的功能之前,请使用`lore-mcp`MCP工具检查其他地方已经做出了什么决定 - 不要假设从零开始:
1. 调用`list_concerns()`以查看所有配置的兄弟仓库中已经记录了哪些主题。
2. 对于可能与您要构建的内容重叠的任何主题,请调用`resolve_concern(concern)`以查找现有的决策和被拒绝的替代方案,然后再提出新的建议。
3. 一旦您找到相关的仓库+功能,请调用`query_context(repo_name, feature_id)`以读取其完整的决策历史记录。
在编写架构文档、设计提案或重要的新代码之前执行此操作 - 而不是之后。如果`resolve_concern`显示了一个被拒绝的替代方案与您的计划相符,请将其视为一个强烈的信号,重新考虑,而不是仅仅作为一个数据点,顺便提及。
```
这样做是因为`CLAUDE.md`在每个Claude Code会话开始时都会自动读取 - 指令到达每个代理调用,无需依赖任何个别开发人员的提示。如果您的团队使用[nWave](https://github.com/nWave-ai/nWave),则此功能与现有的`## Development Paradigm`约定自然配对。
---
## 设计原则
- **实时读取,无缓存** - 每个工具调用都从磁盘实时读取。您的文档编辑后,立即在下一个查询中可见,无需重启服务器(ADR-004)。
- **仅结构化错误** - 所有故障模式都返回四种已文档化的JSON格式之一。原始异常永远不会到达代理。
- **功能核心/命令式外壳** - 纯粹的分类和格式化逻辑(`src/core/`)使用内存固定测试完全测试;只有`src/shell/`与文件系统和MCP传输接触。
- **只读** - LoreMCP永远不会写入任何仓库。它是一个只读镜头,而不是写入路径。
---
## 开发
```bash
npm install
npm test # vitest, 442 tests
npm run typecheck
npm run check:arch # dependency-cruiser: core must not import shell
npm run test:mutation # stryker, ≥80% kill rate gate
```
---
## 发布
发布到npm的操作是有意手动的(CI中没有npm token - 见`.github/workflows/ci.yml`对此权衡的评论)。每次发布都遵循此顺序:
1. 将功能/修复PR合并到`main`。
2. 在`main`上:增加版本号(`npm version patch|minor|major --no-git-tag-version`),匹配[semver](https://semver.org/)的更改 - 新增公共MCP工具为`minor`,错误/文档修复为`patch`。
3. 在本地运行完整的检查:`npm run build && npm test && npm run check:arch`。
4. 提交版本号增加(`chore: bump version to X.Y.Z`)并推送到`main`。
5. 发布:`npm publish --access public`(需要OTP/2FA)。
6. **标记和发布** - 这是很容易忘记的步骤,所以这里明确说明:
```bash
git tag -a vX.Y.Z -m "vX.Y.Z"
git push origin vX.Y.Z
gh release create vX.Y.Z --title "vX.Y.Z — <one-line summary>" --notes "<what changed, why, link to the PR>"
```
每个发布的npm版本都应具有匹配的git标签和GitHub Release - 发布说明是更改日志,一次编写,而不是从PR历史记录中重建。
---
## 许可证
MIT