@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.
Files changed (171) hide show
  1. package/README.md +314 -784
  2. package/claude_desktop_config_example.json +1 -0
  3. package/dist/config/index.d.ts.map +1 -1
  4. package/dist/config/index.js +8 -4
  5. package/dist/config/index.js.map +1 -1
  6. package/dist/config/types.d.ts +5 -0
  7. package/dist/config/types.d.ts.map +1 -1
  8. package/dist/image-viewer/image-viewer-app.html +180 -0
  9. package/dist/image-viewer/src/ui/image-viewer.html +324 -0
  10. package/dist/index-new.d.ts +3 -0
  11. package/dist/index-new.d.ts.map +1 -0
  12. package/dist/index-new.js +7 -0
  13. package/dist/index-new.js.map +1 -0
  14. package/dist/index.d.ts +3 -1
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +70 -172
  17. package/dist/index.js.map +1 -1
  18. package/dist/landing-page-viewer/src/ui/landing-page-viewer.html +330 -0
  19. package/dist/services/gemini/export.d.ts +5 -0
  20. package/dist/services/gemini/export.d.ts.map +1 -0
  21. package/dist/services/gemini/export.js +5 -0
  22. package/dist/services/gemini/export.js.map +1 -0
  23. package/dist/services/gemini/image-service.d.ts +45 -0
  24. package/dist/services/gemini/image-service.d.ts.map +1 -0
  25. package/dist/services/gemini/image-service.js +248 -0
  26. package/dist/services/gemini/image-service.js.map +1 -0
  27. package/dist/services/gemini/index.d.ts +7 -2
  28. package/dist/services/gemini/index.d.ts.map +1 -1
  29. package/dist/services/gemini/index.js +132 -56
  30. package/dist/services/gemini/index.js.map +1 -1
  31. package/dist/services/gemini/types.d.ts +32 -0
  32. package/dist/services/gemini/types.d.ts.map +1 -1
  33. package/dist/services/gemini/video-service.d.ts +58 -0
  34. package/dist/services/gemini/video-service.d.ts.map +1 -0
  35. package/dist/services/gemini/video-service.js +325 -0
  36. package/dist/services/gemini/video-service.js.map +1 -0
  37. package/dist/services/media-server.d.ts +28 -0
  38. package/dist/services/media-server.d.ts.map +1 -0
  39. package/dist/services/media-server.js +195 -0
  40. package/dist/services/media-server.js.map +1 -0
  41. package/dist/svg-viewer/src/ui/svg-viewer.html +325 -0
  42. package/dist/tools/gemini-chat.d.ts.map +1 -1
  43. package/dist/tools/gemini-chat.js +7 -1
  44. package/dist/tools/gemini-chat.js.map +1 -1
  45. package/dist/tools/gemini-deep-research.d.ts +1 -2
  46. package/dist/tools/gemini-deep-research.d.ts.map +1 -1
  47. package/dist/tools/gemini-deep-research.js +11 -51
  48. package/dist/tools/gemini-deep-research.js.map +1 -1
  49. package/dist/tools/gemini-help.d.ts +3 -0
  50. package/dist/tools/gemini-help.d.ts.map +1 -0
  51. package/dist/tools/gemini-help.js +534 -0
  52. package/dist/tools/gemini-help.js.map +1 -0
  53. package/dist/tools/gemini-prompt-assistant.d.ts +20 -0
  54. package/dist/tools/gemini-prompt-assistant.d.ts.map +1 -0
  55. package/dist/tools/gemini-prompt-assistant.js +129 -0
  56. package/dist/tools/gemini-prompt-assistant.js.map +1 -0
  57. package/dist/tools/generate-landing-page.d.ts +15 -0
  58. package/dist/tools/generate-landing-page.d.ts.map +1 -0
  59. package/dist/tools/generate-landing-page.js +66 -0
  60. package/dist/tools/generate-landing-page.js.map +1 -0
  61. package/dist/tools/generate-svg.d.ts +14 -0
  62. package/dist/tools/generate-svg.d.ts.map +1 -0
  63. package/dist/tools/generate-svg.js +106 -0
  64. package/dist/tools/generate-svg.js.map +1 -0
  65. package/dist/tools/generate-video.d.ts +24 -0
  66. package/dist/tools/generate-video.d.ts.map +1 -0
  67. package/dist/tools/generate-video.js +163 -0
  68. package/dist/tools/generate-video.js.map +1 -0
  69. package/dist/tools/image-prompt-assistant.d.ts +3 -0
  70. package/dist/tools/image-prompt-assistant.d.ts.map +1 -0
  71. package/dist/tools/image-prompt-assistant.js +790 -0
  72. package/dist/tools/image-prompt-assistant.js.map +1 -0
  73. package/dist/tools/load-image-from-path.d.ts +11 -0
  74. package/dist/tools/load-image-from-path.d.ts.map +1 -0
  75. package/dist/tools/load-image-from-path.js +100 -0
  76. package/dist/tools/load-image-from-path.js.map +1 -0
  77. package/dist/tools/prompt-library/charts.d.ts +325 -0
  78. package/dist/tools/prompt-library/charts.d.ts.map +1 -0
  79. package/dist/tools/prompt-library/charts.js +384 -0
  80. package/dist/tools/prompt-library/charts.js.map +1 -0
  81. package/dist/tools/prompt-library/index.d.ts +8 -0
  82. package/dist/tools/prompt-library/index.d.ts.map +1 -0
  83. package/dist/tools/prompt-library/index.js +10 -0
  84. package/dist/tools/prompt-library/index.js.map +1 -0
  85. package/dist/tools/register-analyze-image.d.ts +3 -0
  86. package/dist/tools/register-analyze-image.d.ts.map +1 -0
  87. package/dist/tools/register-analyze-image.js +67 -0
  88. package/dist/tools/register-analyze-image.js.map +1 -0
  89. package/dist/tools/register-chat.d.ts +3 -0
  90. package/dist/tools/register-chat.d.ts.map +1 -0
  91. package/dist/tools/register-chat.js +71 -0
  92. package/dist/tools/register-chat.js.map +1 -0
  93. package/dist/tools/register-deep-research.d.ts +3 -0
  94. package/dist/tools/register-deep-research.d.ts.map +1 -0
  95. package/dist/tools/register-deep-research.js +59 -0
  96. package/dist/tools/register-deep-research.js.map +1 -0
  97. package/dist/tools/register-describe-image.d.ts +3 -0
  98. package/dist/tools/register-describe-image.d.ts.map +1 -0
  99. package/dist/tools/register-describe-image.js +59 -0
  100. package/dist/tools/register-describe-image.js.map +1 -0
  101. package/dist/tools/register-image-gen.d.ts +3 -0
  102. package/dist/tools/register-image-gen.d.ts.map +1 -0
  103. package/dist/tools/register-image-gen.js +235 -0
  104. package/dist/tools/register-image-gen.js.map +1 -0
  105. package/dist/tools/register-landing-page.d.ts +3 -0
  106. package/dist/tools/register-landing-page.d.ts.map +1 -0
  107. package/dist/tools/register-landing-page.js +79 -0
  108. package/dist/tools/register-landing-page.js.map +1 -0
  109. package/dist/tools/register-list-models.d.ts +3 -0
  110. package/dist/tools/register-list-models.d.ts.map +1 -0
  111. package/dist/tools/register-list-models.js +33 -0
  112. package/dist/tools/register-list-models.js.map +1 -0
  113. package/dist/tools/register-load-image.d.ts +3 -0
  114. package/dist/tools/register-load-image.d.ts.map +1 -0
  115. package/dist/tools/register-load-image.js +66 -0
  116. package/dist/tools/register-load-image.js.map +1 -0
  117. package/dist/tools/register-svg.d.ts +3 -0
  118. package/dist/tools/register-svg.d.ts.map +1 -0
  119. package/dist/tools/register-svg.js +84 -0
  120. package/dist/tools/register-svg.js.map +1 -0
  121. package/dist/tools/register-video.d.ts +3 -0
  122. package/dist/tools/register-video.d.ts.map +1 -0
  123. package/dist/tools/register-video.js +118 -0
  124. package/dist/tools/register-video.js.map +1 -0
  125. package/dist/tools/register-viewers.d.ts +8 -0
  126. package/dist/tools/register-viewers.d.ts.map +1 -0
  127. package/dist/tools/register-viewers.js +89 -0
  128. package/dist/tools/register-viewers.js.map +1 -0
  129. package/dist/tools/schemas.d.ts +33 -0
  130. package/dist/tools/schemas.d.ts.map +1 -0
  131. package/dist/tools/schemas.js +39 -0
  132. package/dist/tools/schemas.js.map +1 -0
  133. package/dist/tools/types.d.ts +12 -0
  134. package/dist/tools/types.d.ts.map +1 -0
  135. package/dist/tools/types.js +2 -0
  136. package/dist/tools/types.js.map +1 -0
  137. package/dist/ui/image-viewer.d.ts +2 -0
  138. package/dist/ui/image-viewer.d.ts.map +1 -0
  139. package/dist/ui/image-viewer.js +42 -0
  140. package/dist/ui/image-viewer.js.map +1 -0
  141. package/dist/utils/chart-design-system.d.ts +92 -0
  142. package/dist/utils/chart-design-system.d.ts.map +1 -0
  143. package/dist/utils/chart-design-system.js +235 -0
  144. package/dist/utils/chart-design-system.js.map +1 -0
  145. package/dist/utils/image-compress.d.ts +9 -0
  146. package/dist/utils/image-compress.d.ts.map +1 -0
  147. package/dist/utils/image-compress.js +43 -0
  148. package/dist/utils/image-compress.js.map +1 -0
  149. package/dist/utils/image-utils.d.ts +9 -0
  150. package/dist/utils/image-utils.d.ts.map +1 -0
  151. package/dist/utils/image-utils.js +257 -0
  152. package/dist/utils/image-utils.js.map +1 -0
  153. package/dist/utils/logger.d.ts.map +1 -1
  154. package/dist/utils/logger.js +45 -11
  155. package/dist/utils/logger.js.map +1 -1
  156. package/dist/utils/resolve-images.d.ts +29 -0
  157. package/dist/utils/resolve-images.d.ts.map +1 -0
  158. package/dist/utils/resolve-images.js +56 -0
  159. package/dist/utils/resolve-images.js.map +1 -0
  160. package/dist/utils/tool-wrapper.d.ts +13 -0
  161. package/dist/utils/tool-wrapper.d.ts.map +1 -0
  162. package/dist/utils/tool-wrapper.js +22 -0
  163. package/dist/utils/tool-wrapper.js.map +1 -0
  164. package/dist/utils/video-utils.d.ts +16 -0
  165. package/dist/utils/video-utils.d.ts.map +1 -0
  166. package/dist/utils/video-utils.js +319 -0
  167. package/dist/utils/video-utils.js.map +1 -0
  168. package/dist/video-viewer/src/ui/video-viewer.html +310 -0
  169. package/houtini-logo.jpg +0 -0
  170. package/package.json +24 -8
  171. package/server.json +30 -0
@@ -5,6 +5,7 @@
5
5
  "args": ["C:\\path\\to\\gemini-mcp\\dist\\index.js"],
6
6
  "env": {
7
7
  "GEMINI_API_KEY": "your-api-key-here",
8
+ "GEMINI_IMAGE_OUTPUT_DIR": "C:\\Users\\YourName\\Pictures\\gemini-images",
8
9
  "LOG_LEVEL": "info"
9
10
  }
10
11
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAKpC,eAAO,MAAM,MAAM,EAAE,MAmCpB,CAAC;AAEF,wBAAgB,cAAc,IAAI,IAAI,CAOrC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAKpC,eAAO,MAAM,MAAM,EAAE,MAuCpB,CAAC;AAEF,wBAAgB,cAAc,IAAI,IAAI,CAOrC"}
@@ -21,15 +21,19 @@ export const config = {
21
21
  threshold: 'BLOCK_MEDIUM_AND_ABOVE'
22
22
  }
23
23
  ],
24
- defaultModel: 'gemini-3-pro-preview',
25
- maxTokens: 16384,
26
- temperature: 0.7,
24
+ defaultModel: 'gemini-3.1-pro-preview', // chat / text
25
+ defaultImageAnalysisModel: 'gemini-3.1-pro-preview', // analyze_image
26
+ defaultImageDescribeModel: 'gemini-3.1-pro-preview', // describe_image
27
+ defaultImageGenerationModel: 'gemini-3-pro-image-preview', // generate_image / edit_image
28
+ maxTokens: 65536,
29
+ temperature: 1.0,
27
30
  defaultGrounding: true,
28
31
  allowExperimentalModels: process.env.GEMINI_ALLOW_EXPERIMENTAL === 'true'
29
32
  },
30
33
  server: {
31
34
  name: 'gemini-mcp',
32
- version: '1.0.0'
35
+ version: '2.2.0',
36
+ imageOutputDir: process.env.GEMINI_IMAGE_OUTPUT_DIR
33
37
  },
34
38
  logging: {
35
39
  level: process.env.LOG_LEVEL || 'info',
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AAEjC,MAAM,CAAC,MAAM,EAAE,CAAC;AAEhB,MAAM,CAAC,MAAM,MAAM,GAAW;IAC5B,MAAM,EAAE;QACN,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc;QAClC,cAAc,EAAE;YACd;gBACE,QAAQ,EAAE,0BAA0B;gBACpC,SAAS,EAAE,wBAAwB;aACpC;YACD;gBACE,QAAQ,EAAE,2BAA2B;gBACrC,SAAS,EAAE,wBAAwB;aACpC;YACD;gBACE,QAAQ,EAAE,iCAAiC;gBAC3C,SAAS,EAAE,wBAAwB;aACpC;YACD;gBACE,QAAQ,EAAE,iCAAiC;gBAC3C,SAAS,EAAE,wBAAwB;aACpC;SACF;QACD,YAAY,EAAE,sBAAsB;QACpC,SAAS,EAAE,KAAK;QAChB,WAAW,EAAE,GAAG;QAChB,gBAAgB,EAAE,IAAI;QACtB,uBAAuB,EAAE,OAAO,CAAC,GAAG,CAAC,yBAAyB,KAAK,MAAM;KAC1E;IACD,MAAM,EAAE;QACN,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,OAAO;KACjB;IACD,OAAO,EAAE;QACP,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,MAAM;QACtC,MAAM,EAAE,UAAU;KACnB;CACF,CAAC;AAEF,MAAM,UAAU,cAAc;IAC5B,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CACb,+CAA+C;YAC/C,yEAAyE,CAC1E,CAAC;IACJ,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AAEjC,MAAM,CAAC,MAAM,EAAE,CAAC;AAEhB,MAAM,CAAC,MAAM,MAAM,GAAW;IAC5B,MAAM,EAAE;QACN,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc;QAClC,cAAc,EAAE;YACd;gBACE,QAAQ,EAAE,0BAA0B;gBACpC,SAAS,EAAE,wBAAwB;aACpC;YACD;gBACE,QAAQ,EAAE,2BAA2B;gBACrC,SAAS,EAAE,wBAAwB;aACpC;YACD;gBACE,QAAQ,EAAE,iCAAiC;gBAC3C,SAAS,EAAE,wBAAwB;aACpC;YACD;gBACE,QAAQ,EAAE,iCAAiC;gBAC3C,SAAS,EAAE,wBAAwB;aACpC;SACF;QACD,YAAY,EAAE,wBAAwB,EAAgB,cAAc;QACpE,yBAAyB,EAAE,wBAAwB,EAAE,gBAAgB;QACrE,yBAAyB,EAAE,wBAAwB,EAAE,iBAAiB;QACtE,2BAA2B,EAAE,4BAA4B,EAAE,8BAA8B;QACzF,SAAS,EAAE,KAAK;QAChB,WAAW,EAAE,GAAG;QAChB,gBAAgB,EAAE,IAAI;QACtB,uBAAuB,EAAE,OAAO,CAAC,GAAG,CAAC,yBAAyB,KAAK,MAAM;KAC1E;IACD,MAAM,EAAE;QACN,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,OAAO;QAChB,cAAc,EAAE,OAAO,CAAC,GAAG,CAAC,uBAAuB;KACpD;IACD,OAAO,EAAE;QACP,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,MAAM;QACtC,MAAM,EAAE,UAAU;KACnB;CACF,CAAC;AAEF,MAAM,UAAU,cAAc;IAC5B,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CACb,+CAA+C;YAC/C,yEAAyE,CAC1E,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -2,10 +2,14 @@ export interface SafetySetting {
2
2
  category: string;
3
3
  threshold: string;
4
4
  }
5
+ export type ThinkingLevel = 'low' | 'medium' | 'high' | 'minimal';
5
6
  export interface GeminiConfig {
6
7
  apiKey?: string;
7
8
  safetySettings: SafetySetting[];
8
9
  defaultModel: string;
10
+ defaultImageAnalysisModel: string;
11
+ defaultImageDescribeModel: string;
12
+ defaultImageGenerationModel: string;
9
13
  maxTokens: number;
10
14
  temperature: number;
11
15
  defaultGrounding: boolean;
@@ -14,6 +18,7 @@ export interface GeminiConfig {
14
18
  export interface ServerConfig {
15
19
  name: string;
16
20
  version: string;
21
+ imageOutputDir?: string;
17
22
  }
18
23
  export interface Config {
19
24
  gemini: GeminiConfig;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,MAAM;IACrB,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;AAElE,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,aAAa,EAAE,CAAC;IAEhC,YAAY,EAAE,MAAM,CAAC;IACrB,yBAAyB,EAAE,MAAM,CAAC;IAClC,yBAAyB,EAAE,MAAM,CAAC;IAClC,2BAA2B,EAAE,MAAM,CAAC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,MAAM;IACrB,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH"}
@@ -0,0 +1,180 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Gemini Image Viewer</title>
7
+ <style>
8
+ * { box-sizing: border-box; margin: 0; padding: 0; }
9
+
10
+ body {
11
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
12
+ background: #0f0f0f;
13
+ color: #e8e8e8;
14
+ min-height: 100vh;
15
+ display: flex;
16
+ flex-direction: column;
17
+ align-items: center;
18
+ padding: 20px;
19
+ gap: 16px;
20
+ }
21
+
22
+ #loading {
23
+ margin-top: 60px;
24
+ color: #666;
25
+ font-size: 14px;
26
+ text-align: center;
27
+ }
28
+
29
+ #content { display: none; width: 100%; max-width: 900px; }
30
+
31
+ .image-wrap {
32
+ width: 100%;
33
+ border-radius: 8px;
34
+ overflow: hidden;
35
+ box-shadow: 0 4px 32px rgba(0,0,0,0.6);
36
+ }
37
+
38
+ img { width: 100%; height: auto; display: block; }
39
+
40
+ .meta {
41
+ width: 100%;
42
+ background: #1a1a1a;
43
+ border-radius: 8px;
44
+ padding: 14px 16px;
45
+ font-size: 13px;
46
+ line-height: 1.6;
47
+ margin-top: 12px;
48
+ }
49
+
50
+ .path {
51
+ font-family: 'Menlo', 'Consolas', monospace;
52
+ font-size: 12px;
53
+ color: #6ee7b7;
54
+ word-break: break-all;
55
+ }
56
+
57
+ .meta-row {
58
+ display: flex;
59
+ align-items: flex-start;
60
+ justify-content: space-between;
61
+ gap: 12px;
62
+ }
63
+
64
+ .copy-btn {
65
+ flex-shrink: 0;
66
+ padding: 4px 12px;
67
+ background: #2a2a2a;
68
+ border: 1px solid #444;
69
+ color: #ccc;
70
+ border-radius: 4px;
71
+ font-size: 12px;
72
+ cursor: pointer;
73
+ white-space: nowrap;
74
+ }
75
+
76
+ .copy-btn:hover { background: #333; }
77
+ .copy-btn.copied { color: #6ee7b7; border-color: #6ee7b7; }
78
+
79
+ .desc {
80
+ margin-top: 8px;
81
+ color: #aaa;
82
+ font-size: 13px;
83
+ line-height: 1.6;
84
+ }
85
+
86
+ .prompt {
87
+ margin-top: 12px;
88
+ padding-top: 12px;
89
+ border-top: 1px solid #2a2a2a;
90
+ color: #888;
91
+ font-size: 12px;
92
+ line-height: 1.6;
93
+ }
94
+
95
+ .prompt-label {
96
+ color: #6ee7b7;
97
+ font-weight: 600;
98
+ margin-bottom: 4px;
99
+ }
100
+
101
+ .no-path { color: #555; font-style: italic; font-size: 12px; }
102
+ </style>
103
+ </head>
104
+ <body>
105
+ <div id="loading">Waiting for image…</div>
106
+ <div id="content">
107
+ <div class="image-wrap">
108
+ <img id="img" src="" alt="Generated image" />
109
+ </div>
110
+ <div class="meta">
111
+ <div class="meta-row">
112
+ <div id="path-display" class="path"></div>
113
+ <button id="copy-btn" class="copy-btn" style="display:none">Copy path</button>
114
+ </div>
115
+ <div id="desc" class="desc" style="display:none"></div>
116
+ <div id="prompt" class="prompt" style="display:none">
117
+ <div class="prompt-label">Prompt</div>
118
+ <div id="prompt-text"></div>
119
+ </div>
120
+ </div>
121
+ </div>
122
+
123
+ <script type="module">
124
+ import { App } from 'https://esm.sh/@modelcontextprotocol/ext-apps@1.0.1';
125
+
126
+ const app = new App({ name: 'Gemini Image Viewer', version: '1.0.0' });
127
+
128
+ app.ontoolresult = (result) => {
129
+ const data = result.structuredContent;
130
+ if (!data || !data.base64Data) return;
131
+ render(data);
132
+ };
133
+
134
+ app.connect();
135
+
136
+ function render(data) {
137
+ const loading = document.getElementById('loading');
138
+ const content = document.getElementById('content');
139
+ const img = document.getElementById('img');
140
+ const pathDisplay = document.getElementById('path-display');
141
+ const copyBtn = document.getElementById('copy-btn');
142
+ const descEl = document.getElementById('desc');
143
+ const promptEl = document.getElementById('prompt');
144
+ const promptTextEl = document.getElementById('prompt-text');
145
+
146
+ img.src = `data:${data.mimeType};base64,${data.base64Data}`;
147
+
148
+ if (data.savedPath) {
149
+ pathDisplay.textContent = data.savedPath;
150
+ copyBtn.style.display = 'block';
151
+ copyBtn.addEventListener('click', () => {
152
+ navigator.clipboard.writeText(data.savedPath).then(() => {
153
+ copyBtn.textContent = 'Copied!';
154
+ copyBtn.classList.add('copied');
155
+ setTimeout(() => {
156
+ copyBtn.textContent = 'Copy path';
157
+ copyBtn.classList.remove('copied');
158
+ }, 2000);
159
+ });
160
+ });
161
+ } else {
162
+ pathDisplay.innerHTML = '<span class="no-path">Not saved to disk</span>';
163
+ }
164
+
165
+ if (data.description) {
166
+ descEl.textContent = data.description;
167
+ descEl.style.display = 'block';
168
+ }
169
+
170
+ if (data.prompt) {
171
+ promptTextEl.textContent = data.prompt;
172
+ promptEl.style.display = 'block';
173
+ }
174
+
175
+ loading.style.display = 'none';
176
+ content.style.display = 'block';
177
+ }
178
+ </script>
179
+ </body>
180
+ </html>