@urbicon-ui/mcp-server 6.28.0 → 6.29.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 CHANGED
@@ -97,7 +97,7 @@ All tools are read-only (`readOnlyHint: true`) — this server never touches the
97
97
  | `urbicon://guide/design-quality` | AVOID/INSTEAD patterns from A/B-tested design-quality guidance (+33.8 % improvement in user study) |
98
98
  | `urbicon://guide/component-families` | Six-family component taxonomy - ARIA roles and per-family border-token source |
99
99
  | `urbicon://guide/customization` | `unstyled` / `slotClasses` / `preset` override system + `BlocksProvider` overrides |
100
- | `urbicon://guide/auth-setup` | Auth package setup - handler factories, handle hook, adapter pattern, client stores |
100
+ | `urbicon://guide/auth` | Complete auth reference - served verbatim from the bundled, tarball-canonical `AUTH.md` |
101
101
  | `urbicon://guide/style-patterns` | Reusable style presets and composition templates |
102
102
  | `urbicon://guide/tokens` | OKLCH token reference, same data as `get_css_reference` |
103
103
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@urbicon-ui/mcp-server",
3
- "version": "6.28.0",
3
+ "version": "6.29.0",
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": {
@@ -39,8 +39,8 @@
39
39
  },
40
40
  "dependencies": {
41
41
  "@modelcontextprotocol/sdk": "^1.29.0",
42
- "@urbicon-ui/design-content": "6.28.0",
43
- "@urbicon-ui/design-engine": "6.28.0",
42
+ "@urbicon-ui/design-content": "6.29.0",
43
+ "@urbicon-ui/design-engine": "6.29.0",
44
44
  "zod": "^4.3.6"
45
45
  },
46
46
  "devDependencies": {
@@ -0,0 +1,29 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { getGuidePath } from '@urbicon-ui/design-content';
3
+
4
+ /**
5
+ * Reader for the bundle's canonical package guides (`guides/<slug>.md`) — the
6
+ * tarball-shipped guide documents (e.g. `packages/auth/docs/AUTH.md`) that
7
+ * docs-gen distributes into the design-content bundle. Unlike the template
8
+ * sections (template-loader.ts) these are complete documents, served verbatim.
9
+ * Cached per process, like the template sections.
10
+ */
11
+ const cachedGuides = new Map<string, string>();
12
+
13
+ /**
14
+ * Load one bundled package guide by slug. `null` when the guide (or the
15
+ * bundle) is absent — the resource read degrades to a "not found" note, the
16
+ * same contract as a missing template section.
17
+ */
18
+ export async function loadPackageGuide(slug: string): Promise<string | null> {
19
+ const cached = cachedGuides.get(slug);
20
+ if (cached !== undefined) return cached;
21
+
22
+ try {
23
+ const content = await readFile(getGuidePath(slug), 'utf-8');
24
+ cachedGuides.set(slug, content);
25
+ return content;
26
+ } catch {
27
+ return null;
28
+ }
29
+ }
@@ -2,9 +2,11 @@ import { readFile } from 'node:fs/promises';
2
2
  import { getTemplatePath } from '@urbicon-ui/design-content';
3
3
 
4
4
  /**
5
- * The seven guide sections carved out of the single template document, keyed by
5
+ * The six guide sections carved out of the single template document, keyed by
6
6
  * guide id. Each value is the raw markdown of one `## …` section; the keys are
7
- * the ids the guide resources ({@link registerGuideResources}) expose.
7
+ * the ids the guide resources ({@link registerGuideResources}) expose. The auth
8
+ * guide is deliberately NOT here — it is a canonical package guide served from
9
+ * the bundle's `guides/auth.md` (see `guide-loader.ts`), not a template slice.
8
10
  */
9
11
  export interface TemplateSections {
10
12
  'api-grammar': string;
@@ -13,7 +15,6 @@ export interface TemplateSections {
13
15
  'design-quality': string;
14
16
  customization: string;
15
17
  'style-patterns': string;
16
- 'auth-setup': string;
17
18
  }
18
19
 
19
20
  let cachedSections: TemplateSections | null = null;
@@ -34,9 +35,9 @@ function extractSection(lines: string[], startHeading: string, endMarker: string
34
35
  }
35
36
 
36
37
  /**
37
- * Load the template document once and slice it into the seven
38
+ * Load the template document once and slice it into the six
38
39
  * {@link TemplateSections} by `## …` heading (each running up to the next `---`
39
- * rule; auth-setup, the last section, runs to EOF). Cached per process.
40
+ * rule). Cached per process.
40
41
  */
41
42
  export async function loadTemplateSections(): Promise<TemplateSections> {
42
43
  if (cachedSections) return cachedSections;
@@ -51,10 +52,7 @@ export async function loadTemplateSections(): Promise<TemplateSections> {
51
52
  tokens: extractSection(lines, '## Design Token System', '---'),
52
53
  'design-quality': extractSection(lines, '## Design Quality', '---'),
53
54
  customization: extractSection(lines, '## Customization', '---'),
54
- 'style-patterns': extractSection(lines, '## Style Patterns', '---'),
55
- // Auth Setup is the last section and contains no `---` rules of its own, so
56
- // it extracts cleanly to EOF. Its `###` stage sub-headings carry the staging.
57
- 'auth-setup': extractSection(lines, '## Auth Setup', '---')
55
+ 'style-patterns': extractSection(lines, '## Style Patterns', '---')
58
56
  };
59
57
 
60
58
  return cachedSections;
@@ -1,67 +1,86 @@
1
1
  import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { loadPackageGuide } from '../data/guide-loader.js';
2
3
  import type { TemplateSections } from '../data/template-loader.js';
3
4
  import { loadTemplateSections } from '../data/template-loader.js';
4
5
 
5
6
  /**
6
- * The seven guide surfaces, each mapping a stable resource id to a section of
7
- * the template bundle ({@link TemplateSections}). Edit here to add/rename a
8
- * guide; the `key` must exist in `TemplateSections`.
7
+ * The seven guide surfaces. Six slice a `## …` section out of the template
8
+ * bundle ({@link TemplateSections}); the auth guide is a canonical package
9
+ * guide served verbatim from the bundle's `guides/auth.md` (the tarball-shipped
10
+ * `packages/auth/docs/AUTH.md` — one source, all channels, docs/DOCS-SURFACES.md).
11
+ * The `urbicon` CLI lists every bundled package guide dynamically
12
+ * (`urbicon guide`); this static list names the ones the server advertises.
9
13
  */
10
- const GUIDE_RESOURCES: { id: string; name: string; key: keyof TemplateSections }[] = [
14
+ const GUIDE_RESOURCES: (
15
+ | { id: string; name: string; source: 'template'; key: keyof TemplateSections }
16
+ | { id: string; name: string; source: 'package-guide'; slug: string }
17
+ )[] = [
11
18
  {
12
19
  id: 'api-grammar',
13
20
  name: 'API Grammar Guide',
21
+ source: 'template',
14
22
  key: 'api-grammar'
15
23
  },
16
24
  {
17
25
  id: 'component-families',
18
26
  name: 'Component Families Guide',
27
+ source: 'template',
19
28
  key: 'component-families'
20
29
  },
21
30
  {
22
31
  id: 'tokens',
23
32
  name: 'Design Tokens Guide',
33
+ source: 'template',
24
34
  key: 'tokens'
25
35
  },
26
36
  {
27
37
  id: 'design-quality',
28
38
  name: 'Design Quality Guide',
39
+ source: 'template',
29
40
  key: 'design-quality'
30
41
  },
31
42
  {
32
43
  id: 'customization',
33
44
  name: 'Customization Guide',
45
+ source: 'template',
34
46
  key: 'customization'
35
47
  },
36
48
  {
37
49
  id: 'style-patterns',
38
50
  name: 'Style Patterns Guide',
51
+ source: 'template',
39
52
  key: 'style-patterns'
40
53
  },
41
54
  {
42
- id: 'auth-setup',
43
- name: 'Auth Setup Guide',
44
- key: 'auth-setup'
55
+ id: 'auth',
56
+ name: 'Auth Reference',
57
+ source: 'package-guide',
58
+ slug: 'auth'
45
59
  }
46
60
  ];
47
61
 
48
62
  /**
49
63
  * Register one `urbicon://guide/<id>` resource per {@link GUIDE_RESOURCES} entry.
50
- * Each read slices its section out of the cached template bundle and degrades to
51
- * a "not found" note if the section is missing.
64
+ * Each read resolves its content lazily (template slice or bundled package
65
+ * guide) and degrades to a "not found" note if the content is missing.
52
66
  */
53
67
  export function registerGuideResources(server: McpServer): void {
54
68
  for (const guide of GUIDE_RESOURCES) {
55
69
  server.resource(`guide-${guide.id}`, `urbicon://guide/${guide.id}`, async (uri) => {
56
- const sections = await loadTemplateSections();
57
- const content = sections[guide.key];
70
+ let content: string | null;
71
+ if (guide.source === 'template') {
72
+ const sections = await loadTemplateSections();
73
+ content = sections[guide.key] || null;
74
+ } else {
75
+ content = await loadPackageGuide(guide.slug);
76
+ }
58
77
 
59
78
  return {
60
79
  contents: [
61
80
  {
62
81
  uri: uri.href,
63
82
  mimeType: 'text/markdown',
64
- text: content || `Guide section "${guide.id}" not found.`
83
+ text: content ?? `Guide "${guide.id}" not found.`
65
84
  }
66
85
  ]
67
86
  };