内容
# ts-header-mcp
MCP 服务器生成 TypeScript 源代码的头文件视图,供 AI 编码代理使用:函数、类和类型签名,并带有其原始行号,可按文件、目录或整个项目请求。
```typescript
// ==== src/services/userService.ts — 312 lines, 8 exports ====
export class UserService { // L24-198
constructor(db: Database, cache?: CacheLayer) // L31
getUser(id: UserId): Promise<User | null> // L45
// Fetches a user by ID, checking cache first.
patch(id: UserId, p: Partial<User>): Promise<User> // L69 ⚠ deprecated
}
// -- types: L201-240 --
export type UserId = Brand<string, "UserId">;
export interface User { id: UserId; name: string; email: string; roles: Role[]; }
export function createUserService(cfg: Config): UserService // L245
export function processOrder(o: Ordr): number // L319-321 ⚠ TS2304: Cannot find name 'Ordr'. — type unreliable
```
其理念与 C 头文件相同:代理首先读取紧凑视图,然后仅在需要行号处打开源代码。返回类型来自 TypeScript 类型检查器,因此推断返回类型会明确显示。具有类型或语法错误的源文件仍会生成头文件;不可靠签名会单独标记(`// L319-321 ⚠ TS2304: Cannot find name 'Ordr'`),而不是使整个文件失败。
## 与现有工具的关系
几种现有方法涵盖了部分内容。具体使用哪一种取决于代理和任务;ts-header 针对特定空白区域进行了构建。
- **`tsc --emitDeclarationOnly`** 生成 `.d.ts` 文件,与头文件类似。但它们需要可编译的项目,将文件写入树中,不携带源行号,仅涵盖公共表面。如果您想为库消费者生成构建工件,则 `.d.ts` 是合适的工具;对于导航,尤其是在当前无法编译的代码中,ts-header 更合适。
- **LSP 支持的 MCP 服务器**(Serena、lsmcp、symbols-mcp)将符号查询公开为单独的工具:获取大纲、查找符号、查找引用。它们比 ts-header 更精确、更强大,适用于精确的问题。但是,回答“此代码库中有什么?”需要一系列具有正确参数的工具调用,这对于较强的代理来说很好,而对于较弱的代理来说往往不奏效。ts-header 将该工作流折叠为一个工具,其输出针对请求的路径完整。
- **仓库映射**(Aider 的仓库映射、RepoMapper)生成最重要的符号的单个排名摘要,适合令牌预算。这是一种适合自动上下文注入的格式。但是,它是有损的:未排名的符号被省略,没有办法请求特定文件的完整内容。
ts-header 相对于上述工具的优势在于:
- 完整的按路径输出(无排名省略)及原始行号作为跳转目标
- 一个适用于所有级别的工具:项目概览、目录列表、文件头
- 适用于无法编译的代码,并带有每个符号的错误标记
- 包括按请求导出的非导出和函数本地声明
- 默认情况下不写入文件,因此不会泄漏到版本控制中
- 关注结果并减少工具调用以提高 LLM 注意力
(参见下面的比较表。)
## 工具
一个工具,`ts_header(path, depth?, docs?, max_tokens?, filter?)`。导航深度由路径表示,因此交互模型类似于熟悉的 `ls` / `cat` 模式,而不是一组要选择的工具。
- `path`: 文件或目录,相对于工作区。目录中的目录返回项目概览;目录中的文件返回每个文件的导出列表(带有桶文件检测和 `[test]` 标签);文件返回完整的头文件。`"."` 给出项目概览。还接受文件路径数组或 glob 模式(`"src/**/*.ts"`)用于一次调用中的批量多文件头文件,限制为 20 个文件;令牌预算在批处理中分摊,逐项问题(缺少文件、目录、非 TS)内联报告而不会使其他文件失败。
- `depth`: `exports`(默认)| `all`(添加非导出声明和私有成员)| `deep`(还深入函数体:内部函数、闭包、局部声明的类)。
- `docs`: `none` | `brief`(默认:第一个 JSDoc 句子;在单行签名后显示,在多行声明前显示)| `full`(完整的 JSDoc,包括 `@param` 和 `@throws`)。`@deprecated` 始终显示,无论模式如何。文件顶部的 JSDoc 块被视为文件的描述,而不是第一个声明的描述:它在头文件横幅下呈现,并在文件行的目录列表中作为简短注释。
- `max_tokens`: 近似输出预算,默认 4000。截断的输出会说明并说明如何请求更多。
- `filter`: 仅显示名称与模式(不区分大小写的正则表达式;纯文本也适用)匹配的符号。在每个级别应用,因此 `ts_header(".", {filter: "booking"})` 充当整个项目的轻量级类型符号搜索。筛选器仅名称;函数体内的全文搜索仍然是 grep 的工作。
- `includeImports`: 当为 true 时,头文件以 `// -- imports --` 块开头,列出文件的导入语句,每个导入语句折叠为一行并精简为 120 个字符。默认情况下关闭(导入很少为定位赚取令牌)。
对于 Convex 等框架包装器声明,头文件在签名下添加 `// args:` 行,显示验证器形状(或处理程序的参数列表,如果没有 `args` 属性)。如果该行仅重述已经在检查签名中可见的属性名称,则该行被抑制;如果过长,则整个属性被省略,并带有 `…n more` 而不是在标识符中间剪切。
### 视觉比较:ts-header 与替代品
| 功能 | ts-header | LSP 服务器 | 仓库映射(Aider) | tsc --emitDeclaration |
| --- | --- | --- | --- | --- |
| **保留行号** | **是(Lnn)** | 是(符号) | 否 | 否 |
| **令牌预算感知** | **是** | 否 | **是** | 否 |
| **适用于无法编译的代码** | **是** | 是 | 是 | 否 |
| **一次性项目导航** | **是** | 否(多步骤) | **是**(有损) | 否 |
| **包括私有/本地符号** | **可选** | 是 | 否 | 否 |
## 为什么使用它
通过 grep 和读取整个文件来定位的代理会在噪音上烧掉令牌,并且仍然会错过某些内容。为了衡量差异,我们在大型 monorepo 上运行了相同的查询 — “在此项目中解释 waitlist 队列的工作原理” — 在两个会话中使用相同的 LLM:一个使用 `ts_header`,另一个不使用。
| 维度 | 无 `ts_header` | 使用 `ts_header` |
| --- | --- | --- |
| **初始发现策略** | 无过滤的 `grep_search("waitlist")`(200 个匹配) | 结构化的 `ts_header` 目录扫描和筛选 |
| **模块覆盖** | 找到 4 个关键文件;遗漏 2 个 | 找到所有 5 个与 waitlist 相关的文件 |
| **工具执行效率** | 试错 grep + 全文件查看 | 目录概览 → 筛选签名 → 目标行视图 |
| **解释完整性** | 扎实的概览,遗漏两个入口 | 完整的端到端跟踪,包括管理员发布和后台通知 |
使用 `ts_header` 的会话更加高效(索引驱动的发现而不是试错 grep),并且更加完整(它找到了另一个会话忽略的入口)。完整的会话间分解在 [docs/case-study.md](docs/case-study.md) 中。
## 安装
需要 Node 22+ 和 [pnpm](https://pnpm.io)。
```bash
git clone https://github.com/trophygeek/ts-header-mcp.git ~/tools/ts-header-mcp
cd ~/tools/ts-header-mcp
pnpm install
pnpm test # 静默单元测试(提取器、格式化器、路由器)
pnpm run smoke-test # 详细:打印完整的示例头文件供仔细检查
pnpm run build # -> dist/server.js 和 dist/cli.js
```
将服务器克隆到工作存储库之外(例如 `~/tools`),以防止其被提交到项目的版本控制中。
注意 TypeScript 6.0+:编译器不再自动包含 `node_modules/@types` 中的包,因此项目 tsconfig 显式设置 `"types": ["node"]`。如果您在 `pnpm run build` 期间看到 `TS2591: Cannot find name 'process'`,则缺少该行。
## CLI 用法
对于非 MCP 集成或命令行脚本,您可以直接从终端运行 CLI。
```bash
# 使用 node 运行
node dist/cli.js <workspaceRoot> <path> [options]
# 或通过 ts-header-cli 命令(如果安装/链接)
ts-header-cli <workspaceRoot> <path> [options]
```
### 选项
* `--depth=exports|all|deep`: 要提取的声明详细程度。
* `--docs=none|brief|full`: JSDoc 详细程度。
* `--max-tokens=N`: 近似令牌预算限制。
* `--filter=PATTERN`: 按名称筛选符号的正则表达式模式。
输出写入 `stdout`,错误写入 `stderr`(成功时退出代码 `0`,错误时退出代码 `1`)。
## 客户端设置
服务器使用 stdio 进行通信。第二个 `args` 项是它所服务的工作区;如果省略,则使用进程工作目录。
### VS Code(Copilot 代理模式)
在工作区中创建 `.vscode/mcp.json`(此文件可以安全提交)或从命令面板运行 `MCP: Open User Configuration` 以进行用户级配置。注意根键是 `servers` 而不是 `mcpServers`,并且支持 `${workspaceFolder}`:
```json
{
"servers": {
"ts-header": {
"type": "stdio",
"command": "node",
"args": ["/home/you/tools/ts-header-mcp/dist/server.js", "${workspaceFolder}"]
}
}
}
```
MCP 工具仅在 Copilot 的 Agent 模式下可用(聊天视图中的模式下拉菜单)。如果服务器行为异常,`MCP: List Servers` → 选择它 → 显示输出会显示其 stderr。
### Cursor
在项目中创建 `.cursor/mcp.json` 或 `~/.cursor/mcp.json` 以适用于所有项目。Cursor 使用 `mcpServers` 根键;使用绝对路径:
```json
{
"mcpServers": {
"ts-header": {
"command": "node",
"args": ["/home/you/tools/ts-header-mcp/dist/server.js", "/path/to/your/workspace"]
}
}
}
```
在 Cursor 设置 → MCP 下启用服务器(如果它没有自动出现)。对于全局配置服务多个项目,请为每个工作区添加一个条目(例如 `ts-header-projA`、`ts-header-projB`)。
### Google Antigravity(2.x)
共享配置为 `~/.gemini/config/mcp_config.json`(2.0 之前的安装使用 `~/.gemini/antigravity/mcp_config.json`)。您可以在 IDE 中从内部打开正确的文件:代理面板 `…` 菜单 → MCP 服务器 → 管理 MCP 服务器 → 查看原始配置。将条目合并到现有的 `mcpServers` 对象中(与 Cursor 示例相同,绝对路径,不含 `~` JSON),然后在设置 → 自定义化 → 已安装的 MCP 服务器下刷新。
<details>
<summary>提示 Antigravity 的代理为您设置</summary>
替换占位符并粘贴到代理面板:
```
请为我设置一个名为 ts-header 的本地 MCP 服务器。按照以下步骤执行,并确保每个步骤正确,然后再继续下一步。不要跳过测试步骤。
来源:https://github.com/trophygeek/ts-header-mcp.git
它将服务的 WORKSPACE:<PATH_TO_MY_TS_PROJECT>
1. 预检:
运行 `node -v` 以确保我的环境有 Node.js 22 或更高版本。
如果版本较低,请立即停止并说明需要 Node 22+。还要确认 pnpm 可用(`pnpm -v`);如果不可用,请运行 `corepack enable`。
2. 安装位置:
将源代码克隆到 ~/tools/ts-header。永远不要复制到我的当前
工作区;不得将此设置提交到我的任何存储库中。
3. 构建和测试:
cd ~/tools/ts-header
pnpm install
pnpm test # 单元测试:必须以“fail 0”结束
pnpm run build # 生成 dist/server.js
如果测试失败,请停止并显示完整的输出。不要修改源
以使测试通过而不告诉我您更改了什么以及原因。
4. 注册服务器:
查找我的 MCP 配置: ~/.gemini/config/mcp_config.json 在当前 Antigravity
版本(较旧的安装使用 ~/.gemini/antigravity/mcp_config.json ...使用
哪一个存在;如果两者都存在,请使用 IDE 通过
代理面板“…”菜单 > MCP 服务器 > 管理 MCP 服务器 > 查看原始配置)。
将以下条目合并到现有的“mcpServers”对象中。不要
覆盖或删除文件中已有的任何服务器。显示我更改的配置差异
之前保存。
"ts-header": {
"command": "node",
"args": ["<ABSOLUTE HOME PATH>/tools/ts-header/dist/server.js",
"<WORKSPACE IT WILL SERVE>"]
}
使用真正的绝对路径(JSON 内不含 ~)。
5. 激活和验证:
刷新 MCP 服务器(设置 > 自定义 > 已安装的 MCP 服务器 >
刷新,或重启 IDE)。确认“ts-header”出现并带有 1 个工具,
ts_header。如果服务器启动失败,请手动运行
node ~/tools/ts-header/dist/server.js <WORKSPACE> 并捕获 stderr,
并在我更改任何内容之前向您显示它。
6. 烟雾测试工具,通过调用它三次并显示每个输出:
ts_header(".") -> 项目概览
ts_header("<some src directory>") -> 每个文件的导出列表
ts_header("<one .ts file from that list>") -> 带 // L45 数字的签名
7. 从现在开始,在此工作区:当您需要了解 TypeScript 代码时,
先调用 ts_header 目录或文件,然后仅在它报告的特定行号处打开源文件。
不要为定位而读取整个 .ts 文件。将此规则添加到您的项目规则/内存中
如果您支持的话。
请报告安装路径、您编辑的配置文件、配置差异、
测试结果和三个烟雾测试输出。
```
</details>
### 其他客户端(HTTP 桥)
对于无法启动_stdio 服务器的客户端,`http-server.mjs` 包装相同的路由器并在本地 HTTP 上提供纯 JSON )。一个示例集成位于 [`mirica-tool/`](mirica-tool/README.md)。
## 教你的代理如何使用它
注册服务器只是设置的一半。没有明确的指令,代理倾向于回落到读取整个文件进行定位。在您的项目代理说明文件(`AGENTS.md`、`.cursorrules`、`CLAUDE.md` 或等效文件)中添加一条规则:
```markdown
# TypeScript 项目分析
- 分析 TypeScript 项目时,始终先调用 `ts_header` 工具
获取文件和目录结构,而不是读取整个源文件。
- 仅在 `ts_header` 报告的特定行号处打开源文件。
```
在现场测试中,这条规则是使用该工具的一致性和忽略它的区别。
## 文件、缓存和沙盒
默认情况下,服务器不执行磁盘写入;所有缓存都在内存中,它在只读沙盒中运行。编译器选项被 `noEmit` 和 `incremental: false` 覆盖,因此具有 `incremental: true` 的工作区 tsconfig 不会导致 `.tsbuildinfo` 文件出现在您的存储库中。有一个回归测试用于该用例。
持久缓存通过 `TS_HEADER_CACHE=1` 作为可选功能启用。其位置按顺序解析:`TS_HEADER_CACHE_DIR`,然后 `$XDG_CACHE_HOME/ts-header`,然后 `os.tmpdir()/ts-header`。每个候选者都通过启动时写入探测;如果都不可写,服务器会记录一行并继续仅使用内存缓存。如果您故意将缓存放在工作区内,则写入一个 `.gitignore` 文件,内容为`*`。
目录列表尊重工作区根目录 `.gitignore`(通用子集:`*`、`?`、`**`、否定、目录模式)上的内置跳过列表(`node_modules`、`dist`、`.git` ...)。嵌套的 `.gitignore` 文件不读取。直接访问被忽略的文件仍然有效;过滤器仅适用于列表。
其他环境变量:- `TS_HEADER_GITIGNORE=0`: 禁用列表中的 `.gitignore` 处理
- `TS_HEADER_DOCS=none|brief|full`: 服务器范围内的 `docs` 选项默认值,用于测试 `docs` 摘要是否值得您的代理获取令牌
- `TS_HEADER_DENSE_MIN`: 声明块的分组阈值,默认为 6 源行数
- `TS_HEADER_MAX_PROJECTS`: 语言服务 LRU 大小,monorepo 默认 4
## 架构
`server.ts`(MCP 层,唯一导入 SDK 的模块)和 `cli.ts`(CLI 入口点)→ `router.ts`(路径 → 项目概览 | 目录列表 | 文件头文件,加上内容哈希缓存)→ `formatter.ts`(所有布局规则)← `FileHeaderModel`(`model.ts` 中的纯 JSON 合同)← `extractor.ts`(原始 TypeScript 编译器 API)← `project.ts`(最近的 tsconfig 发现,一个长期存在的 `ts.LanguageService` per config,项目引用源折叠,LRU 淘汰)。提取器位于 `FileHeaderModel` 合同下,因此可以通过替换它(例如 tree-sitter 实现)而语)← `extractor.ts`(原始 TypeScript 编译器 API)← `project.ts`(最近的 tsconfig 发现,单个长期 `ts.LanguageService` 每配置,项目引用源折叠,LRU 淘汰)。`ts-header-design.md` 包含设计原理和决策日志。
## 待办事项和下一步计划
大致按照优先级顺序。前两项来自原始设计文档(参见 `ts-header-design.md` §12);其余项是在对真实 monorepo 进行实地测试期间积累的。
1. **基于预算的树深度**。项目概览当前仅显示一个目录级别。更好的是,在令牌预算允许的情况下,展开子目录,首先折叠最大的子树,这样深度就不再受固定常数的限制,而是取决于 `max_tokens`。
2. **解决方案构建器项目引用**。Monorepo 引用通过将引用项目的源文件折叠到一个程序中来处理 - 正确,但在大工作区中,程序会变得很大。使用编译器的解决方案构建器机制可以保持每个包的程序彼此独立。
3. **文件监视器失效**。目前,新鲜度是每次请求的 mtime 检查(正确,但对大项目来说,`stat` 调用次数过多)。基于 `fs.watch` 的失效器将使重复目录列表更加便宜。
4. **多工作区服务**。服务器在启动时提供给定的单个工作区;每个项目一个配置项是变通方法。通过调用路径或客户端 `cwd` 解析工作区,将允许一个注册服务于所有内容。
5. **`docs:"auto"`**。仅当它在符号名称之外添加信息时,才包含简短的文档句子(跳过 `fetchUser` 上的“获取用户”)。需要一个能优雅失败的启发式算法;依赖于上面的评估来确定它是否重要。
6. **机器可读输出**。对于希望进行后处理而不是读取的编排器,`FileHeaderModel` 的可选 JSON 变体。该模型内部已经是纯 JSON;这主要是 `format` 参数。
7. **嵌套 `.gitignore` 文件**。目前只读取工作区根目录下的 `.gitignore`;每个目录的忽略文件是 `src/ignore.ts` 的直接扩展。
8. **Vue/Svelte SFC 脚本块**。从 `<script lang="ts">` 部分提取。优先级较低,除非目标代码库需要它。
9. **重载改进**。重载链紧密渲染,但实现签名(在 TS 中不可调用)仍然与声明重载一起出现;`.d.ts` 约定将隐藏它,同时保持其在链上的 L 范围。
刻意不涉及的范围:编辑/重构(只读工具)、函数体内的全文搜索(grep 可以更好地完成此任务)和重要性排名(按照设计,标头是完整的;排名摘要是 Aider-repo-map 领域)。
## 状态和测试
- `pnpm test` 运行单元测试套件(`test/unit/`,Node 内置测试运行器通过 tsx,66 个测试):格式化器测试是纯函数测试,针对手动构建的模型(注释、文档模式、密集块分组、错误横幅、截断、TOC 布局);提取器测试构建一个程序,针对共享夹具进行模型结构断言(深度语义、推断返回类型、重载、JSDoc 提取、诊断附件、桶检测);路由器测试在 OS 临时目录中构建一个临时工作区,涵盖所有三个导航级别、`filter` 参数、`.gitignore` 处理、防护轨和零写入不变性(包括带有 `incremental: true` tsconfig 的情况)。Convex 形状的夹具保护了在实地测试中发现的框架代码回归:大型 `export const x = framework({...})` 声明保留其自己的行注释,渲染类型长度上限,带有 `import("...")` 修饰符剥离。
- `pnpm run smoke-test` 故意冗长:它为夹具在两个深度/文档组合上打印完整的渲染标头,供人类审查输出格式,然后是一组汇总断言。
- `server.ts` 针对 `@modelcontextprotocol/sdk` ^1.x。它是在没有注册表访问的环境中编写的,因此 SDK 连线是测试套件未执行的唯一部分;它下面的所有内容都在 `--strict` 下执行和类型检查。
已知限制被跟踪为上述待办事项 2 和 3。 此外,设计文档描述了对代理错误文件读取的系统评估,有和没有工具;[docs/case-study.md](docs/case-study.md) 中存在非正式比较,但该评估尚未运行。
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器