@houtini/gemini-mcp 1.4.2 → 2.2.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 +314 -784
- package/claude_desktop_config_example.json +1 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +8 -4
- package/dist/config/index.js.map +1 -1
- package/dist/config/types.d.ts +5 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/image-viewer/image-viewer-app.html +180 -0
- package/dist/image-viewer/src/ui/image-viewer.html +324 -0
- package/dist/index-new.d.ts +3 -0
- package/dist/index-new.d.ts.map +1 -0
- package/dist/index-new.js +7 -0
- package/dist/index-new.js.map +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +70 -172
- package/dist/index.js.map +1 -1
- package/dist/landing-page-viewer/src/ui/landing-page-viewer.html +330 -0
- package/dist/services/gemini/export.d.ts +5 -0
- package/dist/services/gemini/export.d.ts.map +1 -0
- package/dist/services/gemini/export.js +5 -0
- package/dist/services/gemini/export.js.map +1 -0
- package/dist/services/gemini/image-service.d.ts +45 -0
- package/dist/services/gemini/image-service.d.ts.map +1 -0
- package/dist/services/gemini/image-service.js +248 -0
- package/dist/services/gemini/image-service.js.map +1 -0
- package/dist/services/gemini/index.d.ts +7 -2
- package/dist/services/gemini/index.d.ts.map +1 -1
- package/dist/services/gemini/index.js +132 -56
- package/dist/services/gemini/index.js.map +1 -1
- package/dist/services/gemini/types.d.ts +32 -0
- package/dist/services/gemini/types.d.ts.map +1 -1
- package/dist/services/gemini/video-service.d.ts +58 -0
- package/dist/services/gemini/video-service.d.ts.map +1 -0
- package/dist/services/gemini/video-service.js +325 -0
- package/dist/services/gemini/video-service.js.map +1 -0
- package/dist/services/media-server.d.ts +28 -0
- package/dist/services/media-server.d.ts.map +1 -0
- package/dist/services/media-server.js +195 -0
- package/dist/services/media-server.js.map +1 -0
- package/dist/svg-viewer/src/ui/svg-viewer.html +325 -0
- package/dist/tools/gemini-chat.d.ts.map +1 -1
- package/dist/tools/gemini-chat.js +7 -1
- package/dist/tools/gemini-chat.js.map +1 -1
- package/dist/tools/gemini-deep-research.d.ts +1 -2
- package/dist/tools/gemini-deep-research.d.ts.map +1 -1
- package/dist/tools/gemini-deep-research.js +11 -51
- package/dist/tools/gemini-deep-research.js.map +1 -1
- package/dist/tools/gemini-help.d.ts +3 -0
- package/dist/tools/gemini-help.d.ts.map +1 -0
- package/dist/tools/gemini-help.js +534 -0
- package/dist/tools/gemini-help.js.map +1 -0
- package/dist/tools/gemini-prompt-assistant.d.ts +20 -0
- package/dist/tools/gemini-prompt-assistant.d.ts.map +1 -0
- package/dist/tools/gemini-prompt-assistant.js +129 -0
- package/dist/tools/gemini-prompt-assistant.js.map +1 -0
- package/dist/tools/generate-landing-page.d.ts +15 -0
- package/dist/tools/generate-landing-page.d.ts.map +1 -0
- package/dist/tools/generate-landing-page.js +66 -0
- package/dist/tools/generate-landing-page.js.map +1 -0
- package/dist/tools/generate-svg.d.ts +14 -0
- package/dist/tools/generate-svg.d.ts.map +1 -0
- package/dist/tools/generate-svg.js +106 -0
- package/dist/tools/generate-svg.js.map +1 -0
- package/dist/tools/generate-video.d.ts +24 -0
- package/dist/tools/generate-video.d.ts.map +1 -0
- package/dist/tools/generate-video.js +163 -0
- package/dist/tools/generate-video.js.map +1 -0
- package/dist/tools/image-prompt-assistant.d.ts +3 -0
- package/dist/tools/image-prompt-assistant.d.ts.map +1 -0
- package/dist/tools/image-prompt-assistant.js +790 -0
- package/dist/tools/image-prompt-assistant.js.map +1 -0
- package/dist/tools/load-image-from-path.d.ts +11 -0
- package/dist/tools/load-image-from-path.d.ts.map +1 -0
- package/dist/tools/load-image-from-path.js +100 -0
- package/dist/tools/load-image-from-path.js.map +1 -0
- package/dist/tools/prompt-library/charts.d.ts +325 -0
- package/dist/tools/prompt-library/charts.d.ts.map +1 -0
- package/dist/tools/prompt-library/charts.js +384 -0
- package/dist/tools/prompt-library/charts.js.map +1 -0
- package/dist/tools/prompt-library/index.d.ts +8 -0
- package/dist/tools/prompt-library/index.d.ts.map +1 -0
- package/dist/tools/prompt-library/index.js +10 -0
- package/dist/tools/prompt-library/index.js.map +1 -0
- package/dist/tools/register-analyze-image.d.ts +3 -0
- package/dist/tools/register-analyze-image.d.ts.map +1 -0
- package/dist/tools/register-analyze-image.js +67 -0
- package/dist/tools/register-analyze-image.js.map +1 -0
- package/dist/tools/register-chat.d.ts +3 -0
- package/dist/tools/register-chat.d.ts.map +1 -0
- package/dist/tools/register-chat.js +71 -0
- package/dist/tools/register-chat.js.map +1 -0
- package/dist/tools/register-deep-research.d.ts +3 -0
- package/dist/tools/register-deep-research.d.ts.map +1 -0
- package/dist/tools/register-deep-research.js +59 -0
- package/dist/tools/register-deep-research.js.map +1 -0
- package/dist/tools/register-describe-image.d.ts +3 -0
- package/dist/tools/register-describe-image.d.ts.map +1 -0
- package/dist/tools/register-describe-image.js +59 -0
- package/dist/tools/register-describe-image.js.map +1 -0
- package/dist/tools/register-image-gen.d.ts +3 -0
- package/dist/tools/register-image-gen.d.ts.map +1 -0
- package/dist/tools/register-image-gen.js +235 -0
- package/dist/tools/register-image-gen.js.map +1 -0
- package/dist/tools/register-landing-page.d.ts +3 -0
- package/dist/tools/register-landing-page.d.ts.map +1 -0
- package/dist/tools/register-landing-page.js +79 -0
- package/dist/tools/register-landing-page.js.map +1 -0
- package/dist/tools/register-list-models.d.ts +3 -0
- package/dist/tools/register-list-models.d.ts.map +1 -0
- package/dist/tools/register-list-models.js +33 -0
- package/dist/tools/register-list-models.js.map +1 -0
- package/dist/tools/register-load-image.d.ts +3 -0
- package/dist/tools/register-load-image.d.ts.map +1 -0
- package/dist/tools/register-load-image.js +66 -0
- package/dist/tools/register-load-image.js.map +1 -0
- package/dist/tools/register-svg.d.ts +3 -0
- package/dist/tools/register-svg.d.ts.map +1 -0
- package/dist/tools/register-svg.js +84 -0
- package/dist/tools/register-svg.js.map +1 -0
- package/dist/tools/register-video.d.ts +3 -0
- package/dist/tools/register-video.d.ts.map +1 -0
- package/dist/tools/register-video.js +118 -0
- package/dist/tools/register-video.js.map +1 -0
- package/dist/tools/register-viewers.d.ts +8 -0
- package/dist/tools/register-viewers.d.ts.map +1 -0
- package/dist/tools/register-viewers.js +89 -0
- package/dist/tools/register-viewers.js.map +1 -0
- package/dist/tools/schemas.d.ts +33 -0
- package/dist/tools/schemas.d.ts.map +1 -0
- package/dist/tools/schemas.js +39 -0
- package/dist/tools/schemas.js.map +1 -0
- package/dist/tools/types.d.ts +12 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +2 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/ui/image-viewer.d.ts +2 -0
- package/dist/ui/image-viewer.d.ts.map +1 -0
- package/dist/ui/image-viewer.js +42 -0
- package/dist/ui/image-viewer.js.map +1 -0
- package/dist/utils/chart-design-system.d.ts +92 -0
- package/dist/utils/chart-design-system.d.ts.map +1 -0
- package/dist/utils/chart-design-system.js +235 -0
- package/dist/utils/chart-design-system.js.map +1 -0
- package/dist/utils/image-compress.d.ts +9 -0
- package/dist/utils/image-compress.d.ts.map +1 -0
- package/dist/utils/image-compress.js +43 -0
- package/dist/utils/image-compress.js.map +1 -0
- package/dist/utils/image-utils.d.ts +9 -0
- package/dist/utils/image-utils.d.ts.map +1 -0
- package/dist/utils/image-utils.js +257 -0
- package/dist/utils/image-utils.js.map +1 -0
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +45 -11
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/resolve-images.d.ts +29 -0
- package/dist/utils/resolve-images.d.ts.map +1 -0
- package/dist/utils/resolve-images.js +56 -0
- package/dist/utils/resolve-images.js.map +1 -0
- package/dist/utils/tool-wrapper.d.ts +13 -0
- package/dist/utils/tool-wrapper.d.ts.map +1 -0
- package/dist/utils/tool-wrapper.js +22 -0
- package/dist/utils/tool-wrapper.js.map +1 -0
- package/dist/utils/video-utils.d.ts +16 -0
- package/dist/utils/video-utils.d.ts.map +1 -0
- package/dist/utils/video-utils.js +319 -0
- package/dist/utils/video-utils.js.map +1 -0
- package/dist/video-viewer/src/ui/video-viewer.html +310 -0
- package/houtini-logo.jpg +0 -0
- package/package.json +24 -8
- package/server.json +30 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import * as z from 'zod';
|
|
2
|
+
import logger from '../utils/logger.js';
|
|
3
|
+
import { toolError } from '../utils/tool-wrapper.js';
|
|
4
|
+
import { GeminiDeepResearchTool } from './gemini-deep-research.js';
|
|
5
|
+
export function register(ctx) {
|
|
6
|
+
ctx.server.registerTool('gemini_deep_research', {
|
|
7
|
+
title: 'Gemini Deep Research',
|
|
8
|
+
description: 'Conduct deep research on complex topics using iterative multi-step analysis with Gemini. ' +
|
|
9
|
+
'This performs multiple searches and synthesizes comprehensive research reports (takes several minutes). ' +
|
|
10
|
+
'[MCP_RECOMMENDED_TIMEOUT_MS: 900000]',
|
|
11
|
+
inputSchema: {
|
|
12
|
+
research_question: z.string().describe('The complex research question or topic to investigate deeply'),
|
|
13
|
+
model: z.string()
|
|
14
|
+
.optional()
|
|
15
|
+
.describe('Model to use for deep research (defaults to latest available)'),
|
|
16
|
+
max_iterations: z.number()
|
|
17
|
+
.int()
|
|
18
|
+
.min(3)
|
|
19
|
+
.max(10)
|
|
20
|
+
.optional()
|
|
21
|
+
.default(5)
|
|
22
|
+
.describe('Number of research iterations (3-10, default 5). Environment guidance: ' +
|
|
23
|
+
'Claude Desktop: use 3-4 (4-min timeout). ' +
|
|
24
|
+
'Agent SDK/IDEs (VSCode, Cursor, Windsurf)/AI platforms (Cline, Roo-Cline): can use 7-10 (longer timeout tolerance)'),
|
|
25
|
+
focus_areas: z.array(z.string())
|
|
26
|
+
.optional()
|
|
27
|
+
.describe('Optional: specific areas to focus the research on')
|
|
28
|
+
},
|
|
29
|
+
outputSchema: {
|
|
30
|
+
content: z.string(),
|
|
31
|
+
success: z.boolean()
|
|
32
|
+
}
|
|
33
|
+
}, async ({ research_question, model, max_iterations, focus_areas }) => {
|
|
34
|
+
try {
|
|
35
|
+
logger.info('Starting deep research', {
|
|
36
|
+
question: research_question,
|
|
37
|
+
maxIterations: max_iterations || 5
|
|
38
|
+
});
|
|
39
|
+
const deepResearchTool = new GeminiDeepResearchTool(ctx.geminiService);
|
|
40
|
+
const result = await deepResearchTool.execute({
|
|
41
|
+
research_question,
|
|
42
|
+
model,
|
|
43
|
+
max_iterations,
|
|
44
|
+
focus_areas
|
|
45
|
+
});
|
|
46
|
+
return {
|
|
47
|
+
content: result,
|
|
48
|
+
structuredContent: {
|
|
49
|
+
content: result[0]?.text || 'Research completed',
|
|
50
|
+
success: true
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
return toolError('gemini_deep_research', error);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=register-deep-research.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register-deep-research.js","sourceRoot":"","sources":["../../src/tools/register-deep-research.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AACzB,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAGnE,MAAM,UAAU,QAAQ,CAAC,GAAgB;IACvC,GAAG,CAAC,MAAM,CAAC,YAAY,CACrB,sBAAsB,EACtB;QACE,KAAK,EAAE,sBAAsB;QAC7B,WAAW,EACT,2FAA2F;YAC3F,0GAA0G;YAC1G,sCAAsC;QACxC,WAAW,EAAE;YACX,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8DAA8D,CAAC;YACtG,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;iBACd,QAAQ,EAAE;iBACV,QAAQ,CAAC,+DAA+D,CAAC;YAC5E,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE;iBACvB,GAAG,EAAE;iBACL,GAAG,CAAC,CAAC,CAAC;iBACN,GAAG,CAAC,EAAE,CAAC;iBACP,QAAQ,EAAE;iBACV,OAAO,CAAC,CAAC,CAAC;iBACV,QAAQ,CACP,yEAAyE;gBACzE,2CAA2C;gBAC3C,oHAAoH,CACrH;YACH,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;iBAC7B,QAAQ,EAAE;iBACV,QAAQ,CAAC,mDAAmD,CAAC;SACjE;QACD,YAAY,EAAE;YACZ,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;YACnB,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE;SACrB;KACF,EACD,KAAK,EAAE,EAAE,iBAAiB,EAAE,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,EAAE,EAAE;QAClE,IAAI,CAAC;YACH,MAAM,CAAC,IAAI,CAAC,wBAAwB,EAAE;gBACpC,QAAQ,EAAE,iBAAiB;gBAC3B,aAAa,EAAE,cAAc,IAAI,CAAC;aACnC,CAAC,CAAC;YAEH,MAAM,gBAAgB,GAAG,IAAI,sBAAsB,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;YACvE,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,OAAO,CAAC;gBAC5C,iBAAiB;gBACjB,KAAK;gBACL,cAAc;gBACd,WAAW;aACZ,CAAC,CAAC;YAEH,OAAO;gBACL,OAAO,EAAE,MAAM;gBACf,iBAAiB,EAAE;oBACjB,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,IAAI,oBAAoB;oBAChD,OAAO,EAAE,IAAI;iBACd;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,SAAS,CAAC,sBAAsB,EAAE,KAAK,CAAC,CAAC;QAClD,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register-describe-image.d.ts","sourceRoot":"","sources":["../../src/tools/register-describe-image.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,wBAAgB,QAAQ,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CA0D/C"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import * as z from 'zod';
|
|
2
|
+
import logger from '../utils/logger.js';
|
|
3
|
+
import { createToolResult } from '../utils/error-handler.js';
|
|
4
|
+
import { toolError } from '../utils/tool-wrapper.js';
|
|
5
|
+
import { resolveImageInputs } from '../utils/resolve-images.js';
|
|
6
|
+
import { imageInputSchema } from './schemas.js';
|
|
7
|
+
export function register(ctx) {
|
|
8
|
+
ctx.server.registerTool('describe_image', {
|
|
9
|
+
title: 'Describe Image (Nano Banana Pro)',
|
|
10
|
+
description: 'Analyze and describe one or more images using Google Gemini image models (Nano Banana Pro). ' +
|
|
11
|
+
'Returns a text description — no image is generated. Default model: gemini-3-flash-preview.',
|
|
12
|
+
inputSchema: {
|
|
13
|
+
images: z.array(imageInputSchema)
|
|
14
|
+
.min(1)
|
|
15
|
+
.describe('One or more images to describe/analyze'),
|
|
16
|
+
prompt: z.string()
|
|
17
|
+
.optional()
|
|
18
|
+
.describe('Optional custom analysis prompt (default: general description)'),
|
|
19
|
+
model: z.string()
|
|
20
|
+
.optional()
|
|
21
|
+
.describe('Gemini image model to use (default: gemini-3-flash-preview)'),
|
|
22
|
+
global_media_resolution: z.enum([
|
|
23
|
+
'MEDIA_RESOLUTION_LOW',
|
|
24
|
+
'MEDIA_RESOLUTION_MEDIUM',
|
|
25
|
+
'MEDIA_RESOLUTION_HIGH'
|
|
26
|
+
])
|
|
27
|
+
.optional()
|
|
28
|
+
.describe('Global image quality for cost optimization. MEDIUM recommended for PDFs (50% savings).'),
|
|
29
|
+
},
|
|
30
|
+
outputSchema: {
|
|
31
|
+
content: z.string(),
|
|
32
|
+
success: z.boolean(),
|
|
33
|
+
},
|
|
34
|
+
}, async ({ images, prompt, model, global_media_resolution }) => {
|
|
35
|
+
try {
|
|
36
|
+
logger.info('Executing describe_image tool', {
|
|
37
|
+
model,
|
|
38
|
+
imageCount: images.length,
|
|
39
|
+
globalMediaResolution: global_media_resolution
|
|
40
|
+
});
|
|
41
|
+
// Resolve filePath references server-side (bypasses MCP transport)
|
|
42
|
+
const resolved = await resolveImageInputs(images);
|
|
43
|
+
const description = await ctx.imageService.describeImage({
|
|
44
|
+
images: resolved,
|
|
45
|
+
prompt,
|
|
46
|
+
model,
|
|
47
|
+
globalMediaResolution: global_media_resolution
|
|
48
|
+
});
|
|
49
|
+
return {
|
|
50
|
+
content: createToolResult(true, description),
|
|
51
|
+
structuredContent: { content: description, success: true },
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
return toolError('describe_image', error);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=register-describe-image.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register-describe-image.js","sourceRoot":"","sources":["../../src/tools/register-describe-image.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AACzB,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGhD,MAAM,UAAU,QAAQ,CAAC,GAAgB;IACvC,GAAG,CAAC,MAAM,CAAC,YAAY,CACrB,gBAAgB,EAChB;QACE,KAAK,EAAE,kCAAkC;QACzC,WAAW,EACT,8FAA8F;YAC9F,4FAA4F;QAC9F,WAAW,EAAE;YACX,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,gBAAgB,CAAC;iBAC9B,GAAG,CAAC,CAAC,CAAC;iBACN,QAAQ,CAAC,wCAAwC,CAAC;YACrD,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;iBACf,QAAQ,EAAE;iBACV,QAAQ,CAAC,gEAAgE,CAAC;YAC7E,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;iBACd,QAAQ,EAAE;iBACV,QAAQ,CAAC,6DAA6D,CAAC;YAC1E,uBAAuB,EAAE,CAAC,CAAC,IAAI,CAAC;gBAC9B,sBAAsB;gBACtB,yBAAyB;gBACzB,uBAAuB;aACxB,CAAC;iBACC,QAAQ,EAAE;iBACV,QAAQ,CAAC,wFAAwF,CAAC;SACtG;QACD,YAAY,EAAE;YACZ,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;YACnB,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE;SACrB;KACF,EACD,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,uBAAuB,EAAE,EAAE,EAAE;QAC3D,IAAI,CAAC;YACH,MAAM,CAAC,IAAI,CAAC,+BAA+B,EAAE;gBAC3C,KAAK;gBACL,UAAU,EAAE,MAAM,CAAC,MAAM;gBACzB,qBAAqB,EAAE,uBAAuB;aAC/C,CAAC,CAAC;YAEH,mEAAmE;YACnE,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CAAC,MAAa,CAAC,CAAC;YAEzD,MAAM,WAAW,GAAG,MAAM,GAAG,CAAC,YAAY,CAAC,aAAa,CAAC;gBACvD,MAAM,EAAE,QAAe;gBACvB,MAAM;gBACN,KAAK;gBACL,qBAAqB,EAAE,uBAA8B;aACtD,CAAC,CAAC;YAEH,OAAO;gBACL,OAAO,EAAE,gBAAgB,CAAC,IAAI,EAAE,WAAW,CAAC;gBAC5C,iBAAiB,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE;aAC3D,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,SAAS,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register-image-gen.d.ts","sourceRoot":"","sources":["../../src/tools/register-image-gen.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AA8B9C,wBAAgB,QAAQ,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CA0P/C"}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import * as z from 'zod';
|
|
2
|
+
import { registerAppTool } from '@modelcontextprotocol/ext-apps/server';
|
|
3
|
+
import { resolve } from 'path';
|
|
4
|
+
import logger from '../utils/logger.js';
|
|
5
|
+
import { McpError, createToolResult } from '../utils/error-handler.js';
|
|
6
|
+
import { processGeneratedImage } from '../utils/image-utils.js';
|
|
7
|
+
import { resolveImageInputs } from '../utils/resolve-images.js';
|
|
8
|
+
import { savedFileMessage } from '../utils/tool-wrapper.js';
|
|
9
|
+
import { imageInputSchema } from './schemas.js';
|
|
10
|
+
function buildTextLines(savedPath, previewPath, description, groundingSources, thoughtSignature) {
|
|
11
|
+
const lines = [];
|
|
12
|
+
if (savedPath)
|
|
13
|
+
lines.push(savedFileMessage('Image saved', savedPath));
|
|
14
|
+
if (previewPath)
|
|
15
|
+
lines.push(savedFileMessage('HTML preview', previewPath));
|
|
16
|
+
if (description)
|
|
17
|
+
lines.push(`\n${description}`);
|
|
18
|
+
if (groundingSources && groundingSources.length > 0) {
|
|
19
|
+
lines.push('\n**Sources used for grounding:**');
|
|
20
|
+
groundingSources.forEach((source, idx) => {
|
|
21
|
+
lines.push(`${idx + 1}. [${source.title}](${source.url})`);
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
// Surface thoughtSignature so Claude can pass it to subsequent edit_image calls
|
|
25
|
+
// for conversational editing with Gemini 3 Pro Image
|
|
26
|
+
if (thoughtSignature) {
|
|
27
|
+
lines.push(`\n**thoughtSignature** (for conversational editing — pass to edit_image): \`${thoughtSignature}\``);
|
|
28
|
+
}
|
|
29
|
+
return lines;
|
|
30
|
+
}
|
|
31
|
+
export function register(ctx) {
|
|
32
|
+
registerAppTool(ctx.server, 'generate_image', {
|
|
33
|
+
title: 'Generate Image with Gemini',
|
|
34
|
+
description: 'Generate an image using Google Gemini image models (Nano Banana Pro). ' +
|
|
35
|
+
'Returns image with inline preview in Claude Desktop and saves full-resolution to disk. ' +
|
|
36
|
+
'Default model: gemini-3-pro-image-preview.',
|
|
37
|
+
inputSchema: {
|
|
38
|
+
prompt: z.string().describe('Description of the image to generate'),
|
|
39
|
+
model: z.string()
|
|
40
|
+
.optional()
|
|
41
|
+
.describe('Gemini image model to use (default: gemini-3-pro-image-preview). ' +
|
|
42
|
+
'Options: gemini-3-pro-image-preview, gemini-2.5-flash-image, nano-banana-pro-preview'),
|
|
43
|
+
aspectRatio: z.enum(['1:1', '3:4', '4:3', '9:16', '16:9'])
|
|
44
|
+
.optional()
|
|
45
|
+
.default('1:1')
|
|
46
|
+
.describe('Aspect ratio of the generated image'),
|
|
47
|
+
imageSize: z.enum(['1K', '2K', '4K'])
|
|
48
|
+
.optional()
|
|
49
|
+
.describe('Resolution of the generated image (only for image-specific models)'),
|
|
50
|
+
images: z.array(imageInputSchema)
|
|
51
|
+
.optional()
|
|
52
|
+
.describe('Optional reference images to guide generation'),
|
|
53
|
+
use_search: z.boolean()
|
|
54
|
+
.optional()
|
|
55
|
+
.default(false)
|
|
56
|
+
.describe('Enable Google Search grounding for data-driven image generation. ' +
|
|
57
|
+
'Use for: weather forecasts, current events, stock prices, sports scores, statistics. ' +
|
|
58
|
+
'The model will search the web for real-time data to inform image generation.'),
|
|
59
|
+
global_media_resolution: z.enum([
|
|
60
|
+
'MEDIA_RESOLUTION_LOW',
|
|
61
|
+
'MEDIA_RESOLUTION_MEDIUM',
|
|
62
|
+
'MEDIA_RESOLUTION_HIGH'
|
|
63
|
+
])
|
|
64
|
+
.optional()
|
|
65
|
+
.describe('Global image quality setting for cost optimization (default: HIGH). ' +
|
|
66
|
+
'LOW (280 tokens, 75% savings) - Simple tasks, bulk operations. ' +
|
|
67
|
+
'MEDIUM (560 tokens, 50% savings) - PDFs/documents (OCR saturates at medium). ' +
|
|
68
|
+
'HIGH (1120 tokens) - Best quality, detailed analysis. ' +
|
|
69
|
+
'Can be overridden per-image using mediaResolution in images array.'),
|
|
70
|
+
outputPath: z.string()
|
|
71
|
+
.optional()
|
|
72
|
+
.describe('Optional file path to save the generated image (e.g., ./output/image.png)'),
|
|
73
|
+
},
|
|
74
|
+
_meta: {
|
|
75
|
+
ui: { resourceUri: 'ui://gemini/image-viewer.html' }
|
|
76
|
+
}
|
|
77
|
+
}, async ({ prompt, model, aspectRatio, imageSize, images, use_search, global_media_resolution, outputPath }) => {
|
|
78
|
+
try {
|
|
79
|
+
logger.info('Executing generate_image tool', {
|
|
80
|
+
model,
|
|
81
|
+
promptLength: prompt.length,
|
|
82
|
+
useSearch: use_search,
|
|
83
|
+
globalMediaResolution: global_media_resolution
|
|
84
|
+
});
|
|
85
|
+
// Resolve any filePath references in input images server-side
|
|
86
|
+
const resolvedImages = images ? await resolveImageInputs(images) : undefined;
|
|
87
|
+
const result = await ctx.imageService.generateImage({
|
|
88
|
+
prompt,
|
|
89
|
+
model,
|
|
90
|
+
aspectRatio,
|
|
91
|
+
imageSize,
|
|
92
|
+
images: resolvedImages,
|
|
93
|
+
useSearch: use_search,
|
|
94
|
+
globalMediaResolution: global_media_resolution
|
|
95
|
+
});
|
|
96
|
+
const firstImage = result.parts.find(p => p.type === 'image' && p.base64Data);
|
|
97
|
+
const resolvedSavePath = outputPath
|
|
98
|
+
? resolve(outputPath)
|
|
99
|
+
: resolve(ctx.outputDir, `gemini-${Date.now()}.png`);
|
|
100
|
+
let savedPath;
|
|
101
|
+
let previewPath;
|
|
102
|
+
let previewImageData;
|
|
103
|
+
if (firstImage?.base64Data) {
|
|
104
|
+
const processed = await processGeneratedImage(firstImage.base64Data, firstImage.mimeType || 'image/png', resolvedSavePath, prompt, result.description);
|
|
105
|
+
savedPath = processed.savedPath;
|
|
106
|
+
previewPath = processed.previewPath;
|
|
107
|
+
previewImageData = processed.previewImageData;
|
|
108
|
+
}
|
|
109
|
+
// Extract thoughtSignature from response parts for conversational editing
|
|
110
|
+
const thoughtSignature = result.parts.find(p => !!p.thoughtSignature)?.thoughtSignature;
|
|
111
|
+
const textLines = buildTextLines(savedPath, previewPath, result.description, result.groundingSources, thoughtSignature);
|
|
112
|
+
// Serve full-res image via media server (bypasses MCP 1MB limit)
|
|
113
|
+
const imageUrl = savedPath ? ctx.mediaServer.getFileUrl(savedPath) : undefined;
|
|
114
|
+
return {
|
|
115
|
+
structuredContent: {
|
|
116
|
+
imageUrl,
|
|
117
|
+
base64Data: previewImageData || '',
|
|
118
|
+
mimeType: 'image/jpeg',
|
|
119
|
+
savedPath,
|
|
120
|
+
previewPath,
|
|
121
|
+
description: result.description,
|
|
122
|
+
prompt,
|
|
123
|
+
groundingSources: result.groundingSources
|
|
124
|
+
},
|
|
125
|
+
content: [
|
|
126
|
+
{
|
|
127
|
+
type: 'text',
|
|
128
|
+
text: textLines.join('\n') || 'Image generated successfully'
|
|
129
|
+
}
|
|
130
|
+
]
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
logger.error('generate_image tool failed', { error });
|
|
135
|
+
const msg = error instanceof McpError
|
|
136
|
+
? error.message
|
|
137
|
+
: `Failed to generate image: ${error.message}`;
|
|
138
|
+
return { content: createToolResult(false, msg, error) };
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
registerAppTool(ctx.server, 'edit_image', {
|
|
142
|
+
title: 'Edit Image with Gemini',
|
|
143
|
+
description: 'Edit one or more images using Google Gemini image models (Nano Banana Pro). ' +
|
|
144
|
+
'Provide images and natural-language instructions for how to modify them. ' +
|
|
145
|
+
'Returns edited image with inline preview and saves full-resolution to disk.',
|
|
146
|
+
inputSchema: {
|
|
147
|
+
prompt: z.string().describe('Instructions for how to edit the image(s)'),
|
|
148
|
+
images: z.array(imageInputSchema)
|
|
149
|
+
.min(1)
|
|
150
|
+
.describe('One or more images to edit'),
|
|
151
|
+
model: z.string()
|
|
152
|
+
.optional()
|
|
153
|
+
.describe('Gemini image model to use (default: gemini-3-pro-image-preview)'),
|
|
154
|
+
use_search: z.boolean()
|
|
155
|
+
.optional()
|
|
156
|
+
.default(false)
|
|
157
|
+
.describe('Enable Google Search grounding for data-driven editing'),
|
|
158
|
+
global_media_resolution: z.enum([
|
|
159
|
+
'MEDIA_RESOLUTION_LOW',
|
|
160
|
+
'MEDIA_RESOLUTION_MEDIUM',
|
|
161
|
+
'MEDIA_RESOLUTION_HIGH'
|
|
162
|
+
])
|
|
163
|
+
.optional()
|
|
164
|
+
.describe('Global image quality setting (default: HIGH). See generate_image for details.'),
|
|
165
|
+
outputPath: z.string()
|
|
166
|
+
.optional()
|
|
167
|
+
.describe('Optional file path to save the edited image (e.g., ./output/edited.png)'),
|
|
168
|
+
},
|
|
169
|
+
_meta: {
|
|
170
|
+
ui: { resourceUri: 'ui://gemini/image-viewer.html' }
|
|
171
|
+
}
|
|
172
|
+
}, async ({ prompt, images, model, use_search, global_media_resolution, outputPath }) => {
|
|
173
|
+
try {
|
|
174
|
+
logger.info('Executing edit_image tool', {
|
|
175
|
+
model,
|
|
176
|
+
imageCount: images.length,
|
|
177
|
+
useSearch: use_search,
|
|
178
|
+
globalMediaResolution: global_media_resolution
|
|
179
|
+
});
|
|
180
|
+
// Resolve any filePath references in input images server-side
|
|
181
|
+
const resolvedImages = await resolveImageInputs(images);
|
|
182
|
+
const result = await ctx.imageService.generateImage({
|
|
183
|
+
prompt,
|
|
184
|
+
model,
|
|
185
|
+
images: resolvedImages,
|
|
186
|
+
useSearch: use_search,
|
|
187
|
+
globalMediaResolution: global_media_resolution
|
|
188
|
+
});
|
|
189
|
+
const firstImage = result.parts.find(p => p.type === 'image' && p.base64Data);
|
|
190
|
+
const resolvedSavePath = outputPath
|
|
191
|
+
? resolve(outputPath)
|
|
192
|
+
: resolve(ctx.outputDir, `gemini-edit-${Date.now()}.png`);
|
|
193
|
+
let savedPath;
|
|
194
|
+
let previewPath;
|
|
195
|
+
let previewImageData;
|
|
196
|
+
if (firstImage?.base64Data) {
|
|
197
|
+
const processed = await processGeneratedImage(firstImage.base64Data, firstImage.mimeType || 'image/png', resolvedSavePath, `[EDIT] ${prompt}`, result.description);
|
|
198
|
+
savedPath = processed.savedPath;
|
|
199
|
+
previewPath = processed.previewPath;
|
|
200
|
+
previewImageData = processed.previewImageData;
|
|
201
|
+
}
|
|
202
|
+
// Extract thoughtSignature from response parts for conversational editing
|
|
203
|
+
const thoughtSignature = result.parts.find(p => !!p.thoughtSignature)?.thoughtSignature;
|
|
204
|
+
const textLines = buildTextLines(savedPath, previewPath, result.description, result.groundingSources, thoughtSignature);
|
|
205
|
+
// Serve full-res image via media server (bypasses MCP 1MB limit)
|
|
206
|
+
const imageUrl = savedPath ? ctx.mediaServer.getFileUrl(savedPath) : undefined;
|
|
207
|
+
return {
|
|
208
|
+
structuredContent: {
|
|
209
|
+
imageUrl,
|
|
210
|
+
base64Data: previewImageData || '',
|
|
211
|
+
mimeType: 'image/jpeg',
|
|
212
|
+
savedPath,
|
|
213
|
+
previewPath,
|
|
214
|
+
description: result.description,
|
|
215
|
+
prompt: `[EDIT] ${prompt}`,
|
|
216
|
+
groundingSources: result.groundingSources
|
|
217
|
+
},
|
|
218
|
+
content: [
|
|
219
|
+
{
|
|
220
|
+
type: 'text',
|
|
221
|
+
text: textLines.join('\n') || 'Image edited successfully'
|
|
222
|
+
}
|
|
223
|
+
]
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
catch (error) {
|
|
227
|
+
logger.error('edit_image tool failed', { error });
|
|
228
|
+
const msg = error instanceof McpError
|
|
229
|
+
? error.message
|
|
230
|
+
: `Failed to edit image: ${error.message}`;
|
|
231
|
+
return { content: createToolResult(false, msg, error) };
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
//# sourceMappingURL=register-image-gen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register-image-gen.js","sourceRoot":"","sources":["../../src/tools/register-image-gen.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register-landing-page.d.ts","sourceRoot":"","sources":["../../src/tools/register-landing-page.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,wBAAgB,QAAQ,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAgF/C"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import * as z from 'zod';
|
|
2
|
+
import { registerAppTool } from '@modelcontextprotocol/ext-apps/server';
|
|
3
|
+
import { writeFile, mkdir } from 'fs/promises';
|
|
4
|
+
import { dirname, resolve } from 'path';
|
|
5
|
+
import logger from '../utils/logger.js';
|
|
6
|
+
import { McpError, createToolResult } from '../utils/error-handler.js';
|
|
7
|
+
import { savedFileMessage } from '../utils/tool-wrapper.js';
|
|
8
|
+
import { GenerateLandingPageTool } from './generate-landing-page.js';
|
|
9
|
+
export function register(ctx) {
|
|
10
|
+
const landingPageTool = new GenerateLandingPageTool(ctx.geminiService);
|
|
11
|
+
registerAppTool(ctx.server, 'generate_landing_page', {
|
|
12
|
+
title: 'Generate Landing Page',
|
|
13
|
+
description: 'Generate a complete, self-contained HTML landing page using Gemini. ' +
|
|
14
|
+
'Returns inline preview with responsive viewport controls. ' +
|
|
15
|
+
'No external dependencies; inline CSS and vanilla JS only.',
|
|
16
|
+
inputSchema: {
|
|
17
|
+
brief: z.string().describe('Description of the product/service and page goals'),
|
|
18
|
+
companyName: z.string().optional().describe('Company or product name'),
|
|
19
|
+
primaryColour: z.string().optional().describe('Primary brand colour (e.g. #3B82F6 or "deep blue")'),
|
|
20
|
+
style: z.enum(['minimal', 'bold', 'corporate', 'startup'])
|
|
21
|
+
.optional()
|
|
22
|
+
.default('startup')
|
|
23
|
+
.describe('Visual design style'),
|
|
24
|
+
sections: z.array(z.string())
|
|
25
|
+
.optional()
|
|
26
|
+
.describe('Sections to include (e.g. ["hero", "features", "pricing", "cta"])'),
|
|
27
|
+
model: z.string().optional().describe('Gemini model to use (defaults to configured default)'),
|
|
28
|
+
outputPath: z.string()
|
|
29
|
+
.optional()
|
|
30
|
+
.describe('Optional file path to save the HTML (e.g. C:/dev/output/landing.html)'),
|
|
31
|
+
},
|
|
32
|
+
_meta: {
|
|
33
|
+
ui: { resourceUri: 'ui://gemini/landing-page-viewer.html' }
|
|
34
|
+
}
|
|
35
|
+
}, async ({ brief, companyName, primaryColour, style, sections, model, outputPath }) => {
|
|
36
|
+
try {
|
|
37
|
+
logger.info('Executing generate_landing_page tool', { style, model });
|
|
38
|
+
const html = await landingPageTool.execute({
|
|
39
|
+
brief,
|
|
40
|
+
companyName,
|
|
41
|
+
primaryColour,
|
|
42
|
+
style,
|
|
43
|
+
sections,
|
|
44
|
+
model,
|
|
45
|
+
});
|
|
46
|
+
const absolutePath = outputPath
|
|
47
|
+
? resolve(outputPath)
|
|
48
|
+
: resolve(ctx.outputDir, `gemini-landing-${Date.now()}.html`);
|
|
49
|
+
await mkdir(dirname(absolutePath), { recursive: true });
|
|
50
|
+
await writeFile(absolutePath, html, 'utf-8');
|
|
51
|
+
logger.info('Landing page saved successfully', { savedPath: absolutePath });
|
|
52
|
+
return {
|
|
53
|
+
structuredContent: {
|
|
54
|
+
html,
|
|
55
|
+
savedPath: absolutePath,
|
|
56
|
+
brief,
|
|
57
|
+
companyName
|
|
58
|
+
},
|
|
59
|
+
content: [
|
|
60
|
+
{
|
|
61
|
+
type: 'text',
|
|
62
|
+
text: `${savedFileMessage('Landing page saved', absolutePath)}\n\nOpen this file in your browser to view the landing page.`
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
logger.error('generate_landing_page tool failed', { error });
|
|
69
|
+
const msg = error instanceof McpError
|
|
70
|
+
? error.message
|
|
71
|
+
: `Failed to generate landing page: ${error.message}`;
|
|
72
|
+
return {
|
|
73
|
+
content: createToolResult(false, msg, error),
|
|
74
|
+
structuredContent: { content: msg, success: false },
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=register-landing-page.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register-landing-page.js","sourceRoot":"","sources":["../../src/tools/register-landing-page.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register-list-models.d.ts","sourceRoot":"","sources":["../../src/tools/register-list-models.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,wBAAgB,QAAQ,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAmC/C"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import * as z from 'zod';
|
|
2
|
+
import logger from '../utils/logger.js';
|
|
3
|
+
import { createToolResult } from '../utils/error-handler.js';
|
|
4
|
+
import { toolError } from '../utils/tool-wrapper.js';
|
|
5
|
+
export function register(ctx) {
|
|
6
|
+
ctx.server.registerTool('gemini_list_models', {
|
|
7
|
+
title: 'List Gemini Models',
|
|
8
|
+
description: 'List available Gemini models and their descriptions',
|
|
9
|
+
inputSchema: {},
|
|
10
|
+
outputSchema: {
|
|
11
|
+
content: z.string(),
|
|
12
|
+
success: z.boolean()
|
|
13
|
+
}
|
|
14
|
+
}, async () => {
|
|
15
|
+
try {
|
|
16
|
+
logger.info('Executing gemini_list_models tool');
|
|
17
|
+
const response = await ctx.geminiService.listModels();
|
|
18
|
+
let modelsInfo = 'Available Gemini Models:\n\n';
|
|
19
|
+
for (const model of response.models) {
|
|
20
|
+
modelsInfo += `• **${model.name}**: ${model.description}\n`;
|
|
21
|
+
}
|
|
22
|
+
modelsInfo += `\nLast updated: ${response.timestamp}`;
|
|
23
|
+
return {
|
|
24
|
+
content: createToolResult(true, modelsInfo),
|
|
25
|
+
structuredContent: { content: modelsInfo, success: true }
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
return toolError('gemini_list_models', error);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=register-list-models.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register-list-models.js","sourceRoot":"","sources":["../../src/tools/register-list-models.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AACzB,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAGrD,MAAM,UAAU,QAAQ,CAAC,GAAgB;IACvC,GAAG,CAAC,MAAM,CAAC,YAAY,CACrB,oBAAoB,EACpB;QACE,KAAK,EAAE,oBAAoB;QAC3B,WAAW,EAAE,qDAAqD;QAClE,WAAW,EAAE,EAAE;QACf,YAAY,EAAE;YACZ,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;YACnB,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE;SACrB;KACF,EACD,KAAK,IAAI,EAAE;QACT,IAAI,CAAC;YACH,MAAM,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;YAEjD,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,aAAa,CAAC,UAAU,EAAE,CAAC;YAEtD,IAAI,UAAU,GAAG,8BAA8B,CAAC;YAEhD,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;gBACpC,UAAU,IAAI,OAAO,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,WAAW,IAAI,CAAC;YAC9D,CAAC;YAED,UAAU,IAAI,mBAAmB,QAAQ,CAAC,SAAS,EAAE,CAAC;YAEtD,OAAO;gBACL,OAAO,EAAE,gBAAgB,CAAC,IAAI,EAAE,UAAU,CAAC;gBAC3C,iBAAiB,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE;aAC1D,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,SAAS,CAAC,oBAAoB,EAAE,KAAK,CAAC,CAAC;QAChD,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register-load-image.d.ts","sourceRoot":"","sources":["../../src/tools/register-load-image.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAI9C,wBAAgB,QAAQ,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CA8D/C"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import * as z from 'zod';
|
|
2
|
+
import { stat } from 'fs/promises';
|
|
3
|
+
import { resolve } from 'path';
|
|
4
|
+
import logger from '../utils/logger.js';
|
|
5
|
+
import { createToolResult } from '../utils/error-handler.js';
|
|
6
|
+
import { toolError } from '../utils/tool-wrapper.js';
|
|
7
|
+
const SUPPORTED_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.bmp'];
|
|
8
|
+
export function register(ctx) {
|
|
9
|
+
ctx.server.registerTool('load_image_from_path', {
|
|
10
|
+
title: 'Load Image from File Path',
|
|
11
|
+
description: 'Read a local image file and return it as base64-encoded data ready to pass to ' +
|
|
12
|
+
'generate_image, edit_image, describe_image, or analyze_image tools. ' +
|
|
13
|
+
'Supports JPEG, PNG, GIF, WebP, BMP.',
|
|
14
|
+
inputSchema: {
|
|
15
|
+
filePath: z.string().describe('Absolute or relative path to the image file'),
|
|
16
|
+
},
|
|
17
|
+
outputSchema: {
|
|
18
|
+
content: z.string(),
|
|
19
|
+
success: z.boolean(),
|
|
20
|
+
},
|
|
21
|
+
}, async ({ filePath }) => {
|
|
22
|
+
try {
|
|
23
|
+
logger.info('Executing load_image_from_path tool', { filePath });
|
|
24
|
+
const absolutePath = resolve(filePath);
|
|
25
|
+
const ext = absolutePath.toLowerCase().match(/\.[a-z]+$/)?.[0];
|
|
26
|
+
if (!ext || !SUPPORTED_EXTENSIONS.includes(ext)) {
|
|
27
|
+
throw new Error(`Unsupported image format: ${ext || 'unknown'}. ` +
|
|
28
|
+
`Supported: ${SUPPORTED_EXTENSIONS.join(', ')}`);
|
|
29
|
+
}
|
|
30
|
+
const stats = await stat(absolutePath);
|
|
31
|
+
const sizeBytes = stats.size;
|
|
32
|
+
// Get media server URL for preview display (bypasses MCP transport)
|
|
33
|
+
const imageUrl = ctx.mediaServer.getFileUrl(absolutePath);
|
|
34
|
+
const summary = JSON.stringify({
|
|
35
|
+
filePath: absolutePath,
|
|
36
|
+
mimeType: MIME_MAP[ext] || 'application/octet-stream',
|
|
37
|
+
sizeBytes,
|
|
38
|
+
sizeKB: Math.round(sizeBytes / 1024),
|
|
39
|
+
imageUrl,
|
|
40
|
+
note: 'Pass filePath to edit_image, describe_image, or analyze_image. ' +
|
|
41
|
+
'Images are loaded server-side, bypassing MCP transport limits.',
|
|
42
|
+
});
|
|
43
|
+
logger.info('Image loaded via media server', {
|
|
44
|
+
filePath: absolutePath,
|
|
45
|
+
sizeKB: Math.round(sizeBytes / 1024),
|
|
46
|
+
hasUrl: !!imageUrl,
|
|
47
|
+
});
|
|
48
|
+
return {
|
|
49
|
+
content: createToolResult(true, summary),
|
|
50
|
+
structuredContent: { content: summary, success: true },
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
return toolError('load_image_from_path', error);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
const MIME_MAP = {
|
|
59
|
+
'.jpg': 'image/jpeg',
|
|
60
|
+
'.jpeg': 'image/jpeg',
|
|
61
|
+
'.png': 'image/png',
|
|
62
|
+
'.gif': 'image/gif',
|
|
63
|
+
'.webp': 'image/webp',
|
|
64
|
+
'.bmp': 'image/bmp',
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=register-load-image.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register-load-image.js","sourceRoot":"","sources":["../../src/tools/register-load-image.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register-svg.d.ts","sourceRoot":"","sources":["../../src/tools/register-svg.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,wBAAgB,QAAQ,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAqF/C"}
|