news 2026/10/15 18:02:52

MooTool Compose 桌面版落地 AI 接入与 MCP 运行时:DIFF-131 技术实现全解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MooTool Compose 桌面版落地 AI 接入与 MCP 运行时:DIFF-131 技术实现全解析
  • 桌面应用
  • 开发工具

【免费下载链接】MooTool

Handy tool set for developers

项目地址:https://gitcode.com/gh_mirrors/mo/MooTool
点击查看免费下载

导读

本文基于 MooTool 仓库next-compose子项目的 DIFF-131 设计文档,深入讲解 Compose 桌面版如何对照 Electron 版AiIntegrationSettings与aiIntegrationService,落地"设置中的 AI 接入 + MCP(Model Context Protocol)子进程运行时"这一首版能力。你将掌握:AI 接入设置面板的完整形态与交互、--mcp子进程的引导与工具注册机制、Codex/Claude Code/Cursor 三类客户端配置文件的合并写入策略,以及安装预览、连接测试、数据只读授权等核心流程的实现原理与测试证据。


一、DIFF-131 要解决什么问题

MooTool 的next(Electron)分支已经具备完整的 AI 接入能力(设置窗口中的AiIntegrationSettings、主进程aiIntegrationService)。DIFF-131 的目标是:在next-compose(Kotlin Compose Desktop 重写版)中把同一套能力按首版标准落地,形成三条工作线:

  1. A01 设置(Settings):在设置导航中新增AI 接入(Ai)分类,位于"运行环境(Runtime)"与"工具(Tools)"之间,提供客户端/模式选择、安装预览、测试连接、随手记与 JSON 只读授权开关。
  2. MCP 运行时:新增--mcp子进程入口(Main.kt→McpBootstrap),以 stdio 传输方式对外提供 MCP 工具,复用现有的JsonEngine/EncodeEngine/TimeEngine/DiffEngine等领域引擎。
  3. 安装(Install):向 Codex 的 TOML 配置、Claude Code / Cursor 的mcp.json合并mootool服务器配置;Skill 文件写入SKILL.md(模板来自 resources/mcp/SKILL.md)与runtime.md。

这一阶段明确的两项边界:安装 receipt 与manageServer的细节落在 DIFF-133,Vault MCP 只读工具落在 DIFF-132;且首版未在本机对真实 Codex/Claude/Cursor 客户端做端到端安装验收。

二、A01 设置面板:AI 接入导航分类

2.1 导航位置

SettingsNavCategory枚举(SettingsNavCategory.kt)的声明顺序为:General, Appearance, Layout, Editor, Network, Data, Vault, Runtime, Ai, Tools, Shortcuts, About。Ai恰好位于Runtime(运行环境)与Tools(工具)之间,与文档描述一致,并在设置界面通过SettingsNavCategory.Ai -> AiIntegrationSettingsPanel(container)挂载(SettingsScreen.kt)。

2.2 面板能力与交互

AiIntegrationSettingsPanel(AiIntegrationSettingsPanel.kt)由remember { mutableStateOf(...) }维护全部状态,核心要素如下:

控件可选项 / 行为说明
客户端(client)Codex/Claude Code/Cursor切换为Cursor时,安装模式被强制为MCP(Cursor 只支持 MCP 安装)
安装模式(mode)MCP + Skill/MCP/SkillCursor客户端不展示MCP + Skill与Skill选项
安装状态MCP: …Skill: …状态机为NotInstalled / Installed / NeedsRepair / Conflict四态
安装按钮点击后执行container.aiIntegration.install(id)依赖预览存在且非忙态
测试连接点击后执行testConnection()成功时 Toast 显示返回的工具数量
刷新使revision += 1,触发LaunchedEffect重新拉取状态/预览

每个控件的变更都会触发refresh():在Dispatchers.IO中并行读取getStatus(client)、getDataAccess()与preview(AiInstallRequest(client, mode)),任何失败都会显示在面板的错误文本中(红色,colors.danger)。

2.3 数据只读授权开关

面板底部是"数据访问"分组,包含两个MooSwitch:

  • 随手记(notes)授权:container.aiIntegration.setDataAccess(AiDataAccessRequest(notes = enabled, json = jsonAccess))
  • JSON 文档(json)授权:container.aiIntegration.setDataAccess(AiDataAccessRequest(notes = notesAccess, json = enabled))

底层实现(AiIntegrationService.kt)把授权结果持久化到ai-integration/access.json(McpLaunchResolver.accessFile),字段为{"version":1, "notes": "<realpath 绝对路径>", "json": "<realpath 绝对路径>"}:

  • 开启授权前校验对应 Vault 根目录必须存在,否则抛出The MooTool vault directory is unavailable;
  • 保存的是root.toRealPath().toString()规范化后的绝对路径(与 ElectronsetDataAccess对齐);
  • 当用户在设置中更换数据目录或 Vault 路径时,AppContainer会自动把授权重置为关闭(AppContainer.kt),避免旧路径悬空。

这些只读工具与访问控制落在 DIFF-132 的VaultMcpReadService/VaultMcpTools中,未授权时调用会直接失败。

三、MCP 子进程运行时:--mcp入口与工具注册

3.1 入口分流

main函数(Main.kt)先检查命令行参数:

fun main(args: Array<String>) { if (args.contains("--mcp")) { McpBootstrap.run(args) return } application { /* 正常桌面 GUI 启动 */ } }

即:当 AI 客户端以命令 + --mcp方式拉起本进程时,进程不再启动 Compose 窗口,而是以纯 MCP stdio 服务模式运行——这与 Electron 版ELECTRON_RUN_AS_NODE=1+mcp.js的启动路径不同,但对外协议一致。

3.2 McpBootstrap 引导逻辑

MCP 引导类完成以下步骤:

  1. parseAccessFile(args):解析--access-file <path>,用于向 Vault 工具传递授权文件位置;
  2. 通过StdioServerTransportProvider+McpJsonDefaults.getMapper()建立标准输入输出传输;
  3. McpServer.sync(transport).serverInfo("MooTool", ProductIdentity.VERSION)声明服务标识;
  4. 遍历McpToolCatalog.registrations(),为每个注册表项构建带inputSchema与annotations(readOnlyHint等)的McpSchema.Tool;
  5. 在工具调用回调中按名称分流:VaultMcpTools.isVaultTool(name)走VaultMcpTools.call(name, map, accessFile),否则走MooToolMcpTools.call(name, map);
  6. builder.build()后Thread.currentThread().join()常驻等待。

3.3 工具目录:从 7 个到 12 个

DIFF-131 基线登记了mootool_json_format等7 个通用工具;后续迭代(例如 DIFF-554 中补充protobuf_wire)使目录扩展。当前仓库McpToolCatalog(McpToolCatalog.kt)注册了8 个通用工具 + 4 个 Vault 只读工具 = 12 个,测试AiIntegrationMcpListToolsTest与AiIntegrationConnectionTest均断言tools.size == 12。

通用工具(mootool_*)

工具名能力入参 Schema 要点
mootool_json_format格式化/压缩 JSON,可排序键、拒绝重复键text(≤100000, 必填),spaces(0–8, 默认2),sortKeys(默认false),checkDuplicateKeys(默认true)
mootool_json_queryJSONPath 查询,返回匹配数组text(≤100000, 必填),path(1–1000, 必填);禁用脚本/过滤表达式
mootool_encodeBase64/URL/十六进制/Unicode 转码text,format(base64|url|hex|unicode),direction(encode|decode),charset(utf-8|gb2312)
mootool_timestampUnix 时间戳与本地时间互转text(≤100),direction(to-local|to-timestamp),unit(second|millisecond),zone(默认UTC);13+ 位按毫秒识别
mootool_diff双文本对比left/right(各≤8000),ignoreWhitespace(默认false)
mootool_hash计算摘要(十六进制)text,algorithm(md5|sha1|sha256|sha384|sha512, 默认sha256)
mootool_uuid本地生成 v4 UUIDcount(1–100, 默认1)
mootool_protobuf_wireprotobuf wire 字节解码(无需 .proto)text,format(hex|base64)

Vault 只读工具(4 个):mootool_notes_search/mootool_notes_read/mootool_json_documents_search/mootool_json_documents_read,均标记idempotentHint=true;search 参数为query(≤200)、limit(1–50)、offset(0–2000),read 参数为path(必填)、offset(0–2,000,000)、length(1–50,000)。这些工具严格遵守只读授权与.gitignore/符号链接排除规则。

3.4 复用领域引擎与输入边界

MooToolMcpTools(MooToolMcpTools.kt)把每个工具映射到既有引擎,做到"一套引擎、多端复用":

  • mootool_json_format→JsonEngine.formatAdvanced(..., JsonFormatOptions(spaces, sortKeys, checkDuplicateKeys, ignoreCase=false));
  • mootool_json_query→JsonEngine.queryPath,且显式拒绝含?(的 JSONPath 过滤表达式(JSONPath filter expressions are disabled for MCP tools);
  • mootool_encode→EncodeEngine.urlEncode/urlDecode/textToHex/hexToText/toUnicode/fromUnicode,Base64 解码前用正则校验;
  • mootool_timestamp→TimeEngine.timestampToLocal / localToTimestamp,13+ 位数字自动按毫秒解释(对齐 ElectrontimeTools.timestampToLocal);
  • mootool_diff→DiffEngine.compare,返回包含unified/added/removed/changed的 JSON 对象;
  • mootool_hash→MessageDigest实现五种算法;
  • mootool_protobuf_wire→ProtobufEngine.decodeWire(Hex/Base64 两种输入)。

安全与健壮性设计值得在集成时注意:

  • 输入上限:通用文本工具100_000字符,时间戳100、diff 每侧8_000、JSONPath1_000;
  • 参数白名单:requireKnownKeys拒绝任何未登记字段;requireStringArg/boundedIntArg对类型与边界做严格校验,越界直接报错而非静默钳制;
  • 所有工具返回McpToolResult(text, isError),异常信息原样返回给调用方。

四、安装流程:配置文件合并、Skill 写入与 receipt

4.1 三类客户端的目标文件

AiIntegrationService.configPath()(AiIntegrationService.kt)按客户端解析家目录下的配置文件:

客户端配置文件格式
Codex~/.codex/config.tomlTOML,[mcp_servers.mootool]
Claude Code~/.claude.jsonJSON/JSONC,mcpServers.mootool
Cursor~/.cursor/mcp.jsonJSON/JSONC,mcpServers.mootool

4.2 合并策略与冲突检测

AiClientConfigMerge(AiClientConfigMerge.kt)负责安全合并,与 ElectronaiIntegrationConfig.ts(next/electron/main/aiIntegrationConfig.ts)逐项对齐:

  • TOML 侧:用org.tomlj解析;若已存在mcp_servers.mootool且与期望 launch 不一致,抛出"已存在不同配置,请重命名或删除后重装";追加的块为:
    [mcp_servers.mootool] command = "…" args = ["--mcp", "--access-file", "…"]
  • JSON 侧:用 Jackson 解析,开启ALLOW_COMMENTS、ALLOW_TRAILING_COMMA与STRICT_DUPLICATE_DETECTION。若源文件含注释/尾逗号(JSONC 风格),走insertJsonServerEntry文本级插入以保留用户注释;否则用 pretty printer 规范化输出;重复键、mcpServers非对象、语法损坏都会拒绝合并(测试见 AiClientConfigMergeTest.kt)。
  • 外部篡改防护:manageServer在安装/修复/卸载时对照安装时保存的 receiptmcp字段;若条目被用户或第三方改过且不在 receipt 中,直接拒绝并提示"配置在安装器之外被修改"。

4.3 MCP 启动命令(launch)

McpLaunchResolver(McpLaunchResolver.kt)生成当前进程的 MCP 启动命令:

fun clientLaunch(accessFile: Path): McpLaunch { val command = ProcessHandle.current().info().command().orElse(javaBinary()) val args = listOf("--mcp", "--access-file", accessFile.absolutePathString()) return McpLaunch(command = command, args = args) }
  • 开发阶段:command为 JVMjava(javaBinary()回退逻辑处理了java.exe的 Windows 差异);
  • 打包后:为当前进程可执行文件 +--mcp;
  • 与 Electron 的ELECTRON_RUN_AS_NODE=1+mcp.js路径不同,但 stdio 协议一致。

4.4 Skill 文件与运行时提示

安装时(模式含 Skill)写入两个文件到~/.agents/skills/mootool/(Codex)或~/.claude/skills/mootool/(Claude Code):

  1. SKILL.md:模板来自打包资源 resources/mcp/SKILL.md,frontmatter 声明name: mootool与"使用本地 MooTool 做开发工具与只读搜索/读取"的描述,正文指导模型优先使用mootool_*MCP 工具、遵守授权开关、不要绕过只读授权读取底层文件;
  2. runtime.md:运行时生成,记录本次安装的可执行文件与命令行调用方式,例如:
    <当前命令> <--mcp …参数> --list

SKILL.md同时记录了无 MCP 连接时的 CLI 兜底路径(--list发现工具、--call TOOL_NAME从 stdin 传 JSON 参数),该路径由 Electron 侧 next/electron/mcp/index.ts 实现。

4.5 安装事务:预览 → 校验 → 写盘 → 回滚

AiIntegrationService的安装是"事务式"的(AiIntegrationService.kt):

  1. preview():生成AiInstallPreview,列出每个文件的前后内容与动作(create/update/delete/unchanged),记录 receipt 内部变更,plan 有效期10 分钟,并发只保留最多 20 个 plan;
  2. install(id):执行前逐文件assertUnchanged(防止预览过期后文件被改);非卸载场景先做连接验证(testConnection()或注入的connectionVerifier);
  3. 每个变更文件先atomicWrite一个*.mootool-backup-*备份,再写目标文件;
  4. 全部写完后逐文件比对校验;任何一步失败则逆序回滚已写文件;回滚也失败时提示用户从备份手动恢复。

安装 receipt 持久化到ai-integration/{codex|claude-code|cursor}.json,包含schemaVersion=1、appVersion、mcp与skills(内容 SHA-256 摘要),用于状态判定与外部篡改检测(详见 DIFF-133)。

五、测试连接:真正的端到端握手

设置面板的"测试连接"调用AiIntegrationService.testConnection()(AiIntegrationService.kt),它不是桩实现,而是真实启动一次 stdio 子进程:

  1. 用StdioClientTransport+ServerParameters以当前 launch 启动子进程,10 秒请求超时;
  2. initialize()完成 MCP 握手,listTools()必须覆盖MooToolMcpTools.toolNames()+VaultMcpTools.toolNames全部12 个工具,缺失即失败;
  3. 调用mootool_json_format({"moo":true}, spaces=0),断言返回文本严格等于{"moo":true};
  4. 返回AiConnectionResult(serverName = "MooTool", tools = [...])。

对应的自动化测试是 AiIntegrationConnectionTest.kt:它用临时目录构造AppContainer,以desktopTestMcpLaunch注入测试 launch,真实拉起子进程完成握手并断言 12 个工具齐全——这直接印证了生产路径testConnection的实现;AiIntegrationMcpListToolsTest.kt 则额外校验readOnlyHint与inputSchema.type === object。

六、依赖与资源

MCP 与 TOML 解析依赖集中在 gradle/libs.versions.toml:

依赖版本用途
io.modelcontextprotocol.sdk:mcp0.18.1MCP 客户端/服务端 SDK、stdio 传输、schema 构建
org.tomlj:tomlj1.1.1Codexconfig.toml的解析与合并

在 build.gradle.kts 中分别以implementation(libs.mcp)、implementation(libs.tomlj)声明于desktopMain依赖块。实现相关的主要源文件:

  • 入口分流:Main.kt
  • MCP 服务:McpBootstrap.kt、McpToolCatalog.kt、MooToolMcpTools.kt
  • 安装与状态:AiIntegrationService.kt、AiClientConfigMerge.kt、McpLaunchResolver.kt
  • 设置面板与导航:AiIntegrationSettingsPanel.kt、SettingsNavCategory.kt
  • Skill 模板:resources/mcp/SKILL.md
  • 对照参考:Electron aiIntegrationService.ts、mcp/server.ts、mcp/index.ts

七、已知边界与后续演进

按 DIFF-131 的自我声明,本阶段存在两项明确边界:

  1. 未做真实客户端端到端验收:未在本机对真实 Codex / Claude / Cursor 客户端执行安装后的端到端验证,AiClientConfigMergeTest等单测通过隔离的临时目录模拟了合并与安装行为;
  2. 打包后--mcp路径待验证:开发态 launch 为java,打包态为"当前进程可执行文件 +--mcp",该打包态路径的验证被推迟到 P7 阶段。

后续 DIFF 系列补齐了 receipt 管理(DIFF-133)、Vault 只读工具(DIFF-132)、重复键检测、Codex TOML Skill 安装等能力。集成方在复刻这套方案时,建议重点守住三条底线:合并前必须语法校验与重复键检测、写盘必须可回滚并留备份、只读工具必须受 access.json 授权约束。

  • 桌面应用
  • 开发工具

【免费下载链接】MooTool

Handy tool set for developers

项目地址:https://gitcode.com/gh_mirrors/mo/MooTool
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 18:02:24

基于D3D的YV12视频渲染:GPU纹理与Shader实现高性能上屏

简介&#xff1a;在视频播放与监控上屏开发中&#xff0c;YUV色彩空间转换是决定性能的关键环节。以YV12为代表的4:2:0平面格式&#xff0c;若在CPU中逐像素转换为RGB&#xff0c;会导致高占用与帧率下降。基于D3D纹理上传与像素着色器&#xff08;Shader&#xff09;的GPU渲染…

作者头像 李华
网站建设 2026/10/15 18:02:16

把 GoAnime 当库用:pkg/goanime 客户端二次开发完全指南

【免费下载链接】GoAnime Search, stream and download anime, movies and TV shows from the terminal, in English and Brazilian Portuguese. 项目地址&#xff1a; https://gitcode.com/gh_mirrors/go/GoAnime 点击查看 免费下载 GoAnime 是一款在终端搜索、流媒体播放和下…

作者头像 李华
网站建设 2026/10/15 18:02:00

工业边缘AI部署实战:TorchScript离线推理系统拆解

简介&#xff1a;本资源是一套基于STM32F405RG平台开发的AD7928双芯片高精度模拟量采集驱动工程&#xff0c;面向嵌入式软硬件工程师及STM32进阶学习者&#xff0c;解决多通道同步采样中SPI时序控制、序列器配置与多片级联等典型难点。工程完整实现AD7928内部序列器对通道0–7的…

作者头像 李华
网站建设 2026/10/15 18:01:22

Flutter 与 LLM 多智能体实战:FastAPI 编排与流式输出

1. 为什么要把 Flutter 和 LLM 多智能体放在一起折腾移动端做 AI 应用&#xff0c;最容易踩的坑就是“把大模型当接口调”。一开始我也这么干&#xff1a;Flutter 页面里塞一个输入框&#xff0c;用户点一下&#xff0c;后端转发给 LLM&#xff0c;返回一段文字渲染出来&#x…

作者头像 李华