MiMo Proxy 是一个面向 MiMoCode 的轻量 OpenAI 兼容代理。推荐使用 Responses API;对于只支持 Chat Completions 的中转站,代理也能修补流中不完整的 tool_calls,作为兼容回退。
本文档按实际操作顺序说明如何安装、替换不同中转站、配置 MiMoCode、验证连接和排查错误。
当中转站返回下面这种分阶段工具调用时:
{
"index": 0,
"type": "function"
}MiMoCode 可能因为当前 SSE 帧缺少 function 对象而校验失败:
choices[0].delta.tool_calls[0].function
Invalid input: expected object, received undefined
代理会把当前片段修补为:
{
"index": 0,
"type": "function",
"function": {}
}代理不会猜测函数名或参数,后续 SSE 帧仍可继续提供 name 和 arguments。
MiMoCode
|
| OpenAI-compatible request + API Key
v
MiMo Proxy http://127.0.0.1:3000
|
| Chat SSE 修补 / Responses 原样透传
v
任意兼容中转站
本地支持以下请求路径:
| MiMoCode 请求路径 | 转发目标 | 处理方式 |
|---|---|---|
/chat/completions |
UPSTREAM_URL |
修补 Chat SSE |
/v1/chat/completions |
UPSTREAM_URL |
修补 Chat SSE |
/responses |
RESPONSES_UPSTREAM_URL |
原样透传 |
/v1/responses |
RESPONSES_UPSTREAM_URL |
原样透传 |
替换中转站前,先从其文档或控制台确认以下信息:
| 检查项 | 要求 | 示例 |
|---|---|---|
| Responses API | 推荐,优先确认并提供完整接口地址 | https://relay.example.com/v1/responses |
| Chat Completions | 可选,仅在中转站不支持 Responses 时作为回退 | https://relay.example.com/v1/chat/completions |
| 鉴权方式 | 支持 Authorization: Bearer <API_KEY> |
大多数 OpenAI 兼容站点均支持 |
| 流式格式 | 使用 text/event-stream 和 data: 事件 |
Chat 流式响应 |
| 模型名称 | 必须与中转站实际模型 ID 完全一致 | gpt-5.6-sol |
💡 网页上的“API 地址”有时只是域名,有时已经包含
/v1。本项目需要的是完整接口 URL,不要只凭界面名称猜路径。
- Node.js 18 或更高版本
- pnpm 10 或兼容版本
- 一个 OpenAI 兼容中转站及其 API Key
检查版本:
node --version
pnpm --versiongit clone git@github.com:maycode0-0/mimo-proxy.git
cd mimo-proxy
pnpm install --frozen-lockfile$env:UPSTREAM_URL = 'https://relay.example.com/v1/chat/completions'
$env:RESPONSES_UPSTREAM_URL = 'https://relay.example.com/v1/responses'
$env:HOST = '127.0.0.1'
$env:PORT = '3000'export UPSTREAM_URL='https://relay.example.com/v1/chat/completions'
export RESPONSES_UPSTREAM_URL='https://relay.example.com/v1/responses'
export HOST='127.0.0.1'
export PORT='3000'
⚠️ 项目没有加载 dotenv。直接创建.env文件不会自动生效,请在启动进程的 Shell、进程管理器或系统服务中设置环境变量。
pnpm start启动成功:
Proxy listening on 127.0.0.1:3000
如果没有设置 HOST,默认输出为:
Proxy listening on 0.0.0.0:3000
curl.exe -i http://127.0.0.1:3000/v1/responses预期结果为 405 Method Not Allowed,并包含:
Allow: POST
这表示本地代理已经运行。它不是上游调用失败,测试使用了 GET,而模型接口只接受 POST。
代码中只有 RouterTeam 是默认值,运行时可以通过环境变量切换到任何兼容站点,无需修改 proxy.js。
这是最完整的配置:
$env:UPSTREAM_URL = 'https://relay.example.com/v1/chat/completions'
$env:RESPONSES_UPSTREAM_URL = 'https://relay.example.com/v1/responses'
pnpm start建议始终显式填写两个地址,并在 MiMoCode 中优先使用 Responses API。即使两个接口在同一域名,也能避免中转站使用特殊路径前缀时推导错误。
只配置 Chat 地址:
$env:UPSTREAM_URL = 'https://relay.example.com/v1/chat/completions'
Remove-Item Env:RESPONSES_UPSTREAM_URL -ErrorAction SilentlyContinue
pnpm start同时在 MiMoCode provider 中指定 OpenAI Compatible SDK:
这样 MiMoCode 会走 Chat Completions,不会请求中转站未实现的 Responses API。
有些站点的接口不是标准根路径,例如:
https://relay.example.com/openai/v1/chat/completions
https://relay.example.com/openai/v1/responses
必须分别配置完整地址:
$env:UPSTREAM_URL = 'https://relay.example.com/openai/v1/chat/completions'
$env:RESPONSES_UPSTREAM_URL = 'https://relay.example.com/openai/v1/responses'
pnpm start如果省略 RESPONSES_UPSTREAM_URL,代理会根据 Chat 地址的域名推导标准路径 /v1/responses。推导结果不会保留 /openai 前缀,因此自定义路径必须显式配置。
RouterTeam 提供多个入口时,可以任选网络质量较好的一个,并确保两个接口使用同一入口。
# CF 代理线路
$env:UPSTREAM_URL = 'https://ai.router.team/v1/chat/completions'
$env:RESPONSES_UPSTREAM_URL = 'https://ai.router.team/v1/responses'
# 或中国大陆优化线路
# $env:UPSTREAM_URL = 'https://cn2.router.team/v1/chat/completions'
# $env:RESPONSES_UPSTREAM_URL = 'https://cn2.router.team/v1/responses'
# 或美国直连线路
# $env:UPSTREAM_URL = 'https://api.router.team/v1/chat/completions'
# $env:RESPONSES_UPSTREAM_URL = 'https://api.router.team/v1/responses'
pnpm start编辑配置文件:
~/.config/mimocode/mimocode.jsonc
推荐使用 OpenAI provider,通过 Responses API 调用中转站:
{
"$schema": "https://mimo.xiaomi.com/mimocode/config.json",
"model": "openai-any-router/your-model-id",
"provider": {
"openai-any-router": {
"npm": "@ai-sdk/openai",
"options": {
"baseURL": "http://127.0.0.1:3000",
"apiKey": "<YOUR_API_KEY>",
"timeout": 90000
},
"models": {
"your-model-id": {
"name": "Your Model",
"tool_call": true
}
}
}
}
}替换以下占位值:
| 占位值 | 替换内容 |
|---|---|
<YOUR_API_KEY> |
中转站生成的 API Key |
your-model-id |
中转站提供的真实模型 ID |
Your Model |
MiMoCode 界面显示名称,可自定义 |
@ai-sdk/openai 默认使用 Responses API。仅当中转站没有实现 Responses API 时,才改用场景 B 中的 @ai-sdk/openai-compatible,回退到 Chat Completions。
MiMoCode 会把 API Key 放入请求的 Authorization 头,代理只转发该请求头,不需要在代理项目中保存 Key。
修改配置后,建议退出并重新启动 MiMoCode,避免旧 provider 配置仍在内存中。
| 变量 | 默认值 | 说明 |
|---|---|---|
UPSTREAM_URL |
https://cn2.router.team/v1/chat/completions |
完整 Chat Completions 接口 URL |
RESPONSES_UPSTREAM_URL |
根据 Chat 地址推导同域 /v1/responses |
完整 Responses API 接口 URL |
UPSTREAM_TIMEOUT_MS |
90000 |
上游请求超时,单位毫秒 |
REQUEST_BODY_LIMIT |
10mb |
请求体大小上限 |
HOST |
0.0.0.0 |
本地监听地址 |
PORT |
3000 |
本地监听端口 |
环境变量只在当前 Shell 会话和它启动的子进程中生效。关闭终端后需要重新设置,或交给 PM2、systemd、Docker 等进程管理方式持久化。
- 优先确认中转站支持 Responses API,并复制 Responses 的完整接口地址。
- 确认需要使用的模型 ID,不要使用仅用于显示的别名。
- 在启动代理的 Shell 中设置
RESPONSES_UPSTREAM_URL;如需兼容回退,再设置UPSTREAM_URL。 - 启动代理并用 GET 请求确认本地端口返回 405。
- 在 MiMoCode 中把
baseURL指向本地代理。 - 新建 MiMoCode 会话,先发送简单文本验证流式输出。
- 再执行一次会触发工具调用的任务,确认 Responses 工具调用正常。
按顺序检查:
- MiMoCode 的
baseURL是否为http://127.0.0.1:3000。 - 是否运行了最新代理,而不是仍占用端口的旧进程。
RESPONSES_UPSTREAM_URL是否包含完整的/responses路径。- 中转站是否真的支持
/responses。不支持时才使用 Chat Compatible provider。 - 中转站是否要求额外路径前缀,并显式设置了两个上游地址。
- 检查 API Key 是否属于当前中转站。
- 检查 Key 是否启用、过期或被限制分组。
- 确认 MiMoCode provider 的
apiKey已更新,并重启 MiMoCode。
- 使用中转站 API 文档中的真实模型 ID。
- 检查 Key 所属分组是否有该模型权限。
- 模型显示名称可以自定义,但配置对象的 key 必须与请求模型一致。
- 确认 MiMoCode 请求经过本地代理,而不是直接访问中转站。
- 确认已重启代理并加载最新代码。
- 查看返回内容是否为 Chat Completions SSE,Responses API 不使用这套修补格式。
旧版代理可能向成功事件加入了 error: null。最新版本会删除空错误哨兵,同时保留真实错误对象。
端口已被旧代理或其他程序占用。更换端口:
$env:PORT = '3001'
pnpm start同时把 MiMoCode 的 baseURL 改为:
http://127.0.0.1:3001
- 切换中转站线路。
- 增大
UPSTREAM_TIMEOUT_MS。 - 检查中转站服务状态和模型排队情况。
$env:UPSTREAM_TIMEOUT_MS = '180000'
pnpm start- 仅本机使用时设置
HOST=127.0.0.1。 - 默认
HOST=0.0.0.0会允许局域网设备访问。 - 不要把代理直接暴露到公网,它没有身份验证、限流或 TLS 终止。
- 不要把真实 API Key 写入仓库、Issue、日志或截图。
- 代理只转发必要请求头,不主动记录 Authorization 内容。
安装依赖:
pnpm install --frozen-lockfile运行语法检查和完整回归测试:
pnpm check测试覆盖:
- 非流式错误状态、响应头和正文透传
- 空
error清理与真实错误保留 - 超过 Express 默认 100KB 的请求体
- 分片 CRLF SSE 与最后一个未闭合事件
- Chat 和 Responses 的路径别名
- 无正文的
204响应 - 非 POST 方法拒绝
- 上游断开后的结构化
502
MiMoCode 使用联合类型校验成功响应与错误响应。当成功流中的 tool_call.function 暂时缺失时,成功分支校验失败;错误分支也会因为没有顶层 error 而失败。
这不表示成功响应需要添加 error: null。正确处理方式是:
- 缺少
tool_call.function时补{}。 error为null或undefined时删除该字段。error为真实对象时保持不变。
一个空对象解决类型问题,一个空错误对象则会制造新问题。区别不大,也就差一次崩溃。🙂
.
├── proxy.js # Express 代理与 SSE 修补逻辑
├── test/
│ └── proxy.test.js # 本地伪上游回归测试
├── package.json
├── pnpm-lock.yaml
├── LICENSE
└── README.md
本项目基于 MIT License 开源。
{ "provider": { "openai-any-router": { "npm": "@ai-sdk/openai-compatible", "options": { "baseURL": "http://127.0.0.1:3000", "apiKey": "<YOUR_API_KEY>" }, "models": { "your-model-id": { "name": "Your Model" } } } } }