@houtini/gemini-mcp 1.4.5 → 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 -834
- 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/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/package.json +21 -7
- package/server.json +30 -29
|
@@ -0,0 +1,84 @@
|
|
|
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 { GenerateSVGTool } from './generate-svg.js';
|
|
9
|
+
export function register(ctx) {
|
|
10
|
+
const svgTool = new GenerateSVGTool(ctx.geminiService);
|
|
11
|
+
registerAppTool(ctx.server, 'generate_svg', {
|
|
12
|
+
title: 'Generate SVG Graphic',
|
|
13
|
+
description: 'Generate scalable vector graphics (SVG) using Gemini. ' +
|
|
14
|
+
'Creates clean, production-ready SVG code for diagrams, illustrations, icons, and data visualizations. ' +
|
|
15
|
+
'Returns inline preview with SVG viewer.',
|
|
16
|
+
inputSchema: {
|
|
17
|
+
prompt: z.string().describe('Description of the SVG graphic to generate'),
|
|
18
|
+
width: z.number()
|
|
19
|
+
.optional()
|
|
20
|
+
.default(800)
|
|
21
|
+
.describe('SVG width in pixels (default: 800)'),
|
|
22
|
+
height: z.number()
|
|
23
|
+
.optional()
|
|
24
|
+
.default(600)
|
|
25
|
+
.describe('SVG height in pixels (default: 600)'),
|
|
26
|
+
style: z.enum(['technical', 'artistic', 'minimal', 'data-viz'])
|
|
27
|
+
.optional()
|
|
28
|
+
.default('technical')
|
|
29
|
+
.describe('Visual style: technical (diagrams), artistic (illustrations), minimal (simple), data-viz (charts)'),
|
|
30
|
+
model: z.string()
|
|
31
|
+
.optional()
|
|
32
|
+
.describe('Gemini model to use (defaults to configured default)'),
|
|
33
|
+
outputPath: z.string()
|
|
34
|
+
.optional()
|
|
35
|
+
.describe('Optional file path to save the SVG (e.g. C:/output/diagram.svg)'),
|
|
36
|
+
},
|
|
37
|
+
_meta: {
|
|
38
|
+
ui: { resourceUri: 'ui://gemini/svg-viewer.html' }
|
|
39
|
+
}
|
|
40
|
+
}, async ({ prompt, width, height, style, model, outputPath }) => {
|
|
41
|
+
try {
|
|
42
|
+
logger.info('Executing generate_svg tool', { style, dimensions: `${width}x${height}`, model });
|
|
43
|
+
const svgContent = await svgTool.execute({
|
|
44
|
+
prompt,
|
|
45
|
+
width,
|
|
46
|
+
height,
|
|
47
|
+
style,
|
|
48
|
+
model,
|
|
49
|
+
});
|
|
50
|
+
const absolutePath = outputPath
|
|
51
|
+
? resolve(outputPath)
|
|
52
|
+
: resolve(ctx.outputDir, `gemini-${Date.now()}.svg`);
|
|
53
|
+
await mkdir(dirname(absolutePath), { recursive: true });
|
|
54
|
+
await writeFile(absolutePath, svgContent, 'utf-8');
|
|
55
|
+
logger.info('SVG saved successfully', { savedPath: absolutePath });
|
|
56
|
+
return {
|
|
57
|
+
structuredContent: {
|
|
58
|
+
svgContent,
|
|
59
|
+
mimeType: 'image/svg+xml',
|
|
60
|
+
savedPath: absolutePath,
|
|
61
|
+
description: `${style} style SVG graphic (${width}x${height})`,
|
|
62
|
+
prompt
|
|
63
|
+
},
|
|
64
|
+
content: [
|
|
65
|
+
{
|
|
66
|
+
type: 'text',
|
|
67
|
+
text: savedFileMessage('SVG saved', absolutePath)
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
logger.error('generate_svg tool failed', { error });
|
|
74
|
+
const msg = error instanceof McpError
|
|
75
|
+
? error.message
|
|
76
|
+
: `Failed to generate SVG: ${error.message}`;
|
|
77
|
+
return {
|
|
78
|
+
content: createToolResult(false, msg, error),
|
|
79
|
+
structuredContent: { content: msg, success: false },
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=register-svg.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register-svg.js","sourceRoot":"","sources":["../../src/tools/register-svg.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register-video.d.ts","sourceRoot":"","sources":["../../src/tools/register-video.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,wBAAgB,QAAQ,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CA+H/C"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import * as z from 'zod';
|
|
2
|
+
import { registerAppTool } from '@modelcontextprotocol/ext-apps/server';
|
|
3
|
+
import logger from '../utils/logger.js';
|
|
4
|
+
import { toolError } from '../utils/tool-wrapper.js';
|
|
5
|
+
import { GenerateVideoTool } from './generate-video.js';
|
|
6
|
+
import { imageInputSchema } from './schemas.js';
|
|
7
|
+
import { resolveImageInput } from '../utils/resolve-images.js';
|
|
8
|
+
export function register(ctx) {
|
|
9
|
+
registerAppTool(ctx.server, 'generate_video', {
|
|
10
|
+
title: 'Generate Video',
|
|
11
|
+
description: 'Generate videos using Google Veo 3.1 AI model. Creates realistic 4-8 second videos from text prompts ' +
|
|
12
|
+
'with optional first-frame image and reference images for character/style consistency. ' +
|
|
13
|
+
'Supports native audio generation. Processing time: 2-5 minutes for 1080p videos. ' +
|
|
14
|
+
'Returns video file path with optional thumbnail and HTML preview player. ' +
|
|
15
|
+
'\u26a0\ufe0f IMPORTANT: Video generation is ASYNC and takes 2-5 minutes. The tool will poll for completion automatically.',
|
|
16
|
+
inputSchema: {
|
|
17
|
+
prompt: z.string().describe('Detailed description of the video to generate. Be specific about actions, camera movements, lighting, and style. ' +
|
|
18
|
+
'Example: "A close-up shot of a futuristic coffee machine brewing a glowing blue espresso, with steam rising dramatically. Cinematic lighting, 4K quality."'),
|
|
19
|
+
model: z.string().optional().default('veo-3.1-generate-preview')
|
|
20
|
+
.describe('Video generation model (default: veo-3.1-generate-preview)'),
|
|
21
|
+
aspectRatio: z.enum(['16:9', '9:16']).optional().default('16:9')
|
|
22
|
+
.describe('Video aspect ratio: 16:9 (landscape) or 9:16 (portrait/vertical)'),
|
|
23
|
+
resolution: z.enum(['720p', '1080p', '4k']).optional().default('1080p')
|
|
24
|
+
.describe('Video resolution. Higher resolutions take longer to generate and result in larger files.'),
|
|
25
|
+
durationSeconds: z.union([z.literal(4), z.literal(6), z.literal(8)]).optional().default(8)
|
|
26
|
+
.describe('Video duration in seconds (4, 6, or 8 seconds)'),
|
|
27
|
+
generateAudio: z.boolean().optional().default(true)
|
|
28
|
+
.describe('Generate native synchronized audio effects and dialogue based on the prompt'),
|
|
29
|
+
sampleCount: z.number().min(1).max(4).optional().default(1)
|
|
30
|
+
.describe('Number of video samples to generate (1-4). Each sample is a separate generation.'),
|
|
31
|
+
seed: z.number().optional()
|
|
32
|
+
.describe('Optional seed for deterministic output. Use the same seed with the same prompt for consistent results.'),
|
|
33
|
+
outputPath: z.string().optional()
|
|
34
|
+
.describe('Optional custom output path for the video file (e.g., C:/videos/output.mp4). If not provided, saves to default output directory with timestamped filename.'),
|
|
35
|
+
generateThumbnail: z.boolean().optional().default(true)
|
|
36
|
+
.describe('Extract thumbnail from video (requires ffmpeg installed). Thumbnail is saved alongside video.'),
|
|
37
|
+
generateHTMLPlayer: z.boolean().optional().default(true)
|
|
38
|
+
.describe('Generate interactive HTML video player with preview and download options'),
|
|
39
|
+
firstFrameImage: imageInputSchema
|
|
40
|
+
.optional()
|
|
41
|
+
.describe('Starting frame image for image-to-video generation. Provide via filePath (local file) or data+mimeType (base64). ' +
|
|
42
|
+
'The video will animate from this image. Supports JPEG, PNG, WebP.'),
|
|
43
|
+
referenceImages: z.array(z.object({
|
|
44
|
+
referenceType: z.enum(['asset', 'style']).describe('Type of reference: "asset" for character/object consistency, "style" for visual style transfer'),
|
|
45
|
+
image: imageInputSchema.describe('The reference image (filePath or base64 data)')
|
|
46
|
+
}))
|
|
47
|
+
.max(3)
|
|
48
|
+
.optional()
|
|
49
|
+
.describe('Up to 3 reference images for character/style consistency. Each needs a referenceType ("asset" or "style") and an image.')
|
|
50
|
+
},
|
|
51
|
+
_meta: {
|
|
52
|
+
ui: { resourceUri: 'ui://gemini/video-viewer.html' }
|
|
53
|
+
}
|
|
54
|
+
}, async ({ prompt, model, aspectRatio, resolution, durationSeconds, generateAudio, sampleCount, seed, outputPath, generateThumbnail, generateHTMLPlayer, firstFrameImage, referenceImages }) => {
|
|
55
|
+
try {
|
|
56
|
+
logger.info('Executing generate_video tool', {
|
|
57
|
+
prompt: prompt.slice(0, 100),
|
|
58
|
+
duration: durationSeconds || 8,
|
|
59
|
+
resolution: resolution || '1080p',
|
|
60
|
+
hasFirstFrame: !!firstFrameImage,
|
|
61
|
+
referenceImageCount: referenceImages?.length || 0
|
|
62
|
+
});
|
|
63
|
+
// Resolve first-frame image from filePath if provided
|
|
64
|
+
let resolvedFirstFrame;
|
|
65
|
+
if (firstFrameImage) {
|
|
66
|
+
const resolved = await resolveImageInput(firstFrameImage);
|
|
67
|
+
resolvedFirstFrame = { data: resolved.data, mimeType: resolved.mimeType };
|
|
68
|
+
}
|
|
69
|
+
// Resolve reference images from filePaths if provided
|
|
70
|
+
let resolvedReferenceImages;
|
|
71
|
+
if (referenceImages?.length) {
|
|
72
|
+
resolvedReferenceImages = await Promise.all(referenceImages.map(async (ref) => {
|
|
73
|
+
const resolved = await resolveImageInput(ref.image);
|
|
74
|
+
return {
|
|
75
|
+
referenceType: ref.referenceType,
|
|
76
|
+
image: { data: resolved.data, mimeType: resolved.mimeType }
|
|
77
|
+
};
|
|
78
|
+
}));
|
|
79
|
+
}
|
|
80
|
+
const videoTool = new GenerateVideoTool(ctx.geminiService);
|
|
81
|
+
const { content, metadata } = await videoTool.execute({
|
|
82
|
+
prompt,
|
|
83
|
+
model,
|
|
84
|
+
aspectRatio,
|
|
85
|
+
resolution,
|
|
86
|
+
durationSeconds,
|
|
87
|
+
generateAudio,
|
|
88
|
+
sampleCount,
|
|
89
|
+
seed,
|
|
90
|
+
outputPath,
|
|
91
|
+
generateThumbnail,
|
|
92
|
+
generateHTMLPlayer,
|
|
93
|
+
firstFrameImage: resolvedFirstFrame,
|
|
94
|
+
referenceImages: resolvedReferenceImages
|
|
95
|
+
});
|
|
96
|
+
// Enrich with media server URLs for inline playback in the viewer
|
|
97
|
+
const enriched = { ...metadata };
|
|
98
|
+
if (metadata.videoPath) {
|
|
99
|
+
const videoUrl = ctx.mediaServer.getFileUrl(metadata.videoPath);
|
|
100
|
+
if (videoUrl)
|
|
101
|
+
enriched.videoUrl = videoUrl;
|
|
102
|
+
}
|
|
103
|
+
if (metadata.thumbnailPath) {
|
|
104
|
+
const thumbUrl = ctx.mediaServer.getFileUrl(metadata.thumbnailPath);
|
|
105
|
+
if (thumbUrl)
|
|
106
|
+
enriched.thumbnailUrl = thumbUrl;
|
|
107
|
+
}
|
|
108
|
+
return {
|
|
109
|
+
content,
|
|
110
|
+
structuredContent: enriched
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
return toolError('generate_video', error);
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=register-video.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register-video.js","sourceRoot":"","sources":["../../src/tools/register-video.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AACzB,OAAO,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAC;AACxE,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAsB,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAGnF,MAAM,UAAU,QAAQ,CAAC,GAAgB;IACvC,eAAe,CACb,GAAG,CAAC,MAAM,EACV,gBAAgB,EAChB;QACE,KAAK,EAAE,gBAAgB;QACvB,WAAW,EACT,uGAAuG;YACvG,wFAAwF;YACxF,mFAAmF;YACnF,2EAA2E;YAC3E,2HAA2H;QAC7H,WAAW,EAAE;YACX,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CACzB,mHAAmH;gBACnH,4JAA4J,CAC7J;YACD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,0BAA0B,CAAC;iBAC7D,QAAQ,CAAC,4DAA4D,CAAC;YACzE,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC;iBAC7D,QAAQ,CAAC,kEAAkE,CAAC;YAC/E,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC;iBACpE,QAAQ,CAAC,0FAA0F,CAAC;YACvG,eAAe,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;iBACvF,QAAQ,CAAC,gDAAgD,CAAC;YAC7D,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;iBAChD,QAAQ,CAAC,6EAA6E,CAAC;YAC1F,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;iBACxD,QAAQ,CAAC,kFAAkF,CAAC;YAC/F,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;iBACxB,QAAQ,CAAC,wGAAwG,CAAC;YACrH,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;iBAC9B,QAAQ,CAAC,4JAA4J,CAAC;YACzK,iBAAiB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;iBACpD,QAAQ,CAAC,+FAA+F,CAAC;YAC5G,kBAAkB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;iBACrD,QAAQ,CAAC,0EAA0E,CAAC;YACvF,eAAe,EAAE,gBAAgB;iBAC9B,QAAQ,EAAE;iBACV,QAAQ,CACP,mHAAmH;gBACnH,mEAAmE,CACpE;YACH,eAAe,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;gBAChC,aAAa,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,CAChD,gGAAgG,CACjG;gBACD,KAAK,EAAE,gBAAgB,CAAC,QAAQ,CAAC,+CAA+C,CAAC;aAClF,CAAC,CAAC;iBACA,GAAG,CAAC,CAAC,CAAC;iBACN,QAAQ,EAAE;iBACV,QAAQ,CACP,yHAAyH,CAC1H;SACJ;QACD,KAAK,EAAE;YACL,EAAE,EAAE,EAAE,WAAW,EAAE,+BAA+B,EAAE;SACrD;KACF,EACD,KAAK,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,eAAe,EAAE,aAAa,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,eAAe,EAAE,eAAe,EAAE,EAAE,EAAE;QAC3L,IAAI,CAAC;YACH,MAAM,CAAC,IAAI,CAAC,+BAA+B,EAAE;gBAC3C,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;gBAC5B,QAAQ,EAAE,eAAe,IAAI,CAAC;gBAC9B,UAAU,EAAE,UAAU,IAAI,OAAO;gBACjC,aAAa,EAAE,CAAC,CAAC,eAAe;gBAChC,mBAAmB,EAAE,eAAe,EAAE,MAAM,IAAI,CAAC;aAClD,CAAC,CAAC;YAEH,sDAAsD;YACtD,IAAI,kBAAkE,CAAC;YACvE,IAAI,eAAe,EAAE,CAAC;gBACpB,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,eAAsB,CAAC,CAAC;gBACjE,kBAAkB,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC;YAC5E,CAAC;YAED,sDAAsD;YACtD,IAAI,uBAA2H,CAAC;YAChI,IAAI,eAAe,EAAE,MAAM,EAAE,CAAC;gBAC5B,uBAAuB,GAAG,MAAM,OAAO,CAAC,GAAG,CACxC,eAAyB,CAAC,GAAG,CAAC,KAAK,EAAE,GAAQ,EAAE,EAAE;oBAChD,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;oBACpD,OAAO;wBACL,aAAa,EAAE,GAAG,CAAC,aAAkC;wBACrD,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE;qBAC5D,CAAC;gBACJ,CAAC,CAAC,CACH,CAAC;YACJ,CAAC;YAED,MAAM,SAAS,GAAG,IAAI,iBAAiB,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;YAC3D,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC;gBACpD,MAAM;gBACN,KAAK;gBACL,WAAW;gBACX,UAAU;gBACV,eAAe;gBACf,aAAa;gBACb,WAAW;gBACX,IAAI;gBACJ,UAAU;gBACV,iBAAiB;gBACjB,kBAAkB;gBAClB,eAAe,EAAE,kBAAkB;gBACnC,eAAe,EAAE,uBAAuB;aACzC,CAAC,CAAC;YAEH,kEAAkE;YAClE,MAAM,QAAQ,GAAG,EAAE,GAAG,QAAQ,EAA6B,CAAC;YAC5D,IAAI,QAAQ,CAAC,SAAS,EAAE,CAAC;gBACvB,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,CAAC,UAAU,CAAC,QAAQ,CAAC,SAAmB,CAAC,CAAC;gBAC1E,IAAI,QAAQ;oBAAE,QAAQ,CAAC,QAAQ,GAAG,QAAQ,CAAC;YAC7C,CAAC;YACD,IAAI,QAAQ,CAAC,aAAa,EAAE,CAAC;gBAC3B,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,CAAC,UAAU,CAAC,QAAQ,CAAC,aAAuB,CAAC,CAAC;gBAC9E,IAAI,QAAQ;oBAAE,QAAQ,CAAC,YAAY,GAAG,QAAQ,CAAC;YACjD,CAAC;YAED,OAAO;gBACL,OAAO;gBACP,iBAAiB,EAAE,QAAQ;aAC5B,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,8 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
/**
|
|
3
|
+
* Register all MCP App viewer resources from a data-driven spec.
|
|
4
|
+
* When a mediaServerPort is provided, viewers that need it get CSP whitelisting
|
|
5
|
+
* to load media from the localhost server.
|
|
6
|
+
*/
|
|
7
|
+
export declare function registerViewers(server: McpServer, distDir: string, mediaServerPort?: number): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=register-viewers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register-viewers.d.ts","sourceRoot":"","sources":["../../src/tools/register-viewers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA+CpE;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,MAAM,EACf,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC,IAAI,CAAC,CAgEf"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { registerAppResource, RESOURCE_MIME_TYPE } from '@modelcontextprotocol/ext-apps/server';
|
|
2
|
+
import { readFile } from 'fs/promises';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import logger from '../utils/logger.js';
|
|
5
|
+
const VIEWERS = [
|
|
6
|
+
{
|
|
7
|
+
name: 'Image Viewer',
|
|
8
|
+
resourceId: 'gemini-image-viewer',
|
|
9
|
+
uri: 'ui://gemini/image-viewer.html',
|
|
10
|
+
segments: ['image-viewer', 'src', 'ui', 'image-viewer.html'],
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
name: 'Video Viewer',
|
|
14
|
+
resourceId: 'gemini-video-viewer',
|
|
15
|
+
uri: 'ui://gemini/video-viewer.html',
|
|
16
|
+
segments: ['video-viewer', 'src', 'ui', 'video-viewer.html'],
|
|
17
|
+
needsMediaServer: true,
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: 'SVG Viewer',
|
|
21
|
+
resourceId: 'gemini-svg-viewer',
|
|
22
|
+
uri: 'ui://gemini/svg-viewer.html',
|
|
23
|
+
segments: ['svg-viewer', 'src', 'ui', 'svg-viewer.html'],
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: 'Landing Page Viewer',
|
|
27
|
+
resourceId: 'gemini-landing-page-viewer',
|
|
28
|
+
uri: 'ui://gemini/landing-page-viewer.html',
|
|
29
|
+
segments: ['landing-page-viewer', 'src', 'ui', 'landing-page-viewer.html'],
|
|
30
|
+
},
|
|
31
|
+
];
|
|
32
|
+
/**
|
|
33
|
+
* Register all MCP App viewer resources from a data-driven spec.
|
|
34
|
+
* When a mediaServerPort is provided, viewers that need it get CSP whitelisting
|
|
35
|
+
* to load media from the localhost server.
|
|
36
|
+
*/
|
|
37
|
+
export async function registerViewers(server, distDir, mediaServerPort) {
|
|
38
|
+
const mediaOrigin = mediaServerPort
|
|
39
|
+
? `http://127.0.0.1:${mediaServerPort}`
|
|
40
|
+
: undefined;
|
|
41
|
+
const results = await Promise.allSettled(VIEWERS.map(async (v) => {
|
|
42
|
+
const htmlPath = join(distDir, ...v.segments);
|
|
43
|
+
const html = await readFile(htmlPath, 'utf-8');
|
|
44
|
+
// Build CSP metadata for viewers that need media server access
|
|
45
|
+
const needsCsp = v.needsMediaServer && mediaOrigin;
|
|
46
|
+
const contentMeta = needsCsp
|
|
47
|
+
? {
|
|
48
|
+
_meta: {
|
|
49
|
+
ui: {
|
|
50
|
+
csp: {
|
|
51
|
+
resourceDomains: [mediaOrigin],
|
|
52
|
+
connectDomains: [mediaOrigin],
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
}
|
|
57
|
+
: {};
|
|
58
|
+
registerAppResource(server, v.resourceId, v.uri, {}, async () => ({
|
|
59
|
+
contents: [{
|
|
60
|
+
uri: v.uri,
|
|
61
|
+
mimeType: RESOURCE_MIME_TYPE,
|
|
62
|
+
text: html,
|
|
63
|
+
...contentMeta,
|
|
64
|
+
}],
|
|
65
|
+
}));
|
|
66
|
+
return v.name;
|
|
67
|
+
}));
|
|
68
|
+
const succeeded = results
|
|
69
|
+
.filter((r) => r.status === 'fulfilled')
|
|
70
|
+
.map((r) => r.value);
|
|
71
|
+
const failed = results
|
|
72
|
+
.map((r, i) => ({ result: r, spec: VIEWERS[i] }))
|
|
73
|
+
.filter((x) => x.result.status === 'rejected');
|
|
74
|
+
logger.info('Viewer registration complete', {
|
|
75
|
+
succeeded: succeeded.length,
|
|
76
|
+
failed: failed.length,
|
|
77
|
+
available: succeeded,
|
|
78
|
+
mediaServerCsp: mediaOrigin || 'none',
|
|
79
|
+
});
|
|
80
|
+
if (failed.length > 0) {
|
|
81
|
+
for (const { spec, result } of failed) {
|
|
82
|
+
logger.warn(`Failed to load ${spec.name} viewer - inline preview will not be available`, {
|
|
83
|
+
viewer: spec.name,
|
|
84
|
+
error: result.reason,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=register-viewers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register-viewers.js","sourceRoot":"","sources":["../../src/tools/register-viewers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import * as z from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Shared Zod schema for image input, used by describe_image, analyze_image,
|
|
4
|
+
* generate_image (reference images), and edit_image.
|
|
5
|
+
*
|
|
6
|
+
* Images can be provided in two ways:
|
|
7
|
+
* 1. Inline base64: set `data` (base64 string) and `mimeType`
|
|
8
|
+
* 2. File path: set `filePath` — the tool loads the image server-side,
|
|
9
|
+
* bypassing the MCP transport limit entirely.
|
|
10
|
+
*
|
|
11
|
+
* Use `filePath` for large images (>1 MB) to avoid MCP transport failures.
|
|
12
|
+
* The `load_image_from_path` tool returns a filePath you can pass directly.
|
|
13
|
+
*/
|
|
14
|
+
export declare const imageInputSchema: z.ZodObject<{
|
|
15
|
+
data: z.ZodOptional<z.ZodString>;
|
|
16
|
+
filePath: z.ZodOptional<z.ZodString>;
|
|
17
|
+
mimeType: z.ZodOptional<z.ZodString>;
|
|
18
|
+
thoughtSignature: z.ZodOptional<z.ZodString>;
|
|
19
|
+
mediaResolution: z.ZodOptional<z.ZodEnum<["MEDIA_RESOLUTION_LOW", "MEDIA_RESOLUTION_MEDIUM", "MEDIA_RESOLUTION_HIGH", "MEDIA_RESOLUTION_ULTRA_HIGH"]>>;
|
|
20
|
+
}, "strip", z.ZodTypeAny, {
|
|
21
|
+
mimeType?: string;
|
|
22
|
+
data?: string;
|
|
23
|
+
thoughtSignature?: string;
|
|
24
|
+
mediaResolution?: "MEDIA_RESOLUTION_LOW" | "MEDIA_RESOLUTION_MEDIUM" | "MEDIA_RESOLUTION_HIGH" | "MEDIA_RESOLUTION_ULTRA_HIGH";
|
|
25
|
+
filePath?: string;
|
|
26
|
+
}, {
|
|
27
|
+
mimeType?: string;
|
|
28
|
+
data?: string;
|
|
29
|
+
thoughtSignature?: string;
|
|
30
|
+
mediaResolution?: "MEDIA_RESOLUTION_LOW" | "MEDIA_RESOLUTION_MEDIUM" | "MEDIA_RESOLUTION_HIGH" | "MEDIA_RESOLUTION_ULTRA_HIGH";
|
|
31
|
+
filePath?: string;
|
|
32
|
+
}>;
|
|
33
|
+
//# sourceMappingURL=schemas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../src/tools/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAEzB;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;EA8B3B,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as z from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Shared Zod schema for image input, used by describe_image, analyze_image,
|
|
4
|
+
* generate_image (reference images), and edit_image.
|
|
5
|
+
*
|
|
6
|
+
* Images can be provided in two ways:
|
|
7
|
+
* 1. Inline base64: set `data` (base64 string) and `mimeType`
|
|
8
|
+
* 2. File path: set `filePath` — the tool loads the image server-side,
|
|
9
|
+
* bypassing the MCP transport limit entirely.
|
|
10
|
+
*
|
|
11
|
+
* Use `filePath` for large images (>1 MB) to avoid MCP transport failures.
|
|
12
|
+
* The `load_image_from_path` tool returns a filePath you can pass directly.
|
|
13
|
+
*/
|
|
14
|
+
export const imageInputSchema = z.object({
|
|
15
|
+
data: z.string()
|
|
16
|
+
.optional()
|
|
17
|
+
.describe('Base64 encoded image data'),
|
|
18
|
+
filePath: z.string()
|
|
19
|
+
.optional()
|
|
20
|
+
.describe('Local file path to the image (alternative to base64 data). ' +
|
|
21
|
+
'The image is loaded server-side, bypassing MCP transport limits. ' +
|
|
22
|
+
'Use the filePath returned by load_image_from_path.'),
|
|
23
|
+
mimeType: z.string()
|
|
24
|
+
.optional()
|
|
25
|
+
.describe('MIME type of the image (e.g., image/png, image/jpeg). Required when using data, auto-detected from filePath.'),
|
|
26
|
+
thoughtSignature: z.string()
|
|
27
|
+
.optional()
|
|
28
|
+
.describe('Thought signature from a previous generate_image or edit_image call. ' +
|
|
29
|
+
'Required for conversational editing with Gemini 3 Pro Image. ' +
|
|
30
|
+
'Pass the thoughtSignature from the previous response to maintain edit context.'),
|
|
31
|
+
mediaResolution: z.enum([
|
|
32
|
+
'MEDIA_RESOLUTION_LOW',
|
|
33
|
+
'MEDIA_RESOLUTION_MEDIUM',
|
|
34
|
+
'MEDIA_RESOLUTION_HIGH',
|
|
35
|
+
'MEDIA_RESOLUTION_ULTRA_HIGH'
|
|
36
|
+
]).optional().describe('Per-image resolution override. LOW=280 tokens (75% savings), MEDIUM=560 tokens (50% savings), ' +
|
|
37
|
+
'HIGH=1120 tokens (default), ULTRA_HIGH=2000+ tokens (max detail, per-image only)')
|
|
38
|
+
});
|
|
39
|
+
//# sourceMappingURL=schemas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../src/tools/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAEzB;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;SACb,QAAQ,EAAE;SACV,QAAQ,CAAC,2BAA2B,CAAC;IACxC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;SACjB,QAAQ,EAAE;SACV,QAAQ,CACP,6DAA6D;QAC7D,mEAAmE;QACnE,oDAAoD,CACrD;IACH,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;SACjB,QAAQ,EAAE;SACV,QAAQ,CAAC,8GAA8G,CAAC;IAC3H,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE;SACzB,QAAQ,EAAE;SACV,QAAQ,CACP,uEAAuE;QACvE,+DAA+D;QAC/D,gFAAgF,CACjF;IACH,eAAe,EAAE,CAAC,CAAC,IAAI,CAAC;QACtB,sBAAsB;QACtB,yBAAyB;QACzB,uBAAuB;QACvB,6BAA6B;KAC9B,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CACpB,gGAAgG;QAChG,kFAAkF,CACnF;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { GeminiService } from '../services/gemini/index.js';
|
|
3
|
+
import { GeminiImageService } from '../services/gemini/image-service.js';
|
|
4
|
+
import { MediaServer } from '../services/media-server.js';
|
|
5
|
+
export interface ToolContext {
|
|
6
|
+
server: McpServer;
|
|
7
|
+
geminiService: GeminiService;
|
|
8
|
+
imageService: GeminiImageService;
|
|
9
|
+
outputDir: string;
|
|
10
|
+
mediaServer: MediaServer;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/tools/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAE1D,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,SAAS,CAAC;IAClB,aAAa,EAAE,aAAa,CAAC;IAC7B,YAAY,EAAE,kBAAkB,CAAC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,WAAW,CAAC;CAC1B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/tools/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-viewer.d.ts","sourceRoot":"","sources":["../../src/ui/image-viewer.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { App } from '@modelcontextprotocol/ext-apps';
|
|
2
|
+
const app = new App({ name: 'Gemini Image Viewer', version: '1.0.0' });
|
|
3
|
+
app.ontoolresult = (result) => {
|
|
4
|
+
const data = result.structuredContent;
|
|
5
|
+
if (!data || !data.base64Data)
|
|
6
|
+
return;
|
|
7
|
+
render(data);
|
|
8
|
+
};
|
|
9
|
+
app.connect();
|
|
10
|
+
function render(data) {
|
|
11
|
+
const loading = document.getElementById('loading');
|
|
12
|
+
const content = document.getElementById('content');
|
|
13
|
+
const img = document.getElementById('img');
|
|
14
|
+
const pathDisplay = document.getElementById('path-display');
|
|
15
|
+
const copyBtn = document.getElementById('copy-btn');
|
|
16
|
+
const descEl = document.getElementById('desc');
|
|
17
|
+
img.src = `data:${data.mimeType};base64,${data.base64Data}`;
|
|
18
|
+
if (data.savedPath) {
|
|
19
|
+
pathDisplay.textContent = data.savedPath;
|
|
20
|
+
copyBtn.style.display = 'block';
|
|
21
|
+
copyBtn.addEventListener('click', () => {
|
|
22
|
+
navigator.clipboard.writeText(data.savedPath).then(() => {
|
|
23
|
+
copyBtn.textContent = 'Copied!';
|
|
24
|
+
copyBtn.classList.add('copied');
|
|
25
|
+
setTimeout(() => {
|
|
26
|
+
copyBtn.textContent = 'Copy path';
|
|
27
|
+
copyBtn.classList.remove('copied');
|
|
28
|
+
}, 2000);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
pathDisplay.innerHTML = '<span class="no-path">Not saved to disk</span>';
|
|
34
|
+
}
|
|
35
|
+
if (data.description) {
|
|
36
|
+
descEl.textContent = data.description;
|
|
37
|
+
descEl.style.display = 'block';
|
|
38
|
+
}
|
|
39
|
+
loading.style.display = 'none';
|
|
40
|
+
content.style.display = 'block';
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=image-viewer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-viewer.js","sourceRoot":"","sources":["../../src/ui/image-viewer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,gCAAgC,CAAC;AASrD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,EAAE,IAAI,EAAE,qBAAqB,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;AAEvE,GAAG,CAAC,YAAY,GAAG,CAAC,MAA2C,EAAE,EAAE;IACjE,MAAM,IAAI,GAAG,MAAM,CAAC,iBAAiB,CAAC;IACtC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU;QAAE,OAAO;IACtC,MAAM,CAAC,IAAI,CAAC,CAAC;AACf,CAAC,CAAC;AAEF,GAAG,CAAC,OAAO,EAAE,CAAC;AAEd,SAAS,MAAM,CAAC,IAAiB;IAC/B,MAAM,OAAO,GAAG,QAAQ,CAAC,cAAc,CAAC,SAAS,CAAE,CAAC;IACpD,MAAM,OAAO,GAAG,QAAQ,CAAC,cAAc,CAAC,SAAS,CAAE,CAAC;IACpD,MAAM,GAAG,GAAG,QAAQ,CAAC,cAAc,CAAC,KAAK,CAAqB,CAAC;IAC/D,MAAM,WAAW,GAAG,QAAQ,CAAC,cAAc,CAAC,cAAc,CAAE,CAAC;IAC7D,MAAM,OAAO,GAAG,QAAQ,CAAC,cAAc,CAAC,UAAU,CAAsB,CAAC;IACzE,MAAM,MAAM,GAAG,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAE,CAAC;IAEhD,GAAG,CAAC,GAAG,GAAG,QAAQ,IAAI,CAAC,QAAQ,WAAW,IAAI,CAAC,UAAU,EAAE,CAAC;IAE5D,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,WAAW,CAAC,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC;QACzC,OAAO,CAAC,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC;QAChC,OAAO,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE;YACrC,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,SAAU,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;gBACvD,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC;gBAChC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;gBAChC,UAAU,CAAC,GAAG,EAAE;oBACd,OAAO,CAAC,WAAW,GAAG,WAAW,CAAC;oBAClC,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBACrC,CAAC,EAAE,IAAI,CAAC,CAAC;YACX,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;SAAM,CAAC;QACN,WAAW,CAAC,SAAS,GAAG,gDAAgD,CAAC;IAC3E,CAAC;IAED,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;QACrB,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;QACtC,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC;IACjC,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC;IAC/B,OAAO,CAAC,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC;AAClC,CAAC"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Professional Chart & Data Visualization Design System
|
|
3
|
+
*
|
|
4
|
+
* Based on research from Observable, D3.js, Information is Beautiful,
|
|
5
|
+
* and modern dashboard design systems.
|
|
6
|
+
*
|
|
7
|
+
* Purpose: Enhance prompts with professional design principles to avoid
|
|
8
|
+
* generic AI-generated aesthetics.
|
|
9
|
+
*/
|
|
10
|
+
export interface ChartStyleOptions {
|
|
11
|
+
colorScheme?: 'professional' | 'editorial' | 'scientific' | 'minimal' | 'dark';
|
|
12
|
+
chartType?: 'line' | 'bar' | 'scatter' | 'area' | 'pie' | 'network' | 'heatmap' | 'treemap';
|
|
13
|
+
emphasis?: 'data-ink' | 'storytelling' | 'exploration' | 'presentation';
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Professional color palettes based on industry standards
|
|
17
|
+
*/
|
|
18
|
+
declare const COLOR_SYSTEMS: {
|
|
19
|
+
professional: {
|
|
20
|
+
primary: string[];
|
|
21
|
+
neutral: string[];
|
|
22
|
+
accent: string[];
|
|
23
|
+
description: string;
|
|
24
|
+
};
|
|
25
|
+
editorial: {
|
|
26
|
+
primary: string[];
|
|
27
|
+
neutral: string[];
|
|
28
|
+
accent: string[];
|
|
29
|
+
description: string;
|
|
30
|
+
};
|
|
31
|
+
scientific: {
|
|
32
|
+
primary: string[];
|
|
33
|
+
neutral: string[];
|
|
34
|
+
accent: string[];
|
|
35
|
+
description: string;
|
|
36
|
+
};
|
|
37
|
+
minimal: {
|
|
38
|
+
primary: string[];
|
|
39
|
+
neutral: string[];
|
|
40
|
+
accent: string[];
|
|
41
|
+
description: string;
|
|
42
|
+
};
|
|
43
|
+
dark: {
|
|
44
|
+
primary: string[];
|
|
45
|
+
neutral: string[];
|
|
46
|
+
accent: string[];
|
|
47
|
+
description: string;
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Generate professional design prompt enhancement
|
|
52
|
+
*/
|
|
53
|
+
export declare function enhanceChartPrompt(basePrompt: string, options?: ChartStyleOptions): string;
|
|
54
|
+
/**
|
|
55
|
+
* Get color palette for a specific scheme
|
|
56
|
+
*/
|
|
57
|
+
export declare function getColorPalette(scheme: keyof typeof COLOR_SYSTEMS): {
|
|
58
|
+
primary: string[];
|
|
59
|
+
neutral: string[];
|
|
60
|
+
accent: string[];
|
|
61
|
+
description: string;
|
|
62
|
+
} | {
|
|
63
|
+
primary: string[];
|
|
64
|
+
neutral: string[];
|
|
65
|
+
accent: string[];
|
|
66
|
+
description: string;
|
|
67
|
+
} | {
|
|
68
|
+
primary: string[];
|
|
69
|
+
neutral: string[];
|
|
70
|
+
accent: string[];
|
|
71
|
+
description: string;
|
|
72
|
+
} | {
|
|
73
|
+
primary: string[];
|
|
74
|
+
neutral: string[];
|
|
75
|
+
accent: string[];
|
|
76
|
+
description: string;
|
|
77
|
+
} | {
|
|
78
|
+
primary: string[];
|
|
79
|
+
neutral: string[];
|
|
80
|
+
accent: string[];
|
|
81
|
+
description: string;
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Validate chart design prompt for common issues
|
|
85
|
+
*/
|
|
86
|
+
export declare function validateChartPrompt(prompt: string): {
|
|
87
|
+
valid: boolean;
|
|
88
|
+
warnings: string[];
|
|
89
|
+
suggestions: string[];
|
|
90
|
+
};
|
|
91
|
+
export {};
|
|
92
|
+
//# sourceMappingURL=chart-design-system.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chart-design-system.d.ts","sourceRoot":"","sources":["../../src/utils/chart-design-system.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,iBAAiB;IAChC,WAAW,CAAC,EAAE,cAAc,GAAG,WAAW,GAAG,YAAY,GAAG,SAAS,GAAG,MAAM,CAAC;IAC/E,SAAS,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;IAC5F,QAAQ,CAAC,EAAE,UAAU,GAAG,cAAc,GAAG,aAAa,GAAG,cAAc,CAAC;CACzE;AAED;;GAEG;AACH,QAAA,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+BlB,CAAC;AA+GF;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,iBAAsB,GAC9B,MAAM,CAuDR;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,OAAO,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;EAEjE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG;IACnD,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB,CA4BA"}
|