tarkov-mcp
by OatmeaILL
README.md
# Tarkov MCP — 垃圾箱截图识别 + PVE 查价 + 出售推荐
一个 MCP (stdio) 服务:**塔科夫垃圾箱/仓库截图 → OCR 标签计数识别 → PVE 物价 →
任务/藏身处需求 → 出售推荐**,一次调用全链路完成,零视觉 token。
> 面向两类读者:**调用方模型**(只用工具,重点读 §4/§5)和
> **部署/维护者**(重点读 §2/§3/§7/§9)。识别原理与调参史见 `HANDOFF.md`。
---
## 目录
- [1. 效果图(识别截图实拍)](#1-效果图)
- [2. MCP 配置(即抄即用)](#2-mcp-配置即抄即用)
- [3. 数据源与口径](#3-数据源与口径)
- [4. 工具清单(调用方模型重点读)](#4-工具清单调用方模型重点读)
- [5. 识别能力与边界](#5-识别能力与边界)
- [6. 直接脚本调用](#6-直接脚本调用不经-mcp)
- [7. 测试与诊断](#7-测试与诊断)
- [8. 输出示例(单物品查价)](#8-输出示例单物品查价)
- [9. 踩坑记录](#9-踩坑记录改代码前必读)
- [10. 架构](#10-架构)
- [11. 环境变量](#11-环境变量)
- [12. 本地调试](#12-本地调试)
---
## 1. 效果图(识别截图实拍)
以下为真实游戏截图的识别叠加结果(绿色 = 普通物品,黄色/橙色 = 高价值物品,
带中文标注与网格坐标):
**垃圾箱截图 1 识别结果**

**垃圾箱截图 2 识别结果**

**大仓库截图识别结果**

> 原始测试样本位于 `tests/samples/`,`tests/out/*_overlay.png` 为完整分辨率叠加图。
---
## 2. MCP 配置(即抄即用)
`~/.workbuddy/mcp.json`:
```json
{
"mcpServers": {
"tarkov": {
"type": "stdio",
"command": "C:\\Python314\\python.exe",
"args": [
"E:\\Programming\\xioamaipian\\0TarkovMCP\\run_server.py"
],
"env": {
"TARKOV_GAME_MODE": "pve",
"PYTHONPATH": "E:\\Programming\\xioamaipian\\0TarkovMCP\\.pylibs"
},
"disabled": false
}
}
}
```
**关键点(缺一不可)**:
- **Python**: `C:\Python314\python.exe`(3.14.4)
- **PYTHONPATH 必须指向 `.pylibs`**:mcp 1.x、scipy、rapidocr-onnxruntime **1.4.4**
全部装在这里。不设或指错 → import 到全局 site-packages 的 rapidocr 1.2.3 →
`KeyError: 'model_path'` 崩溃;或 mcp 2.x → `No module named 'mcp.server.fastmcp'`
- **TARKOV_GAME_MODE=pve**:走 json.tarkov.dev 的 `/pve/items` 端点(PVE 物价)。
缓存按 gameMode 校验,模式不符自动重抓
- **修改本仓库代码后必须重启 MCP 服务**(server 进程在启动时加载代码与注册
docstring,老进程永远跑旧代码)
## 2. 数据源与口径
| 项 | 值 |
|---|---|
| API | `https://json.tarkov.dev/{gameMode}/items`(pve / regular / pvp-season) |
| **价格口径(定版)** | **跳蚤均价 = 行情主口径**(表列/总价值/建议判断);**24h 最低 = 急卖地板价**(尾注参考。PVE 市场浅,甩卖单会砸出极低单,别按地板价贱卖) |
| 缓存 | `cache/db/full_items_cache.json`,TTL 60 分钟(`TARKOV_CACHE_TTL_MIN` 可调),**按 gameMode 校验** |
| 任务/藏身处 | eftarkov 统计页,24h 重爬,pve/pvp 后缀自动区分 |
| 任务专属道具 | **识别字典自动剔除**(不可上架 + 无商人收购 + 无基础价,275 个 FIR-only 物品)——它们不会出现在玩家垃圾箱,留在字典只会被噪声误命中 |
## 4. 工具清单(调用方模型重点读)
| 工具 | 用途 | 何时用 |
|------|------|--------|
| `inventory_from_screenshot(image_path)` | **主工具**:识别 + 逐物品查价 + 需求标记 → Markdown 成品报告(含推荐出售列 + 叠加图路径 + 行情参考尾注) | 用户发仓库/垃圾箱截图时 |
| `recognize_tarkov_junkbox(image_path, detail)` | 纯识别(无价格)。`detail="summary"`(默认,~0.8k token,counts 数量摘要)/ `"full"`(逐格明细 ~11k) | 只要数量、不要价格时 |
| `query_item_price(item_name)` | 单物品查价 + 出售建议 + 任务需求 + 弹药对照 | 用户点名某物品 |
| `search_items(query, top_n)` | 名称模糊搜索(消歧用) | 查价前不确定物品名 |
| `get_price_by_id(item_id)` | 按 ID 精确查价 | search 消歧后 |
| `check_item_usage(item_name)` | 查物品是哪些任务/藏身处需要(能不能卖) | 单独问用途 |
| `sync_items(force)` / `refresh_usage_data(force)` | 手动刷新物品价格索引 / 任务统计数据 | 价格疑似过期 |
### 输出规范(docstring 中已声明,调用方必须遵守)
1. **`inventory_from_screenshot` 返回的 Markdown 是成品**:列(物品/数量/跳蚤均价/
小计/**推荐出售(跳蚤/具体商人)**/任务藏身处)、价格口径、单位(₽)已定版——
**原样输出给用户,不要重排版、改列名、换口径、省略尾注**,最多在前面加一句自己的话
2. **识别叠加图必须每次自动展示**:`meta.overlay_image`(或报告尾部路径)调
`present_files` 展示——不要等用户要求,也**不要自己用 OpenCV 画框**
3. **"推荐出售"列已自动比价**(跳蚤均价 vs 最高商人价):跳蚤高 →
`跳蚤 \`X\`(多 \`Y\`)`;商人高 → 具体商人名。引用时保持原样,不要重新判断
4. 引用数量用 `counts` 摘要;坐标用 `行X列Y`,禁止"左排/上边那堆"等模糊描述
5. 汇报格式统一:**一句总数("共 X 件 / Y 种")→ 按数量降序的物品清单 → overlay 展示**
6. 用户问"值多少钱"时引用报告数字,**不要自己心算或换算**
## 4. 识别能力与边界(调用方须知)
- **管线(v5.9.2)**:网格周期检测(含边缘部分格)→ 三级 OCR(整图双通道
det=1920 强制放大 + 局部拼贴 CLAHE + 逐格补召)→ 噪声过滤(99/100、×2、①②
等数量标记 + OCR 误读纠正表)→ 单字精确/模糊匹配 → 短标签跨界重归属 →
短名消歧(BEAR=干员玩偶、工具=输血工具、TG=SJ1 注射剂等)→ 多格冲突消解 →
未识别簇切图
- **`unresolved[]`**:未能确定性识别的格簇,每项带切图路径 + 已检出文本。
**视觉兜底**:模型读切图认出物品 → `query_item_price` 补价,并向用户说明
这部分是 OCR 极限
- **低置信(score<0.9)或用户质疑某格**:读该格切图人工确认
- 剩余漏检主因 = 标签像素 10-12px + 低对比(白底白字,如 DVD 光驱);
**根治靠更高分辨率截图**(1440p/4K 下文字像素翻倍)
## 6. 直接脚本调用(不经 MCP)
```bash
PYTHONPATH="E:\Programming\xioamaipian\0TarkovMCP\.pylibs" TARKOV_GAME_MODE=pve \
C:/Python314/python.exe -c "import sys; sys.path.insert(0, '.'); \
from tarkov_mcp.server import inventory_from_screenshot; \
print(inventory_from_screenshot('tests/samples/垃圾箱测试2.png'))"
```
- 所有依赖在 `.pylibs`(mcp 1.x / scipy / rapidocr-onnxruntime 1.4.4 等)——
**脚本调用也建议带 PYTHONPATH**,与 MCP 进程保持一致(全局 site-packages 版本混杂)
- 识别结果落盘:`cache/out/<图名>_overlay.png`(叠加图)、
`cache/inv_cells/<图名>/`(未识别簇切图)、`cache/logs/log.txt`(日志含 traceback)
## 6. 测试与诊断
```bash
C:/Python314/python.exe tests/run_bench.py --save --overlay # 全样本回归 + 固化 baseline + 出叠加图
C:/Python314/python.exe tests/check_consistency.py --from-result # 数量一致性自检
```
- 样本 `tests/samples/`,baseline `tests/baseline.json`
- 当前基准:垃圾箱1 132 件/67 种、垃圾箱2 133 件/74 种、大仓库 290/121 与 262/129
## 8. 输出示例(单物品查价)
```markdown
| 项目 | 价格 |
|------|------|
| 跳蚤市场 · 24h 均价 | `466,208` ₽ |
| 跳蚤市场 · 24h 最低(急卖地板价) | `400,000` ₽ |
| 跳蚤市场 · 24h 最高 | `511,111` ₽ |
| 跳蚤市场 · 在售挂单 | 209 |
💡 **建议跳蚤市场出售**:行情约 `466,208` ₽(比最高商人收购多 `351,662` ₽)
**📌 任务 / 藏身处需求**:共需 4 个(⚠️ FIR)——卖掉前先留够任务数!
```
## 8. 踩坑记录(改代码前必读,完整调参史见 HANDOFF.md)
1. **网格基准偏移搜索必须全范围 `[0, p)`**——曾只扫前 24px,首格偏移大的截图
整个网格歪掉(切格全错、标签被切进相邻格、大片漏检)
2. **边缘部分格**(截图裁掉一部分的外圈格,残留 ≥60% 格宽)必须参与识别
3. **位置过滤标签不可行**(标签跨格线 + 歪基准污染测量);噪声靠 `_NOISE_RE`
内容过滤 + `_OCR_FIX` 误读纠正表(绚索→绳索、推血工具→输血工具)
4. **短名消歧**:`BEAR`/`USEC`/`工具`/`TG` 被多个物品共用(狗牌 vs 干员玩偶、
一套工具 vs 输血工具、臂带 vs SJ1 注射剂)→ `_pick_by_footprint` 按
"footprint 真放得下 + name 包含短词的更具体名"裁决
5. **多格候选必须 footprint 放得下**,否则拒绝——宁可漏进未识别簇,不把
1×1 错标成 2×2
6. **任务专属道具剔除在 db 层**(`all_names_tradable`)——主匹配/短名索引/
包含裁决三个通道必须同源,漏一个任务道具就会经短名通道"复活"
7. **缓存必须校验 gameMode**(PVE/PVP 价格完全不同,旧模式缓存会被误用)
8. 价格口径定版:**均价=行情**(表列/总价值/建议判断)、**最低价=急卖地板参考**
(尾注)——用户先要求最低价、见米屈肼甩卖单砸地板后改定均价
9. **单字标签("药"=一堆药)只认字典别名精确匹配**,partial 绝不放宽
## 9. 架构
```
tarkov_mcp/
├── server.py FastMCP 入口(stdio),8 个工具 + 输出规范 docstring
├── run_server.py 无 cwd 依赖的启动脚本(客户端用)
├── icon_base/ 物品图标(透明 base-image 版)
└── core/
├── app.py 单例生命周期:索引自动同步 + 启动预热
├── config.py 常量 / 环境变量(GAME_MODE、TTL)/ 数据目录
├── network.py json.tarkov.dev 客户端(/pve/items,缓存按 gameMode 校验)
├── database.py SQLite + FTS5(all_names_tradable 剔除任务道具)
├── matcher.py 归一化 + FTS5 召回 + RapidFuzz 打分(文本搜索用)
├── grid.py 网格周期检测(全范围偏移搜索)
├── recognition.py v5.9.2 识别管线(三级 OCR + 消歧 + 冲突消解 + overlay)
├── inventory.py 识别 → 价格(均价口径)/需求/推荐出售汇总报表
├── ammo.py 弹药包 ↔ 散装弹互查
├── usage.py 任务/藏身处需求爬虫(eftarkov,24h 缓存,pve/pvp)
├── price_service.py Item → 价格快照
├── render.py Markdown 渲染(价格表/建议/弹药对照)
└── models.py 数据模型
```
## 11. 环境变量
| 变量 | 默认 | 说明 |
|------|------|------|
| `TARKOV_GAME_MODE` | `pve` | 游戏模式:`regular` / `pve` / `pvp-season`(影响价格端点与任务数据) |
| `TARKOV_CACHE_TTL_MIN` | `60` | 全量数据刷新间隔(分钟) |
| `TARKOV_DATA_DIR` | `项目根/cache` | 缓存根目录(db/ 索引、inv_cells/ 切图、out/ 叠加图、logs/ 日志) |
## 12. 本地调试
```bash
# 直接调用工具函数(带 PYTHONPATH!)
PYTHONPATH="E:\Programming\xioamaipian\0TarkovMCP\.pylibs" TARKOV_GAME_MODE=pve \
C:/Python314/python.exe -c "from tarkov_mcp.server import query_item_price; print(query_item_price('显卡'))"
# 走 MCP 协议(stdio)
python -m tarkov_mcp.server
```
详细接入排错见 [SETUP_MCP.md](SETUP_MCP.md);识别管线完整调参史与教训见
[HANDOFF.md](HANDOFF.md)。
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues