@urbicon-ui/mcp-server 6.21.0 → 6.21.1

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": "@urbicon-ui/mcp-server",
3
- "version": "6.21.0",
3
+ "version": "6.21.1",
4
4
  "description": "Model Context Protocol server exposing the Urbicon UI component catalog, recipes and design intelligence to LLM agents",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -32,13 +32,13 @@
32
32
  },
33
33
  "dependencies": {
34
34
  "@modelcontextprotocol/sdk": "^1.29.0",
35
- "@urbicon-ui/design-content": "6.21.0",
36
- "@urbicon-ui/design-engine": "6.21.0",
35
+ "@urbicon-ui/design-content": "6.21.1",
36
+ "@urbicon-ui/design-engine": "6.21.1",
37
37
  "zod": "^4.3.6"
38
38
  },
39
39
  "devDependencies": {
40
40
  "typescript": "^6.0.3",
41
- "@types/node": "^25.9.4",
41
+ "@types/node": "^25.9.5",
42
42
  "vitest": "^4.1.9"
43
43
  }
44
44
  }
@@ -88,8 +88,8 @@ function extractDescription(content: string): string {
88
88
  if (titleIdx === -1) return '';
89
89
 
90
90
  for (let i = titleIdx + 1; i < lines.length; i++) {
91
- const line = lines[i]!.trim();
92
- if (line === '') continue;
91
+ const line = lines[i]?.trim();
92
+ if (!line) continue;
93
93
  if (line.startsWith('#')) break;
94
94
  return line;
95
95
  }
@@ -115,7 +115,7 @@ export function extractPrincipleSection(content: string, topic: PrincipleTopic):
115
115
 
116
116
  let endIdx = lines.length;
117
117
  for (let i = startIdx + 1; i < lines.length; i++) {
118
- if (/^## /.test(lines[i]!)) {
118
+ if (/^## /.test(lines[i] ?? '')) {
119
119
  endIdx = i;
120
120
  break;
121
121
  }
@@ -36,8 +36,9 @@ export function registerFindIconsTool(server: McpServer): void {
36
36
  const byCategory = new Map<string, typeof icons>();
37
37
  for (const icon of icons) {
38
38
  for (const cat of icon.categories) {
39
- if (!byCategory.has(cat)) byCategory.set(cat, []);
40
- byCategory.get(cat)!.push(icon);
39
+ const bucket = byCategory.get(cat);
40
+ if (bucket) bucket.push(icon);
41
+ else byCategory.set(cat, [icon]);
41
42
  }
42
43
  }
43
44
 
@@ -236,8 +236,8 @@ Shadows automatically increase opacity in dark mode (0.05 → 0.2 for xs, etc.).
236
236
  | \`--z-hide\` | -1 | Hidden |
237
237
  | \`--z-base\` | 0 | Default |
238
238
  | \`--z-docked\` | 10 | Docked elements |
239
- | \`--z-dropdown\` | 9999 | Menus, listboxes, floating panels |
240
239
  | \`--z-sticky\` | 1100 | Sticky headers |
240
+ | \`--z-dropdown\` | 1150 | Menus, listboxes, floating panels (above sticky, below banner) |
241
241
  | \`--z-banner\` | 1200 | Banners |
242
242
  | \`--z-overlay\` | 1300 | Overlays |
243
243
  | \`--z-sidebar\` | 1350 | Sidebars |
@@ -345,7 +345,7 @@ For a temperature-free, true grayscale chassis (content-focused UIs), set chroma
345
345
 
346
346
  ## Intent-hue collisions
347
347
 
348
- If your accent hue lands near an intent hue, the two become hard to tell apart. The library intents sit at: success 140, warning 80, danger 25, info 220, secondary 280. A green brand (~140) collides with success; an amber brand (~80) collides with warning. When that happens, re-tune the colliding intent ramp away from the accent (push the hue ±15–25° and/or drop its lightness so it reads as "status", not "brand"). \`apps/docs/src/lib/style/editorial.css\` is a worked example (green brand → success pushed to 150 + darkened, warning pulled to amber 55).
348
+ If your accent hue lands near an intent hue, the two become hard to tell apart. The library intents sit at: success 140, warning 80, danger 25, info 220, secondary 280. A green brand (~140) collides with success; an amber brand (~80) collides with warning. When that happens, re-tune the colliding intent ramp away from the accent (push the hue ±15–25° and/or drop its lightness so it reads as "status", not "brand"). \`apps/docs/src/lib/style/rooms-docs.css\` is a worked example (green brand → success pushed to 150 + darkened, warning pulled to amber 55).
349
349
 
350
350
  ## Overriding Semantic Tokens
351
351
 
@@ -390,7 +390,7 @@ Fix: inside the scoped block, re-declare the derived tokens too, so substitution
390
390
  /* ...and the same for any neutral-derived surface/text/border tokens you rely on */
391
391
  }
392
392
  \`\`\`
393
- A global \`@theme\` block (the built-in themes, the Theme Builder output) does NOT hit this — everything lands on \`:root\`, the same element where the derived tokens compute, so re-declaration is unnecessary. Prefer global themes unless you genuinely need multiple themes live on one page. \`apps/docs/src/lib/style/editorial.css\` is the canonical scoped example.
393
+ A global \`@theme\` block (the built-in themes, the Theme Builder output) does NOT hit this — everything lands on \`:root\`, the same element where the derived tokens compute, so re-declaration is unnecessary. Prefer global themes unless you genuinely need multiple themes live on one page. \`apps/docs/src/lib/style/rooms-docs.css\` is the canonical scoped example.
394
394
 
395
395
  ## Component-Level Overrides
396
396
 
@@ -17,8 +17,9 @@ export async function startHttpTransport(port: number): Promise<void> {
17
17
  const sessionId = req.headers['mcp-session-id'] as string | undefined;
18
18
 
19
19
  if (req.method === 'POST') {
20
- if (sessionId && sessions.has(sessionId)) {
21
- await sessions.get(sessionId)!.handleRequest(req, res);
20
+ const session = sessionId ? sessions.get(sessionId) : undefined;
21
+ if (session) {
22
+ await session.handleRequest(req, res);
22
23
  } else if (!sessionId) {
23
24
  const transport = new StreamableHTTPServerTransport({
24
25
  sessionIdGenerator: () => crypto.randomUUID()
@@ -41,8 +42,9 @@ export async function startHttpTransport(port: number): Promise<void> {
41
42
  );
42
43
  }
43
44
  } else if (req.method === 'GET') {
44
- if (sessionId && sessions.has(sessionId)) {
45
- await sessions.get(sessionId)!.handleRequest(req, res);
45
+ const session = sessionId ? sessions.get(sessionId) : undefined;
46
+ if (session) {
47
+ await session.handleRequest(req, res);
46
48
  } else {
47
49
  res.writeHead(400, { 'Content-Type': 'application/json' });
48
50
  res.end(
@@ -54,8 +56,9 @@ export async function startHttpTransport(port: number): Promise<void> {
54
56
  );
55
57
  }
56
58
  } else if (req.method === 'DELETE') {
57
- if (sessionId && sessions.has(sessionId)) {
58
- await sessions.get(sessionId)!.handleRequest(req, res);
59
+ const session = sessionId ? sessions.get(sessionId) : undefined;
60
+ if (session && sessionId) {
61
+ await session.handleRequest(req, res);
59
62
  sessions.delete(sessionId);
60
63
  } else {
61
64
  res.writeHead(204);
@@ -46,8 +46,9 @@ export function formatCompactCatalog(
46
46
  for (const comp of filtered) {
47
47
  const primaryTag = comp.tags[0];
48
48
  if (primaryTag && TAG_LABELS[primaryTag]) {
49
- if (!grouped.has(primaryTag)) grouped.set(primaryTag, []);
50
- grouped.get(primaryTag)!.push(comp);
49
+ const bucket = grouped.get(primaryTag);
50
+ if (bucket) bucket.push(comp);
51
+ else grouped.set(primaryTag, [comp]);
51
52
  } else {
52
53
  ungrouped.push(comp);
53
54
  }