内容
# GunStore-POS 管理服务器 MCP
GunStore-POS 的本地 [MCP](https://modelcontextprotocol.io) 服务器,封装了 GunStore-POS Frappe REST API,以便您可以从 Claude 或 Codex 读取和更改**生产**设置/内容 - 切换集成配置,编辑商品定价/列表,修复记录,触发 RSR/FastBound/ATF 操作,运行 Firearms-In-Stock 报告。
> **伴侣仓库:** [`firearm-listing-import`](https://github.com/xuanji86/firearm-listing-import) - 一个 Claude Code / Codex 技能,使用此 MCP(每枪照片 + 描述 → 序列号 → WooCommerce)。从 gunstore-pos 应用中提取为独立的,可单独分发的软件包。
## 工作原理
- 一个小型**通用骨架**(`frappe_*` 工具)涵盖每个文档类型和每个白名单方法 - 当前和未来。一个**精选层**使得频繁的设置/同步/报告操作一步到位。
- 通过 HTTPS 与 Frappe 进行令牌身份验证(`Authorization: token key:secret`)。
- **安全性**:删除/取消/提交和破坏性方法 - 包括此域自己的高后果动词(处置/推送/充电/合并/发货/退货/接收/售出/结算/上线)- 需要 `confirm=true`;密码/凭证字段永远不会传输(在 Desk 中设置);模式/权限文档类型为只读。
## 安装
### 1. 生成 Frappe API 密钥
在 Desk 中,以您要扮演的用户(管理员)身份:右上角头像 → **我的设置** → **API 访问** → **生成密钥**。复制 **API 密钥** 和 **API 密钥**(密钥仅显示一次)。
### 2. 配置凭证
```bash
cp .env.example .env
# 编辑 .env:FRAPPE_BASE_URL, FRAPPE_API_KEY, FRAPPE_API_SECRET
```
`.env` 被 git 忽略。首先指向开发环境(`http://dev.localhost:8000`)进行测试,然后切换到生产环境(`https://pos.oldsteelarsenal.com`)。
### 3. 安装
```bash
uv sync # 创建 .venv 并安装依赖
```
### 4. 在您的代理中注册
`/path/to/gunstore-pos-mcp` 以下是在您克隆此仓库的位置(软件包在仓库根目录)。服务器通过其自己的文件路径加载 `.env`,因此凭证永远不会进入代理配置。
**Claude Code** - 添加到 `.mcp.json`(项目)或运行 `claude mcp add`:
```json
{
"mcpServers": {
"gunstore-pos": {
"command": "uv",
"args": ["run", "--directory", "/path/to/gunstore-pos-mcp", "gunstore-mcp"]
}
}
}
```
**Claude Desktop** - 在 `claude_desktop_config.json` 中使用相同的块。
**Codex** - 添加到 `~/.codex/config.toml`,然后 **重启 Codex** (它在启动时读取 MCP 服务器):
```toml
[mcp_servers.gunstore-pos]
command = "uv" # 或 uv 的绝对路径(如果它不在 Codex 的 PATH 中)
args = ["run", "--directory", "/path/to/gunstore-pos-mcp", "gunstore-mcp"]
startup_timeout_sec = 120
```
通过快速标准输入/输出握手(`initialize` + `tools/list`)或仅在 Codex 中列出工具来验证。
机密存储在 `.env` 中(由服务器加载),不在代理配置中。
## 工具
> **中文速查手册(按"你想干什么"组织,含安全须知与替代路径):[TOOLS.md](TOOLS.md)**
总共 79 个工具:10 个通用工具 + 53 个精选工具 + 11 个分销商工具 + 5 个 CPA 报告;75 个默认注册 - 4 个分销商队列操作通过 `GUNSTORE_MCP_DISTRIBUTOR_ACTIONS=1` 选择加入(否则不注册)。
**模式**:`GUNSTORE_MCP_MODE=cpa` 启动只读会计界面 - 正好 18 个工具(绝不写入),按名称允许的只读方法列表在客户端层面,以及 7 个集成设置文档类型阻止读取。默认(`full`)是整个界面。注册第二个服务器条目(例如 `gunstore-pos-cpa`)并使用相同的命令加上 `"env": {"GUNSTORE_MCP_MODE": "cpa"}` 以同时运行两个。
### 独立 CPA 安装
要仅安装只读会计界面(不安装完整服务器)- 例如在第二台机器或分析师代理上:
```bash
git clone git@github.com:xuanji86/gunstore-pos-mcp.git ~/gunstore-pos-mcp
claude mcp add gunstore-pos-cpa --scope user \
--env GUNSTORE_MCP_MODE=cpa \
--env FRAPPE_BASE_URL=https://pos.example.com \
--env FRAPPE_API_KEY=<key> \
--env FRAPPE_API_SECRET=<secret> \
-- uv run --directory ~/gunstore-pos-mcp gunstore-mcp
```
- **进程环境变量胜过 `.env`**:服务器以 `override=False` 加载 `.env`,因此注册中设置的 env 变量生效。独立安装不需要 `.env` 文件 - 相同的代码库可以为多个条目提供服务,并具有不同的 `FRAPPE_BASE_URL` / 模式组合(例如开发站点实例)。
- **验证**:连接后,`tools/list` 必须显示确切的 **18** 个工具和服务器名称 `gunstore-pos-cpa`。拼写错误/未知模式值拒绝启动(关闭失败)而不是静默降级到可写界面。
- **安全边界 - 在交给第三方之前阅读**:三层门控仅限制 *MCP 调用层*。注册中的 API 密钥/密钥是 Frappe 用户可以做的任何事情 - 使用系统管理员密钥,任何提取它的人都可以通过纯 REST、MCP 门控或不进行 MCP 门控进行写入。对于第三方(例如外部会计师的机器),创建具有只读角色的专用 Frappe API 用户,并使用*该*密钥对注册。
### 通用骨架
| 工具 | 用途 |
|---|---|
| `frappe_list_documents` | 列出任意文档类型(过滤器/字段/限制;`limit=0` = 所有) |
| `frappe_get_document` | 获取一个文档(单个:`name == doctype`) |
| `frappe_describe_doctype` | 字段包括自定义字段;标记密码字段 |
| `frappe_create_document` | 创建(凭证字段剥离) |
| `frappe_update_document` | 更新(凭证字段剥离) |
| `frappe_delete_document` | 删除 - 需要 `confirm=true` |
| `frappe_submit_document` | 提交草稿 - 需要 `confirm=true` |
| `frappe_cancel_document` | 取消提交的文档 - 需要 `confirm=true` |
| `frappe_run_method` | 按点路径调用任意白名单方法 |
| `frappe_run_report` | 运行脚本/查询报告 |
### 精选
| 工具 | 用途 |
|---|---|
| `get_settings` / `update_settings` | `ffl` \| `fastbound` \| `rsr` \| `payroc` \| `woocommerce` \| `dealer` \| `shipstation` |
| `find_item` / `item_stock` / `available_serials` | 类型搜索项目 / 项目库存 / 库存序列号 + 每枪价格 |
| `firearms_in_stock` | 火器库存报告 |
| `receive_goods` | 采购收货 + FFL 收购 + FastBound 推送(`confirm`) |
| `add_stock` / `set_stock` | 非序列化库存添加 / 绝对设置(`confirm`) |
| `toggle_service_need` | 序列号上的修理工标志(`confirm`) |
| `rsr_catalog_search` / `rsr_sync_catalog` / `rsr_test_connection` | RSR 目录搜索 / 完整同步 / FTPS 探测 |
| `promote_to_item` / `backfill_from_rsr` | RSR 目录行 → 可售项目 / 填充项目字段(`confirm`) |
| `fastbound_test_connection` / `push_serial_to_fastbound` / `boundbook_reconcile` | FB 探测 / 每枪修正推送(`confirm`)/ 绑定簿核对(应用需要 `confirm`) |
| `atf_verify_ffl` / `verify_supplier_ffl` / `reverify_all_ffls` | ATF eZ-Check 验证(`confirm`) |
| `woo_test_connection` / `woo_push_item` / `woo_delist_item` / `woo_reconcile` | 存储探测 / 列表 / 下架 / 核对项目 - 所有操作均需要 `site: retail\|dealer`(写入需要 `confirm`) |
| `woo_push_serial` / `woo_delist_serial` | 列表 / 下架一把枪(SKU `item_code::serial`; `site`; `confirm`) |
| `set_serial_title` | 每枪 Woo 列表标题(写入 `Serial No.item_name`; 在下一次推送时生效) |
| `pending_orders` / `pending_web_orders` | 待处理订单队列:柜台/经销商行 + 已支付的网络订单(只读;委托存储在 `consignment_queue` 中) |
| `dispose_order` / `dispose_web_order` | 预订 FFL 转移处置 - 库存出库 + FastBound 推送(`confirm`) |
| `record_payment` | 支付条目针对未支付的已提交发票;Zelle 需要 `transaction_number`(`confirm`) |
| `cancel_order` | 取消已提交的柜台/经销商订单 - 级联处置/库存/FastBound/ShipStation 反转 + 退款(`confirm` + `reason`) |
| `push_shipment` / `mark_shipped_manually` / `shipstation_test_connection` | ShipStation 标签推送(`confirm`)/ 无推送逃生口(`confirm`)/ 探测 |
| `consignment_queue` / `consignment_dealers` / `consignment_serials` / `consignment_dealer_orders` | 外发委托读取:经销商队列 / 可发货 FFL 经销商 / 可挑选序列号 / 结算队列 |
| `create_consignment_out` / `ship_consignment_out` / `push_consignment_shipment` / `mark_consignment_shipped` | 构建 / 处置+发货 / ShipStation 推送 / 手动发货并跟踪(`confirm`) |
| `retry_consignment_invoice` / `return_consignment_lines` / `cancel_consignment` | 结算发票重试 / 取回未售枪支 / 取消行或草稿(`confirm`; 取消需要 `reason`) |
| `start_4473` / `manager_override_4473` / `start_transfer_4473` | 4473 启动 / 卡住销售经理覆盖 / 客户转移(`confirm`) |
| `upload_attachment` | multipart 文件上传 → 文件文档,可选地附加到文档类型+名称 / 附件字段 |
### CPA 报告(只读;两种模式下均注册)
| 工具 | 用途 |
|---|---|
| `sales_report` | POS 销售报告, payload 原样传递(查看订单 / 订单详情 / 产品;渠道 POS/Web/B2B-手动) |
| `gl_entries` | 日期范围内的 GL 行(始终 `is_cancelled=0`;显式 `truncated:true`) |
| `financial_statement` | 损益表 / 资产负债表(日期范围)/ 试算平衡表(会计年度自动解析) |
| `tax_liability` | 从 GL 滚存销售税负债 - 账户从默认销售税模板解析,凭证分桶失败关闭,精确到美分 |
| `ar_ap_summary` | 截至某日期的 AR / AP 账龄( posting date 基础,30/60/90/120) |
## 安全注意事项
- 使用密钥的用户(管理员)= 完全访问权限。在 **本地运行**;将 `.env` 保存在 git 外(默认情况下)。
- 凭证永远不会通过 MCP 传输:密码类型和凭证命名字段在每次写入时都会被剥离。在 Desk 中设置机密。
- 所有写入操作都由 Frappe 在密钥用户下记录(审计轨迹)。
- 要撤销访问权限,请在 Desk 中重新生成该用户的密钥。