@urbicon-ui/mcp-server 6.25.0 → 6.26.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 +9 -3
- package/dist/data/catalog-loader.d.ts +0 -37
- package/dist/data/catalog-loader.d.ts.map +0 -1
- package/dist/data/catalog-loader.js +0 -15
- package/dist/data/catalog-loader.js.map +0 -1
- package/dist/data/component-loader.d.ts +0 -2
- package/dist/data/component-loader.d.ts.map +0 -1
- package/dist/data/component-loader.js +0 -17
- package/dist/data/component-loader.js.map +0 -1
- package/dist/data/recipe-loader.d.ts +0 -4
- package/dist/data/recipe-loader.d.ts.map +0 -1
- package/dist/data/recipe-loader.js +0 -102
- package/dist/data/recipe-loader.js.map +0 -1
- package/dist/data/template-loader.d.ts +0 -8
- package/dist/data/template-loader.d.ts.map +0 -1
- package/dist/data/template-loader.js +0 -33
- package/dist/data/template-loader.js.map +0 -1
- package/dist/index.d.ts +0 -3
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -57
- package/dist/index.js.map +0 -1
- package/dist/resources/catalog.d.ts +0 -3
- package/dist/resources/catalog.d.ts.map +0 -1
- package/dist/resources/catalog.js +0 -20
- package/dist/resources/catalog.js.map +0 -1
- package/dist/resources/component.d.ts +0 -3
- package/dist/resources/component.d.ts.map +0 -1
- package/dist/resources/component.js +0 -29
- package/dist/resources/component.js.map +0 -1
- package/dist/resources/guides.d.ts +0 -3
- package/dist/resources/guides.d.ts.map +0 -1
- package/dist/resources/guides.js +0 -36
- package/dist/resources/guides.js.map +0 -1
- package/dist/server.d.ts +0 -3
- package/dist/server.d.ts.map +0 -1
- package/dist/server.js.map +0 -1
- package/dist/tools/find-components.d.ts +0 -3
- package/dist/tools/find-components.d.ts.map +0 -1
- package/dist/tools/find-components.js +0 -21
- package/dist/tools/find-components.js.map +0 -1
- package/dist/tools/get-recipe.d.ts +0 -3
- package/dist/tools/get-recipe.d.ts.map +0 -1
- package/dist/tools/get-recipe.js +0 -48
- package/dist/tools/get-recipe.js.map +0 -1
- package/dist/tools/suggest-implementation.d.ts +0 -3
- package/dist/tools/suggest-implementation.d.ts.map +0 -1
- package/dist/tools/suggest-implementation.js +0 -178
- package/dist/tools/suggest-implementation.js.map +0 -1
- package/dist/transports/http.d.ts +0 -2
- package/dist/transports/http.d.ts.map +0 -1
- package/dist/transports/http.js +0 -77
- package/dist/transports/http.js.map +0 -1
- package/dist/transports/stdio.d.ts +0 -3
- package/dist/transports/stdio.d.ts.map +0 -1
- package/dist/transports/stdio.js +0 -6
- package/dist/transports/stdio.js.map +0 -1
- package/dist/tsconfig.tsbuildinfo +0 -1
- package/dist/utils/format-catalog.d.ts +0 -7
- package/dist/utils/format-catalog.d.ts.map +0 -1
- package/dist/utils/format-catalog.js +0 -93
- package/dist/utils/format-catalog.js.map +0 -1
- package/dist/utils/paths.d.ts +0 -7
- package/dist/utils/paths.d.ts.map +0 -1
- package/dist/utils/paths.js +0 -23
- package/dist/utils/paths.js.map +0 -1
- package/dist/utils/search.d.ts +0 -3
- package/dist/utils/search.d.ts.map +0 -1
- package/dist/utils/search.js +0 -44
- package/dist/utils/search.js.map +0 -1
- package/src/data/catalog-loader.test.ts +0 -42
- package/src/data/design-system-loader.test.ts +0 -82
- package/src/data/icon-loader.test.ts +0 -30
- package/src/eval/briefs.ts +0 -104
- package/src/eval/eval.test.ts +0 -106
- package/src/eval/index.ts +0 -11
- package/src/eval/score.ts +0 -128
- package/src/prompts/design-prompts.test.ts +0 -79
- package/src/server.test.ts +0 -78
- package/src/utils/format-catalog.test.ts +0 -144
- package/tsconfig.json +0 -27
- package/vitest.config.ts +0 -15
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { loadVerb } from '../data/verb-loader.js';
|
|
3
|
-
import { buildVerbPrompt, variantCount } from './design-prompts.js';
|
|
4
|
-
|
|
5
|
-
/** The full §8 verb table — every recipe must be present in the bundle. */
|
|
6
|
-
const VERB_NAMES = [
|
|
7
|
-
'onboard',
|
|
8
|
-
'adopt',
|
|
9
|
-
'compose',
|
|
10
|
-
'redesign',
|
|
11
|
-
'polish',
|
|
12
|
-
'critique',
|
|
13
|
-
'fix',
|
|
14
|
-
'retheme',
|
|
15
|
-
'audit',
|
|
16
|
-
'migrate'
|
|
17
|
-
];
|
|
18
|
-
|
|
19
|
-
describe('variantCount', () => {
|
|
20
|
-
it('defaults to 3 for missing or non-numeric input', () => {
|
|
21
|
-
expect(variantCount(undefined)).toBe(3);
|
|
22
|
-
expect(variantCount('abc')).toBe(3);
|
|
23
|
-
});
|
|
24
|
-
it('clamps to the 2–5 range', () => {
|
|
25
|
-
expect(variantCount('1')).toBe(2);
|
|
26
|
-
expect(variantCount('9')).toBe(5);
|
|
27
|
-
expect(variantCount('4')).toBe(4);
|
|
28
|
-
});
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
describe('buildVerbPrompt', () => {
|
|
32
|
-
const body = '1. **Context.** Read the manifest.\n2. **Validate.** Run the linter.';
|
|
33
|
-
|
|
34
|
-
it('frames the verb and includes the recipe body', () => {
|
|
35
|
-
const p = buildVerbPrompt('compose', body, {});
|
|
36
|
-
expect(p).toContain('**compose** design recipe');
|
|
37
|
-
expect(p).toContain('Read the manifest');
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it('embeds the brief as a blockquote when provided', () => {
|
|
41
|
-
expect(buildVerbPrompt('compose', body, { brief: 'a billing page' })).toContain(
|
|
42
|
-
'> **a billing page**'
|
|
43
|
-
);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it('inlines provided code in a svelte fence', () => {
|
|
47
|
-
const p = buildVerbPrompt('redesign', body, { code: '<div>old</div>' });
|
|
48
|
-
expect(p).toContain('```svelte\n<div>old</div>\n```');
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it('appends a clamped variant instruction when variants are requested', () => {
|
|
52
|
-
expect(buildVerbPrompt('compose', body, { variants: '9' })).toContain('explore exactly 5');
|
|
53
|
-
expect(buildVerbPrompt('compose', body, { variants: '1' })).toContain('explore exactly 2');
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it('degrades to a rebuild hint when the body is empty', () => {
|
|
57
|
-
expect(buildVerbPrompt('compose', '', {})).toContain('rebuild the design-content bundle');
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
describe('loadVerb (against the bundled recipes)', () => {
|
|
62
|
-
it('loads every verb in the §8 table, non-empty', async () => {
|
|
63
|
-
for (const name of VERB_NAMES) {
|
|
64
|
-
const body = await loadVerb(name);
|
|
65
|
-
expect(body.length, name).toBeGreaterThan(0);
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
it('a recipe opens by reading the manifest and references the real tool surface', async () => {
|
|
70
|
-
const compose = await loadVerb('compose');
|
|
71
|
-
expect(compose).toContain('manifest');
|
|
72
|
-
expect(compose).toContain('validate_design');
|
|
73
|
-
expect(compose).toContain('get_design_principles(as="rubric")');
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
it('returns the empty string for an unknown verb (read tolerant)', async () => {
|
|
77
|
-
expect(await loadVerb('does-not-exist')).toBe('');
|
|
78
|
-
});
|
|
79
|
-
});
|
package/src/server.test.ts
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { createServer } from './server.js';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Smoke tests for the MCP server assembly. The SDK's `McpServer` keeps its
|
|
6
|
-
* tool/resource maps on private fields (`_registeredTools`, `_registeredResources`,
|
|
7
|
-
* `_registeredResourceTemplates`). We deliberately reach into those here because
|
|
8
|
-
* the point of this test is to guard the wiring in `server.ts` — if a tool
|
|
9
|
-
* registration goes missing or is renamed, this file should tell us about it.
|
|
10
|
-
*/
|
|
11
|
-
interface McpServerInternals {
|
|
12
|
-
_registeredTools: Record<string, unknown>;
|
|
13
|
-
_registeredResources: Record<string, unknown>;
|
|
14
|
-
_registeredResourceTemplates: Record<string, unknown>;
|
|
15
|
-
_registeredPrompts: Record<string, unknown>;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const EXPECTED_TOOLS = [
|
|
19
|
-
'find_components',
|
|
20
|
-
'get_component',
|
|
21
|
-
'get_recipe',
|
|
22
|
-
'suggest_implementation',
|
|
23
|
-
'get_implementation_checklist',
|
|
24
|
-
'get_css_reference',
|
|
25
|
-
'find_icons',
|
|
26
|
-
'get_design_principles',
|
|
27
|
-
'get_pattern',
|
|
28
|
-
'validate_design'
|
|
29
|
-
] as const;
|
|
30
|
-
|
|
31
|
-
describe('createServer', () => {
|
|
32
|
-
it('boots without throwing', () => {
|
|
33
|
-
expect(() => createServer()).not.toThrow();
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it('returns an object', () => {
|
|
37
|
-
const server = createServer();
|
|
38
|
-
expect(server).toBeTypeOf('object');
|
|
39
|
-
expect(server).not.toBeNull();
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it('registers exactly the expected set of tools', () => {
|
|
43
|
-
const server = createServer() as unknown as McpServerInternals;
|
|
44
|
-
const toolNames = Object.keys(server._registeredTools);
|
|
45
|
-
|
|
46
|
-
for (const expected of EXPECTED_TOOLS) {
|
|
47
|
-
expect(toolNames, `missing tool: ${expected}`).toContain(expected);
|
|
48
|
-
}
|
|
49
|
-
expect(toolNames).toHaveLength(EXPECTED_TOOLS.length);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it('registers at least one catalog resource', () => {
|
|
53
|
-
const server = createServer() as unknown as McpServerInternals;
|
|
54
|
-
const resourceCount =
|
|
55
|
-
Object.keys(server._registeredResources).length +
|
|
56
|
-
Object.keys(server._registeredResourceTemplates).length;
|
|
57
|
-
expect(resourceCount).toBeGreaterThan(0);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it('registers the full design-verb table as prompts', () => {
|
|
61
|
-
const server = createServer() as unknown as McpServerInternals;
|
|
62
|
-
const promptNames = Object.keys(server._registeredPrompts);
|
|
63
|
-
for (const verb of [
|
|
64
|
-
'onboard',
|
|
65
|
-
'adopt',
|
|
66
|
-
'compose',
|
|
67
|
-
'redesign',
|
|
68
|
-
'polish',
|
|
69
|
-
'critique',
|
|
70
|
-
'fix',
|
|
71
|
-
'retheme',
|
|
72
|
-
'audit',
|
|
73
|
-
'migrate'
|
|
74
|
-
]) {
|
|
75
|
-
expect(promptNames, verb).toContain(verb);
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
});
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import type { ComponentCatalogEntry, RecipeEntry } from '../data/catalog-loader.js';
|
|
3
|
-
import { filterInternalComponents, formatCompactCatalog } from './format-catalog.js';
|
|
4
|
-
|
|
5
|
-
function makeEntry(
|
|
6
|
-
overrides: Partial<ComponentCatalogEntry> & Pick<ComponentCatalogEntry, 'name' | 'slug'>
|
|
7
|
-
): ComponentCatalogEntry {
|
|
8
|
-
return {
|
|
9
|
-
package: '@urbicon-ui/blocks',
|
|
10
|
-
group: 'primitives',
|
|
11
|
-
description: 'desc',
|
|
12
|
-
tags: [],
|
|
13
|
-
import: `import { ${overrides.name} } from '@urbicon-ui/blocks';`,
|
|
14
|
-
llmTxtPath: '',
|
|
15
|
-
variants: [],
|
|
16
|
-
keyProps: [],
|
|
17
|
-
keyPropTypes: {},
|
|
18
|
-
slots: [],
|
|
19
|
-
hasExamples: false,
|
|
20
|
-
relatedComponents: [],
|
|
21
|
-
...overrides
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
describe('filterInternalComponents', () => {
|
|
26
|
-
it('removes docs-site-internal components from the list', () => {
|
|
27
|
-
const entries = [
|
|
28
|
-
makeEntry({ name: 'Button', slug: 'button' }),
|
|
29
|
-
makeEntry({ name: 'ApiReference', slug: 'api-reference' }),
|
|
30
|
-
makeEntry({ name: 'PlaygroundConfigurator', slug: 'playground-configurator' }),
|
|
31
|
-
makeEntry({ name: 'Input', slug: 'input' })
|
|
32
|
-
];
|
|
33
|
-
const result = filterInternalComponents(entries);
|
|
34
|
-
expect(result.map((e) => e.name)).toEqual(['Button', 'Input']);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it('returns an empty list when all entries are internal', () => {
|
|
38
|
-
const entries = [
|
|
39
|
-
makeEntry({ name: 'DocsLayout', slug: 'docs-layout' }),
|
|
40
|
-
makeEntry({ name: 'InfoCard', slug: 'info-card' })
|
|
41
|
-
];
|
|
42
|
-
expect(filterInternalComponents(entries)).toEqual([]);
|
|
43
|
-
});
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
describe('formatCompactCatalog', () => {
|
|
47
|
-
const button = makeEntry({
|
|
48
|
-
name: 'Button',
|
|
49
|
-
slug: 'button',
|
|
50
|
-
description: 'Click to do things',
|
|
51
|
-
tags: ['action'],
|
|
52
|
-
variants: [{ name: 'intent', values: ['primary', 'danger'] }]
|
|
53
|
-
});
|
|
54
|
-
const input = makeEntry({
|
|
55
|
-
name: 'Input',
|
|
56
|
-
slug: 'input',
|
|
57
|
-
description: 'Text field',
|
|
58
|
-
tags: ['form'],
|
|
59
|
-
relatedComponents: ['Textarea']
|
|
60
|
-
});
|
|
61
|
-
const alert = makeEntry({
|
|
62
|
-
name: 'Alert',
|
|
63
|
-
slug: 'alert',
|
|
64
|
-
description: 'Inline message',
|
|
65
|
-
tags: ['feedback']
|
|
66
|
-
});
|
|
67
|
-
const orphan = makeEntry({
|
|
68
|
-
name: 'Mystery',
|
|
69
|
-
slug: 'mystery',
|
|
70
|
-
description: 'No primary tag here',
|
|
71
|
-
tags: ['unknown']
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
it('outputs a markdown document with the component count', () => {
|
|
75
|
-
const md = formatCompactCatalog([button, input]);
|
|
76
|
-
expect(md).toContain('# Urbicon UI Components');
|
|
77
|
-
expect(md).toContain('> 2 components available.');
|
|
78
|
-
expect(md).toContain('get_component');
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
it('groups components by their primary tag in the canonical order', () => {
|
|
82
|
-
const md = formatCompactCatalog([alert, button, input]);
|
|
83
|
-
const actionIdx = md.indexOf('## Actions');
|
|
84
|
-
const formsIdx = md.indexOf('## Forms');
|
|
85
|
-
const feedbackIdx = md.indexOf('## Feedback & Status');
|
|
86
|
-
expect(actionIdx).toBeGreaterThan(-1);
|
|
87
|
-
expect(formsIdx).toBeGreaterThan(actionIdx);
|
|
88
|
-
expect(feedbackIdx).toBeGreaterThan(formsIdx);
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
it('puts components with unrecognised primary tags in the Other bucket', () => {
|
|
92
|
-
const md = formatCompactCatalog([orphan]);
|
|
93
|
-
expect(md).toContain('## Other');
|
|
94
|
-
expect(md).toContain('Mystery');
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
it('renders variant details when a non-boolean variant is present', () => {
|
|
98
|
-
const md = formatCompactCatalog([button]);
|
|
99
|
-
expect(md).toContain('intent: primary/danger');
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
it('omits boolean-only variants from the rendered line', () => {
|
|
103
|
-
const withBool = makeEntry({
|
|
104
|
-
name: 'Toggle',
|
|
105
|
-
slug: 'toggle',
|
|
106
|
-
description: 'On/off',
|
|
107
|
-
tags: ['form'],
|
|
108
|
-
variants: [{ name: 'checked', values: ['true', 'false'] }]
|
|
109
|
-
});
|
|
110
|
-
const md = formatCompactCatalog([withBool]);
|
|
111
|
-
expect(md).not.toContain('checked: true/false');
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
it('renders a Related hint when related components exist', () => {
|
|
115
|
-
const md = formatCompactCatalog([input]);
|
|
116
|
-
expect(md).toContain('Related: Textarea');
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
it('filters by the tags option', () => {
|
|
120
|
-
const md = formatCompactCatalog([button, input, alert], { tags: ['form'] });
|
|
121
|
-
// Matching the bold-component-bullet prefix avoids false positives from
|
|
122
|
-
// the Quick-Setup section (which itself references `Button` in code).
|
|
123
|
-
expect(md).toContain('- **Input**');
|
|
124
|
-
expect(md).not.toContain('- **Button**');
|
|
125
|
-
expect(md).not.toContain('- **Alert**');
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
it('appends a Recipes section when recipes are supplied', () => {
|
|
129
|
-
const recipes: RecipeEntry[] = [
|
|
130
|
-
{
|
|
131
|
-
id: 'login-form',
|
|
132
|
-
title: 'Login',
|
|
133
|
-
description: 'Login screen',
|
|
134
|
-
components: ['Input', 'Button'],
|
|
135
|
-
code: '',
|
|
136
|
-
features: []
|
|
137
|
-
}
|
|
138
|
-
];
|
|
139
|
-
const md = formatCompactCatalog([button, input], { recipes });
|
|
140
|
-
expect(md).toContain('## Recipes');
|
|
141
|
-
expect(md).toContain('**login-form**');
|
|
142
|
-
expect(md).toContain('Input, Button');
|
|
143
|
-
});
|
|
144
|
-
});
|
package/tsconfig.json
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2022",
|
|
4
|
-
"module": "ESNext",
|
|
5
|
-
"moduleResolution": "bundler",
|
|
6
|
-
"outDir": "./dist",
|
|
7
|
-
"rootDir": "./src",
|
|
8
|
-
"composite": true,
|
|
9
|
-
"declaration": true,
|
|
10
|
-
"declarationMap": true,
|
|
11
|
-
"sourceMap": true,
|
|
12
|
-
"strict": true,
|
|
13
|
-
"esModuleInterop": true,
|
|
14
|
-
"forceConsistentCasingInFileNames": true,
|
|
15
|
-
"isolatedModules": true,
|
|
16
|
-
"skipLibCheck": true,
|
|
17
|
-
"resolveJsonModule": true,
|
|
18
|
-
"verbatimModuleSyntax": true,
|
|
19
|
-
"noImplicitReturns": true,
|
|
20
|
-
"noFallthroughCasesInSwitch": true,
|
|
21
|
-
"noUncheckedIndexedAccess": true,
|
|
22
|
-
"types": ["node"],
|
|
23
|
-
"tsBuildInfoFile": "./dist/tsconfig.tsbuildinfo"
|
|
24
|
-
},
|
|
25
|
-
"include": ["src/**/*"],
|
|
26
|
-
"exclude": ["node_modules", "dist"]
|
|
27
|
-
}
|
package/vitest.config.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from 'vitest/config';
|
|
2
|
-
|
|
3
|
-
export default defineConfig({
|
|
4
|
-
test: {
|
|
5
|
-
// zod@4's ESM layout needs to be inlined so vitest's vite-ssr runner
|
|
6
|
-
// resolves the named export correctly; otherwise `z.string` comes back
|
|
7
|
-
// as undefined inside the tool modules.
|
|
8
|
-
server: {
|
|
9
|
-
deps: {
|
|
10
|
-
inline: ['zod']
|
|
11
|
-
}
|
|
12
|
-
},
|
|
13
|
-
include: ['src/**/*.test.ts']
|
|
14
|
-
}
|
|
15
|
-
});
|