@hareru/mcp 0.2.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/LICENSE +21 -0
- package/README.md +111 -0
- package/bin/hareru-mcp.mjs +7 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +664 -0
- package/dist/index.js.map +1 -0
- package/package.json +55 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 MUSUBI Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# @hareru/mcp
|
|
2
|
+
|
|
3
|
+
MCP server for [Hareru UI](https://github.com/hareru-ai/ui) — exposes design tokens, component registry, and usage rules to AI agents via [Model Context Protocol](https://modelcontextprotocol.io/).
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@hareru/mcp)
|
|
6
|
+
[](../../LICENSE)
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- **6 resources** — Tokens, token schema, component registry, component schema, task bundles, and consumer rules
|
|
11
|
+
- **5 tools** — Component usage, bundle usage, token validation, CSS mode recommendation, and group filtering
|
|
12
|
+
- **3 prompts** — UI generation, Tailwind coexistence, and consumer rules
|
|
13
|
+
- **stdio transport** — Works with Claude Desktop, Cursor, and any MCP-compatible client
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# npm
|
|
19
|
+
npm install @hareru/mcp
|
|
20
|
+
|
|
21
|
+
# pnpm
|
|
22
|
+
pnpm add @hareru/mcp
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Claude Desktop Configuration
|
|
26
|
+
|
|
27
|
+
Add to your `claude_desktop_config.json`:
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"mcpServers": {
|
|
32
|
+
"hareru-ui": {
|
|
33
|
+
"command": "npx",
|
|
34
|
+
"args": ["@hareru/mcp"]
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Resources
|
|
41
|
+
|
|
42
|
+
| URI | Description |
|
|
43
|
+
|-----|-------------|
|
|
44
|
+
| `hareru-ui://tokens` | DTCG design tokens (light/dark themes, 150+ CSS custom properties) |
|
|
45
|
+
| `hareru-ui://tokens/schema` | JSON Schema for design tokens — CSS variable enums and type constraints |
|
|
46
|
+
| `hareru-ui://components` | Component registry — 40+ components with CVA variants and Props interfaces |
|
|
47
|
+
| `hareru-ui://components/schema` | JSON Schema for the component registry |
|
|
48
|
+
| `hareru-ui://bundles` | Task bundles — curated component sets for common UI patterns |
|
|
49
|
+
| `hareru-ui://rules/consumer` | Consumer rules for AI agents — import patterns, styling rules, and token reference |
|
|
50
|
+
|
|
51
|
+
## Tools
|
|
52
|
+
|
|
53
|
+
| Tool | Description | Parameters |
|
|
54
|
+
|------|-------------|------------|
|
|
55
|
+
| `get-component-usage` | Get usage docs for a component — import, variants, props, and JSX example | `componentName` (string) |
|
|
56
|
+
| `get-bundle-usage` | Get usage docs for a task bundle — components, CSS imports, and token categories | `bundleName` (string) |
|
|
57
|
+
| `validate-token-value` | Validate a CSS value against the token schema | `tokenType` (string), `value` (string) |
|
|
58
|
+
| `recommend-css-mode` | Recommend the best CSS import mode based on project context | `hasTailwind` (boolean), `componentCount` (number), `hasExistingReset?` (boolean) |
|
|
59
|
+
| `list-components-by-group` | List components filtered by group | `group` (enum: core, form, layout, overlay, navigation, feedback, data-display, agent, di-domain) |
|
|
60
|
+
|
|
61
|
+
## Prompts
|
|
62
|
+
|
|
63
|
+
| Prompt | Description | Parameters |
|
|
64
|
+
|--------|-------------|------------|
|
|
65
|
+
| `create-ui` | Generate a UI component using Hareru UI design system | `description` (string), `framework?` (string) |
|
|
66
|
+
| `create-ui-tailwind` | Generate a component mixing Hareru UI and Tailwind CSS with Cascade Layer guidance | `description` (string) |
|
|
67
|
+
| `consumer-rules` | Get the rules for using Hareru UI in your project | — |
|
|
68
|
+
|
|
69
|
+
## Programmatic Usage
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
import { createServer } from "@hareru/mcp";
|
|
73
|
+
|
|
74
|
+
const server = createServer();
|
|
75
|
+
|
|
76
|
+
// Connect with stdio transport
|
|
77
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
78
|
+
const transport = new StdioServerTransport();
|
|
79
|
+
await server.connect(transport);
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Testing with InMemoryTransport
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
import { createServer } from "@hareru/mcp";
|
|
86
|
+
import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
|
|
87
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
88
|
+
|
|
89
|
+
const client = new Client({ name: "test", version: "1.0.0" });
|
|
90
|
+
const server = createServer();
|
|
91
|
+
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
|
|
92
|
+
|
|
93
|
+
await Promise.all([
|
|
94
|
+
client.connect(clientTransport),
|
|
95
|
+
server.connect(serverTransport),
|
|
96
|
+
]);
|
|
97
|
+
|
|
98
|
+
const result = await client.callTool({
|
|
99
|
+
name: "get-component-usage",
|
|
100
|
+
arguments: { componentName: "Button" },
|
|
101
|
+
});
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Links
|
|
105
|
+
|
|
106
|
+
- [Documentation](https://ui.hareru.ai/docs/mcp-server)
|
|
107
|
+
- [GitHub](https://github.com/hareru-ai/ui/tree/main/packages/mcp)
|
|
108
|
+
|
|
109
|
+
## License
|
|
110
|
+
|
|
111
|
+
[MIT](../../LICENSE) — Copyright (c) 2026 MUSUBI Inc.
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,664 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { readFileSync } from "fs";
|
|
3
|
+
import { dirname, join } from "path";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
6
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
7
|
+
|
|
8
|
+
// src/prompts.ts
|
|
9
|
+
import { z } from "zod";
|
|
10
|
+
|
|
11
|
+
// src/utils.ts
|
|
12
|
+
import {
|
|
13
|
+
loadTokens,
|
|
14
|
+
loadSchema,
|
|
15
|
+
loadRegistry,
|
|
16
|
+
loadComponentSchema,
|
|
17
|
+
loadConsumerRules,
|
|
18
|
+
CSS_MODES,
|
|
19
|
+
CSS_MODE_DESCRIPTIONS,
|
|
20
|
+
recommendCssMode
|
|
21
|
+
} from "@hareru/registry";
|
|
22
|
+
|
|
23
|
+
// src/prompts.ts
|
|
24
|
+
function registerPrompts(server) {
|
|
25
|
+
server.prompt(
|
|
26
|
+
"create-ui",
|
|
27
|
+
"Generate a UI component using Hareru UI design system",
|
|
28
|
+
{
|
|
29
|
+
description: z.string().describe(
|
|
30
|
+
'What the component should do (e.g. "A settings form with name and email fields")'
|
|
31
|
+
),
|
|
32
|
+
framework: z.string().optional().describe("Target framework: react (default)")
|
|
33
|
+
},
|
|
34
|
+
async ({ description, framework }) => {
|
|
35
|
+
const registry = loadRegistry();
|
|
36
|
+
const schema = loadSchema();
|
|
37
|
+
const componentList = registry.components.map((c) => {
|
|
38
|
+
const variants = c.variants ?? [];
|
|
39
|
+
const variantInfo = variants.length > 0 ? ` [${variants.flatMap((v) => Object.entries(v.variants).map(([k, opts]) => `${k}(${opts.join("|")})`)).join(", ")}]` : "";
|
|
40
|
+
const desc = c.description ? ` \u2014 ${c.description}` : "";
|
|
41
|
+
return `- ${c.name}${variantInfo}${desc}`;
|
|
42
|
+
}).join("\n");
|
|
43
|
+
const bundles = registry.taskBundles ?? [];
|
|
44
|
+
const bundleList = bundles.length > 0 ? bundles.map((b) => `- ${b.name}: ${b.description} (${b.components.length} components)`).join("\n") : "";
|
|
45
|
+
const cssVars = schema.properties.cssVariables.items.enum.slice(0, 20).join(", ");
|
|
46
|
+
const fw = framework ?? "react";
|
|
47
|
+
return {
|
|
48
|
+
messages: [
|
|
49
|
+
{
|
|
50
|
+
role: "user",
|
|
51
|
+
content: {
|
|
52
|
+
type: "text",
|
|
53
|
+
text: `You are a UI developer using the Hareru UI design system (${fw}).
|
|
54
|
+
|
|
55
|
+
## Available Components
|
|
56
|
+
|
|
57
|
+
${componentList}
|
|
58
|
+
|
|
59
|
+
## Design Token CSS Variables (sample)
|
|
60
|
+
|
|
61
|
+
${cssVars}, ...
|
|
62
|
+
|
|
63
|
+
## Rules
|
|
64
|
+
|
|
65
|
+
1. Import components from '@hareru/ui'. For CSS setup, refer to the consumer-rules (standalone: '@hareru/ui/styles.css', portable: '@hareru/tokens/css' + '@hareru/ui/styles/components.css')
|
|
66
|
+
2. Use only semantic variant props (e.g. variant="default"), never hardcode CSS values
|
|
67
|
+
3. Use CSS variables (--hui-*) for any custom styling
|
|
68
|
+
4. All components support forwardRef
|
|
69
|
+
5. Use BEM class naming (hui-*) if adding custom classes
|
|
70
|
+
6. Colors use OKLCH format
|
|
71
|
+
|
|
72
|
+
## Task
|
|
73
|
+
|
|
74
|
+
${description}
|
|
75
|
+
${bundleList ? `
|
|
76
|
+
## Available Bundles
|
|
77
|
+
|
|
78
|
+
${bundleList}
|
|
79
|
+
` : ""}
|
|
80
|
+
Generate a complete ${fw} component that fulfills this requirement.`
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
]
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
);
|
|
87
|
+
server.prompt(
|
|
88
|
+
"create-ui-tailwind",
|
|
89
|
+
"Generate a UI component mixing Hareru UI and Tailwind CSS with Cascade Layer guidance",
|
|
90
|
+
{
|
|
91
|
+
description: z.string().describe(
|
|
92
|
+
'What the component should do (e.g. "A dashboard card with Tailwind layout and Hareru UI buttons")'
|
|
93
|
+
)
|
|
94
|
+
},
|
|
95
|
+
async ({ description }) => {
|
|
96
|
+
const registry = loadRegistry();
|
|
97
|
+
const componentList = registry.components.map((c) => {
|
|
98
|
+
const desc = c.description ? ` \u2014 ${c.description}` : "";
|
|
99
|
+
return `- ${c.name}${desc}`;
|
|
100
|
+
}).join("\n");
|
|
101
|
+
return {
|
|
102
|
+
messages: [
|
|
103
|
+
{
|
|
104
|
+
role: "user",
|
|
105
|
+
content: {
|
|
106
|
+
type: "text",
|
|
107
|
+
text: `You are a UI developer using Hareru UI + Tailwind CSS v4 together.
|
|
108
|
+
|
|
109
|
+
## Cascade Layer Order
|
|
110
|
+
|
|
111
|
+
Declare this layer order at the top of your CSS entry point:
|
|
112
|
+
|
|
113
|
+
\`\`\`css
|
|
114
|
+
@layer theme, base, hui, components, utilities;
|
|
115
|
+
@import 'tailwindcss';
|
|
116
|
+
@import '@hareru/tokens/css';
|
|
117
|
+
@import '@hareru/ui/styles/components.layer.css';
|
|
118
|
+
\`\`\`
|
|
119
|
+
|
|
120
|
+
- Hareru components live in \`@layer hui\` \u2014 below Tailwind \`utilities\`
|
|
121
|
+
- Tailwind utility classes (e.g. \`flex\`, \`gap-4\`, \`p-2\`) can safely override Hareru layout
|
|
122
|
+
- Never use Tailwind classes to override Hareru component internals (colors, border-radius, shadows) \u2014 use \`--hui-*\` CSS variables instead
|
|
123
|
+
|
|
124
|
+
## Mixing Classes Example
|
|
125
|
+
|
|
126
|
+
\`\`\`tsx
|
|
127
|
+
{/* Tailwind for layout, Hareru for components */}
|
|
128
|
+
<div className="flex gap-4 p-6">
|
|
129
|
+
<Card className="flex-1">
|
|
130
|
+
<CardHeader>Title</CardHeader>
|
|
131
|
+
<CardContent>
|
|
132
|
+
<Button variant="default">Action</Button>
|
|
133
|
+
</CardContent>
|
|
134
|
+
</Card>
|
|
135
|
+
</div>
|
|
136
|
+
\`\`\`
|
|
137
|
+
|
|
138
|
+
## Available Components
|
|
139
|
+
|
|
140
|
+
${componentList}
|
|
141
|
+
|
|
142
|
+
## Rules
|
|
143
|
+
|
|
144
|
+
1. Import components from \`@hareru/ui\`
|
|
145
|
+
2. Use Tailwind utilities for layout (flex, grid, gap, padding, margin)
|
|
146
|
+
3. Use Hareru components for interactive UI elements (Button, Input, Card, Dialog)
|
|
147
|
+
4. Use \`--hui-*\` CSS variables for theming \u2014 do not override with Tailwind color classes
|
|
148
|
+
5. Use BEM class naming (\`hui-*\`) if adding custom component styles
|
|
149
|
+
6. Colors are OKLCH format
|
|
150
|
+
|
|
151
|
+
## Task
|
|
152
|
+
|
|
153
|
+
${description}
|
|
154
|
+
|
|
155
|
+
Generate a complete React component that combines Tailwind layout utilities with Hareru UI components.`
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
]
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
);
|
|
162
|
+
server.prompt(
|
|
163
|
+
"consumer-rules",
|
|
164
|
+
"Get the rules for using Hareru UI in your project",
|
|
165
|
+
{},
|
|
166
|
+
async () => {
|
|
167
|
+
const rules = loadConsumerRules();
|
|
168
|
+
const CODE_BLOCK_SECTIONS = /* @__PURE__ */ new Set(["cssImports"]);
|
|
169
|
+
const rulesSections = Object.entries(rules.rules).map(([key, section]) => {
|
|
170
|
+
const ruleList = section.rules.map((r) => `- ${r}`).join("\n");
|
|
171
|
+
const examples = Object.entries(section.examples).map(
|
|
172
|
+
([label, code]) => CODE_BLOCK_SECTIONS.has(key) ? `**${label}:**
|
|
173
|
+
\`\`\`css
|
|
174
|
+
${code}
|
|
175
|
+
\`\`\`` : ` ${label}: ${code}`
|
|
176
|
+
).join("\n");
|
|
177
|
+
return `### ${key}
|
|
178
|
+
${section.description}
|
|
179
|
+
|
|
180
|
+
${ruleList}
|
|
181
|
+
|
|
182
|
+
Examples:
|
|
183
|
+
${examples}`;
|
|
184
|
+
}).join("\n\n");
|
|
185
|
+
const tokenRef = Object.entries(rules.tokenQuickReference).map(([category, pattern]) => `- ${category}: ${pattern}`).join("\n");
|
|
186
|
+
return {
|
|
187
|
+
messages: [
|
|
188
|
+
{
|
|
189
|
+
role: "user",
|
|
190
|
+
content: {
|
|
191
|
+
type: "text",
|
|
192
|
+
text: `# Hareru UI Consumer Rules (v${rules.version})
|
|
193
|
+
|
|
194
|
+
These rules apply when using Hareru UI in any project.
|
|
195
|
+
|
|
196
|
+
## Rules
|
|
197
|
+
|
|
198
|
+
${rulesSections}
|
|
199
|
+
|
|
200
|
+
## Token Quick Reference
|
|
201
|
+
|
|
202
|
+
${tokenRef}`
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
]
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// src/resources.ts
|
|
212
|
+
function registerResources(server) {
|
|
213
|
+
const schema = loadSchema();
|
|
214
|
+
const tokenCount = schema.properties.tokenCount.const;
|
|
215
|
+
const registry = loadRegistry();
|
|
216
|
+
server.resource(
|
|
217
|
+
"tokens",
|
|
218
|
+
"hareru-ui://tokens",
|
|
219
|
+
{
|
|
220
|
+
description: `DTCG design tokens (light/dark themes, ${tokenCount} CSS custom properties)`,
|
|
221
|
+
mimeType: "application/json"
|
|
222
|
+
},
|
|
223
|
+
async (uri) => ({
|
|
224
|
+
contents: [{ uri: uri.href, text: JSON.stringify(loadTokens(), null, 2) }]
|
|
225
|
+
})
|
|
226
|
+
);
|
|
227
|
+
server.resource(
|
|
228
|
+
"tokens-schema",
|
|
229
|
+
"hareru-ui://tokens/schema",
|
|
230
|
+
{
|
|
231
|
+
description: "JSON Schema for design tokens \u2014 CSS variable enums and type constraints",
|
|
232
|
+
mimeType: "application/json"
|
|
233
|
+
},
|
|
234
|
+
async (uri) => ({
|
|
235
|
+
contents: [{ uri: uri.href, text: JSON.stringify(loadSchema(), null, 2) }]
|
|
236
|
+
})
|
|
237
|
+
);
|
|
238
|
+
server.resource(
|
|
239
|
+
"components",
|
|
240
|
+
"hareru-ui://components",
|
|
241
|
+
{
|
|
242
|
+
description: `Component registry \u2014 ${registry.componentCount} components with CVA variants and Props interfaces`,
|
|
243
|
+
mimeType: "application/json"
|
|
244
|
+
},
|
|
245
|
+
async (uri) => ({
|
|
246
|
+
contents: [{ uri: uri.href, text: JSON.stringify(registry, null, 2) }]
|
|
247
|
+
})
|
|
248
|
+
);
|
|
249
|
+
server.resource(
|
|
250
|
+
"bundles",
|
|
251
|
+
"hareru-ui://bundles",
|
|
252
|
+
{
|
|
253
|
+
description: `Task bundles \u2014 ${registry.taskBundles?.length ?? 0} curated component sets for common UI patterns`,
|
|
254
|
+
mimeType: "application/json"
|
|
255
|
+
},
|
|
256
|
+
async (uri) => ({
|
|
257
|
+
contents: [{ uri: uri.href, text: JSON.stringify(registry.taskBundles ?? [], null, 2) }]
|
|
258
|
+
})
|
|
259
|
+
);
|
|
260
|
+
server.resource(
|
|
261
|
+
"components-schema",
|
|
262
|
+
"hareru-ui://components/schema",
|
|
263
|
+
{
|
|
264
|
+
description: "JSON Schema for the component registry",
|
|
265
|
+
mimeType: "application/json"
|
|
266
|
+
},
|
|
267
|
+
async (uri) => ({
|
|
268
|
+
contents: [{ uri: uri.href, text: JSON.stringify(loadComponentSchema(), null, 2) }]
|
|
269
|
+
})
|
|
270
|
+
);
|
|
271
|
+
server.resource(
|
|
272
|
+
"consumer-rules",
|
|
273
|
+
"hareru-ui://rules/consumer",
|
|
274
|
+
{
|
|
275
|
+
description: "Consumer rules for AI agents \u2014 import patterns, styling rules, and token reference",
|
|
276
|
+
mimeType: "application/json"
|
|
277
|
+
},
|
|
278
|
+
async (uri) => ({
|
|
279
|
+
contents: [{ uri: uri.href, text: JSON.stringify(loadConsumerRules(), null, 2) }]
|
|
280
|
+
})
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// src/tools.ts
|
|
285
|
+
import { z as z2 } from "zod";
|
|
286
|
+
function escPipe(s) {
|
|
287
|
+
return s.replace(/\|/g, "\\|");
|
|
288
|
+
}
|
|
289
|
+
function formatVariantsTable(entry) {
|
|
290
|
+
const variants = entry.variants ?? [];
|
|
291
|
+
if (variants.length === 0) return "No CVA variants defined.";
|
|
292
|
+
const lines = ["| Variant | Options | Default |", "|---------|---------|---------|"];
|
|
293
|
+
for (const v of variants) {
|
|
294
|
+
for (const [key, options] of Object.entries(v.variants)) {
|
|
295
|
+
const defaultVal = v.defaultVariants[key] ?? "-";
|
|
296
|
+
lines.push(
|
|
297
|
+
`| ${escPipe(key)} | ${options.map(escPipe).join(", ")} | ${escPipe(defaultVal)} |`
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
return lines.join("\n");
|
|
302
|
+
}
|
|
303
|
+
function formatUsageMarkdown(entry) {
|
|
304
|
+
const parts = [];
|
|
305
|
+
parts.push(`# ${entry.displayName}`);
|
|
306
|
+
parts.push("");
|
|
307
|
+
parts.push(entry.description);
|
|
308
|
+
parts.push("");
|
|
309
|
+
if (entry.aiHint) {
|
|
310
|
+
parts.push("## AI Guidance");
|
|
311
|
+
parts.push("");
|
|
312
|
+
parts.push(entry.aiHint);
|
|
313
|
+
parts.push("");
|
|
314
|
+
}
|
|
315
|
+
parts.push("## Import");
|
|
316
|
+
parts.push("");
|
|
317
|
+
parts.push("```tsx");
|
|
318
|
+
const subs = entry.subcomponents ?? [];
|
|
319
|
+
const allNames = [entry.name, ...subs];
|
|
320
|
+
parts.push(`import { ${allNames.join(", ")} } from '@hareru/ui';`);
|
|
321
|
+
parts.push("```");
|
|
322
|
+
parts.push("");
|
|
323
|
+
parts.push("## CSS");
|
|
324
|
+
parts.push("");
|
|
325
|
+
parts.push("**Standalone:**");
|
|
326
|
+
parts.push("```css");
|
|
327
|
+
parts.push(`@import '@hareru/ui/styles.css';`);
|
|
328
|
+
parts.push("```");
|
|
329
|
+
parts.push("");
|
|
330
|
+
parts.push("**Per-component:**");
|
|
331
|
+
parts.push("```css");
|
|
332
|
+
parts.push(`@import '@hareru/tokens/css';`);
|
|
333
|
+
for (const dep of entry.requiredCssArtifacts ?? []) {
|
|
334
|
+
parts.push(`@import '@hareru/ui/${dep}';`);
|
|
335
|
+
}
|
|
336
|
+
parts.push(`@import '@hareru/ui/${entry.cssArtifact}';`);
|
|
337
|
+
parts.push("```");
|
|
338
|
+
parts.push("");
|
|
339
|
+
const variants = entry.variants ?? [];
|
|
340
|
+
const props = entry.props ?? [];
|
|
341
|
+
if (variants.length > 0) {
|
|
342
|
+
parts.push("## Variants");
|
|
343
|
+
parts.push("");
|
|
344
|
+
parts.push(formatVariantsTable(entry));
|
|
345
|
+
parts.push("");
|
|
346
|
+
}
|
|
347
|
+
if (props.length > 0) {
|
|
348
|
+
parts.push("## Props");
|
|
349
|
+
parts.push("");
|
|
350
|
+
for (const prop of props) {
|
|
351
|
+
if (prop.extends) {
|
|
352
|
+
parts.push(`- **${prop.name}** extends \`${prop.extends}\``);
|
|
353
|
+
} else {
|
|
354
|
+
parts.push(`- **${prop.name}**`);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
parts.push("");
|
|
358
|
+
}
|
|
359
|
+
if (entry.peerComponents) {
|
|
360
|
+
parts.push("## Also Consider");
|
|
361
|
+
parts.push("");
|
|
362
|
+
for (const peer of entry.peerComponents) {
|
|
363
|
+
parts.push(`- ${peer}`);
|
|
364
|
+
}
|
|
365
|
+
parts.push("");
|
|
366
|
+
}
|
|
367
|
+
parts.push("## Example");
|
|
368
|
+
parts.push("");
|
|
369
|
+
parts.push("```tsx");
|
|
370
|
+
if (variants.length > 0) {
|
|
371
|
+
const firstVariant = variants[0];
|
|
372
|
+
const propsStr = Object.entries(firstVariant.defaultVariants).map(([k, v]) => `${k}="${v}"`).join(" ");
|
|
373
|
+
parts.push(`<${entry.name} ${propsStr}>Content</${entry.name}>`);
|
|
374
|
+
} else if (subs.length > 0) {
|
|
375
|
+
parts.push(`<${entry.name}>`);
|
|
376
|
+
for (const sub of subs) {
|
|
377
|
+
parts.push(` <${sub}>Content</${sub}>`);
|
|
378
|
+
}
|
|
379
|
+
parts.push(`</${entry.name}>`);
|
|
380
|
+
} else {
|
|
381
|
+
parts.push(`<${entry.name}>Content</${entry.name}>`);
|
|
382
|
+
}
|
|
383
|
+
parts.push("```");
|
|
384
|
+
return parts.join("\n");
|
|
385
|
+
}
|
|
386
|
+
function registerTools(server) {
|
|
387
|
+
server.tool(
|
|
388
|
+
"get-component-usage",
|
|
389
|
+
"Get usage documentation for a Hareru UI component \u2014 import, variants, props, and JSX example",
|
|
390
|
+
{ componentName: z2.string().describe('Component name (e.g. "Button", "Card", "Alert")') },
|
|
391
|
+
async ({ componentName }) => {
|
|
392
|
+
const registry = loadRegistry();
|
|
393
|
+
const entry = registry.components.find(
|
|
394
|
+
(c) => c.name.toLowerCase() === componentName.toLowerCase()
|
|
395
|
+
);
|
|
396
|
+
if (!entry) {
|
|
397
|
+
const available = registry.components.map((c) => c.name).join(", ");
|
|
398
|
+
return {
|
|
399
|
+
content: [
|
|
400
|
+
{
|
|
401
|
+
type: "text",
|
|
402
|
+
text: `Component "${componentName}" not found. Available components: ${available}`
|
|
403
|
+
}
|
|
404
|
+
],
|
|
405
|
+
isError: true
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
return {
|
|
409
|
+
content: [{ type: "text", text: formatUsageMarkdown(entry) }]
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
);
|
|
413
|
+
server.tool(
|
|
414
|
+
"get-bundle-usage",
|
|
415
|
+
"Get usage documentation for a Hareru UI task bundle \u2014 components, CSS imports, and token categories",
|
|
416
|
+
{ bundleName: z2.string().describe('Bundle name (e.g. "agent-chat-shell", "form-basics")') },
|
|
417
|
+
async ({ bundleName }) => {
|
|
418
|
+
const registry = loadRegistry();
|
|
419
|
+
const bundles = registry.taskBundles ?? [];
|
|
420
|
+
const bundle = bundles.find((b) => b.name.toLowerCase() === bundleName.toLowerCase());
|
|
421
|
+
if (!bundle) {
|
|
422
|
+
const available = bundles.map((b) => b.name).join(", ");
|
|
423
|
+
return {
|
|
424
|
+
content: [
|
|
425
|
+
{
|
|
426
|
+
type: "text",
|
|
427
|
+
text: `Bundle "${bundleName}" not found. Available bundles: ${available}`
|
|
428
|
+
}
|
|
429
|
+
],
|
|
430
|
+
isError: true
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
const componentMap = new Map(registry.components.map((c) => [c.name, c]));
|
|
434
|
+
const parts = [];
|
|
435
|
+
parts.push(`# Bundle: ${bundle.name}`);
|
|
436
|
+
parts.push("");
|
|
437
|
+
parts.push(bundle.description);
|
|
438
|
+
parts.push("");
|
|
439
|
+
const allImports = [];
|
|
440
|
+
for (const compName of bundle.components) {
|
|
441
|
+
const comp = componentMap.get(compName);
|
|
442
|
+
allImports.push(compName);
|
|
443
|
+
if (comp?.subcomponents) {
|
|
444
|
+
allImports.push(...comp.subcomponents);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
parts.push("## Import");
|
|
448
|
+
parts.push("");
|
|
449
|
+
parts.push("```tsx");
|
|
450
|
+
parts.push(`import { ${allImports.join(", ")} } from '@hareru/ui';`);
|
|
451
|
+
parts.push("```");
|
|
452
|
+
parts.push("");
|
|
453
|
+
parts.push("## CSS");
|
|
454
|
+
parts.push("");
|
|
455
|
+
parts.push("**Standalone:**");
|
|
456
|
+
parts.push("```css");
|
|
457
|
+
parts.push(`@import '@hareru/ui/styles.css';`);
|
|
458
|
+
parts.push("```");
|
|
459
|
+
parts.push("");
|
|
460
|
+
parts.push("**Per-component:**");
|
|
461
|
+
parts.push("```css");
|
|
462
|
+
parts.push(`@import '@hareru/tokens/css';`);
|
|
463
|
+
for (const artifact of bundle.cssArtifacts) {
|
|
464
|
+
parts.push(`@import '@hareru/ui/${artifact}';`);
|
|
465
|
+
}
|
|
466
|
+
parts.push("```");
|
|
467
|
+
parts.push("");
|
|
468
|
+
parts.push("## Token Categories");
|
|
469
|
+
parts.push("");
|
|
470
|
+
parts.push(bundle.tokenCategories.join(", "));
|
|
471
|
+
parts.push("");
|
|
472
|
+
parts.push("## Components");
|
|
473
|
+
parts.push("");
|
|
474
|
+
for (const compName of bundle.components) {
|
|
475
|
+
const comp = componentMap.get(compName);
|
|
476
|
+
if (comp) {
|
|
477
|
+
parts.push(`- **${comp.name}** \u2014 ${comp.description}`);
|
|
478
|
+
} else {
|
|
479
|
+
parts.push(`- **${compName}**`);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
parts.push("");
|
|
483
|
+
return {
|
|
484
|
+
content: [{ type: "text", text: parts.join("\n") }]
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
);
|
|
488
|
+
server.tool(
|
|
489
|
+
"validate-token-value",
|
|
490
|
+
"Validate a CSS token value against the Hareru UI design token schema",
|
|
491
|
+
{
|
|
492
|
+
tokenType: z2.string().describe(
|
|
493
|
+
"Token type: color, dimension, fontFamily, fontWeight, duration, number, shadow, typography, cubicBezier"
|
|
494
|
+
),
|
|
495
|
+
value: z2.string().describe('The value to validate (e.g. "oklch(0.5 0.2 250)")')
|
|
496
|
+
},
|
|
497
|
+
async ({ tokenType, value }) => {
|
|
498
|
+
const schema = loadSchema();
|
|
499
|
+
const constraint = schema.properties.typeConstraints.properties[tokenType];
|
|
500
|
+
if (!constraint) {
|
|
501
|
+
const availableTypes = Object.keys(schema.properties.typeConstraints.properties).join(", ");
|
|
502
|
+
return {
|
|
503
|
+
content: [
|
|
504
|
+
{
|
|
505
|
+
type: "text",
|
|
506
|
+
text: `Unknown token type "${tokenType}". Available types: ${availableTypes}`
|
|
507
|
+
}
|
|
508
|
+
],
|
|
509
|
+
isError: true
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
if (!constraint.pattern) {
|
|
513
|
+
return {
|
|
514
|
+
content: [
|
|
515
|
+
{
|
|
516
|
+
type: "text",
|
|
517
|
+
text: `Valid \u2014 token type "${tokenType}" has no pattern constraint (any ${constraint.type ?? "string"} value accepted).`
|
|
518
|
+
}
|
|
519
|
+
]
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
let regex;
|
|
523
|
+
try {
|
|
524
|
+
regex = new RegExp(constraint.pattern);
|
|
525
|
+
} catch {
|
|
526
|
+
return {
|
|
527
|
+
content: [
|
|
528
|
+
{
|
|
529
|
+
type: "text",
|
|
530
|
+
text: `Error \u2014 invalid pattern for token type "${tokenType}": ${constraint.pattern}`
|
|
531
|
+
}
|
|
532
|
+
],
|
|
533
|
+
isError: true
|
|
534
|
+
};
|
|
535
|
+
}
|
|
536
|
+
const isValid = regex.test(value);
|
|
537
|
+
if (isValid) {
|
|
538
|
+
return {
|
|
539
|
+
content: [
|
|
540
|
+
{
|
|
541
|
+
type: "text",
|
|
542
|
+
text: `Valid \u2014 "${value}" matches the ${tokenType} pattern: ${constraint.pattern}`
|
|
543
|
+
}
|
|
544
|
+
]
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
return {
|
|
548
|
+
content: [
|
|
549
|
+
{
|
|
550
|
+
type: "text",
|
|
551
|
+
text: `Invalid \u2014 "${value}" does not match the ${tokenType} pattern.
|
|
552
|
+
Expected: ${constraint.pattern}
|
|
553
|
+
Description: ${constraint.description ?? tokenType}`
|
|
554
|
+
}
|
|
555
|
+
]
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
);
|
|
559
|
+
server.tool(
|
|
560
|
+
"recommend-css-mode",
|
|
561
|
+
"Recommend the best CSS import mode for a Hareru UI project based on project context",
|
|
562
|
+
{
|
|
563
|
+
hasTailwind: z2.boolean().describe("Whether Tailwind CSS is detected in the project"),
|
|
564
|
+
componentCount: z2.number().int().min(0).describe("Number of Hareru components used in the project"),
|
|
565
|
+
hasExistingReset: z2.boolean().optional().describe(
|
|
566
|
+
"Whether the project already has a CSS reset or framework (e.g. Bootstrap, Pico CSS)"
|
|
567
|
+
)
|
|
568
|
+
},
|
|
569
|
+
async ({ hasTailwind, componentCount, hasExistingReset }) => {
|
|
570
|
+
const result = recommendCssMode({ hasTailwind, componentCount, hasExistingReset });
|
|
571
|
+
const allModes = CSS_MODES.map((m) => {
|
|
572
|
+
const marker = m === result.mode ? " \u2190 recommended" : "";
|
|
573
|
+
return `- **${m}**: ${CSS_MODE_DESCRIPTIONS[m]}${marker}`;
|
|
574
|
+
}).join("\n");
|
|
575
|
+
return {
|
|
576
|
+
content: [
|
|
577
|
+
{
|
|
578
|
+
type: "text",
|
|
579
|
+
text: `## Recommended CSS Mode: \`${result.mode}\`
|
|
580
|
+
|
|
581
|
+
${result.reason}
|
|
582
|
+
|
|
583
|
+
## All Modes
|
|
584
|
+
|
|
585
|
+
${allModes}`
|
|
586
|
+
}
|
|
587
|
+
]
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
);
|
|
591
|
+
server.tool(
|
|
592
|
+
"list-components-by-group",
|
|
593
|
+
"List Hareru UI components filtered by group",
|
|
594
|
+
{
|
|
595
|
+
group: z2.enum([
|
|
596
|
+
"core",
|
|
597
|
+
"form",
|
|
598
|
+
"layout",
|
|
599
|
+
"overlay",
|
|
600
|
+
"navigation",
|
|
601
|
+
"feedback",
|
|
602
|
+
"data-display",
|
|
603
|
+
"agent",
|
|
604
|
+
"di-domain"
|
|
605
|
+
]).describe("Component group to filter by")
|
|
606
|
+
},
|
|
607
|
+
async ({ group }) => {
|
|
608
|
+
const registry = loadRegistry();
|
|
609
|
+
const filtered = registry.components.filter((c) => c.group === group);
|
|
610
|
+
if (filtered.length === 0) {
|
|
611
|
+
const groups = [...new Set(registry.components.map((c) => c.group))].sort();
|
|
612
|
+
return {
|
|
613
|
+
content: [
|
|
614
|
+
{
|
|
615
|
+
type: "text",
|
|
616
|
+
text: `No components in group "${group}". Available groups: ${groups.join(", ")}`
|
|
617
|
+
}
|
|
618
|
+
],
|
|
619
|
+
isError: true
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
const lines = filtered.map((c) => {
|
|
623
|
+
const variants = c.variants ?? [];
|
|
624
|
+
const variantInfo = variants.length > 0 ? ` [${variants.flatMap((v) => Object.entries(v.variants).map(([k, opts]) => `${k}(${opts.join("|")})`)).join(", ")}]` : "";
|
|
625
|
+
return `- **${c.name}**${variantInfo} \u2014 ${c.description}`;
|
|
626
|
+
}).join("\n");
|
|
627
|
+
return {
|
|
628
|
+
content: [
|
|
629
|
+
{
|
|
630
|
+
type: "text",
|
|
631
|
+
text: `## ${group} (${filtered.length} components)
|
|
632
|
+
|
|
633
|
+
${lines}`
|
|
634
|
+
}
|
|
635
|
+
]
|
|
636
|
+
};
|
|
637
|
+
}
|
|
638
|
+
);
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
// src/index.ts
|
|
642
|
+
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
643
|
+
var pkg = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf-8"));
|
|
644
|
+
function createServer() {
|
|
645
|
+
const server = new McpServer({
|
|
646
|
+
name: "hareru-ui",
|
|
647
|
+
version: pkg.version
|
|
648
|
+
});
|
|
649
|
+
registerResources(server);
|
|
650
|
+
registerTools(server);
|
|
651
|
+
registerPrompts(server);
|
|
652
|
+
return server;
|
|
653
|
+
}
|
|
654
|
+
async function startServer() {
|
|
655
|
+
const server = createServer();
|
|
656
|
+
const transport = new StdioServerTransport();
|
|
657
|
+
await server.connect(transport);
|
|
658
|
+
console.error("Hareru UI MCP server started (stdio)");
|
|
659
|
+
}
|
|
660
|
+
export {
|
|
661
|
+
createServer,
|
|
662
|
+
startServer
|
|
663
|
+
};
|
|
664
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/prompts.ts","../src/utils.ts","../src/resources.ts","../src/tools.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { registerPrompts } from './prompts.js';\nimport { registerResources } from './resources.js';\nimport { registerTools } from './tools.js';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8')) as {\n version: string;\n};\n\nexport function createServer(): McpServer {\n const server = new McpServer({\n name: 'hareru-ui',\n version: pkg.version,\n });\n\n registerResources(server);\n registerTools(server);\n registerPrompts(server);\n\n return server;\n}\n\nexport async function startServer(): Promise<void> {\n const server = createServer();\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error('Hareru UI MCP server started (stdio)');\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { loadConsumerRules, loadRegistry, loadSchema } from './utils.js';\n\nexport function registerPrompts(server: McpServer): void {\n server.prompt(\n 'create-ui',\n 'Generate a UI component using Hareru UI design system',\n {\n description: z\n .string()\n .describe(\n 'What the component should do (e.g. \"A settings form with name and email fields\")',\n ),\n framework: z.string().optional().describe('Target framework: react (default)'),\n },\n async ({ description, framework }) => {\n const registry = loadRegistry();\n const schema = loadSchema();\n\n const componentList = registry.components\n .map((c) => {\n const variants = c.variants ?? [];\n const variantInfo =\n variants.length > 0\n ? ` [${variants.flatMap((v) => Object.entries(v.variants).map(([k, opts]) => `${k}(${opts.join('|')})`)).join(', ')}]`\n : '';\n const desc = c.description ? ` — ${c.description}` : '';\n return `- ${c.name}${variantInfo}${desc}`;\n })\n .join('\\n');\n\n const bundles = registry.taskBundles ?? [];\n const bundleList =\n bundles.length > 0\n ? bundles\n .map((b) => `- ${b.name}: ${b.description} (${b.components.length} components)`)\n .join('\\n')\n : '';\n\n const cssVars = schema.properties.cssVariables.items.enum.slice(0, 20).join(', ');\n const fw = framework ?? 'react';\n\n return {\n messages: [\n {\n role: 'user' as const,\n content: {\n type: 'text' as const,\n text: `You are a UI developer using the Hareru UI design system (${fw}).\n\n## Available Components\n\n${componentList}\n\n## Design Token CSS Variables (sample)\n\n${cssVars}, ...\n\n## Rules\n\n1. Import components from '@hareru/ui'. For CSS setup, refer to the consumer-rules (standalone: '@hareru/ui/styles.css', portable: '@hareru/tokens/css' + '@hareru/ui/styles/components.css')\n2. Use only semantic variant props (e.g. variant=\"default\"), never hardcode CSS values\n3. Use CSS variables (--hui-*) for any custom styling\n4. All components support forwardRef\n5. Use BEM class naming (hui-*) if adding custom classes\n6. Colors use OKLCH format\n\n## Task\n\n${description}\n${bundleList ? `\\n## Available Bundles\\n\\n${bundleList}\\n` : ''}\nGenerate a complete ${fw} component that fulfills this requirement.`,\n },\n },\n ],\n };\n },\n );\n\n server.prompt(\n 'create-ui-tailwind',\n 'Generate a UI component mixing Hareru UI and Tailwind CSS with Cascade Layer guidance',\n {\n description: z\n .string()\n .describe(\n 'What the component should do (e.g. \"A dashboard card with Tailwind layout and Hareru UI buttons\")',\n ),\n },\n async ({ description }) => {\n const registry = loadRegistry();\n\n const componentList = registry.components\n .map((c) => {\n const desc = c.description ? ` — ${c.description}` : '';\n return `- ${c.name}${desc}`;\n })\n .join('\\n');\n\n return {\n messages: [\n {\n role: 'user' as const,\n content: {\n type: 'text' as const,\n text: `You are a UI developer using Hareru UI + Tailwind CSS v4 together.\n\n## Cascade Layer Order\n\nDeclare this layer order at the top of your CSS entry point:\n\n\\`\\`\\`css\n@layer theme, base, hui, components, utilities;\n@import 'tailwindcss';\n@import '@hareru/tokens/css';\n@import '@hareru/ui/styles/components.layer.css';\n\\`\\`\\`\n\n- Hareru components live in \\`@layer hui\\` — below Tailwind \\`utilities\\`\n- Tailwind utility classes (e.g. \\`flex\\`, \\`gap-4\\`, \\`p-2\\`) can safely override Hareru layout\n- Never use Tailwind classes to override Hareru component internals (colors, border-radius, shadows) — use \\`--hui-*\\` CSS variables instead\n\n## Mixing Classes Example\n\n\\`\\`\\`tsx\n{/* Tailwind for layout, Hareru for components */}\n<div className=\"flex gap-4 p-6\">\n <Card className=\"flex-1\">\n <CardHeader>Title</CardHeader>\n <CardContent>\n <Button variant=\"default\">Action</Button>\n </CardContent>\n </Card>\n</div>\n\\`\\`\\`\n\n## Available Components\n\n${componentList}\n\n## Rules\n\n1. Import components from \\`@hareru/ui\\`\n2. Use Tailwind utilities for layout (flex, grid, gap, padding, margin)\n3. Use Hareru components for interactive UI elements (Button, Input, Card, Dialog)\n4. Use \\`--hui-*\\` CSS variables for theming — do not override with Tailwind color classes\n5. Use BEM class naming (\\`hui-*\\`) if adding custom component styles\n6. Colors are OKLCH format\n\n## Task\n\n${description}\n\nGenerate a complete React component that combines Tailwind layout utilities with Hareru UI components.`,\n },\n },\n ],\n };\n },\n );\n\n server.prompt(\n 'consumer-rules',\n 'Get the rules for using Hareru UI in your project',\n {},\n async () => {\n const rules = loadConsumerRules();\n\n const CODE_BLOCK_SECTIONS = new Set(['cssImports']);\n\n const rulesSections = Object.entries(rules.rules)\n .map(([key, section]) => {\n const ruleList = section.rules.map((r) => `- ${r}`).join('\\n');\n const examples = Object.entries(section.examples)\n .map(([label, code]) =>\n CODE_BLOCK_SECTIONS.has(key)\n ? `**${label}:**\\n\\`\\`\\`css\\n${code}\\n\\`\\`\\``\n : ` ${label}: ${code}`,\n )\n .join('\\n');\n return `### ${key}\\n${section.description}\\n\\n${ruleList}\\n\\nExamples:\\n${examples}`;\n })\n .join('\\n\\n');\n\n const tokenRef = Object.entries(rules.tokenQuickReference)\n .map(([category, pattern]) => `- ${category}: ${pattern}`)\n .join('\\n');\n\n return {\n messages: [\n {\n role: 'user' as const,\n content: {\n type: 'text' as const,\n text: `# Hareru UI Consumer Rules (v${rules.version})\n\nThese rules apply when using Hareru UI in any project.\n\n## Rules\n\n${rulesSections}\n\n## Token Quick Reference\n\n${tokenRef}`,\n },\n },\n ],\n };\n },\n );\n}\n","export {\n loadTokens,\n loadSchema,\n loadRegistry,\n loadComponentSchema,\n loadConsumerRules,\n CSS_MODES,\n CSS_MODE_DESCRIPTIONS,\n recommendCssMode,\n} from '@hareru/registry';\n\nexport type {\n TokensJSON,\n SchemaJSON,\n ComponentRegistryJSON,\n ComponentEntry,\n TaskBundle,\n ComponentGroup,\n TokenCategory,\n VariantDef,\n CustomPropDef,\n PropDef,\n ComponentSchemaJSON,\n ConsumerRulesJSON,\n CssMode,\n CssModeContext,\n} from '@hareru/registry';\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport {\n loadComponentSchema,\n loadConsumerRules,\n loadRegistry,\n loadSchema,\n loadTokens,\n} from './utils.js';\n\nexport function registerResources(server: McpServer): void {\n const schema = loadSchema();\n const tokenCount = schema.properties.tokenCount.const;\n const registry = loadRegistry();\n\n server.resource(\n 'tokens',\n 'hareru-ui://tokens',\n {\n description: `DTCG design tokens (light/dark themes, ${tokenCount} CSS custom properties)`,\n mimeType: 'application/json',\n },\n async (uri) => ({\n contents: [{ uri: uri.href, text: JSON.stringify(loadTokens(), null, 2) }],\n }),\n );\n\n server.resource(\n 'tokens-schema',\n 'hareru-ui://tokens/schema',\n {\n description: 'JSON Schema for design tokens — CSS variable enums and type constraints',\n mimeType: 'application/json',\n },\n async (uri) => ({\n contents: [{ uri: uri.href, text: JSON.stringify(loadSchema(), null, 2) }],\n }),\n );\n\n server.resource(\n 'components',\n 'hareru-ui://components',\n {\n description: `Component registry — ${registry.componentCount} components with CVA variants and Props interfaces`,\n mimeType: 'application/json',\n },\n async (uri) => ({\n contents: [{ uri: uri.href, text: JSON.stringify(registry, null, 2) }],\n }),\n );\n\n server.resource(\n 'bundles',\n 'hareru-ui://bundles',\n {\n description: `Task bundles — ${registry.taskBundles?.length ?? 0} curated component sets for common UI patterns`,\n mimeType: 'application/json',\n },\n async (uri) => ({\n contents: [{ uri: uri.href, text: JSON.stringify(registry.taskBundles ?? [], null, 2) }],\n }),\n );\n\n server.resource(\n 'components-schema',\n 'hareru-ui://components/schema',\n {\n description: 'JSON Schema for the component registry',\n mimeType: 'application/json',\n },\n async (uri) => ({\n contents: [{ uri: uri.href, text: JSON.stringify(loadComponentSchema(), null, 2) }],\n }),\n );\n\n server.resource(\n 'consumer-rules',\n 'hareru-ui://rules/consumer',\n {\n description:\n 'Consumer rules for AI agents — import patterns, styling rules, and token reference',\n mimeType: 'application/json',\n },\n async (uri) => ({\n contents: [{ uri: uri.href, text: JSON.stringify(loadConsumerRules(), null, 2) }],\n }),\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport {\n CSS_MODES,\n CSS_MODE_DESCRIPTIONS,\n loadRegistry,\n loadSchema,\n recommendCssMode,\n} from './utils.js';\nimport type { ComponentEntry } from './utils.js';\n\nfunction escPipe(s: string): string {\n return s.replace(/\\|/g, '\\\\|');\n}\n\nfunction formatVariantsTable(entry: ComponentEntry): string {\n const variants = entry.variants ?? [];\n if (variants.length === 0) return 'No CVA variants defined.';\n\n const lines: string[] = ['| Variant | Options | Default |', '|---------|---------|---------|'];\n for (const v of variants) {\n for (const [key, options] of Object.entries(v.variants)) {\n const defaultVal = v.defaultVariants[key] ?? '-';\n lines.push(\n `| ${escPipe(key)} | ${options.map(escPipe).join(', ')} | ${escPipe(defaultVal)} |`,\n );\n }\n }\n return lines.join('\\n');\n}\n\nfunction formatUsageMarkdown(entry: ComponentEntry): string {\n const parts: string[] = [];\n\n parts.push(`# ${entry.displayName}`);\n parts.push('');\n\n // Description (Phase 3A)\n parts.push(entry.description);\n parts.push('');\n\n // AI Guidance (Phase 3A)\n if (entry.aiHint) {\n parts.push('## AI Guidance');\n parts.push('');\n parts.push(entry.aiHint);\n parts.push('');\n }\n\n // Import section\n parts.push('## Import');\n parts.push('');\n parts.push('```tsx');\n const subs = entry.subcomponents ?? [];\n const allNames = [entry.name, ...subs];\n parts.push(`import { ${allNames.join(', ')} } from '@hareru/ui';`);\n parts.push('```');\n parts.push('');\n\n // CSS section (registry-driven)\n parts.push('## CSS');\n parts.push('');\n parts.push('**Standalone:**');\n parts.push('```css');\n parts.push(`@import '@hareru/ui/styles.css';`);\n parts.push('```');\n parts.push('');\n parts.push('**Per-component:**');\n parts.push('```css');\n parts.push(`@import '@hareru/tokens/css';`);\n for (const dep of entry.requiredCssArtifacts ?? []) {\n parts.push(`@import '@hareru/ui/${dep}';`);\n }\n parts.push(`@import '@hareru/ui/${entry.cssArtifact}';`);\n parts.push('```');\n parts.push('');\n\n const variants = entry.variants ?? [];\n const props = entry.props ?? [];\n\n if (variants.length > 0) {\n parts.push('## Variants');\n parts.push('');\n parts.push(formatVariantsTable(entry));\n parts.push('');\n }\n\n if (props.length > 0) {\n parts.push('## Props');\n parts.push('');\n for (const prop of props) {\n if (prop.extends) {\n parts.push(`- **${prop.name}** extends \\`${prop.extends}\\``);\n } else {\n parts.push(`- **${prop.name}**`);\n }\n }\n parts.push('');\n }\n\n // Also Consider (Phase 3A)\n if (entry.peerComponents) {\n parts.push('## Also Consider');\n parts.push('');\n for (const peer of entry.peerComponents) {\n parts.push(`- ${peer}`);\n }\n parts.push('');\n }\n\n parts.push('## Example');\n parts.push('');\n parts.push('```tsx');\n if (variants.length > 0) {\n const firstVariant = variants[0];\n const propsStr = Object.entries(firstVariant.defaultVariants)\n .map(([k, v]) => `${k}=\"${v}\"`)\n .join(' ');\n parts.push(`<${entry.name} ${propsStr}>Content</${entry.name}>`);\n } else if (subs.length > 0) {\n parts.push(`<${entry.name}>`);\n for (const sub of subs) {\n parts.push(` <${sub}>Content</${sub}>`);\n }\n parts.push(`</${entry.name}>`);\n } else {\n parts.push(`<${entry.name}>Content</${entry.name}>`);\n }\n parts.push('```');\n\n return parts.join('\\n');\n}\n\nexport function registerTools(server: McpServer): void {\n server.tool(\n 'get-component-usage',\n 'Get usage documentation for a Hareru UI component — import, variants, props, and JSX example',\n { componentName: z.string().describe('Component name (e.g. \"Button\", \"Card\", \"Alert\")') },\n async ({ componentName }) => {\n const registry = loadRegistry();\n const entry = registry.components.find(\n (c) => c.name.toLowerCase() === componentName.toLowerCase(),\n );\n\n if (!entry) {\n const available = registry.components.map((c) => c.name).join(', ');\n return {\n content: [\n {\n type: 'text' as const,\n text: `Component \"${componentName}\" not found. Available components: ${available}`,\n },\n ],\n isError: true,\n };\n }\n\n return {\n content: [{ type: 'text' as const, text: formatUsageMarkdown(entry) }],\n };\n },\n );\n\n server.tool(\n 'get-bundle-usage',\n 'Get usage documentation for a Hareru UI task bundle — components, CSS imports, and token categories',\n { bundleName: z.string().describe('Bundle name (e.g. \"agent-chat-shell\", \"form-basics\")') },\n async ({ bundleName }) => {\n const registry = loadRegistry();\n const bundles = registry.taskBundles ?? [];\n const bundle = bundles.find((b) => b.name.toLowerCase() === bundleName.toLowerCase());\n\n if (!bundle) {\n const available = bundles.map((b) => b.name).join(', ');\n return {\n content: [\n {\n type: 'text' as const,\n text: `Bundle \"${bundleName}\" not found. Available bundles: ${available}`,\n },\n ],\n isError: true,\n };\n }\n\n const componentMap = new Map(registry.components.map((c) => [c.name, c]));\n\n const parts: string[] = [];\n parts.push(`# Bundle: ${bundle.name}`);\n parts.push('');\n parts.push(bundle.description);\n parts.push('');\n\n // Import section — expand subcomponents so the import is copy-pasteable\n const allImports: string[] = [];\n for (const compName of bundle.components) {\n const comp = componentMap.get(compName);\n allImports.push(compName);\n if (comp?.subcomponents) {\n allImports.push(...comp.subcomponents);\n }\n }\n parts.push('## Import');\n parts.push('');\n parts.push('```tsx');\n parts.push(`import { ${allImports.join(', ')} } from '@hareru/ui';`);\n parts.push('```');\n parts.push('');\n\n // CSS section\n parts.push('## CSS');\n parts.push('');\n parts.push('**Standalone:**');\n parts.push('```css');\n parts.push(`@import '@hareru/ui/styles.css';`);\n parts.push('```');\n parts.push('');\n parts.push('**Per-component:**');\n parts.push('```css');\n parts.push(`@import '@hareru/tokens/css';`);\n for (const artifact of bundle.cssArtifacts) {\n parts.push(`@import '@hareru/ui/${artifact}';`);\n }\n parts.push('```');\n parts.push('');\n\n // Token categories\n parts.push('## Token Categories');\n parts.push('');\n parts.push(bundle.tokenCategories.join(', '));\n parts.push('');\n\n // Components detail\n parts.push('## Components');\n parts.push('');\n for (const compName of bundle.components) {\n const comp = componentMap.get(compName);\n if (comp) {\n parts.push(`- **${comp.name}** — ${comp.description}`);\n } else {\n parts.push(`- **${compName}**`);\n }\n }\n parts.push('');\n\n return {\n content: [{ type: 'text' as const, text: parts.join('\\n') }],\n };\n },\n );\n\n server.tool(\n 'validate-token-value',\n 'Validate a CSS token value against the Hareru UI design token schema',\n {\n tokenType: z\n .string()\n .describe(\n 'Token type: color, dimension, fontFamily, fontWeight, duration, number, shadow, typography, cubicBezier',\n ),\n value: z.string().describe('The value to validate (e.g. \"oklch(0.5 0.2 250)\")'),\n },\n async ({ tokenType, value }) => {\n const schema = loadSchema();\n const constraint =\n schema.properties.typeConstraints.properties[\n tokenType as keyof typeof schema.properties.typeConstraints.properties\n ];\n\n if (!constraint) {\n const availableTypes = Object.keys(schema.properties.typeConstraints.properties).join(', ');\n return {\n content: [\n {\n type: 'text' as const,\n text: `Unknown token type \"${tokenType}\". Available types: ${availableTypes}`,\n },\n ],\n isError: true,\n };\n }\n\n if (!constraint.pattern) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Valid — token type \"${tokenType}\" has no pattern constraint (any ${constraint.type ?? 'string'} value accepted).`,\n },\n ],\n };\n }\n\n let regex: RegExp;\n try {\n regex = new RegExp(constraint.pattern);\n } catch {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error — invalid pattern for token type \"${tokenType}\": ${constraint.pattern}`,\n },\n ],\n isError: true,\n };\n }\n\n const isValid = regex.test(value);\n\n if (isValid) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Valid — \"${value}\" matches the ${tokenType} pattern: ${constraint.pattern}`,\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `Invalid — \"${value}\" does not match the ${tokenType} pattern.\\nExpected: ${constraint.pattern}\\nDescription: ${constraint.description ?? tokenType}`,\n },\n ],\n };\n },\n );\n\n server.tool(\n 'recommend-css-mode',\n 'Recommend the best CSS import mode for a Hareru UI project based on project context',\n {\n hasTailwind: z.boolean().describe('Whether Tailwind CSS is detected in the project'),\n componentCount: z\n .number()\n .int()\n .min(0)\n .describe('Number of Hareru components used in the project'),\n hasExistingReset: z\n .boolean()\n .optional()\n .describe(\n 'Whether the project already has a CSS reset or framework (e.g. Bootstrap, Pico CSS)',\n ),\n },\n async ({ hasTailwind, componentCount, hasExistingReset }) => {\n const result = recommendCssMode({ hasTailwind, componentCount, hasExistingReset });\n\n const allModes = CSS_MODES.map((m) => {\n const marker = m === result.mode ? ' ← recommended' : '';\n return `- **${m}**: ${CSS_MODE_DESCRIPTIONS[m]}${marker}`;\n }).join('\\n');\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `## Recommended CSS Mode: \\`${result.mode}\\`\\n\\n${result.reason}\\n\\n## All Modes\\n\\n${allModes}`,\n },\n ],\n };\n },\n );\n\n server.tool(\n 'list-components-by-group',\n 'List Hareru UI components filtered by group',\n {\n group: z\n .enum([\n 'core',\n 'form',\n 'layout',\n 'overlay',\n 'navigation',\n 'feedback',\n 'data-display',\n 'agent',\n 'di-domain',\n ])\n .describe('Component group to filter by'),\n },\n async ({ group }) => {\n const registry = loadRegistry();\n const filtered = registry.components.filter((c) => c.group === group);\n\n if (filtered.length === 0) {\n const groups = [...new Set(registry.components.map((c) => c.group))].sort();\n return {\n content: [\n {\n type: 'text' as const,\n text: `No components in group \"${group}\". Available groups: ${groups.join(', ')}`,\n },\n ],\n isError: true,\n };\n }\n\n const lines = filtered\n .map((c) => {\n const variants = c.variants ?? [];\n const variantInfo =\n variants.length > 0\n ? ` [${variants.flatMap((v) => Object.entries(v.variants).map(([k, opts]) => `${k}(${opts.join('|')})`)).join(', ')}]`\n : '';\n return `- **${c.name}**${variantInfo} — ${c.description}`;\n })\n .join('\\n');\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `## ${group} (${filtered.length} components)\\n\\n${lines}`,\n },\n ],\n };\n },\n );\n}\n"],"mappings":"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","names":["z","z"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hareru/mcp",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "MCP server for Hareru UI design system — exposes tokens, schema, and component registry to AI agents",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/hareru-ai/ui",
|
|
9
|
+
"directory": "packages/mcp"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/hareru-ai/ui",
|
|
12
|
+
"keywords": [
|
|
13
|
+
"mcp",
|
|
14
|
+
"model-context-protocol",
|
|
15
|
+
"design-system",
|
|
16
|
+
"hareru",
|
|
17
|
+
"ai"
|
|
18
|
+
],
|
|
19
|
+
"type": "module",
|
|
20
|
+
"module": "./dist/index.js",
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"types": "./dist/index.d.ts",
|
|
25
|
+
"import": "./dist/index.js"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"bin": {
|
|
29
|
+
"hareru-mcp": "./bin/hareru-mcp.mjs"
|
|
30
|
+
},
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"access": "public"
|
|
33
|
+
},
|
|
34
|
+
"files": [
|
|
35
|
+
"dist",
|
|
36
|
+
"bin",
|
|
37
|
+
"LICENSE"
|
|
38
|
+
],
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
41
|
+
"zod": "^3.23.0",
|
|
42
|
+
"@hareru/registry": "0.2.0"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@types/node": "^22.0.0",
|
|
46
|
+
"tsup": "^8.0.0",
|
|
47
|
+
"typescript": "^5.7.0",
|
|
48
|
+
"vitest": "^2.0.0"
|
|
49
|
+
},
|
|
50
|
+
"scripts": {
|
|
51
|
+
"build": "tsup",
|
|
52
|
+
"dev": "tsup --watch",
|
|
53
|
+
"test": "vitest run"
|
|
54
|
+
}
|
|
55
|
+
}
|