converse-mcp-server 2.29.2 → 3.0.1

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.
Files changed (42) hide show
  1. package/.env.example +6 -3
  2. package/README.md +96 -94
  3. package/docs/API.md +703 -1562
  4. package/docs/ARCHITECTURE.md +13 -11
  5. package/docs/EXAMPLES.md +241 -667
  6. package/docs/PROVIDERS.md +104 -79
  7. package/package.json +1 -1
  8. package/src/async/asyncJobStore.js +2 -2
  9. package/src/async/jobRunner.js +6 -1
  10. package/src/async/providerStreamNormalizer.js +59 -1
  11. package/src/config.js +4 -3
  12. package/src/prompts/helpPrompt.js +43 -61
  13. package/src/providers/anthropic.js +0 -31
  14. package/src/providers/claude.js +0 -14
  15. package/src/providers/codex.js +15 -21
  16. package/src/providers/copilot.js +36 -202
  17. package/src/providers/deepseek.js +73 -53
  18. package/src/providers/gemini-cli.js +0 -3
  19. package/src/providers/google.js +10 -27
  20. package/src/providers/interface.js +0 -3
  21. package/src/providers/mistral.js +169 -63
  22. package/src/providers/openai-compatible.js +113 -28
  23. package/src/providers/openai.js +14 -66
  24. package/src/providers/openrouter-discovery.js +308 -0
  25. package/src/providers/openrouter.js +452 -282
  26. package/src/providers/xai.js +298 -280
  27. package/src/services/summarizationService.js +4 -14
  28. package/src/systemPrompts.js +19 -2
  29. package/src/tools/cancelJob.js +7 -1
  30. package/src/tools/chat.js +957 -995
  31. package/src/tools/checkStatus.js +1 -0
  32. package/src/tools/index.js +2 -6
  33. package/src/tools/modes/parallel.js +488 -0
  34. package/src/tools/modes/roundtable.js +495 -0
  35. package/src/tools/modes/streamShared.js +31 -0
  36. package/src/utils/contextProcessor.js +1 -38
  37. package/src/utils/conversationExporter.js +6 -26
  38. package/src/utils/formatStatus.js +46 -19
  39. package/src/utils/modelRouting.js +207 -4
  40. package/src/providers/openrouter-endpoints-client.js +0 -220
  41. package/src/tools/consensus.js +0 -1813
  42. package/src/tools/conversation.js +0 -1233
package/docs/PROVIDERS.md CHANGED
@@ -22,18 +22,22 @@ This guide documents all supported AI providers in the Converse MCP Server and t
22
22
  - **Get Key**: [makersuite.google.com/app/apikey](https://makersuite.google.com/app/apikey)
23
23
  - **Environment Variable**: `GOOGLE_API_KEY`
24
24
  - **Supported Models**:
25
- - `gemini-3-pro-preview` (alias: `pro`) - Enhanced reasoning with thinking levels (1M context, 64K output)
25
+ - `gemini-3.1-pro-preview` (aliases: `pro`, `gemini-pro`) - Most advanced reasoning with expanded thinking levels (1M context, 64K output)
26
+ - `gemini-3.5-flash` (aliases: `gemini-3.5`, `flash-3.5`) - Frontier-level agentic and coding performance at Flash speed (1M context, 65K output)
26
27
  - `gemini-2.5-pro` (alias: `pro 2.5`) - Deep reasoning with thinking budget (1M context, 65K output)
27
28
  - `gemini-2.5-flash` (alias: `flash`) - Ultra-fast model with thinking budget (1M context, 65K output)
28
- - **Note**: The short model name `gemini` (and `gemini:flash` / `gemini:pro`) routes to the **Antigravity CLI** (`agy`, OAuth-based access). For Google API access, use specific model names like `gemini-2.5-pro` or `gemini-2.5-flash` (bare `gemini-pro`/`gemini-flash` also route to the Google API).
29
+ - `gemini-2.5-flash-lite` (alias: `flash-lite`) - Lightweight fast model (1M context, 65K output)
30
+ - **Note**: The short model name `gemini` (and `gemini:flash` / `gemini:pro`) routes to the **Antigravity CLI** (`agy`, OAuth-based access). For Google API access, use specific model names like `gemini-3.1-pro-preview` or `gemini-2.5-flash` (bare `gemini-pro`/`gemini-flash` also route to the Google API).
29
31
 
30
32
  ### X.AI (Grok)
31
33
  - **API Key Format**: `xai-...` (starts with `xai-`)
32
34
  - **Get Key**: [console.x.ai](https://console.x.ai/)
33
35
  - **Environment Variable**: `XAI_API_KEY`
34
36
  - **Supported Models**:
35
- - `grok-4-0709` - Latest with image support and web search
36
- - `grok-code-fast-1` - Speedy and economical reasoning model that excels at agentic coding
37
+ - `grok-4.5` (default; aliases: `grok`, `grok-4.5-latest`, `grok-build-latest`) - Flagship model with image input, reasoning content, and native web/X search (500K context)
38
+ - **Reasoning**: `reasoning_effort` maps to Grok's `low`/`medium`/`high`. Grok 4.5 always reasons and cannot be turned off, so `none`/`minimal`/`low` clamp to `low`, `medium` stays `medium`, and `high`/`max` clamp to `high`.
39
+ - **Web search**: Automatic — native web/X search (Agent Tools) is attached on every Grok 4.5 request; the model decides per-request whether to search, and any citations are returned in metadata.
40
+ - **Retired IDs**: Older Grok identifiers (e.g. `grok-4-0709`, `grok-code-fast-1`) still pass through as explicit model strings, but xAI does not surface a retirement error for them — it silently remaps them upstream to a current model (HTTP 200). Use `grok-4.5` for predictable results.
37
41
 
38
42
  ### Anthropic (Claude)
39
43
  - **API Key Format**: `sk-ant-...` (starts with `sk-ant-`)
@@ -53,39 +57,40 @@ This guide documents all supported AI providers in the Converse MCP Server and t
53
57
  - **Get Key**: [console.mistral.ai](https://console.mistral.ai/)
54
58
  - **Environment Variable**: `MISTRAL_API_KEY`
55
59
  - **Supported Models**:
56
- - `mistral-large-latest` - Most capable model
57
- - `mistral-medium-latest` - Balanced performance
58
- - `mistral-small-latest` - Fast and efficient
59
- - `open-mistral-7b`, `open-mixtral-8x7b`, `open-mixtral-8x22b` - Open-source models
60
+ - `mistral-medium-3-5` (default; aliases: `mistral`, `mistral-medium`, `mistral-medium-latest`) - Frontier-class multimodal model with adjustable reasoning (256K context)
61
+ - `mistral-small-2603` (aliases: `mistral-small`, `mistral-small-latest`) - Hybrid multimodal model unifying instruct, reasoning, and coding (256K context)
62
+ - `mistral-large-2512` (aliases: `mistral-large`, `mistral-large-latest`) - Open-weight MoE flagship, image-capable (256K context)
63
+ - **Reasoning**: Mistral exposes only `high` and `none`. On the reasoning-capable models (`mistral-medium-3-5`, `mistral-small-2603`), every enabled `reasoning_effort` level maps to `high` and only `none` disables thinking. `mistral-large-2512` has no adjustable reasoning, so `reasoning_effort` is never sent for it.
64
+ - **Images**: `mistral-medium-3-5` and `mistral-small-2603` accept image input; `mistral-large-2512` is text-only.
60
65
 
61
66
  ### DeepSeek
62
67
  - **API Key Format**: 32+ character string
63
68
  - **Get Key**: [platform.deepseek.com](https://platform.deepseek.com/)
64
69
  - **Environment Variable**: `DEEPSEEK_API_KEY`
65
70
  - **Supported Models**:
66
- - `deepseek-chat` - Advanced conversational model
67
- - `deepseek-coder` - Specialized for code generation
71
+ - `deepseek-v4-pro` (default; aliases: `deepseek`, `deepseek-pro`) - Flagship MoE model with thinking mode (1M context, 384K max output, text-only)
72
+ - `deepseek-v4-flash` (alias: `deepseek-flash`) - Faster, lower-cost V4 tier with thinking mode (1M context, 384K max output, text-only)
73
+ - **Reasoning**: DeepSeek V4 exposes thinking mode via a `thinking` toggle plus a `reasoning_effort` of `high` or `max`. `none` disables thinking; `minimal`/`low`/`medium`/`high` enable thinking at `high`; `max` enables thinking at `max`.
68
74
 
69
75
  ### OpenRouter
70
76
  - **API Key Format**: `sk-or-...` (starts with `sk-or-`)
71
77
  - **Get Key**: [openrouter.ai/keys](https://openrouter.ai/keys)
72
- - **Environment Variables**:
78
+ - **Environment Variables**:
73
79
  - `OPENROUTER_API_KEY` - Your API key
74
- - `OPENROUTER_REFERER` - Required referer URL (e.g., your GitHub repo)
75
- - `OPENROUTER_TITLE` - Optional title for request tracking
76
- - `OPENROUTER_DYNAMIC_MODELS` - Enable dynamic model discovery (default: false, required for `provider/model` format)
77
- - **Static Models**: Pre-configured models available without dynamic discovery
78
- - `qwen/qwen3-235b-a22b-thinking-2507` - Qwen3 235B with thinking capabilities
79
- - `qwen/qwen3-coder` - Qwen3 specialized for coding
80
- - `moonshotai/kimi-k2` - Kimi K2 with 200K context window
81
- - `openrouter/auto` - Auto-selects best model using NotDiamond routing
82
- - **Dynamic Models**: Requires `OPENROUTER_DYNAMIC_MODELS=true` to use any model in `provider/model` format
83
- - `anthropic/claude-3.5-sonnet`
84
- - `openai/gpt-4-turbo`
85
- - `google/gemini-pro`
86
- - `mistralai/mistral-large`
87
- - `meta-llama/llama-3.1-405b-instruct`
88
- - And many more - see [openrouter.ai/models](https://openrouter.ai/models)
80
+ - `OPENROUTER_REFERER` - Optional referer URL (e.g., your GitHub repo) for OpenRouter ranking credit; omitting it is valid
81
+ - `OPENROUTER_TITLE` - Optional title for OpenRouter ranking credit
82
+ - **Curated Models** (default `z-ai/glm-5.2`):
83
+ - `z-ai/glm-5.2` (aliases: `glm`, `glm-5.2`) - Large-scale reasoning model, text-only (1M context)
84
+ - `deepseek/deepseek-v4-pro` - DeepSeek V4 Pro reasoning model, text-only (1M context, 384K output)
85
+ - `deepseek/deepseek-v4-flash` - Faster, lower-cost DeepSeek V4 tier, text-only (1M context, 384K output)
86
+ - `qwen/qwen3.7-max` (alias: `qwen3.7-max`) - Flagship Qwen, text-only (1M context)
87
+ - `qwen/qwen3.7-plus` (alias: `qwen3.7-plus`) - Image-capable Qwen (1M context)
88
+ - `moonshotai/kimi-k2.7-code` (alias: `kimi-k2.7-code`) - Coding model, image-capable, reasoning always on (256K context)
89
+ - `moonshotai/kimi-k2.6` (alias: `kimi-k2.6`) - Image-capable general model (256K context)
90
+ - `openrouter/auto` - Auto-selects the best model for your prompt
91
+ - **Any other model**: Use the full `provider/model` slug directly (e.g. `anthropic/claude-sonnet-5`, `meta-llama/llama-3.1-405b-instruct`) or the `openrouter:` namespace (e.g. `openrouter:z-ai/glm-5.2`). No extra configuration is needed — slugs route to OpenRouter as-is. A slug absent from OpenRouter's live catalog fails before inference with `MODEL_NOT_FOUND`. See [openrouter.ai/models](https://openrouter.ai/models) for the full catalog.
92
+ - **Reasoning**: Per-model. `z-ai/glm-5.2` and the `deepseek/deepseek-v4-*` slugs are effort-tiered (`max` → `xhigh`, other enabled levels → `high`, `none` disables); `qwen/qwen3.7-*` and `moonshotai/kimi-k2.6` are enable/disable only (`none` disables, any other level enables); `moonshotai/kimi-k2.7-code` always reasons and cannot be disabled; `openrouter/auto` lets the router choose.
93
+ - **Web search (opt-in, adds cost)**: OpenRouter web search is off by default because it incurs a real per-request charge. Enable it explicitly by appending `:online` to a slug (e.g. `z-ai/glm-5.2:online` or `openrouter:qwen/qwen3.7-max:online`). When enabled, `annotations[].url_citation` citations are captured into metadata. Ordinary requests never attach a web-search plugin.
89
94
 
90
95
  ### Codex
91
96
  - **API Key Format**: Optional (uses ChatGPT login by default)
@@ -133,8 +138,6 @@ This guide documents all supported AI providers in the Converse MCP Server and t
133
138
  - **Subscription Access**: Leverages the Antigravity weekly compute allowance instead of pay-per-API-call
134
139
  - **One-shot responses**: The provider shells out to `agy -p` under a pseudo-terminal and returns the full response in a single chunk (no token-level streaming; ~7s minimum per call, ~30-60s for very large prompts)
135
140
 
136
- > Note: This replaces the previous `@google/gemini-cli` (`ai-sdk-provider-gemini-cli`) integration, whose OAuth access Google sunsets on 2026-06-18.
137
-
138
141
  **Authentication Setup:**
139
142
  ```bash
140
143
  # Install the Antigravity CLI (agy)
@@ -155,18 +158,19 @@ agy
155
158
  "name": "chat",
156
159
  "arguments": {
157
160
  "prompt": "Explain async/await in JavaScript",
158
- "model": "gemini"
161
+ "models": ["gemini"]
159
162
  }
160
163
  }
161
164
  ```
162
165
 
163
- *Consensus Tool:*
166
+ *Consensus mode:*
164
167
  ```json
165
168
  {
166
- "name": "consensus",
169
+ "name": "chat",
167
170
  "arguments": {
168
171
  "prompt": "Should we use TypeScript for this component?",
169
- "models": ["gemini", "gpt-5", "claude-sonnet-4-6"]
172
+ "models": ["gemini", "gpt-5.6", "claude"],
173
+ "mode": "consensus"
170
174
  }
171
175
  }
172
176
  ```
@@ -197,13 +201,30 @@ agy
197
201
  - **Subscription Access**: Uses your Claude subscription instead of API credits
198
202
  - **Local File Access**: Reads files directly from the working directory
199
203
  - **Image Support**: Via the SDK's streaming input mode
200
- - **SDK-Managed Parameters**: `temperature`, `use_websearch`, and `reasoning_effort` are managed internally (ignored if specified)
204
+ - **SDK-Managed Parameters**: `reasoning_effort` and other sampling parameters are managed internally by the SDK
201
205
 
202
206
  **Differences from Anthropic API Provider:**
203
207
  - **Authentication**: Claude Code login vs `ANTHROPIC_API_KEY`
204
208
  - **Billing**: Claude subscription vs pay-per-use API
205
209
  - **Model Routing**: `claude` and `claude:*` → SDK provider; specific names (e.g., `claude-fable-5`, `opus`, `sonnet`) → API provider
206
210
 
211
+ ### GitHub Copilot SDK
212
+ - **Authentication**: GitHub Copilot subscription via the Copilot CLI (`gh auth login` with an active Copilot subscription) — no API key needed
213
+ - **Setup Required**: Authenticate the GitHub CLI and ensure your account has an active Copilot subscription
214
+ - **Environment Variables**: None
215
+ - **Supported Models** (reach them with the `copilot:` namespace, e.g. `copilot:gpt-5.6-terra`):
216
+ - `copilot` - Uses Copilot's default or env-configured model
217
+ - OpenAI: `gpt-5.6-sol` (aliases: bare `gpt-5.6`, `gpt-5`), `gpt-5.6-terra` (recommended balanced tier), `gpt-5.6-luna`
218
+ - Anthropic: `claude-fable-5` (alias: `fable`), `claude-sonnet-5` (alias: `sonnet`), `claude-opus-4.8` (aliases: `opus`, `claude`)
219
+ - Google: `gemini-3.1-pro-preview` (aliases: `gemini`, `gemini-3.1-pro`), `gemini-3.5-flash` (alias: `gemini-flash`)
220
+ - **Reasoning**: The `gpt-5.6-sol`/`terra`/`luna` tiers accept `reasoning_effort`.
221
+ - **Explicit pass-through**: Any other `copilot:<id>` model string is forwarded to the Copilot backend verbatim, so IDs outside the curated list still work while the backend accepts them.
222
+
223
+ **Key Features:**
224
+ - **Subscription Access**: Uses your GitHub Copilot subscription instead of API credits
225
+ - **Multiple Backends**: OpenAI, Anthropic, and Google models through a single subscription
226
+ - **Model IDs**: Lowercase dot-versioned (e.g. `claude-opus-4.8`, `gemini-3.1-pro-preview`)
227
+
207
228
  ## Configuration Examples
208
229
 
209
230
  ### Basic Configuration (.env file)
@@ -214,12 +235,10 @@ ANTHROPIC_API_KEY=sk-ant-your_key_here
214
235
  MISTRAL_API_KEY=your_mistral_key_here
215
236
  DEEPSEEK_API_KEY=your_deepseek_key_here
216
237
 
217
- # OpenRouter requires both API key and referer
238
+ # OpenRouter needs only an API key; any provider/model slug works directly
218
239
  OPENROUTER_API_KEY=sk-or-your_key_here
240
+ # Optional: referer and title for OpenRouter ranking credit
219
241
  OPENROUTER_REFERER=https://github.com/YourUsername/YourApp
220
- # Optional: Enable dynamic model discovery to use any OpenRouter model
221
- OPENROUTER_DYNAMIC_MODELS=true
222
- # Optional: Add title for request tracking
223
242
  OPENROUTER_TITLE=Converse
224
243
 
225
244
  # Codex - Optional API key (uses ChatGPT login by default)
@@ -243,7 +262,6 @@ CODEX_APPROVAL_POLICY=never # never (default), untrusted, on-fa
243
262
  "DEEPSEEK_API_KEY": "your_key_here",
244
263
  "OPENROUTER_API_KEY": "your_key_here",
245
264
  "OPENROUTER_REFERER": "https://github.com/YourUsername/YourApp",
246
- "OPENROUTER_DYNAMIC_MODELS": "true",
247
265
  "OPENROUTER_TITLE": "Converse"
248
266
  }
249
267
  }
@@ -257,20 +275,26 @@ CODEX_APPROVAL_POLICY=never # never (default), untrusted, on-fa
257
275
  All providers support streaming responses for real-time output.
258
276
 
259
277
  ### Image Support
260
- - **Full Support**: OpenAI, Google, X.AI (Grok-4), Anthropic (Claude-4 series, Claude-3-Opus)
261
- - **Via OpenRouter**: Depends on the underlying model
262
- - **No Support**: DeepSeek, Mistral (except Large), Codex
278
+ - **Full Support**: OpenAI, Google, X.AI (Grok 4.5), Anthropic (Claude-4 series, Claude-3-Opus)
279
+ - **Mistral**: `mistral-medium-3-5` and `mistral-small-2603` accept images; `mistral-large-2512` is text-only
280
+ - **Via OpenRouter**: Depends on the model — `qwen/qwen3.7-plus`, `moonshotai/kimi-k2.7-code`, and `moonshotai/kimi-k2.6` accept images; `z-ai/glm-5.2` and the `deepseek/deepseek-v4-*` slugs are text-only
281
+ - **No Support**: DeepSeek (native), Codex
263
282
 
264
283
  ### Web Search
265
- - **Native Support**: OpenAI, Google, X.AI (Grok-4)
266
- - **No Support**: Anthropic, Mistral, DeepSeek, OpenRouter, Codex
284
+ - **Automatic where supported**: OpenAI, Google, and X.AI (Grok 4.5, via Agent Tools) attach web search on every request for capable models; the model decides whether to use it
285
+ - **OpenRouter (opt-in, adds cost)**: Off by default; append `:online` to a slug to enable it per request (real per-request charge), with citations captured into metadata
286
+ - **No Support**: Anthropic, Mistral, DeepSeek, Codex
267
287
 
268
288
  ### Thinking/Reasoning Modes
269
- - **OpenAI**: O3 series models support `reasoning_effort` parameter
289
+ - **OpenAI**: GPT-5 family and O3 series models support the `reasoning_effort` parameter (GPT-5.6 accepts `none` through `max`, mapping `minimal` to `low`; GPT-5 Pro is fixed at `high`)
270
290
  - **Google**:
271
291
  - Gemini 3.0 Pro: Thinking levels (low/high) via `reasoning_effort` - always enabled
272
292
  - Gemini 2.5 Pro/Flash: Thinking budget (token-based) via `reasoning_effort`
273
293
  - **Anthropic**: Claude Fable 5, Opus 4.6+, and Sonnet 4.6 use adaptive thinking (depth controlled by `reasoning_effort` via Anthropic's `effort` parameter); older Claude 4 models use budget-based extended thinking
294
+ - **X.AI**: Grok 4.5 maps `reasoning_effort` to `low`/`medium`/`high` and always reasons (cannot be disabled)
295
+ - **Mistral**: `mistral-medium-3-5` and `mistral-small-2603` map `reasoning_effort` to `high` (enabled) or `none` (disabled); `mistral-large-2512` has no adjustable reasoning
296
+ - **DeepSeek**: V4 models use thinking mode via `reasoning_effort` (`none` disables; enabled levels use `high`, `max` uses `max`)
297
+ - **OpenRouter**: Reasoning is per-model (effort-tiered, enable/disable-only, mandatory, or router-chosen — see the OpenRouter section)
274
298
  - **Codex**: Thread-based agentic reasoning with persistent context
275
299
  - **Others**: Standard inference only
276
300
 
@@ -280,7 +304,7 @@ All providers support streaming responses for real-time output.
280
304
 
281
305
  ## Model Selection in Tools
282
306
 
283
- When using the chat or consensus tools, specify models using their identifiers:
307
+ When using the chat tool in any mode, specify models using their identifiers:
284
308
 
285
309
  ### Model Routing Logic
286
310
 
@@ -307,31 +331,34 @@ When using the chat or consensus tools, specify models using their identifiers:
307
331
  4. **OpenRouter Auto**: Special aliases route to OpenRouter's auto-selection:
308
332
  - "openrouter/auto", "openrouter auto", "auto router", "auto-router"
309
333
 
310
- ```javascript
311
- // Chat tool examples
312
- {
313
- "model": "gpt-5", // OpenAI (keyword match)
314
- "model": "fable", // Anthropic (keyword match -> claude-fable-5)
315
- "model": "opus", // Anthropic (keyword match -> claude-opus-4-8)
316
- "model": "sonnet", // Anthropic (keyword match -> claude-sonnet-4-6)
317
- "model": "claude", // Claude Agent SDK (defaults to Claude Fable 5)
318
- "model": "claude:opus", // Claude Agent SDK (Claude Opus 4.8)
319
- "model": "gemini-2.5-pro", // Google (keyword match)
320
- "model": "grok-4", // X.AI (keyword match)
321
- "model": "mistral-large", // Mistral (keyword match)
322
- "model": "deepseek-chat", // DeepSeek (keyword match)
323
- "model": "anthropic/claude-sonnet-4", // OpenRouter (slash format, not in Anthropic)
324
- "model": "qwen/qwen3-coder", // OpenRouter (static model)
325
- "model": "openrouter/auto" // OpenRouter auto-selection
326
- }
334
+ The `models` array always holds plain model-name strings. Each string routes as follows:
335
+
336
+ ```text
337
+ "gpt-5.6" // OpenAI (keyword match)
338
+ "fable" // Anthropic (keyword match -> claude-fable-5)
339
+ "opus" // Anthropic (keyword match -> claude-opus-4-8)
340
+ "sonnet" // Anthropic (keyword match -> claude-sonnet-4-6)
341
+ "claude" // Claude Agent SDK (defaults to Claude Fable 5)
342
+ "claude:opus" // Claude Agent SDK (Claude Opus 4.8)
343
+ "gemini-2.5-pro" // Google (keyword match)
344
+ "grok-4.5" // X.AI (keyword match)
345
+ "mistral-large" // Mistral (alias -> mistral-large-2512)
346
+ "deepseek" // DeepSeek (alias -> deepseek-v4-pro)
347
+ "z-ai/glm-5.2" // OpenRouter (curated slug)
348
+ "z-ai/glm-5.2:online" // OpenRouter with web search opt-in
349
+ "anthropic/claude-sonnet-5" // OpenRouter (any full slug routes as-is)
350
+ "openrouter/auto" // OpenRouter auto-selection
351
+ ```
327
352
 
328
- // Consensus tool with multiple providers
353
+ ```json
354
+ // Consensus mode with multiple providers
329
355
  {
330
- "models": [
331
- {"model": "o3"},
332
- {"model": "claude-sonnet-4-6"},
333
- {"model": "gemini-2.5-pro"}
334
- ]
356
+ "name": "chat",
357
+ "arguments": {
358
+ "prompt": "Which database fits our workload?",
359
+ "models": ["gpt-5.6", "claude", "gemini-2.5-pro"],
360
+ "mode": "consensus"
361
+ }
335
362
  }
336
363
  ```
337
364
 
@@ -353,14 +380,12 @@ When using the chat or consensus tools, specify models using their identifiers:
353
380
  - OpenRouter provides unified rate limiting across providers
354
381
  - Consider using multiple providers for better availability
355
382
 
356
- ### OpenRouter Compliance
357
- - The `OPENROUTER_REFERER` header is **required**
358
- - Use your application URL or GitHub repository
359
- - This helps OpenRouter track usage for compliance
360
-
361
- ### OpenRouter Dynamic Models
362
- - Enable with `OPENROUTER_DYNAMIC_MODELS=true`
363
- - First request to a new model may be slower (fetches capabilities)
364
- - Model capabilities are cached for 24 hours
365
- - Use any model from [openrouter.ai/models](https://openrouter.ai/models)
366
- - Models must use `provider/model` format (e.g., `meta-llama/llama-3.2-90b`)
383
+ ### OpenRouter Attribution
384
+ - `OPENROUTER_REFERER` and `OPENROUTER_TITLE` are optional — set them to your application URL / name for OpenRouter ranking credit
385
+ - Omitting them is valid and never blocks a request
386
+
387
+ ### OpenRouter Model Selection
388
+ - The 8 curated slugs work out of the box; the default is `z-ai/glm-5.2`
389
+ - Any other model works via its full `provider/model` slug or the `openrouter:` namespace — no extra configuration
390
+ - The first request to a non-curated slug fetches its capabilities from OpenRouter's live catalog; a slug absent from that catalog fails before inference with `MODEL_NOT_FOUND`
391
+ - Append `:online` to a slug to enable web search for that request (adds a real per-request cost)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "converse-mcp-server",
3
- "version": "2.29.2",
3
+ "version": "3.0.1",
4
4
  "description": "Converse MCP Server - Converse with other LLMs with chat and consensus tools",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -167,9 +167,9 @@ class LRUAsyncJobStore extends AsyncJobStoreInterface {
167
167
  async create(tool, options = {}) {
168
168
  try {
169
169
  // Validate parameters
170
- if (!tool || !['chat', 'consensus', 'conversation'].includes(tool)) {
170
+ if (!tool || !['chat'].includes(tool)) {
171
171
  throw new AsyncJobStoreError(
172
- 'Invalid tool: must be "chat", "consensus", or "conversation"',
172
+ 'Invalid tool: must be "chat"',
173
173
  'INVALID_TOOL',
174
174
  );
175
175
  }
@@ -81,7 +81,8 @@ export class JobRunner extends EventEmitter {
81
81
  * Submit a job for background execution
82
82
  * @param {object} jobSpec - Job specification
83
83
  * @param {string} jobSpec.sessionId - Session identifier
84
- * @param {string} jobSpec.tool - Tool name ('chat' | 'consensus')
84
+ * @param {string} jobSpec.tool - Tool name (always 'chat')
85
+ * @param {string} jobSpec.mode - Chat mode ('chat' | 'consensus' | 'roundtable')
85
86
  * @param {Function} runFunction - Function to execute (async)
86
87
  * @param {object} options - Execution options
87
88
  * @param {number} options.timeout - Job timeout in ms
@@ -112,6 +113,7 @@ export class JobRunner extends EventEmitter {
112
113
  // Create job in store
113
114
  const jobId = await this.asyncJobStore.create(jobSpec.tool, {
114
115
  sessionId: jobSpec.sessionId,
116
+ mode: jobSpec.mode,
115
117
  timeout: options.timeout || this.defaultTimeout,
116
118
  priority: options.priority || false,
117
119
  ...jobSpec.options,
@@ -336,6 +338,7 @@ export class JobRunner extends EventEmitter {
336
338
  jobId,
337
339
  status: JOB_STATUS.COMPLETED,
338
340
  tool: finalJobState.tool,
341
+ mode: finalJobState.mode,
339
342
  result,
340
343
  completedAt: Date.now(),
341
344
  createdAt: finalJobState.createdAt,
@@ -396,6 +399,7 @@ export class JobRunner extends EventEmitter {
396
399
  jobId,
397
400
  status: JOB_STATUS.CANCELLED,
398
401
  tool: cancelledJobState.tool,
402
+ mode: cancelledJobState.mode,
399
403
  result: partialResult,
400
404
  cancelledAt: Date.now(),
401
405
  createdAt: cancelledJobState.createdAt,
@@ -446,6 +450,7 @@ export class JobRunner extends EventEmitter {
446
450
  jobId,
447
451
  status: JOB_STATUS.FAILED,
448
452
  tool: failedJobState.tool,
453
+ mode: failedJobState.mode,
449
454
  error: executionError.message || executionError,
450
455
  failedAt: Date.now(),
451
456
  createdAt: failedJobState.createdAt,
@@ -24,6 +24,7 @@ const EVENT_TYPES = {
24
24
  END: 'end',
25
25
  ERROR: 'error',
26
26
  REASONING_SUMMARY: 'reasoning_summary',
27
+ REASONING: 'reasoning',
27
28
  };
28
29
 
29
30
  /**
@@ -174,6 +175,7 @@ class ProviderStreamNormalizer {
174
175
 
175
176
  let hasStarted = false;
176
177
  let accumulatedContent = '';
178
+ let accumulatedReasoning = '';
177
179
  let accumulatedUsage = null;
178
180
  let finishReason = null;
179
181
  const searchMetadata = {};
@@ -194,6 +196,13 @@ class ProviderStreamNormalizer {
194
196
  continue;
195
197
  }
196
198
 
199
+ // Handle reasoning/thinking events (kept separate from answer text)
200
+ if (event.type === 'thinking') {
201
+ accumulatedReasoning += event.content || '';
202
+ yield this.createReasoningEvent(event.content || '', provider, model);
203
+ continue;
204
+ }
205
+
197
206
  // Handle usage events (with XAI-specific search metadata)
198
207
  if (event.type === 'usage') {
199
208
  accumulatedUsage = event.usage;
@@ -212,6 +221,7 @@ class ProviderStreamNormalizer {
212
221
  const endMetadata = {
213
222
  ...event.metadata,
214
223
  ...searchMetadata,
224
+ ...(accumulatedReasoning && { reasoning: accumulatedReasoning }),
215
225
  };
216
226
 
217
227
  yield this.createEndEvent(
@@ -424,6 +434,7 @@ class ProviderStreamNormalizer {
424
434
 
425
435
  let hasStarted = false;
426
436
  let accumulatedContent = '';
437
+ let accumulatedReasoning = '';
427
438
  let accumulatedUsage = null;
428
439
  let finishReason = null;
429
440
 
@@ -443,6 +454,13 @@ class ProviderStreamNormalizer {
443
454
  continue;
444
455
  }
445
456
 
457
+ // Handle reasoning/thinking events (kept separate from answer text)
458
+ if (event.type === 'thinking') {
459
+ accumulatedReasoning += event.content || '';
460
+ yield this.createReasoningEvent(event.content || '', provider, model);
461
+ continue;
462
+ }
463
+
446
464
  // Handle usage events
447
465
  if (event.type === 'usage') {
448
466
  accumulatedUsage = event.usage;
@@ -453,13 +471,17 @@ class ProviderStreamNormalizer {
453
471
  // Handle end event
454
472
  if (event.type === 'end') {
455
473
  finishReason = event.stop_reason || event.metadata?.finish_reason;
474
+ const endMetadata = {
475
+ ...event.metadata,
476
+ ...(accumulatedReasoning && { reasoning: accumulatedReasoning }),
477
+ };
456
478
  yield this.createEndEvent(
457
479
  {
458
480
  content: event.content || accumulatedContent,
459
481
  stopReason: finishReason,
460
482
  usage: event.metadata?.usage || accumulatedUsage,
461
483
  responseTime: Date.now() - startTime,
462
- metadata: event.metadata,
484
+ metadata: endMetadata,
463
485
  },
464
486
  provider,
465
487
  model,
@@ -494,6 +516,7 @@ class ProviderStreamNormalizer {
494
516
 
495
517
  let hasStarted = false;
496
518
  let accumulatedContent = '';
519
+ let accumulatedReasoning = '';
497
520
  let accumulatedUsage = null;
498
521
  let finishReason = null;
499
522
  const reasoningMetadata = {};
@@ -516,6 +539,13 @@ class ProviderStreamNormalizer {
516
539
  continue;
517
540
  }
518
541
 
542
+ // Handle reasoning/thinking events (kept separate from answer text)
543
+ if (event.type === 'thinking') {
544
+ accumulatedReasoning += event.content || '';
545
+ yield this.createReasoningEvent(event.content || '', provider, model);
546
+ continue;
547
+ }
548
+
519
549
  // Handle usage events (with DeepSeek-specific reasoning tokens)
520
550
  if (event.type === 'usage') {
521
551
  accumulatedUsage = event.usage;
@@ -532,6 +562,7 @@ class ProviderStreamNormalizer {
532
562
  const endMetadata = {
533
563
  ...event.metadata,
534
564
  ...reasoningMetadata,
565
+ ...(accumulatedReasoning && { reasoning: accumulatedReasoning }),
535
566
  };
536
567
 
537
568
  yield this.createEndEvent(
@@ -575,6 +606,7 @@ class ProviderStreamNormalizer {
575
606
 
576
607
  let hasStarted = false;
577
608
  let accumulatedContent = '';
609
+ let accumulatedReasoning = '';
578
610
  let accumulatedUsage = null;
579
611
  let finishReason = null;
580
612
  let routingMetadata = {};
@@ -595,6 +627,13 @@ class ProviderStreamNormalizer {
595
627
  continue;
596
628
  }
597
629
 
630
+ // Handle reasoning/thinking events (kept separate from answer text)
631
+ if (event.type === 'thinking') {
632
+ accumulatedReasoning += event.content || '';
633
+ yield this.createReasoningEvent(event.content || '', provider, model);
634
+ continue;
635
+ }
636
+
598
637
  // Handle usage events (with OpenRouter-specific routing metadata)
599
638
  if (event.type === 'usage') {
600
639
  accumulatedUsage = event.usage;
@@ -611,6 +650,7 @@ class ProviderStreamNormalizer {
611
650
  const endMetadata = {
612
651
  ...event.metadata,
613
652
  ...routingMetadata,
653
+ ...(accumulatedReasoning && { reasoning: accumulatedReasoning }),
614
654
  };
615
655
 
616
656
  yield this.createEndEvent(
@@ -771,6 +811,24 @@ class ProviderStreamNormalizer {
771
811
  };
772
812
  }
773
813
 
814
+ /**
815
+ * Create standardized streamed-reasoning event. Distinct from a delta so
816
+ * downstream consumers keep reasoning separate from the visible answer.
817
+ */
818
+ createReasoningEvent(content, provider, model) {
819
+ return {
820
+ type: EVENT_TYPES.REASONING,
821
+ provider,
822
+ model,
823
+ timestamp: Date.now(),
824
+ data: {
825
+ content: content || '',
826
+ role: 'assistant',
827
+ isReasoning: true,
828
+ },
829
+ };
830
+ }
831
+
774
832
  /**
775
833
  * Create standardized reasoning summary event
776
834
  */
package/src/config.js CHANGED
@@ -222,13 +222,14 @@ const CONFIG_SCHEMA = {
222
222
  OPENROUTER_TITLE: {
223
223
  type: 'string',
224
224
  required: false,
225
- description: 'OpenRouter X-Title header for request tracking',
225
+ description:
226
+ 'Optional OpenRouter attribution title, sent as the canonical X-OpenRouter-Title header',
226
227
  },
227
228
  OPENROUTER_DYNAMIC_MODELS: {
228
229
  type: 'boolean',
229
230
  default: false,
230
231
  description:
231
- 'Enable dynamic model discovery via OpenRouter endpoints API',
232
+ 'Accepted but unnecessary full OpenRouter provider/model slugs always resolve without it',
232
233
  },
233
234
 
234
235
  // Google Vertex AI configuration
@@ -294,7 +295,7 @@ const CONFIG_SCHEMA = {
294
295
  type: 'string',
295
296
  required: false,
296
297
  description:
297
- 'Default model for Copilot SDK sessions (e.g., gpt-5, claude-sonnet-4.5)',
298
+ 'Default model for Copilot SDK sessions (e.g., gpt-5.6-sol, claude-sonnet-5)',
298
299
  },
299
300
  COPILOT_CLI_PATH: {
300
301
  type: 'string',