SPONSORED / REPO SPOTLIGHT

走进 finestructure-ai/claude-plugin:七个文件构成的 Claude Code 插件

finestructure-ai/claude-plugin 把 Fine Structure 应用平台打包成一个 Claude Code 插件,提供 /deploy、/fs-status 和 /fs-domain,外加一个真正干活的托管 MCP 连接器。值得读它的理由,与其说是它能部署什么,不如说是它揭示了插件格式本身:全部内容都是 markdown 和 JSON,不到十四千字节,没有构建步骤,也没有编译产物。

THE REPOSITORY

finestructure-ai/claude-pluginSponsored

Open finestructure-ai/claude-plugin

整个仓库只有七个文件

克隆下来,文件树一屏就能看完:

.claude-plugin/
  plugin.json        686 B
  marketplace.json   507 B
commands/
  deploy.md          3.3 KB
  fs-domain.md       905 B
  fs-status.md       741 B
skills/
  fine-structure/
    SKILL.md         4.0 KB
LICENSE              MIT
README.md            2.3 KB

没有 package.json,没有锁文件,没有 CI,没有 dist。没有任何东西需要编译或打包,也不存在会构建失败的版本。如果你一直拖着不写插件,是因为假定背后有一整套工具链,那么这就是纠正:这个格式不过是一套目录约定加两个 JSON 文件,其余都是散文。

plugin.json 是指针,不是程序

清单文件带着常见的身份字段(name、版本 0.1.0、description、author、homepage、repository、license、keywords),随后是唯一一段承担全部有趣工作的配置:

"mcpServers": {
  "finestructure": {
    "type": "http",
    "url": "https://finestructure.ai/api/mcp"
  }
}

两个键。没有 command,没有 args,没有 env。把它和大多数 MCP 配置的形态比一比:一个本地进程(npx、uvx 或者某个可执行文件路径)、一串参数,再加一张存放 API 密钥的 env 映射表。改为声明一个 streamable HTTP 端点,等于把服务器搬离用户的机器,这也是 105 个工具(skill 文件给出的数字)能藏在 686 字节清单背后的原因。用户的 Node 或 Python 版本再怎么变,也破坏不了安装,服务端的改动无需发布插件新版即可生效。代价是可复现性:你无法从客户端固定工具面。

marketplace.json 让仓库成为自己的分发渠道

Claude Code 从 marketplace 安装插件,而不是从软件包注册表,而 marketplace 就是一个列出插件及其源路径的 JSON 文件。.claude-plugin 目录里的第二个文件正是干这个的,它唯一的插件条目写着 "source": "./"。仓库同时是插件本身和分发它的 marketplace,因此发布就是一次公开的 git push:

/plugin marketplace add finestructure-ai/claude-plugin
/plugin install finestructure@finestructure

第二行里那两个一模一样的词,前面是插件名,后面是 marketplace 名,之所以撞在一起,是因为两者都叫 finestructure。如果你照搬这套布局,请给它们取不同的名字。安装说明会更清楚,也给日后添加第二个插件留出余地。

命令是带 frontmatter 的提示词模板

commands/ 目录下的每个文件都是 YAML frontmatter 加散文。deploy.md 声明了 description 和 argument-hint,也就是用户在选择器里看到的两个字符串,接着铺开一棵编号的决策树:先看项目根目录有没有带 app_id 的 .finestructure.json,没有就调用 list_apps 并按名称匹配,再没有就当作首次部署,把 $ARGUMENTS 当成应用名。fs-status.md 只有 741 字节,干的是一个 CLI 子命令的活:确定应用,调用 get_app_status、get_app_links 和 get_errors,然后给出小结。fs-domain.md 依次走过 add_custom_domain、get_domain_verification、check_domain_verification、get_domain_ssl_status 和 set_primary_domain。

设计要点在于:这些文件本身什么也不调用。它们只是点名工具、固定顺序,并描述某一步失败时该怎么办。真正的执行发生在模型调用 MCP 工具的时候。斜杠命令是一份纳入版本管理的提示词,所以评审它不是在问逻辑对不对,而是在问指令是否含糊。

写得最好的是那些否定句。deploy.md 禁止使用删除类工具,除非用户明确要求。fs-domain.md 指出 DNS 传播需要几分钟到几小时,并要求建议稍后重试,而不是卡在验证循环里。这就是用句子写成的重试策略和护栏,也正是粗糙插件会漏掉的东西。

skill 与 command:拉取与推送

skills/fine-structure/SKILL.md 只有两个 frontmatter 字段,name 和 description,而 description 读起来像触发条件而不是摘要:只要用户想部署、创建或更新应用,想连接域名,想管理数据或密钥,就使用它。这样的措辞是有意为之。命令之所以触发,是因为有人敲了它;skill 之所以触发,是因为模型把描述和眼下发生的事对上了。

内容的分工随之而定。SKILL.md 是一套心智模型,不是任务清单:在这里应用意味着什么(JSX 页面、共享组件、实体结构,没有任意服务端代码),实体是什么,哪些操作要消耗额度。接着是以工具链形式给出的工作流,从 get_app_files 到 read_app_file,再到 write_app_file、validate_app 和 publish_app,多文件修改则走变更集。再往后是错误语义,这部分单位字节的分量最重:认证错误意味着重新连接,额度错误意味着充值,两者都不该重试。缺了这层知识的智能体会对一个不可重试的失败反复重试,而在按量计费的平台上,这种循环是要花钱的。

由此可以干净地推出你自己写插件时的规则。如果一个命令文件在解释你的产品是什么,那一段就该放进 skill。命令只负责流程。

OAuth 是清单里不放任何密钥的原因

该端点通过 OAuth 2.1 配合动态客户端注册完成认证,因此第一次调用工具会在浏览器里打开授权页,令牌落在 Claude Code 的凭据存储里,而不是仓库里。派生分支天然安全,撤销在服务端完成,不必靠一次必须传到每台机器的配置修改,也没人被要求把长期有效的密钥粘进一个离公开 diff 只差一次粗心提交的文件。

有哪些值得抄进自己的插件

一些具体建议,大致按照构建顺序排列:

  • 先写 .claude-plugin/plugin.json,放上 name、version 和 description。其余都是可选的。
  • 如果你运营托管的 MCP 端点,就声明 "type": "http" 加一个 url,而不是本地命令。这一步把用户的运行时从你的支持范围里彻底删掉。
  • 在只有一个插件的阶段,把 marketplace.json 放进同一个仓库,写上 "source": "./",并且给它取一个不同于插件的名字。
  • 给每条命令都写上 frontmatter 里的 description 和 argument-hint,把它们当成对两个问题的回答:这条命令做什么,后面该输入什么。
  • 用 $ARGUMENTS,不要自创位置参数语法。这里没有解析器,只有替换。
  • 命令正文按决策树来写,并且把工具名点明。"若配置文件存在则读取 app_id,否则调用 list_apps" 比一整段意图描述更靠得住。
  • 把失败语义写下来:哪些错误是终局,哪些可以重试,不重试时该说什么。
  • 在正文里点名破坏性工具,并规定未经要求不得使用。
  • 领域模型留在 SKILL.md,操作步骤留在命令里。两者重复就是坏味道。
  • 在把任何人指向 main 之前,先用 /plugin marketplace add 对着本地路径或自己的派生分支测一遍。

粗糙之处

老实说有三处,都不致命。全部内容都是英文,而这个格式没有提供任何修补的挂钩:frontmatter 里没有 locale 字段,所以本地化要么复制一份命令文件,要么接受语言不匹配。

“不需要 API 密钥”这个说法带着一个星号。SKILL.md 承认媒体生成类工具位于 OAuth 连接之外,需要一枚带媒体权限的静态 MCP 令牌,在平台的 Studio 里创建,并以 bearer 头发送。插件对此处理得不错,它让模型说明能力缺失,而不是一头撞墙式地重试,但这毕竟是给一个以“只有一条认证路径”为卖点的设计外挂了第二条路径。

而且它是 0.1.0 版,没有 changelog,没有测试,也没有 CI。对 markdown 而言这说得过去,不过在 pre-commit hook 里加一道 JSON schema 校验,就能拦住唯一真正会让安装失败的那类错误:格式损坏的清单文件。撰写本文时,目录收录申请仍在审核,所以目前只能按仓库引用来安装。

先读三个命令文件,再读 SKILL.md,最后读两个 JSON 文件。按这个顺序,格式会自己解释自己:markdown 决定该发生什么以及按什么顺序发生,MCP 服务器决定实际运行什么,而清单文件是两者之间那道细窄的接缝。

QUESTIONS

Asked about this repository

claude code 插件最小的文件结构是什么?
一个文件:带有 name、version 和 description 的 .claude-plugin/plugin.json。命令、skills、代理和 hooks 都是上面的可选层。finestructure-ai/claude-plugin 是个有用的体量参照,因为它用上了其中好几层,总共仍只有七个文件、不到十四千字节,而且没有构建步骤。
斜杠命令在 claude code 插件里是怎么工作的?
斜杠命令就是 commands/ 目录里的一个 markdown 文件,文件名即命令名。frontmatter 为选择器提供 description 和 argument-hint,正文则是命令运行时交给模型的提示词,其中 $ARGUMENTS 会被替换成命令后面跟的内容。文件本身不执行任何东西,真正的工作必须来自模型可以调用的工具,这正是这个插件把命令和一台 MCP 服务器配成一对的原因。
在 claude code 插件里使用 MCP 服务器需要 API 密钥吗?
如果服务器讲 OAuth,就不需要。这份清单只声明了 "type": "http" 和一个 url,端点使用 OAuth 2.1 配合动态客户端注册,授权在浏览器里完成,令牌留在 Claude Code 的凭据存储中。另一种做法是用 env 块放一把密钥,能用,但会把长期有效的机密塞进一个被用户到处复制的文件。这里有一处需要留意:媒体类工具不在这条流程里,仍然需要一枚静态令牌。
怎么把一个 github 仓库变成 claude code 的插件 marketplace?
加入 .claude-plugin/marketplace.json,写上 name、owner 和 plugins 数组。如果它要分发同一仓库里的插件,就把该插件的 source 设为 "./",这个仓库正是这么做的。用户随后运行 /plugin marketplace add owner/repo,再运行 /plugin install plugin-name@marketplace-name。从 git push 到可安装的插件之间,既没有注册表,也没有发布步骤。

THE SPONSOR

The platform behind the endpoint

Fine Structure runs the hosted MCP server this plugin points at, and sponsors this publication.

finestructure.ai