@anzchy/mcp-server-gemini 0.5.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.
- package/CHANGELOG.md +133 -0
- package/LICENSE +21 -0
- package/README.md +264 -0
- package/dist/enhanced-stdio-server.js +1226 -0
- package/dist/enhanced-stdio-server.js.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +67 -0
|
@@ -0,0 +1,1226 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { GoogleGenAI } from '@google/genai';
|
|
3
|
+
import { createInterface } from 'readline';
|
|
4
|
+
// Increase max buffer size for large images (10MB)
|
|
5
|
+
if (process.stdin.setEncoding) {
|
|
6
|
+
process.stdin.setEncoding('utf8');
|
|
7
|
+
}
|
|
8
|
+
// Available Gemini models as of February 2026
|
|
9
|
+
const GEMINI_MODELS = {
|
|
10
|
+
// Gemini 3 series - latest and most capable
|
|
11
|
+
'gemini-3-pro-preview': {
|
|
12
|
+
description: 'Most capable reasoning model, state-of-the-art multimodal and agentic',
|
|
13
|
+
features: ['thinking', 'function_calling', 'json_mode', 'grounding', 'system_instructions'],
|
|
14
|
+
contextWindow: 1048576, // 1M tokens
|
|
15
|
+
maxOutputTokens: 65536,
|
|
16
|
+
thinking: true,
|
|
17
|
+
thinkingLevels: ['low', 'high']
|
|
18
|
+
},
|
|
19
|
+
'gemini-3-flash-preview': {
|
|
20
|
+
description: 'Best balance of speed, scale, and frontier intelligence',
|
|
21
|
+
features: ['thinking', 'function_calling', 'json_mode', 'grounding', 'system_instructions'],
|
|
22
|
+
contextWindow: 1048576, // 1M tokens
|
|
23
|
+
maxOutputTokens: 65536,
|
|
24
|
+
thinking: true,
|
|
25
|
+
thinkingLevels: ['minimal', 'low', 'medium', 'high']
|
|
26
|
+
},
|
|
27
|
+
// Legacy models (2.5 series)
|
|
28
|
+
'gemini-2.5-pro': {
|
|
29
|
+
description: 'Previous generation thinking model, complex reasoning and coding',
|
|
30
|
+
features: ['thinking', 'function_calling', 'json_mode', 'grounding', 'system_instructions'],
|
|
31
|
+
contextWindow: 2000000,
|
|
32
|
+
thinking: true
|
|
33
|
+
},
|
|
34
|
+
'gemini-2.5-flash': {
|
|
35
|
+
description: 'Previous generation fast thinking model',
|
|
36
|
+
features: ['thinking', 'function_calling', 'json_mode', 'grounding', 'system_instructions'],
|
|
37
|
+
contextWindow: 1000000,
|
|
38
|
+
thinking: true
|
|
39
|
+
},
|
|
40
|
+
'gemini-2.5-flash-lite': {
|
|
41
|
+
description: 'Previous generation ultra-fast, cost-efficient thinking model',
|
|
42
|
+
features: ['thinking', 'function_calling', 'json_mode', 'system_instructions'],
|
|
43
|
+
contextWindow: 1000000,
|
|
44
|
+
thinking: true
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
// Configurable default model via GEMINI_DEFAULT_MODEL env var.
|
|
48
|
+
// Falls back to 'gemini-3-pro-preview' if unset or not a known model.
|
|
49
|
+
const DEFAULT_MODEL = (() => {
|
|
50
|
+
const envModel = process.env.GEMINI_DEFAULT_MODEL;
|
|
51
|
+
if (envModel) {
|
|
52
|
+
if (envModel in GEMINI_MODELS)
|
|
53
|
+
return envModel;
|
|
54
|
+
process.stderr.write(`[warn] GEMINI_DEFAULT_MODEL="${envModel}" is not a known model. Falling back to gemini-3-pro-preview.\n`);
|
|
55
|
+
}
|
|
56
|
+
return 'gemini-3-pro-preview';
|
|
57
|
+
})();
|
|
58
|
+
class EnhancedStdioMCPServer {
|
|
59
|
+
genAI;
|
|
60
|
+
conversations = new Map();
|
|
61
|
+
constructor(apiKey) {
|
|
62
|
+
this.genAI = new GoogleGenAI({ apiKey });
|
|
63
|
+
this.setupStdioInterface();
|
|
64
|
+
}
|
|
65
|
+
setupStdioInterface() {
|
|
66
|
+
const rl = createInterface({
|
|
67
|
+
input: process.stdin,
|
|
68
|
+
output: process.stdout,
|
|
69
|
+
terminal: false,
|
|
70
|
+
// Increase max line length for large image data
|
|
71
|
+
crlfDelay: Infinity
|
|
72
|
+
});
|
|
73
|
+
rl.on('line', (line) => {
|
|
74
|
+
if (line.trim()) {
|
|
75
|
+
try {
|
|
76
|
+
const request = JSON.parse(line);
|
|
77
|
+
this.handleRequest(request);
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
console.error('Failed to parse message:', error);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
process.stdin.on('error', (err) => {
|
|
85
|
+
console.error('stdin error:', err);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
async handleRequest(request) {
|
|
89
|
+
console.error('Handling request:', request.method);
|
|
90
|
+
try {
|
|
91
|
+
let response;
|
|
92
|
+
switch (request.method) {
|
|
93
|
+
case 'initialize':
|
|
94
|
+
response = {
|
|
95
|
+
jsonrpc: '2.0',
|
|
96
|
+
id: request.id,
|
|
97
|
+
result: {
|
|
98
|
+
protocolVersion: '2024-11-05',
|
|
99
|
+
serverInfo: {
|
|
100
|
+
name: 'mcp-server-gemini-enhanced',
|
|
101
|
+
version: '0.5.1'
|
|
102
|
+
},
|
|
103
|
+
capabilities: {
|
|
104
|
+
tools: {},
|
|
105
|
+
resources: {},
|
|
106
|
+
prompts: {}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
break;
|
|
111
|
+
case 'tools/list':
|
|
112
|
+
response = {
|
|
113
|
+
jsonrpc: '2.0',
|
|
114
|
+
id: request.id,
|
|
115
|
+
result: {
|
|
116
|
+
tools: this.getAvailableTools()
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
break;
|
|
120
|
+
case 'tools/call':
|
|
121
|
+
response = await this.handleToolCall(request);
|
|
122
|
+
break;
|
|
123
|
+
case 'resources/list':
|
|
124
|
+
response = {
|
|
125
|
+
jsonrpc: '2.0',
|
|
126
|
+
id: request.id,
|
|
127
|
+
result: {
|
|
128
|
+
resources: this.getAvailableResources()
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
break;
|
|
132
|
+
case 'resources/read':
|
|
133
|
+
response = await this.handleResourceRead(request);
|
|
134
|
+
break;
|
|
135
|
+
case 'prompts/list':
|
|
136
|
+
response = {
|
|
137
|
+
jsonrpc: '2.0',
|
|
138
|
+
id: request.id,
|
|
139
|
+
result: {
|
|
140
|
+
prompts: this.getAvailablePrompts()
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
break;
|
|
144
|
+
case 'ping':
|
|
145
|
+
response = {
|
|
146
|
+
jsonrpc: '2.0',
|
|
147
|
+
id: request.id,
|
|
148
|
+
result: {}
|
|
149
|
+
};
|
|
150
|
+
break;
|
|
151
|
+
default:
|
|
152
|
+
if (!('id' in request)) {
|
|
153
|
+
console.error(`Notification received: ${request.method}`);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
response = {
|
|
157
|
+
jsonrpc: '2.0',
|
|
158
|
+
id: request.id,
|
|
159
|
+
error: {
|
|
160
|
+
code: -32601,
|
|
161
|
+
message: 'Method not found'
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
this.sendResponse(response);
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
const errorResponse = {
|
|
169
|
+
jsonrpc: '2.0',
|
|
170
|
+
id: request.id,
|
|
171
|
+
error: {
|
|
172
|
+
code: -32603,
|
|
173
|
+
message: error instanceof Error ? error.message : 'Internal error'
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
this.sendResponse(errorResponse);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
getAvailableTools() {
|
|
180
|
+
return [
|
|
181
|
+
{
|
|
182
|
+
name: 'generate_text',
|
|
183
|
+
description: 'Generate text using Google Gemini with advanced features',
|
|
184
|
+
inputSchema: {
|
|
185
|
+
type: 'object',
|
|
186
|
+
properties: {
|
|
187
|
+
prompt: {
|
|
188
|
+
type: 'string',
|
|
189
|
+
description: 'The prompt to send to Gemini'
|
|
190
|
+
},
|
|
191
|
+
model: {
|
|
192
|
+
type: 'string',
|
|
193
|
+
description: 'Specific Gemini model to use',
|
|
194
|
+
enum: Object.keys(GEMINI_MODELS),
|
|
195
|
+
default: DEFAULT_MODEL
|
|
196
|
+
},
|
|
197
|
+
systemInstruction: {
|
|
198
|
+
type: 'string',
|
|
199
|
+
description: 'System instruction to guide model behavior'
|
|
200
|
+
},
|
|
201
|
+
temperature: {
|
|
202
|
+
type: 'number',
|
|
203
|
+
description: 'Temperature for generation (0-2)',
|
|
204
|
+
default: 1.0,
|
|
205
|
+
minimum: 0,
|
|
206
|
+
maximum: 2
|
|
207
|
+
},
|
|
208
|
+
maxTokens: {
|
|
209
|
+
type: 'number',
|
|
210
|
+
description: 'Maximum tokens to generate',
|
|
211
|
+
default: 2048
|
|
212
|
+
},
|
|
213
|
+
topK: {
|
|
214
|
+
type: 'number',
|
|
215
|
+
description: 'Top-k sampling parameter',
|
|
216
|
+
default: 40
|
|
217
|
+
},
|
|
218
|
+
topP: {
|
|
219
|
+
type: 'number',
|
|
220
|
+
description: 'Top-p (nucleus) sampling parameter',
|
|
221
|
+
default: 0.95
|
|
222
|
+
},
|
|
223
|
+
jsonMode: {
|
|
224
|
+
type: 'boolean',
|
|
225
|
+
description: 'Enable JSON mode for structured output',
|
|
226
|
+
default: false
|
|
227
|
+
},
|
|
228
|
+
jsonSchema: {
|
|
229
|
+
type: 'object',
|
|
230
|
+
description: 'JSON schema for structured output (when jsonMode is true)'
|
|
231
|
+
},
|
|
232
|
+
grounding: {
|
|
233
|
+
type: 'boolean',
|
|
234
|
+
description: 'Enable Google Search grounding for up-to-date information',
|
|
235
|
+
default: false
|
|
236
|
+
},
|
|
237
|
+
safetySettings: {
|
|
238
|
+
type: 'array',
|
|
239
|
+
description: 'Safety settings for content filtering',
|
|
240
|
+
items: {
|
|
241
|
+
type: 'object',
|
|
242
|
+
properties: {
|
|
243
|
+
category: {
|
|
244
|
+
type: 'string',
|
|
245
|
+
enum: ['HARM_CATEGORY_HARASSMENT', 'HARM_CATEGORY_HATE_SPEECH', 'HARM_CATEGORY_SEXUALLY_EXPLICIT', 'HARM_CATEGORY_DANGEROUS_CONTENT']
|
|
246
|
+
},
|
|
247
|
+
threshold: {
|
|
248
|
+
type: 'string',
|
|
249
|
+
enum: ['BLOCK_NONE', 'BLOCK_ONLY_HIGH', 'BLOCK_MEDIUM_AND_ABOVE', 'BLOCK_LOW_AND_ABOVE']
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
conversationId: {
|
|
255
|
+
type: 'string',
|
|
256
|
+
description: 'ID for maintaining conversation context'
|
|
257
|
+
},
|
|
258
|
+
thinkingLevel: {
|
|
259
|
+
type: 'string',
|
|
260
|
+
description: 'Thinking depth for Gemini 3 models. Pro supports low/high; Flash supports minimal/low/medium/high.',
|
|
261
|
+
enum: ['minimal', 'low', 'medium', 'high']
|
|
262
|
+
}
|
|
263
|
+
},
|
|
264
|
+
required: ['prompt']
|
|
265
|
+
}
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
name: 'analyze_image',
|
|
269
|
+
description: 'Analyze images using Gemini vision capabilities',
|
|
270
|
+
inputSchema: {
|
|
271
|
+
type: 'object',
|
|
272
|
+
properties: {
|
|
273
|
+
prompt: {
|
|
274
|
+
type: 'string',
|
|
275
|
+
description: 'Question or instruction about the image'
|
|
276
|
+
},
|
|
277
|
+
imageUrl: {
|
|
278
|
+
type: 'string',
|
|
279
|
+
description: 'URL of the image to analyze. Either imageUrl or imageBase64 must be provided.'
|
|
280
|
+
},
|
|
281
|
+
imageBase64: {
|
|
282
|
+
type: 'string',
|
|
283
|
+
description: 'Base64-encoded image data. Either imageUrl or imageBase64 must be provided.'
|
|
284
|
+
},
|
|
285
|
+
model: {
|
|
286
|
+
type: 'string',
|
|
287
|
+
description: 'Vision-capable Gemini model',
|
|
288
|
+
enum: ['gemini-3-pro-preview', 'gemini-3-flash-preview', 'gemini-2.5-pro', 'gemini-2.5-flash'],
|
|
289
|
+
default: DEFAULT_MODEL
|
|
290
|
+
},
|
|
291
|
+
mediaResolution: {
|
|
292
|
+
type: 'string',
|
|
293
|
+
description: 'Token allocation for image/video inputs. Higher resolution uses more tokens but provides better detail.',
|
|
294
|
+
enum: ['media_resolution_low', 'media_resolution_medium', 'media_resolution_high']
|
|
295
|
+
}
|
|
296
|
+
},
|
|
297
|
+
required: ['prompt']
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
name: 'count_tokens',
|
|
302
|
+
description: 'Count tokens for a given text with a specific model',
|
|
303
|
+
inputSchema: {
|
|
304
|
+
type: 'object',
|
|
305
|
+
properties: {
|
|
306
|
+
text: {
|
|
307
|
+
type: 'string',
|
|
308
|
+
description: 'Text to count tokens for'
|
|
309
|
+
},
|
|
310
|
+
model: {
|
|
311
|
+
type: 'string',
|
|
312
|
+
description: 'Model to use for token counting',
|
|
313
|
+
enum: Object.keys(GEMINI_MODELS),
|
|
314
|
+
default: DEFAULT_MODEL
|
|
315
|
+
}
|
|
316
|
+
},
|
|
317
|
+
required: ['text']
|
|
318
|
+
}
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
name: 'list_models',
|
|
322
|
+
description: 'List all available Gemini models and their capabilities',
|
|
323
|
+
inputSchema: {
|
|
324
|
+
type: 'object',
|
|
325
|
+
properties: {
|
|
326
|
+
filter: {
|
|
327
|
+
type: 'string',
|
|
328
|
+
description: 'Filter models by capability',
|
|
329
|
+
enum: ['all', 'thinking', 'vision', 'grounding', 'json_mode']
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
name: 'embed_text',
|
|
336
|
+
description: 'Generate embeddings for text using Gemini embedding models',
|
|
337
|
+
inputSchema: {
|
|
338
|
+
type: 'object',
|
|
339
|
+
properties: {
|
|
340
|
+
text: {
|
|
341
|
+
type: 'string',
|
|
342
|
+
description: 'Text to generate embeddings for'
|
|
343
|
+
},
|
|
344
|
+
model: {
|
|
345
|
+
type: 'string',
|
|
346
|
+
description: 'Embedding model to use',
|
|
347
|
+
enum: ['gemini-embedding-001'],
|
|
348
|
+
default: 'gemini-embedding-001'
|
|
349
|
+
}
|
|
350
|
+
},
|
|
351
|
+
required: ['text']
|
|
352
|
+
}
|
|
353
|
+
},
|
|
354
|
+
{
|
|
355
|
+
name: 'get_help',
|
|
356
|
+
description: 'Get help and usage information for the Gemini MCP server',
|
|
357
|
+
inputSchema: {
|
|
358
|
+
type: 'object',
|
|
359
|
+
properties: {
|
|
360
|
+
topic: {
|
|
361
|
+
type: 'string',
|
|
362
|
+
description: 'Help topic to get information about',
|
|
363
|
+
enum: ['overview', 'tools', 'models', 'parameters', 'examples', 'quick-start'],
|
|
364
|
+
default: 'overview'
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
];
|
|
370
|
+
}
|
|
371
|
+
getAvailableResources() {
|
|
372
|
+
return [
|
|
373
|
+
{
|
|
374
|
+
uri: 'gemini://models',
|
|
375
|
+
name: 'Available Gemini Models',
|
|
376
|
+
description: 'List of all available Gemini models and their capabilities',
|
|
377
|
+
mimeType: 'application/json'
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
uri: 'gemini://capabilities',
|
|
381
|
+
name: 'API Capabilities',
|
|
382
|
+
description: 'Detailed information about Gemini API capabilities',
|
|
383
|
+
mimeType: 'text/markdown'
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
uri: 'gemini://help/usage',
|
|
387
|
+
name: 'Usage Guide',
|
|
388
|
+
description: 'Complete guide on using all tools and features',
|
|
389
|
+
mimeType: 'text/markdown'
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
uri: 'gemini://help/parameters',
|
|
393
|
+
name: 'Parameters Reference',
|
|
394
|
+
description: 'Detailed documentation of all parameters',
|
|
395
|
+
mimeType: 'text/markdown'
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
uri: 'gemini://help/examples',
|
|
399
|
+
name: 'Examples',
|
|
400
|
+
description: 'Example usage patterns for common tasks',
|
|
401
|
+
mimeType: 'text/markdown'
|
|
402
|
+
}
|
|
403
|
+
];
|
|
404
|
+
}
|
|
405
|
+
getAvailablePrompts() {
|
|
406
|
+
return [
|
|
407
|
+
{
|
|
408
|
+
name: 'code_review',
|
|
409
|
+
description: 'Comprehensive code review with Gemini 3 Pro',
|
|
410
|
+
arguments: [
|
|
411
|
+
{
|
|
412
|
+
name: 'code',
|
|
413
|
+
description: 'Code to review',
|
|
414
|
+
required: true
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
name: 'language',
|
|
418
|
+
description: 'Programming language',
|
|
419
|
+
required: false
|
|
420
|
+
}
|
|
421
|
+
]
|
|
422
|
+
},
|
|
423
|
+
{
|
|
424
|
+
name: 'explain_with_thinking',
|
|
425
|
+
description: 'Deep explanation using Gemini 3 thinking capabilities',
|
|
426
|
+
arguments: [
|
|
427
|
+
{
|
|
428
|
+
name: 'topic',
|
|
429
|
+
description: 'Topic to explain',
|
|
430
|
+
required: true
|
|
431
|
+
},
|
|
432
|
+
{
|
|
433
|
+
name: 'level',
|
|
434
|
+
description: 'Explanation level (beginner/intermediate/expert)',
|
|
435
|
+
required: false
|
|
436
|
+
}
|
|
437
|
+
]
|
|
438
|
+
},
|
|
439
|
+
{
|
|
440
|
+
name: 'creative_writing',
|
|
441
|
+
description: 'Creative writing with style control',
|
|
442
|
+
arguments: [
|
|
443
|
+
{
|
|
444
|
+
name: 'prompt',
|
|
445
|
+
description: 'Writing prompt',
|
|
446
|
+
required: true
|
|
447
|
+
},
|
|
448
|
+
{
|
|
449
|
+
name: 'style',
|
|
450
|
+
description: 'Writing style',
|
|
451
|
+
required: false
|
|
452
|
+
},
|
|
453
|
+
{
|
|
454
|
+
name: 'length',
|
|
455
|
+
description: 'Desired length',
|
|
456
|
+
required: false
|
|
457
|
+
}
|
|
458
|
+
]
|
|
459
|
+
}
|
|
460
|
+
];
|
|
461
|
+
}
|
|
462
|
+
async handleToolCall(request) {
|
|
463
|
+
const { name, arguments: args } = request.params || {};
|
|
464
|
+
switch (name) {
|
|
465
|
+
case 'generate_text':
|
|
466
|
+
return await this.generateText(request.id, args);
|
|
467
|
+
case 'analyze_image':
|
|
468
|
+
return await this.analyzeImage(request.id, args);
|
|
469
|
+
case 'count_tokens':
|
|
470
|
+
return await this.countTokens(request.id, args);
|
|
471
|
+
case 'list_models':
|
|
472
|
+
return this.listModels(request.id, args);
|
|
473
|
+
case 'embed_text':
|
|
474
|
+
return await this.embedText(request.id, args);
|
|
475
|
+
case 'get_help':
|
|
476
|
+
return this.getHelp(request.id, args);
|
|
477
|
+
default:
|
|
478
|
+
return {
|
|
479
|
+
jsonrpc: '2.0',
|
|
480
|
+
id: request.id,
|
|
481
|
+
error: {
|
|
482
|
+
code: -32602,
|
|
483
|
+
message: `Unknown tool: ${name}`
|
|
484
|
+
}
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
async generateText(id, args) {
|
|
489
|
+
try {
|
|
490
|
+
const model = args.model || DEFAULT_MODEL;
|
|
491
|
+
const modelInfo = GEMINI_MODELS[model];
|
|
492
|
+
if (!modelInfo) {
|
|
493
|
+
throw new Error(`Unknown model: ${model}`);
|
|
494
|
+
}
|
|
495
|
+
// Build contents
|
|
496
|
+
let contents = [{
|
|
497
|
+
parts: [{ text: args.prompt }],
|
|
498
|
+
role: 'user'
|
|
499
|
+
}];
|
|
500
|
+
// Prepend conversation history if continuing a conversation
|
|
501
|
+
if (args.conversationId) {
|
|
502
|
+
const history = this.conversations.get(args.conversationId) || [];
|
|
503
|
+
if (history.length > 0) {
|
|
504
|
+
contents = [...history, ...contents];
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
// Build SDK config (flat structure per @google/genai SDK pattern)
|
|
508
|
+
const config = {
|
|
509
|
+
temperature: args.temperature ?? 1.0,
|
|
510
|
+
maxOutputTokens: args.maxTokens || 2048,
|
|
511
|
+
topK: args.topK || 40,
|
|
512
|
+
topP: args.topP || 0.95,
|
|
513
|
+
};
|
|
514
|
+
if (args.systemInstruction) {
|
|
515
|
+
config.systemInstruction = args.systemInstruction;
|
|
516
|
+
}
|
|
517
|
+
if (args.jsonMode) {
|
|
518
|
+
config.responseMimeType = 'application/json';
|
|
519
|
+
if (args.jsonSchema) {
|
|
520
|
+
config.responseSchema = args.jsonSchema;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
if (args.safetySettings) {
|
|
524
|
+
config.safetySettings = args.safetySettings;
|
|
525
|
+
}
|
|
526
|
+
if (args.grounding && modelInfo.features.includes('grounding')) {
|
|
527
|
+
config.tools = [{ googleSearch: {} }];
|
|
528
|
+
}
|
|
529
|
+
// Thinking config for Gemini 3 models (SDK expects uppercase level)
|
|
530
|
+
if (args.thinkingLevel && modelInfo.thinking) {
|
|
531
|
+
config.thinkingConfig = {
|
|
532
|
+
thinkingLevel: args.thinkingLevel.toUpperCase()
|
|
533
|
+
};
|
|
534
|
+
}
|
|
535
|
+
// Call the API using SDK config pattern
|
|
536
|
+
const result = await this.genAI.models.generateContent({
|
|
537
|
+
model,
|
|
538
|
+
contents,
|
|
539
|
+
config,
|
|
540
|
+
});
|
|
541
|
+
const text = result.text || '';
|
|
542
|
+
// Update conversation history with only the new messages
|
|
543
|
+
if (args.conversationId) {
|
|
544
|
+
const history = this.conversations.get(args.conversationId) || [];
|
|
545
|
+
history.push({
|
|
546
|
+
parts: [{ text: args.prompt }],
|
|
547
|
+
role: 'user'
|
|
548
|
+
});
|
|
549
|
+
history.push({
|
|
550
|
+
parts: [{ text: text }],
|
|
551
|
+
role: 'model'
|
|
552
|
+
});
|
|
553
|
+
this.conversations.set(args.conversationId, history);
|
|
554
|
+
}
|
|
555
|
+
return {
|
|
556
|
+
jsonrpc: '2.0',
|
|
557
|
+
id,
|
|
558
|
+
result: {
|
|
559
|
+
content: [{
|
|
560
|
+
type: 'text',
|
|
561
|
+
text: text
|
|
562
|
+
}],
|
|
563
|
+
metadata: {
|
|
564
|
+
model,
|
|
565
|
+
tokensUsed: result.usageMetadata?.totalTokenCount,
|
|
566
|
+
candidatesCount: result.candidates?.length || 1,
|
|
567
|
+
finishReason: result.candidates?.[0]?.finishReason
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
catch (error) {
|
|
573
|
+
console.error('Error in generateText:', error);
|
|
574
|
+
return {
|
|
575
|
+
jsonrpc: '2.0',
|
|
576
|
+
id,
|
|
577
|
+
result: {
|
|
578
|
+
content: [{
|
|
579
|
+
type: 'text',
|
|
580
|
+
text: `Error: ${error instanceof Error ? error.message : 'Internal error'}`
|
|
581
|
+
}],
|
|
582
|
+
isError: true
|
|
583
|
+
}
|
|
584
|
+
};
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
async analyzeImage(id, args) {
|
|
588
|
+
try {
|
|
589
|
+
const model = args.model || DEFAULT_MODEL;
|
|
590
|
+
// Validate inputs
|
|
591
|
+
if (!args.imageUrl && !args.imageBase64) {
|
|
592
|
+
throw new Error('Either imageUrl or imageBase64 must be provided');
|
|
593
|
+
}
|
|
594
|
+
// Prepare image part
|
|
595
|
+
let imagePart;
|
|
596
|
+
if (args.imageUrl) {
|
|
597
|
+
// For URL, we'd need to fetch and convert to base64
|
|
598
|
+
// For now, we'll just pass the URL as instruction
|
|
599
|
+
imagePart = {
|
|
600
|
+
text: `[Image URL: ${args.imageUrl}]`
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
else if (args.imageBase64) {
|
|
604
|
+
// Log base64 data size for debugging
|
|
605
|
+
console.error(`Image base64 length: ${args.imageBase64.length}`);
|
|
606
|
+
// Extract MIME type and data
|
|
607
|
+
const matches = args.imageBase64.match(/^data:(.+);base64,(.+)$/);
|
|
608
|
+
if (matches) {
|
|
609
|
+
console.error(`MIME type: ${matches[1]}, Data length: ${matches[2].length}`);
|
|
610
|
+
imagePart = {
|
|
611
|
+
inlineData: {
|
|
612
|
+
mimeType: matches[1],
|
|
613
|
+
data: matches[2]
|
|
614
|
+
}
|
|
615
|
+
};
|
|
616
|
+
}
|
|
617
|
+
else {
|
|
618
|
+
// If no data URI format, assume raw base64
|
|
619
|
+
console.error('Raw base64 data detected');
|
|
620
|
+
imagePart = {
|
|
621
|
+
inlineData: {
|
|
622
|
+
mimeType: 'image/jpeg',
|
|
623
|
+
data: args.imageBase64
|
|
624
|
+
}
|
|
625
|
+
};
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
// Build SDK config
|
|
629
|
+
const config = {};
|
|
630
|
+
if (args.mediaResolution) {
|
|
631
|
+
config.mediaResolution = args.mediaResolution;
|
|
632
|
+
}
|
|
633
|
+
const result = await this.genAI.models.generateContent({
|
|
634
|
+
model,
|
|
635
|
+
contents: [{
|
|
636
|
+
parts: [
|
|
637
|
+
{ text: args.prompt },
|
|
638
|
+
imagePart
|
|
639
|
+
],
|
|
640
|
+
role: 'user'
|
|
641
|
+
}],
|
|
642
|
+
config: Object.keys(config).length > 0 ? config : undefined,
|
|
643
|
+
});
|
|
644
|
+
const text = result.text || '';
|
|
645
|
+
return {
|
|
646
|
+
jsonrpc: '2.0',
|
|
647
|
+
id,
|
|
648
|
+
result: {
|
|
649
|
+
content: [{
|
|
650
|
+
type: 'text',
|
|
651
|
+
text: text
|
|
652
|
+
}]
|
|
653
|
+
}
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
catch (error) {
|
|
657
|
+
console.error('Error in analyzeImage:', error);
|
|
658
|
+
return {
|
|
659
|
+
jsonrpc: '2.0',
|
|
660
|
+
id,
|
|
661
|
+
result: {
|
|
662
|
+
content: [{
|
|
663
|
+
type: 'text',
|
|
664
|
+
text: `Image analysis failed: ${error instanceof Error ? error.message : 'Unknown error'}`
|
|
665
|
+
}],
|
|
666
|
+
isError: true
|
|
667
|
+
}
|
|
668
|
+
};
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
async countTokens(id, args) {
|
|
672
|
+
try {
|
|
673
|
+
const model = args.model || DEFAULT_MODEL;
|
|
674
|
+
const result = await this.genAI.models.countTokens({
|
|
675
|
+
model,
|
|
676
|
+
contents: [{
|
|
677
|
+
parts: [{
|
|
678
|
+
text: args.text
|
|
679
|
+
}],
|
|
680
|
+
role: 'user'
|
|
681
|
+
}]
|
|
682
|
+
});
|
|
683
|
+
return {
|
|
684
|
+
jsonrpc: '2.0',
|
|
685
|
+
id,
|
|
686
|
+
result: {
|
|
687
|
+
content: [{
|
|
688
|
+
type: 'text',
|
|
689
|
+
text: `Token count: ${result.totalTokens}`
|
|
690
|
+
}],
|
|
691
|
+
metadata: {
|
|
692
|
+
tokenCount: result.totalTokens,
|
|
693
|
+
model
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
};
|
|
697
|
+
}
|
|
698
|
+
catch (error) {
|
|
699
|
+
console.error('Error in countTokens:', error);
|
|
700
|
+
return {
|
|
701
|
+
jsonrpc: '2.0',
|
|
702
|
+
id,
|
|
703
|
+
result: {
|
|
704
|
+
content: [{
|
|
705
|
+
type: 'text',
|
|
706
|
+
text: `Token counting failed: ${error instanceof Error ? error.message : 'Internal error'}`
|
|
707
|
+
}],
|
|
708
|
+
isError: true
|
|
709
|
+
}
|
|
710
|
+
};
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
listModels(id, args) {
|
|
714
|
+
const filter = args?.filter || 'all';
|
|
715
|
+
let models = Object.entries(GEMINI_MODELS);
|
|
716
|
+
if (filter !== 'all') {
|
|
717
|
+
models = models.filter(([_, info]) => {
|
|
718
|
+
switch (filter) {
|
|
719
|
+
case 'thinking':
|
|
720
|
+
return 'thinking' in info && info.thinking === true;
|
|
721
|
+
case 'vision':
|
|
722
|
+
return info.features.includes('function_calling'); // All current models support vision
|
|
723
|
+
case 'grounding':
|
|
724
|
+
return info.features.includes('grounding');
|
|
725
|
+
case 'json_mode':
|
|
726
|
+
return info.features.includes('json_mode');
|
|
727
|
+
default:
|
|
728
|
+
return true;
|
|
729
|
+
}
|
|
730
|
+
});
|
|
731
|
+
}
|
|
732
|
+
const modelList = models.map(([name, info]) => ({
|
|
733
|
+
name,
|
|
734
|
+
...info
|
|
735
|
+
}));
|
|
736
|
+
return {
|
|
737
|
+
jsonrpc: '2.0',
|
|
738
|
+
id,
|
|
739
|
+
result: {
|
|
740
|
+
content: [{
|
|
741
|
+
type: 'text',
|
|
742
|
+
text: JSON.stringify(modelList, null, 2)
|
|
743
|
+
}],
|
|
744
|
+
metadata: {
|
|
745
|
+
count: modelList.length,
|
|
746
|
+
filter
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
};
|
|
750
|
+
}
|
|
751
|
+
async embedText(id, args) {
|
|
752
|
+
try {
|
|
753
|
+
const model = args.model || 'gemini-embedding-001';
|
|
754
|
+
const result = await this.genAI.models.embedContent({
|
|
755
|
+
model,
|
|
756
|
+
contents: args.text
|
|
757
|
+
});
|
|
758
|
+
return {
|
|
759
|
+
jsonrpc: '2.0',
|
|
760
|
+
id,
|
|
761
|
+
result: {
|
|
762
|
+
content: [{
|
|
763
|
+
type: 'text',
|
|
764
|
+
text: JSON.stringify({
|
|
765
|
+
embedding: result.embeddings?.[0]?.values || [],
|
|
766
|
+
model
|
|
767
|
+
})
|
|
768
|
+
}],
|
|
769
|
+
metadata: {
|
|
770
|
+
model,
|
|
771
|
+
dimensions: result.embeddings?.[0]?.values?.length || 0
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
};
|
|
775
|
+
}
|
|
776
|
+
catch (error) {
|
|
777
|
+
console.error('Error in embedText:', error);
|
|
778
|
+
return {
|
|
779
|
+
jsonrpc: '2.0',
|
|
780
|
+
id,
|
|
781
|
+
result: {
|
|
782
|
+
content: [{
|
|
783
|
+
type: 'text',
|
|
784
|
+
text: `Embedding failed: ${error instanceof Error ? error.message : 'Internal error'}`
|
|
785
|
+
}],
|
|
786
|
+
isError: true
|
|
787
|
+
}
|
|
788
|
+
};
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
async handleResourceRead(request) {
|
|
792
|
+
const uri = request.params?.uri;
|
|
793
|
+
if (!uri) {
|
|
794
|
+
return {
|
|
795
|
+
jsonrpc: '2.0',
|
|
796
|
+
id: request.id,
|
|
797
|
+
error: {
|
|
798
|
+
code: -32602,
|
|
799
|
+
message: 'Missing required parameter: uri'
|
|
800
|
+
}
|
|
801
|
+
};
|
|
802
|
+
}
|
|
803
|
+
let content = '';
|
|
804
|
+
let mimeType = 'text/plain';
|
|
805
|
+
switch (uri) {
|
|
806
|
+
case 'gemini://models':
|
|
807
|
+
content = JSON.stringify(GEMINI_MODELS, null, 2);
|
|
808
|
+
mimeType = 'application/json';
|
|
809
|
+
break;
|
|
810
|
+
case 'gemini://capabilities':
|
|
811
|
+
content = `# Gemini API Capabilities
|
|
812
|
+
|
|
813
|
+
## Text Generation
|
|
814
|
+
- All models support advanced text generation
|
|
815
|
+
- System instructions for behavior control
|
|
816
|
+
- Temperature, topK, topP for output control
|
|
817
|
+
- Default temperature: 1.0 (recommended for Gemini 3)
|
|
818
|
+
|
|
819
|
+
## Thinking Models (3.x Series)
|
|
820
|
+
- Step-by-step reasoning before responding
|
|
821
|
+
- Configurable thinking depth via thinkingLevel parameter
|
|
822
|
+
- Gemini 3 Pro: low, high
|
|
823
|
+
- Gemini 3 Flash: minimal, low, medium, high
|
|
824
|
+
- Better accuracy for complex problems
|
|
825
|
+
- Ideal for coding, analysis, and problem-solving
|
|
826
|
+
|
|
827
|
+
## Media Resolution
|
|
828
|
+
- Control token allocation for image/video inputs
|
|
829
|
+
- Options: media_resolution_low, media_resolution_medium (default), media_resolution_high
|
|
830
|
+
- Higher resolution provides better detail at the cost of more tokens
|
|
831
|
+
|
|
832
|
+
## JSON Mode
|
|
833
|
+
- Structured output with schema validation
|
|
834
|
+
- Available on all models
|
|
835
|
+
- Ensures consistent response format
|
|
836
|
+
|
|
837
|
+
## Google Search Grounding
|
|
838
|
+
- Real-time web search integration
|
|
839
|
+
- Available on select models
|
|
840
|
+
- Perfect for current events and facts
|
|
841
|
+
|
|
842
|
+
## Vision Capabilities
|
|
843
|
+
- Image analysis and understanding
|
|
844
|
+
- Available on most models
|
|
845
|
+
- Supports URLs and base64 images
|
|
846
|
+
|
|
847
|
+
## Embeddings
|
|
848
|
+
- Semantic text embeddings
|
|
849
|
+
- Multiple models available
|
|
850
|
+
- Multilingual support
|
|
851
|
+
|
|
852
|
+
## Safety Settings
|
|
853
|
+
- Granular content filtering
|
|
854
|
+
- Customizable thresholds
|
|
855
|
+
- Per-category control
|
|
856
|
+
|
|
857
|
+
## Conversation Memory
|
|
858
|
+
- Context retention across messages
|
|
859
|
+
- Session-based conversations
|
|
860
|
+
- Ideal for multi-turn interactions`;
|
|
861
|
+
mimeType = 'text/markdown';
|
|
862
|
+
break;
|
|
863
|
+
case 'gemini://help/usage':
|
|
864
|
+
content = this.getHelpContent('overview') + '\n\n' + this.getHelpContent('tools');
|
|
865
|
+
mimeType = 'text/markdown';
|
|
866
|
+
break;
|
|
867
|
+
case 'gemini://help/parameters':
|
|
868
|
+
content = this.getHelpContent('parameters');
|
|
869
|
+
mimeType = 'text/markdown';
|
|
870
|
+
break;
|
|
871
|
+
case 'gemini://help/examples':
|
|
872
|
+
content = this.getHelpContent('examples');
|
|
873
|
+
mimeType = 'text/markdown';
|
|
874
|
+
break;
|
|
875
|
+
default:
|
|
876
|
+
return {
|
|
877
|
+
jsonrpc: '2.0',
|
|
878
|
+
id: request.id,
|
|
879
|
+
error: {
|
|
880
|
+
code: -32602,
|
|
881
|
+
message: `Unknown resource: ${uri}`
|
|
882
|
+
}
|
|
883
|
+
};
|
|
884
|
+
}
|
|
885
|
+
return {
|
|
886
|
+
jsonrpc: '2.0',
|
|
887
|
+
id: request.id,
|
|
888
|
+
result: {
|
|
889
|
+
contents: [{
|
|
890
|
+
uri,
|
|
891
|
+
mimeType,
|
|
892
|
+
text: content
|
|
893
|
+
}]
|
|
894
|
+
}
|
|
895
|
+
};
|
|
896
|
+
}
|
|
897
|
+
getHelpContent(topic) {
|
|
898
|
+
// Extract help content generation to a separate method
|
|
899
|
+
switch (topic) {
|
|
900
|
+
case 'overview':
|
|
901
|
+
return `# Gemini MCP Server Help
|
|
902
|
+
|
|
903
|
+
Welcome to the Gemini MCP Server v0.5.1! This server provides access to Google's Gemini AI models through Claude Desktop.
|
|
904
|
+
|
|
905
|
+
## Available Tools
|
|
906
|
+
1. **generate_text** - Generate text with advanced features
|
|
907
|
+
2. **analyze_image** - Analyze images using vision models
|
|
908
|
+
3. **count_tokens** - Count tokens for cost estimation
|
|
909
|
+
4. **list_models** - List all available models
|
|
910
|
+
5. **embed_text** - Generate text embeddings
|
|
911
|
+
6. **get_help** - Get help on using this server
|
|
912
|
+
|
|
913
|
+
## Quick Start
|
|
914
|
+
- "Use Gemini to explain [topic]"
|
|
915
|
+
- "Analyze this image with Gemini"
|
|
916
|
+
- "List all Gemini models"
|
|
917
|
+
- "Get help on parameters"
|
|
918
|
+
|
|
919
|
+
## Key Features
|
|
920
|
+
- Latest Gemini 3 models with configurable thinking depth
|
|
921
|
+
- Thinking level control (minimal/low/medium/high)
|
|
922
|
+
- Media resolution control for vision tasks
|
|
923
|
+
- JSON mode for structured output
|
|
924
|
+
- Google Search grounding for current information
|
|
925
|
+
- System instructions for behavior control
|
|
926
|
+
- Conversation memory for context
|
|
927
|
+
- Safety settings customization
|
|
928
|
+
|
|
929
|
+
Use "get help on tools" for detailed tool information.`;
|
|
930
|
+
case 'tools':
|
|
931
|
+
return `# Available Tools
|
|
932
|
+
|
|
933
|
+
## 1. generate_text
|
|
934
|
+
Generate text using Gemini models with advanced features.
|
|
935
|
+
|
|
936
|
+
**Parameters:**
|
|
937
|
+
- prompt (required): Your text prompt
|
|
938
|
+
- model: Choose from gemini-3-pro-preview, gemini-3-flash-preview, etc.
|
|
939
|
+
- temperature: 0-2 (default 1.0)
|
|
940
|
+
- maxTokens: Max output tokens (default 2048)
|
|
941
|
+
- systemInstruction: Guide model behavior
|
|
942
|
+
- jsonMode: Enable JSON output
|
|
943
|
+
- grounding: Enable Google Search
|
|
944
|
+
- conversationId: Maintain conversation context
|
|
945
|
+
- thinkingLevel: Thinking depth (minimal/low/medium/high) for Gemini 3 models
|
|
946
|
+
|
|
947
|
+
**Example:** "Use Gemini 3 Pro to explain quantum computing"
|
|
948
|
+
|
|
949
|
+
## 2. analyze_image
|
|
950
|
+
Analyze images using vision-capable models.
|
|
951
|
+
|
|
952
|
+
**Parameters:**
|
|
953
|
+
- prompt (required): Question about the image
|
|
954
|
+
- imageUrl OR imageBase64 (required): Image source
|
|
955
|
+
- model: Vision-capable model (default gemini-3-pro-preview)
|
|
956
|
+
- mediaResolution: Token allocation for images (low/medium/high)
|
|
957
|
+
|
|
958
|
+
**Example:** "Analyze this architecture diagram"
|
|
959
|
+
|
|
960
|
+
## 3. count_tokens
|
|
961
|
+
Count tokens for text with a specific model.
|
|
962
|
+
|
|
963
|
+
**Parameters:**
|
|
964
|
+
- text (required): Text to count
|
|
965
|
+
- model: Model for counting (default gemini-3-pro-preview)
|
|
966
|
+
|
|
967
|
+
**Example:** "Count tokens for this paragraph"
|
|
968
|
+
|
|
969
|
+
## 4. list_models
|
|
970
|
+
List available models with optional filtering.
|
|
971
|
+
|
|
972
|
+
**Parameters:**
|
|
973
|
+
- filter: all, thinking, vision, grounding, json_mode
|
|
974
|
+
|
|
975
|
+
**Example:** "List models with thinking capability"
|
|
976
|
+
|
|
977
|
+
## 5. embed_text
|
|
978
|
+
Generate embeddings for semantic search.
|
|
979
|
+
|
|
980
|
+
**Parameters:**
|
|
981
|
+
- text (required): Text to embed
|
|
982
|
+
- model: gemini-embedding-001 (default)
|
|
983
|
+
|
|
984
|
+
**Example:** "Generate embeddings for similarity search"
|
|
985
|
+
|
|
986
|
+
## 6. get_help
|
|
987
|
+
Get help on using this server.
|
|
988
|
+
|
|
989
|
+
**Parameters:**
|
|
990
|
+
- topic: overview, tools, models, parameters, examples, quick-start
|
|
991
|
+
|
|
992
|
+
**Example:** "Get help on parameters"`;
|
|
993
|
+
case 'parameters':
|
|
994
|
+
return `# Parameter Reference
|
|
995
|
+
|
|
996
|
+
## generate_text Parameters
|
|
997
|
+
|
|
998
|
+
**Required:**
|
|
999
|
+
- prompt (string): Your text prompt
|
|
1000
|
+
|
|
1001
|
+
**Optional:**
|
|
1002
|
+
- model (string): Model to use (default: gemini-3-pro-preview)
|
|
1003
|
+
- systemInstruction (string): System prompt for behavior
|
|
1004
|
+
- temperature (0-2): Creativity level (default: 1.0)
|
|
1005
|
+
- maxTokens (number): Max output tokens (default: 2048)
|
|
1006
|
+
- topK (number): Top-k sampling (default: 40)
|
|
1007
|
+
- topP (number): Nucleus sampling (default: 0.95)
|
|
1008
|
+
- jsonMode (boolean): Enable JSON output
|
|
1009
|
+
- jsonSchema (object): JSON schema for validation
|
|
1010
|
+
- grounding (boolean): Enable Google Search
|
|
1011
|
+
- conversationId (string): Conversation identifier
|
|
1012
|
+
- safetySettings (array): Content filtering settings
|
|
1013
|
+
- thinkingLevel (string): Thinking depth for Gemini 3 models (minimal/low/medium/high)
|
|
1014
|
+
|
|
1015
|
+
## analyze_image Parameters
|
|
1016
|
+
|
|
1017
|
+
**Required:**
|
|
1018
|
+
- prompt (string): Question about the image
|
|
1019
|
+
- imageUrl OR imageBase64: Image source
|
|
1020
|
+
|
|
1021
|
+
**Optional:**
|
|
1022
|
+
- model (string): Vision model (default: gemini-3-pro-preview)
|
|
1023
|
+
- mediaResolution (string): Token allocation for images
|
|
1024
|
+
- media_resolution_low: Fewer tokens, faster processing
|
|
1025
|
+
- media_resolution_medium: Balanced (default)
|
|
1026
|
+
- media_resolution_high: More tokens, better detail
|
|
1027
|
+
|
|
1028
|
+
## Thinking Level Guide
|
|
1029
|
+
- minimal: Fastest, minimal reasoning (Flash only)
|
|
1030
|
+
- low: Light reasoning
|
|
1031
|
+
- medium: Moderate reasoning (Flash only)
|
|
1032
|
+
- high: Deep reasoning (default for thinking models)
|
|
1033
|
+
|
|
1034
|
+
## Temperature Guide
|
|
1035
|
+
- 0.1-0.3: Precise, factual
|
|
1036
|
+
- 0.7-1.0: Balanced (default 1.0, recommended for Gemini 3)
|
|
1037
|
+
- 1.0-1.5: Creative
|
|
1038
|
+
- 1.5-2.0: Very creative
|
|
1039
|
+
|
|
1040
|
+
## JSON Mode Example
|
|
1041
|
+
Enable jsonMode and provide jsonSchema:
|
|
1042
|
+
{
|
|
1043
|
+
"type": "object",
|
|
1044
|
+
"properties": {
|
|
1045
|
+
"sentiment": {"type": "string"},
|
|
1046
|
+
"score": {"type": "number"}
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
## Safety Settings
|
|
1051
|
+
Categories: HARASSMENT, HATE_SPEECH, SEXUALLY_EXPLICIT, DANGEROUS_CONTENT
|
|
1052
|
+
Thresholds: BLOCK_NONE, BLOCK_ONLY_HIGH, BLOCK_MEDIUM_AND_ABOVE, BLOCK_LOW_AND_ABOVE`;
|
|
1053
|
+
case 'examples':
|
|
1054
|
+
return `# Usage Examples
|
|
1055
|
+
|
|
1056
|
+
## Basic Text Generation
|
|
1057
|
+
"Use Gemini to explain machine learning"
|
|
1058
|
+
|
|
1059
|
+
## With Specific Model
|
|
1060
|
+
"Use Gemini 3 Pro to write a Python sorting function"
|
|
1061
|
+
|
|
1062
|
+
## With Thinking Level
|
|
1063
|
+
"Use Gemini 3 Pro with thinkingLevel high to solve this math problem"
|
|
1064
|
+
|
|
1065
|
+
## With Temperature
|
|
1066
|
+
"Use Gemini with temperature 1.5 to write a creative story"
|
|
1067
|
+
|
|
1068
|
+
## JSON Mode
|
|
1069
|
+
"Use Gemini in JSON mode to analyze sentiment and return {sentiment, confidence, keywords}"
|
|
1070
|
+
|
|
1071
|
+
## With Grounding
|
|
1072
|
+
"Use Gemini with grounding to research latest AI developments"
|
|
1073
|
+
|
|
1074
|
+
## System Instructions
|
|
1075
|
+
"Use Gemini as a Python tutor to explain decorators"
|
|
1076
|
+
|
|
1077
|
+
## Conversation Context
|
|
1078
|
+
"Start conversation 'chat-001' about web development"
|
|
1079
|
+
"Continue chat-001 and ask about React hooks"
|
|
1080
|
+
|
|
1081
|
+
## Image Analysis
|
|
1082
|
+
"Analyze this screenshot and describe the UI elements"
|
|
1083
|
+
|
|
1084
|
+
## Image Analysis with High Resolution
|
|
1085
|
+
"Analyze this diagram with mediaResolution high for maximum detail"
|
|
1086
|
+
|
|
1087
|
+
## Token Counting
|
|
1088
|
+
"Count tokens for this document using gemini-3-pro-preview"
|
|
1089
|
+
|
|
1090
|
+
## Complex Example
|
|
1091
|
+
"Use Gemini 3 Pro to review this code with:
|
|
1092
|
+
- System instruction: 'You are a security expert'
|
|
1093
|
+
- Temperature: 0.3
|
|
1094
|
+
- thinkingLevel: high
|
|
1095
|
+
- JSON mode with schema for findings
|
|
1096
|
+
- Grounding for latest security practices"`;
|
|
1097
|
+
default:
|
|
1098
|
+
return 'Unknown help topic.';
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
getHelp(id, args) {
|
|
1102
|
+
const topic = args?.topic || 'overview';
|
|
1103
|
+
let helpContent = '';
|
|
1104
|
+
switch (topic) {
|
|
1105
|
+
case 'overview':
|
|
1106
|
+
helpContent = this.getHelpContent('overview');
|
|
1107
|
+
break;
|
|
1108
|
+
case 'tools':
|
|
1109
|
+
helpContent = this.getHelpContent('tools');
|
|
1110
|
+
break;
|
|
1111
|
+
case 'models':
|
|
1112
|
+
helpContent = `# Available Gemini Models
|
|
1113
|
+
|
|
1114
|
+
## Gemini 3 Series (Latest)
|
|
1115
|
+
**gemini-3-pro-preview** ⭐ Recommended
|
|
1116
|
+
- Most capable reasoning model, state-of-the-art multimodal and agentic
|
|
1117
|
+
- 1M token context, 64K max output
|
|
1118
|
+
- Thinking levels: low, high
|
|
1119
|
+
- Features: thinking, JSON mode, grounding, system instructions
|
|
1120
|
+
|
|
1121
|
+
**gemini-3-flash-preview**
|
|
1122
|
+
- Best balance of speed, scale, and frontier intelligence
|
|
1123
|
+
- 1M token context, 64K max output
|
|
1124
|
+
- Thinking levels: minimal, low, medium, high
|
|
1125
|
+
- Features: thinking, JSON mode, grounding, system instructions
|
|
1126
|
+
|
|
1127
|
+
## Legacy Models (2.5 Series)
|
|
1128
|
+
**gemini-2.5-pro**
|
|
1129
|
+
- Previous generation thinking model
|
|
1130
|
+
- 2M token context window
|
|
1131
|
+
- Features: thinking, JSON mode, grounding, system instructions
|
|
1132
|
+
|
|
1133
|
+
**gemini-2.5-flash**
|
|
1134
|
+
- Previous generation fast thinking model
|
|
1135
|
+
- 1M token context window
|
|
1136
|
+
- Features: thinking, JSON mode, grounding, system instructions
|
|
1137
|
+
|
|
1138
|
+
**gemini-2.5-flash-lite**
|
|
1139
|
+
- Previous generation ultra-fast model
|
|
1140
|
+
- 1M token context window
|
|
1141
|
+
- Features: thinking, JSON mode, system instructions
|
|
1142
|
+
|
|
1143
|
+
## Model Selection Guide
|
|
1144
|
+
- Complex reasoning: gemini-3-pro-preview
|
|
1145
|
+
- General use: gemini-3-pro-preview
|
|
1146
|
+
- Fast responses: gemini-3-flash-preview
|
|
1147
|
+
- Cost-sensitive: gemini-2.5-flash-lite
|
|
1148
|
+
- Maximum thinking control: gemini-3-flash-preview (4 levels)`;
|
|
1149
|
+
break;
|
|
1150
|
+
case 'parameters':
|
|
1151
|
+
helpContent = this.getHelpContent('parameters');
|
|
1152
|
+
break;
|
|
1153
|
+
case 'examples':
|
|
1154
|
+
helpContent = this.getHelpContent('examples');
|
|
1155
|
+
break;
|
|
1156
|
+
case 'quick-start':
|
|
1157
|
+
helpContent = `# Quick Start Guide
|
|
1158
|
+
|
|
1159
|
+
## 1. Basic Usage
|
|
1160
|
+
Just ask naturally:
|
|
1161
|
+
- "Use Gemini to [your request]"
|
|
1162
|
+
- "Ask Gemini about [topic]"
|
|
1163
|
+
|
|
1164
|
+
## 2. Common Tasks
|
|
1165
|
+
|
|
1166
|
+
**Text Generation:**
|
|
1167
|
+
"Use Gemini to write a function that sorts arrays"
|
|
1168
|
+
|
|
1169
|
+
**Image Analysis:**
|
|
1170
|
+
"What's in this image?" [attach image]
|
|
1171
|
+
|
|
1172
|
+
**Model Info:**
|
|
1173
|
+
"List all Gemini models"
|
|
1174
|
+
|
|
1175
|
+
**Token Counting:**
|
|
1176
|
+
"Count tokens for my prompt"
|
|
1177
|
+
|
|
1178
|
+
## 3. Advanced Features
|
|
1179
|
+
|
|
1180
|
+
**JSON Output:**
|
|
1181
|
+
"Use Gemini in JSON mode to extract key points"
|
|
1182
|
+
|
|
1183
|
+
**Current Information:**
|
|
1184
|
+
"Use Gemini with grounding to get latest news"
|
|
1185
|
+
|
|
1186
|
+
**Conversations:**
|
|
1187
|
+
"Start a chat with Gemini about Python"
|
|
1188
|
+
|
|
1189
|
+
## 4. Tips
|
|
1190
|
+
- Use gemini-3-pro-preview for most tasks
|
|
1191
|
+
- Lower temperature for facts, higher for creativity
|
|
1192
|
+
- Enable grounding for current information
|
|
1193
|
+
- Use conversation IDs to maintain context
|
|
1194
|
+
|
|
1195
|
+
## Need More Help?
|
|
1196
|
+
- "Get help on tools" - Detailed tool information
|
|
1197
|
+
- "Get help on parameters" - All parameters explained
|
|
1198
|
+
- "Get help on models" - Model selection guide`;
|
|
1199
|
+
break;
|
|
1200
|
+
default:
|
|
1201
|
+
helpContent = 'Unknown help topic. Available topics: overview, tools, models, parameters, examples, quick-start';
|
|
1202
|
+
}
|
|
1203
|
+
return {
|
|
1204
|
+
jsonrpc: '2.0',
|
|
1205
|
+
id,
|
|
1206
|
+
result: {
|
|
1207
|
+
content: [{
|
|
1208
|
+
type: 'text',
|
|
1209
|
+
text: helpContent
|
|
1210
|
+
}]
|
|
1211
|
+
}
|
|
1212
|
+
};
|
|
1213
|
+
}
|
|
1214
|
+
sendResponse(response) {
|
|
1215
|
+
const responseStr = JSON.stringify(response);
|
|
1216
|
+
process.stdout.write(responseStr + '\n');
|
|
1217
|
+
}
|
|
1218
|
+
}
|
|
1219
|
+
// Start the server
|
|
1220
|
+
const apiKey = process.env.GEMINI_API_KEY;
|
|
1221
|
+
if (!apiKey) {
|
|
1222
|
+
console.error('GEMINI_API_KEY environment variable is required');
|
|
1223
|
+
process.exit(1);
|
|
1224
|
+
}
|
|
1225
|
+
new EnhancedStdioMCPServer(apiKey);
|
|
1226
|
+
//# sourceMappingURL=enhanced-stdio-server.js.map
|