Metadata-Version: 2.4
Name: a02-mock-career-mcp
Version: 0.3.0
Summary: A02 职业资源检索 Mock MCP Server：课程检索 / 职位检索 / 天气查询（演示数据，职位已标注）
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: mcp<2.0.0,>=1.9.0
Requires-Dist: pydantic>=2.0

# mcp/ · N5 执行环节 MCP 插件包

N5「执行」环节的 MCP 主轨（E8 评分核心）。一个 Server 暴露 3 个工具，百宝箱插件层注册后，由 N5 的两个「插件」节点调用。

## 文件清单

| 文件 | 作用 |
|------|------|
| `mock_server.py` | MCP Server 本体 v0.3（fetch_courses / fetch_jobs / fetch_weather；三传输可切） |
| `test_client.py` | 联调自测：拉起 Server → 完整 MCP 握手 → 逐工具调用 → 结构校验 |
| `requirements.txt` | 依赖（`mcp` 包，**钉死 <2**：2.x 改名 MCPServer 不兼容，实测踩坑） |
| `README.md` | 本文件：启动 / 自测 / 平台接入三条路线 |

## 快速开始（3 步 · 5 分钟）

```powershell
# ① 建虚拟环境（首次）
python -m venv .venv
.\.venv\Scripts\Activate.ps1

# ② 装依赖
pip install -r requirements.txt

# ③ 体检（不联网）
python mock_server.py --selftest
# 期望最后一行：selftest ALL PASS（7 用例 + 2 结构红线）

# 联调（拉起 Server 走完整 MCP 协议链，= 平台将来干的事）
python test_client.py
# 期望最后一行：ALL PASS：MCP 全链路（握手/列工具/调用/结构）通过
```

> test_client 通过 = Server 侧无问题。**百宝箱注册后仍连不上，问题必在"平台→你机器"这一段网络**（见下面平台接入），不在代码。

## 运行配置（环境变量，全部可选）

| 变量 | 默认 | 说明 |
|------|------|------|
| `MCP_TRANSPORT` | `streamable-http` | `sse` → 挂 `/sse`；`stdio` → 标准输入输出（一键部署用，无端口） |
| `MCP_HOST` | `0.0.0.0` | 对外可访问 |
| `MCP_PORT` | `8000` | 端口冲突时换（**实测**：本机 8000 被残留静态服务占用） |

三种传输均已 test_client 全链路验证（2026-09-18）。

## 百宝箱平台接入（面板实测 2026-09-18 · 详细手册 = docs/15 附录 D）

**路径**：百宝箱 → 插件 → 新建插件 → 左侧「**创建 MCP 服务**」。面板「MCP 创建方式」两条路，对应三种玩法：

### 路线 A：先跑通结构（10 分钟，探路日配套）
- 插件市场找官方通用 MCP 插件建测试插件，把 N5「插件」节点的入参引用/输出引用名跑通（A.2 归一化吃的是输出结构）
- 本 Server 接入后工作流层零改动

### 路线 B：自部署 MCP（探路日先端到端）
- 面板选「**自部署 MCP**」→ 填公网 URL
- 本机起 Server（streamable-http → `/mcp`；平台报协议错换 `MCP_TRANSPORT=sse` → `/sse`）
- 公网化：内网穿透（cpolar/ngrok，`ngrok http 8000`）或免费云部署（Render/HF Space）
- ⚠ 免费档坑：穿透重启 URL 变、限流、答辩现场网络——只做探路，不做演示依赖

### 路线 C：百宝箱一键部署（★推荐正式版）
- 面板选「**百宝箱一键部署 MCP**」+ 安装方式 **uvx**——平台把 stdio Server 托管到支付宝小程序云，**免穿透免服务器**
- 前置：包发布到 PyPI（**`pyproject.toml` 已落库并本机验证**：`pip install .` → 入口 `mock-career-mcp` 可拉起 stdio 服务；剩 `python -m build` + `twine upload`，步骤见 docs/15 附录 D.2），本机先 `uvx a02-mock-career-mcp` 验证
- 面板 MCP 服务配置 JSON：

```json
{
  "mcpServers": {
    "a02-career": {
      "command": "uvx",
      "args": ["a02-mock-career-mcp"],
      "env": {}
    }
  }
}
```

- Server 已支持 stdio（v0.3，stdio 联调 ALL PASS）；**stdio 模式严禁 print 到 stdout**（协议流污染，代码已禁，改代码别破坏）
- ⚠ **30 天无调用自动释放云资源**（面板黄条原文：状态重置"未发布"，所有关联应用无法调用）→ 每周跑一次 N5 试运行保活，写进阶段门检查单

**踩坑实录（test_client 联调发现）**：mcp SDK 的 stdio_client 拉子进程**不继承自定义环境变量**——`StdioServerParameters` 必须显式传 `env={...}`，否则子进程拿不到 `MCP_TRANSPORT` 跑错模式。

## 验收清单（docs/15 §3 附加验收 · 平台侧）

- [ ] `python mock_server.py --selftest` ALL PASS
- [ ] `python test_client.py` ALL PASS
- [ ] 百宝箱插件详情页能看到 3 个工具，逐个「测试」通过（截图存 E8 素材）
- [ ] N5 试运行用例 #1：两个插件节点返回真实（演示）数据，entries 非 fallback
- [ ] 用例 #4 拔 Server：降级表现记录回 docs/15 §0.2 ③（阻断 → 录屏备份；不阻断 → 现场拔线演示）

## 红线（E8 合规）

1. 所有职位字段带**（演示）**后缀，绝不冒充真实岗位
2. 课程 URL 只用 N4 兜底池已人工核验的站点级链接，不编深链
3. 返回统一 `{status:"success", data:[...], latency_ms}` 骨架——N5 A.2 归一化按此取数

## 升级真实 API（Day 14-18）

只改 `mock_server.py` 里 `COURSES`/`JOBS` 的取数逻辑（本地列表 → HTTP 请求合规公开 API），**工具签名与返回结构不变**——插件层、N5 工作流层零改动。「Server 端替换、插件层不动」的解耦设计，答辩讲这个。
