Skip to main content

LoongClaw MCP 开发者工具包 — 创建、加密、打包、发布、下架/重新上架 MCP 插件

Project description

LoongClaw DevKit — MCP 插件开发完整指南

目标读者:想开发 LoongClaw MCP 插件的开发者

MCP 插件开发者工具包。一键创建、加密打包、发布 MCP 插件到 LoongClaw 商店。


目录

# 章节 解决什么
1 5 分钟上手 装好 → 让 AI 帮你产出第一个插件
2 一个合格的 MCP 插件长什么样 不管用不用 DevKit 都要懂的 MCP 基础
3 DevKit 提供的工具(AI-first) 5 个工具能干啥(不用记命令)
4 manifest.json 字段速查表 每个 .publish.json 字段长什么样
5 configFields — 让用户填 API Key 插件需要用户自己输入密钥时怎么写
5A 使用 LoongClaw 平台 LLM 让用户不用自带 OpenAI Key(合作方专用)
6 postInstallCommands 装完插件后还需要下浏览器/模型时怎么写
7 Python 版本与依赖策略 跨平台不踩坑的 requirements.txt 写法
8 加密发布(Cython) 源码保护怎么自动开启
9 商店访问控制 public / private 两种访问类型怎么选
10 付费/授权模式 把插件做成商业化付费的流程
11 更新与增量发布 改一行也要重发整个包吗
12 在其他 AI 客户端中使用 Claude Desktop / Cursor / VS Code 怎么接
13 常见报错 FAQ 出问题先来这查
14 参考代码 duanju-mcp 真实可跑的样例项目
15 附录 命令行逃生 / Store Key / 调试技巧 / 能力边界

1. 5 分钟上手

1.1 什么是 LoongClaw MCP 插件

MCP(Model Context Protocol,模型上下文协议)是 Anthropic 提出的标准,让 AI 能调用外部工具。LoongClaw MCP 插件 = 一个独立的 Python 程序,按 MCP 协议暴露工具给 LoongClaw 桌面客户端里的 AI 调用。

类比:AI 就像一个刚入职的新员工,MCP 插件就是你给他的一本「操作手册」——上面写明这个员工可以用哪些工具、每个工具怎么用、参数有哪些。AI 看完手册就知道「原来我能查短剧库、发布视频、下载素材」。

1.2 DevKit 是什么

loongclaw-devkit 是一个本身也是 MCP 插件的工具包。安装后,你的 AI 助手(LoongClaw、Claude Desktop、Cursor)会多出 5 个工具:

  • create_mcp_project — 一句话生成项目骨架
  • publish_mcp — 一键加密 + 打包 + 上传
  • unpublish_mcp — 下架自己发布的插件(软下架,不影响已安装用户)
  • republish_mcp — 重新上架之前下架的插件
  • check_mcp_status — 查看已发布状态

一句话:你让 AI 干活,AI 让 DevKit 干活。 你不用记任何命令。

1.3 安装

推荐使用 uvx(零安装直接运行):

uvx loongclaw-devkit

或用 pip 安装:

pip install loongclaw-devkit

在 LoongClaw 客户端里直接搜索 loongclaw-devkit 一键安装即可,不需要命令行。在 Claude Desktop / Cursor / VS Code 中使用,见第 12 章

� v0.10.6(2026-04-27)— 性能 + 质量两大升级

加密耗时大幅缩短:以前每个 .py 文件都单独冷启动 Python 子进程跑 setup.py(每次 1-2s)。文件多的项目(如 70 文件级别)光启动开销就 ~2-3 分钟。v0.10.6 改成批量并行编译——一次性 cythonize(nthreads=CPU核数) + build_ext -jN,多核机器加速明显(实测 8 核 macOS:56 文件 ~15min → ~3min)。无需修改 .publish.json,升级即享

新增 --dry-run 预览模式:第一次发版或改了 .mcpignore 后,先 python publish.py --auto --dry-run 把"什么进了包"看一眼再决定要不要真上传。完整跑加密 + 打包 + 烟雾测试,最后打印 zip 内全部文件列表(每条标 🔒 加密 / 📄 明文 / 📦 资源 + 大小);不生成 manifest、不上传、不修改 .publish.json

新增 staging 烟雾测试(自动行为):打包前自动跑 compileall 验证所有明文 .py 语法 + 子进程 import server 验证入口能加载,能在发版前抓"明文 .py 损坏"和".mcpignore 误排除关键模块"两类问题。注意:开发机里依赖未装属正常(包还没 pip install 呢),这种情况降级为 ⚠ warn 不阻断;语法损坏 / __init__.py 缺失等真错误才阻断。

升级pip install -U loongclaw-devkit==0.10.6

�🔥 v0.10.5(2026-04-27)— 关键修复:所有 .publish.json 字段现在真正生效

如果你写的 .publish.json 里有 configFields / env / postInstallCommandsv0.10.4 及之前的版本会在生成 manifest 时悄悄丢掉这些字段——你写的中文 label、自定义环境变量、装后命令全都进不到服务器,客户端也读不到。v0.10.4 我们修了入口侧白名单,但下游 manifest 组装阶段还有一道独立白名单当时没扫到。现在彻底修了

v0.10.5 一并修复 5 个 bug:

  • configFields / env / postInstallCommands / replaces / companionSkill 全部透传:用户在 .publish.json 写的字段进 manifest(同时保留 server.py 自动扫描作 configFields 兜底)。replaces 和 companionSkill 是发版前自审查新发现的——v0.10.4 修了 main() 但 generate_manifest 同样从未透传这俩字段,客户端的「配套技能」UI 标签和「压制内置工具组」功能此前一直默默不生效
  • --json-output 失败时 sys.exit(1):CI 脚本($LASTEXITCODE)现在能正确判断成败,不再"假发版"
  • Windows 系统代理隔离:requests 默认会读 winhttp(v2rayN/Clash 装代理后必踩),现在显式 trust_env=False
  • PowerShell 5.1 中文不再乱码:启动时 sys.stdout.reconfigure(encoding="utf-8")

升级pip install -U loongclaw-devkit==0.10.5,再重新发一次插件即可。

📜 历史版本变更(v0.9.x — v0.10.4,已稳定,仅作存档)

v0.9.1(2026-04-24)— 三项开发者体验补丁

  1. Cython 产物警告文案修正:旧文案只提"声明 requiredPython",没提还会自动写 buildPlatform。v0.9.1 修正为同时说明两个字段及实际值。
  2. .mcpignore UTF-8 BOM 自动处理:Windows 记事本等编辑器默认保存 BOM,会污染第一行规则(*.log 被当成 \ufeff*.log 而匹配失败)。v0.9.1 用 utf-8-sig 自动剥离 BOM 并给出警告。
  3. 上传成功后输出丰富化:打印插件 ID / 版本 / access 类型 / buildPlatform / requiredPython / 包大小 / 上传地址,方便开发者和 AI 核对。

⚠️ v0.9.0 Breaking Changes(2026-04-24)

行为变化(可能影响现有项目):

  1. skipEncrypt / --skip-encrypt / publish_mcp(skip_encrypt=...) 全部删除。非 MCP 运行时文件请改用 .mcpignore(gitignore 语法)完全排除出包——保留明文既无法加密保护又占用 zip 体积,不是正确做法。
  2. _vendor/ 默认不再打入 zip。客户端 mcp-store-python.ts 已有 PyPI 在线安装三级 fallback(--only-binary → 正常 pip → venv pip 兜底),打 vendor 会让 zip 从几 MB 涨到几十 MB 常被网关拦截。需要离线分发时,在 .publish.json 显式设 "bundleVendor": true
  3. Cython 编译失败 = 发版失败(Fail Fast)。旧版本会回退为明文导致源码泄漏,现在直接 abort 并输出 stderr,要求开发者修好再发。
  4. 发版前自动做 Cython 可行性前置扫描:文件名必须是 ASCII 合法标识符(中文/空格/连字符拒绝);函数参数名不能撞 C/Cython 保留字(int/char/long/...)。一次性报告所有问题,不再走到子进程编译阶段才挂。
  5. 上传不再设固定 read timeout(对齐「超时铁律」)。v0.8.x 的 300s read-timeout 在慢网络下会误杀合法上传;v0.9.0 仅保留 10s 连接超时,body 上传由 TCP/服务端自行判活。
  6. 上传体积上限改为服务端单源查询Cloud /v1/store/limitsLOONGCLAW_MAX_UPLOAD_MB 环境变量 → 内置兜底(三层 fallback)。具体阈值以服务端为准。超过 warn 打印警告但允许上传,超过 max 直接拒绝。
  7. CLI flag 在所有模式下都覆盖 saved 配置:v0.8.x 仅 --auto 模式下 CLI 生效,导致 python publish.py --version 1.0.1 在已有 .publish.json 时参数被静默忽略。

新增能力:

  • 新增 .mcpignore 文件支持:项目根创建即可,支持 ** / !negate / #comment 标准 gitignore 语法。
  • 硬红线不可覆盖(即使 .mcpignore!.git/ 也无效):__pycache__/ *.pyc *.pyo .git/ .venv/ venv/ _staging/ .publish.json project.zip .mcpignore
  • staging 清理用 try/finally 保证:任何一步失败(含 SystemExit)都会清理 _staging/,防止下次 publish 读到旧残留。
  • 自动包含构建工具链setuptools / wheel / Cython / pip / pathspec 现为 devkit 运行时依赖。

.publish.json 里的 skipEncrypt 字段会被自动丢弃并提示迁移。

v0.10.4(2026-04-27)— main() 字段透传

修了 publish.py main() 里的字段白名单——以前 runtime / mcp / replaces / companionSkill / usesPlatformLlm 等字段在 saved → config 阶段会被丢,导致重复发版时 .publish.json 有的字段进不到 manifest。但 generate_manifest 阶段还有第二道白名单当时没扫到,所以 configFields/env/postInstallCommands 还是会丢——v0.10.5 才彻底修完。

1.4 三句话产出一个插件

在 LoongClaw / Claude Desktop 里直接对 AI 说:

:"帮我在 ~/projects/weather-mcp 创建一个 MCP 插件,ID 叫 weather-mcp,功能是查天气"

AI 调用 create_mcp_project 生成骨架。

:"在 server.py 里加一个工具,接收城市名,返回今天天气"

AI 编辑代码。

:"发布到 LoongClaw 商店"

AI 调用 publish_mcp 完成加密、打包、上传。

就这样。


2. 一个合格的 MCP 插件长什么样

这一章是所有 MCP 开发者都要懂的基础——不管你用不用 DevKit。

2.1 最小可运行结构

weather-mcp/
├── server.py            ← MCP 入口(FastMCP 实例 + 工具注册)
├── requirements.txt     ← Python 依赖
└── .publish.json        ← DevKit 发布配置(DevKit 自动生成骨架,access 字段必须你/AI 手动填 public 或 private)

server.py 模板

#!/usr/bin/env python3
"""weather-mcp — 天气查询插件"""

from mcp.server.fastmcp import FastMCP

mcp = FastMCP(
    "weather-mcp",
    instructions="提供全球城市天气查询能力。"
)

@mcp.tool()
def get_weather(city: str) -> str:
    """查询指定城市今天的天气。

    Args:
        city: 城市名(中文或英文均可,如 "北京" / "Tokyo")
    """
    # ... 你的业务逻辑
    return f"{city}: 晴,25°C"

if __name__ == "__main__":
    mcp.run(transport="stdio")

requirements.txt

mcp>=0.4.0
requests>=2.31.0

就这样。一个合格的 MCP 插件 = FastMCP 实例 + 若干 @mcp.tool() 装饰的函数 + stdio transport 启动。

2.2 三个必知原则

原则一:工具名禁止加前缀 ⚠️ 这是第一大坑

不要这样写:

# ❌ 错误示范
@mcp.tool()
def mcp__weather__get_weather(city: str) -> str:  # 别加前缀!
    ...

LoongClaw 的 MCP Manager 会自动把你的工具重命名为 mcp__weather-mcp__get_weather(对标 Claude Code 标准)。你手动加前缀 → 双重前缀 → 工具名里会变成 mcp__weather-mcp__mcp__weather__get_weather → AI 根本调不到。

正确做法:工具名只写功能名,如 get_weathersend_messagelist_accounts

代码依据:loongclaw/gateway/mcp/mcp-manager.ts:309 —— const prefixedName = \mcp${PREFIX_SEP}${serverName}${PREFIX_SEP}${mcpTool.name}``

原则二:docstring 决定 AI 用不用你的工具

AI 只看 docstring来决定要不要调这个工具。Docstring 写得烂 = 工具形同虚设。

差的 docstring

@mcp.tool()
def process(data: str) -> str:
    """处理数据"""  # AI 看了一脸懵:啥数据?怎么处理?

好的 docstring

@mcp.tool()
def get_weather(city: str, unit: str = "celsius") -> str:
    """查询城市今日天气。支持全球 200+ 城市。

    Args:
        city: 城市名,中文或英文均可(如 "北京" / "Tokyo" / "New York")
        unit: 温度单位,"celsius" 或 "fahrenheit",默认 celsius

    Returns:
        JSON 格式字符串,包含 temperature, condition, humidity, wind 四个字段

    Example:
        get_weather("北京") → {"temperature": 25, "condition": "晴", ...}
    """

规则

  • 首句用动词开头,一句话说清楚做什么
  • 每个参数都写类型 + 示例
  • 有返回结构时用 Returns: 块说明
  • 有副作用(写文件、发网络请求、花钱)必须标明

LoongClaw 限制:工具 description 超过 2048 字符会被截断(防止 OpenAPI 自动生成的 60KB 文档撑爆上下文)。

原则三:核心业务逻辑放独立文件

# server.py(入口,明文)
from core import query_weather_api

@mcp.tool()
def get_weather(city: str) -> str:
    return query_weather_api(city)
# core.py(核心逻辑,发布时会被 Cython 加密成 .so/.pyd)
def query_weather_api(city: str) -> str:
    # 你的真正业务逻辑,发布后用户看不到源码
    ...

为什么这样分server.py 是启动入口,必须明文;其他 .py 文件 DevKit 会自动 Cython 编译加密。详见第 8 章


3. DevKit 提供的工具(AI-first)

DevKit 本身是一个 MCP 插件,注册在你的 AI 客户端里。v0.9.0 起对 AI 暴露 9 个工具, 覆盖创建→诊断→配置→发布→下架的完整生命周期。推荐 AI 工作流

create_mcp_project → (写业务逻辑) → update_mcp_config (author/access)
  → add_ignore_pattern (排除测试/数据) → diagnose_mcp_project
  → publish_mcp(upload=True)

所有错误返回 {status, code, error, fix},AI 看 code 字段(稳定枚举)自动路由修复。

3.1 create_mcp_project — 创建项目

对 AI 说:"创建一个 MCP 插件到 ~/projects/weather-mcp,ID 叫 weather-mcp,功能是天气查询"

幕后做了什么

  1. 在目标目录创建骨架:

    • server.py(填入 ID 和描述的 FastMCP 模板)
    • requirements.txt(含 mcp>=0.4.0
    • AGENTS.md(给 AI 看的开发规范)
    • .publish.json(发布配置:ID / 版本 / 访问类型;author 和 access 留空,强制显式填充)

    v0.9.0 不再复制 publish.py 到用户项目——发布逻辑在 devkit 自身,用户项目保持纯净。

  2. 返回 next_steps 提示 AI 下一步干什么

代码依据:server.py create_mcp_project,模板文件在 src/loongclaw_devkit/templates/

3.1b 配置/诊断工具(v0.9.0 新增)

工具 作用
update_mcp_config(project_dir, field, value) 更新 .publish.json 单个字段(白名单校验;access 限 public/private)
add_ignore_pattern(project_dir, patterns) 追加 .mcpignore 规则(去重、保序)
list_mcp_tools(project_dir) AST 解析 server.py 列出所有 @mcp.tool() 函数及签名
diagnose_mcp_project(project_dir) 不构建不上传的预检:配置完整性 + Cython 可行性 + @mcp.tool() 数量 + 体积预估,返回 {ok[], warnings[], issues[], ready_to_publish}

AI 强烈推荐publish_mcp 之前先调 diagnose_mcp_project——本地秒级反馈, 避免发到云端才发现 author 没填、Cython 函数参数撞保留字等问题。

3.2 publish_mcp — 一键发布

对 AI 说:"把 ~/projects/weather-mcp 发布到 LoongClaw 商店,版本 1.0.0"

幕后 6 个步骤(全自动):

步骤 做什么 失败后果
1. 校验项目 检查 server.py 是否有 FastMCP 实例 + mcp.run()requirements.txt 是否存在;private 付费插件额外要求 FastMCP 实例命名为 mcp(壳模式约定,见§8.3 返回错误并给修复建议
2. 检测跨平台风险 扫 requirements.txt,警告 greenlet==X.Y.Z 等严格锁版(Windows 可能装不上) 警告但不中断
3. Cython 加密 public:除 server.py/__init__.py 外所有 .py 加密。privateserver.py 一起加密server_impl.so,staging 自动生成入口壳 server.py(含 sys.path 自注入,兼容嵌入式 Python) 任何业务 .py 编译失败 → private 模式 Fail-Close abortpublic 模式回退明文会警告
4. 离线 wheel 打包 根据 requirements.txt 下载所有依赖到 _vendor/(用户无网也能装) 默认 PyPI 失败 → 自动重试清华镜像
5. 打 zip 明文 + .so + _vendor/project.zip(排除 __pycache__ / .venv / 上次残留的 project.zip
6. 生成 manifest + 上传 算每个文件的 SHA-256 + zip 整体 SHA-256,组装 manifest.json,上传到 Cloud API 缺 Store Key → 报错并提示申请地址

代码依据:publish.py(devkit 内部引擎 ~1200 行,涵盖全部 6 步;v0.9.0 起不再复制到用户项目)

紧急逃生(日常不用)python -c "import loongclaw_devkit, pathlib; print(pathlib.Path(loongclaw_devkit.__file__).parent)" 找到 devkit 安装位置后直接跑 python <路径>/publish.py --auto ...。仅在 devkit MCP 服务挂了或 CI 流水线场景使用。

3.3 check_mcp_status — 查状态

对 AI 说:"查下 weather-mcp 现在商店里是什么版本"

幕后做了什么:从 Cloud 拉 registry.json,对比本地 .publish.json 的版本号,告诉你是否需要 bump version。

3.4 unpublish_mcp — 下架自己发布的插件

对 AI 说:"我的 weather-mcp 有严重 bug,先下架"

幕后做了什么:调用 Cloud 的 POST /v1/store/unpublish,服务端校验「当前 Store Key 的 userId == manifest.uploadedBy」才允许操作。下架后:

  • 新用户在商店里看不到这个插件
  • 已安装的用户不受影响——他们本地已有的代码继续工作(LoongClaw 不会远程禁用用户本地代码,这是用户权益铁律)
  • 你之后上传同 id 的新版本不会自动复活——防止带 bug 的旧版本又被重新展示。确认新版本修复了问题后,调用 republish_mcp 才重新上架

参数:plugin_id(必填)、store_type(mcp|skill,默认 mcp)、reason(可选,便于 admin 后续排查)

3.5 republish_mcp — 重新上架

对 AI 说:"weather-mcp 新版本 1.2.0 我已经测过了,重新上架"

幕后做了什么:调用 POST /v1/store/republish,把 store_revocations 表里的记录标为 restored,registry 自动刷新后用户就能再次看到。

只能操作你自己发布的插件(uploadedBy 校验),别人的下架不了。


4. manifest.json 完整字段速查表

DevKit 发布时会自动生成 manifest.json,你一般不用手写。但你得懂里面每个字段在 LoongClaw 客户端对应什么行为——调试 bug 时就靠它

字段 类型 必填 作用
id string 插件唯一 ID。仅允许 [a-zA-Z0-9_-],长度 ≤100。DevKit 从 .publish.json 读取
name string 显示名(用户在商店看到的)
description string 插件描述,AI 选择插件时会读这个
version string 语义版本号(如 1.0.0)。LoongClaw 通过字符串比较判断「是否有更新」
author string 作者名
icon string emoji 或 URL
runtime string 支持 "python"(缺省)或 "self-contained"(自带运行时,见§4.7)。老 .publish.json 不写默认 python
entrypoint string 入口文件,始终 "server.py"(self-contained 下不被客户端读,仅占位)
files object 新格式{ "文件相对路径": { "hash": "SHA-256", "size": 字节数 } }。用于增量更新判断
sourceArchive string zip 文件名,DevKit 统一为 "project.zip"
sourceArchiveHash string zip 整体 SHA-256。增量更新的关键判断依据(见第 11 章
env object 默认环境变量(用户可在客户端 UI 覆盖)
configFields array 用户可填的配置项,见第 5 章
postInstallCommands string[][] pip install 后执行的命令,见第 6 章
requiredPython string Python 版本约束,见第 7 章
replaces string[] 替代的内置工具组名(安装后自动隐藏,避免 UI 重复)
companionSkill string 配套 Skill 名(前端用于关联提示)
accessType "public" | "private" 访问控制,见第 9 章必填,无默认值;Cloud 白名单拒绝任何非法值,DevKit publish.py 上传前本地预校验拦截
usesPlatformLlm bool 声明该 MCP 需要使用 LoongClaw 平台 LLM(默认 false)。类型必须是 JSON 布尔 true/false,不能写成 "true" / 1 / True——v0.10.4+ devkit 会在 publish 预检 fail-fast 报错。⚠️ v0.10.3 及以前版本字段会被丢(main() 白名单),v0.10.4 修了 main() 但 generate_manifest 仍漏 replaces / companionSkill / env / configFields / postInstallCommands —— 必须升级到 v0.10.5 才彻底正常。详见 5A 章——该能力暂不开放外部开发者自助申请,仅 LoongClaw 自研插件 + 已签约合作方使用,未加白名单时调用稳定返 403。
mcp object MCP 标准字段(transport/command/args)。runtime=self-contained 时必填 command
skipCython bool 跳过 Cython 加密(默认 false)。适用于中间产物已是 .so/.pyd 的场景;self-contained 自动跳过不需显式设置
buildPlatform string 构建平台(darwin/linux/win32)。默认仅在有 Cython 产物时自动写入;runtime=self-contained 时必填(自带二进制必然平台特定,客户端 precheck 据此过滤)

代码依据:store-types.ts —— StoreManifest 接口(约第 57 行起)

Cloud 端额外自动注入的字段(你不用写):

  • uploadedBy — 上传者的 userId,用于防止他人覆盖你的插件(所有权校验)
  • uploadedAt — 上传时间

4.7 self-contained — 自带运行时(高级)

绝大多数插件应该用默认 runtime=python。仅当你自带 Python 解释器或单文件二进制(pyinstaller / nuitka / 嵌入式 Python / Go 编译产物)时才用 self-contained

与 python 模式的区别

行为 python self-contained
客户端创建 venv
客户端跑 pip install -r requirements.txt
启动方式 python server.py manifest.mcp.command + args
requirements.txt 必需 ❌(可缺失)
mcp.command 必需
buildPlatform 必需
Cython 加密 access=public 时跳过 / access=private 时强制 access=public 时跳过 / access=private仍强制加密项目内 .py

⚠️ accessType=private 安全承诺:无论 runtime=self-contained 还是 skipCython=true,只要 access=private,项目内的业务 .py 文件都会被强制 Cython 加密——这是平台付费包源码保护的硬性承诺,无法绕过。如果 self-contained 项目纯靠预编译二进制启动(项目里不含业务 .py,仅 __init__.py 占位),则正常打包不加密;只要存在 .py 业务源码就必须加密成功才能继续发版。

.publish.json 最小示例

{
  "id": "my-binary-mcp",
  "name": "My Binary MCP",
  "description": "Self-contained MCP with bundled binary",
  "version": "1.0.0",
  "author": "you",
  "access": "public",
  "runtime": "self-contained",
  "buildPlatform": "darwin",
  "mcp": {
    "command": "./bin/my-server",
    "args": ["--stdio"]
  }
}

mcp.command 取值规则

  • 路径形式(含 / \. 开头):相对 installDir 解析,必须落在 installDir 内(沙箱防穿越)
  • 裸命令名:必须在客户端白名单内 — python python3 node npx uv uvx deno bun cmd sh bash pwsh

多平台分发:自带二进制天然单平台。如要支持 macOS/Windows/Linux 三端,需各构建一份 zip 并各自上传(Store 多 slot 模型已支持,见 BACKLOG #14)。


5. configFields — 让用户填 API Key

5.1 场景

你的天气插件需要调和风天气 API,用户得先去注册账号拿自己的 Key。你不能把 Key 硬编码进代码(那是你的 Key,用户用你的额度)。

5.2 声明方式

server.py直接写 os.environ.get("HEFENG_API_KEY", ""),DevKit 的 publish.py自动扫描并生成 configFields

import os

HEFENG_API_KEY = os.environ.get("HEFENG_API_KEY", "")  # DevKit 自动识别
HEFENG_UNIT    = os.environ.get("HEFENG_UNIT", "celsius")

生成的 manifest 里:

{
  "configFields": [
    { "key": "HEFENG_API_KEY", "label": "Hefeng Api Key", "default": "", "required": true },
    { "key": "HEFENG_UNIT",    "label": "Hefeng Unit",    "default": "celsius", "required": false }
  ]
}

规则:无默认值required: true有默认值required: false

代码依据:publish.py:372 —— re.finditer(r'os\.environ\.get\(...)

5.3 手动覆盖(密码类型 / 中文 label / 帮助文案)

自动扫描出来的字段是纯文本输入框,label 是英文 Hefeng Api Key。如果你想要密码遮罩 / 中文 label / 友好的帮助文案,在 .publish.json显式写 configFields——v0.10.5+ 会优先用你写的,扫源码作兜底。

{
  "id": "weather-mcp",
  "version": "1.0.0",
  "configFields": [
    {
      "key": "HEFENG_API_KEY",
      "label": "和风天气 API Key",
      "type": "password",
      "required": true,
      "description": "在 https://dev.qweather.com 注册账号后到「应用管理」获取"
    }
  ]
}

⚠️ v0.10.4 及之前的版本有 bug:即使你在 .publish.json 写了 configFields,发布时也会被丢,最终 manifest 还是用扫源码生成的英文 label。v0.10.5 修复

5.4 用户视角

用户在 LoongClaw 商店点「安装」→ 弹出填写表单 → 用户填完 → 客户端把值以环境变量形式注入你的 Python 进程。你在 server.pyos.environ.get(...) 直接拿到。

5.5 装好后用户怎么改 secret(API Key 轮换 / Token 过期)

LoongClaw 客户端 v?.??+ 起:用户在「商店 → 已安装条目卡片」可以看到 「⚙ 配置」按钮,点开会弹出和首次安装一样的 configFields 表单。

行为:

  • 留空 = 保持原值(password 字段不预填,避免 DOM/截屏泄露)
  • 提交后客户端会停掉 MCP 进程 → 改写本机 mcp-servers.json 的对应 env → 自动 重启 MCP 加载新值
  • 用户在 mcp-servers.json 里手加的额外 env 字段(manifest 没声明的,比如 DEBUG=1 之类诊断变量)会被保留

作为开发者你不需要做任何额外工作 —— configFields 已经在 manifest 里了,「⚙ 配置」会自动复用。但请注意:

  • 不要在 server.py 里把 secret 写到 stderr/log,否则 Cloud 端遥测可能采到(v0.9.0+ 客户端有 sanitizeErrorMessage 但你的业务日志不在保护范围)
  • 不要让 AI 帮用户写 secret:客户端 system prompt 已经引导 AI 让用户走「⚙ 配置」UI 路径,避免 secret 进对话历史

5A. 使用 LoongClaw 平台 LLM(不让用户填 OpenAI Key 的方案)

此功能暂不开放外部开发者自助申请。 仅 LoongClaw 自研插件 + 已签约的长期合作方可用。 如有合作意向请邮件联系:XiaojieMa103@163.com(注明插件用途、目标用户群、预估 LLM 调用量)。

未加入白名单的 MCP 调用 /v1/mcp-llm/issue-token稳定返回 HTTP 403 MCP_NOT_WHITELISTED——不是偶发错误,重试无意义。请用第 5 章 configFields 让用户填自己的 OpenAI Key 作为替代方案。

5A.1 适用场景

你的 MCP 内部需要调 LLM(让 AI 总结 / 抽取 / 翻译 / JSON 化),但你不想让每个用户都自己去注册 OpenAI 账号、复制 API Key。

LoongClaw 提供平台 LLM 代理:声明一个开关后,客户端会在 spawn 你的子进程时自动注入 OPENAI_BASE_URL / OPENAI_API_KEY → 你的代码用标准 openai SDK 调用 → 客户端本地代理拦截后,用最终用户的算力余额扣费(不是开发者掏钱)。

计费归属:调用产生的费用从最终用户的算力账户扣(流水标 source=mcp + mcp_id),不是从开发者账户扣。请在你的 MCP 文档里向用户说明这一点,避免认知偏差。

5A.2 开启方式(合作方专用)

AI 调一次工具即可:

update_mcp_config(field="usesPlatformLlm", value=True)

之后请把 mcpId 邮件给我们,由 LoongClaw 后台手动加入 mcp_llm_whitelist 表后生效。

5A.3 调用代码(合作方落地后才有效)

零代码改动,标准 openai SDK 即可:

from openai import OpenAI

client = OpenAI()  # 自动读 env 里的 OPENAI_BASE_URL / OPENAI_API_KEY
resp = client.chat.completions.create(
    model="qwen3.5-plus",  # 见 5A.4 模型选择
    messages=[{"role": "user", "content": "..."}],
)

协议:纯 OpenAI Chat Completions 兼容。

💡 本地开发期想脱离客户端单跑 server.py 调试?§5A.9 本地开发期 LLM 兜底

5A.4 可用模型清单(运行时拉取)

不要把模型 ID 硬编码在文档里——LoongClaw 上下线模型很频繁,写死的清单会过期。

查询当前可用模型的标准方式:

curl https://api.loongclaw.net.cn/v1/models | jq -r '.data[].id'

输出形如 claude-sonnet-4.5 / gpt-5 / qwen3.5-plus / MiniMax/MiniMax-M2.5 / ...——这些就是可以直接填到 model= 参数里的真实 ID(注意:客户端 UI 上显示的是美化后的名字如「Claude Sonnet 4.5」,那个名字不能用于 API 调用,必须用 /v1/models 返回的原始 ID)。

该端点无需认证,开发者和 AI 在写代码前都可以直接拉一次确认当前清单。

⚠️ 服务端有 IP 限流/v1/models/v1/models/config/v1/model-context-limits 三个端点各自独立计数,每个端点同 IP 每分钟最多 30 次。开发者拉一次确认即可,不要在 CI / 启动脚本里轮询——超限会返 429 + Retry-After 响应头。

拿不准选哪个模型时的兜底建议

如果你是 AI / 开发者写代码时不确定该选哪个模型,推荐(不是强制)选 qwen3.5-plus 作为起点——综合性价比、稳定性、响应速度比较平衡,适合大多数 MCP 内部调用场景(总结、抽取、JSON 化)。

但请注意:

  • 这只是「拿不准时的合理默认」,不是强制要求
  • 你完全可以从 /v1/models 拉到的清单里任选其它模型(比如对生成质量要求高 → claude-sonnet-4.5;对成本敏感 → 选更便宜的 flash 系列)
  • 不要在代码里写死单一模型——把 model 名留作 MCP 工具参数或 configField,让用户/上层 AI 决定更好

5A.5 ⚠️ 安全规则:禁止把 OPENAI_API_KEY 落盘 / 打日志

每次客户端启动 / MCP 重连,注入的 token 都会变(基于 nonce 重新分配)。

  • ❌ 不要 print(os.environ["OPENAI_API_KEY"]) —— 真 token 泄漏到日志
  • ❌ 不要把 key 写到本地缓存文件 —— 下次启动就废了
  • ❌ 不要在工具返回值里回显 key —— 暴露给上层 AI 和用户
  • ✅ 只在调用 LLM 时通过 OpenAI() 默认读取,用完就忘

5A.6 ⚠️ 401 自动续约由代理层处理

如果用户在其它设备登录把当前设备踢下线 / 重新登录 → 旧 token 失效 → 你这边 chat 调用返 401。本地代理会自动重新申请 token 并重试一次,对你的代码完全透明。

不要自己实现 401 重试逻辑——会和代理层冲突,可能导致重复扣费或卡死。

5A.7 ⚠️ 首次调用可能 ~200-500ms 延迟(不是失败)

客户端 spawn 你的子进程时 env 里塞的是临时占位符(lc-pending-<nonce>),不是真 token。第一次 chat 请求到达本地代理时才向 Cloud 申请真 token,所以首次请求会比后续慢 200-500ms,之后所有请求走缓存。

网络抖动导致首次签发失败时会返 502,OpenAI Python SDK 默认会自动重试 2 次(指数退避 0.5s → 1s)——通常无需你额外处理。如果你在工具里捕获了 LLM 异常,保留至少一次重试,不要把 502 直接透传给上层 AI。

5A.8 不要做的事

行为 后果
requests 直连 https://api.openai.com 绕过代理 = 用户没付钱给你跑了 LLM
自己读 OPENAI_API_KEY 拼别的 base_url 真 token 暴露给第三方上游
假设 base_url 一定是 http://127.0.0.1:18789/v1 端口可能变(用户自定义 gateway 端口)—— 永远用 SDK 默认
在工具内调 openai SDK 但不 catch 异常 用户首次使用偶发慢/失败,体验差
在代码里硬编码模型名(如 model="gpt-4o" 模型下线后整个 MCP 失效;改成 configField 或工具参数

5A.9 本地开发期 LLM 兜底(IDE / CLI 调试)

生产环境的平台 LLM 走客户端注入,但开发期常常脱离 LoongClaw 客户端单跑 server.py(IDE F5 调试 / CLI 跑测试 / 单跑某个工具看效果)。这种场景下没有客户端注入 env,标准 OpenAI() 默认调 https://api.openai.com 拿不到 key 直接 401。

官方推荐姿势:开发者各自配自己的 OpenAI / DeepSeek / 百炼 key + 显式开发标记触发兜底。

⚠️ 平台 token 不签发给开发者。dev token / CLI 一键拉 token 等方案我们均不提供——平台 token 是绑定"客户端运行时 + 最终用户"的 nonce 凭据,签发给开发者长期持有 = 计费归属混乱 + 绕过白名单审计 + token 泄漏风险。如果你需要用平台同款模型测口径,直接装 LoongClaw 客户端跑一次端到端是最准确的做法(那条路径就是生产路径)。

开发期 MCP 工具逻辑(参数解析、数据流、业务规则)和 LLM 模型解耦,用自己的 OpenAI / DeepSeek key 测出能跑通,生产期换成平台模型也能跑通。release 前装客户端冒烟一遍即可校准 prompt 工程口径。

推荐写法(fail-fast + 显式开发标记)

import os
from openai import OpenAI

def _make_openai_client() -> OpenAI:
    """
    生产路径:客户端注入 OPENAI_BASE_URL → 走平台 LLM(用户余额扣费)
    开发路径:必须显式设 LOONGCLAW_DEV=1 + 自带 OpenAI/DeepSeek key
    其它情况:fail-fast,避免静默走错路径
    """
    # 1) 生产:客户端注入了 base_url(这是路径标志,比 OPENAI_API_KEY 更可靠
    #    —— 开发者本机可能因为别的项目就有 OPENAI_API_KEY)
    if os.environ.get("OPENAI_BASE_URL"):
        return OpenAI()  # 自动读 env

    # 2) 开发:显式 LOONGCLAW_DEV=1 才走兜底
    if os.environ.get("LOONGCLAW_DEV") == "1":
        api_key = os.environ.get("LOONGCLAW_DEV_OPENAI_API_KEY")
        # base_url 选填:用 OpenAI 官方 key 不填;用 DeepSeek/百炼/其它兼容 key 才填
        base_url = os.environ.get("LOONGCLAW_DEV_OPENAI_BASE_URL")
        if not api_key:
            raise RuntimeError(
                "LOONGCLAW_DEV=1 但未设 LOONGCLAW_DEV_OPENAI_API_KEY;"
                "请配置开发期 LLM key(自己的 OpenAI/DeepSeek/百炼 key 均可)"
            )
        return OpenAI(api_key=api_key, base_url=base_url)

    # 3) 既无生产 env 也无开发标记 = 配置错误,立即报错
    raise RuntimeError(
        "未检测到 LoongClaw 平台 LLM 环境变量(OPENAI_BASE_URL)。\n"
        "→ LoongClaw 客户端内运行:检查 manifest.usesPlatformLlm + 白名单是否生效。\n"
        "→ IDE/CLI 本地开发:设 LOONGCLAW_DEV=1 + LOONGCLAW_DEV_OPENAI_API_KEY=<你的 key>"
    )

# 调用处
client = _make_openai_client()
resp = client.chat.completions.create(model="qwen3.5-plus", messages=[...])

三个关键设计点

  1. 生产判断必须用 OPENAI_BASE_URL,不能用 OPENAI_API_KEY——后者开发者本机可能因为别的项目就有,会误判为生产环境。
  2. 变量名加 LOONGCLAW_DEV_ 前缀——避免和 OPENAI_API_KEY 这种系统级 OpenAI 配置混淆。
  3. LOONGCLAW_DEV=1 必须显式人工设置——正常用户场景永远不会有这个 env,所以不存在"客户机巧合走兜底"的风险。极端情况客户端注入失败 → 直接 raise 报错(用户能看到),而不是静默走开发兜底 → 默默扣开发者钱 + 数据漏到第三方上游。

开发者本机一次性配置示例

# ~/.zshrc 或项目本地 .env(别提交到仓库!)
export LOONGCLAW_DEV=1
export LOONGCLAW_DEV_OPENAI_API_KEY="sk-xxx"   # 你自己的 OpenAI key
# 用 DeepSeek/百炼 时再加:
# export LOONGCLAW_DEV_OPENAI_BASE_URL="https://api.deepseek.com/v1"

上架前自查清单

  • 在 LoongClaw 客户端内装一次跑通(确认生产路径生效,不是只跑过开发兜底)
  • grep 代码确认没有把 LOONGCLAW_DEV_* 写到任何 manifest / 默认值 / 上传产物里(这些只能存在于开发者本机环境变量)
  • 关掉所有 LOONGCLAW_DEV* env 直接跑 server.py,应该看到清晰的 fail-fast 报错而不是 401 / 502 / 静默调到 OpenAI 官方

6. postInstallCommands — 需要浏览器/字体/模型时怎么办

6.1 场景

playwright 需要下载 Chromium;transformers 需要拉模型权重;matplotlib 需要装中文字体。这些不能靠 pip install 解决,必须在安装完依赖之后跑额外命令。

6.2 写法

.publish.json 里加一项(或让 AI 帮你改 manifest):

{
  "postInstallCommands": [
    ["python", "-m", "playwright", "install", "chromium"],
    ["python", "-m", "nltk.downloader", "punkt"]
  ]
}

每个元素是一个命令数组(不是字符串,防 shell 注入)。LoongClaw 客户端会在 pip install 完成后逐个执行。

6.3 特殊处理

命令数组里如果第一个元素是 "python",客户端自动替换为 venv 内的 Python 路径(Windows 是 venv\Scripts\python.exe,Unix 是 venv/bin/python)。你不用关心跨平台。

6.4 不要在 postInstallCommands 里重复写 pip install -r requirements.txt

LoongClaw 客户端在 postInstallCommands 之前已经自动跑过一次 pip install -r requirements.txt,所以你不需要再写一遍——会重复装包浪费时间。

{
  "postInstallCommands": [
    // ❌ 不要这样写——客户端已经自动装过依赖了
    ["python", "-m", "pip", "install", "-r", "requirements.txt", "-i", "https://pypi.tuna.tsinghua.edu.cn/simple"],
    // ✅ 只写真正的 post-install 步骤
    ["python", "-m", "playwright", "install", "chromium"]
  ]
}

关于国内镜像源:LoongClaw 客户端 v1.31+ 内嵌 Python 是隔离环境,不再读用户系统 pip config——一律默认走清华镜像 + pypi.org 兜底,并把镜像写入插件 venv 的 pip.conf/pip.ini。你的 postInstallCommands 里跑 python -m pip install ... 会自动用这套镜像,不需要自己加 -i 参数。如果你的插件依赖私有索引,用 --extra-index-url 即可。


7. Python 版本与依赖策略

重要:客户端 ≥1.31 已内嵌 Python 3.12.13

LoongClaw 客户端 1.31 开始,安装包自带 python-build-standalone 的 Python 3.12.13(mac-arm64 / win-x64 双平台)。终端用户不需再自己安装 Python

对你(插件作者)意味着:

  • 仍然需要在 manifest.json 声明 requiredPython 范围,客户端会校验内嵌版本是否在范围内
  • 内嵌版是 3.12,你的插件锁死 ==3.10 / <3.12 会被拒绝——推荐写 >=3.10,<3.13
  • 系统 python 不再被使用。插件在用户机器上跑的是内嵌解释器 + 插件 venv 里的依赖

7.1 requiredPython 版本范围

{ "requiredPython": ">=3.10,<3.13" }

解析规则:

  • 语法:op major.minor[,op major.minor],op 支持 >= > <= < ==
  • 不填默认 >=3.10(兼容旧插件)
  • 客户端 1.31+ 只查内嵌 Python(3.12.x)是否符合范围
  • 不符合 → 提示「请联系插件作者放宽 requiredPython 范围」——不再诱导用户去装别的版本

代码依据:mcp-store-python.tsfindPython()。1.31 起仅读 LOONGCLAW_BUNDLED_PYTHON_DIR env,不再扫系统 PATH。

7.2 requirements.txt 避坑

第一坑:C 扩展严格锁版

# ❌ 风险
greenlet==2.0.1
# 问题:Windows 用户没 MSVC Build Tools → pip 要源码编译 → 失败

# ✅ 推荐
greenlet>=2.0
# pip 找预编译 wheel,三平台都能装

DevKit publish.py 会扫 requirements.txt,对以下包的严格锁版发出警告: greenlet / numpy / scipy / pandas / lxml / pillow / cryptography / grpcio / psycopg2

代码依据:publish.py:111-135

第二坑:跨平台特定依赖

uvloop 只支持 Linux/macOS,Windows 装不上。用环境标记:

uvloop>=0.17; sys_platform != "win32"

7.3 离线 wheel 机制

DevKit 发布时会提前下载所有 wheel 包_vendor/ 目录,打进 project.zip。用户安装时即使无网也能装。

客户端 pip install 时会优先用 _vendor/ 里的 wheel。

7.X LoongClaw 客户端从哪里下载依赖(P-002 后,2026-04-28+)

MCP 作者须知:从 LoongClaw 客户端 v1.32+(对应 P-002 阶段 3 落地)起,客户端装 MCP 时 pip 链路改成:

客户端 pip install
  → 优先 https://pypi.loongclaw.net.cn/simple/  (LoongClaw 官方私有 PyPI,我们主动准备的 wheels)
  → 找不到 fallback 到 https://pypi.tuna.tsinghua.edu.cn/simple  (清华兜底)
  → ~~pypi.org 直连~~  (弃用,境外不稳定)

对你 MCP 作者的影响: 零代码改动。客户机器 pip 自动走 LoongClaw mirror,你不用改 requirements.txt 任何东西。

LoongClaw 自研 MCP 的额外收益:发版时跑 loongclaw-server:/usr/local/bin/prep-loongclaw-wheels.sh <requirements.txt> 把依赖灌进 mirror,客户机器装 MCP 时字节级一致地从我们服务器拉(避免不同客户机器装出不同版本 venv)。

Playwright Chromium driver:客户端也注入 PLAYWRIGHT_DOWNLOAD_HOST=https://pwbin.loongclaw.net.cn,你的 MCP 用 playwright 时 chromium 二进制走我们 nginx 反代缓存(国内带宽 13MB/s,境外直连可能 1MB/s 以下)。

故障演练:客户报"装不上",让客户在 ~/.loongclaw/pip-mirror.json{"indexUrl":"https://pypi.tuna.tsinghua.edu.cn/simple","extraIndexUrl":"https://pypi.org/simple"} → 重启客户端 → 走清华全量(等同 P-002 之前状态)。

详见 plan/P-002(workspace 内)。


8. 加密发布(Cython 自动编译)

8.1 为什么要加密

你的核心算法、接入的 API Key 逻辑、独特的数据处理流程……不想被用户直接 cat core.py 看光光。

8.2 DevKit 自动做了什么

发布时自动把除以下白名单外的所有 .py 编译成 .so(macOS/Linux)或 .pyd(Windows):

白名单(始终保留明文)

  • publish.py —— 你的发布脚本(硬红线排除出 zip)
  • __init__.py / setup.py —— Python 打包约定

排除非 MCP 运行时文件(v0.9.0):代码/测试/数据仪表板等非运行时文件,在项目根创建 .mcpignore(gitignore 语法)完全排除出 zip。示例:

# 当前项目根下的 .mcpignore
tests/
dashboard/
docs/
*.log

公开(public)插件白名单额外加

  • server.py —— 入口文件保持明文,客户端直接 python server.py 启动

付费(private)插件不在此列——server.py 会被强制加密(见 §8.3)。其他所有 .py 都会被加密。流程:

core.py  →  复制为 core.pyx  →  Cython 编译为 core.cpython-312-darwin.so  →  删除 .pyx 和 .c 中间文件

8.3 私有插件全量加密(壳模式)

2026-04-22 安全升级:private 付费插件的 server.py 默认也会被加密,防止核心业务逻辑源码泄露。

8.3.1 为什么

历史版本的 DevKit 永久豁免 server.py 不加密——因为 Cython 不支持直接编译含 if __name__ == "__main__": 启动块的入口文件。但很多开发者把核心调用链直接写在 server.py 里(例如 server.pycore.process() 再调 pipeline/step_1.py),结果:所有被 import 的模块都加密了,但 import 它们的 server.py 自己保留明文——攻击者 cat server.py 就能反推整条业务逻辑。

8.3.2 怎么做(自动,无需手工干预)

```text
你写的 server.py
    ↓
DevKit 加密成 server_impl.cpython-XXX.so
    ↓
DevKit 自动生成壳 server.py 塑回 zip(v0.10.2 起包含 sys.path 自注入):
    #!/usr/bin/env python3
    import os, sys
    # WHY 见 publish.py _SHELL_SERVER_PY 内详细注释(防 REV3/PERM5 类回归):
    # 嵌入式 Python(python._pth 隔离模式)和 `python -I` 启动时不会自动把
    # 脚本目录加进 sys.path,bare 导入会 ModuleNotFoundError,子进程在 MCP
    # stdio 握手前秒死,客户端只看到 -32000 Connection closed。
    sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
    from server_impl import mcp
    if __name__ == "__main__":
        mcp.run(transport="stdio")
    ↓
客户端 `python server.py` 启动 → 加载 server_impl.so → 拿到 mcp 实例 → 启动 stdio 服务

manifest.entrypoint 仍是 server.py,客户端启动逻辑零改动,老版本客户端完全兼容

8.3.3 开发者只需要遵守一个约定:FastMCP 实例命名为 mcp

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("my-private-mcp", instructions="...")  # ← 实例名必须是 mcp

@mcp.tool()
def tool_x(...):
    ...

if __name__ == "__main__":
    mcp.run(transport="stdio")     # ← FastMCP 标准写法,本地直跑也能走

为什么要叫 mcp:壳脚本需要从加密模块里拿到 FastMCP 实例启动服务。选 mcp 这个名字是因为:

  • FastMCP 官方文档示例统一用 mcp = FastMCP(...)
  • DevKit 项目骨架 (create_mcp_project) 生成的模板就是 mcp = FastMCP(...)
  • 不需要开发者额外写 def main() 或任何额外代码

为什么不用 runpy.run_module 触发加密模块的 if __name__ == "__main__" 块? Python 标准库 runpy 不支持扩展模块(.so/.pyd)——Cython 编译产物没有 Python code object 可供重放,会报 ImportError: No code object available。因此采用 from server_impl import mcp + 显式调 mcp.run() 的方式。

8.3.4 三层 Fail-Close 防护

时机 检查 失败后果
发布前预校验 access=privateserver.py 未定义 mcp = FastMCP(...)(实例名不是 mcp 立即 abort,提示改名
加密过程中 access=privateserver.py Cython 编译失败回退明文 立即 abort(不允许壳模式下 server.py 回退明文)
加密完成后 access=private 且有任何非 __init__.py 的明文业务 .py 残留 立即 abort

这三层防护闭合了「付费插件源码泄露」的根因——private + 明文业务 .py 的组合永远不可能进入 project.zip。

8.4 跨平台

DevKit 只编译当前平台的产物。用户装你的插件时,客户端会在用户机器上重新跑 pip install,但 .so/.pyd 是二进制,不会重新编译

所以:macOS 开发者发布 → .so 打进 zip → Windows 用户装了 → 缺 .pyd → 报错 ImportError: no such module

解决方案二选一

  1. 在每个目标平台各跑一次 DevKit 发布,最终 zip 里同时包含 core.cpython-312-darwin.so + core.cp312-win_amd64.pyd + core.cpython-312-x86_64-linux-gnu.so(server.py 加密后是 server_impl.cpython-XXX.so,同理需要各平台产物)。
  2. 不用 Cython(仅 public 插件):把不需要加密的文件整个放进 .mcpignore 排除出包;或者把真正保留明文的逻辑拆到独立包中以越过 Cython 编译失败。private 插件禁止明文业务 .py——Fail-Close 第 3 层会阻断。

DevKit 路线图:未来会加 GitHub Actions 模板一次性跨平台编译。当前阶段建议方案 1。

8.5 ⚠️ 禁忌

  • 禁止.pyx 源码上传到商店。DevKit 会自动删除中间文件,但如果你自己手动打包,要确保 zip 里没有 .pyx
  • 禁止 付费(private)插件把 FastMCP 实例叫成 app/server 等其他名字——壳模式约定必须命名为 mcp,预校验会拦截。
  • 禁止 把敏感信息(API Key、内部 URL)写死在代码里——就算 .so 也能被逆向工程师用 Ghidra/IDA 看出大概逻辑。敏感信息应用 configFields 让用户填。

9. 商店访问控制(public / private)

9.1 两种访问类型

谁能下载 使用场景
"public" 所有已登录 LoongClaw 用户 开源插件、免费工具、推广插件
"private" 授权列表内的用户 企业定制、付费插件、内测阶段插件

⚠️ 关键澄清

  1. private 不等于「付费」——它只是「需要授权」。付费模式本身由商务流程处理(付款后把用户加入授权表),商店代码不碰价格。
  2. accessType 必填且只能是 "public""private"Fail-Close 三层防护(Cloud 安全升级后):
    • DevKit publish.py 上传前本地预校验:缺失/非法 → 立即退出,不浪费构建时间
    • Cloud /v1/store/upload 入口:白名单拒绝,返回 400 错误
    • Cloud registry 重建时:遗留的未知值降级为 "private"(更安全的默认,不是 public) 任何拼写错误(如 "paid" / "premium")都会被拒绝上传。

代码依据:store-upload.ts —— ALLOWED_ACCESS_TYPES + validateManifest 严格校验

9.2 DevKit 怎么设

.publish.json必填

{ "access": "private" }

create_mcp_project 生成的模板里 access 字段是空字符串""),并带 ⚠️ 必填 注释——你或 AI 必须显式改为 publicprivate 后才能上传,否则 publish.py 会在本地预校验阶段报错退出。这是有意设计:防止 AI 走神漏填导致插件被默认公开。

也可以发布时让 AI 说:"发布 weather-mcp,版本 1.0.0,access 设为 private"——AI 会依次调 update_mcp_config(field="access", value="private") + update_mcp_config(field="version", value="1.0.0") + publish_mcp(...)

9.3 客户端行为

情况 用户体验
public 插件 商店直接「安装」按钮
private 插件,用户已授权 正常安装
private 插件,用户未授权 按钮变灰,提示「此插件需联系客服开通」
private 插件已安装,随后授权被撤销 下次启动时加载失败,UI 提示需重新开通

9.4 授权数据存哪

Cloud 端有个表 mcp_permissions (user_id, mcp_id)。管理员在后台添加记录即开通权限。

下载时校验逻辑:

用户请求下载 private 插件
 → Cloud 查 accessTypeCache(5 分钟 TTL)
 → private → 查 mcp_permissions 表
 → 有记录 → 放行;无记录 → 403

代码依据:store-download.ts:26-45 —— accessTypeCache + 5 分钟 TTL


10. 付费/授权模式如何落地

LoongClaw MCP 商店目前的「付费插件」模式:

10.1 流程

1. 开发者发布插件时 accessType: "private"
2. 用户在客户端看到插件 → 点「安装」
3. 客户端调用 Cloud API → 未授权 → 返回 403 + 友好提示
4. 用户看到提示联系客服 / 开发者
5. 商务走完付款流程,管理员在后台 mcp_permissions 表加记录
6. 用户在客户端重试安装 → 通过

10.2 你(开发者)需要做什么

  1. 发布时设 access: "private"
  2. 提供联系方式(微信/邮箱,在 description 里写清楚)
  3. 收款 + 授权(和 LoongClaw 管理员协调,或自己走付款然后通知平台加记录)

10.3 运营方做什么

  • 维护 mcp_permissions 表(加/删记录)
  • 管理 Store Key 体系(谁能上传插件)
  • 提供授权管理后台 UI(规划中)

10.4 不支持的模式(现阶段)

  • ❌ 按调用次数计费(客户端不上报调用数据到 Cloud)
  • ❌ 订阅制自动扣费(无订阅系统)
  • ❌ 零散充值余额兑换(积分和 LLM 余额是分开的)

如需这些模式,请联系 LoongClaw 团队走定制化方案。


11. 更新与增量发布

11.1 用户侧的增量更新体验

用户点「更新」时,LoongClaw 并无脑重新下载。流程:

1. 拉新版 manifest.json
2. 对比 sourceArchiveHash:
   ├─ 相同 → 整个目录从旧版「硬链接」复用(O(1),零下载,秒更新)
   └─ 不同 → 重新下载 project.zip + 重建 venv
3. 失败自动回滚到旧版

硬链接是什么:类比「快捷方式的升级版」,两个路径指向磁盘同一份数据,不占额外空间,切换比复制快 1000 倍。

失败回滚:旧目录在更新期间先改名 .old,成功才删,失败则改回。用户永远不会遇到「更新一半插件坏掉」。

代码依据:mcp-store.ts:230-370

11.2 开发者要做什么

什么都不用做。 DevKit publish_mcp 每次都会:

  1. 重新算 zip 的 SHA-256 → 写入 sourceArchiveHash
  2. 代码没变 → zip 相同 → hash 相同 → 用户秒更新
  3. 代码变了 → zip 变了 → hash 变了 → 用户重新下载

你只需要 bump version 字段。

11.3 版本号规则

  • 建议使用语义版本:主.次.修订(如 1.2.3
  • 客户端判断「是否有更新」用字符串不等(local.version !== entry.version),不做大小比较也不做 semver 解析——任何不相等的版本号都会触发更新,哪怕新版本号「更小」
  • 因此每次发布都必须 bump version,否则客户端认为「无更新」;反之只要改了版本号就一定能触发

代码依据:mcp-store.ts:105 / 440 —— local.version !== entry.version

11.4 所有权保护

插件一旦被你上传过,manifest 里会注入 uploadedBy: "你的 userId"。之后别人用自己的 Store Key 上传同 ID 插件会被 403 拒绝——防止恶意覆盖。

代码依据:store-upload.ts:109-130 —— existing.uploadedBy !== userId 拒绝 + 新记录注入 uploadedBy


12. 在其他 AI 客户端中使用

12.1 LoongClaw 桌面客户端

在 MCP 商店中搜索 loongclaw-devkit 一键安装。

12.2 Claude Desktop / Cursor / VS Code

在 MCP 配置文件中添加:

{
  "mcpServers": {
    "loongclaw-devkit": {
      "command": "uvx",
      "args": ["loongclaw-devkit"]
    }
  }
}

12.3 命令行直接使用

也可以不通过 AI,直接命令行运行:

# 启动 MCP server(开发调试用)
loongclaw-devkit

# 或用 Python 模块方式
python -m loongclaw_devkit

13. 常见报错 FAQ

Q1. 安装后工具不可用,AI 说「不知道有这个工具」

症结:工具名双重前缀(第 2.2 节原则一)。

检查

grep "def mcp__" server.py  # 应该没有任何匹配

修正:去掉所有以 mcp__ 开头的函数名,只写功能名。

Q2. publish_mcpLOONGCLAW_STORE_KEY 缺失

# 方式 1:环境变量
export LOONGCLAW_STORE_KEY="lc-store-xxxxx"

# 方式 2:.publish.json
{ "token": "lc-store-xxxxx" }

Store Key 获取:loongclaw.net.cn/dev/ 登录 → 申请开发者 → 审批通过 → 生成 Store Key。

Q3. 上传被拒 无权更新此插件(不是原上传者)

原因:你的 Store Key 对应的 userId ≠ 插件第一次上传时的 userId(manifest 里的 uploadedBy)。

解决

  • 用原 userId 的 Store Key 上传
  • 或换个 id(改 .publish.json 里的 id 字段)
  • 或联系管理员清掉旧所有权

Q4. Cython 编译失败,某个 .py 没被加密

DevKit 的行为:编译失败 → 自动回退为明文 + 打日志,不中断发布。

常见原因

  • macOS 缺 Xcode CLI:xcode-select --install
  • Windows 缺 MSVC Build Tools:装 Visual Studio Build Tools 或从 python.org 装 Python(自带)

临时方案(仅 public 插件):在项目根 .mcpignore 中添加该文件路径把它完全排除出包(而不是保留明文,生产发布前修好编译环境再重发)。

Q5. Windows 用户装不上,报 C 扩展编译错误

99% 原因requirements.txt 里有严格锁版的 C 扩展(numpy==1.24.0 等),Windows 没预编译 wheel。

解决:改成 >= 宽松版本:

# 改之前
numpy==1.24.0

# 改之后
numpy>=1.24,<2.0

Q6. configFields 没有被自动识别

DevKit 靠正则扫 os.environ.get("KEY", "default")。以下写法不会被识别:

# ❌ 不识别
k = "MY_KEY"
v = os.environ.get(k, "")

# ❌ 不识别(非字符串字面量)
v = os.environ.get(MY_CONST)

# ✅ 识别
v = os.environ.get("MY_KEY", "")

实在不行,手动改 manifest.json(让 AI 帮你改,然后重新上传)。

Q7. 更新了代码但用户客户端说「无更新」

可能原因

  1. 没 bump version(最常见)
  2. Cloud registry 更新失败(上传返回 ok 但 registry 没同步,5 分钟内缓存过期)
  3. 用户客户端缓存(重启客户端)

排查

# 查 Cloud registry 最新版本
curl https://api.loongclaw.net.cn/v1/store/mcp/registry.json | jq '.servers[] | select(.id == "your-id")'

Q8. 本地测试 python server.py 正常,上传后装不起来

常见原因

  • requirements.txt 漏了运行时依赖(你本地 venv 有但 requirements 里没写)
  • _vendor/ wheel 下载失败(检查 publish.py 输出的警告)
  • 用了相对路径导入 __file__ 的资源,但 zip 解压层级错了

排查:解压 project.zip 手动 pip install -r requirements.txt && python server.py 跑一遍。

Q9. 发布报 .publish.json 缺少必填字段 / 字段 access 必填且只能是 ['private', 'public']

原因:v0.6.0 起 publish.py 在上传前本地预校验 id / name / description / version / author / access 六个字段,缺任何一个或 access 不在白名单内 → 立即退出。

修法:编辑 .publish.json 补全字段:

{
  "id": "weather-mcp",
  "name": "和风天气插件",
  "description": "查询全球城市天气,支持中英文城市名(≥10 字符)",
  "version": "1.0.0",
  "author": "你的名字",
  "access": "public"
}

或让 AI 调 update_mcp_config(field="author", value="你的名字") / update_mcp_config(field="access", value="public") 补全(v0.9.0 起已删除 --reconfigure 交互式配置,统一走 AI 工具路径)。

为什么这么严:2026-04-22 发生过「5 个 MCP 上传后全被标成 public 可免费下载」的事故,根因是旧版本对 access 字段有默认降级 fallback。修复后本地 + Cloud 双层拦截,宁可报错也不静默默认。

Q10. 上传报 上传被中断(Broken pipe / Connection reset)

✅ v0.8.0 已修复:DevKit 现在优先使用 requests + requests-toolbelt.MultipartEncoder 做流式上传(带 Expect: 100-continue + 分段 timeout),不再把 zip 整体拼进内存。升级命令

pip install -U loongclaw-devkit  # 应为 >= 0.8.0

如果升级后仍报依赖缺失错误:v0.9.0 起 setuptools / wheel / Cython / pip / pathspec / requests / requests-toolbelt 已声明为 devkit 运行时依赖,pip install -U loongclaw-devkituv tool install loongclaw-devkit 自动带齐。如果你用了 pipx 独立 venv 或手工 pip install 老版本,修复

pip install -U loongclaw-devkit  # 应 >= 0.9.0
# 重新让 AI 调 publish_mcp 即可

最终兜底方案(极端情况下):如果以上都不行,可以用 curl 手动上传——本地打包产物在 .loongclaw-build/staging/

curl -X POST https://api.loongclaw.net.cn/v1/store/upload \
  -H "Authorization: Bearer lc-store-YOUR_STORE_KEY" \
  -F "manifest=@.loongclaw-build/staging/manifest.json;type=application/json" \
  -F "archive=@.loongclaw-build/staging/project.zip;type=application/zip" \
  -F "accessType=public"

三个字段名不能写错:manifestarchiveaccessTypepublicprivate,必须和 .publish.jsonaccess 字段一致)。成功响应:{"ok": true, "id": "...", "version": "..."}

注意:curl 绕过的只是 DevKit 本地上传实现,不绕过任何服务端安全检查——Store Key 认证、manifest 字段白名单、私有包明文扫描、所有权(uploadedBy)校验在服务端全都照跑。


14. 参考代码:duanju-mcp 实战样例

duanju-mcp 是短剧自动发布插件,LoongClaw 内部使用,是一个复杂场景样例。

关键看点

  1. 多模块拆分mcp_server.py 作为入口,逻辑分散在 mcp_preflight_tools.py / mcp_query_tools.py / mcp_pipeline_tools.py
  2. configFields 复杂用法:比特浏览器端口、发布路径等 15+ 配置项
  3. postInstallCommands:装 Playwright Chromium
  4. companionSkill:关联 duanju-full-pipeline-executor Skill

建议当作写复杂插件时的参考——结构清晰、分层合理。


15. 附录

附录 A:命令行紧急逃生(高级用法)

DevKit 的日常路径是让 AI 调工具(§3)。下面的命令行仅用于 devkit MCP 服务挂了CI 流水线 场景,日常别用。

# 启动 DevKit 自己作为 MCP server(调试用)
loongclaw-devkit

# 紧急逃生:直接跑 devkit 内部的 publish.py
# 1) 找到 devkit 安装位置
DEVKIT_DIR=$(python -c "import loongclaw_devkit, pathlib; print(pathlib.Path(loongclaw_devkit.__file__).parent)")

# 2) 在你的 MCP 项目目录执行
cd ~/projects/weather-mcp
python "$DEVKIT_DIR/publish.py" --auto --json-output --version 1.0.1
python "$DEVKIT_DIR/publish.py" --auto --json-output --access private --version 1.0.1
python "$DEVKIT_DIR/publish.py" --auto --json-output --no-upload        # 只打包不上传

v0.9.0 已删除 --reconfigure 和交互模式;--access 只接受 public / private。配置变更统一走 update_mcp_config 工具。

附录 B:Store Key 申请流程

  1. 访问 loongclaw.net.cn/dev/ 登录
  2. 提交开发者申请(填个人/公司信息、开发目的)
  3. 等待管理员审批(通常 1 个工作日)
  4. 审批通过后生成 Store Key(形如 lc-store-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  5. 配置到环境变量或 .publish.json

⚠️ Store Key 保管

  • 不要上传到 Git(.publish.json 默认在 .gitignore 里的话 OK;否则用环境变量)
  • 泄露后立即到开发者中心吊销 + 重新生成

附录 C:调试技巧

本地测试 MCP server(不发布):

cd ~/projects/weather-mcp

# 方式 1:直接跑(会等待 stdin)
python server.py
# 输入 JSON-RPC 请求(高级用户)

# 方式 2:MCP Inspector(可视化调试)
npx @modelcontextprotocol/inspector python server.py
# 浏览器打开 http://localhost:5173 图形化调工具

装到 LoongClaw 本地调试(不过 Cloud):

编辑 ~/.loongclaw/mcp-servers.json,手动加一项(CC 标准格式,Claude Desktop / Cursor 同结构):

{
  "mcpServers": {
    "weather-mcp-dev": {
      "command": "python",
      "args": ["/Users/you/projects/weather-mcp/server.py"],
      "env": { "HEFENG_API_KEY": "..." }
    }
  }
}

重启 LoongClaw 即生效。这种方式不走商店,不需要上传。

附录 D:能力边界速查

能力 DevKit 支持? 备注
FastMCP + stdio 核心
HTTP/SSE transport 未来支持
Cython 加密 .py 自动
离线 wheel 打包 自动
增量更新 对开发者透明
configFields 自动生成 os.environ.get
多 Python 版本约束 requiredPython
postInstallCommands manifest 字段
Private 授权 accessType: private
跨平台一次性编译 ⚠️ 需各平台各发一次
Node.js runtime 类型定义预留,未落地
按调用计费 不支持
MCP Resources / Prompts ⚠️ FastMCP 原生支持,但 LoongClaw 当前主要消费 tools

License

MIT


文档结束。 有问题?到 LoongClaw 开发者中心 反馈。

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

loongclaw_devkit-0.10.9.tar.gz (112.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

loongclaw_devkit-0.10.9-py3-none-any.whl (101.4 kB view details)

Uploaded Python 3

File details

Details for the file loongclaw_devkit-0.10.9.tar.gz.

File metadata

  • Download URL: loongclaw_devkit-0.10.9.tar.gz
  • Upload date:
  • Size: 112.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for loongclaw_devkit-0.10.9.tar.gz
Algorithm Hash digest
SHA256 4fdeca315457c3ccd728070aac0d53f80259deebb3d0fe656d3caf6bcc750944
MD5 5699ad5d3d1c42e17d2b6f1267029ebd
BLAKE2b-256 5868763ff0142c12c4cebdb89a73bdb68e7d76b5b78fd802ea25d4f461c964bd

See more details on using hashes here.

File details

Details for the file loongclaw_devkit-0.10.9-py3-none-any.whl.

File metadata

File hashes

Hashes for loongclaw_devkit-0.10.9-py3-none-any.whl
Algorithm Hash digest
SHA256 8b8039ca09474b0ec11564496f21bb74e508a193a88e7b6a0bc35922345e9409
MD5 c98474d4b6ff66996e10a6b1052bcff8
BLAKE2b-256 5b9bc4f23c1560cd1c9f8c4b9740a29d9c64ae458ebc325f161ec8a7621c0914

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page