mcpField
T
tieline

tieline

本地服务
github.com开发工具020 周前更新

关于 tieline

tieline 静态比对前端 API 调用与后端路由,发现路径和方法不一致,无需运行两端。它适合希望在 CI 中加入确定性契约检查的团队,也可检查代码与 OpenAPI 文档的差异。

主要功能

  1. 01静态匹配前后端路由
  2. 02检测漂移、无法验证项和孤立路由
  3. 03支持所列客户端与服务端适配器
  4. 04CI 失败门禁及 JSON/HTML 报告
  5. 05通过 doctor 检查代码与 OpenAPI

适用场景

  1. 01在 CI 中发现前端调用不存在的后端路由
  2. 02找出没有前端调用到达的后端路由
  3. 03核对实现路由与 OpenAPI 文档

MCP 相关

其 MCP 服务提供 5 个工具,用于检查、列出和查看路由映射、比较代码与 OpenAPI 文档,以及初始化配置。结果由与 CLI 相同的确定性引擎生成。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"nugehs-tieline": {
"command": "npx",
"args": [
"-y",
"@nugehs/tieline"
]
}
}
}
启动命令npx -y @nugehs/tieline

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npm@nugehs/tieline0.1.4

工具

5

收录的工具列表 · 更新于 3 周前

参数类型必填说明
configstring否tieline.config.json 的路径。默认从服务器工作目录向上搜索。

详细介绍

tieline

静态前端↔后端契约漂移检查器。无需编写任何契约测试,也能实现 Pact 的效果。

npm CI license: MIT node tests dependencies

tieline 演示

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 Querynestjs — 装饰器
axios-fetch — axios / fetch、React Query 和 SWR 的 queryFnexpress — app.use() 挂载图,跨文件
angular-http — Angular HttpClientfastify — 动词简写 + 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_checkconfig?总计数 + drift + unverifiable(漂移门禁)
tieline_listconfig?完整解析后的契约映射
tieline_orphansconfig?没有前端调用到达的后端路由
tieline_doctorconfig?undocumented + phantom(代码 ↔ 规范)
tieline_initcwd?自动检测附近的仓库并写入配置

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 2 basePath、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。静态分析,而非模型。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。