@webmcp-auto-ui/sdk 2.5.31 → 2.5.33

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": "@webmcp-auto-ui/sdk",
3
- "version": "2.5.31",
3
+ "version": "2.5.33",
4
4
  "description": "Skills CRUD, HyperSkill format, Svelte 5 stores",
5
5
  "license": "AGPL-3.0-or-later",
6
6
  "type": "module",
package/src/index.ts CHANGED
@@ -96,3 +96,6 @@ export type { ParsedSegment, RunResult, RunLog, RunTab, RecipeData } from './rec
96
96
 
97
97
  // Short URL — domain-dependent compact token
98
98
  export { buildShortUrl, getShortToken } from './short-url.js';
99
+
100
+ // Widget sample-data extractor — parses the `## Example` block of a recipe
101
+ export { extractSampleData } from './widget-sample-data.js';
@@ -80,7 +80,6 @@ function createCanvas() {
80
80
  // Setters (kept for backward compat)
81
81
  setMode(m: Mode) { canvasVanilla.setMode(m); },
82
82
  setLlm(l: LLMId) { canvasVanilla.setLlm(l); },
83
- setMcpUrl(u: string) { canvasVanilla.setMcpUrl(u); },
84
83
  setGenerating(g: boolean) { canvasVanilla.setGenerating(g); },
85
84
 
86
85
  // Widget actions (primary name)
@@ -101,11 +100,6 @@ function createCanvas() {
101
100
  updateMsg: canvasVanilla.updateMsg.bind(canvasVanilla),
102
101
  clearMessages: canvasVanilla.clearMessages.bind(canvasVanilla),
103
102
 
104
- // MCP
105
- setMcpConnecting: canvasVanilla.setMcpConnecting.bind(canvasVanilla),
106
- setMcpConnected: canvasVanilla.setMcpConnected.bind(canvasVanilla),
107
- setMcpError: canvasVanilla.setMcpError.bind(canvasVanilla),
108
-
109
103
  // Theme
110
104
  get themeOverrides() { return themeOverrides; },
111
105
  setThemeOverrides: canvasVanilla.setThemeOverrides.bind(canvasVanilla),
@@ -118,6 +112,7 @@ function createCanvas() {
118
112
  get dataServers() { return dataServers; },
119
113
  set dataServers(v: DataServer[]) { canvasVanilla.dataServers = v; },
120
114
  addDataServer: canvasVanilla.addDataServer.bind(canvasVanilla),
115
+ addMcpServer: canvasVanilla.addMcpServer.bind(canvasVanilla),
121
116
  removeDataServer: canvasVanilla.removeDataServer.bind(canvasVanilla),
122
117
  getDataServer: canvasVanilla.getDataServer.bind(canvasVanilla),
123
118
  setDataServerMeta: canvasVanilla.setDataServerMeta.bind(canvasVanilla),
@@ -10,17 +10,15 @@
10
10
  *
11
11
  * Historically this store had TWO parallel surfaces for MCP servers:
12
12
  * - `mcpUrl` / `mcpName` / `mcpConnected` / `mcpConnecting` / `mcpTools`
13
- * (flat, single-server or comma-joined multi)
13
+ * (flat, single-server or comma-joined multi) driven by legacy
14
+ * `setMcpConnected`/`setMcpConnecting`/`setMcpError` setters.
14
15
  * - `dataServers: DataServer[]` (list, managed by MultiMcpBridge)
15
16
  *
16
- * They were actually the same concept. This file now stores a single list
17
- * (`_servers`) and derives the flat `mcp*` fields from it. All writes (via
18
- * `setMcpConnected`, `addDataServer`, etc.) mutate the same underlying list,
19
- * so tools populated by the agent-MCP path are visible to the notebook / data
20
- * server consumers and vice-versa.
21
- *
22
- * The public API shape is preserved (both `mcp*` and `dataServers` / `addDataServer`)
23
- * so existing apps keep working without modification.
17
+ * They were the same concept. The legacy setters and the `primary` flag have
18
+ * been removed; writes go through `addDataServer` / `setDataServerMeta` /
19
+ * `setDataServerEnabled` / `addMcpServer` (url shorthand) exclusively. Flat
20
+ * getters (`mcpConnected`, `mcpName`, `mcpUrl`, `mcpConnecting`, `mcpTools`)
21
+ * remain as read-only derivations over the server list for UI back-compat.
24
22
  */
25
23
 
26
24
  import { encode, decode } from '../hyperskills.js';
@@ -62,9 +60,8 @@ export interface McpToolInfo {
62
60
 
63
61
  /**
64
62
  * Single MCP server entry — the one true shape.
65
- * `primary: true` marks the "agent MCP" (used by the chat/tool-call path) —
66
- * at most one server may be primary. Additional servers (data-only) are
67
- * non-primary but otherwise identical.
63
+ * All servers are equal; there is no "primary" concept. The MultiMcpBridge
64
+ * singleton reconciles connection state across all entries.
68
65
  */
69
66
  export interface DataServer {
70
67
  name: string; // user-chosen label
@@ -73,10 +70,12 @@ export interface DataServer {
73
70
  enabled: boolean; // user intent
74
71
  connected: boolean; // handshake completed
75
72
  connecting?: boolean;
76
- primary?: boolean; // agent MCP when true
77
73
  tools?: McpToolInfo[];
78
74
  recipes?: { name: string; description?: string; body?: string }[];
79
75
  error?: string;
76
+ /** Real server name from MCP handshake (initResult.serverInfo.name, aliased).
77
+ * Canvas `.name` is URL-host; `.serverName` is what to display. */
78
+ serverName?: string;
80
79
  }
81
80
 
82
81
  export interface CanvasSnapshot {
@@ -124,9 +123,6 @@ function createCanvasVanilla() {
124
123
  let _servers: DataServer[] = [];
125
124
 
126
125
  // ── Helpers over _servers ──────────────────────────────────────────────
127
- function primaryServer(): DataServer | undefined {
128
- return _servers.find((s) => s.primary);
129
- }
130
126
  function connectedServers(): DataServer[] {
131
127
  return _servers.filter((s) => s.connected);
132
128
  }
@@ -162,33 +158,35 @@ function createCanvasVanilla() {
162
158
  }
163
159
 
164
160
  // ── Server list actions (public, stable) ───────────────────────────────
165
- function addDataServer(desc: { name: string; url: string; primary?: boolean }): DataServer {
161
+ function addDataServer(desc: { name: string; url: string }): DataServer {
166
162
  const existing = _servers.find((s) => s.name === desc.name);
167
- if (existing) {
168
- if (desc.primary && !existing.primary) {
169
- // Promote: there's only one primary. Demote others.
170
- _servers = _servers.map((s) => ({ ...s, primary: s.name === desc.name }));
171
- notify();
172
- }
173
- return existing;
174
- }
163
+ if (existing) return existing;
175
164
  const srv: DataServer = {
176
165
  name: desc.name,
177
166
  url: desc.url,
178
167
  kind: 'data',
179
168
  enabled: true,
180
169
  connected: false,
181
- primary: !!desc.primary,
182
170
  };
183
- if (srv.primary) {
184
- // Demote any existing primary before inserting.
185
- _servers = _servers.map((s) => ({ ...s, primary: false }));
186
- }
187
171
  _servers = [..._servers, srv];
188
172
  notify();
189
173
  return srv;
190
174
  }
191
175
 
176
+ /**
177
+ * Add a server by URL alone (derives name from the URL host). Returns the
178
+ * canvas name so callers can reference it later.
179
+ */
180
+ function addMcpServer(url: string): string {
181
+ if (!url) return '';
182
+ let name: string;
183
+ try { name = new URL(url, 'http://local').host || url; }
184
+ catch { name = url; }
185
+ addDataServer({ name, url });
186
+ setDataServerEnabled(name, true);
187
+ return name;
188
+ }
189
+
192
190
  function removeDataServer(name: string): boolean {
193
191
  const before = _servers.length;
194
192
  _servers = _servers.filter((s) => s.name !== name);
@@ -222,68 +220,6 @@ function createCanvasVanilla() {
222
220
  return setDataServerEnabled(name, !s.enabled);
223
221
  }
224
222
 
225
- // ── Agent-MCP compatibility layer ──────────────────────────────────────
226
- // All these mutate the SAME _servers list; `mcpUrl` targets the primary
227
- // entry, creating one if none exists. Apps can equivalently call
228
- // addDataServer({primary: true}) + setDataServerMeta(name, ...) directly.
229
- function ensurePrimary(url?: string): DataServer {
230
- let p = primaryServer();
231
- if (p) {
232
- if (url && p.url !== url) {
233
- _servers = _servers.map((s) => s.name === p!.name ? { ...s, url } : s);
234
- }
235
- return _servers.find((s) => s.primary)!;
236
- }
237
- // Create a placeholder primary with a stable name derived from the URL.
238
- const nm = url ? new URL(url, 'http://local').host || url : 'primary';
239
- _servers = [..._servers, {
240
- name: nm, url: url ?? '', kind: 'data', enabled: true, connected: false, primary: true,
241
- }];
242
- return _servers[_servers.length - 1]!;
243
- }
244
-
245
- function setMcpUrl(u: string): void {
246
- // Update the primary server's URL (create one if none).
247
- ensurePrimary(u);
248
- notify();
249
- }
250
-
251
- function setMcpConnecting(connecting: boolean): void {
252
- const p = ensurePrimary();
253
- _servers = _servers.map((s) => s.name === p.name ? { ...s, connecting } : s);
254
- notify();
255
- }
256
-
257
- function setMcpConnected(connected: boolean, name?: string, tools?: McpToolInfo[]): void {
258
- if (!connected) {
259
- // Disconnect all — agent-level disconnect affects the primary and
260
- // traditionally cleared the flat tools. Mirror that by disconnecting
261
- // all primary-flagged servers.
262
- const p = primaryServer();
263
- if (p) {
264
- _servers = _servers.map((s) => s.primary
265
- ? { ...s, connected: false, connecting: false, tools: [], error: undefined }
266
- : s);
267
- }
268
- notify();
269
- return;
270
- }
271
- const p = ensurePrimary();
272
- const newName = name && name.length > 0 ? name : p.name;
273
- _servers = _servers.map((s) => s.name === p.name
274
- ? { ...s, name: newName, connected: true, connecting: false, tools: tools ?? s.tools ?? [], error: undefined }
275
- : s);
276
- notify();
277
- }
278
-
279
- function setMcpError(err: string): void {
280
- const p = ensurePrimary();
281
- _servers = _servers.map((s) => s.name === p.name
282
- ? { ...s, connected: false, connecting: false, error: err }
283
- : s);
284
- notify();
285
- }
286
-
287
223
  // ── Widget actions ─────────────────────────────────────────────────────
288
224
  function addWidget(type: WidgetType, data: Record<string, unknown> = {}): Widget {
289
225
  const widget: Widget = { id: uuid(), type, data };
@@ -340,12 +276,12 @@ function createCanvasVanilla() {
340
276
 
341
277
  // ── HyperSkill ─────────────────────────────────────────────────────────
342
278
  function buildSkillJSON() {
343
- const p = primaryServer();
279
+ const first = connectedServers()[0] ?? _servers[0];
344
280
  const skill: Record<string, unknown> = {
345
281
  version: '1.0',
346
282
  name: 'skill-' + Date.now(),
347
283
  created: new Date().toISOString(),
348
- mcp: p?.url ?? '',
284
+ mcp: first?.url ?? '',
349
285
  llm: _llm,
350
286
  blocks: _blocks.map((b) => ({ type: b.type, data: JSON.parse(JSON.stringify(b.data)) })),
351
287
  };
@@ -368,7 +304,7 @@ function createCanvasVanilla() {
368
304
  servers?: string[];
369
305
  blocks?: { type: WidgetType; data: Record<string, unknown> }[];
370
306
  }) {
371
- if (skill.mcp) ensurePrimary(skill.mcp);
307
+ if (skill.mcp) addMcpServer(skill.mcp);
372
308
  if (skill.llm) _llm = skill.llm;
373
309
  if (skill.theme) _themeOverrides = skill.theme;
374
310
  if (skill.servers) _enabledServerIds = skill.servers;
@@ -401,7 +337,7 @@ function createCanvasVanilla() {
401
337
  content?: { blocks?: { type: WidgetType; data: Record<string, unknown> }[] };
402
338
  servers?: string[];
403
339
  };
404
- if (decoded.meta?.mcp) ensurePrimary(decoded.meta.mcp as string);
340
+ if (decoded.meta?.mcp) addMcpServer(decoded.meta.mcp as string);
405
341
  if (decoded.meta?.llm) _llm = decoded.meta.llm as LLMId;
406
342
  if (decoded.meta?.theme) _themeOverrides = decoded.meta.theme as Record<string, string>;
407
343
  const servers = (decoded.servers ?? (decoded.meta?.servers as string[] | undefined));
@@ -416,15 +352,15 @@ function createCanvasVanilla() {
416
352
 
417
353
  // ── Snapshot (fields kept for API stability) ───────────────────────────
418
354
  function getSnapshot(): CanvasSnapshot {
419
- const p = primaryServer();
355
+ const first = connectedServers()[0] ?? _servers[0];
420
356
  return {
421
357
  blocks: _blocks,
422
358
  mode: _mode,
423
359
  llm: _llm,
424
- mcpUrl: p?.url ?? '',
425
- mcpConnected: p?.connected ?? false,
360
+ mcpUrl: first?.url ?? '',
361
+ mcpConnected: _servers.some((s) => s.connected),
426
362
  mcpConnecting: anyConnecting(),
427
- mcpName: displayName(),
363
+ mcpName: first && first.connected ? aliasName(first.serverName ?? first.name) : '',
428
364
  mcpTools: unionTools(),
429
365
  messages: _messages,
430
366
  generating: _generating,
@@ -450,11 +386,14 @@ function createCanvasVanilla() {
450
386
  set mode(v: Mode) { _mode = v; notify(); },
451
387
  get llm() { return _llm; },
452
388
  set llm(v: LLMId) { _llm = v; notify(); },
453
- get mcpUrl() { return primaryServer()?.url ?? ''; },
454
- set mcpUrl(v: string) { setMcpUrl(v); },
455
- get mcpConnected() { return primaryServer()?.connected ?? false; },
389
+ get mcpUrl() { return (connectedServers()[0] ?? _servers[0])?.url ?? ''; },
390
+ set mcpUrl(v: string) { addMcpServer(v); },
391
+ get mcpConnected() { return _servers.some((s) => s.connected); },
456
392
  get mcpConnecting() { return anyConnecting(); },
457
- get mcpName() { return displayName(); },
393
+ get mcpName() {
394
+ const s = connectedServers()[0];
395
+ return s ? aliasName(s.serverName ?? s.name) : '';
396
+ },
458
397
  get mcpTools() { return unionTools(); },
459
398
  get messages() { return _messages; },
460
399
  get generating() { return _generating; },
@@ -466,15 +405,12 @@ function createCanvasVanilla() {
466
405
 
467
406
  setMode(m: Mode) { _mode = m; notify(); },
468
407
  setLlm(l: LLMId) { _llm = l; notify(); },
469
- setMcpUrl,
470
408
  setGenerating(g: boolean) { _generating = g; notify(); },
471
409
 
472
410
  addWidget, addBlock,
473
411
  removeBlock, updateBlock, moveBlock, clearBlocks, setBlocks,
474
412
  addMsg, updateMsg, clearMessages,
475
413
 
476
- setMcpConnecting, setMcpConnected, setMcpError,
477
-
478
414
  get themeOverrides() { return _themeOverrides; },
479
415
  setThemeOverrides,
480
416
 
@@ -486,6 +422,7 @@ function createCanvasVanilla() {
486
422
  get dataServers() { return _servers; },
487
423
  set dataServers(v: DataServer[]) { _servers = Array.isArray(v) ? v : []; notify(); },
488
424
  addDataServer,
425
+ addMcpServer,
489
426
  removeDataServer,
490
427
  getDataServer,
491
428
  setDataServerMeta,
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Extract sample `params` data from a widget recipe's `## Example` block.
3
+ *
4
+ * Recipes have shape:
5
+ * ## Example
6
+ * ```
7
+ * <server>_webmcp_widget_display({name: "<widget>", params: { ... }})
8
+ * ```
9
+ *
10
+ * Recipes are bundled at build time from our own source — `new Function`
11
+ * eval is acceptable here (not user input).
12
+ */
13
+
14
+ function findBalancedBraces(text: string, fromIndex: number): string | null {
15
+ let depth = 0;
16
+ let start = -1;
17
+ for (let i = fromIndex; i < text.length; i++) {
18
+ const ch = text[i];
19
+ if (ch === '{') {
20
+ if (start === -1) start = i;
21
+ depth++;
22
+ } else if (ch === '}') {
23
+ depth--;
24
+ if (depth === 0 && start !== -1) return text.slice(start, i + 1);
25
+ }
26
+ }
27
+ return null;
28
+ }
29
+
30
+ export function extractSampleData(recipe: string | undefined | null): Record<string, unknown> | null {
31
+ if (!recipe) return null;
32
+ const exampleHeader = recipe.search(/^##\s*Example/m);
33
+ if (exampleHeader === -1) return null;
34
+ const after = recipe.slice(exampleHeader);
35
+ const paramsIdx = after.search(/params\s*:/);
36
+ if (paramsIdx === -1) return null;
37
+ const objStart = after.indexOf('{', paramsIdx);
38
+ if (objStart === -1) return null;
39
+ const objLiteral = findBalancedBraces(after, objStart);
40
+ if (!objLiteral) return null;
41
+ try {
42
+ const fn = new Function(`return (${objLiteral});`);
43
+ const value = fn();
44
+ if (value && typeof value === 'object') return value as Record<string, unknown>;
45
+ } catch { /* parse error — fall through */ }
46
+ return null;
47
+ }
package/tsconfig.json CHANGED
@@ -16,7 +16,6 @@
16
16
  "declaration": true
17
17
  },
18
18
  "include": [
19
- "src/**/*.ts",
20
- "src/**/*.svelte"
19
+ "src/**/*.ts"
21
20
  ]
22
21
  }
package/src/Index.svelte DELETED
@@ -1,5 +0,0 @@
1
- <!-- @webmcp-auto-ui/sdk — browser components stub -->
2
- <script lang="ts">
3
- // This file exists to satisfy svelte-check tooling.
4
- // Import canvas store via: import { canvas } from '@webmcp-auto-ui/sdk/canvas'
5
- </script>