Skip to main content
Glama
README.md
# image-mcp

> **lk888 (gpt-image-2) 图像生成 MCP server** · 文生图 + 图生图 · 双 transport (stdio + HTTP) · MySQL 使用量统计 · OSS 持久化
> 用于 Claude Code / 任何 MCP 客户端做 UI 形态对照、参考稿、概念草图。

## 1. 它是什么

- **协议**:Model Context Protocol (MCP),工具被任何 MCP 客户端(Claude Code / Claude Desktop / Cursor 等)调用
- **能力**:一个工具 `generate_image` — 调 lk888 `/v1/media/generate` 异步任务,出图后下载 → 上传 OSS → 落 MySQL → 把图直接 base64 返给客户端
- **存储**:OSS 永久持久化(预签名 URL,1h),本地是 fallback;MySQL 一张 `mcp_usage` 表统计每次调用的 size/quality/cost/duration
- **transport**:
  - `stdio` 本地直连(Claude Code 拉起本地进程)
  - `http` 远程(ECS + Nginx + Bearer 鉴权,任何 MCP 客户端都能连)

## 2. 一次性准备(只跑一次)

### 2.1 RDS 建库

```bash
mysql -h rm-bp1126b6e6ibav2uxzo.mysql.rds.aliyuncs.com -P 3306 -u error_boot -p \
  -e "CREATE DATABASE IF NOT EXISTS \`image2-mcp\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
```

> 库名带连字符,SQL 里必须反引号转义。表 `mcp_usage` server 启动会自动 `CREATE TABLE IF NOT EXISTS`,不需要手建。

### 2.2 白名单

把"本机公网 IP"和"ECS 公网 IP `47.98.87.96`"加进 RDS 白名单(阿里云控制台 → 数据安全性 → 白名单)。

### 2.3 凭据 — 与 errorbook 共享 `.env`,只追加独有 key

**复用思路**:`RDS_*` / `ALIYUN_AK/SK` 这些"轮换困难"的凭据已经在 errorbook 的 `.env.prod` / `.env.local` 里了,**image-mcp 不重新定义**,通过 docker compose 多 `--env-file` 叠加引用。

| 文件 | 位置 | 内容 |
|---|---|---|
| 共享基础 .env | 本地 `D:\workplace\superpower-dev\.env.local` / `.env.prod`,ECS `/opt/errorbook/.env.prod` | RDS_HOST / RDS_USERNAME / RDS_PASSWORD / ALIYUN_ACCESS_KEY_ID/SECRET 等(errorbook 已有,**不动**) |
| image-mcp 增量 | 本地 `D:\workplace\superpower-dev\image-mcp\.env.local` / `.env.prod`,ECS `/opt/image-mcp/.env.prod` | LK888_KEY / MCP_AUTH_TOKEN / RDS_DB=image2-mcp / IMAGE_MCP_ACR_IMAGE / NGINX_PORT 等(参考 `.env.example`) |

**键名对齐说明**:
- ✅ `RDS_USERNAME`(不是 `RDS_USER`)— 对齐 errorbook .env
- ✅ `RDS_DB` 独立 key,值 = `image2-mcp` — 错开 errorbook 的 `RDS_DATABASE`=`ai_errorbook_v2`
- ✅ `IMAGE_MCP_ACR_IMAGE` 独立 key — 错开 errorbook 的 `ACR_IMAGE`
- ✅ `NGINX_PORT` 默认 `8080`,避开 errorbook nginx 占的 80

## 3. 工具签名

```python
generate_image(
  prompt: str,                               # 必填,中英文皆可
  images: list[str] | None = None,           # 参考图 URL(最多 10);空=文生图,非空=图生图
  size: "1024x1024" | "1024x1536" | "1536x1024" |
        "2048x2048" | "2048x1152" | "3840x2160" | "2160x3840" | "auto" = "1024x1536",
  quality: "low" | "medium" | "high" | "auto" = "medium",
  background: "opaque" | "transparent" = "opaque",
  n: int = 1,                                # 1~4
) -> [ImageContent (base64 PNG), TextContent (元信息 + OSS URL)]
```

每次调用会落一条 `mcp_usage` 记录:`ts / task_id / mode (t2i|i2i) / size / quality / duration_s / cost_usd / status / result_url / oss_key / oss_url / local_path`。

## 4. 本地跑

### 4.1 stdio 模式(Claude Code 直连)

`claude_desktop_config.json`(Windows 在 `%APPDATA%\Claude\`):

```json
{
  "mcpServers": {
    "image-mcp": {
      "command": "D:/workplace/superpower-dev/image-mcp/.venv/Scripts/python.exe",
      "args": ["-m", "image_mcp.server"],
      "env": {
        "PYTHONPATH": "D:/workplace/superpower-dev/image-mcp/src",
        "LK888_KEY": "sk-...",
        "RDS_HOST": "rm-bp1126b6e6ibav2uxzo.mysql.rds.aliyuncs.com",
        "RDS_USERNAME": "error_boot",
        "RDS_PASSWORD": "...",
        "RDS_DB": "image2-mcp",
        "ALIYUN_ACCESS_KEY_ID": "...",
        "ALIYUN_ACCESS_KEY_SECRET": "..."
      }
    }
  }
}
```

> stdio 模式 env 直接写 `claude_desktop_config.json` 是 Claude Code 唯一的注入方式 — 这份配置在用户 AppData 下,**不入项目 git**。如果嫌重复,也可以把 env 留空,改用 dotenv 自动加载(让 server 启动时读 `D:\workplace\superpower-dev\.env.local`)。

### 4.2 HTTP 模式(本机调试)

```powershell
# PowerShell,凭据走 session env
$env:LK888_KEY = "..."; $env:RDS_HOST = "..."; ...; $env:MCP_AUTH_TOKEN = "<32+ chars>"
$env:PYTHONPATH = "src"
.venv\Scripts\python.exe -m image_mcp.server --transport http --port 8765
```

Claude Code 连远程:
```bash
claude mcp add image-mcp --transport http http://127.0.0.1:8765/mcp \
  --header "Authorization: Bearer <token>"
```

## 5. 云上部署(参考 superpower/部署空间/部署运维手册.md 风格)

> 复用 errorbook 后端的 ACR + ECS 链路,新仓库 `errorboot/image-mcp`。

### 5.1 本地 build + push 镜像

```powershell
cd D:\workplace\superpower-dev\image-mcp
docker build -t crpi-4e3qyeiaxmbfzar4.cn-hangzhou.personal.cr.aliyuncs.com/errorboot/image-mcp:latest .
docker push  crpi-4e3qyeiaxmbfzar4.cn-hangzhou.personal.cr.aliyuncs.com/errorboot/image-mcp:latest
```

首次 push 需要 `docker login crpi-4e3qyeiaxmbfzar4.cn-hangzhou.personal.cr.aliyuncs.com`(凭据在 ACR 控制台 "访问凭证")。

### 5.2 ECS 一次性准备

```bash
ssh root@47.98.87.96
mkdir -p /opt/image-mcp/deploy
cd /opt/image-mcp

# scp 上去:docker-compose.prod.yml + deploy/nginx.conf
# .env.prod 自己建(只放 image-mcp 独有 key,参考 .env.example;不入 git)

docker login crpi-4e3qyeiaxmbfzar4-vpc.cn-hangzhou.personal.cr.aliyuncs.com
```

### 5.3 ECS 拉镜像 + 起服务 — **共享 errorbook .env.prod**

```bash
cd /opt/image-mcp
docker compose -f docker-compose.prod.yml \
  --env-file /opt/errorbook/.env.prod \    # 复用 errorbook 的 RDS_* / ALIYUN_*
  --env-file ./.env.prod \                 # image-mcp 独有:LK888_KEY / MCP_AUTH_TOKEN / RDS_DB / IMAGE_MCP_ACR_IMAGE
  pull
docker compose -f docker-compose.prod.yml \
  --env-file /opt/errorbook/.env.prod \
  --env-file ./.env.prod \
  up -d
docker compose -f docker-compose.prod.yml \
  --env-file /opt/errorbook/.env.prod \
  --env-file ./.env.prod \
  ps
```

> 🔴 **铁则升级版**:这里和 errorbook 部署手册 §1 的"单 --env-file"铁则**有意分歧**:image-mcp 走**双 --env-file 叠加**(后面的覆盖前面的)。共享凭据基础 + 服务独立配置,避免凭据重复定义。

> **建议沉淀一个 alias** 在 ECS `~/.bashrc`:
> ```bash
> alias img-mcp='docker compose -f /opt/image-mcp/docker-compose.prod.yml --env-file /opt/errorbook/.env.prod --env-file /opt/image-mcp/.env.prod'
> # 之后:img-mcp pull / img-mcp up -d / img-mcp ps / img-mcp logs -f image-mcp
> ```

### 5.4 smoke 验证

```bash
# Bearer 校验 — 无 token 应 401
curl -s -o /dev/null -w "%{http_code}\n" http://localhost/mcp

# 带正确 token + MCP initialize 应 200 + SSE 流
curl -s -i -X POST http://localhost/mcp \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json, text/event-stream" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"smoke","version":"0"}}}' \
  | head -20
```

### 5.5 改代码后重发

```powershell
docker build -t crpi-4e3qyeiaxmbfzar4.cn-hangzhou.personal.cr.aliyuncs.com/errorboot/image-mcp:latest .
docker push  crpi-4e3qyeiaxmbfzar4.cn-hangzhou.personal.cr.aliyuncs.com/errorboot/image-mcp:latest
```
```bash
ssh root@47.98.87.96 'img-mcp pull && img-mcp up -d'   # 用 §5.3 沉淀的 alias
```

## 6. 凭据安全

- 全部走 env(`.env.local` / `.env.prod`),源码、git 历史、Docker 镜像里都见不到凭据
- `.gitignore` 屏蔽 `.env*`
- push 前 grep:`grep -rn "lizhao@\|aliyun.*KEY\|sk-" --include="*.py" --include="*.yml" --include="*.toml" .`
- `MCP_AUTH_TOKEN` 用 32+ 位强随机串(`openssl rand -hex 32`)
- 密码在对话/截图前**永远先脱敏**

## 7. 已知坑

- 库名 `image2-mcp` 带连字符,所有 SQL 引用必须反引号 `` `image2-mcp` ``
- POST 端点是 `/mcp`(不带尾 slash);带 `/mcp/` 会 307 重定向
- `dev:h5` / playwright 等浏览器自动化**不适用**(MCP 协议层,不是 web 页面)
- OSS 是私有 bucket,返回的是预签名 URL,**1h 后失效**,需要查时重签

## 8. 待办

- ICP 备案 + 域名 + HTTPS → 解锁微信小程序审核场景调用
- 多 caller 区分(目前 `caller` 字段恒为 NULL,后期按 token / IP 落)
- 接监控告警(失败率、cost 周报)