Metadata-Version: 2.3
Name: turan-mcp
Version: 0.1.2
Summary: 通过 MCP 连接图然业务 API，支持本地图片上传和视觉生成工作流
Keywords: turan,mcp,model-context-protocol,aigc,image-generation
Author: bitatom
Author-email: bitatom <bitatom_tech@163.com>
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: End Users/Desktop
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Multimedia :: Graphics
Requires-Dist: httpx>=0.28.1
Requires-Dist: mcp[cli]>=2.1.1,<3
Requires-Dist: starlette>=1.6,<2
Requires-Dist: uvicorn>=0.30,<1
Requires-Dist: pydantic-settings>=2.15.0
Requires-Python: >=3.12
Project-URL: Homepage, https://www.turan.design
Description-Content-Type: text/markdown

# 图然视觉生成 MCP 服务器

Python 提供本地 stdio 和 Hosted Streamable HTTP 两种运行方式
推荐使用本地 stdio 运行

**版本：0.1.0**

## 代码结构

正式运行路径按职责分层：

```text
src/turan_mcp/
├── cli.py                  # 命令行与运行模式选择
├── settings.py             # 环境变量和模式校验
├── context.py              # 请求级 Key、模式和 requestId
├── errors.py               # 脱敏错误分类
├── observability.py        # 结构化日志、stderr 和轮转文件输出
├── backend/client.py       # 图然业务 HTTP API、连接池和响应解析
├── services/local_upload.py# 本地文件读取、校验和上传编排
├── mcp/registry.py         # 工具定义与业务方法映射
├── mcp/executor.py         # 参数校验、能力检查和错误转换
├── mcp/server.py           # MCP SDK 结果适配
├── mcp/stdio.py            # 本地 stdio 入口
└── mcp/hosted.py           # Hosted HTTP 入口
```

`server.py`、`hosted.py`、`upload.py`、`api.py` 和 `tools.py` 根目录文件只为旧导入路径提供迁移兼容；新的业务代码不要继续引用它们。共享连接池不保存用户身份，Hosted 每次请求单独解析 `X-API-Key`，本地文件工具只在 stdio 模式注册。

## 功能

- 查询可用工作流、真实参数、默认值和价格档位。
- 文生图、图生图及多图输入，具体能力以平台开放的工作流为准。
- 本地模式自动读取用户指定的图片绝对路径并上传。
- 两种模式均支持公网 HTTPS 图片导入和任务查询、取消、显式重试。

## 安装

需要 Python 3.12 或更高版本。推荐通过 `uvx` 直接运行，首次执行时会自动从 PyPI 下载并创建隔离环境：

```shell
uvx turan-mcp --help
```

也可以安装到当前 Python 环境：

```shell
pip install turan-mcp
turan-mcp --help
```

## 推荐方式：本地 stdio

适用于支持 command/stdio 的客户端。下面是 `mcpServers` 格式示例，其他配置入口按客户端要求调整：

```json
{
  "mcpServers": {
    "turan": {
      "command": "uvx",
      "args": ["turan-mcp"],
      "env": {
        "TURAN_API_BASE_URL": "https://<图然业务API域名>",
        "TURAN_API_KEY": "<用户的图然API Key>"
      }
    }
  }
}
```

## 环境变量

| 变量 | 必需 | 默认值和说明 |
| --- | --- | --- |
| `TURAN_API_BASE_URL` | 是  | Java 业务 API 基地址，不含 `/mcp` |
| `TURAN_API_KEY` | stdio 必需 | 从图然平台获取；Hosted 从每个 MCP 请求的 `X-API-Key` 读取，不使用进程环境变量中的 Key |
| `TURAN_MODE` | 否  | `stdio`，也可为 `hosted`；CLI `--mode` 优先 |
| `TURAN_ALLOW_HTTP_BACKEND` | 否  | `false`；localhost 和回环 IP 自动允许 HTTP，其他受信内网 HTTP 后端需显式开启 |
| `TURAN_HOST` | 否  | `127.0.0.1`，Hosted 监听地址 |
| `TURAN_PORT` | 否  | `8000`，Hosted 监听端口 |
| `TURAN_ALLOWED_HOSTS` | 否  | JSON 数组，默认仅 localhost、127.0.0.1、[::1] |
| `TURAN_ALLOWED_ORIGINS` | 否  | JSON 数组，默认空；携带 Origin 的请求须显式允许 |
| `TURAN_MAX_UPLOAD_BYTES` | 否  | `20971520`，本地图片默认 20 MiB |
| `TURAN_TIMEOUT_SECONDS` | 否  | `120`，业务请求超时秒数 |
| `TURAN_LOG_LEVEL` | 否  | `INFO`；可选 `DEBUG`、`INFO`、`WARNING`、`ERROR`、`CRITICAL` |
| `TURAN_LOG_FORMAT` | 否  | `auto`；stdio 使用文本，Hosted 使用 JSON，也可显式指定 `text` 或 `json` |
| `TURAN_LOG_FILE` | 否  | 空；设置后同时写入 UTF-8 轮转文件，日志仍会写入 stderr |
| `TURAN_LOG_MAX_BYTES` | 否  | `10485760`，单个日志文件最大 10 MiB |
| `TURAN_LOG_BACKUP_COUNT` | 否  | `5`，轮转备份数量 |

公网代理若保留原始 Host，应配置例如 `TURAN_ALLOWED_HOSTS='["api.example.com"]'`，实际域名以部署为准，不建议使用通配符。普通桌面客户端通常不发送 Origin；这里未提供完整浏览器跨域 CORS 接入支持。

本地联调时，`localhost`、`127.0.0.0/8` 和 `::1` 会规范化为同一个回环来源。因此业务基地址使用 `http://localhost:8080`、Java 直传地址使用 `http://127.0.0.1:8080` 时可以正常上传；协议和端口仍须一致。

## 日志与问题排查

默认日志级别是 `INFO`，始终写入 stderr。stdio 模式使用文本格式，Hosted 模式使用单行 JSON，便于 Docker、systemd 或日志平台采集。MCP 协议内容仍只写 stdout。

如果桌面 MCP 客户端不展示 stderr，可以在客户端的 `env` 中增加：

```json
{
  "TURAN_LOG_LEVEL": "DEBUG",
  "TURAN_LOG_FILE": "E:/logs/turan-mcp.log"
}
```

日志文件达到 `TURAN_LOG_MAX_BYTES` 后自动轮转。问题复现后先搜索 MCP 错误结果中的 `requestId`；同一标识会出现在 Python 的 Hosted、工具、上传和后端请求日志中，并通过 `X-Request-ID` 传给 Java。

常见事件：

| 事件 | 含义 |
| --- | --- |
| `service_starting`、`runtime_started` | 进程及共享 HTTP 运行时已启动 |
| `hosted_request_completed`、`hosted_request_rejected` | Hosted 请求完成或在传输边界被拒绝 |
| `tool_completed`、`tool_rejected`、`tool_failed` | 工具成功、业务返回失败或执行异常 |
| `backend_request_completed`、`backend_request_failed` | Python 调用 Java 成功或失败 |
| `local_upload_completed`、`local_upload_validation_failed` | 本地图片上传成功或文件校验失败 |

日志记录工具名、工作流编码、任务标识、阶段、状态和耗时，不记录 API Key、请求体、图片内容或本地绝对路径。

## 可用工具

| 工具 | 参数 | 用途 |
| --- | --- | --- |
| `list_workflows` | 无 | 工作流目录 |
| `get_workflow_schema` | `workflowCode` | 真实输入和价格 |
| `get_workflow_upload_spec` | `workflowCode`、`formName` | 上传规格，本身不上传 |
| `upload_local_workflow_image` | `workflowCode`、`formName`、`localPath` | 仅本地模式可用 |
| `upload_workflow_image` | `workflowCode`、`formName`、`imageUrl` | 公网 HTTPS 图片导入 |
| `create_workflow_task` | `workflowCode`；可选 `fileBindings`、`inputValues`、`priceType` | 创建任务，可能消费燃币 |
| `get_task` | `taskId` | 查询任务 |
| `cancel_task` | `taskId` | 用户显式取消 |
| `retry_failed_task` | `taskId` | 用户显式重试失败任务 |

工具名固定，工作流编码及参数动态查询。创建前必须确认 Schema、必填图片和价格。本地图片仅支持 PNG、JPEG、GIF、WebP 文件头检查，云端继续校验完整图片。

图片上传返回 `formName` 和 `tempFileId`，直接用于现有 `fileBindings`。普通输入为 `{formName,value}`，不需要客户端拼接内部动态表单。

## 对话示例
> 请调用图然 list_workflows，列出可用工作流。

> 帮我调用图然mcp完成文生图：一只橘色小猫咪戴着宇航员头盔，漂浮在太空中，周围环绕着彩色星球和星星，3D卡通渲染风格，柔和的渐变背景，可爱表情，皮克斯风格
