Skip to main content
Glama
GAJYA

Customer MCP App

by GAJYA
README.md
# Customer MCP App

基于已验证的 Hermes 开发环境 API 构建的客户 MCP App,并包含一个将存量项目信息详情页面嵌入 MCP Host 的验证 App。模型可按名称查询客户;支持 MCP Apps 的 Host 还会获得 React 交互界面,用于分页、查看详情、搜索外部企业,以及经过明确确认后安全新增客户。

## 能力

- `query-customers`:模型和 App 均可调用,关联客户列表 UI。
- “查看详情”:使用查询结果随附的 App 专用详情数据在本地弹框,不调用 Tool。
- `search-external-companies`:仅 App 调用,搜索新增候选。
- `prepare-customer-create`:仅准备预览和短期确认令牌,不写数据。
- `confirm-create-customer`:用户勾选并点击确认后,最多提交一次创建请求。
- `show-project-detail`:通过独立 MCP View 嵌入存量业务平台项目详情;默认打开示例项目 `18703741`。
- Streamable HTTP:`/mcp`;stdio:`--stdio`。

界面不直接连接 Hermes,也不会接触 Cookie、Session Token 或完整的原始创建资料。

## 环境要求

- Node.js 20 或更高版本。
- 能访问目标 Hermes 环境;开发环境通常还需要 aTrust/零信任连接。
- 有效的登录 Cookie。可选地同时提供业务 User ID 和 Session Token。

## 安装与配置

```bash
npm install
npm run setup:local
```

`setup:local` 会要求粘贴一次浏览器开发者工具中 dev 请求的完整 `Cookie` Header 值,输入过程不回显。脚本会自动生成:

- `.env`:已填好的 dev Base URL 和本地运行参数;
- `.local/hermes-cookie.txt`:明文 Cookie,仅当前用户可读。

两者都被 Git 忽略,服务启动时会自动加载 `.env`,不需要手动 `source`。如果当前 shell 已有 `HERMES_COOKIE`,脚本会直接使用它而不再询问。

也可以先把 Cookie Header 值复制到 macOS 剪贴板,再执行 `npm run setup:local:clipboard`;脚本不会打印剪贴板内容。

需要连接其他环境时,也可以复制 `.env.example` 后自行调整。

关键配置:

| 变量 | 必需 | 说明 |
|---|---:|---|
| `HERMES_BASE_URL` | 是 | Hermes API 根路径,例如本地代理的 `http://127.0.0.1:8081/hermes`;远端地址只允许 HTTPS |
| `HERMES_COOKIE` | 二选一 | 完整 Cookie 请求头值 |
| `HERMES_COOKIE_FILE` | 二选一 | 只含 Cookie 值的本地文件路径;自动生成时使用绝对路径 |
| `HERMES_USER_ID` | 否 | 与 `HERMES_SESSION_TOKEN` 成对配置 |
| `HERMES_SESSION_TOKEN` | 否 | 与 `HERMES_USER_ID` 成对配置 |
| `HERMES_TIMEOUT_MS` | 否 | 上游超时,默认 15000 ms |
| `LEGACY_WEB_BASE_URL` | 否 | 存量 Web 系统基址,默认 `http://localhost:8081`;远端地址必须使用 HTTPS |
| `MCP_HOST` / `PORT` | 否 | HTTP 监听地址;代码默认 `127.0.0.1:3001`,`setup:local` 为 Docker Quick Tunnel 生成 `0.0.0.0:3002` |
| `MCP_ALLOWED_ORIGINS` | 否 | 逗号分隔的浏览器 Origin 白名单 |
| `MCP_PUBLIC_URL` | 否 | 当前 Quick Tunnel 的 HTTPS URL;仅用于 Codex Host 阻断 iframe `tools/call` 时启用短期令牌兼容通道,可填写带 `/mcp` 的完整 endpoint |

`.env`、`.local/`、Cookie 和 Session Token 已被 Git 忽略;即使是 dev 凭证,也不要把真实值写进代码、文档、日志或测试。

## 启动

HTTP:

```bash
npm run build
npm run serve
```

使用 `setup:local` 生成的配置时,MCP endpoint 为 `http://127.0.0.1:3002/mcp`,健康检查为 `http://127.0.0.1:3002/health`;服务实际监听 `0.0.0.0:3002`,以便 Docker 容器通过 `host.docker.internal:3002` 访问。`0.0.0.0` 是监听地址,不是客户端 URL。

`0.0.0.0` 模式不配置固定 Host allowlist,以兼容每次变化的 `*.trycloudflare.com` Host Header;`MCP_ALLOWED_ORIGINS` 的浏览器 CORS 白名单仍然生效。当前 MCP endpoint 没有远程身份认证,随机 Tunnel URL 也不是访问控制,因此该模式仅供开发者监督下的短时本地联调。

### Docker Quick Tunnel

保持 MCP App 和 aTrust 在宿主机运行,启动 Docker Desktop 后执行:

```bash
docker run --rm \
  --name customer-mcp-tunnel \
  --dns 1.1.1.1 \
  --dns 1.0.0.1 \
  cloudflare/cloudflared:latest \
  tunnel --no-autoupdate --protocol http2 \
  --url http://host.docker.internal:3002
```

只使用本次命令新打印的 `https://<random>.trycloudflare.com/mcp`。如果当前 Codex Host 无法代理 View 内按钮调用,把同一个地址写入 `.env` 的 `MCP_PUBLIC_URL` 并重启服务;服务会启用短期能力令牌保护的 UI 兼容端点。终端必须保持运行;测试完成后按 `Ctrl+C` 同时停止 Tunnel 并删除临时容器。需要稳定域名、长期运行或多人共享时,必须移除该临时通道或另行增加受信网关身份认证和授权。

stdio:

```bash
npm run build
npm run serve:stdio
```

本地开发(监听 UI 和 Server 源码变化):

```bash
npm run dev
```

## 验证

```bash
npm run typecheck
npm test
npm run build
```

自动化测试全部使用 mock,不连接真实 Hermes 环境,也不会执行真实创建。运行和排障细节见 [运行手册](doc/customer-mcp-app/runbook.md),需求与验收标准见 [客户列表 Spec](spec/customer-list.md)。

### 项目详情嵌入验证

1. 在 `/Users/lunarjan/workspace/gjthrd_aries` 启动存量前端并确认以下地址能在浏览器中打开:

   ```text
   http://localhost:8081/apps/gjthrd_aries/project/18703741?name=2022%E6%9D%8E%E7%99%BD%E5%85%AC%E5%8F%B8%E5%80%BA%28%E4%B8%BB%E6%89%BF%29&from=ProjectList
   ```

2. 启动本仓库 MCP Server,并让 Host 调用 `show-project-detail`;不传参数即使用上述示例。
3. 如果页面被拒绝嵌入,检查实际响应的 `X-Frame-Options` 和 CSP `frame-ancestors`。
4. 如果 Host 阻止 HTTP 混合内容,把存量前端放到可访问的 HTTPS 测试地址,并更新 `LEGACY_WEB_BASE_URL` 后重启 MCP Server。

该验证 View 不读取 iframe DOM,也不通过 MCP Server 代理项目数据。登录、权限和页面内动作仍由存量系统控制;验证期间不要执行真实业务写操作。详细边界见 [项目详情嵌入 Spec](spec/project-detail-embed.md)。

## 创建安全边界

新增客户始终经过“获取原始资料 → 查重 → 展示预览 → 用户明确确认 → 再次查重 → 单次创建 → 回查”。确认令牌默认 5 分钟过期,只在进程内保存哈希。创建请求发生超时或断网时不会自动重试;系统只做只读回查,无法确认结果时要求先人工核查客户列表。