@sunflower0305/claude-proxy 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.env.example CHANGED
@@ -1,15 +1,20 @@
1
- # Choose your provider: qwen | deepseek | glm | minimax | kimi
1
+ # Choose your provider: qwen | deepseek | glm | minimax | kimi | mimo
2
2
  PROVIDER=deepseek
3
3
 
4
4
  # Proxy server port (default: 8080)
5
5
  PROXY_PORT=8080
6
6
 
7
+ # Optional local proxy token.
8
+ # When set, clients must send this value as x-api-key or Authorization: Bearer.
9
+ # PROXY_API_KEY=your-local-proxy-token
10
+
7
11
  # API keys - set the one(s) you need
8
12
  QWEN_API_KEY=your-qwen-api-key
9
13
  DEEPSEEK_API_KEY=your-deepseek-key
10
14
  GLM_API_KEY=your-glm-key
11
15
  MINIMAX_API_KEY=your-minimax-key
12
16
  KIMI_API_KEY=your-kimi-key
17
+ MIMO_API_KEY=your-mimo-key
13
18
 
14
19
  # Optional model overrides
15
20
  QWEN_MODEL=qwen-plus
@@ -17,6 +22,7 @@ DEEPSEEK_MODEL=deepseek-v4-pro
17
22
  GLM_MODEL=glm-5.1
18
23
  MINIMAX_MODEL=MiniMax-M2.7-highspeed
19
24
  KIMI_MODEL=kimi-k2.6
25
+ MIMO_MODEL=mimo-v2.5-pro
20
26
 
21
27
  # Optional upstream Anthropic-compatible base URL overrides
22
28
  # QWEN_ANTHROPIC_BASE_URL=https://dashscope.aliyuncs.com/apps/anthropic
@@ -24,3 +30,4 @@ KIMI_MODEL=kimi-k2.6
24
30
  # GLM_ANTHROPIC_BASE_URL=https://open.bigmodel.cn/api/anthropic
25
31
  # MINIMAX_ANTHROPIC_BASE_URL=https://api.minimaxi.com/anthropic
26
32
  # KIMI_ANTHROPIC_BASE_URL=https://api.moonshot.cn/anthropic
33
+ # MIMO_ANTHROPIC_BASE_URL=https://api.xiaomimimo.com/anthropic
package/CHANGELOG.md CHANGED
@@ -2,6 +2,18 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [1.3.0] - 2026-05-06
6
+
7
+ Minor release of `@sunflower0305/claude-proxy`.
8
+
9
+ ### Added
10
+
11
+ - Anthropic-compatible proxy support for MIMO through the `mimo` provider
12
+ - `MIMO_API_KEY`, `MIMO_MODEL`, and `MIMO_ANTHROPIC_BASE_URL` configuration
13
+ - local integration coverage for MIMO provider switching, model mapping, and non-streaming request proxying
14
+
15
+ Detailed release notes: [docs/releases/1.3.0.md](docs/releases/1.3.0.md)
16
+
5
17
  ## [1.2.0] - 2026-05-01
6
18
 
7
19
  Minor release of `@sunflower0305/claude-proxy`.
package/README.md CHANGED
@@ -4,13 +4,13 @@
4
4
  [![CD](https://github.com/sunflower0305/claude-proxy/actions/workflows/cd.yml/badge.svg)](https://github.com/sunflower0305/claude-proxy/actions/workflows/cd.yml)
5
5
  [![Coverage Status](https://coveralls.io/repos/github/sunflower0305/claude-proxy/badge.svg?branch=master)](https://coveralls.io/github/sunflower0305/claude-proxy?branch=master)
6
6
  [![npm version](https://img.shields.io/npm/v/%40sunflower0305%2Fclaude-proxy)](https://www.npmjs.com/package/@sunflower0305/claude-proxy)
7
- [![npm downloads](https://img.shields.io/endpoint?url=https%3A%2F%2Fcdn.jsdelivr.net%2Fgh%2Fsunflower0305%2Fclaude-proxy%40master%2F.github%2Fbadges%2Fnpm-weekly-downloads.json&cacheSeconds=60)](https://www.npmjs.com/package/@sunflower0305/claude-proxy)
7
+ [![npm downloads](https://img.shields.io/npm/dm/%40sunflower0305%2Fclaude-proxy?cacheSeconds=60)](https://www.npmjs.com/package/@sunflower0305/claude-proxy)
8
8
  [![GitHub stars](https://img.shields.io/github/stars/sunflower0305/claude-proxy?cacheSeconds=60)](https://github.com/sunflower0305/claude-proxy/stargazers)
9
9
  [![License](https://img.shields.io/github/license/sunflower0305/claude-proxy)](https://github.com/sunflower0305/claude-proxy/blob/master/LICENSE)
10
10
 
11
11
  `claude-proxy` is published on npm as `@sunflower0305/claude-proxy`. It is a lightweight Express proxy that lets Claude Code or the Claude Agent SDK talk to domestic Chinese LLM providers through Anthropic-compatible `/v1/messages` endpoints.
12
12
 
13
- It currently supports `qwen`, `deepseek`, `glm`, `minimax`, and `kimi`.
13
+ It currently supports `qwen`, `deepseek`, `glm`, `minimax`, `kimi`, and `mimo`.
14
14
 
15
15
  ## Install
16
16
 
@@ -38,6 +38,8 @@ Example `.env`:
38
38
  ```dotenv
39
39
  PROVIDER=deepseek
40
40
  PROXY_PORT=8080
41
+ # Optional: require clients to send this token to write endpoints.
42
+ # PROXY_API_KEY=your-local-proxy-token
41
43
  DEEPSEEK_API_KEY=your-deepseek-api-key
42
44
  DEEPSEEK_MODEL=deepseek-v4-pro
43
45
  ```
@@ -48,13 +50,15 @@ Available variables:
48
50
  | ------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- |
49
51
  | `PROVIDER` | Active provider. Defaults to `deepseek`. |
50
52
  | `PROXY_PORT` | Local server port. Defaults to `8080`. |
53
+ | `PROXY_API_KEY` | Optional local proxy token for `POST /v1/messages` and `POST /api/provider`. |
51
54
  | `QWEN_API_KEY` | API key for Qwen. |
52
55
  | `DEEPSEEK_API_KEY` | API key for DeepSeek. |
53
56
  | `GLM_API_KEY` | API key for GLM. |
54
57
  | `MINIMAX_API_KEY` | API key for MiniMax. |
55
58
  | `KIMI_API_KEY` | API key for Kimi. |
56
- | `QWEN_ANTHROPIC_BASE_URL`, `DEEPSEEK_ANTHROPIC_BASE_URL`, `GLM_ANTHROPIC_BASE_URL`, `MINIMAX_ANTHROPIC_BASE_URL`, `KIMI_ANTHROPIC_BASE_URL` | Override the upstream Anthropic-compatible base URL for a provider. |
57
- | `QWEN_MODEL`, `DEEPSEEK_MODEL`, `GLM_MODEL`, `MINIMAX_MODEL`, `KIMI_MODEL` | Override the default upstream model for a provider. |
59
+ | `MIMO_API_KEY` | API key for MIMO. |
60
+ | `QWEN_ANTHROPIC_BASE_URL`, `DEEPSEEK_ANTHROPIC_BASE_URL`, `GLM_ANTHROPIC_BASE_URL`, `MINIMAX_ANTHROPIC_BASE_URL`, `KIMI_ANTHROPIC_BASE_URL`, `MIMO_ANTHROPIC_BASE_URL` | Override the upstream Anthropic-compatible base URL for a provider. |
61
+ | `QWEN_MODEL`, `DEEPSEEK_MODEL`, `GLM_MODEL`, `MINIMAX_MODEL`, `KIMI_MODEL`, `MIMO_MODEL` | Override the default upstream model for a provider. |
58
62
 
59
63
  Provider defaults:
60
64
 
@@ -65,6 +69,7 @@ Provider defaults:
65
69
  | `glm` | `GLM_MODEL` | `glm-5.1` |
66
70
  | `minimax` | `MINIMAX_MODEL` | `MiniMax-M2.7-highspeed` |
67
71
  | `kimi` | `KIMI_MODEL` | `kimi-k2.6` |
72
+ | `mimo` | `MIMO_MODEL` | `mimo-v2.5-pro` |
68
73
 
69
74
  You can use the bundled example as a starting point:
70
75
 
@@ -89,6 +94,11 @@ export ANTHROPIC_BASE_URL=http://localhost:8080
89
94
  export ANTHROPIC_API_KEY=any-string-works
90
95
  ```
91
96
 
97
+ If you set `PROXY_API_KEY`, set the client `ANTHROPIC_API_KEY` to the same
98
+ value. The proxy accepts it through either `x-api-key` or
99
+ `Authorization: Bearer`. If `PROXY_API_KEY` is not set, the local proxy does not
100
+ validate the client API key and any non-empty string can be used.
101
+
92
102
  Example SDK usage:
93
103
 
94
104
  ```ts
@@ -96,7 +106,7 @@ import Anthropic from "@anthropic-ai/sdk";
96
106
 
97
107
  const client = new Anthropic({
98
108
  baseURL: "http://localhost:8080",
99
- apiKey: "any-string",
109
+ apiKey: process.env.PROXY_API_KEY || "any-string",
100
110
  });
101
111
  ```
102
112
 
package/dist/proxy.d.ts CHANGED
@@ -8,6 +8,7 @@
8
8
  * Usage:
9
9
  * export ANTHROPIC_BASE_URL=http://localhost:8080
10
10
  * export ANTHROPIC_API_KEY=any-key-works
11
+ * # If PROXY_API_KEY is set, use that same value instead.
11
12
  */
12
13
  import express from "express";
13
14
  export declare function createApp(): express.Express;
package/dist/proxy.js CHANGED
@@ -8,6 +8,7 @@
8
8
  * Usage:
9
9
  * export ANTHROPIC_BASE_URL=http://localhost:8080
10
10
  * export ANTHROPIC_API_KEY=any-key-works
11
+ * # If PROXY_API_KEY is set, use that same value instead.
11
12
  */
12
13
  import express from "express";
13
14
  import { existsSync, realpathSync } from "node:fs";
@@ -67,12 +68,20 @@ const PROVIDERS = {
67
68
  apiKey: process.env.KIMI_API_KEY || "",
68
69
  model: pickEnv("KIMI_MODEL") || "kimi-k2.6",
69
70
  },
71
+ mimo: {
72
+ baseUrl: pickEnv("MIMO_ANTHROPIC_BASE_URL") ||
73
+ "https://api.xiaomimimo.com/anthropic",
74
+ apiKey: process.env.MIMO_API_KEY || "",
75
+ model: pickEnv("MIMO_MODEL") || "mimo-v2.5-pro",
76
+ },
70
77
  };
71
78
  function isProviderKey(value) {
72
79
  return Boolean(value && value in PROVIDERS);
73
80
  }
74
81
  function getInitialProvider() {
75
- return isProviderKey(process.env.PROVIDER) ? process.env.PROVIDER : "deepseek";
82
+ return isProviderKey(process.env.PROVIDER)
83
+ ? process.env.PROVIDER
84
+ : "deepseek";
76
85
  }
77
86
  function getProviderConfig(provider) {
78
87
  return PROVIDERS[provider] || PROVIDERS.deepseek;
@@ -123,6 +132,19 @@ function createProxyError(message) {
123
132
  },
124
133
  };
125
134
  }
135
+ function createAuthenticationError() {
136
+ return {
137
+ type: "error",
138
+ error: {
139
+ type: "authentication_error",
140
+ message: "Invalid API key",
141
+ },
142
+ };
143
+ }
144
+ function getBearerToken(authorization) {
145
+ const match = authorization?.match(/^Bearer\s+(.+)$/i);
146
+ return match?.[1]?.trim() || undefined;
147
+ }
126
148
  function inferProviderFromModel(model) {
127
149
  if (!model)
128
150
  return undefined;
@@ -149,6 +171,7 @@ function logTimingEvent(trace, phase, extra = {}) {
149
171
  export function createApp() {
150
172
  let currentProvider = getInitialProvider();
151
173
  let requestSequence = 0;
174
+ const proxyApiKey = pickEnv("PROXY_API_KEY");
152
175
  function getConfig(provider = currentProvider) {
153
176
  return getProviderConfig(provider);
154
177
  }
@@ -180,6 +203,21 @@ export function createApp() {
180
203
  startedAt: Date.now(),
181
204
  };
182
205
  }
206
+ function requireProxyApiKey(req, res, next) {
207
+ if (!proxyApiKey) {
208
+ next();
209
+ return;
210
+ }
211
+ const clientTokens = [
212
+ getHeaderValue(req.headers["x-api-key"])?.trim(),
213
+ getBearerToken(getHeaderValue(req.headers.authorization)),
214
+ ].filter((token) => Boolean(token));
215
+ if (clientTokens.includes(proxyApiKey)) {
216
+ next();
217
+ return;
218
+ }
219
+ res.status(401).json(createAuthenticationError());
220
+ }
183
221
  async function handleNonStreamingRequest(req, res) {
184
222
  const config = getConfig();
185
223
  const targetModel = getTargetModel(req.body?.model);
@@ -308,7 +346,7 @@ export function createApp() {
308
346
  }
309
347
  }
310
348
  const app = express();
311
- app.use(express.json({ limit: "50mb" }));
349
+ app.use(express.json({ limit: "32mb" }));
312
350
  app.get("/", (_req, res) => {
313
351
  const config = getConfig();
314
352
  res.json({
@@ -324,7 +362,7 @@ export function createApp() {
324
362
  },
325
363
  });
326
364
  });
327
- app.post("/v1/messages", async (req, res) => {
365
+ app.post("/v1/messages", requireProxyApiKey, async (req, res) => {
328
366
  if (req.body?.stream) {
329
367
  await handleStreamingRequest(req, res);
330
368
  return;
@@ -353,7 +391,7 @@ export function createApp() {
353
391
  availableProviders: Object.keys(PROVIDERS),
354
392
  });
355
393
  });
356
- app.post("/api/provider", (req, res) => {
394
+ app.post("/api/provider", requireProxyApiKey, (req, res) => {
357
395
  const { provider, model } = (req.body ?? {});
358
396
  const targetProvider = provider ?? inferProviderFromModel(model);
359
397
  if (!isProviderKey(targetProvider)) {
@@ -397,6 +435,9 @@ function isMainModule() {
397
435
  if (isMainModule()) {
398
436
  const initialProvider = getInitialProvider();
399
437
  const initialConfig = getProviderConfig(initialProvider);
438
+ const clientApiKeyHint = pickEnv("PROXY_API_KEY")
439
+ ? "same value as PROXY_API_KEY"
440
+ : "any-string-works";
400
441
  if (!initialConfig.apiKey) {
401
442
  console.warn(`Warning: API key not configured for provider: ${initialProvider}`);
402
443
  console.warn("Please set the appropriate environment variable in .env");
@@ -413,7 +454,7 @@ if (isMainModule()) {
413
454
  ╠═══════════════════════════════════════════════════════╣
414
455
  ║ Set these env vars in your app: ║
415
456
  ║ ANTHROPIC_BASE_URL=http://localhost:${PORT}
416
- ║ ANTHROPIC_API_KEY=any-string-works ║
457
+ ║ ANTHROPIC_API_KEY=${clientApiKeyHint}
417
458
  ╚═══════════════════════════════════════════════════════╝
418
459
  `);
419
460
  });
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@sunflower0305/claude-proxy",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "type": "module",
5
- "description": "A proxy that lets Claude Agent SDK use domestic Chinese LLMs (DeepSeek, Qwen, GLM, MiniMax) as backend",
5
+ "description": "A proxy that lets Claude Agent SDK use domestic Chinese LLMs (DeepSeek, Qwen, GLM, MiniMax, Kimi, MIMO) as backend",
6
6
  "license": "MIT",
7
7
  "main": "./dist/proxy.js",
8
8
  "types": "./dist/proxy.d.ts",
@@ -46,7 +46,8 @@
46
46
  "deepseek",
47
47
  "glm",
48
48
  "minimax",
49
- "kimi"
49
+ "kimi",
50
+ "mimo"
50
51
  ],
51
52
  "scripts": {
52
53
  "dev": "tsx watch src/proxy.ts",