关于 build-mcpb
面向开发者的技能,用于将本地 MCP 服务及其运行时打包为 MCPB。内容涵盖清单、依赖打包、验证和安全注意事项,适用于需访问本地文件、桌面应用或 localhost 服务的服务。
主要功能
- 01定义 MCPB 清单与配置
- 02打包服务端代码及依赖
- 03打包并验证 MCPB 文件
- 04配置安装时的用户设置
- 05检查本地服务的安全风险
适用场景
- 01分发读取本地文件的服务
- 02打包控制桌面应用的服务
- 03打包使用 localhost 服务的服务
MCP 相关
MCPB 包含标准的 stdio MCP 服务。宿主根据清单配置启动该服务,并通过 stdio 传递 MCP 消息。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ anthropics/ claude-plugins-official --skill build-mcpb安装后在 Claude Code 中输入/build-mcpb确认已加载。
附带文件references/local-security.mdreferences/manifest-schema.md
详细介绍
构建 MCPB(打包的本地 MCP 服务)
MCPB 是一种与其运行时一起打包的本地 MCP 服务。用户安装单个文件即可运行,无需在其机器上安装 Node、Python 或任何工具链。这是分发本地 MCP 服务的官方认可方式。
MCPB 是次要分发路径。Anthropic 推荐使用远程 MCP 服务进行目录收录——参见 https://claude.com/docs/connectors/building/what-to-build。
当服务必须在用户机器上运行时使用 MCPB——读取本地文件、驱动桌面应用、与 localhost 服务通信、调用操作系统级 API。如果你的服务只访问云端 API,那几乎肯定应该改用远程 HTTP 服务(参见 build-mcp-server)。不要为了一件本可以做成 URL 的事情去支付 MCPB 的打包税。
MCPB 包包含什么
my-server.mcpb (zip archive)
├── manifest.json ← identity, entry point, config schema, compatibility
├── server/ ← your MCP server code
│ ├── index.js
│ └── node_modules/ ← bundled dependencies (or vendored)
└── icon.png
宿主读取 manifest.json,以 stdio MCP 服务的方式启动 server.mcp_config.command,并转发消息。从你的代码角度看,这与本地 stdio 服务完全相同——唯一区别在于打包方式。
Manifest
{
"$schema": "https://raw.githubusercontent.com/anthropics/mcpb/main/schemas/mcpb-manifest-v0.4.schema.json",
"manifest_version": "0.4",
"name": "local-files",
"version": "0.1.0",
"description": "Read, search, and watch files on the local filesystem.",
"author": { "name": "Your Name" },
"server": {
"type": "node",
"entry_point": "server/index.js",
"mcp_config": {
"command": "node",
"args": ["${__dirname}/server/index.js"],
"env": {
"ROOT_DIR": "${user_config.rootDir}"
}
}
},
"user_config": {
"rootDir": {
"type": "directory",
"title": "Root directory",
"description": "Directory to expose. Defaults to ~/Documents.",
"default": "${HOME}/Documents",
"required": true
}
},
"compatibility": {
"claude_desktop": ">=1.0.0",
"platforms": ["darwin", "win32", "linux"]
}
}
server.type——node、python 或 binary。仅供参考;实际启动方式来自 mcp_config。
server.mcp_config——用于启动的字面命令/参数/环境变量。使用 ${__dirname} 表示包内相对路径,使用 ${user_config.<key>} 替换安装时配置。没有自动前缀——你的服务读取的环境变量名就是你在 env 中填写的名称。
user_config——在宿主 UI 中呈现的安装时设置。type: "directory" 会渲染原生文件夹选择器。sensitive: true 会存储到操作系统钥匙串。所有字段参见 references/manifest-schema.md。
服务代码:与本地 stdio 相同
服务本身就是一个标准的 stdio MCP 服务。工具逻辑中没有任何 MCPB 特有的内容。
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
import { readFile, readdir } from "node:fs/promises";
import { join } from "node:path";
import { homedir } from "node:os";
// ROOT_DIR comes from what you put in manifest's server.mcp_config.env — no auto-prefix
const ROOT = (process.env.ROOT_DIR ?? join(homedir(), "Documents"));
const server = new McpServer({ name: "local-files", version: "0.1.0" });
server.registerTool(
"list_files",
{
description: "List files in a directory under the configured root.",
inputSchema: { path: z.string().default(".") },
annotations: { readOnlyHint: true },
},
async ({ path }) => {
const entries = await readdir(join(ROOT, path), { withFileTypes: true });
const list = entries.map(e => ({ name: e.name, dir: e.isDirectory() }));
return { content: [{ type: "text", text: JSON.stringify(list, null, 2) }] };
},
);
server.registerTool(
"read_file",
{
description: "Read a file's contents. Path is relative to the configured root.",
inputSchema: { path: z.string() },
annotations: { readOnlyHint: true },
},
async ({ path }) => {
const text = await readFile(join(ROOT, path), "utf8");
return { content: [{ type: "text", text }] };
},
);
const transport = new StdioServerTransport();
await server.connect(transport);
沙箱完全由你负责。 Manifest 层面没有沙箱——进程以完整的用户权限运行。验证路径、拒绝逃逸出 ROOT、对 spawn 使用白名单。参见 references/local-security.md。
在从配置环境变量硬编码 ROOT 之前,检查宿主是否支持 roots/list——这是规范原生的、获取用户授权目录的方式。模式参见 references/local-security.md。
构建流水线
Node
npm install
npx esbuild src/index.ts --bundle --platform=node --outfile=server/index.js
# or: copy node_modules wholesale if native deps resist bundling
npx @anthropic-ai/mcpb pack
mcpb pack 会打包该目录,并根据 schema 验证 manifest.json。
Python
pip install -t server/vendor -r requirements.txt
npx @anthropic-ai/mcpb pack
将依赖项放入子目录,并在你的入口脚本中将其前置到 sys.path。原生扩展(numpy 等)必须为每个目标平台分别构建——尽可能避免使用原生依赖。
MCPB 没有沙箱——安全由你负责
与移动应用商店不同,MCPB 不强制实施权限。Manifest 中没有 permissions 块——服务以完整的用户权限运行。references/local-security.md 是必读内容,而非可选。每个路径都必须验证,每次 spawn 都必须列入白名单,因为在平台层面没有任何机制能阻止你。
如果你来到这里时期望从 manifest 获得文件系统/网络范围限制:它并不存在。请在工具处理程序中自行实现。
如果你的服务唯一的工作就是访问某个云端 API,那就停下——那是一个穿着 MCPB 外衣的远程服务。用户在本地运行它得不到任何好处,而你却毫无理由地承担了本地安全负担。
MCPB + UI 组件
MCPB 服务可以像远程 MCP 应用一样提供 UI 资源——组件机制与传输方式无关。比如一个浏览真实磁盘的本地文件选择器、一个控制原生应用的对话框等。
组件编写在 build-mcp-app 技能中介绍;在这里同样适用。唯一区别是服务运行的位置。
测试
# Interactive manifest creation (first time)
npx @anthropic-ai/mcpb init
# Run the server directly over stdio, poke it with the inspector
npx @modelcontextprotocol/inspector node server/index.js
# Validate manifest against schema, then pack
npx @anthropic-ai/mcpb validate
npx @anthropic-ai/mcpb pack
# Sign for distribution
npx @anthropic-ai/mcpb sign dist/local-files.mcpb
# Install: drag the .mcpb file onto Claude Desktop
在发布前,在一台没有你的开发工具链的机器上测试。MCPB 中“在我机器上能跑”的失败几乎总是源于某个依赖实际上并未被打包进去。
参考文件
references/manifest-schema.md— 完整的manifest.json字段参考references/local-security.md— 路径遍历、沙箱、最小权限