Skip to content

Commit 8c125d7

Browse files
linfangwclaude
andauthored
feat: multi-region support improvements across CLI, MCP, and docs (#13)
* feat: add CLI/Agent sections to getting-started docs + fix CLI multi-region gaps - Add QVeris CLI and Agent Setup sections to all three getting-started docs (en-US, zh-CN, cn/zh-CN), reorder sections: CLI → MCP → SDK → API - Fix CLI multi-region support: region-aware account URLs in login/credits, display region in doctor/whoami/config list, pass baseUrl in login validation, store region in session, add QVERIS_REGION to help text Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(cli): interactive region selection during login When QVERIS_REGION or --base-url is not set, `qveris login` now prompts the user to choose their region (Global/China) before showing the API key URL. This removes the need to set environment variables before first login. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): handle custom region in getSiteUrl and persist baseUrl in session Address PR review feedback: - getSiteUrl() now accepts baseUrl param to infer site URL for custom regions - All callers pass baseUrl to getSiteUrl() - Session now stores baseUrl alongside region for custom region support Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * docs: update CLI docs for interactive region selection and region display - login: document interactive region prompt (Global/China) - whoami: mention region display - doctor: mention region and base URL display - session: document region and baseUrl storage Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * docs: clarify agent/script region usage vs interactive login prompt Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore(cli): bump version to 0.4.0 - Interactive region selection during login - Multi-region fixes (region-aware URLs, doctor/whoami/config region display) - Custom region support (getSiteUrl inference, baseUrl in session) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * docs(mcp): add multi-region configuration documentation - README: add QVERIS_REGION and QVERIS_BASE_URL env vars, Region section with key prefix table, priority chain, and China config example - docs/en-US/mcp-server.md: add env var list, region auto-detection note, China region config example - docs/zh-CN/mcp-server.md: same updates in Chinese Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): use resolved baseUrl in all API calls instead of raw flag All commands now pass the region-resolved baseUrl to API calls, ensuring QVERIS_REGION env var and key prefix detection are respected for actual requests, not just for display/session purposes. Fixes: credits, discover, doctor, interactive Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): remove duplicate resolveBaseUrl call in discover.mjs Region and baseUrl are already resolved at function entry (line 11). The second call inside the try block was redundant. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 3000a96 commit 8c125d7

8 files changed

Lines changed: 91 additions & 16 deletions

File tree

docs/en-US/mcp-server.md

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,16 @@ Both surfaces map to the same QVeris protocol:
5454
npx -y @qverisai/mcp
5555
```
5656

57-
The MCP server reads your API key from:
57+
The MCP server reads configuration from environment variables:
5858

5959
```bash
60-
QVERIS_API_KEY=your-api-key
60+
QVERIS_API_KEY=your-api-key # Required
61+
QVERIS_REGION=cn # Optional: force region (global | cn)
62+
QVERIS_BASE_URL=https://... # Optional: override API base URL
6163
```
6264

65+
Region is auto-detected from your API key prefix (`sk-cn-xxx` → China, `sk-xxx` → Global). Set `QVERIS_REGION` only if you need to override.
66+
6367
### Claude Desktop example
6468

6569
```json
@@ -92,6 +96,25 @@ QVERIS_API_KEY=your-api-key
9296
}
9397
```
9498

99+
### China region example
100+
101+
For users in mainland China, add `QVERIS_REGION` or use a `sk-cn-` prefixed key:
102+
103+
```json
104+
{
105+
"mcpServers": {
106+
"qveris": {
107+
"command": "npx",
108+
"args": ["-y", "@qverisai/mcp"],
109+
"env": {
110+
"QVERIS_API_KEY": "sk-cn-your-api-key-here",
111+
"QVERIS_REGION": "cn"
112+
}
113+
}
114+
}
115+
}
116+
```
117+
95118
For environment-specific setup guides, see:
96119

97120
- [SETUP.md](../../agent/SETUP.md)

docs/zh-CN/mcp-server.md

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,16 @@
5454
npx -y @qverisai/mcp
5555
```
5656

57-
MCP 服务器从以下环境变量读取 API 密钥
57+
MCP 服务器从以下环境变量读取配置
5858

5959
```bash
60-
QVERIS_API_KEY=your-api-key
60+
QVERIS_API_KEY=your-api-key # 必填
61+
QVERIS_REGION=cn # 可选:强制区域(global | cn)
62+
QVERIS_BASE_URL=https://... # 可选:覆盖 API 地址
6163
```
6264

65+
区域从 API key 前缀自动检测(`sk-cn-xxx` → 中国区,`sk-xxx` → 全球)。仅在需要覆盖时设置 `QVERIS_REGION`
66+
6367
### Claude Desktop 配置示例
6468

6569
```json
@@ -92,6 +96,25 @@ QVERIS_API_KEY=your-api-key
9296
}
9397
```
9498

99+
### 中国区配置示例
100+
101+
中国大陆用户可添加 `QVERIS_REGION` 或使用 `sk-cn-` 前缀的 key:
102+
103+
```json
104+
{
105+
"mcpServers": {
106+
"qveris": {
107+
"command": "npx",
108+
"args": ["-y", "@qverisai/mcp"],
109+
"env": {
110+
"QVERIS_API_KEY": "sk-cn-your-api-key-here",
111+
"QVERIS_REGION": "cn"
112+
}
113+
}
114+
}
115+
}
116+
```
117+
95118
各环境的详细配置指南,请参考:
96119

97120
- [Agent 安装指南](../../agent/SETUP.md)

packages/cli/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@qverisai/cli",
3-
"version": "0.2.0",
3+
"version": "0.4.0",
44
"description": "QVeris CLI -- discover, inspect, and call 10,000+ capabilities",
55
"type": "module",
66
"bin": {

packages/cli/src/commands/credits.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export async function runCredits(flags) {
1414

1515
try {
1616
// The backend returns remaining_credits in every /search response
17-
const result = await discoverTools({ apiKey, baseUrl: flags.baseUrl, query: "credit balance", limit: 1, timeoutMs: 10000 });
17+
const result = await discoverTools({ apiKey, baseUrl, query: "credit balance", limit: 1, timeoutMs: 10000 });
1818
spinner.stop();
1919

2020
const credits = result.remaining_credits;

packages/cli/src/commands/discover.mjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { createSpinner } from "../output/spinner.mjs";
88

99
export async function runDiscover(query, flags) {
1010
const apiKey = resolveApiKey(flags.apiKey);
11+
const { region, baseUrl: resolvedBaseUrl } = resolveBaseUrl({ baseUrlFlag: flags.baseUrl, apiKey });
1112
const limit = parseInt(flags.limit, 10) || 5;
1213
const timeoutMs = (parseInt(flags.timeout, 10) || 30) * 1000;
1314

@@ -16,7 +17,7 @@ export async function runDiscover(query, flags) {
1617
try {
1718
const result = await discoverTools({
1819
apiKey,
19-
baseUrl: flags.baseUrl,
20+
baseUrl: resolvedBaseUrl,
2021
query,
2122
limit,
2223
timeoutMs,
@@ -26,7 +27,6 @@ export async function runDiscover(query, flags) {
2627

2728
// Store richer session data for index resolution
2829
const tools = result.results ?? [];
29-
const { region, baseUrl: resolvedBaseUrl } = resolveBaseUrl({ baseUrlFlag: flags.baseUrl, apiKey });
3030
writeSession({
3131
discoveryId: result.search_id,
3232
query,

packages/cli/src/commands/doctor.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export async function runDoctor(flags) {
3030
// Test connectivity
3131
process.stderr.write(` \u2026 Testing API connectivity...\r`);
3232
try {
33-
await discoverTools({ apiKey, baseUrl: flags.baseUrl, query: "test", limit: 1, timeoutMs: 10000 });
33+
await discoverTools({ apiKey, baseUrl, query: "test", limit: 1, timeoutMs: 10000 });
3434
console.log(` ${green("\u2713")} API connectivity OK `);
3535
} catch (err) {
3636
console.log(` ${red("\u2718")} API connectivity failed: ${err.message} `);

packages/cli/src/commands/interactive.mjs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ import { createSpinner } from "../output/spinner.mjs";
1414

1515
export async function runInteractive(flags) {
1616
const apiKey = resolveApiKey(flags.apiKey);
17-
const baseUrl = flags.baseUrl;
18-
const { region, baseUrl: resolvedBaseUrl } = resolveBaseUrl({ baseUrlFlag: baseUrl, apiKey });
17+
const { region, baseUrl: resolvedBaseUrl } = resolveBaseUrl({ baseUrlFlag: flags.baseUrl, apiKey });
1918
const limit = parseInt(flags.limit, 10) || 5;
2019
const discoverTimeout = (parseInt(flags.timeout, 10) || 30) * 1000;
2120
const callTimeout = (parseInt(flags.timeout, 10) || 60) * 1000;
@@ -58,7 +57,7 @@ export async function runInteractive(flags) {
5857
const query = rest.join(" ");
5958
if (!query) { console.log(" Usage: discover <query>"); break; }
6059
const sp = createSpinner("Discovering...");
61-
const result = await discoverTools({ apiKey, baseUrl, query, limit, timeoutMs: discoverTimeout });
60+
const result = await discoverTools({ apiKey, baseUrl: resolvedBaseUrl, query, limit, timeoutMs: discoverTimeout });
6261
sp.stop();
6362
state.discoveryId = result.search_id;
6463
state.results = (result.results ?? []).map((t, i) => ({
@@ -73,7 +72,7 @@ export async function runInteractive(flags) {
7372
const toolId = resolveId(rest[0], state);
7473
if (!toolId) { console.log(" Usage: inspect <index|tool_id>"); break; }
7574
const sp2 = createSpinner("Inspecting...");
76-
const result = await inspectToolsByIds({ apiKey, baseUrl, toolIds: [toolId], discoveryId: state.discoveryId, timeoutMs: discoverTimeout });
75+
const result = await inspectToolsByIds({ apiKey, baseUrl: resolvedBaseUrl, toolIds: [toolId], discoveryId: state.discoveryId, timeoutMs: discoverTimeout });
7776
sp2.stop();
7877
console.log(formatInspectResult(result));
7978
break;
@@ -85,7 +84,7 @@ export async function runInteractive(flags) {
8584
const paramsStr = rest.slice(1).join(" ") || "{}";
8685
const parameters = resolveParams(paramsStr);
8786
const sp3 = createSpinner("Calling...");
88-
const result = await callTool({ apiKey, baseUrl, toolId, discoveryId: state.discoveryId, parameters, timeoutMs: callTimeout });
87+
const result = await callTool({ apiKey, baseUrl: resolvedBaseUrl, toolId, discoveryId: state.discoveryId, parameters, timeoutMs: callTimeout });
8988
sp3.stop();
9089
console.log(formatCallResult(result));
9190
if (result.success) {

packages/mcp/README.md

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ This SDK provides a [Model Context Protocol (MCP)](https://modelcontextprotocol.
1717

1818
### 1. Get Your API Key
1919

20-
Visit [QVeris](https://qveris.ai) to get your API key.
20+
Visit [QVeris](https://qveris.ai) (Global) or [QVeris](https://qveris.cn) (China) to get your API key.
2121

2222
### 2. Configure Your MCP Client
2323

@@ -182,11 +182,41 @@ The `full_content_file_url` is valid for 120 minutes.
182182
| Variable | Required | Description |
183183
|----------|----------|-------------|
184184
| `QVERIS_API_KEY` || Your QVeris API key |
185+
| `QVERIS_REGION` | | Force region: `global` or `cn` (auto-detected from key prefix if not set) |
186+
| `QVERIS_BASE_URL` | | Override API base URL (highest priority, for custom endpoints) |
187+
188+
## Region
189+
190+
Region is auto-detected from your API key prefix — no extra configuration needed.
191+
192+
| Key prefix | Region | API endpoint |
193+
|------------|--------|--------------|
194+
| `sk-xxx` | Global | `https://qveris.ai/api/v1` |
195+
| `sk-cn-xxx` | China | `https://qveris.cn/api/v1` |
196+
197+
To override manually, set environment variables in your MCP client config:
198+
199+
```json
200+
{
201+
"mcpServers": {
202+
"qveris": {
203+
"command": "npx",
204+
"args": ["-y", "@qverisai/mcp"],
205+
"env": {
206+
"QVERIS_API_KEY": "your-api-key",
207+
"QVERIS_REGION": "cn"
208+
}
209+
}
210+
}
211+
}
212+
```
213+
214+
**Priority:** `QVERIS_BASE_URL` > `QVERIS_REGION` > API key prefix auto-detection > default (global)
185215

186216
## Requirements
187217

188218
- Node.js 18.0.0 or higher
189-
- A valid QVeris API key
219+
- A valid QVeris API key ([qveris.ai](https://qveris.ai) or [qveris.cn](https://qveris.cn))
190220

191221
## Development
192222

0 commit comments

Comments
 (0)