@urbicon-ui/mcp-server 6.22.0 → 6.23.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/package.json +3 -3
- package/src/data/catalog-loader.ts +8 -0
- package/src/data/component-loader.ts +10 -0
- package/src/data/design-system-loader.ts +11 -0
- package/src/data/template-loader.ts +11 -0
- package/src/prompts/design-prompts.ts +5 -0
- package/src/resources/catalog.ts +6 -0
- package/src/resources/guides.ts +10 -0
- package/src/server.ts +10 -0
- package/src/tools/find-components.ts +7 -0
- package/src/tools/find-icons.ts +6 -0
- package/src/tools/get-checklist.ts +7 -0
- package/src/tools/get-component.ts +7 -0
- package/src/tools/get-css-reference.ts +6 -0
- package/src/tools/get-design-principles.ts +7 -0
- package/src/tools/get-pattern.ts +6 -0
- package/src/tools/get-recipe.ts +6 -0
- package/src/tools/suggest-implementation.ts +8 -0
- package/src/tools/validate-design.ts +7 -0
- package/src/transports/http.ts +14 -0
- package/src/transports/stdio.ts +7 -0
- package/src/utils/format-catalog.ts +23 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@urbicon-ui/mcp-server",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.23.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": {
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
35
|
-
"@urbicon-ui/design-content": "6.
|
|
36
|
-
"@urbicon-ui/design-engine": "6.
|
|
35
|
+
"@urbicon-ui/design-content": "6.23.0",
|
|
36
|
+
"@urbicon-ui/design-engine": "6.23.0",
|
|
37
37
|
"zod": "^4.3.6"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
@@ -31,6 +31,13 @@ function initWatcher(): void {
|
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Load and cache the assembled component catalog (the single source of truth,
|
|
36
|
+
* auth components included). Unlike the read-tolerant loaders, this **throws**
|
|
37
|
+
* on a missing or corrupt catalog by design — the server never serves a
|
|
38
|
+
* silently empty or stale catalog. A file watcher invalidates the cache when
|
|
39
|
+
* the catalog changes on disk (dev regeneration).
|
|
40
|
+
*/
|
|
34
41
|
export async function loadCatalog(): Promise<ComponentCatalog> {
|
|
35
42
|
if (cachedCatalog) return cachedCatalog;
|
|
36
43
|
|
|
@@ -48,6 +55,7 @@ export async function loadCatalog(): Promise<ComponentCatalog> {
|
|
|
48
55
|
return cachedCatalog;
|
|
49
56
|
}
|
|
50
57
|
|
|
58
|
+
/** The in-memory catalog if {@link loadCatalog} has run, else `null`. No I/O. */
|
|
51
59
|
export function getCachedCatalog(): ComponentCatalog | null {
|
|
52
60
|
return cachedCatalog;
|
|
53
61
|
}
|
|
@@ -9,6 +9,16 @@ const SEARCH_GROUPS = [
|
|
|
9
9
|
'auth/components'
|
|
10
10
|
];
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Read a component's `llm.txt` by slug, probing each search group in order
|
|
14
|
+
* (blocks primitives/components, docs, table, auth). Returns `null` only when
|
|
15
|
+
* the file is absent (ENOENT) in *every* group — a genuine "unknown component".
|
|
16
|
+
* Any other I/O error (permissions, corrupt mount) is rethrown rather than
|
|
17
|
+
* masked as not-found.
|
|
18
|
+
*
|
|
19
|
+
* @param slug - Kebab-case component slug (e.g. `date-picker`).
|
|
20
|
+
* @returns The raw llm.txt, or `null` if no group has it.
|
|
21
|
+
*/
|
|
12
22
|
export async function loadComponentLlmTxt(slug: string): Promise<string | null> {
|
|
13
23
|
for (const group of SEARCH_GROUPS) {
|
|
14
24
|
const path = getComponentLlmPath(group, slug);
|
|
@@ -16,6 +16,11 @@ export {
|
|
|
16
16
|
let cachedPrinciples: string | null = null;
|
|
17
17
|
let cachedPatterns: PatternEntry[] | null = null;
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Load and cache `principles.md` from the design-system dir. Read-tolerant:
|
|
21
|
+
* yields `''` when the file is absent, so `get_design_principles` can degrade to
|
|
22
|
+
* a hint instead of crashing.
|
|
23
|
+
*/
|
|
19
24
|
export async function loadPrinciples(): Promise<string> {
|
|
20
25
|
if (cachedPrinciples !== null) return cachedPrinciples;
|
|
21
26
|
|
|
@@ -28,6 +33,11 @@ export async function loadPrinciples(): Promise<string> {
|
|
|
28
33
|
return cachedPrinciples;
|
|
29
34
|
}
|
|
30
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Load, parse and cache every `patterns/*.md` file, sorted by name. Read-
|
|
38
|
+
* tolerant: a missing dir or an unreadable file yields `[]` / is skipped rather
|
|
39
|
+
* than throwing.
|
|
40
|
+
*/
|
|
31
41
|
export async function loadPatterns(): Promise<PatternEntry[]> {
|
|
32
42
|
if (cachedPatterns) return cachedPatterns;
|
|
33
43
|
|
|
@@ -61,6 +71,7 @@ export async function loadPatterns(): Promise<PatternEntry[]> {
|
|
|
61
71
|
return entries;
|
|
62
72
|
}
|
|
63
73
|
|
|
74
|
+
/** One pattern by exact name from the cached set, or `null` if none matches. */
|
|
64
75
|
export async function getPatternByName(name: string): Promise<PatternEntry | null> {
|
|
65
76
|
const patterns = await loadPatterns();
|
|
66
77
|
return patterns.find((p) => p.name === name) ?? null;
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
2
|
import { getTemplatePath } from '@urbicon-ui/design-content';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* The seven guide sections carved out of the single template document, keyed by
|
|
6
|
+
* guide id. Each value is the raw markdown of one `## …` section; the keys are
|
|
7
|
+
* the ids the guide resources ({@link registerGuideResources}) expose.
|
|
8
|
+
*/
|
|
4
9
|
export interface TemplateSections {
|
|
5
10
|
'api-grammar': string;
|
|
6
11
|
'component-families': string;
|
|
@@ -28,6 +33,11 @@ function extractSection(lines: string[], startHeading: string, endMarker: string
|
|
|
28
33
|
return lines.slice(startIdx, endIdx).join('\n').trim();
|
|
29
34
|
}
|
|
30
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Load the template document once and slice it into the seven
|
|
38
|
+
* {@link TemplateSections} by `## …` heading (each running up to the next `---`
|
|
39
|
+
* rule; auth-setup, the last section, runs to EOF). Cached per process.
|
|
40
|
+
*/
|
|
31
41
|
export async function loadTemplateSections(): Promise<TemplateSections> {
|
|
32
42
|
if (cachedSections) return cachedSections;
|
|
33
43
|
|
|
@@ -50,6 +60,7 @@ export async function loadTemplateSections(): Promise<TemplateSections> {
|
|
|
50
60
|
return cachedSections;
|
|
51
61
|
}
|
|
52
62
|
|
|
63
|
+
/** The cached sections if {@link loadTemplateSections} has run, else `null`. No I/O. */
|
|
53
64
|
export function getCachedSections(): TemplateSections | null {
|
|
54
65
|
return cachedSections;
|
|
55
66
|
}
|
|
@@ -141,6 +141,11 @@ function schemaFor(args: VerbArg[]): Record<string, z.ZodString | z.ZodOptional<
|
|
|
141
141
|
return shape;
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
+
/**
|
|
145
|
+
* Register one MCP prompt per {@link VERBS} entry. Each prompt exposes only the
|
|
146
|
+
* args that verb uses, loads its recipe body lazily on invocation (via
|
|
147
|
+
* `loadVerb`), and wraps it with the per-call header from {@link buildVerbPrompt}.
|
|
148
|
+
*/
|
|
144
149
|
export function registerDesignPrompts(server: McpServer): void {
|
|
145
150
|
for (const verb of VERBS) {
|
|
146
151
|
server.prompt(verb.name, verb.summary, schemaFor(verb.args), async (args: VerbArgs) => {
|
package/src/resources/catalog.ts
CHANGED
|
@@ -2,6 +2,12 @@ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
2
2
|
import { loadCatalog } from '../data/catalog-loader.js';
|
|
3
3
|
import { formatCompactCatalog } from '../utils/format-catalog.js';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Register the `urbicon://catalog` resource: the whole component catalog as
|
|
7
|
+
* compact markdown (the same `formatCompactCatalog` render as `find_components`
|
|
8
|
+
* with no query). Lets a client pin the catalog as context instead of calling
|
|
9
|
+
* the tool.
|
|
10
|
+
*/
|
|
5
11
|
export function registerCatalogResource(server: McpServer): void {
|
|
6
12
|
server.resource('catalog', 'urbicon://catalog', async (uri) => {
|
|
7
13
|
const catalog = await loadCatalog();
|
package/src/resources/guides.ts
CHANGED
|
@@ -2,6 +2,11 @@ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
2
2
|
import type { TemplateSections } from '../data/template-loader.js';
|
|
3
3
|
import { loadTemplateSections } from '../data/template-loader.js';
|
|
4
4
|
|
|
5
|
+
/**
|
|
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`.
|
|
9
|
+
*/
|
|
5
10
|
const GUIDE_RESOURCES: { id: string; name: string; key: keyof TemplateSections }[] = [
|
|
6
11
|
{
|
|
7
12
|
id: 'api-grammar',
|
|
@@ -40,6 +45,11 @@ const GUIDE_RESOURCES: { id: string; name: string; key: keyof TemplateSections }
|
|
|
40
45
|
}
|
|
41
46
|
];
|
|
42
47
|
|
|
48
|
+
/**
|
|
49
|
+
* 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.
|
|
52
|
+
*/
|
|
43
53
|
export function registerGuideResources(server: McpServer): void {
|
|
44
54
|
for (const guide of GUIDE_RESOURCES) {
|
|
45
55
|
server.resource(`guide-${guide.id}`, `urbicon://guide/${guide.id}`, async (uri) => {
|
package/src/server.ts
CHANGED
|
@@ -13,6 +13,16 @@ import { registerGetRecipeTool } from './tools/get-recipe.js';
|
|
|
13
13
|
import { registerSuggestImplementationTool } from './tools/suggest-implementation.js';
|
|
14
14
|
import { registerValidateDesignTool } from './tools/validate-design.js';
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Assemble a fully-wired `urbicon-ui` MCP server: the two resources, the ten
|
|
18
|
+
* read-only tools, and the design-verb prompts. Deliberately stateless — it
|
|
19
|
+
* never reads or writes a consumer's design manifest (that lives in the
|
|
20
|
+
* consumer repo, via the `urbicon` CLI or the agent's own file tools), so a
|
|
21
|
+
* fresh instance can be created per HTTP session. Called by both transports.
|
|
22
|
+
*
|
|
23
|
+
* @returns A ready-to-connect `McpServer`; the caller attaches a transport
|
|
24
|
+
* (`startStdioTransport` / `startHttpTransport`).
|
|
25
|
+
*/
|
|
16
26
|
export function createServer(): McpServer {
|
|
17
27
|
const server = new McpServer({
|
|
18
28
|
name: 'urbicon-ui',
|
|
@@ -4,6 +4,13 @@ import { z } from 'zod';
|
|
|
4
4
|
import { loadCatalog } from '../data/catalog-loader.js';
|
|
5
5
|
import { formatCompactCatalog, formatComponentLine } from '../utils/format-catalog.js';
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Register the `find_components` tool: the catalog entry point. With no query it
|
|
9
|
+
* renders the full catalog grouped by category (via `formatCompactCatalog`);
|
|
10
|
+
* with a query it fuzzy-matches names/descriptions/tags through the engine's
|
|
11
|
+
* `matchComponents` (top 10). Every line keeps the origin-package tag so a
|
|
12
|
+
* non-blocks match (e.g. `Table`) is never mistaken for a blocks export.
|
|
13
|
+
*/
|
|
7
14
|
export function registerFindComponentsTool(server: McpServer): void {
|
|
8
15
|
server.tool(
|
|
9
16
|
'find_components',
|
package/src/tools/find-icons.ts
CHANGED
|
@@ -2,6 +2,12 @@ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
2
2
|
import { ICON_CATEGORY_ORDER } from '@urbicon-ui/design-engine/search';
|
|
3
3
|
import { loadIcons } from '../data/icon-loader.js';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Register the `find_icons` tool (no arguments): render the full icon reference
|
|
7
|
+
* — usage snippets plus every icon grouped by `ICON_CATEGORY_ORDER`, each listed
|
|
8
|
+
* as component name + dynamic `name`. Degrades to a hint when the icon bundle is
|
|
9
|
+
* unavailable (see {@link loadIcons}).
|
|
10
|
+
*/
|
|
5
11
|
export function registerFindIconsTool(server: McpServer): void {
|
|
6
12
|
server.tool(
|
|
7
13
|
'find_icons',
|
|
@@ -2,6 +2,13 @@ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { loadCatalog } from '../data/catalog-loader.js';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Register the `get_implementation_checklist` tool: emit the static best-practice
|
|
7
|
+
* checklist (setup, tokens, styling, a11y, i18n, design quality). When
|
|
8
|
+
* `components` are supplied, append a per-component notes section (variants,
|
|
9
|
+
* slots, related) resolved from the catalog. Overlaps the rules that
|
|
10
|
+
* `suggest_implementation` inlines — this is the standalone entry point.
|
|
11
|
+
*/
|
|
5
12
|
export function registerGetChecklistTool(server: McpServer): void {
|
|
6
13
|
server.tool(
|
|
7
14
|
'get_implementation_checklist',
|
|
@@ -127,6 +127,13 @@ function generateCompactView(entry: ComponentCatalogEntry, llmContent: string):
|
|
|
127
127
|
return md;
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
+
/**
|
|
131
|
+
* Register the `get_component` tool: per-component API docs at three depths —
|
|
132
|
+
* a compact catalog+llm.txt summary (default), one named `section`, or the full
|
|
133
|
+
* llm.txt (`section="full"`). Unknown slugs return a find_components hint; a
|
|
134
|
+
* slug present in llm.txt but absent from the catalog falls back to full content
|
|
135
|
+
* rather than failing.
|
|
136
|
+
*/
|
|
130
137
|
export function registerGetComponentTool(server: McpServer): void {
|
|
131
138
|
server.tool(
|
|
132
139
|
'get_component',
|
|
@@ -9,6 +9,12 @@ import { z } from 'zod';
|
|
|
9
9
|
// `urbicon css-reference` CLI command so local and remote answers agree; this tool is
|
|
10
10
|
// only the MCP facade. Drift against the real blocks CSS is guarded by the engine's
|
|
11
11
|
// `css-reference.test.ts`.
|
|
12
|
+
/**
|
|
13
|
+
* Register the `get_css_reference` tool: a pure facade over the engine's
|
|
14
|
+
* `renderCssReference`. Returns the token overview (naming + dark-mode
|
|
15
|
+
* mechanism) or a single category section. All text lives in the engine, shared
|
|
16
|
+
* with `urbicon css-reference`, so this file holds no reference content itself.
|
|
17
|
+
*/
|
|
12
18
|
export function registerGetCssReferenceTool(server: McpServer): void {
|
|
13
19
|
server.tool(
|
|
14
20
|
'get_css_reference',
|
|
@@ -7,6 +7,13 @@ import {
|
|
|
7
7
|
PRINCIPLE_TOPICS
|
|
8
8
|
} from '../data/design-system-loader.js';
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Register the `get_design_principles` tool with two output modes. `as="guide"`
|
|
12
|
+
* (default) returns the heuristics from `principles.md` — whole, or one `topic`
|
|
13
|
+
* section. `as="rubric"` instead renders the engine's scoring rubric (via
|
|
14
|
+
* `renderRubric`) and ignores `topic`. Missing principles content degrades to a
|
|
15
|
+
* hint rather than throwing.
|
|
16
|
+
*/
|
|
10
17
|
export function registerGetDesignPrinciplesTool(server: McpServer): void {
|
|
11
18
|
server.tool(
|
|
12
19
|
'get_design_principles',
|
package/src/tools/get-pattern.ts
CHANGED
|
@@ -2,6 +2,12 @@ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { getPatternByName, loadPatterns } from '../data/design-system-loader.js';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Register the `get_pattern` tool: one composition pattern's full content by
|
|
7
|
+
* `name`, or — when `name` is omitted — the list of available patterns. An
|
|
8
|
+
* unknown name echoes the valid names back. Patterns are loaded/cached by
|
|
9
|
+
* `design-system-loader`.
|
|
10
|
+
*/
|
|
5
11
|
export function registerGetPatternTool(server: McpServer): void {
|
|
6
12
|
server.tool(
|
|
7
13
|
'get_pattern',
|
package/src/tools/get-recipe.ts
CHANGED
|
@@ -2,6 +2,12 @@ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { loadCatalog } from '../data/catalog-loader.js';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Register the `get_recipe` tool: return a full, production-ready recipe (title,
|
|
7
|
+
* pattern link, components, features, code) by id. Recipes travel inside the
|
|
8
|
+
* catalog — no separate source read — so an unknown id lists every available id
|
|
9
|
+
* from the same catalog load.
|
|
10
|
+
*/
|
|
5
11
|
export function registerGetRecipeTool(server: McpServer): void {
|
|
6
12
|
server.tool(
|
|
7
13
|
'get_recipe',
|
|
@@ -86,6 +86,14 @@ const IMPLEMENTATION_RULES = `## Implementation Rules
|
|
|
86
86
|
- **Don't copy recipe styling** — Recipes show ONE interpretation. Create YOUR visual identity with your own spacing rhythm, color distribution, and layout density.
|
|
87
87
|
`;
|
|
88
88
|
|
|
89
|
+
/**
|
|
90
|
+
* Register the `suggest_implementation` tool: assemble a Svelte 5 skeleton from
|
|
91
|
+
* either explicit component names (looked up in the catalog) or a free-text
|
|
92
|
+
* description (matched via the engine). Emits imports, a per-component prop/
|
|
93
|
+
* variant digest, a skeleton built from `SKELETON_HINTS`, the inlined
|
|
94
|
+
* `IMPLEMENTATION_RULES` (so no follow-up checklist call is needed), and any
|
|
95
|
+
* recipe whose id substring-matches or that shares ≥40% of the matched set.
|
|
96
|
+
*/
|
|
89
97
|
export function registerSuggestImplementationTool(server: McpServer): void {
|
|
90
98
|
server.tool(
|
|
91
99
|
'suggest_implementation',
|
|
@@ -56,6 +56,13 @@ function renderReport(report: LintReport): string {
|
|
|
56
56
|
return md;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Register the `validate_design` tool: a thin facade over the engine's
|
|
61
|
+
* `lintDesign`. It renders the {@link LintReport} into markdown (findings
|
|
62
|
+
* grouped by severity, with per-finding fixes and the two scores) but adds no
|
|
63
|
+
* rules of its own — the linter is shared verbatim with the `urbicon validate`
|
|
64
|
+
* CLI, so local and remote verdicts agree.
|
|
65
|
+
*/
|
|
59
66
|
export function registerValidateDesignTool(server: McpServer): void {
|
|
60
67
|
server.tool(
|
|
61
68
|
'validate_design',
|
package/src/transports/http.ts
CHANGED
|
@@ -2,6 +2,20 @@ import { createServer as createHttpServer } from 'node:http';
|
|
|
2
2
|
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
3
3
|
import { createServer as createMcpServer } from '../server.js';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Serve the MCP over Streamable HTTP on `/mcp`, multiplexing clients by the
|
|
7
|
+
* `mcp-session-id` header. Each session gets its own server + transport pair:
|
|
8
|
+
* - `POST` **without** a session id opens one (fresh {@link createServer}, a
|
|
9
|
+
* generated id) and remains registered until the transport closes;
|
|
10
|
+
* - `POST`/`GET`/`DELETE` **with** a known id are routed to that session;
|
|
11
|
+
* - a `POST` carrying an **unknown** id, or a session-less `GET`/`DELETE`, is a
|
|
12
|
+
* `400` — the stateless server never resurrects a session it did not open.
|
|
13
|
+
*
|
|
14
|
+
* Any non-`/mcp` path returns a plain-text banner (a lightweight liveness ping).
|
|
15
|
+
* Runs until the process exits; there is no returned stop handle.
|
|
16
|
+
*
|
|
17
|
+
* @param port - TCP port to listen on (binds `http://localhost:<port>/mcp`).
|
|
18
|
+
*/
|
|
5
19
|
export async function startHttpTransport(port: number): Promise<void> {
|
|
6
20
|
const sessions = new Map<string, StreamableHTTPServerTransport>();
|
|
7
21
|
|
package/src/transports/stdio.ts
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
2
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Connect an assembled server over stdio — the transport for a local, single-
|
|
6
|
+
* client host (one server instance per process; the client speaks JSON-RPC on
|
|
7
|
+
* stdin/stdout). For a shared network endpoint use {@link startHttpTransport}.
|
|
8
|
+
*
|
|
9
|
+
* @param server - A server from {@link createServer}.
|
|
10
|
+
*/
|
|
4
11
|
export async function startStdioTransport(server: McpServer): Promise<void> {
|
|
5
12
|
const transport = new StdioServerTransport();
|
|
6
13
|
await server.connect(transport);
|
|
@@ -23,12 +23,29 @@ const TAG_LABELS: Record<string, string> = {
|
|
|
23
23
|
data: 'Data'
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
+
/**
|
|
27
|
+
* Drop the docs-site-only components (`ApiReference`, `CodeExample`, …) that
|
|
28
|
+
* ship in the assembled catalog but are not consumer-facing API, so they never
|
|
29
|
+
* surface in `find_components` / the catalog resource.
|
|
30
|
+
*/
|
|
26
31
|
export function filterInternalComponents(
|
|
27
32
|
components: ComponentCatalogEntry[]
|
|
28
33
|
): ComponentCatalogEntry[] {
|
|
29
34
|
return components.filter((c) => !INTERNAL_COMPONENTS.has(c.name));
|
|
30
35
|
}
|
|
31
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Render the browse-view markdown: internal components filtered out, the rest
|
|
39
|
+
* bucketed by their primary tag in a fixed section order (`TAG_ORDER`, unknown
|
|
40
|
+
* tags → "Other"), preceded by the install/CSS/dark-mode setup block and
|
|
41
|
+
* followed by the recipe list. Shared by `find_components` (no query) and the
|
|
42
|
+
* catalog resource.
|
|
43
|
+
*
|
|
44
|
+
* @param components - Full catalog entries (internal ones are removed here).
|
|
45
|
+
* @param options - `tags` narrows to matching categories (case-insensitive);
|
|
46
|
+
* `recipes` appends the recipe index.
|
|
47
|
+
* @returns Markdown document.
|
|
48
|
+
*/
|
|
32
49
|
export function formatCompactCatalog(
|
|
33
50
|
components: ComponentCatalogEntry[],
|
|
34
51
|
options?: { recipes?: RecipeEntry[]; tags?: string[] }
|
|
@@ -111,6 +128,12 @@ function isBooleanVariant(values: string[]): boolean {
|
|
|
111
128
|
);
|
|
112
129
|
}
|
|
113
130
|
|
|
131
|
+
/**
|
|
132
|
+
* Format one catalog entry as a single markdown bullet: name, an origin-package
|
|
133
|
+
* tag for non-blocks components (so `Table` reads as `@urbicon-ui/table`), the
|
|
134
|
+
* description, its meaningful (non-boolean) variants, and related components.
|
|
135
|
+
* The one line shape shared by the browse and search views.
|
|
136
|
+
*/
|
|
114
137
|
export function formatComponentLine(comp: ComponentCatalogEntry): string {
|
|
115
138
|
const variants = comp.variants
|
|
116
139
|
.filter((v) => !isBooleanVariant(v.values))
|