关于 tieline
tieline 静态比对前端 API 调用与后端路由,发现路径和方法不一致,无需运行两端。它适合希望在 CI 中加入确定性契约检查的团队,也可检查代码与 OpenAPI 文档的差异。
主要功能
- 01静态匹配前后端路由
- 02检测漂移、无法验证项和孤立路由
- 03支持所列客户端与服务端适配器
- 04CI 失败门禁及 JSON/HTML 报告
- 05通过 doctor 检查代码与 OpenAPI
适用场景
- 01在 CI 中发现前端调用不存在的后端路由
- 02找出没有前端调用到达的后端路由
- 03核对实现路由与 OpenAPI 文档
MCP 相关
其 MCP 服务提供 5 个工具,用于检查、列出和查看路由映射、比较代码与 OpenAPI 文档,以及初始化配置。结果由与 CLI 相同的确定性引擎生成。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
5收录的工具列表 · 更新于 3 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| config | string | 否 | tieline.config.json 的路径。默认从服务器工作目录向上搜索。 |
详细介绍
tieline
静态前端↔后端契约漂移检查器。无需编写任何契约测试,也能实现 Pact 的效果。

tieline 会读取你在 API 边界两侧已经编写的代码——前端发出的 HTTP 调用和后端公开的路由——并指出它们不一致的地方。无需编写契约测试,无需运行 broker,也无需启动后端。它能在不到一秒的时间内完成检查,并且专为在 CI 中作为门禁运行而设计。
即使删掉大模型,开发者仍会安装它。
tieline首先是一个确定性工具;Agent 读取其输出只是额外福利。
工作原理
frontend code backend code
(axios, rtk-query, …) (express, nestjs, openapi, …)
│ │
client adapter server adapter
│ normalize ${id} :id {id} → {} │
└───────────────► join on (METHOD, path) ◄──────┘
│
✅ matched ❌ drift ⚠️ unverifiable 🟡 dead
两侧的数据都会归一化为 (METHOD, path),然后进行匹配。匹配器与适配器无关——任意客户端适配器都能与任意服务端适配器配对,因此同一个引擎可以检查 React 应用与 Express、Angular 应用与 Spring 的匹配情况,也可以将任何应用与 OpenAPI 规范进行比对。
| 结果 | 含义 |
|---|---|
| ✅ 匹配 | FE 调用对应到真实的 BE 路由 |
| ❌ 漂移 | FE 调用能够解析,但 BE 中没有对应的路由或方法——问题所在 |
| ⚠️ 无法验证 | FE URL 在运行时构建——会报告,但绝不猜测 |
| 🟡 未使用 | 没有可解析的 FE 调用访问该 BE 路由(仅供参考) |
tieline 与替代方案
这些工具解决的是相近的问题——根据你现有的条件和希望获得的保证来选择。
| 工具 | 工作原理 | 能发现的问题 | 需要什么 | 适用场景 |
|---|---|---|---|---|
| tieline | 静态分析 FE 调用位置和 BE 路由声明,并根据 (METHOD, path) 进行匹配 | 前端调用了后端未公开的路由(路径或方法漂移)、未记录或虚构的规范路由 | 两侧的源代码;无需运行任何服务,也无需编写任何内容 | 你希望在 CI 中进行亚秒级检查,且不必编写或维护契约测试 |
| Pact | 在运行时执行消费者驱动的契约测试,并通过 broker 共享 | 特定消费者–提供者组合之间的请求/响应负载不匹配 | 两侧都要编写契约测试、Pact broker,以及提供者验证构建 | 独立团队需要负载级保证和“能否部署”工作流 |
| openapi-diff | 比较两份 OpenAPI 文档 | 两个规范版本之间的破坏性变更 | 两个版本都要有准确的规范;不会读取源代码 | 你的 API 采用规范优先模式,并且希望对规范变更设置门禁 |
| Optic | 持续跟踪 OpenAPI 规范,并在 CI 中比较每次变更 | 规范历史中的破坏性变更和风格/标准违规 | 仓库中维护的 OpenAPI 规范 | 你需要管理不断演进的规范,并希望审核每个 PR 中的 API 变更 |
| Schemathesis | 针对 OpenAPI/GraphQL 架构,对运行中的 API 进行基于属性的模糊测试 | 服务端崩溃、架构违规、运行时未记录的响应 | 可启动的后端和架构 | 你希望对实现进行运行时一致性和稳健性测试 |
这些工具可以组合使用:tieline 在每个 PR 中静态捕获 FE↔BE 漂移,tieline doctor
确保代码与规范保持一致,而 Pact 或 Schemathesis 这类运行时工具则可以守护底层的
负载/行为层。
快速开始
安装(或使用 npx 运行):
npm install -g @nugehs/tieline
# or, from a clone: git clone … && cd tieline && npm link
生成 tieline.config.json — init 会检查周边目录(当前工作目录、其子目录和同级目录),识别已知技术栈并写入可直接运行的配置:
tieline init
tieline · init
scanning ~/code for repos…
✔ client: rtk-query → web (roots: src/redux/apis)
✔ server: nestjs → api (roots: src)
📝 wrote tieline.config.json
它会从 package.json 依赖项(@reduxjs/toolkit、axios、@angular/core、@nestjs/core、express、fastify、next)、requirements.txt / pyproject.toml(fastapi、flask)、pom.xml / build.gradle(spring)中检测适配器,并在上述方式都未检测到时使用任意 OpenAPI 文档作为后备。无法检测到的内容会写为占位符,供你编辑。该文件总是会被覆盖,因此每当目录结构发生变化时,都要重新运行。
也可以手动编写 — 放在仓库根目录或其上层目录:
{
"client": { "adapter": "rtk-query", "repo": "../web", "roots": ["src/redux/apis"], "basePath": "/api/v1" },
"server": { "adapter": "nestjs", "repo": "../api", "roots": ["src"], "globalPrefix": "api/v1" },
"failOn": ["drift"]
}
运行:
tieline check
tieline · contract check
❌ 2 drift (FE calls a route the backend does not expose)
GET /users/{}
getUser · web/src/redux/apis/user-api.ts:42
→ did you mean "user/{}"? # plural vs singular — a guaranteed 404
PUT /orders/{}
updateOrder · web/src/redux/apis/order-api.ts:88
→ path exists but as GET, not PUT # method mismatch
✅ 274 matched ❌ 2 drift ⚠️ 6 unverifiable 🟡 31 unused backend routes
如果任一 failOn 类别不为空,check 就会以非零状态码退出 — 将其加入 CI,当两端不一致时,构建就会失败。
命令
tieline init # auto-detect nearby repos and write tieline.config.json
tieline check # FE↔BE drift; exits non-zero on drift (the CI gate)
tieline list # the full resolved contract map (every endpoint + status)
tieline orphans # backend routes no frontend call reaches
tieline doctor # code↔spec drift (see below)
| 标志 | 效果 |
|---|---|
--config <path> | tieline.config.json 的路径(默认:从当前工作目录向上查找) |
--json | 机器可读的输出 |
--html <file> | 独立的可视化报告(参见可视化报告) |
--no-fail | 始终退出码为 0(仅生成报告) |
支持的技术栈
任意客户端适配器都可以与任意服务端适配器配对 — 匹配器始终不变。
| 客户端(调用) | 服务端(路由) |
|---|---|
rtk-query — Redux Toolkit Query | nestjs — 装饰器 |
axios-fetch — axios / fetch、React Query 和 SWR 的 queryFn | express — app.use() 挂载图,跨文件 |
angular-http — Angular HttpClient | fastify — 动词简写 + route({}) |
next — 基于文件(app router + pages API) | |
fastapi — APIRouter 前缀 + include_router | |
flask — 蓝图 + methods=[] | |
spring — @RequestMapping + @*Mapping | |
openapi — 通用:任意 OpenAPI 2/3 文档(文件或 URL) |
这涵盖了 MERN(rtk/axios ↔ express)、MEAN(angular ↔ express)、MEVN(axios ↔ express)、Next 全栈、Python(fastapi/flask)和企业级(angular ↔ spring)— 还包括适用于任何能生成规范的后端的 openapi(Express+swagger-jsdoc、FastAPI、Spring springdoc、.NET Swashbuckle,……)。
说明:
express会跨越require/import边界遍历app.use()挂载图和嵌套路由器;无法访问的路由器会被标记,绝不会被丢弃。next使用文件系统路由 — app-router 文件导出GET/POST/…;pages-router 处理程序可服务任意动词(匹配为ALL)。- 运行时构建的 URL(例如
`users/${id}?x=${q}`)会标记为无法验证,而不会进行猜测。
配置
tieline.config.json — 仓库路径相对于配置文件解析。
{
"client": {
"adapter": "rtk-query", // rtk-query | axios-fetch | angular-http
"repo": "../web",
"roots": ["src/redux/apis"], // dirs to scan for call sites
"basePath": "/api/v1" // stripped from call sites before matching
},
"server": {
"adapter": "nestjs", // nestjs | express | fastify | next | fastapi | flask | spring | openapi
"repo": "../api",
"roots": ["src"],
"globalPrefix": "api/v1", // stripped from routes before matching
"spec": "openapi.json" // openapi adapter & `doctor` only — file path or URL
},
"ignore": ["internal/.*"], // regexes on the normalized path
"failOn": ["drift"] // buckets that make `check` exit non-zero
}
可视化报告
tieline check --html report.html 会生成一个独立文件(内联 CSS/JS,无外部资源),你可以在任意浏览器中打开,或附加到 PR:
- 契约流向图 — 前端资源在左,后端在右,弯曲连线以绿色(匹配)/红色(偏差)标示,并包含一个用于接收未能命中任何路由的调用的
∅ no route节点;悬停在资源上可高亮其连线 - 健康度圆环、摘要卡片,以及可实时筛选的偏差 / 无法验证 / 未使用表格
tieline doctor — 你的代码与已发布文档是否一致?
doctor 会比较从源码解析的路由(如原生适配器 nestjs)与 OpenAPI 规范(server.spec)中声明的路由:
tieline · doctor code (nestjs) ↔ spec (http://localhost:9999/doc-json)
❌ 4 undocumented (in code, missing from the published spec)
GET /billing/invoices src/billing/billing.controller.ts:54
POST /webhooks/stripe src/webhooks/webhooks.controller.ts:21
...
👻 1 phantom (in the spec, no matching route in code)
✅ 312 agree ❌ 4 undocumented 👻 1 phantom (316 code routes, 313 spec routes)
- 未记录 — 可正常工作的路由,但对任何根据该规范生成 SDK 或合作伙伴集成的人来说都不可见。
- 虚构路由 — 规范承诺提供某个路由,但代码已不再提供(文档过时)。
同时运行它和 check,你的规范就绝不会在不知不觉中偏离代码。
用作 MCP 服务
tieline 提供了一个 MCP 服务,让 Agent 可以询问“这两个仓库现在是否仍然一致?”,并获得与 CLI 生成的相同结构化结果——分析不是由大模型完成的,而是由确定性引擎完成的。它仍然是零依赖:服务采用手写的 stdio JSON-RPC,没有使用 SDK。
将其注册到任意 MCP 客户端(Claude Code、Claude Desktop 等):
{
"mcpServers": {
"tieline": { "command": "npx", "args": ["-y", "-p", "@nugehs/tieline", "tieline-mcp"] }
}
}
或者,如果是全局安装(npm i -g @nugehs/tieline),只需设置 "command": "tieline-mcp"。
它提供五个工具,每个工具都返回 JSON:
| 工具 | 参数 | 返回内容 |
|---|---|---|
tieline_check | config? | 总计数 + drift + unverifiable(漂移门禁) |
tieline_list | config? | 完整解析后的契约映射 |
tieline_orphans | config? | 没有前端调用到达的后端路由 |
tieline_doctor | config? | undocumented + phantom(代码 ↔ 规范) |
tieline_init | cwd? | 自动检测附近的仓库并写入配置 |
config 默认从服务的工作目录开始向上搜索,与 CLI 完全相同——因此,Agent 在含有 tieline.config.json 的仓库中启动后,只需调用 tieline_check 即可。
架构
两侧各自实现一个提取器;之后的所有处理都由双方共享。
ClientAdapter.extract() → Endpoint[] { method, rawPath, resolvable, file, line }
ServerAdapter.extract() → Route[] { method, rawPath, file, line }
新增一种框架只需新增一个适配器(约 80 行)——归一化器、匹配器、报告生成器和 CLI 都无需更改。基于路径是否存在的漂移检测现已提供;OpenAPI DTO 结构差异比较(--deep)以及 SARIF/PR 注释已列入路线图。
测试
npm test # node --test — zero dependencies, nothing to install
使用 Node 内置测试运行器运行的 71 项测试:
- normalize — 覆盖所有参数语法(
${id}/:id/<int:id>/[id]/{id})、 查询参数剥离、basePath、路径拼接 - matcher — 覆盖全部四种类别、漂移提示(method-mismatch、“你是否想找”)、
ignore、ALL/ANY任意动词路由、跨语法参数匹配 - adapters — 使用 fixture 测试每个客户端和服务端适配器,并通过临时仓库测试边缘情况
(Express
app.all+ 未挂载的路由器、Next 路由组 + catch-all、 Spring@RequestMapping(method=…)、Flask 默认 GET、运行时 url → unverifiable、忽略非 HttpClient 的.get()) - openapi —
servers[].url前缀、Swagger 2basePath、stripPrefix - doctor — undocumented / phantom / matched + 提示
- init — 技术栈自动检测(node 依赖、Python、Spring、OpenAPI 回退)、 目录名偏好、同级/子级扫描、占位符回退、配置往返验证
- integration — 三项跨技术栈验证(RTK↔Express、Angular↔Spring、
axios↔FastAPI)以及真实 CLI(退出码、
--json、--html、doctor) - mcp — stdio JSON-RPC 服务:握手、
tools/list、对 fixture 执行真实的tieline_check、带内工具错误、method-not-found
路线图
- SARIF 输出 — 在 GitHub PR 上添加行内漂移注释
--deep— 通过 OpenAPI 比较请求/响应的DTO 结构,而不仅仅是路径 (捕获字段重命名或枚举变更——昂贵的 Bug 往往就在这些地方)- 更多适配器 — 为
react-query/swr提供一等客户端支持,为koa/django提供服务端支持 - AST 提取 — 用 AST 替代正则解析,以支持非常规声明
目前的已知限制:基于正则的提取(对常规代码可靠)、每个文件只能有一个
@Controller,仅检查路径/方法是否存在。GraphQL 不在范围内。
许可证
MIT © Segun Olumbe
工具链的一部分
tieline 是构成 AI 辅助开发确定性信任层的四种工具之一。每种工具都通过静态分析来回答人们总是交给大模型的问题。
- repoctx — 上下文:这项更改实际影响了什么?
- tieline(此工具)— 契约:前端和后端是否在不知不觉中不再保持一致?
- bouncer — 合规:你能为此向 Ofcom 辩护吗?
- aiglare — 治理:模型在哪些地方可能做出你无法撤销的操作?
更多信息请访问 segunolumbe.com。静态分析,而非模型。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。