内容
# `@samchon/graph`

[](https://github.com/samchon/graph/blob/master/LICENSE) [](https://www.npmjs.com/package/@samchon/graph) [](https://www.npmjs.com/package/@samchon/graph) [](https://github.com/samchon/graph/actions?query=workflow%3Atest)
`@samchon/graph` 是一个 MCP 服务器,为 AI 代理提供代码图谱代替源代码文件。
它将 16 种语言的代码库索引到声明及其关系的图谱中,并通过单个工具回答代理的代码问题。编译器拥有的提供程序在可用时提供语义边,语言服务器,然后是单独打包的 `@samchon/graph-sitter` 的尽力回退。
通常,编码代理通过 grep 仓库和读取文件到上下文来回答代码问题,而这种读取大部分是 token 账单。图谱消除了这种需求,它自己的答案保持很小:它们携带名称、签名、关系和源代码跨度,从不携带文件正文。
由于交换的双方都没有随着仓库的增长而增长,成本在每种情况下都减少了类似的比例,在每个代码库上 - 对于一个信任图谱结果的代理来说。 codex/gpt-5.4-mini 就是这样;参见下面的 [基准测试](#benchmark) 部分,了解模型不信任图谱结果并在图谱调用后仍然读取的代码。
## 快速入门
### MCP 服务器
```bash
npm install -D @samchon/graph
```
```json
{
"mcpServers": {
"samchon-graph": {
"command": "npx",
"args": ["-y", "@samchon/graph"]
}
}
}
```
从项目根目录启动客户端。服务器构建一个常驻图谱,并从内存中回答每个 MCP 调用。如果没有安装语言服务器,则内置的静态索引器直接解析源代码;每种语言的索引大约需要 1-2 秒,即使在大型仓库中也是如此。
### 语言服务器
语言服务器使用语义解析的边来改进图谱。 为您的技术栈安装它们;不会自动提供任何内容,而已安装的编辑器(如 VS Code)不会公开 stdio 语言服务器:
| 语言 | 服务器 | 安装 |
|---|---|---|
| TypeScript | `ttscgraph` / `ttscserver` | `npm i -D ttsc@^0.20.1 typescript` |
| Python | `pyright-langserver` | `npm i -D pyright` |
| Go | `gopls` | `go install golang.org/x/tools/gopls@latest` |
| Rust | `rust-analyzer` | `rustup component add rust-analyzer` |
| C / C++ | `clangd` | LLVM 发布版,或您的包管理器 |
| Java | `jdtls` | Eclipse JDT LS(需要 JDK 21+) |
| C# | `csharp-ls` | `dotnet tool install -g csharp-ls` |
| Kotlin | `kotlin-language-server` | fwcd/kotlin-language-server |
| Swift | `sourcekit-lsp` | 随 Swift 工具链附带 |
| Scala | `metals` | `cs install metals` |
| Zig | `zls` | zigtools/zls |
| Ruby | `ruby-lsp` | `gem install ruby-lsp` |
| PHP | `intelephense` | `npm i -D intelephense` |
| Lua | `lua-language-server` | LuaLS/lua-language-server |
| Dart | `dart` | 随 Dart SDK 附带 |
每个服务器必须位于 `PATH`。如果某个文件的语言没有服务器,则该语言会自动回退到静态索引器。
## 基准测试
每个仓库都使用无头代理运行每个臂(`baseline` 无 MCP,`@samchon/graph`,`codegraph`,`codebase-memory`,`serena`)在两个提示家族上,跨两个代理 CLI(`codex` 和 Claude Code)。语料库固定了 13 个仓库,每个语言一个,代表 codegraph 自己的评估套件,可以在基准测试主机上使用完整的语言服务器索引运行。
### 入职
每个仓库都被问到相同的入职问题。每个安装工具的臂接收相同的工具中立提示;基准测试仅接收参考工具包使用的相同检查接地规则。
> 我是这个代码库的新手,需要在进行第一次行为更改之前进行实际的代码遍历。
>
> 找到中央运行时流,从公共 API 跟踪到执行工作的代码,并显示附近的代码路径和测试,我应该接下来阅读。
<details>
<summary><code>codex</code> · <code>gpt-5.4-mini</code> — 中位数 token 减少 96%(codegraph 66%,serena 11%)</summary>

</details>
### 专用
`codegraph` 自己的每个仓库问题,原样:
| 项目 | 语言 | 提示 |
|---|---|---|
| [excalidraw](https://github.com/excalidraw/excalidraw) | TypeScript | Excalidraw 如何渲染和更新画布元素? |
| [gin](https://github.com/gin-gonic/gin) | Go | Gin 如何通过其中间件链路由请求? |
| [flask](https://github.com/pallets/flask) | Python | Flask 如何将请求调度到视图函数? |
| [tokio](https://github.com/tokio-rs/tokio) | Rust | Tokio 如何在其运行时调度和运行异步任务? |
| [gson](https://github.com/google/gson) | Java | Gson 如何将对象序列化为 JSON? |
| [redis](https://github.com/redis/redis) | C | Redis 如何解析和调度客户端命令? |
| [leveldb](https://github.com/google/leveldb) | C++ | LevelDB 如何通过其存储引擎读取和写入键? |
| [sinatra](https://github.com/sinatra/sinatra) | Ruby | Sinatra 如何将请求匹配到路由处理程序? |
| [slim](https://github.com/slimphp/Slim) | PHP | Slim 如何通过其中间件处理请求? |
| [serilog](https://github.com/serilog/serilog) | C# | Serilog 如何将日志事件路由到其接收器? |
| [koin](https://github.com/InsertKoinIO/koin) | Kotlin | Koin 如何解析和注入依赖项? |
| [lualine](https://github.com/nvim-lualine/lualine.nvim) | Lua | lualine 如何组装和渲染其状态栏部分和组件? |
| [darthttp](https://github.com/dart-lang/http) | Dart | http 包如何发送请求并生成响应? |
<details>
<summary><code>codex</code> · <code>gpt-5.4-mini</code> — 中位数 token 减少 78%(codegraph 52%,serena 5%)</summary>

</details>
### 索引时间
| 项目 | 语言 | 首次索引 |
|---|---|---|
| [slim](https://github.com/slimphp/Slim) | PHP | 5s |
| [excalidraw](https://github.com/excalidraw/excalidraw) | TypeScript | 5s |
| [gin](https://github.com/gin-gonic/gin) | Go | 15s |
| [leveldb](https://github.com/google/leveldb) | C++ | 16s |
| [darthttp](https://github.com/dart-lang/http) | Dart | 23s |
| [lualine](https://github.com/nvim-lualine/lualine.nvim) | Lua | 25s |
| [flask](https://github.com/pallets/flask) | Python | 55s |
| [gson](https://github.com/google/gson) | Java | 2m22s |
| [sinatra](https://github.com/sinatra/sinatra) | Ruby | 2m35s |
| [redis](https://github.com/redis/redis) | C | 2m50s |
| [tokio](https://github.com/tokio-rs/tokio) | Rust | 3m |
| [koin](https://github.com/InsertKoinIO/koin) | Kotlin | 19m25s |
| [serilog](https://github.com/serilog/serilog) | C# | 未记录 |
每个仓库的一次性成本。服务器仅在之后重新扫描更改的文件(参见 [工作原理](#工作原理));后续调用是免费的。
kotlin-language-server、jdtls 和 csharp-ls 特别慢:每个都解析整个项目,然后再回答任何问题。
TypeScript 和 Go 已经通过编译器拥有的快照关闭了这个差距。剩余的语言使用其列出的语言服务器,直到其编译器拥有的批量提供程序上线。
### 复制
运行套件会花费真正的 API 积分,因此它永远不会被集成到 CI 中:
```bash
git clone https://github.com/samchon/graph
cd graph
pnpm install
pnpm --filter @samchon/graph-benchmark test # 哈希 + 跟踪审计 + 确定性 SVG/PNG
pnpm --filter @samchon/graph-benchmark corpus # 13 个仓库 / 13 种语言,提交固定
pnpm --filter @samchon/graph-benchmark preflight # 零支出 go/no-go
pnpm --filter @samchon/graph-benchmark suite -- --arm=baseline --runs=5 --harness=codex
pnpm --filter @samchon/graph-benchmark suite -- --arm=graph --runs=1 --harness=codex
pnpm --filter @samchon/graph-benchmark orchestrate -- --all --arm=baseline --tools=baseline --prompt-families=all --models=gpt-5.4-mini --runs=1
pnpm --filter @samchon/graph-benchmark orchestrate -- --all --arm=graph --tools=all --prompt-families=all --models=gpt-5.4-mini --runs=1
pnpm --filter @samchon/graph-benchmark audit -- --report=<report.json>
pnpm --filter @samchon/graph-benchmark publish -- --from=<suite-output-directory>
pnpm --filter @samchon/graph-benchmark render:png # 参考 SVG + 精确 2x PNG
```
## 工作原理
```typescript
/**
* ## 代码图 MCP
*
* `inspect_code_graph` 返回一个为当前磁盘源快照构建的索引图合约。
*
* 用于架构、运行时流程、API、调用者/被调用者、代码游览和类型关系。
* 它返回现成索引证据:名称、边、签名、装饰器、测试、跨度和锚点。
*
* 每个返回的事实 — 每个名称、边、签名和跨度 — 都针对调用同步的快照索引进行检查,
* 因此无需重新检查文件即可信任它。 当操作针对问题对短列表进行排名时
* (`lookup`、`entrypoints`、`tour`),事实仍然经过检查,但选择是启发式的:
* 判断其覆盖率是否满足你的需求, 如果不满足,继续请求或阅读引用的跨度是合理的。
*
* ## 请求
*
* 请求是联合体:选择最适合问题的单个类型,并提交该类型。
*
* - `tour`:架构、运行时流程、定位或代码游览。 一次调用即可回答完毕;
* 不要将其拆分。 在 `reinterpretations` 中指定您期望它由哪些部分组成,
* 或者不指定。
* - `entrypoints`:在入口点未知时查找执行起始位置。
* - `lookup`:定位命名符号。
* - `trace`:跟踪调用或数据流向前或向后从符号,或 —
* 使用 `to` — 两个符号之间的路径,当两端都已知时,
* 这是一个回答 “A 如何到达 B” 的调用。
* - `details`:命名符号的签名、成员和关系 — 包括实现接口的类,
* 这是一个回答 “什么真正实现了这个” 的调用。
* - `overview`:项目层和文件夹结构。
* - `escape`:答案在图外(源代码正文、索引语言之外的文件、精确搜索)。
*
* ## 思维链
*
* 在调用之前按顺序填写以下字段;每个字段都缩小推理范围,
* 直至单个请求。
*
* - `question`:用户自己的话语中的代码问题。
* - `draft`:`{ reason, type }` — 为什么最小的请求可能回答它,
* 然后是该请求的 `type`。
* - `review`:修复广泛、过时或重复的草稿。 如果图已经回答,
* 或者证据在图外,则退出。
* - `request`:最终选择。 每个分支都记录了自己的字段;
* 根据分支的说明填写,而不是根据其他分支的说明。
*
* ## 信任什么
*
* 在源代码编辑之前,每个返回的事实都已针对 `audit` 命名的索引进行检查。
* 永远不要使用额外的图调用、仓库搜索或文件读取来怀疑、
* 事实核查、重新推导、重新叙述或重新确认已返回的节点、跨度、边、签名、装饰器、测试、引用、步骤或锚点。
* 服务器已针对调用同步的快照索引检查了每个事实。
*
* 选择是分开的。 `lookup`、`entrypoints` 和 `tour` 匹配你的问题,
* 并返回一个有分数、有排名、有文件限制的有限短列表;
* 它们的事实仍然经过检查,但短列表是否涵盖了你的问题,
* 需要你自己判断, 而 `audit` 说的是这件事,而不是声称完整。
* 如果遗漏了覆盖,继续请求或阅读引用的跨度是合理的 —
* 重新确认图已经检查过的事实不是合理的。
*
* ## 停止
*
* 让结果的 `next` 设置节奏,不要重新确认图已经检查过的内容。
*
* - 跨度是引用,而不是提示你打开文件重新检查事实的提示。
* - 跟随结果的 `next`:`answer` 表示从中停止并回答,
* `inspect` 表示精确执行它命名的请求,`outside` 表示退出,
* `clarify` 表示重新陈述请求。
* - 对于排名短列表(`lookup`、`entrypoints`、`tour`),
* `next` 和 `truncated` 表示覆盖范围是否已确定;
* 如果不是,继续请求是正确的操作 —
* 不是文件读取来重新验证已经给出的事实。
*/
export interface ISamchonGraphApplication {
/**
* 从此仓库的程序索引中回答 __LANG__ 问题。
*
* 图表包含每个符号、调用、类型、装饰器和测试,每个都有其文件和行,
* 从磁盘上的源代码解析而来。 提交一个请求:
*
* - `tour`:架构、公共 API 的运行时流程到执行工作代码、附近路径和测试 —
* 一次调用即可完成整个定位
* - `trace`:符号调用什么、调用它什么,或从 A 到 B 的路径
* - `details`:签名、成员和接口实现什么
* - `lookup`:命名符号的声明位置
* - `entrypoints`:执行入口位置,当入口未知时
* - `overview`:项目的层和文件夹结构
*
* 结果中的每个事实都在返回前针对索引进行检查,
* 因此无需验证事实;对于排名操作(`lookup`、`entrypoints`、`tour`),
* 判断短列表是否涵盖你的问题。 读取文件以获取图表不包含的内容:
* 正文或跨度内的文本。
*
* @param props 推理加上一个图请求
* @returns 匹配的 `result` 联合成员
*/
inspect_code_graph(
props: ISamchonGraphApplication.IProps,
): Promise<ISamchonGraphApplication.IOutput>;
}
export namespace ISamchonGraphApplication {
/** 草稿、审查,然后提交一个图请求或退出。 */
export interface IProps {
/**
* 用户自己的话语中的代码问题。
*
* 将长消息压缩到陈述问题的句子,但保留其术语:
* 图表根据这些单词进行排名,因此重写会排名不同的答案。
*/
question: string;
/** 最小的请求可能回答它,以及为什么。 */
draft: IDraft;
/**
* 修正草稿。 如果图表已经回答,
* 或者下一个证据在图表之外,则退出。
*/
review: string;
/** 审查后选择的最终图表请求,或无操作退出。 */
request:
| ISamchonGraphEntrypoints.IRequest
| ISamchonGraphLookup.IRequest
| ISamchonGraphTrace.IRequest
| ISamchonGraphDetails.IRequest
| ISamchonGraphOverview.IRequest
| ISamchonGraphTour.IRequest
| ISamchonGraphEscape.IRequest;
}
/** 第一阶段计划;`reason` 先于 `type`,因此先写入。 */
export interface IDraft {
/** 这是最小的有用下一步的原因。 */
reason: string;
/** 正在考虑的请求类型。 */
type: IProps["request"]["type"];
}
/** 选定的请求的输出。 `result.type` 映射 `request.type` 。 */
export interface IOutput {
/**
* 服务器在返回结果之前检查的结果对应的索引,
* 用其自己的话语表示。 审计命名了构建当前快照的 LSP、静态或混合索引。
*
* 审计是操作感知的。 对于命名句柄的遍历(`trace`、`overview`),
* 它报告了为命名句柄保留的结构,限定在 `truncated` 处。
* 对于 `details`,它报告了解决的符号的两个部分:
* 它自己的形状完整返回,除非调用者显式限制成员,
* 以及其扇出作为切片,并使用 `trace` 表示其余部分。
* 对于排名操作(`lookup`、`entrypoints`、`tour`),
* 它还表示选择已匹配、评分、排名和限定为问题,
* 因此事实已检查,但短列表覆盖范围由您判断。
*/
audit: string;
/** 对 `result` 的操作:回答、检查一个命名请求或退出。 */
next: ISamchonGraphNext;
/** 匹配提交的 `request.type` 的结果分支。 */
result:
| ISamchonGraphEntrypoints
| ISamchonGraphLookup
| ISamchonGraphTrace
| ISamchonGraphDetails
| ISamchonGraphOverview
| ISamchonGraphTour
| ISamchonGraphEscape;
}
}
```
> [`packages/graph/src/structures/ISamchonGraphApplication.ts`](https://github.com/samchon/graph/blob/master/packages/graph/src/structures/ISamchonGraphApplication.ts)
### 思维链
`question`、`draft` 和 `review` 是必填字段,因此模型将其推理写入调用本身:陈述问题,草拟最小的请求,然后审查草稿。 提示行可以忽略;必填字段不能忽略。
审查允许推翻草稿,而且这比规划更重要。 当像 Claude Code 这样的代理进入具有图表无法回答的问题的工具时,`review` 会立即替换起草的请求,而 `escape` 会完全退出。 错误的输入只需一个小调用即可解决,而不是使会话脱轨。
`question` 只需询问一次,遍历会根据它进行排名。 其 JSDoc 说明了这一点,因为当字符串到达时,它是模型选择写入的内容,而模式是模型在填充字段前读取的唯一文本: *"将长消息压缩到陈述问题的句子,但保留其术语:图表根据这些单词进行排名,因此重写会排名不同的答案。"*
### 精确度而非限制
没有被禁止的内容。 工具描述说明了图表何时适用以及何时停止。 Grep 和文件读取仍然可用,代理在它们是正确操作时仍然使用它们。
保持代理在图表上的原因是精确度。 答案带有名称、签名、边和跨度,由语言服务器解析,因此代理接受它们作为最终答案,而不是用自己的读取重新验证。 并且由于永远不会包含文件正文,大型仓库不会增加响应大小。
### 比较
[`serena`](https://github.com/oraios/serena) 和 [`codegraph`](https://github.com/colbymchenry/codegraph) 与代理对抗:
- 围绕一个图表有十几个工具,因此代理通常选择错误的入口点
- 注入了 100–150 行指令,大部分用于禁止 grep 和文件读取
- 答案中的源代码片段内联,这重新引入了图表旨在消除的读取成本
- 代理不信任的答案结构松散,因此它会回到读取文件来验证它们
- 没有退出方式,因此错误的入口点继续支付工具调用,而不是退出
在这里,相同的策略适合一个键入的合约,通过模式执行而不是用散文恳求。
## 赞助商
[](https://github.com/sponsors/samchon)
感谢您的支持。
您的 [捐赠](https://github.com/sponsors/samchon) 鼓励 `@samchon/graph` 开发。
## 参考
- 动机:[`codegraph`](https://github.com/colbymchenry/codegraph) 的实际使用提高了令牌成本而不是降低了它,并且明显降低了代理推理。
- 前身:[`@ttsc/graph`](https://github.com/samchon/ttsc),TypeScript 原始版本,本项目将其推广;其 [启动帖](https://ttsc.dev/blog/i-made-ts-compiler-graph-mcp/) 分析了为什么早期的图表工具没有减少令牌账单。
- 函数调用工具:[第 1 部分 — 验证反馈](https://dev.to/samchon/qwen-meetup-function-calling-harness-from-675-to-100-3830) 和 [第 2 部分 — CoT 合规](https://dev.to/samchon/function-calling-harness-2-cot-compliance-from-991-to-100-4f0h),用于构建合约的 typia 技术。
- 对比:[`codegraph`](https://github.com/colbymchenry/codegraph) 和 [`serena`](https://github.com/oraios/serena)。
- 协议:[模型上下文协议](https://modelcontextprotocol.io) 和 [语言服务器协议](https://microsoft.github.io/language-server-protocol/)。
- 验证 & MCP 表面:[`typia`](https://github.com/samchon/typia) 和 [`@typia/mcp`](https://github.com/samchon/typia)。
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器