gemini-studio-mcp 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -2
- package/dist/config.js +2 -0
- package/dist/config.js.map +1 -1
- package/dist/gemini/client.js +9 -0
- package/dist/gemini/client.js.map +1 -1
- package/dist/server.js +1 -1
- package/dist/tools/editImage.js +8 -4
- package/dist/tools/editImage.js.map +1 -1
- package/dist/tools/generateImage.js +7 -3
- package/dist/tools/generateImage.js.map +1 -1
- package/dist/tools/generateVideo.js +8 -4
- package/dist/tools/generateVideo.js.map +1 -1
- package/dist/tools/translate.js +12 -0
- package/dist/tools/translate.js.map +1 -0
- package/dist/translate/detect.js +6 -0
- package/dist/translate/detect.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -88,12 +88,14 @@ Get a key at **https://aistudio.google.com/apikey** — then restart your client
|
|
|
88
88
|
| `GEMINI_IMAGE_MODEL` | Image generation model | `imagen-4.0-generate-001` |
|
|
89
89
|
| `GEMINI_EDIT_MODEL` | Edit / iterate model | `gemini-3-pro-image-preview` |
|
|
90
90
|
| `GEMINI_VIDEO_MODEL` | Video model | `veo-3.1-generate-preview` |
|
|
91
|
+
| `GEMINI_AUTO_TRANSLATE` | Auto-translate non-English prompts | `true` |
|
|
92
|
+
| `GEMINI_TRANSLATE_MODEL` | Model used for translation | `gemini-2.5-flash` |
|
|
91
93
|
|
|
92
94
|
**Cost awareness:** image tools report an estimated price; `generate_video` is paid and returns an estimate first — pass `confirm: true` to actually render.
|
|
93
95
|
|
|
94
96
|
> **Tip:** when launched via `npx` from a desktop client, the process working directory may be non-obvious — set `GEMINI_STUDIO_DIR` to an absolute path so you can always find your output.
|
|
95
97
|
|
|
96
|
-
> **
|
|
98
|
+
> **Multilingual:** non-English prompts are auto-translated to English before generation (Imagen follows English best). Disable per call with `translate: false`, or globally with `GEMINI_AUTO_TRANSLATE=false`.
|
|
97
99
|
|
|
98
100
|
## How it works
|
|
99
101
|
|
|
@@ -121,7 +123,8 @@ Tested against the live Gemini API: ✅ `generate_image` (Imagen 4) · ✅ `edit
|
|
|
121
123
|
## Roadmap
|
|
122
124
|
|
|
123
125
|
- **v0.1 — core:** generate · edit · iterate · video, with asset lineage.
|
|
124
|
-
- **v0.2 — studio
|
|
126
|
+
- **v0.2 — studio:** style presets, gallery & `show_asset`, cost estimates (with a `confirm` gate on paid video).
|
|
127
|
+
- **v0.3 — multilingual (current):** non-English prompts auto-translated to English for better adherence.
|
|
125
128
|
- **Next:** non-blocking / resumable video jobs with progress.
|
|
126
129
|
|
|
127
130
|
## Development
|
package/dist/config.js
CHANGED
|
@@ -14,6 +14,8 @@ export function loadConfig(env = process.env) {
|
|
|
14
14
|
defaultImageModel: env.GEMINI_IMAGE_MODEL ?? 'imagen-4.0-generate-001',
|
|
15
15
|
editModel: env.GEMINI_EDIT_MODEL ?? 'gemini-3-pro-image-preview',
|
|
16
16
|
videoModel: env.GEMINI_VIDEO_MODEL ?? 'veo-3.1-generate-preview',
|
|
17
|
+
autoTranslate: env.GEMINI_AUTO_TRANSLATE !== 'false',
|
|
18
|
+
translateModel: env.GEMINI_TRANSLATE_MODEL ?? 'gemini-2.5-flash',
|
|
17
19
|
};
|
|
18
20
|
}
|
|
19
21
|
//# sourceMappingURL=config.js.map
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAY7B,MAAM,OAAO,kBAAmB,SAAQ,KAAK;CAAG;AAEhD,MAAM,UAAU,UAAU,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC7D,MAAM,MAAM,GAAG,GAAG,CAAC,cAAc,CAAC;IAClC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,kBAAkB,CAC1B,6EAA6E;YAC7E,2DAA2D,CAC5D,CAAC;IACJ,CAAC;IACD,MAAM,OAAO,GAAG,GAAG,CAAC,iBAAiB,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,gBAAgB,CAAC,CAAC;IAClG,OAAO;QACL,MAAM;QACN,UAAU,EAAE,OAAO;QACnB,iBAAiB,EAAE,GAAG,CAAC,kBAAkB,IAAI,yBAAyB;QACtE,SAAS,EAAE,GAAG,CAAC,iBAAiB,IAAI,4BAA4B;QAChE,UAAU,EAAE,GAAG,CAAC,kBAAkB,IAAI,0BAA0B;QAChE,aAAa,EAAE,GAAG,CAAC,qBAAqB,KAAK,OAAO;QACpD,cAAc,EAAE,GAAG,CAAC,sBAAsB,IAAI,kBAAkB;KACjE,CAAC;AACJ,CAAC"}
|
package/dist/gemini/client.js
CHANGED
|
@@ -18,6 +18,15 @@ export class RealGeminiClient {
|
|
|
18
18
|
}
|
|
19
19
|
return { data: Buffer.from(img.imageBytes, 'base64'), mimeType: img.mimeType ?? 'image/png' };
|
|
20
20
|
}
|
|
21
|
+
async translateToEnglish(text, model) {
|
|
22
|
+
const res = await this.ai.models.generateContent({
|
|
23
|
+
model,
|
|
24
|
+
contents: 'Translate the following image prompt to natural English. ' +
|
|
25
|
+
'Output ONLY the translation — no quotes, no notes, no preamble:\n\n' + text,
|
|
26
|
+
});
|
|
27
|
+
const out = (res?.text ?? '').trim();
|
|
28
|
+
return out || text;
|
|
29
|
+
}
|
|
21
30
|
async editImage({ prompt, model, image }) {
|
|
22
31
|
const res = await this.ai.interactions.create({
|
|
23
32
|
model,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/gemini/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,MAAM,KAAK,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/gemini/client.ts"],"names":[],"mappings":"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"}
|
package/dist/server.js
CHANGED
|
@@ -22,7 +22,7 @@ export async function startServer() {
|
|
|
22
22
|
session: new Session(),
|
|
23
23
|
config,
|
|
24
24
|
};
|
|
25
|
-
const server = new McpServer({ name: 'gemini-studio-mcp', version: '0.
|
|
25
|
+
const server = new McpServer({ name: 'gemini-studio-mcp', version: '0.3.0' });
|
|
26
26
|
registerGenerateImage(server, deps);
|
|
27
27
|
registerEditImage(server, deps);
|
|
28
28
|
registerIterate(server, deps);
|
package/dist/tools/editImage.js
CHANGED
|
@@ -3,10 +3,12 @@ import { z } from 'zod';
|
|
|
3
3
|
import { imageResult, errorResult } from './result.js';
|
|
4
4
|
import { extFromMime } from '../util/mime.js';
|
|
5
5
|
import { estimateCost } from '../cost/pricing.js';
|
|
6
|
+
import { maybeTranslate } from './translate.js';
|
|
6
7
|
export const editImageInput = {
|
|
7
8
|
id: z.string().describe('id ранее сгенерированного изображения'),
|
|
8
9
|
prompt: z.string().describe('Что изменить'),
|
|
9
10
|
model: z.string().optional(),
|
|
11
|
+
translate: z.boolean().optional().describe('Перевести инструкцию на английский (по умолчанию авто при кириллице)'),
|
|
10
12
|
};
|
|
11
13
|
export async function editImageHandler(input, deps) {
|
|
12
14
|
try {
|
|
@@ -14,26 +16,28 @@ export async function editImageHandler(input, deps) {
|
|
|
14
16
|
const bytes = await deps.store.readBytes(input.id);
|
|
15
17
|
if (!source || !bytes)
|
|
16
18
|
throw new Error(`Изображение с id="${input.id}" не найдено.`);
|
|
19
|
+
const t = await maybeTranslate(input.prompt, deps, input.translate);
|
|
17
20
|
const model = input.model ?? deps.config.editModel;
|
|
18
21
|
const media = await deps.client.editImage({
|
|
19
|
-
prompt:
|
|
22
|
+
prompt: t.text, model, image: { data: bytes, mimeType: source.mimeType },
|
|
20
23
|
});
|
|
21
24
|
const id = randomUUID().slice(0, 8);
|
|
22
25
|
const manifest = {
|
|
23
|
-
id, parentId: source.id, kind: 'image', prompt:
|
|
26
|
+
id, parentId: source.id, kind: 'image', prompt: t.text, model,
|
|
24
27
|
file: `${id}.${extFromMime(media.mimeType)}`, mimeType: media.mimeType,
|
|
25
28
|
createdAt: new Date().toISOString(),
|
|
26
29
|
};
|
|
27
30
|
await deps.store.save(manifest, media.data);
|
|
28
31
|
deps.session.setLastImageId(id);
|
|
29
32
|
const cost = estimateCost({ kind: 'image', model });
|
|
30
|
-
|
|
33
|
+
const note = t.translated ? ` Инструкция переведена: "${t.text}".` : '';
|
|
34
|
+
return imageResult(media, `Готово. id=${id} (правка ${source.id}), файл: ${manifest.file}. Стоимость: ${cost.text}.${note}`);
|
|
31
35
|
}
|
|
32
36
|
catch (err) {
|
|
33
37
|
return errorResult(err);
|
|
34
38
|
}
|
|
35
39
|
}
|
|
36
40
|
export function registerEditImage(server, deps) {
|
|
37
|
-
server.registerTool('edit_image', { title: 'Edit image', description: 'Отредактировать сохранённое изображение по его id и текстовой
|
|
41
|
+
server.registerTool('edit_image', { title: 'Edit image', description: 'Отредактировать сохранённое изображение по его id и текстовой инструкции (русская инструкция переводится автоматически).', inputSchema: editImageInput }, (input) => editImageHandler(input, deps));
|
|
38
42
|
}
|
|
39
43
|
//# sourceMappingURL=editImage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editImage.js","sourceRoot":"","sources":["../../src/tools/editImage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,WAAW,EAAE,WAAW,EAAuB,MAAM,aAAa,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"editImage.js","sourceRoot":"","sources":["../../src/tools/editImage.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,14 +3,17 @@ import { z } from 'zod';
|
|
|
3
3
|
import { imageResult, errorResult } from './result.js';
|
|
4
4
|
import { extFromMime } from '../util/mime.js';
|
|
5
5
|
import { estimateCost } from '../cost/pricing.js';
|
|
6
|
+
import { maybeTranslate } from './translate.js';
|
|
6
7
|
export const generateImageInput = {
|
|
7
8
|
prompt: z.string().describe('Что нарисовать'),
|
|
8
9
|
model: z.string().optional().describe('Переопределить модель (по умолчанию Imagen 4)'),
|
|
9
10
|
preset: z.string().optional().describe('Имя сохранённого пресета стиля (его стиль добавится к промпту)'),
|
|
11
|
+
translate: z.boolean().optional().describe('Перевести промпт на английский (по умолчанию авто при кириллице)'),
|
|
10
12
|
};
|
|
11
13
|
export async function generateImageHandler(input, deps) {
|
|
12
14
|
try {
|
|
13
|
-
|
|
15
|
+
const t = await maybeTranslate(input.prompt, deps, input.translate);
|
|
16
|
+
let prompt = t.text;
|
|
14
17
|
if (input.preset) {
|
|
15
18
|
const preset = await deps.presets.get(input.preset);
|
|
16
19
|
if (!preset)
|
|
@@ -28,13 +31,14 @@ export async function generateImageHandler(input, deps) {
|
|
|
28
31
|
await deps.store.save(manifest, media.data);
|
|
29
32
|
deps.session.setLastImageId(id);
|
|
30
33
|
const cost = estimateCost({ kind: 'image', model });
|
|
31
|
-
|
|
34
|
+
const note = t.translated ? ` Промпт переведён на английский: "${t.text}".` : '';
|
|
35
|
+
return imageResult(media, `Готово. id=${id}, файл: ${manifest.file} (в ${deps.config.workingDir}). Стоимость: ${cost.text}.${note}`);
|
|
32
36
|
}
|
|
33
37
|
catch (err) {
|
|
34
38
|
return errorResult(err);
|
|
35
39
|
}
|
|
36
40
|
}
|
|
37
41
|
export function registerGenerateImage(server, deps) {
|
|
38
|
-
server.registerTool('generate_image', { title: 'Generate image', description: 'Сгенерировать изображение по тексту через Gemini (Imagen 4). Можно указать preset
|
|
42
|
+
server.registerTool('generate_image', { title: 'Generate image', description: 'Сгенерировать изображение по тексту через Gemini (Imagen 4). Русские промпты автоматически переводятся на английский. Можно указать preset.', inputSchema: generateImageInput }, (input) => generateImageHandler(input, deps));
|
|
39
43
|
}
|
|
40
44
|
//# sourceMappingURL=generateImage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateImage.js","sourceRoot":"","sources":["../../src/tools/generateImage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,WAAW,EAAE,WAAW,EAAuB,MAAM,aAAa,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"generateImage.js","sourceRoot":"","sources":["../../src/tools/generateImage.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,10 +3,12 @@ import { z } from 'zod';
|
|
|
3
3
|
import { imageResult, errorResult } from './result.js';
|
|
4
4
|
import { extFromMime } from '../util/mime.js';
|
|
5
5
|
import { estimateCost } from '../cost/pricing.js';
|
|
6
|
+
import { maybeTranslate } from './translate.js';
|
|
6
7
|
export const generateVideoInput = {
|
|
7
8
|
prompt: z.string().describe('Что снять'),
|
|
8
9
|
model: z.string().optional(),
|
|
9
10
|
confirm: z.boolean().optional().describe('Подтверждение генерации видео (платно). Без него вернётся только смета.'),
|
|
11
|
+
translate: z.boolean().optional().describe('Перевести промпт на английский (по умолчанию авто при кириллице)'),
|
|
10
12
|
};
|
|
11
13
|
export async function generateVideoHandler(input, deps) {
|
|
12
14
|
const model = input.model ?? deps.config.videoModel;
|
|
@@ -15,21 +17,23 @@ export async function generateVideoHandler(input, deps) {
|
|
|
15
17
|
return { content: [{ type: 'text', text: `Видео через ${model} стоит ${cost.text}. Это платно. Чтобы сгенерировать, вызови ещё раз с confirm: true.` }] };
|
|
16
18
|
}
|
|
17
19
|
try {
|
|
18
|
-
const
|
|
20
|
+
const t = await maybeTranslate(input.prompt, deps, input.translate);
|
|
21
|
+
const media = await deps.client.generateVideo({ prompt: t.text, model });
|
|
19
22
|
const id = randomUUID().slice(0, 8);
|
|
20
23
|
const manifest = {
|
|
21
|
-
id, parentId: null, kind: 'video', prompt:
|
|
24
|
+
id, parentId: null, kind: 'video', prompt: t.text, model,
|
|
22
25
|
file: `${id}.${extFromMime(media.mimeType)}`, mimeType: media.mimeType,
|
|
23
26
|
createdAt: new Date().toISOString(),
|
|
24
27
|
};
|
|
25
28
|
await deps.store.save(manifest, media.data);
|
|
26
|
-
|
|
29
|
+
const note = t.translated ? ` Промпт переведён: "${t.text}".` : '';
|
|
30
|
+
return imageResult(media, `Видео готово. id=${id}, файл: ${manifest.file} (в ${deps.config.workingDir}). Стоимость: ${cost.text}.${note}`);
|
|
27
31
|
}
|
|
28
32
|
catch (err) {
|
|
29
33
|
return errorResult(err);
|
|
30
34
|
}
|
|
31
35
|
}
|
|
32
36
|
export function registerGenerateVideo(server, deps) {
|
|
33
|
-
server.registerTool('generate_video', { title: 'Generate video', description: 'Сгенерировать видео по тексту через Gemini (Veo). Платно: без confirm:true вернёт смету.
|
|
37
|
+
server.registerTool('generate_video', { title: 'Generate video', description: 'Сгенерировать видео по тексту через Gemini (Veo). Платно: без confirm:true вернёт смету. Русский промпт переводится автоматически.', inputSchema: generateVideoInput }, (input) => generateVideoHandler(input, deps));
|
|
34
38
|
}
|
|
35
39
|
//# sourceMappingURL=generateVideo.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateVideo.js","sourceRoot":"","sources":["../../src/tools/generateVideo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,WAAW,EAAE,WAAW,EAAuB,MAAM,aAAa,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"generateVideo.js","sourceRoot":"","sources":["../../src/tools/generateVideo.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { needsTranslation } from '../translate/detect.js';
|
|
2
|
+
export async function maybeTranslate(text, deps, override) {
|
|
3
|
+
const auto = deps.config.autoTranslate ?? true;
|
|
4
|
+
const should = override === true || (override !== false && auto && needsTranslation(text));
|
|
5
|
+
if (!should || !deps.client.translateToEnglish) {
|
|
6
|
+
return { text, translated: false };
|
|
7
|
+
}
|
|
8
|
+
const model = deps.config.translateModel ?? 'gemini-2.5-flash';
|
|
9
|
+
const translated = await deps.client.translateToEnglish(text, model);
|
|
10
|
+
return { text: translated, translated: translated !== text };
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=translate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"translate.js","sourceRoot":"","sources":["../../src/tools/translate.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAI1D,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,IAAY,EACZ,IAAc,EACd,QAAkB;IAElB,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,IAAI,IAAI,CAAC;IAC/C,MAAM,MAAM,GAAG,QAAQ,KAAK,IAAI,IAAI,CAAC,QAAQ,KAAK,KAAK,IAAI,IAAI,IAAI,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3F,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC;QAC/C,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;IACrC,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc,IAAI,kBAAkB,CAAC;IAC/D,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACrE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,KAAK,IAAI,EAAE,CAAC;AAC/D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect.js","sourceRoot":"","sources":["../../src/translate/detect.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,2DAA2D;AAC3D,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gemini-studio-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "MCP server for iterative image & video generation via the Gemini API (Imagen 4, Gemini 3 Pro Image, Veo) — generate and refine in plain words, with lineage.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": { "gemini-studio-mcp": "dist/index.js" },
|