beacon-mfg-mcp 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,142 @@
1
+ # Beacon-MFG 只读 MCP 服务
2
+
3
+ 让任意支持 MCP 的主流 agent(Claude Desktop / Cline / Continue / WorkBuddy 等)能够**检索与调用**
4
+ 已经发布到 Cloudflare Pages(或 GitHub)的灯塔工厂供应商数据,**而无需 clone 整个仓库、无需任何密钥**。
5
+
6
+ > 设计边界(用户 2026-09-18 明确约定):MCP 只做**只读检索**。后端数据采集(`fetch_batch`)、
7
+ > 英文翻译(`en_backfill`)、库维护(`postfetch` / `gb_store` / `sync_assets`)等流水线**不进 MCP**、
8
+ > 不暴露、不持密钥;MCP 也不会落在任何写路径上。
9
+
10
+ ## 三个只读 tool
11
+
12
+ | tool | 用途 | 关键参数 |
13
+ |------|------|----------|
14
+ | `search_vendors` | 按 关键词 / 城市 / 国标码 检索,返回精简档案 | `query` `city` `gb` `limit` `offset` |
15
+
16
+ > **搜索语义(v1.1.1)**:
17
+ > - `query` 按**空格分词、要求全部命中(AND)**。例如 `query="精密 加工"` 匹配同时含「精密」和「加工」的记录;而 `query="精密加工"`(连写)只匹配四字**连续出现**的记录,召回更少。
18
+ > **实测对照**:`city=苏州` 时 `"精密加工"` 连写仅 **2** 条,`"精密 加工"` 分词 **26** 条(更贴合「精密加工企业」意图);单关键词(如 `"宾馆"`)分词与连写等价(`city=贵阳` 命中 57 条)。
19
+ > - **建议 agent**:把用户的多个关键词用空格拆开再传(如「上海 酒店」「精密 加工」),避免连写成一个词导致漏召回。
20
+ > - **检索架构(v1.2.0 起:按需拉取,不再全量冷启动)**:
21
+ > 早期实现每次查询都要把**全部 fp 分片**拉下来在客户端建索引,复杂度 O(数据总量) —— 11.8 万条约 5.8s,线性外推千万级约 **491s / 2.2GB 内存**,不可用。
22
+ > v1.2.0 改为 **O(命中量)**:索引在**发布侧预构建**(`scripts/gen_search_index.py`,随 `postfetch` 的 `searchindex` 步骤产出 `skills/registry/index/`),
23
+ > MCP 只拉 `meta` + 城市表 + 命中的 1~N 个词桶(512 桶,平均每桶 ~46KB)→ 求交得到候选分片 → **只拉这些分片**做精确过滤。
24
+ > **实测**:`贵阳+宾馆` 扫 9/267 片 1.1s、`苏州+精密加工` 扫 3/267 片 1.2s;结果与此前的全量扫描**逐条等价**(53 / 54 / 2 / 26 / 57 全部一致)。
25
+ > 索引缺失、版本不符或落后于数据时**自动回退**全量扫描(返回值里 `via_index` 标明本次是否走索引)。
26
+ > 千万量级下只需增大桶数(如 4096)并按城市对大分片二级切分,首次查询耗时仍与总量基本无关。
27
+ | `get_vendor` | 按 id(+国标码)取完整中文档案 | `id`(必填) `gb`(可选,自动反查) |
28
+ | `get_capability_card` | 按 id 取能力卡(工艺/设备/产能/认证等) | `id`(必填) |
29
+
30
+ 所有返回都是 JSON 文本。找不到时返回 `{ "error": ... }` 或 `has_card:false`,不会抛协议错。
31
+
32
+ ## 安装 / 接入
33
+
34
+ 服务是**零第三方依赖**的单文件(`server.py`,仅用 Python 标准库),只需 Python 3.8+。
35
+
36
+ **方式 A — 本地 git 仓库(推荐:离线 + 隐私安全 + 零 CF 流量)**
37
+
38
+ ```jsonc
39
+ // Claude Desktop / 其它 MCP 客户端配置
40
+ {
41
+ "mcpServers": {
42
+ "beacon-mfg": {
43
+ "command": "python",
44
+ "args": ["/绝对路径/到/beacon-mfg/mcp/server.py"],
45
+ "env": { "BEACON_REPO": "/绝对路径/到/beacon-mfg" }
46
+ }
47
+ }
48
+ }
49
+ ```
50
+
51
+ 本地模式只通过 `git show HEAD:<path>` 读取**已提交**内容——这是掩码态手机号(138\*\*\*\*0000),
52
+ 且不会触发 `maskphone` 的 smudge、不会碰 git index 锁。
53
+
54
+ **方式 B — Cloudflare Pages 公开端点(最省事,需联网)**
55
+
56
+ 不设置 `BEACON_REPO` 即可,默认基址 `https://beacon-mfg.pages.dev`。可改:
57
+
58
+ ```jsonc
59
+ { "env": { "BEACON_SOURCE": "https://你的自定义域名/" } }
60
+ ```
61
+
62
+ HTTP 模式带正确 `User-Agent` 与 `ETag` 304 缓存(与 App 同款策略),并落盘 `~/.cache/beacon-mcp-cache`,
63
+ 重复查询零传输。CF 部署版手机号可能是全号——隐私敏感场景请用方式 A。
64
+
65
+ ## 影响评估(对现有系统为零影响)
66
+
67
+ ### 1) 对 Android App(Beacon-MFG)— 无影响
68
+ - App 是**纯只读 HTTP 客户端**:运行时只从 `beacon-mfg.pages.dev`(主源)+ jsDelivr / raw.githubusercontent
69
+ (兜底镜像)拉 `manifest.json` → 分片,用 ETag/304 增量更新。它**不调用 MCP、不共享进程/内存/文件**,
70
+ MCP 是 agent 侧独立进程(stdio 拉起),App 根本感知不到它存在。
71
+ - 唯一共享的外部资源是 Cloudflare CDN。只要 MCP 遵守两条(发正确 UA + 复用 ETag 缓存,重活走本地 git),
72
+ 就不会触发 Cloudflare Bot Fight Mode(error 1010)——而那正是 App 更新能否成功的前提。服务已内置 UA 与缓存。
73
+
74
+ ### 2) 对 cron / GUI 流水线 — 无影响(前提:遵守两条硬规则)
75
+ cron / GUI 是**写方**:`fetch_batch` / `postfetch` 改写 `data/gb`、`data/en`、`data/phone-index.jsonl`
76
+ (经 maskphone clean 过滤脱敏),再发布到 R2 / Pages / GitHub(`fetch_batch` 还持有仓库级 PID 锁
77
+ `.fetch_batch.lock`)。MCP 是**只读**且不调用任何后端脚本,因此:
78
+
79
+ - **硬规则 1 — 只读已发布快照,不碰实时工作树**:MCP 只从「CF 公开端点」或「`git show HEAD:` 已提交内容」
80
+ 读取,**绝不读 cron 正在写的实时工作树**,避免读到半成品 JSON。本服务严格按此实现。
81
+ - **硬规则 2 — 绝不 `git checkout` / `git restore` 本仓库**:这是历史「42578 个手机号被无声掩码」事故的
82
+ 根因——smudge 过滤器会把 index 里的脱敏内容写回工作树,且 `git status` 仍显干净。本服务**只**用
83
+ `git show HEAD:`(不触发 smudge、不碰 index 锁),从根上避开。
84
+ - 端口/进程:MCP 走 stdio(无监听端口),与后端 FastAPI(认领/RFQ)端口、cron 的 PID 锁互不冲突。
85
+ - GitHub 推送 / R2 / Pages:`step_git` 用 L0 白名单 + 脱敏安全闸门,MCP 的存在不改变任何发布行为。
86
+
87
+ **结论**:在两条硬规则下,MCP 对 App、cron、GUI 全部零影响;这两条已写进 `server.py` 的实现与注释,
88
+ 无法被误用成写操作。
89
+
90
+ ## 数据源映射(与 App 完全一致)
91
+
92
+ | 数据 | 路径(相对仓库根) | 说明 |
93
+ |------|-------------------|------|
94
+ | 分片清单 | `data/manifest.json` | App 增量更新的指针,已为「免 clone 检索」设计 |
95
+ | 指纹分片(fp) | `skills/registry/fingerprint/gb/{门}/{码}.jsonl` | 精简记录,供 `search_vendors` |
96
+ | 中文全量(zh) | `data/gb/{门}/{码前2}/{码}.json` | 完整档案,供 `get_vendor` |
97
+ | 能力卡 | `skills/registry/capability/{id}.json` | 不进 git,经 R2 按需提供,供 `get_capability_card` |
98
+
99
+ ## 分发 / 版本发布
100
+
101
+ MCP 服务有两种发布渠道(详见 `mcp/RELEASE.md`):
102
+
103
+ - **GitHub Release(已配 CI)**:推送 `mcp-v*` 标签即由 `.github/workflows/mcp-release.yml`
104
+ 自动打包 `mcp/` 目录为 `beacon-mfg-mcp-mcp-vX.Y.Z.tar.gz` 并创建 Release。
105
+ - **npm 包(代码已就绪,尚未发布)**:`mcp/package.json` + `mcp/bin/beacon-mfg-mcp.js`
106
+ (Node 启动器,自动探测 Python)。截至最近一次核对,`beacon-mfg-mcp` **尚未发布到 npm 公共仓库**
107
+ (`npm view beacon-mfg-mcp` 返回 404),因此 `npx beacon-mfg-mcp` 暂不可用。发布后客户端可直接用
108
+ `"command": "beacon-mfg-mcp"`。
109
+
110
+ ### 发布到 npm 的步骤(需要 Access Token,不是 2FA 种子)
111
+
112
+ > ⚠️ **常见误区**:npm 启用 2FA 后给的「密钥 / TOTP 种子」(64 位十六进制串)是给认证器 App 生成动态码用的,
113
+ > **它本身不能用于发布**——直接拿它当 token 会返回 `401 Unauthorized`。
114
+ > 发布必须用 npm 网站生成的 **Granular Access Token**(形如 `npm_...`)。
115
+
116
+ 1. 登录 <https://www.npmjs.com> → 右上角头像 → **Access Tokens** → **Generate New Token**
117
+ → 选 **Granular Access Token**。
118
+ 2. 权限选 **Read and write**;如需 CI 自动发布,勾选 **Bypass two-factor authentication**。
119
+ 3. 生成后立刻复制(只显示一次),写入仓库根 `.env`:
120
+ ```
121
+ NPM_TOKEN=npm_xxxxxxxxxxxxxxxxxxxxxxxxxx
122
+ ```
123
+ 4. 本地发布(在 `mcp/` 目录):
124
+ ```bash
125
+ npm config set //registry.npmjs.org/:_authToken "$NPM_TOKEN"
126
+ npm publish --dry-run # 先预览将要上传的文件
127
+ npm publish
128
+ ```
129
+ 5. CI 自动发布:把该 token 配进仓库 Secrets 的 `NPM_TOKEN`,之后手动触发
130
+ `.github/workflows/npm-publish.yml` 即可(该工作流已就位)。
131
+
132
+ ### 客户端接入速查
133
+
134
+ ```jsonc
135
+ // 方式一:GitHub Release / 源码 —— 直接指向 server.py(当前可用)
136
+ { "mcpServers": { "beacon-mfg": { "command": "python",
137
+ "args": ["/路径/beacon-mfg/mcp/server.py"],
138
+ "env": { "BEACON_REPO": "/路径/beacon-mfg" } } } }
139
+
140
+ // 方式二:npm 安装后(待 npm 发布完成后可用,无需 clone)
141
+ { "mcpServers": { "beacon-mfg": { "command": "beacon-mfg-mcp", "args": [] } } }
142
+ ```
package/RELEASE.md ADDED
@@ -0,0 +1,60 @@
1
+ # Beacon-MFG 只读 MCP 服务 · v0.1.0
2
+
3
+ 让任意支持 MCP 的主流 agent(Claude Desktop / Cline / Continue / WorkBuddy 等)能够
4
+ **检索与调用**已发布到 Cloudflare Pages(或 GitHub)的灯塔工厂供应商数据,
5
+ **无需 clone 整个仓库、无需任何密钥**。
6
+
7
+ ## 设计边界
8
+ MCP 只做**只读检索**。后端数据采集、英文翻译、库维护等流水线**不进 MCP、不暴露、不持密钥**,
9
+ 也不会落在任何写路径上。对 Android App 与 cron/GUI 流水线**零影响**(详见 `mcp/README.md`)。
10
+
11
+ ## 三个只读 tool
12
+ | tool | 用途 | 关键参数 |
13
+ |------|------|----------|
14
+ | `search_vendors` | 按 关键词 / 城市 / 国标码 检索,返回精简档案 | `query` `city` `gb` `limit` `offset` |
15
+ | `get_vendor` | 按 id(+国标码)取完整中文档案 | `id`(必填) `gb`(可选) |
16
+ | `get_capability_card` | 按 id 取能力卡(工艺/设备/产能/认证) | `id`(必填) |
17
+
18
+ ## 安装(三选一)
19
+
20
+ ### 1. 从 GitHub Release 下载(推荐,零依赖)
21
+ 下载本 Release 的 `beacon-mfg-mcp-mcp-v0.1.0.tar.gz`,解压后:
22
+ ```jsonc
23
+ {
24
+ "mcpServers": {
25
+ "beacon-mfg": {
26
+ "command": "python",
27
+ "args": ["/解压目录/server.py"],
28
+ "env": { "BEACON_REPO": "/你的/beacon-mfg仓库路径" } // 可选:离线 + 隐私安全
29
+ }
30
+ }
31
+ }
32
+ ```
33
+
34
+ ### 2. npm(需先 `npm login`,仓库已配 `NPM_TOKEN` 后自动发布)
35
+ ```bash
36
+ npm install -g beacon-mfg-mcp
37
+ # 或一次性运行:
38
+ npx beacon-mfg-mcp
39
+ ```
40
+ 装好后客户端配置:
41
+ ```jsonc
42
+ {
43
+ "mcpServers": {
44
+ "beacon-mfg": { "command": "beacon-mfg-mcp", "args": [] }
45
+ }
46
+ }
47
+ ```
48
+
49
+ ### 3. 从源码(git clone)
50
+ ```bash
51
+ git clone https://github.com/eiry16/beacon-mfg.git
52
+ # 客户端 command 指向 beacon-mfg/mcp/server.py
53
+ ```
54
+
55
+ ## 环境变量
56
+ - `BEACON_REPO`:本地 git 仓库路径;设了就用 `git show HEAD:` 读(推荐:离线 + 掩码态隐私安全)。
57
+ - `BEACON_SOURCE`:HTTP 基址,默认 `https://beacon-mfg.pages.dev`(可改自定义域名)。
58
+
59
+ ## 许可
60
+ MIT
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+ // beacon-mfg-mcp 启动器:本 MCP 服务是纯 Python 标准库实现,这里只负责
4
+ // 在用户机器上找到 Python 解释器并拉起 server.py(stdio 协议)。
5
+ const { spawnSync } = require('child_process');
6
+ const path = require('path');
7
+
8
+ const serverPy = path.join(__dirname, '..', 'server.py');
9
+
10
+ // 探测可用的 Python 解释器(优先 python3,兼容 python / py)
11
+ const candidates = ['python3', 'python', 'py'];
12
+ let chosen = null;
13
+ for (const c of candidates) {
14
+ const r = spawnSync(c, ['--version'], { stdio: 'ignore' });
15
+ if (r.status === 0) {
16
+ chosen = c;
17
+ break;
18
+ }
19
+ }
20
+ if (!chosen) {
21
+ process.stderr.write(
22
+ '[beacon-mfg-mcp] 未找到 Python 3。请先安装 Python 3.8+ 并加入 PATH,再重试。\n'
23
+ );
24
+ process.exit(1);
25
+ }
26
+
27
+ const child = spawnSync(chosen, [serverPy, ...process.argv.slice(2)], {
28
+ stdio: 'inherit',
29
+ });
30
+ process.exit(child.status === null ? 1 : child.status);
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "beacon-mfg-mcp",
3
+ "version": "0.1.3",
4
+ "description": "Read-only MCP server exposing the BeaconMFG灯塔工厂 supplier directory (search vendors, get vendor detail, get capability card) to any MCP-compatible agent. No API key, no repo clone required.",
5
+ "keywords": [
6
+ "mcp",
7
+ "model-context-protocol",
8
+ "beacon-mfg",
9
+ "suppliers",
10
+ "manufacturing",
11
+ "china"
12
+ ],
13
+ "homepage": "https://github.com/eiry16/beacon-mfg#readme",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/eiry16/beacon-mfg.git"
17
+ },
18
+ "bugs": {
19
+ "url": "https://github.com/eiry16/beacon-mfg/issues"
20
+ },
21
+ "license": "MIT",
22
+ "bin": {
23
+ "beacon-mfg-mcp": "bin/beacon-mfg-mcp.js"
24
+ },
25
+ "files": [
26
+ "server.py",
27
+ "bin/",
28
+ "README.md",
29
+ "RELEASE.md"
30
+ ],
31
+ "engines": {
32
+ "node": ">=16"
33
+ },
34
+ "dependencies": {}
35
+ }