@kazee-ds/mcp 0.0.0-stage → 0.1.3

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,50 @@
1
1
  {
2
2
  "name": "@kazee-ds/mcp",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.1.3",
4
+ "description": "Versioned React and Vue documentation tools for Kazee Design System agents",
5
+ "type": "module",
6
+ "bin": {
7
+ "kazee-mcp": "./bin/kazee-mcp.mjs"
8
+ },
9
+ "files": [
10
+ "bin",
11
+ "src",
12
+ "dist",
13
+ "README.md"
14
+ ],
15
+ "license": "UNLICENSED",
16
+ "engines": {
17
+ "node": ">=22.16.0"
18
+ },
19
+ "dependencies": {
20
+ "@modelcontextprotocol/sdk": "1.32.1",
21
+ "zod": "4.6.6"
22
+ },
23
+ "devDependencies": {
24
+ "typescript": "~5.9.3",
25
+ "publint": "^0.3.25",
26
+ "@types/react": "^19.3.0",
27
+ "react": "^19.3.0",
28
+ "vue": "^3.5.32",
29
+ "vue-tsc": "^3.3.12",
30
+ "@kazee-ds/react": "0.5.0",
31
+ "@kazee-ds/vue": "0.5.0",
32
+ "@kazee-ds/styles": "0.5.0",
33
+ "@kazee-ds/tokens": "0.4.0"
34
+ },
35
+ "publishConfig": {
36
+ "access": "public",
37
+ "registry": "https://registry.npmjs.org/"
38
+ },
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "git+https://gitlab.com/kazee.indonesia/kazee-design-system.git",
42
+ "directory": "packages/mcp"
43
+ },
44
+ "homepage": "https://kazee-design-system-023417.gitlab.io",
45
+ "scripts": {
46
+ "build": "node scripts/build.mjs && node --check bin/kazee-mcp.mjs && node --check src/server.mjs",
47
+ "test": "node --test test/*.test.mjs",
48
+ "lint:package": "publint --strict"
49
+ }
6
50
  }
@@ -0,0 +1,66 @@
1
+ import { readFileSync } from 'node:fs';
2
+
3
+ export function loadCatalog() {
4
+ return JSON.parse(readFileSync(new URL('../dist/catalog.json', import.meta.url), 'utf8'));
5
+ }
6
+ export function selectCatalog(data, framework, version) {
7
+ const catalog = data.catalogs.find((item) => item.version === version);
8
+ if (!catalog || !catalog.frameworks[framework])
9
+ throw new Error(
10
+ `Unsupported ${framework} version ${version}. Supported exact versions: ${data.catalogs.map((item) => item.version).join(', ')}. Read the installed public package.json version or lockfile; do not guess or use a semver range.`,
11
+ );
12
+ return catalog;
13
+ }
14
+ export function selectComponent(catalog, framework, name) {
15
+ const component = Object.values(catalog.frameworks[framework]).find(
16
+ (item) => item.name.toLowerCase() === name.toLowerCase(),
17
+ );
18
+ if (!component)
19
+ throw new Error(
20
+ `${name} is not exported by @kazee-ds/${framework}@${catalog.version}. Use list_components for this exact version; do not import another library's component under the Kazee name.`,
21
+ );
22
+ return component;
23
+ }
24
+ export function context(catalog, framework) {
25
+ return {
26
+ framework,
27
+ version: catalog.version,
28
+ catalogStatus: catalog.status,
29
+ package: `@kazee-ds/${framework}`,
30
+ packages: catalog.packages,
31
+ provenance: catalog.provenance,
32
+ warning:
33
+ catalog.status === 'release-candidate'
34
+ ? 'This catalog was prepared from the current workspace. Registry publication is not verified by this offline server. The workspace selector is not an installation version; use matching local packed packages for testing.'
35
+ : undefined,
36
+ };
37
+ }
38
+ export function themeVariables(catalog, theme, query, limit) {
39
+ const flat = (tree, prefix = []) =>
40
+ Object.entries(tree).flatMap(([key, value]) =>
41
+ typeof value === 'string'
42
+ ? [{ name: `--ds-${[...prefix, key].join('-')}`, value }]
43
+ : flat(value, [...prefix, key]),
44
+ );
45
+ const primitive = new Map(flat(catalog.tokens.primitive).map((item) => [item.name, item.value]));
46
+ const semantic = flat(catalog.tokens.semantic[theme]).map((item) => ({
47
+ ...item,
48
+ cssValue: item.value.replace(
49
+ /\{([a-z0-9.-]+)\}/gi,
50
+ (_, ref) => `var(--ds-${ref.replaceAll('.', '-')})`,
51
+ ),
52
+ resolvedValue: item.value.replace(
53
+ /\{([a-z0-9.-]+)\}/gi,
54
+ (_, ref) => primitive.get(`--ds-${ref.replaceAll('.', '-')}`) ?? `{${ref}}`,
55
+ ),
56
+ }));
57
+ const filtered = semantic.filter((item) => item.name.toLowerCase().includes(query.toLowerCase()));
58
+ return {
59
+ theme,
60
+ total: filtered.length,
61
+ variables: filtered.slice(0, limit),
62
+ truncated: filtered.length > limit,
63
+ usage:
64
+ 'Use semantic --ds-* variables. Import @kazee-ds/styles/index.css once; it includes tokens. Switch themes with data-theme="light" or data-theme="dark" on a surrounding root. Application charts, maps and word clouds can consume these variables.',
65
+ };
66
+ }
package/src/guides.mjs ADDED
@@ -0,0 +1,60 @@
1
+ export const REGISTRY = 'https://registry.npmjs.org/';
2
+ export const guides = {
3
+ workflow:
4
+ 'Read get_catalog_versions, then the installed public @kazee-ds/react or @kazee-ds/vue package.json version (or exact lockfile version). Pass framework and that exact version to tools. A -workspace selector is only for explicitly reviewing this unpublished checkout or matching local packed artifacts; never substitute it for an installed registry release. Search list_components, read get_component_docs and get_component_examples before editing. Use public Kazee imports, never guessed HeroUI/Reka/React Aria props or package internals. Implement in the application. Run its existing lint, typecheck and build, then check keyboard, disabled/loading, clear/reset and relevant responsive interactions. Report missing or unrun checks. Stop dependency exploration after successful checks unless there is a concrete error. MCP tools return documentation; they do not execute commands, install packages, inspect the project, or validate its UI.',
5
+ composition:
6
+ 'Compose product dashboards in the application using Card, Tabs, controls and menus. Data fetching, routing, permissions, sorting, export actions, ranking, platform markers, avatar fallback and sentiment segments remain application-owned. Avatar is not currently exported. ECharts/map/word-cloud integration stays in the application. DataTable emits sort requests; it does not sort or fetch rows. Shortcut strings are display hints; register shortcuts in the application.',
7
+ styling:
8
+ 'Import @kazee-ds/styles/index.css once in the global application entry point. Use semantic --ds-* CSS variables and data-theme light/dark. Use documented component size/variant props and slots. Some components deliberately do not forward arbitrary HTML attributes; consult their API. Card and native table composition allow application layout wrappers. Preserve accessible names on icon-only controls. Use reduced-motion preferences; do not disable accessibility checks to obtain visual parity.',
9
+ frameworks:
10
+ 'React uses callbacks such as onPress/onChange and isDisabled/isRequired; Vue uses @press, v-model, disabled/required and named/scoped slots. These are Kazee-specific contracts, not interchangeable HeroUI or shadcn APIs. Select chooses fixed options; Combobox provides searchable single selection in the newer catalog. Read the versioned props/events/slots rather than borrowing upstream API names.',
11
+ toast:
12
+ 'Toast and ToastProvider are currently workspace-only additions, not exported by the immutable registry-verified 0.4.0 release. When matching local packed artifacts or reviewing this checkout, use createToastManager and one ToastProvider per manager; useToast accesses the nearest provider. Import the shared stylesheet once. Use semantic tone neutral/info/success/warning/danger, duration zero for persistent content, and explicit action altText. Promise updates retain the same ID and never recreate a dismissed notification. Hover/focus/window blur/hidden document pause remaining time; queued notifications start timing only when visible. Alt+T focuses the region and Escape closes one while focus is inside it. Critical errors and required responses belong in persistent application UI. New package versions and a separately verified MCP catalog are required before registry consumers can adopt Toast; this server does not publish them.',
13
+ };
14
+ export function installation(catalog, framework, manager, serverVersion) {
15
+ const workspace = catalog.provenance.source === 'workspace';
16
+ const registry = catalog.provenance.registry ?? REGISTRY;
17
+ const legacy = registry !== REGISTRY;
18
+ const dependencies = `@kazee-ds/${framework}@${catalog.packages[framework]} @kazee-ds/styles@${catalog.packages.styles}`;
19
+ const lint = `@kazee-ds/eslint-config@${catalog.packages['eslint-config']}`;
20
+ const commands =
21
+ manager === 'pnpm'
22
+ ? [`pnpm add --save-exact ${dependencies}`, `pnpm add --save-dev --save-exact ${lint}`]
23
+ : manager === 'yarn'
24
+ ? [`yarn add --exact ${dependencies}`, `yarn add --dev --exact ${lint}`]
25
+ : [
26
+ `npm install --save-exact ${dependencies}`,
27
+ `npm install --save-dev --save-exact ${lint}`,
28
+ ];
29
+ return {
30
+ mode: workspace
31
+ ? 'workspace-local'
32
+ : catalog.status === 'registry-verified'
33
+ ? 'verified-release'
34
+ : 'release-candidate',
35
+ publication: workspace
36
+ ? 'This is an unpublished workspace preview. Build and install matching local packed .tgz artifacts. The catalog selector is not a registry version; installing the same manifest version from the registry does not provide these workspace changes.'
37
+ : catalog.status === 'registry-verified'
38
+ ? 'This version was verified against registry archives when the catalog was built.'
39
+ : 'Publish matching packages before using the registry commands below. For local verification, install packed .tgz files of these exact candidate versions instead. This server does not publish or install anything.',
40
+ registry,
41
+ npmrc: `@kazee-ds:registry=${registry}\n${legacy ? '//gitlab.com/api/v4/projects/87560456/packages/npm/:_authToken=${KAZEE_DS_NPM_TOKEN}\n' : ''}`,
42
+ credentials: legacy
43
+ ? 'This historical release belongs to the private GitLab registry. Supply KAZEE_DS_NPM_TOKEN through your shell or secret manager. Never paste its value into MCP calls, source, frontend code or .mcp.json.'
44
+ : 'Public npm installation requires no read token or npm login. Publishing credentials belong only in the release environment, never in frontend code or consumer MCP configuration.',
45
+ requirements:
46
+ framework === 'react'
47
+ ? 'React and React DOM >=19, ESM. Install React/React DOM in the application. Next.js modules using hooks need a client boundary.'
48
+ : 'Vue >=3.4, ESM. Install Vue in the application. Nuxt global CSS belongs in its css configuration.',
49
+ commands: workspace ? [] : commands,
50
+ stylesheet: "import '@kazee-ds/styles/index.css';",
51
+ lint: "Merge consumerConfig() from '@kazee-ds/eslint-config' into the existing ESLint flat config after its parsers; include lint in CI. Installing the package alone does not enable the rules.",
52
+ mcp: {
53
+ mcpServers: { kazee: { command: 'npx', args: ['-y', `@kazee-ds/mcp@${serverVersion}`] } },
54
+ },
55
+ mcpPublication:
56
+ 'The npx configuration requires this MCP package version to have been published. Before publication use node with the absolute local bin/kazee-mcp.mjs path. Merge the kazee entry into existing MCP configuration; preserve other servers. Client configuration formats differ; .mcp.json is the Claude Code project format.',
57
+ verification:
58
+ 'Run existing application lint, typecheck and build. Then verify actual component interactions in a browser. Do not claim production adoption from an isolated consumer test.',
59
+ };
60
+ }
package/src/server.mjs ADDED
@@ -0,0 +1,210 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { z } from 'zod';
3
+ import {
4
+ context,
5
+ loadCatalog,
6
+ selectCatalog,
7
+ selectComponent,
8
+ themeVariables,
9
+ } from './catalog.mjs';
10
+ import { guides, installation } from './guides.mjs';
11
+
12
+ const framework = z
13
+ .enum(['react', 'vue'])
14
+ .describe('Application framework. React JSX and Vue SFC APIs are different.');
15
+ const version = z
16
+ .string()
17
+ .regex(/^\d+\.\d+\.\d+(?:-[a-zA-Z0-9.-]+)?$/)
18
+ .max(60)
19
+ .describe(
20
+ 'Exact installed Kazee framework version, not a range. Read get_catalog_versions first; never silently substitute latest. A -workspace selector is only for explicitly reviewing the unpublished checkout or matching local packed artifacts.',
21
+ );
22
+ const component = z
23
+ .string()
24
+ .trim()
25
+ .min(1)
26
+ .max(80)
27
+ .describe('Public component name from list_components.');
28
+ const annotations = {
29
+ readOnlyHint: true,
30
+ destructiveHint: false,
31
+ idempotentHint: true,
32
+ openWorldHint: false,
33
+ };
34
+ const response = (value) => ({
35
+ content: [{ type: 'text', text: JSON.stringify(value, null, 2) }],
36
+ structuredContent: value,
37
+ });
38
+ export function createServer(data = loadCatalog()) {
39
+ const server = new McpServer(
40
+ { name: 'kazee-design-system', version: data.serverVersion },
41
+ {
42
+ instructions:
43
+ 'Read-only, offline Kazee Design System reference for React/Vue. Start with get_catalog_versions. Use exact installed package versions. A -workspace selector is only for explicitly reviewing this unpublished checkout or matching local packed artifacts; it is not a registry installation version. Request public docs/examples before implementation; do not scan dependency internals. Release candidates are explicitly marked and do not prove registry publication. Documentation tools never install, modify files, execute commands, read credentials or inspect your project.',
44
+ },
45
+ );
46
+ function tool(name, description, inputSchema, handler) {
47
+ server.registerTool(name, { description, inputSchema, annotations }, async (args) => {
48
+ try {
49
+ return response(handler(args));
50
+ } catch (error) {
51
+ return { isError: true, content: [{ type: 'text', text: error.message }] };
52
+ }
53
+ });
54
+ }
55
+ tool(
56
+ 'get_catalog_versions',
57
+ 'Start here: list exact Kazee versions, framework coverage and publication provenance. An offline server cannot know later releases.',
58
+ {},
59
+ () => ({
60
+ serverVersion: data.serverVersion,
61
+ offline: true,
62
+ versions: data.catalogs.map((catalog) => ({
63
+ version: catalog.version,
64
+ status: catalog.status,
65
+ packages: catalog.packages,
66
+ components: Object.fromEntries(
67
+ Object.entries(catalog.frameworks).map(([key, value]) => [
68
+ key,
69
+ Object.keys(value).length,
70
+ ]),
71
+ ),
72
+ provenance: catalog.provenance,
73
+ })),
74
+ next: 'Read the installed public package.json or lockfile version. Pass that exact version to list_components, docs and examples. For an intentional review of this unpublished checkout, explicitly choose the workspace preview selector instead; do not use it as a registry installation version.',
75
+ }),
76
+ );
77
+ tool(
78
+ 'list_components',
79
+ 'Browse or search public components by name, function, Indonesian/English keyword, category, or aliases. Empty search lists the versioned catalog. No upstream component is invented.',
80
+ {
81
+ framework,
82
+ version,
83
+ query: z.string().trim().max(120).default(''),
84
+ category: z.string().max(40).optional(),
85
+ },
86
+ ({ framework, version, query, category }) => {
87
+ const catalog = selectCatalog(data, framework, version);
88
+ const terms = query.toLowerCase().split(/\s+/).filter(Boolean);
89
+ const components = Object.values(catalog.frameworks[framework])
90
+ .filter(
91
+ (item) =>
92
+ (!category || item.category === category) &&
93
+ terms.every((term) =>
94
+ [item.name, item.description, ...item.keywords]
95
+ .join(' ')
96
+ .toLowerCase()
97
+ .includes(term),
98
+ ),
99
+ )
100
+ .map(({ name, category, description }) => ({ name, category, description }));
101
+ return {
102
+ ...context(catalog, framework),
103
+ total: components.length,
104
+ components,
105
+ next: components.length
106
+ ? 'Read get_component_docs and get_component_examples for the selected component.'
107
+ : 'No matching Kazee component in this version. Do not invent an import; use application composition or review another supported version.',
108
+ };
109
+ },
110
+ );
111
+ tool(
112
+ 'get_component_docs',
113
+ 'Get exact versioned public props, discriminated variants, events, slots, related types and constraints. Generated from package declarations; use these contracts instead of headless-library APIs.',
114
+ { framework, version, component },
115
+ ({ framework, version, component }) => {
116
+ const catalog = selectCatalog(data, framework, version);
117
+ const { examples, ...docs } = selectComponent(catalog, framework, component);
118
+ return {
119
+ ...context(catalog, framework),
120
+ ...docs,
121
+ exampleIds: examples.map((item) => item.id),
122
+ guidance: guides.frameworks,
123
+ };
124
+ },
125
+ );
126
+ tool(
127
+ 'get_component_examples',
128
+ 'Get complete, typechecked React .tsx or Vue .vue modules using only public Kazee imports. Select an exampleId from docs, or omit it for all examples of this component/version.',
129
+ {
130
+ framework,
131
+ version,
132
+ component,
133
+ exampleId: z.string().trim().min(1).max(80).optional(),
134
+ },
135
+ ({ framework, version, component, exampleId }) => {
136
+ const catalog = selectCatalog(data, framework, version);
137
+ const item = selectComponent(catalog, framework, component);
138
+ const examples = item.examples.filter((item) => !exampleId || item.id === exampleId);
139
+ if (!examples.length)
140
+ throw new Error(
141
+ `Unknown example ${exampleId}. Available: ${item.examples.map((item) => item.id).join(', ')}`,
142
+ );
143
+ return { ...context(catalog, framework), component: item.name, examples };
144
+ },
145
+ );
146
+ tool(
147
+ 'get_theme_variables',
148
+ 'Search semantic CSS variables with actual light/dark token values for this package version. Uses bundled data; does not inspect or mutate application themes.',
149
+ {
150
+ framework,
151
+ version,
152
+ theme: z.enum(['light', 'dark']).default('light'),
153
+ query: z.string().max(100).default(''),
154
+ limit: z.number().int().min(1).max(100).default(40),
155
+ },
156
+ ({ framework, version, theme, query, limit }) => {
157
+ const catalog = selectCatalog(data, framework, version);
158
+ return { ...context(catalog, framework), ...themeVariables(catalog, theme, query, limit) };
159
+ },
160
+ );
161
+ tool(
162
+ 'get_installation',
163
+ 'Return version-pinned installation, registry-specific guidance, global CSS, lint and MCP setup. New public npm releases need no read token; historical GitLab catalogs keep their original registry. Read-only documentation: no installation, credential access or file writes occur.',
164
+ {
165
+ framework,
166
+ version,
167
+ packageManager: z.enum(['npm', 'pnpm', 'yarn']).default('npm'),
168
+ },
169
+ ({ framework, version, packageManager }) => {
170
+ const catalog = selectCatalog(data, framework, version);
171
+ return {
172
+ ...context(catalog, framework),
173
+ ...installation(catalog, framework, packageManager, data.serverVersion),
174
+ };
175
+ },
176
+ );
177
+ tool(
178
+ 'get_guides',
179
+ 'Read Kazee agent workflow, styling, React/Vue differences, Toast lifecycle, or dashboard application-composition boundaries.',
180
+ { topic: z.enum(['workflow', 'styling', 'frameworks', 'composition', 'toast']) },
181
+ ({ topic }) => ({ topic, guide: guides[topic] }),
182
+ );
183
+ server.registerResource(
184
+ 'workflow',
185
+ 'kazee://guides/workflow',
186
+ { description: 'Kazee agent workflow and public API boundaries', mimeType: 'text/plain' },
187
+ async (uri) => ({
188
+ contents: [{ uri: uri.href, mimeType: 'text/plain', text: guides.workflow }],
189
+ }),
190
+ );
191
+ server.registerResource(
192
+ 'versions',
193
+ 'kazee://catalog/versions',
194
+ { description: 'Bundled version/catalog provenance', mimeType: 'application/json' },
195
+ async (uri) => ({
196
+ contents: [
197
+ {
198
+ uri: uri.href,
199
+ mimeType: 'application/json',
200
+ text: JSON.stringify(
201
+ data.catalogs.map(({ version, status, packages }) => ({ version, status, packages })),
202
+ null,
203
+ 2,
204
+ ),
205
+ },
206
+ ],
207
+ }),
208
+ );
209
+ return server;
210
+ }