@kolbo/mcp 1.30.3 → 1.30.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kolbo/mcp",
3
- "version": "1.30.3",
3
+ "version": "1.30.5",
4
4
  "description": "Kolbo AI MCP Server - Generate images, videos, music, speech, and sound effects from Claude Code",
5
5
  "main": "src/index.js",
6
6
  "bin": {
package/src/apps/index.js CHANGED
@@ -48,16 +48,29 @@ function widgetHtml(uri) {
48
48
  // img/script/style/font/media-src; connectDomains to connect-src.
49
49
  const WIDGET_CSP = {
50
50
  resourceDomains: [
51
- 'https://*.kolbo.ai', // media.kolbo.ai CDN + app.kolbo.ai model icons
52
- 'https://*.digitaloceanspaces.com', // DO Spaces buckets (all envs)
53
- 'https://*.cdn.digitaloceanspaces.com', // DO Spaces CDN endpoints
51
+ // Exact hosts FIRST not every host CSP implementation honors wildcards,
52
+ // and a declared-but-unmatched allowlist blocks harder than no declaration.
53
+ 'https://api.kolbo.ai', // model icons (/assets)
54
+ 'https://app.kolbo.ai',
55
+ 'https://media.kolbo.ai', // media CDN (prod)
56
+ 'https://media-staging.kolbo.ai',
57
+ 'https://media-dev.kolbo.ai',
58
+ 'https://kolboai-production.ams3.digitaloceanspaces.com',
59
+ 'https://kolboai-production.ams3.cdn.digitaloceanspaces.com',
60
+ 'https://kolboai-development.ams3.digitaloceanspaces.com',
61
+ 'https://kolboai-development.ams3.cdn.digitaloceanspaces.com',
62
+ 'https://kolbo-general-media.fra1.cdn.digitaloceanspaces.com',
54
63
  'https://fonts.googleapis.com', // Inter / JetBrains Mono stylesheet
55
64
  'https://fonts.gstatic.com', // font files
56
65
  'https://images.pexels.com', // stock thumbnails
66
+ // Wildcards as a second layer for hosts that do support them.
67
+ 'https://*.kolbo.ai',
68
+ 'https://*.digitaloceanspaces.com',
69
+ 'https://*.cdn.digitaloceanspaces.com',
57
70
  'https://*.pexels.com',
58
71
  'https://*.pixabay.com',
59
72
  'https://*.sketchfab.com',
60
- 'https://*.cloudfront.net', // provider-hosted previews
73
+ 'https://*.cloudfront.net',
61
74
  ],
62
75
  connectDomains: [],
63
76
  };
@@ -125,6 +138,23 @@ function uiResult(uri, text, structured) {
125
138
  const ICON_TTL_MS = 10 * 60 * 1000;
126
139
  const infoCache = new Map(); // apiBase → { at, byKey: Map<lowername, {icon, eta}> }
127
140
 
141
+ /**
142
+ * Resolve a Model.avatar value to an absolute URL. Avatars are bare filenames
143
+ * (sometimes with spaces) living in the BACKEND's public assets folder —
144
+ * `<api origin>/assets/<file>`. Do NOT use app.kolbo.ai for this: it's the SPA,
145
+ * whose catch-all returns 200 text/html for any missing file, which renders as
146
+ * a broken image in widgets.
147
+ */
148
+ function resolveAvatarUrl(avatar, apiBase) {
149
+ if (!avatar) return null;
150
+ if (/^https?:\/\//i.test(avatar)) return avatar;
151
+ let origin = 'https://api.kolbo.ai';
152
+ try {
153
+ origin = new URL(apiBase || 'https://api.kolbo.ai/api').origin;
154
+ } catch (_) { /* keep default */ }
155
+ return `${origin}/assets/${encodeURIComponent(avatar)}`;
156
+ }
157
+
128
158
  async function modelInfoMap(client) {
129
159
  const cacheKey = client.apiBase || 'default';
130
160
  const hit = infoCache.get(cacheKey);
@@ -135,13 +165,7 @@ async function modelInfoMap(client) {
135
165
  const models = res?.models || res?.data?.models || [];
136
166
  for (const m of models) {
137
167
  if (!m) continue;
138
- // The API usually resolves avatars to absolute URLs; bare filenames (older
139
- // deployments / internal calls) resolve against the app's public icon dir.
140
- const icon = m.avatar
141
- ? (/^https?:\/\//i.test(m.avatar)
142
- ? m.avatar
143
- : `https://app.kolbo.ai/models_icons/${encodeURIComponent(m.avatar)}`)
144
- : null;
168
+ const icon = resolveAvatarUrl(m.avatar, client.apiBase);
145
169
  // Real p75 wall-clock estimate mined from production creditUsages —
146
170
  // the same source the in-app countdowns use. No estimate → no ETA shown.
147
171
  const eta = Number(m.estimatedDurationSeconds || m.estimated_duration_seconds) || null;
@@ -232,5 +256,6 @@ module.exports = {
232
256
  modelIcon,
233
257
  modelInfo,
234
258
  modelInfoMap,
259
+ resolveAvatarUrl,
235
260
  widgetHtml, // exported for smoke tests
236
261
  };
@@ -92,7 +92,7 @@ function renderChips(sc) {
92
92
  if (s.voice) h += chip('🎤 ' + esc(s.voice));
93
93
  if (s.mode) h += chip(esc(s.mode));
94
94
  if (sc.count > 1) h += chip('×' + sc.count);
95
- if (sc.reference_image) h += '<img class="k-ref-thumb" src="' + esc(sc.reference_image) + '" alt="" title="Reference image" onerror="this.style.display=\'none\'">';
95
+ if (sc.reference_image) h += '<img class="k-ref-thumb" src="' + esc(sc.reference_image) + '" alt="" title="Reference image" onerror="this.style.display=\\'none\\'">';
96
96
  el('chips').innerHTML = h;
97
97
  }
98
98
  function chip(inner) { return '<span class="k-chip">' + inner + '</span>'; }
package/src/index.js CHANGED
@@ -97,7 +97,12 @@ function createServer(opts = {}) {
97
97
 
98
98
  const server = new McpServer({
99
99
  name: 'kolbo',
100
- version: '1.0.0'
100
+ title: 'Kolbo',
101
+ version: '1.0.0',
102
+ websiteUrl: 'https://kolbo.ai',
103
+ // Connector avatar for hosts that render server icons (claude.ai tool
104
+ // headers show this instead of a letter monogram).
105
+ icons: [{ src: 'https://api.kolbo.ai/assets/kolbo-ai.png', mimeType: 'image/png', sizes: ['512x512'] }]
101
106
  });
102
107
 
103
108
  // Register all tools. `inlineImages` (off by default) is opt-in: only the