Skip to main content
Glama

LinkTerm v2

Desktop + Web monorepo migration in progress. The existing desktop behavior is preserved under apps/desktop; an independently deployable single-user Web service is now implemented under apps/server and apps/web. See the current migration status, project structure and Web deployment guide. The historical desktop documentation below still describes the pre-migration src/ paths and should not be used as the new package layout.

LinkTerm v2 是一个基于 Electron + TypeScript 的桌面终端与 MCP 自动化平台,作为旧 Qt/C++ 终端的重写版本。它在单一运行时内同时服务四类用户:桌面终端用户(本地 Shell / SSH / 串口)、嵌入式固件开发者(终端模式 + sendAndWait + RTT/J-Link 工作流)、AI Host / MCP 客户端(通过生产运行时的 63 个 MCP 工具读写同一会话、抓取截图、烧录调试),以及项目维护者(pure-TS core、依赖注入式 transport、双向许可证校验)。

更换 J-Link 后串口丢失或需要显式启用 VCOM 时,参见 J-Link VCOM 串口恢复

  • 包名:linkterm-v2

  • 版本:0.1.0

  • License:AGPL-3.0-or-later;闭源/专有使用可购买商业许可证

  • 官方仓库:https://gitee.com/wake_micro/link-mcp

  • 包管理器:pnpm@9.15.0(必需,不能用 npm/yarn

  • Node:^22.13.0 || >=24.0.0(CI 验证 Node.js 22.13.0 下界)


当前状态

13 / 13 个计划实现阶段已经完成。公开正式版仍需完成真实硬件/UI 手工验收、依赖安全收口、官方产物签名和发布门禁;当前完成度以 project-completion-audit.md 为准。

阶段

状态

Phase 0 — 项目脚手架

已完成

Phase 1 — 核心 Session / Transcript / WriteQueue

已完成

Phase 2 — 串口适配器

已完成

Phase 3 — SSH + 本地 Shell

已完成

Phase 4 — MCP 终端工具(8 个)

已完成

Phase 5 — AI-人共同操作硬化(priority 队列、多订阅 cursor)

已完成

Phase 6 — Electron Renderer UI(xterm.js + shadcn + i18n)

已完成

Phase 7 — 嵌入式终端规则 + sendAndWait FSM

已完成

Phase 8 — 工作区配置持久化(.linkterm/config.json

已完成

Phase 9 — J-Link MCP 调试面(30 个工具 + NullBackend 兜底)

已完成

Phase 10 — UI MCP 面(ui_configure + ui_screenshot

已完成

Phase 11 — 双向许可证校验脚本

已完成

Phase 12 — 集成覆盖 + 高影响操作观测 + 性能基线

已完成

测试基线以 docs/engineering/quality-gates.md 和最新 pnpm test 输出为准。


Related MCP server: Embedded xLink MCP

架构概览

进程模型

  • Main Process 持有所有运行时状态:SessionManagerTranscriptBufferWriteQueue、Transport 适配器、MCP Server、WorkspaceConfigManager、J-Link backend 抽象、UI bridge。

  • Renderer Process 是 React + xterm.js 的薄壳,仅通过 window.linkterm(由 src/main/preload.ts 注入)经 IPC 与主进程交互。

  • MCP Server 在 Main Process 内运行,与 UI 共享同一个 SessionManager 实例 —— 这是「AI 与人对同一会话共同操作」的承载点(需求 §4.5)。

  • IPC BridgeipcRenderer.invoke / ipcMain.handle 做请求/响应;流式 transcript 数据用事件推送。

支持的 MCP / Activity Runtime 拓扑

生产支持的 Agent 调用只走 Electron Main 拥有的 direct MCP server 或 localhost HTTP owner。两条通道共享同一个 OperationLedger / OperationRecorder / ControlWorkflowJobManager,因此 Activity IPC 看到的是同一 runtime id、同一单调 cursor、同一组 display-safe 操作事件。当前 stdio 集成是连接 HTTP owner 的 proxy;src/mcp/stdio-entry.ts 仅保留为 legacy / 非默认开发可执行入口,不由当前 Agent integrations 安装或宣传,也不提供 Phase 1 可查询的 Main-owned ledger。

单一序列化点(最重要的不变量)

任何对会话的写入 —— 无论来自 UI(origin='human')还是 MCP(origin='ai')—— 都必须SessionManager.writeWriteQueueITransport

WriteQueue 是唯一的串行化瓶颈,保证 AI 与人输入的全局顺序、产生审计踪迹。TranscriptBuffer 仅追加,配以单调递增的 sequence cursor;clear 也以事件形式入档(meta.kind: 'clear'),以保留 AI 的可读历史。MCP 工具与 IPC handler 不允许直接触碰 transport(需求 §4.4 / §5.1)。

本地持久审计(A+D Phase 8)

Activity Ledger 的显示安全事件会由 Main 进程异步复制到 Electron userData/activity/ 下的 JSONL:默认保留 30 天,单文件达到 10 MiB 前轮转。恢复只读取有界的近期记录,破损尾行会显示为 警告而不会伪造操作终态。Activity Center 的“导出脱敏活动”和“删除本机活动”均由 Main 写入/清理; Renderer 不接触审计路径,删除需要显式确认。

审计记录不包含密码、私钥、token、完整终端内容、脚本正文、固件/二进制字节、截图、绝对路径或 PreparedOperation、授权、principal、lease 等 Main-only 对象。持久化是 best-effort 观测副本,失败不会 阻塞 MCP 响应或 transport 写入。

MCP 隔离 Surface(生产运行时共 63 个工具)

Surface

工具数

工具名

Evidence Kind

Runtime / Agent

3

restart_mcp_runtimeget_agent_runbookget_app_status

agent_runbook / app_status

Terminal

8

list_sessionsopen_sessionclose_sessionwrite_to_sessionread_from_sessionsend_and_waitdiscover_serial_portsget_session_status

terminal_output

Workspace

3

init_workspaceget_workspace_configupdate_workspace_config

workspace_config

Control Profile

8

init_control_profileget_control_profileinspect_control_profileprepare_control_profile_questionsapply_control_profile_answeractivate_control_profileconnect_control_profile_chipdisconnect_control_profile_chip

workspace_config

Control Workflow

5

run_control_workflowget_control_workflow_job_statusread_control_workflow_jobcancel_control_workflow_jobcleanup_control_workflow_jobs

debug_output

Debug (J-Link)

30

probe_detect/connect/disconnect/statusjlink_rebootcpu_reset/halt/run/stepbreakpoint_set/clear/listregister_read/write/listmemory_read/writeflash_download/write/verify/erasertt_connect/clear/read/searchgdb_server_start/stopsnapshot_capturecrash_diagnosejlink_commander_script

debug_output

RTT Log Session

2

open_rtt_log_sessiondiagnose_rtt_log_session

terminal_output / debug_output

J-Link Device Catalog

2

jlink_device_catalog_searchjlink_device_catalog_get

debug_output

UI

2

ui_configure(4-action discriminatedUnion)、ui_screenshot(PNG,16 MiB 上限)

ui_screenshot

每个 MCP 工具都返回 { success, sessionId?, state?, evidence: { kind, data, cursor }, error?, correlationId, origin: 'ai', schemaVersion }

高影响工具的自动执行与观测

下列 7 个 J-Link 工具会在 schema、运行时、资源和准入检查通过后立即执行;Activity Center 与本机审计负责记录过程和结果:

flash_downloadflash_writeflash_erasecpu_resetgdb_server_startjlink_rebootjlink_commander_script

旧客户端仍可传入 confirm,但该字段仅作为兼容元数据被接受和忽略,不构成授权或执行门禁。

Backend 兜底策略

  • 没有真实 J-Link backend 注入时,createMcpServer 默认使用 NullJLinkBackend,所有 30 个 debug 工具仍会注册,但每次调用返回 { code: 'NO_BACKEND' }

  • 没有 UI bridge 注入时,ui_configure / ui_screenshot 仍会注册,调用返回 { code: 'UI_NOT_AVAILABLE' }

  • 工作区、控制配置、控制工作流和 J-Link 设备库工具依赖对应 manager/catalog 注入;生产 main runtime 会注入这些依赖,精简测试 server 可省略。


模块布局

src/
├── main/                        # Electron 主进程(仅这里允许 import 'electron')
│   ├── index.ts                 # App 入口,BrowserWindow 创建
│   ├── app-lifecycle.ts         # ready/quit + Vite did-fail-load 重试
│   ├── preload.ts               # contextBridge → window.linkterm
│   └── ipc/
│       ├── index.ts             # 注册所有 IPC handlers + getActiveWindow 闭包
│       ├── session-ipc.ts       # session:write / transcript:subscribe 等
│       ├── session-create-handler.ts
│       ├── serial-ipc.ts        # 串口枚举
│       └── ui-bridge.ts         # ui:statePatch 单向广播
├── core/                        # 纯业务逻辑,零 Electron 依赖
│   ├── session/                 # ISession、SessionBase、SessionManager
│   ├── transcript/              # TranscriptBuffer + cursor
│   ├── write-queue/             # 单一序列化点(high/normal 双 lane)
│   ├── terminal-rules/          # CompletionDetector + EchoHandler + sendAndWait
│   └── workspace/               # WorkspaceConfigManager + Zod 严格校验
├── transports/                  # ITransport 适配器(工厂注入,便于测试)
│   ├── serial/                  # serialport
│   ├── ssh/                     # ssh2
│   └── local-shell/             # node-pty
├── mcp/
│   ├── server.ts、registry.ts、transport.ts、limits.ts
│   ├── versioning/
│   └── surfaces/{terminal,debug,ui,workspace,control-profile,control-workflow,rtt-log-session,...}/
├── jlink/                       # IJLinkBackend 调试/烧录/RTT/GDB 抽象 + 域错误 + NullJLinkBackend
├── renderer/                    # React + xterm.js + shadcn primitives
│   ├── components/              # ConnectionDialog / TerminalView / SessionTabBar / ...
│   ├── hooks/                   # useSession / useTranscript / useUiPatchSubscription
│   ├── store/                   # Zustand
│   ├── i18n/                    # zh / en
│   └── lib/                     # linkterm-bridge.ts 等
└── shared/                      # 跨进程类型 + IPC 通道名 + ERROR_CODES

src/core/src/jlink/src/mcp/surfaces/ 必须保持 Electron 无关,并使用相对 import + .js 后缀(ESM 要求)。@/ 路径别名仅在 renderer 与测试中可用 —— 见下方「构建配置注意事项」。


快速开始

必须使用 pnpm(详见 package.jsonenginespackageManager)。

pnpm install            # 安装依赖
pnpm run build          # 完整构建(tsc -b composite + vite build)
pnpm start              # 启动已构建的 Electron 应用

仅迭代 renderer 时:

pnpm run build:main     # 主进程必须先编译一次
pnpm run dev            # Vite dev server(main 仍需 build)
pnpm start              # 另起 Electron

注意 pnpm run dev 只启动 Vite;Electron 启动时若 Vite 还没就绪,src/main/app-lifecycle.ts 会以 500 ms × 20 次的 did-fail-load 重试兜底。


常用命令

命令

作用

pnpm install

安装依赖

pnpm run build

完整构建:tsc -b(composite 项目)+ vite build

pnpm run build:main

仅构建主进程(tsc -p tsconfig.main.json

pnpm run build:renderer

仅构建 renderer

pnpm run build:all

串行执行 main + renderer

pnpm test

一次性跑全部 Vitest

pnpm run test:coverage

全量 Vitest + whole-source V8 coverage 报告(无阈值)

pnpm test -- path/to/file.test.ts

单文件

pnpm test -- -t "test name"

按名匹配

pnpm run test:watch

watch 模式

pnpm run lint

ESLint(src/ + tests/

pnpm run format

Prettier 格式化

pnpm run validate:licenses

双向校验 third-party-manifest.jsonlicenses/package.json

pnpm run ci:check

串行执行 lint、build、全量 test、license validation

pnpm start

启动已构建的 Electron 应用

pnpm run dev

Vite dev server(仅 renderer)

pnpm run pack

先完整构建,再执行 electron-builder --dir(不打安装包)

pnpm run dist

先完整构建,再按 electron-builder.yml 生成发布产物


构建配置注意事项

  • ESM onlypackage.json "type": "module"。主进程必须用 import.meta.url 派生 __dirnamefileURLToPath(import.meta.url))。

  • 主入口路径是 dist/main/main/index.js(双 main),来自 TypeScript composite + tsconfig.main.jsonrootDir: srcpackage.jsonmain 字段已设为该路径,请勿擅自改动。

  • @/* 别名是非对称的:在 tsconfig.jsonvite.config.tsvitest.config.ts 中均配置为 src/*,但 tsc 不会在 emit 时改写路径别名。规则:

    • Renderer 代码与测试可自由使用 @/...(Vite/Vitest 会改写)。

    • 主进程与 src/core/src/jlink/src/mcp/ 代码必须用相对 import../shared/types.js),且必须带 .js 后缀。

    • 全局把相对 import 替换成 @/ 会过 tsc -b,但运行时 Node/Electron 抛 ERR_MODULE_NOT_FOUND

  • tsconfig.renderer.jsonrootDirsrc(不是 src/renderer),以便引入 src/shared/

  • Tailwind v4 使用 @tailwindcss/postcss(独立包),CSS 入口写 @import 'tailwindcss';

  • CSP 通过 session.defaultSession.webRequest.onHeadersReceived 注入,dev 与 prod 策略不同;不要在 index.html 里加 <meta http-equiv="Content-Security-Policy">,否则会阻断 Vite HMR。

  • TypeScript 严格模式;ESLint 使用 flat config(eslint.config.js)+ typescript-eslint,启用 no-unused-varsargsIgnorePattern: ^_)与 no-explicit-any 警告。


测试策略

  • 框架:Vitest(不是 Jest)。配置见 vitest.config.ts

  • 默认 environment: 'node';renderer 测试通过文件首行 // @vitest-environment happy-dom 切换。

  • Setup:tests/unit/setup.ts + tests/setup-renderer.ts

  • Coverage 范围(v8 provider):src/**/*.{ts,tsx}(仅排除声明文件);Phase 0 只报告 whole-source baseline,不设数值阈值。

  • 当前规模以本页顶部测试摘要和 docs/engineering/quality-gates.md 的最新基线为准。组织:

tests/
├── fixtures/        # mock-serialport / mock-ssh / mock-pty / fake-jlink-backend
├── integration/     # ai-human-coop / send-and-wait / serial-* / perf-* / high-impact execution
└── unit/
    ├── core/        # session-manager / write-queue / transcript-buffer / terminal-rules / workspace
    ├── transports/  # serial / ssh / local-shell(transport 与 session 各自一份)
    ├── mcp/         # terminal-tools / debug / ui / workspace-tools / version-check
    ├── jlink/       # null-backend / jlink-adapter
    ├── main/ipc/    # session-create / ui-bridge
    ├── renderer/    # 组件 / hooks / store / lib(happy-dom)
    └── scripts/     # validate-licenses

关键约束src/core/ 的测试必须能在没有 Electron / 真实硬件 / SSH 服务器 / J-Link 探针的环境下运行(需求 §5.2)。Transport 适配器通过工厂依赖注入实现这一点 —— 见 src/transports/serial/serial-port-like.tsSerialPortFactorysrc/transports/ssh/ssh-client-like.tsSshClientFactorysrc/transports/local-shell/pty-like.tsPtyFactory,测试用 tests/fixtures/mock-{serialport,ssh,pty}.ts 替换默认工厂。


许可证与第三方合规

项目自有代码按 GNU AGPL v3 或更高版本 发布。你可以免费使用、修改、分发和商业使用,但分发修改版或通过网络向用户提供修改版服务时,必须履行 AGPL 的对应源码义务。闭源分发、嵌入专有产品或免除 AGPL 开源义务的授权路径见 许可与商业授权。贡献代码需接受其中的 CLA,以维持双许可能力。

项目许可证不覆盖第三方依赖、商标或厂商工具;归因入口见 NOTICE

第三方依赖门禁

每个运行时第三方依赖必须同时存在于:

  1. third-party-manifest.jsondependencies 数组(含 name / version / license / licenseFile

  2. licenses/<name>.LICENSE 文件

  3. package.jsondependencies(或 EXTRA_RUNTIME_DEPS 白名单)

pnpm run validate:licenses(脚本:scripts/validate-licenses.ts,纯函数 validateLicenses({ manifestPath, packageJsonPath, rootDir }))先执行 4 项 runtime 不变量校验:

  1. Manifest 内部一致性 —— 每条记录字段齐全且 license 文件实际存在;

  2. package.json → manifest —— 每个 dependencies 键必须在 manifest 中有对应记录(或在 EXTRA_RUNTIME_DEPS 白名单中);

  3. manifest → package.json —— 每条 manifest 记录必须出现在 dependencies 或白名单中(删除依赖却忘删 manifest 会失败);

  4. 版本严格相等 —— manifest.version === package.json.dependencies[name](字符串比较,无 semver 容忍)。

EXTRA_RUNTIME_DEPS 当前仅含 electron(位于 devDependencies 但会被 electron-builder 打入运行时产物)。

当前已记录的 19 条运行时依赖:@modelcontextprotocol/sdkreactreact-domzustandelectronzodserialportssh2node-pty@xterm/xterm@xterm/addon-fit@radix-ui/react-{dialog,tabs,select,label,slot}class-variance-authorityclsxtailwind-merge

Coverage provider 不属于产品运行时。third-party-manifest.json 的独立 auditedDevTooling 区域记录 @vitest/coverage-v8@4.1.8 及其沿已安装包普通 dependencies 边可达的 29 包 production closure;每项使用 exact resolved version、上游 license identifier 和仓库内归因文件。该范围明确排除 peer dependencies、包自身的 devDependencies 和未安装 optional peers,且不声称覆盖全部开发依赖。许可证门禁成功时分别报告 19 个 runtime 条目与 1 个 audited tooling root / 29 个 closure 包。

工具链闭包额外双向校验 missing/stale/duplicate record、root specifier、exact resolved version、上游 license identifier 与 license 文件。runtime 与 audited tooling 逻辑分别由 tests/unit/scripts/validate-licenses.test.tstests/unit/scripts/validate-dev-tooling-licenses.test.ts 的聚焦用例守护。

第三方开源项目的设计可作参考,但源码复制需先做许可证审查与归因;jlinkmcphttps://github.com/daikw/JLinkMCP)无声明 license,仅作设计参考、不复制源码(需求 §4.11)。


协作与维护者要点

外部贡献流程、开发环境、行为准则、安全报告与支持边界见 社区与贡献。项目治理、路线图与变更记录见 治理、路线图与变更记录

  • 修改前先读 PROJECT_REQUIREMENTS.mdCLAUDE.md 和相关规范:这些是当前产品边界与工程约束的入口。

  • 新增运行时依赖 = 同一次提交里同时更新 package.jsonthird-party-manifest.jsonlicenses/<name>.LICENSE,并跑通 pnpm run validate:licenses

  • 新增错误码(M5 双向同步模式):必须同时加入

    • src/shared/error-codes.tsERROR_CODES 常量;

    • src/mcp/registry.tsToolErrorCode 联合类型。 现有翻译层基于 instanceof 的错误链(见 src/mcp/surfaces/debug/error-translate.tssrc/mcp/surfaces/workspace/tools.ts),缺失任一半会让翻译静默退化。

  • 新增高影响 J-Link 工具:保持严格 schema、Main-owned admission、IJLinkBackend 单一后端边界与 Activity/Audit 观测;如为旧客户端保留 confirm,必须明确标注其仅为被忽略的兼容元数据。

  • 不得让 MCP 工具或 IPC handler 直接触碰 transport —— 一切写入必须经 SessionManager.write。这是硬安全边界。

  • 不要在 src/core/ 引入 electronserialportssh2node-pty;只能通过 *-{port,client}-like.ts 接口与默认工厂消费。

  • 不要把 SSH 凭据放进 SshSessionConfig 持久结构 —— credentialssession:create IPC 的独立顶层字段,buildSession()await 之前就会清空它。

  • 每次收尾时:确认 ESLint 与 Vitest 全绿,必要时同步更新项目审计与发布说明。


关键参考文档

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    C
    maintenance
    Stateful MCP server for driving debug probes (J-Link) to flash, debug, and inspect embedded targets. Enables AI agents to perform flash, memory, breakpoint, and ELF/SVD-aware operations conversationally.
    41
    10
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    MCP server for embedded debugging based on probe-rs, providing 22 tools for ARM Cortex-M and RISC-V microcontrollers, including connection, memory operations, breakpoints, flash programming, and RTT communication.
    2
    MIT