consult-llm-mcp 2.4.1 → 2.4.2
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/README.md +10 -5
- package/dist/config.d.ts +8 -0
- package/dist/config.js +30 -4
- package/dist/config.test.js +89 -1
- package/dist/llm-cost.js +4 -0
- package/dist/models.d.ts +1 -1
- package/dist/models.js +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Consult LLM MCP
|
|
2
2
|
|
|
3
3
|
An MCP server that lets Claude Code consult stronger AI models (GPT-5.2, Gemini
|
|
4
|
-
3.
|
|
4
|
+
3.1 Pro, DeepSeek Reasoner) when Sonnet has you running in circles and you need
|
|
5
5
|
to bring in the heavy artillery. Supports multi-turn conversations.
|
|
6
6
|
|
|
7
7
|
```
|
|
@@ -27,7 +27,7 @@ to bring in the heavy artillery. Supports multi-turn conversations.
|
|
|
27
27
|
|
|
28
28
|
## Features
|
|
29
29
|
|
|
30
|
-
- Query powerful AI models (GPT-5.2, Gemini 3.
|
|
30
|
+
- Query powerful AI models (GPT-5.2, Gemini 3.1 Pro, DeepSeek Reasoner) with
|
|
31
31
|
relevant files as context
|
|
32
32
|
- Direct queries with optional file context
|
|
33
33
|
- Include git changes for code review and analysis
|
|
@@ -333,7 +333,8 @@ context, but it helps.
|
|
|
333
333
|
#### Gemini CLI
|
|
334
334
|
|
|
335
335
|
Use Gemini's local CLI to take advantage of Google's
|
|
336
|
-
[free quota](https://developers.google.com/gemini-code-assist/resources/quotas#quotas-for-agent-mode-gemini-cli)
|
|
336
|
+
[free quota](https://developers.google.com/gemini-code-assist/resources/quotas#quotas-for-agent-mode-gemini-cli)
|
|
337
|
+
or use your Google AI Pro subscription.
|
|
337
338
|
|
|
338
339
|
**Requirements:**
|
|
339
340
|
|
|
@@ -456,7 +457,8 @@ See the "Using web mode..." example above for a concrete transcript.
|
|
|
456
457
|
- `DEEPSEEK_API_KEY` - Your DeepSeek API key (required for DeepSeek models)
|
|
457
458
|
- `CONSULT_LLM_DEFAULT_MODEL` - Override the default model (optional)
|
|
458
459
|
- Options: `gpt-5.2` (default), `gemini-2.5-pro`, `gemini-3-pro-preview`,
|
|
459
|
-
`deepseek-reasoner`, `gpt-5.3-codex`,
|
|
460
|
+
`gemini-3.1-pro-preview`, `deepseek-reasoner`, `gpt-5.3-codex`,
|
|
461
|
+
`gpt-5.2-codex`
|
|
460
462
|
- `GEMINI_BACKEND` - Backend for Gemini models (optional)
|
|
461
463
|
- Options: `api` (default), `gemini-cli`, `cursor-cli`
|
|
462
464
|
- `OPENAI_BACKEND` - Backend for OpenAI models (optional)
|
|
@@ -554,7 +556,8 @@ models complex questions.
|
|
|
554
556
|
|
|
555
557
|
- **model** (optional): LLM model to use
|
|
556
558
|
- Options: `gpt-5.2` (default), `gemini-2.5-pro`, `gemini-3-pro-preview`,
|
|
557
|
-
`deepseek-reasoner`, `gpt-5.3-codex`,
|
|
559
|
+
`gemini-3.1-pro-preview`, `deepseek-reasoner`, `gpt-5.3-codex`,
|
|
560
|
+
`gpt-5.2-codex`
|
|
558
561
|
|
|
559
562
|
- **task_mode** (optional): Controls the system prompt persona. The calling LLM
|
|
560
563
|
should choose based on the task:
|
|
@@ -589,6 +592,8 @@ models complex questions.
|
|
|
589
592
|
- **gemini-2.5-pro**: Google's Gemini 2.5 Pro ($1.25/$10 per million tokens)
|
|
590
593
|
- **gemini-3-pro-preview**: Google's Gemini 3 Pro Preview ($2/$12 per million
|
|
591
594
|
tokens for prompts ≤200k tokens, $4/$18 for prompts >200k tokens)
|
|
595
|
+
- **gemini-3.1-pro-preview**: Google's Gemini 3.1 Pro Preview ($2/$12 per
|
|
596
|
+
million tokens for prompts ≤200k tokens, $4/$18 for prompts >200k tokens)
|
|
592
597
|
- **deepseek-reasoner**: DeepSeek's reasoning model ($0.55/$2.19 per million
|
|
593
598
|
tokens)
|
|
594
599
|
- **gpt-5.2**: OpenAI's latest GPT model
|
package/dist/config.d.ts
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
import { z } from 'zod/v4';
|
|
2
|
+
export interface ProviderAvailability {
|
|
3
|
+
geminiApiKey?: string;
|
|
4
|
+
geminiBackend: string;
|
|
5
|
+
openaiApiKey?: string;
|
|
6
|
+
openaiBackend: string;
|
|
7
|
+
deepseekApiKey?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function filterByAvailability(models: string[], providers: ProviderAvailability): string[];
|
|
2
10
|
/** Build the final model catalog from built-in + extra + allowlist filtering. */
|
|
3
11
|
export declare function buildModelCatalog(builtinModels: readonly string[], extraModelsRaw?: string, allowedModelsRaw?: string): string[];
|
|
4
12
|
export declare const SupportedChatModel: z.ZodEnum<{
|
package/dist/config.js
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
import { z } from 'zod/v4';
|
|
2
2
|
import { ALL_MODELS } from './models.js';
|
|
3
3
|
import { logToFile } from './logger.js';
|
|
4
|
+
export function filterByAvailability(models, providers) {
|
|
5
|
+
return models.filter((model) => {
|
|
6
|
+
if (model.startsWith('gemini-')) {
|
|
7
|
+
return providers.geminiBackend !== 'api' || !!providers.geminiApiKey;
|
|
8
|
+
}
|
|
9
|
+
if (model.startsWith('gpt-')) {
|
|
10
|
+
return providers.openaiBackend !== 'api' || !!providers.openaiApiKey;
|
|
11
|
+
}
|
|
12
|
+
if (model.startsWith('deepseek-')) {
|
|
13
|
+
return !!providers.deepseekApiKey;
|
|
14
|
+
}
|
|
15
|
+
// Unknown prefix (user-added extra models) — always include
|
|
16
|
+
return true;
|
|
17
|
+
});
|
|
18
|
+
}
|
|
4
19
|
/** Build the final model catalog from built-in + extra + allowlist filtering. */
|
|
5
20
|
export function buildModelCatalog(builtinModels, extraModelsRaw, allowedModelsRaw) {
|
|
6
21
|
const extraModels = extraModelsRaw
|
|
@@ -23,9 +38,20 @@ export function buildModelCatalog(builtinModels, extraModelsRaw, allowedModelsRa
|
|
|
23
38
|
? allAvailable.filter((m) => allowedModels.includes(m))
|
|
24
39
|
: allAvailable;
|
|
25
40
|
}
|
|
26
|
-
|
|
41
|
+
// Resolve backends early (needed for availability filtering)
|
|
42
|
+
const resolvedGeminiBackend = migrateBackendEnv(process.env.GEMINI_BACKEND, process.env.GEMINI_MODE, 'gemini-cli', 'GEMINI_MODE', 'GEMINI_BACKEND');
|
|
43
|
+
const resolvedOpenaiBackend = migrateBackendEnv(process.env.OPENAI_BACKEND, process.env.OPENAI_MODE, 'codex-cli', 'OPENAI_MODE', 'OPENAI_BACKEND');
|
|
44
|
+
// Build catalog, then filter to only available providers
|
|
45
|
+
const catalogModels = buildModelCatalog(ALL_MODELS, process.env.CONSULT_LLM_EXTRA_MODELS, process.env.CONSULT_LLM_ALLOWED_MODELS);
|
|
46
|
+
const enabledModels = filterByAvailability(catalogModels, {
|
|
47
|
+
geminiApiKey: process.env.GEMINI_API_KEY,
|
|
48
|
+
geminiBackend: resolvedGeminiBackend ?? 'api',
|
|
49
|
+
openaiApiKey: process.env.OPENAI_API_KEY,
|
|
50
|
+
openaiBackend: resolvedOpenaiBackend ?? 'api',
|
|
51
|
+
deepseekApiKey: process.env.DEEPSEEK_API_KEY,
|
|
52
|
+
});
|
|
27
53
|
if (enabledModels.length === 0) {
|
|
28
|
-
const msg = 'Invalid environment variables:\n
|
|
54
|
+
const msg = 'Invalid environment variables:\n No models available. Set API keys or configure CLI backends.';
|
|
29
55
|
logToFile(`FATAL ERROR:\n${msg}`);
|
|
30
56
|
console.error(`❌ ${msg}`);
|
|
31
57
|
process.exit(1);
|
|
@@ -62,8 +88,8 @@ const parsedConfig = Config.safeParse({
|
|
|
62
88
|
geminiApiKey: process.env.GEMINI_API_KEY,
|
|
63
89
|
deepseekApiKey: process.env.DEEPSEEK_API_KEY,
|
|
64
90
|
defaultModel: process.env.CONSULT_LLM_DEFAULT_MODEL,
|
|
65
|
-
geminiBackend:
|
|
66
|
-
openaiBackend:
|
|
91
|
+
geminiBackend: resolvedGeminiBackend,
|
|
92
|
+
openaiBackend: resolvedOpenaiBackend,
|
|
67
93
|
codexReasoningEffort: process.env.CODEX_REASONING_EFFORT,
|
|
68
94
|
systemPromptPath: process.env.CONSULT_LLM_SYSTEM_PROMPT_PATH,
|
|
69
95
|
});
|
package/dist/config.test.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
-
import { migrateBackendEnv, buildModelCatalog } from './config.js';
|
|
2
|
+
import { migrateBackendEnv, buildModelCatalog, filterByAvailability, } from './config.js';
|
|
3
3
|
import { ALL_MODELS } from './models.js';
|
|
4
4
|
vi.mock('./logger.js', () => ({ logToFile: vi.fn() }));
|
|
5
5
|
describe('migrateBackendEnv', () => {
|
|
@@ -19,6 +19,94 @@ describe('migrateBackendEnv', () => {
|
|
|
19
19
|
expect(migrateBackendEnv(undefined, 'cli', 'codex-cli', 'OPENAI_MODE', 'OPENAI_BACKEND')).toBe('codex-cli');
|
|
20
20
|
});
|
|
21
21
|
});
|
|
22
|
+
describe('filterByAvailability', () => {
|
|
23
|
+
const allModels = ['gemini-2.5-pro', 'gpt-5.2', 'deepseek-reasoner'];
|
|
24
|
+
it('includes gemini models when using gemini-cli backend', () => {
|
|
25
|
+
const result = filterByAvailability(allModels, {
|
|
26
|
+
geminiBackend: 'gemini-cli',
|
|
27
|
+
openaiBackend: 'api',
|
|
28
|
+
});
|
|
29
|
+
expect(result).toContain('gemini-2.5-pro');
|
|
30
|
+
expect(result).not.toContain('gpt-5.2');
|
|
31
|
+
});
|
|
32
|
+
it('includes gemini models when using cursor-cli backend', () => {
|
|
33
|
+
const result = filterByAvailability(allModels, {
|
|
34
|
+
geminiBackend: 'cursor-cli',
|
|
35
|
+
openaiBackend: 'api',
|
|
36
|
+
});
|
|
37
|
+
expect(result).toContain('gemini-2.5-pro');
|
|
38
|
+
});
|
|
39
|
+
it('includes gemini models when API key is set', () => {
|
|
40
|
+
const result = filterByAvailability(allModels, {
|
|
41
|
+
geminiApiKey: 'key',
|
|
42
|
+
geminiBackend: 'api',
|
|
43
|
+
openaiBackend: 'api',
|
|
44
|
+
});
|
|
45
|
+
expect(result).toContain('gemini-2.5-pro');
|
|
46
|
+
});
|
|
47
|
+
it('excludes gemini models when backend is api and no key', () => {
|
|
48
|
+
const result = filterByAvailability(allModels, {
|
|
49
|
+
geminiBackend: 'api',
|
|
50
|
+
openaiBackend: 'api',
|
|
51
|
+
});
|
|
52
|
+
expect(result).not.toContain('gemini-2.5-pro');
|
|
53
|
+
});
|
|
54
|
+
it('includes gpt models when using codex-cli backend', () => {
|
|
55
|
+
const result = filterByAvailability(allModels, {
|
|
56
|
+
geminiBackend: 'api',
|
|
57
|
+
openaiBackend: 'codex-cli',
|
|
58
|
+
});
|
|
59
|
+
expect(result).toContain('gpt-5.2');
|
|
60
|
+
expect(result).not.toContain('gemini-2.5-pro');
|
|
61
|
+
});
|
|
62
|
+
it('includes gpt models when using cursor-cli backend', () => {
|
|
63
|
+
const result = filterByAvailability(allModels, {
|
|
64
|
+
geminiBackend: 'api',
|
|
65
|
+
openaiBackend: 'cursor-cli',
|
|
66
|
+
});
|
|
67
|
+
expect(result).toContain('gpt-5.2');
|
|
68
|
+
});
|
|
69
|
+
it('includes gpt models when API key is set', () => {
|
|
70
|
+
const result = filterByAvailability(allModels, {
|
|
71
|
+
geminiBackend: 'api',
|
|
72
|
+
openaiApiKey: 'key',
|
|
73
|
+
openaiBackend: 'api',
|
|
74
|
+
});
|
|
75
|
+
expect(result).toContain('gpt-5.2');
|
|
76
|
+
});
|
|
77
|
+
it('excludes gpt models when backend is api and no key', () => {
|
|
78
|
+
const result = filterByAvailability(allModels, {
|
|
79
|
+
geminiBackend: 'api',
|
|
80
|
+
openaiBackend: 'api',
|
|
81
|
+
});
|
|
82
|
+
expect(result).not.toContain('gpt-5.2');
|
|
83
|
+
});
|
|
84
|
+
it('includes deepseek models only when API key is set', () => {
|
|
85
|
+
expect(filterByAvailability(allModels, {
|
|
86
|
+
geminiBackend: 'api',
|
|
87
|
+
openaiBackend: 'api',
|
|
88
|
+
deepseekApiKey: 'key',
|
|
89
|
+
})).toContain('deepseek-reasoner');
|
|
90
|
+
expect(filterByAvailability(allModels, {
|
|
91
|
+
geminiBackend: 'api',
|
|
92
|
+
openaiBackend: 'api',
|
|
93
|
+
})).not.toContain('deepseek-reasoner');
|
|
94
|
+
});
|
|
95
|
+
it('includes unknown-prefix models (user extras)', () => {
|
|
96
|
+
const result = filterByAvailability([...allModels, 'grok-3'], {
|
|
97
|
+
geminiBackend: 'api',
|
|
98
|
+
openaiBackend: 'api',
|
|
99
|
+
});
|
|
100
|
+
expect(result).toContain('grok-3');
|
|
101
|
+
});
|
|
102
|
+
it('returns empty array when no providers are available', () => {
|
|
103
|
+
const result = filterByAvailability(allModels, {
|
|
104
|
+
geminiBackend: 'api',
|
|
105
|
+
openaiBackend: 'api',
|
|
106
|
+
});
|
|
107
|
+
expect(result).toEqual([]);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
22
110
|
describe('buildModelCatalog', () => {
|
|
23
111
|
it('returns all built-in models when no env vars are set', () => {
|
|
24
112
|
const result = buildModelCatalog(ALL_MODELS);
|
package/dist/llm-cost.js
CHANGED
|
@@ -11,6 +11,10 @@ const MODEL_PRICING = {
|
|
|
11
11
|
inputCostPerMillion: 2.0,
|
|
12
12
|
outputCostPerMillion: 12.0,
|
|
13
13
|
},
|
|
14
|
+
'gemini-3.1-pro-preview': {
|
|
15
|
+
inputCostPerMillion: 2.0,
|
|
16
|
+
outputCostPerMillion: 12.0,
|
|
17
|
+
},
|
|
14
18
|
'deepseek-reasoner': {
|
|
15
19
|
inputCostPerMillion: 0.55,
|
|
16
20
|
outputCostPerMillion: 2.19,
|
package/dist/models.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const ALL_MODELS: readonly ["gemini-2.5-pro", "gemini-3-pro-preview", "deepseek-reasoner", "gpt-5.2", "gpt-5.3-codex", "gpt-5.2-codex"];
|
|
1
|
+
export declare const ALL_MODELS: readonly ["gemini-2.5-pro", "gemini-3-pro-preview", "gemini-3.1-pro-preview", "deepseek-reasoner", "gpt-5.2", "gpt-5.3-codex", "gpt-5.2-codex"];
|
package/dist/models.js
CHANGED
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const GIT_HASH = "
|
|
1
|
+
export declare const GIT_HASH = "1c9e0da";
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const GIT_HASH = "
|
|
1
|
+
export const GIT_HASH = "1c9e0da";
|