@pandacss/mcp 1.11.2 → 2.0.0-beta.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.md +1 -1
- package/README.md +18 -0
- package/bin.js +3 -0
- package/dist/chunk-OBOPWZHX.mjs +150 -0
- package/dist/cli.js +192 -0
- package/dist/cli.mjs +24 -0
- package/dist/index.js +53 -189
- package/dist/index.mjs +4 -279
- package/package.json +11 -10
package/LICENSE.md
CHANGED
package/README.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# @pandacss/mcp
|
|
2
|
+
|
|
3
|
+
A [Model Context Protocol](https://modelcontextprotocol.io) server for [Panda CSS](https://panda-css.com), giving AI
|
|
4
|
+
assistants structured access to the Panda compiler.
|
|
5
|
+
|
|
6
|
+
## Usage
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npx -y @pandacss/mcp
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Documentation
|
|
13
|
+
|
|
14
|
+
Visit the [Panda CSS documentation](https://panda-css.com) to learn more.
|
|
15
|
+
|
|
16
|
+
## License
|
|
17
|
+
|
|
18
|
+
MIT © [Chakra Systems Inc.](https://github.com/chakra-ui)
|
package/bin.js
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
// src/server.ts
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { createNodeDriver } from "@pandacss/compiler";
|
|
5
|
+
import { resolve } from "path";
|
|
6
|
+
import * as z from "zod/v4";
|
|
7
|
+
var json = (data) => ({
|
|
8
|
+
content: [{ type: "text", text: JSON.stringify(data) }]
|
|
9
|
+
});
|
|
10
|
+
function createMcpServer(options) {
|
|
11
|
+
const { driver } = options;
|
|
12
|
+
const spec = driver.introspect.spec;
|
|
13
|
+
const theme = driver.config.theme ?? {};
|
|
14
|
+
const server = new McpServer({
|
|
15
|
+
name: "@pandacss/mcp",
|
|
16
|
+
version: "1.0.0"
|
|
17
|
+
});
|
|
18
|
+
const tokenCategories = Object.keys(spec.tokens.categories);
|
|
19
|
+
const recipeNames = driver.introspect.recipes();
|
|
20
|
+
const patternNames = driver.introspect.patterns();
|
|
21
|
+
const tokenCategorySchema = (tokenCategories.length ? z.enum(tokenCategories) : z.string()).optional().describe("Filter by token category");
|
|
22
|
+
const recipeNameSchema = recipeNames.length ? z.enum(recipeNames).optional().describe("Filter by recipe name") : z.string().optional().describe("Filter by recipe name");
|
|
23
|
+
const patternNameSchema = patternNames.length ? z.enum(patternNames).optional().describe("Filter by pattern name") : z.string().optional().describe("Filter by pattern name");
|
|
24
|
+
const pickCategory = (record, category) => category ? { [category]: record[category] } : record;
|
|
25
|
+
server.registerTool(
|
|
26
|
+
"get_tokens",
|
|
27
|
+
{
|
|
28
|
+
description: "Get all design tokens with their values, CSS variables, and usage examples",
|
|
29
|
+
inputSchema: { category: tokenCategorySchema }
|
|
30
|
+
},
|
|
31
|
+
async ({ category }) => {
|
|
32
|
+
const categories = category ? { [category]: spec.tokens.categories[category] } : spec.tokens.categories;
|
|
33
|
+
const values = category ? Object.fromEntries(Object.entries(spec.tokens.values).filter(([path]) => path.startsWith(`${category}.`))) : spec.tokens.values;
|
|
34
|
+
return json({ categories, values, deprecated: spec.tokens.deprecated });
|
|
35
|
+
}
|
|
36
|
+
);
|
|
37
|
+
server.registerTool(
|
|
38
|
+
"get_semantic_tokens",
|
|
39
|
+
{
|
|
40
|
+
description: "Get semantic tokens with their conditional values (responsive, color modes)",
|
|
41
|
+
inputSchema: { category: tokenCategorySchema }
|
|
42
|
+
},
|
|
43
|
+
async ({ category }) => {
|
|
44
|
+
const semanticTokens = theme.semanticTokens ?? {};
|
|
45
|
+
return json(pickCategory(semanticTokens, category));
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
server.registerTool(
|
|
49
|
+
"get_recipes",
|
|
50
|
+
{
|
|
51
|
+
description: "Get component recipes with their variants, default values, and usage examples",
|
|
52
|
+
inputSchema: { name: recipeNameSchema }
|
|
53
|
+
},
|
|
54
|
+
async ({ name }) => {
|
|
55
|
+
const { recipes, slotRecipes } = spec.recipes;
|
|
56
|
+
if (name) {
|
|
57
|
+
return json({
|
|
58
|
+
recipes: pickCategory(recipes, name in recipes ? name : void 0),
|
|
59
|
+
slotRecipes: pickCategory(slotRecipes, name in slotRecipes ? name : void 0)
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
return json({ recipes, slotRecipes });
|
|
63
|
+
}
|
|
64
|
+
);
|
|
65
|
+
server.registerTool(
|
|
66
|
+
"get_patterns",
|
|
67
|
+
{
|
|
68
|
+
description: "Get layout patterns with their properties and usage examples",
|
|
69
|
+
inputSchema: { name: patternNameSchema }
|
|
70
|
+
},
|
|
71
|
+
async ({ name }) => json(pickCategory(spec.patterns.patterns, name))
|
|
72
|
+
);
|
|
73
|
+
server.registerTool(
|
|
74
|
+
"get_conditions",
|
|
75
|
+
{ description: "Get all conditions (breakpoints, pseudo-classes, color modes) and their CSS values" },
|
|
76
|
+
async () => json({ ...spec.conditions, definitions: theme.conditions ?? driver.config.conditions ?? {} })
|
|
77
|
+
);
|
|
78
|
+
server.registerTool(
|
|
79
|
+
"get_keyframes",
|
|
80
|
+
{ description: "Get keyframe animations defined in the theme" },
|
|
81
|
+
async () => json(theme.keyframes ?? {})
|
|
82
|
+
);
|
|
83
|
+
server.registerTool(
|
|
84
|
+
"get_text_styles",
|
|
85
|
+
{ description: "Get text style compositions for typography" },
|
|
86
|
+
async () => json(theme.textStyles ?? {})
|
|
87
|
+
);
|
|
88
|
+
server.registerTool(
|
|
89
|
+
"get_layer_styles",
|
|
90
|
+
{ description: "Get layer style compositions for visual styling" },
|
|
91
|
+
async () => json(theme.layerStyles ?? {})
|
|
92
|
+
);
|
|
93
|
+
server.registerTool(
|
|
94
|
+
"get_animation_styles",
|
|
95
|
+
{ description: "Get animation style compositions" },
|
|
96
|
+
async () => json(theme.animationStyles ?? {})
|
|
97
|
+
);
|
|
98
|
+
server.registerTool(
|
|
99
|
+
"get_color_palette",
|
|
100
|
+
{ description: "Get the color palette with all color values" },
|
|
101
|
+
async () => json({
|
|
102
|
+
colorPalettes: spec.tokens.colorPalettes,
|
|
103
|
+
colors: Object.fromEntries(Object.entries(spec.tokens.values).filter(([path]) => path.startsWith("colors.")))
|
|
104
|
+
})
|
|
105
|
+
);
|
|
106
|
+
server.registerTool(
|
|
107
|
+
"get_config",
|
|
108
|
+
{ description: "Get the resolved Panda CSS configuration including paths, JSX settings, and output options" },
|
|
109
|
+
async () => json(driver.config)
|
|
110
|
+
);
|
|
111
|
+
return server;
|
|
112
|
+
}
|
|
113
|
+
async function startMcpServer(options = {}) {
|
|
114
|
+
const { cwd = process.cwd(), config: configPath, silent = false, transport } = options;
|
|
115
|
+
const resolvedCwd = resolve(cwd);
|
|
116
|
+
const resolvedConfigPath = configPath ? resolve(configPath) : void 0;
|
|
117
|
+
const driver = await createNodeDriver({
|
|
118
|
+
cwd: resolvedCwd,
|
|
119
|
+
configPath: resolvedConfigPath
|
|
120
|
+
});
|
|
121
|
+
const server = createMcpServer({ driver });
|
|
122
|
+
const serverTransport = transport ?? new StdioServerTransport();
|
|
123
|
+
if (!transport) {
|
|
124
|
+
exitOnDisconnect();
|
|
125
|
+
}
|
|
126
|
+
await server.connect(serverTransport);
|
|
127
|
+
if (!silent) {
|
|
128
|
+
console.error("Panda CSS MCP server started");
|
|
129
|
+
console.error(`Working directory: ${resolvedCwd}`);
|
|
130
|
+
if (resolvedConfigPath) {
|
|
131
|
+
console.error(`Config path: ${resolvedConfigPath}`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return server;
|
|
135
|
+
}
|
|
136
|
+
function exitOnDisconnect(options = {}) {
|
|
137
|
+
const stdin = options.stdin ?? process.stdin;
|
|
138
|
+
const on = options.on ?? process.on.bind(process);
|
|
139
|
+
const exit = options.exit ?? ((code) => process.exit(code));
|
|
140
|
+
stdin.on("end", () => exit(0));
|
|
141
|
+
stdin.on("close", () => exit(0));
|
|
142
|
+
on("SIGINT", () => exit(0));
|
|
143
|
+
on("SIGTERM", () => exit(0));
|
|
144
|
+
on("SIGHUP", () => exit(0));
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export {
|
|
148
|
+
createMcpServer,
|
|
149
|
+
startMcpServer
|
|
150
|
+
};
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
+
for (let key of __getOwnPropNames(from))
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
12
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
13
|
+
}
|
|
14
|
+
return to;
|
|
15
|
+
};
|
|
16
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
17
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
18
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
19
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
20
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
21
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
|
+
mod
|
|
23
|
+
));
|
|
24
|
+
|
|
25
|
+
// src/cli.ts
|
|
26
|
+
var import_citty = require("citty");
|
|
27
|
+
|
|
28
|
+
// src/server.ts
|
|
29
|
+
var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
30
|
+
var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
31
|
+
var import_compiler = require("@pandacss/compiler");
|
|
32
|
+
var import_path = require("path");
|
|
33
|
+
var z = __toESM(require("zod/v4"));
|
|
34
|
+
var json = (data) => ({
|
|
35
|
+
content: [{ type: "text", text: JSON.stringify(data) }]
|
|
36
|
+
});
|
|
37
|
+
function createMcpServer(options) {
|
|
38
|
+
const { driver } = options;
|
|
39
|
+
const spec = driver.introspect.spec;
|
|
40
|
+
const theme = driver.config.theme ?? {};
|
|
41
|
+
const server = new import_mcp.McpServer({
|
|
42
|
+
name: "@pandacss/mcp",
|
|
43
|
+
version: "1.0.0"
|
|
44
|
+
});
|
|
45
|
+
const tokenCategories = Object.keys(spec.tokens.categories);
|
|
46
|
+
const recipeNames = driver.introspect.recipes();
|
|
47
|
+
const patternNames = driver.introspect.patterns();
|
|
48
|
+
const tokenCategorySchema = (tokenCategories.length ? z.enum(tokenCategories) : z.string()).optional().describe("Filter by token category");
|
|
49
|
+
const recipeNameSchema = recipeNames.length ? z.enum(recipeNames).optional().describe("Filter by recipe name") : z.string().optional().describe("Filter by recipe name");
|
|
50
|
+
const patternNameSchema = patternNames.length ? z.enum(patternNames).optional().describe("Filter by pattern name") : z.string().optional().describe("Filter by pattern name");
|
|
51
|
+
const pickCategory = (record, category) => category ? { [category]: record[category] } : record;
|
|
52
|
+
server.registerTool(
|
|
53
|
+
"get_tokens",
|
|
54
|
+
{
|
|
55
|
+
description: "Get all design tokens with their values, CSS variables, and usage examples",
|
|
56
|
+
inputSchema: { category: tokenCategorySchema }
|
|
57
|
+
},
|
|
58
|
+
async ({ category }) => {
|
|
59
|
+
const categories = category ? { [category]: spec.tokens.categories[category] } : spec.tokens.categories;
|
|
60
|
+
const values = category ? Object.fromEntries(Object.entries(spec.tokens.values).filter(([path]) => path.startsWith(`${category}.`))) : spec.tokens.values;
|
|
61
|
+
return json({ categories, values, deprecated: spec.tokens.deprecated });
|
|
62
|
+
}
|
|
63
|
+
);
|
|
64
|
+
server.registerTool(
|
|
65
|
+
"get_semantic_tokens",
|
|
66
|
+
{
|
|
67
|
+
description: "Get semantic tokens with their conditional values (responsive, color modes)",
|
|
68
|
+
inputSchema: { category: tokenCategorySchema }
|
|
69
|
+
},
|
|
70
|
+
async ({ category }) => {
|
|
71
|
+
const semanticTokens = theme.semanticTokens ?? {};
|
|
72
|
+
return json(pickCategory(semanticTokens, category));
|
|
73
|
+
}
|
|
74
|
+
);
|
|
75
|
+
server.registerTool(
|
|
76
|
+
"get_recipes",
|
|
77
|
+
{
|
|
78
|
+
description: "Get component recipes with their variants, default values, and usage examples",
|
|
79
|
+
inputSchema: { name: recipeNameSchema }
|
|
80
|
+
},
|
|
81
|
+
async ({ name }) => {
|
|
82
|
+
const { recipes, slotRecipes } = spec.recipes;
|
|
83
|
+
if (name) {
|
|
84
|
+
return json({
|
|
85
|
+
recipes: pickCategory(recipes, name in recipes ? name : void 0),
|
|
86
|
+
slotRecipes: pickCategory(slotRecipes, name in slotRecipes ? name : void 0)
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
return json({ recipes, slotRecipes });
|
|
90
|
+
}
|
|
91
|
+
);
|
|
92
|
+
server.registerTool(
|
|
93
|
+
"get_patterns",
|
|
94
|
+
{
|
|
95
|
+
description: "Get layout patterns with their properties and usage examples",
|
|
96
|
+
inputSchema: { name: patternNameSchema }
|
|
97
|
+
},
|
|
98
|
+
async ({ name }) => json(pickCategory(spec.patterns.patterns, name))
|
|
99
|
+
);
|
|
100
|
+
server.registerTool(
|
|
101
|
+
"get_conditions",
|
|
102
|
+
{ description: "Get all conditions (breakpoints, pseudo-classes, color modes) and their CSS values" },
|
|
103
|
+
async () => json({ ...spec.conditions, definitions: theme.conditions ?? driver.config.conditions ?? {} })
|
|
104
|
+
);
|
|
105
|
+
server.registerTool(
|
|
106
|
+
"get_keyframes",
|
|
107
|
+
{ description: "Get keyframe animations defined in the theme" },
|
|
108
|
+
async () => json(theme.keyframes ?? {})
|
|
109
|
+
);
|
|
110
|
+
server.registerTool(
|
|
111
|
+
"get_text_styles",
|
|
112
|
+
{ description: "Get text style compositions for typography" },
|
|
113
|
+
async () => json(theme.textStyles ?? {})
|
|
114
|
+
);
|
|
115
|
+
server.registerTool(
|
|
116
|
+
"get_layer_styles",
|
|
117
|
+
{ description: "Get layer style compositions for visual styling" },
|
|
118
|
+
async () => json(theme.layerStyles ?? {})
|
|
119
|
+
);
|
|
120
|
+
server.registerTool(
|
|
121
|
+
"get_animation_styles",
|
|
122
|
+
{ description: "Get animation style compositions" },
|
|
123
|
+
async () => json(theme.animationStyles ?? {})
|
|
124
|
+
);
|
|
125
|
+
server.registerTool(
|
|
126
|
+
"get_color_palette",
|
|
127
|
+
{ description: "Get the color palette with all color values" },
|
|
128
|
+
async () => json({
|
|
129
|
+
colorPalettes: spec.tokens.colorPalettes,
|
|
130
|
+
colors: Object.fromEntries(Object.entries(spec.tokens.values).filter(([path]) => path.startsWith("colors.")))
|
|
131
|
+
})
|
|
132
|
+
);
|
|
133
|
+
server.registerTool(
|
|
134
|
+
"get_config",
|
|
135
|
+
{ description: "Get the resolved Panda CSS configuration including paths, JSX settings, and output options" },
|
|
136
|
+
async () => json(driver.config)
|
|
137
|
+
);
|
|
138
|
+
return server;
|
|
139
|
+
}
|
|
140
|
+
async function startMcpServer(options = {}) {
|
|
141
|
+
const { cwd = process.cwd(), config: configPath, silent = false, transport } = options;
|
|
142
|
+
const resolvedCwd = (0, import_path.resolve)(cwd);
|
|
143
|
+
const resolvedConfigPath = configPath ? (0, import_path.resolve)(configPath) : void 0;
|
|
144
|
+
const driver = await (0, import_compiler.createNodeDriver)({
|
|
145
|
+
cwd: resolvedCwd,
|
|
146
|
+
configPath: resolvedConfigPath
|
|
147
|
+
});
|
|
148
|
+
const server = createMcpServer({ driver });
|
|
149
|
+
const serverTransport = transport ?? new import_stdio.StdioServerTransport();
|
|
150
|
+
if (!transport) {
|
|
151
|
+
exitOnDisconnect();
|
|
152
|
+
}
|
|
153
|
+
await server.connect(serverTransport);
|
|
154
|
+
if (!silent) {
|
|
155
|
+
console.error("Panda CSS MCP server started");
|
|
156
|
+
console.error(`Working directory: ${resolvedCwd}`);
|
|
157
|
+
if (resolvedConfigPath) {
|
|
158
|
+
console.error(`Config path: ${resolvedConfigPath}`);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return server;
|
|
162
|
+
}
|
|
163
|
+
function exitOnDisconnect(options = {}) {
|
|
164
|
+
const stdin = options.stdin ?? process.stdin;
|
|
165
|
+
const on = options.on ?? process.on.bind(process);
|
|
166
|
+
const exit = options.exit ?? ((code) => process.exit(code));
|
|
167
|
+
stdin.on("end", () => exit(0));
|
|
168
|
+
stdin.on("close", () => exit(0));
|
|
169
|
+
on("SIGINT", () => exit(0));
|
|
170
|
+
on("SIGTERM", () => exit(0));
|
|
171
|
+
on("SIGHUP", () => exit(0));
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// src/cli.ts
|
|
175
|
+
var mainCommand = (0, import_citty.defineCommand)({
|
|
176
|
+
meta: {
|
|
177
|
+
name: "panda-mcp",
|
|
178
|
+
description: "Panda CSS MCP server"
|
|
179
|
+
},
|
|
180
|
+
args: {
|
|
181
|
+
cwd: { type: "string", description: "Current working directory" },
|
|
182
|
+
config: { type: "string", description: "Path to panda config file", alias: "c" },
|
|
183
|
+
silent: { type: "boolean", description: "Suppress startup logs" }
|
|
184
|
+
},
|
|
185
|
+
run: async ({ args }) => {
|
|
186
|
+
await startMcpServer({ cwd: args.cwd, config: args.config, silent: args.silent });
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
(0, import_citty.runMain)(mainCommand).catch((error) => {
|
|
190
|
+
console.error(error instanceof Error ? error.message : error);
|
|
191
|
+
process.exitCode = 1;
|
|
192
|
+
});
|
package/dist/cli.mjs
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import {
|
|
2
|
+
startMcpServer
|
|
3
|
+
} from "./chunk-OBOPWZHX.mjs";
|
|
4
|
+
|
|
5
|
+
// src/cli.ts
|
|
6
|
+
import { defineCommand, runMain } from "citty";
|
|
7
|
+
var mainCommand = defineCommand({
|
|
8
|
+
meta: {
|
|
9
|
+
name: "panda-mcp",
|
|
10
|
+
description: "Panda CSS MCP server"
|
|
11
|
+
},
|
|
12
|
+
args: {
|
|
13
|
+
cwd: { type: "string", description: "Current working directory" },
|
|
14
|
+
config: { type: "string", description: "Path to panda config file", alias: "c" },
|
|
15
|
+
silent: { type: "boolean", description: "Suppress startup logs" }
|
|
16
|
+
},
|
|
17
|
+
run: async ({ args }) => {
|
|
18
|
+
await startMcpServer({ cwd: args.cwd, config: args.config, silent: args.silent });
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
runMain(mainCommand).catch((error) => {
|
|
22
|
+
console.error(error instanceof Error ? error.message : error);
|
|
23
|
+
process.exitCode = 1;
|
|
24
|
+
});
|
package/dist/index.js
CHANGED
|
@@ -30,9 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
-
MCP_CLIENTS: () => MCP_CLIENTS,
|
|
34
33
|
createMcpServer: () => createMcpServer,
|
|
35
|
-
initMcpConfig: () => initMcpConfig,
|
|
36
34
|
startMcpServer: () => startMcpServer
|
|
37
35
|
});
|
|
38
36
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -40,25 +38,27 @@ module.exports = __toCommonJS(index_exports);
|
|
|
40
38
|
// src/server.ts
|
|
41
39
|
var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
42
40
|
var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
43
|
-
var
|
|
44
|
-
var import_node = require("@pandacss/node");
|
|
45
|
-
var import_token_dictionary = require("@pandacss/token-dictionary");
|
|
41
|
+
var import_compiler = require("@pandacss/compiler");
|
|
46
42
|
var import_path = require("path");
|
|
47
43
|
var z = __toESM(require("zod/v4"));
|
|
48
|
-
var tokenCategorySchema = z.enum(import_token_dictionary.TOKEN_CATEGORIES).optional().describe("Filter by token category");
|
|
49
44
|
var json = (data) => ({
|
|
50
45
|
content: [{ type: "text", text: JSON.stringify(data) }]
|
|
51
46
|
});
|
|
52
47
|
function createMcpServer(options) {
|
|
53
|
-
const {
|
|
48
|
+
const { driver } = options;
|
|
49
|
+
const spec = driver.introspect.spec;
|
|
50
|
+
const theme = driver.config.theme ?? {};
|
|
54
51
|
const server = new import_mcp.McpServer({
|
|
55
52
|
name: "@pandacss/mcp",
|
|
56
53
|
version: "1.0.0"
|
|
57
54
|
});
|
|
58
|
-
const
|
|
59
|
-
const
|
|
55
|
+
const tokenCategories = Object.keys(spec.tokens.categories);
|
|
56
|
+
const recipeNames = driver.introspect.recipes();
|
|
57
|
+
const patternNames = driver.introspect.patterns();
|
|
58
|
+
const tokenCategorySchema = (tokenCategories.length ? z.enum(tokenCategories) : z.string()).optional().describe("Filter by token category");
|
|
60
59
|
const recipeNameSchema = recipeNames.length ? z.enum(recipeNames).optional().describe("Filter by recipe name") : z.string().optional().describe("Filter by recipe name");
|
|
61
60
|
const patternNameSchema = patternNames.length ? z.enum(patternNames).optional().describe("Filter by pattern name") : z.string().optional().describe("Filter by pattern name");
|
|
61
|
+
const pickCategory = (record, category) => category ? { [category]: record[category] } : record;
|
|
62
62
|
server.registerTool(
|
|
63
63
|
"get_tokens",
|
|
64
64
|
{
|
|
@@ -66,9 +66,9 @@ function createMcpServer(options) {
|
|
|
66
66
|
inputSchema: { category: tokenCategorySchema }
|
|
67
67
|
},
|
|
68
68
|
async ({ category }) => {
|
|
69
|
-
const
|
|
70
|
-
const
|
|
71
|
-
return json({
|
|
69
|
+
const categories = category ? { [category]: spec.tokens.categories[category] } : spec.tokens.categories;
|
|
70
|
+
const values = category ? Object.fromEntries(Object.entries(spec.tokens.values).filter(([path]) => path.startsWith(`${category}.`))) : spec.tokens.values;
|
|
71
|
+
return json({ categories, values, deprecated: spec.tokens.deprecated });
|
|
72
72
|
}
|
|
73
73
|
);
|
|
74
74
|
server.registerTool(
|
|
@@ -78,9 +78,8 @@ function createMcpServer(options) {
|
|
|
78
78
|
inputSchema: { category: tokenCategorySchema }
|
|
79
79
|
},
|
|
80
80
|
async ({ category }) => {
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
return json({ type: spec.type, data });
|
|
81
|
+
const semanticTokens = theme.semanticTokens ?? {};
|
|
82
|
+
return json(pickCategory(semanticTokens, category));
|
|
84
83
|
}
|
|
85
84
|
);
|
|
86
85
|
server.registerTool(
|
|
@@ -90,9 +89,14 @@ function createMcpServer(options) {
|
|
|
90
89
|
inputSchema: { name: recipeNameSchema }
|
|
91
90
|
},
|
|
92
91
|
async ({ name }) => {
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
|
|
92
|
+
const { recipes, slotRecipes } = spec.recipes;
|
|
93
|
+
if (name) {
|
|
94
|
+
return json({
|
|
95
|
+
recipes: pickCategory(recipes, name in recipes ? name : void 0),
|
|
96
|
+
slotRecipes: pickCategory(slotRecipes, name in slotRecipes ? name : void 0)
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
return json({ recipes, slotRecipes });
|
|
96
100
|
}
|
|
97
101
|
);
|
|
98
102
|
server.registerTool(
|
|
@@ -101,223 +105,83 @@ function createMcpServer(options) {
|
|
|
101
105
|
description: "Get layout patterns with their properties and usage examples",
|
|
102
106
|
inputSchema: { name: patternNameSchema }
|
|
103
107
|
},
|
|
104
|
-
async ({ name }) =>
|
|
105
|
-
const spec = ctx.getSpecOfType("patterns");
|
|
106
|
-
const data = name ? spec.data.filter((item) => item.name === name) : spec.data;
|
|
107
|
-
return json({ type: spec.type, data });
|
|
108
|
-
}
|
|
108
|
+
async ({ name }) => json(pickCategory(spec.patterns.patterns, name))
|
|
109
109
|
);
|
|
110
110
|
server.registerTool(
|
|
111
111
|
"get_conditions",
|
|
112
112
|
{ description: "Get all conditions (breakpoints, pseudo-classes, color modes) and their CSS values" },
|
|
113
|
-
async () => json(
|
|
113
|
+
async () => json({ ...spec.conditions, definitions: theme.conditions ?? driver.config.conditions ?? {} })
|
|
114
114
|
);
|
|
115
115
|
server.registerTool(
|
|
116
116
|
"get_keyframes",
|
|
117
117
|
{ description: "Get keyframe animations defined in the theme" },
|
|
118
|
-
async () => json(
|
|
118
|
+
async () => json(theme.keyframes ?? {})
|
|
119
119
|
);
|
|
120
120
|
server.registerTool(
|
|
121
121
|
"get_text_styles",
|
|
122
122
|
{ description: "Get text style compositions for typography" },
|
|
123
|
-
async () => json(
|
|
123
|
+
async () => json(theme.textStyles ?? {})
|
|
124
124
|
);
|
|
125
125
|
server.registerTool(
|
|
126
126
|
"get_layer_styles",
|
|
127
127
|
{ description: "Get layer style compositions for visual styling" },
|
|
128
|
-
async () => json(
|
|
128
|
+
async () => json(theme.layerStyles ?? {})
|
|
129
129
|
);
|
|
130
130
|
server.registerTool(
|
|
131
131
|
"get_animation_styles",
|
|
132
132
|
{ description: "Get animation style compositions" },
|
|
133
|
-
async () => json(
|
|
133
|
+
async () => json(theme.animationStyles ?? {})
|
|
134
134
|
);
|
|
135
135
|
server.registerTool(
|
|
136
136
|
"get_color_palette",
|
|
137
137
|
{ description: "Get the color palette with all color values" },
|
|
138
|
-
async () => json(
|
|
138
|
+
async () => json({
|
|
139
|
+
colorPalettes: spec.tokens.colorPalettes,
|
|
140
|
+
colors: Object.fromEntries(Object.entries(spec.tokens.values).filter(([path]) => path.startsWith("colors.")))
|
|
141
|
+
})
|
|
139
142
|
);
|
|
140
143
|
server.registerTool(
|
|
141
144
|
"get_config",
|
|
142
145
|
{ description: "Get the resolved Panda CSS configuration including paths, JSX settings, and output options" },
|
|
143
|
-
async () => json(
|
|
144
|
-
);
|
|
145
|
-
server.registerTool(
|
|
146
|
-
"get_usage_report",
|
|
147
|
-
{
|
|
148
|
-
description: "Get a usage report of design tokens and recipes across the codebase. Shows which tokens/recipes are used, unused, or missing. Useful for auditing, cleanup, and identifying dead code.",
|
|
149
|
-
inputSchema: {
|
|
150
|
-
scope: z.enum(["all", "token", "recipe"]).optional().describe("Analysis scope: token, recipe, or all (default)")
|
|
151
|
-
}
|
|
152
|
-
},
|
|
153
|
-
async ({ scope }) => {
|
|
154
|
-
const result = (0, import_node.analyze)(ctx);
|
|
155
|
-
const includeTokens = !scope || scope === "all" || scope === "token";
|
|
156
|
-
const includeRecipes = !scope || scope === "all" || scope === "recipe";
|
|
157
|
-
const report = {};
|
|
158
|
-
if (includeTokens && !ctx.tokens.isEmpty) {
|
|
159
|
-
const tokenReport = result.getTokenReport();
|
|
160
|
-
report.tokens = tokenReport.report.getSummary();
|
|
161
|
-
}
|
|
162
|
-
if (includeRecipes && !ctx.recipes.isEmpty()) {
|
|
163
|
-
const recipeReport = result.getRecipeReport();
|
|
164
|
-
report.recipes = recipeReport.report;
|
|
165
|
-
}
|
|
166
|
-
return json(report);
|
|
167
|
-
}
|
|
146
|
+
async () => json(driver.config)
|
|
168
147
|
);
|
|
169
148
|
return server;
|
|
170
149
|
}
|
|
171
150
|
async function startMcpServer(options = {}) {
|
|
172
151
|
const { cwd = process.cwd(), config: configPath, silent = false, transport } = options;
|
|
173
|
-
if (silent) {
|
|
174
|
-
import_logger.logger.level = "silent";
|
|
175
|
-
}
|
|
176
152
|
const resolvedCwd = (0, import_path.resolve)(cwd);
|
|
177
153
|
const resolvedConfigPath = configPath ? (0, import_path.resolve)(configPath) : void 0;
|
|
178
|
-
const
|
|
154
|
+
const driver = await (0, import_compiler.createNodeDriver)({
|
|
179
155
|
cwd: resolvedCwd,
|
|
180
156
|
configPath: resolvedConfigPath
|
|
181
157
|
});
|
|
182
|
-
const server = createMcpServer({
|
|
158
|
+
const server = createMcpServer({ driver });
|
|
183
159
|
const serverTransport = transport ?? new import_stdio.StdioServerTransport();
|
|
160
|
+
if (!transport) {
|
|
161
|
+
exitOnDisconnect();
|
|
162
|
+
}
|
|
184
163
|
await server.connect(serverTransport);
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
164
|
+
if (!silent) {
|
|
165
|
+
console.error("Panda CSS MCP server started");
|
|
166
|
+
console.error(`Working directory: ${resolvedCwd}`);
|
|
167
|
+
if (resolvedConfigPath) {
|
|
168
|
+
console.error(`Config path: ${resolvedConfigPath}`);
|
|
169
|
+
}
|
|
189
170
|
}
|
|
190
171
|
return server;
|
|
191
172
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
claude: {
|
|
202
|
-
name: "claude",
|
|
203
|
-
label: "Claude (.mcp.json)",
|
|
204
|
-
configPath: ".mcp.json",
|
|
205
|
-
configKey: "mcpServers"
|
|
206
|
-
},
|
|
207
|
-
cursor: {
|
|
208
|
-
name: "cursor",
|
|
209
|
-
label: "Cursor (.cursor/mcp.json)",
|
|
210
|
-
configPath: ".cursor/mcp.json",
|
|
211
|
-
configKey: "mcpServers"
|
|
212
|
-
},
|
|
213
|
-
vscode: {
|
|
214
|
-
name: "vscode",
|
|
215
|
-
label: "VS Code (.vscode/mcp.json)",
|
|
216
|
-
configPath: ".vscode/mcp.json",
|
|
217
|
-
configKey: "servers"
|
|
218
|
-
},
|
|
219
|
-
windsurf: {
|
|
220
|
-
name: "windsurf",
|
|
221
|
-
label: "Windsurf (.windsurf/mcp.json)",
|
|
222
|
-
configPath: ".windsurf/mcp.json",
|
|
223
|
-
configKey: "mcpServers"
|
|
224
|
-
},
|
|
225
|
-
codex: {
|
|
226
|
-
name: "codex",
|
|
227
|
-
label: "Codex (.codex/mcp.json)",
|
|
228
|
-
configPath: ".codex/mcp.json",
|
|
229
|
-
configKey: "mcpServers"
|
|
230
|
-
}
|
|
231
|
-
};
|
|
232
|
-
var CLIENT_NAMES = Object.keys(MCP_CLIENTS);
|
|
233
|
-
function isValidClient(client) {
|
|
234
|
-
return CLIENT_NAMES.includes(client);
|
|
235
|
-
}
|
|
236
|
-
function getClientConfig(client) {
|
|
237
|
-
return MCP_CLIENTS[client];
|
|
238
|
-
}
|
|
239
|
-
function generateMcpConfig(clientConfig) {
|
|
240
|
-
const serverConfig = {
|
|
241
|
-
command: "npx",
|
|
242
|
-
args: ["panda", "mcp"]
|
|
243
|
-
};
|
|
244
|
-
return {
|
|
245
|
-
[clientConfig.configKey]: {
|
|
246
|
-
panda: serverConfig
|
|
247
|
-
}
|
|
248
|
-
};
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
// src/init.ts
|
|
252
|
-
async function initMcpConfig(options = {}) {
|
|
253
|
-
const { cwd = process.cwd() } = options;
|
|
254
|
-
let { clients } = options;
|
|
255
|
-
p.intro("Panda MCP Setup");
|
|
256
|
-
if (!clients || clients.length === 0) {
|
|
257
|
-
const selected = await p.multiselect({
|
|
258
|
-
message: "Select AI clients to configure:",
|
|
259
|
-
options: CLIENT_NAMES.map((client) => ({
|
|
260
|
-
value: client,
|
|
261
|
-
label: MCP_CLIENTS[client].label
|
|
262
|
-
})),
|
|
263
|
-
required: true
|
|
264
|
-
});
|
|
265
|
-
if (p.isCancel(selected)) {
|
|
266
|
-
p.cancel("Setup cancelled.");
|
|
267
|
-
process.exit(0);
|
|
268
|
-
}
|
|
269
|
-
clients = selected;
|
|
270
|
-
}
|
|
271
|
-
const validClients = clients.filter((client) => {
|
|
272
|
-
if (!isValidClient(client)) {
|
|
273
|
-
import_logger2.logger.warn("mcp:init", `Unknown client: ${client}`);
|
|
274
|
-
return false;
|
|
275
|
-
}
|
|
276
|
-
return true;
|
|
277
|
-
});
|
|
278
|
-
if (validClients.length === 0) {
|
|
279
|
-
p.cancel("No valid clients selected.");
|
|
280
|
-
process.exit(1);
|
|
281
|
-
}
|
|
282
|
-
const results = [];
|
|
283
|
-
for (const client of validClients) {
|
|
284
|
-
const clientConfig = getClientConfig(client);
|
|
285
|
-
const configPath = (0, import_path2.resolve)(cwd, clientConfig.configPath);
|
|
286
|
-
const configDir = (0, import_path2.dirname)(configPath);
|
|
287
|
-
if (!(0, import_fs.existsSync)(configDir)) {
|
|
288
|
-
(0, import_fs.mkdirSync)(configDir, { recursive: true });
|
|
289
|
-
}
|
|
290
|
-
const newConfig = generateMcpConfig(clientConfig);
|
|
291
|
-
let finalConfig = newConfig;
|
|
292
|
-
if ((0, import_fs.existsSync)(configPath)) {
|
|
293
|
-
try {
|
|
294
|
-
const existingContent = (0, import_fs.readFileSync)(configPath, "utf-8");
|
|
295
|
-
const existingConfig = JSON.parse(existingContent);
|
|
296
|
-
finalConfig = {
|
|
297
|
-
...existingConfig,
|
|
298
|
-
[clientConfig.configKey]: {
|
|
299
|
-
...existingConfig[clientConfig.configKey],
|
|
300
|
-
...newConfig[clientConfig.configKey]
|
|
301
|
-
}
|
|
302
|
-
};
|
|
303
|
-
} catch {
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
(0, import_fs.writeFileSync)(configPath, JSON.stringify(finalConfig, null, 2));
|
|
307
|
-
results.push({
|
|
308
|
-
client,
|
|
309
|
-
path: clientConfig.configPath,
|
|
310
|
-
created: true
|
|
311
|
-
});
|
|
312
|
-
}
|
|
313
|
-
p.note(results.map((r) => `${r.client}: ${r.path}`).join("\n"), "Created MCP configurations");
|
|
314
|
-
p.outro("MCP setup complete! Your AI assistants can now use Panda CSS tools.");
|
|
315
|
-
return results;
|
|
173
|
+
function exitOnDisconnect(options = {}) {
|
|
174
|
+
const stdin = options.stdin ?? process.stdin;
|
|
175
|
+
const on = options.on ?? process.on.bind(process);
|
|
176
|
+
const exit = options.exit ?? ((code) => process.exit(code));
|
|
177
|
+
stdin.on("end", () => exit(0));
|
|
178
|
+
stdin.on("close", () => exit(0));
|
|
179
|
+
on("SIGINT", () => exit(0));
|
|
180
|
+
on("SIGTERM", () => exit(0));
|
|
181
|
+
on("SIGHUP", () => exit(0));
|
|
316
182
|
}
|
|
317
183
|
// Annotate the CommonJS export names for ESM import in node:
|
|
318
184
|
0 && (module.exports = {
|
|
319
|
-
MCP_CLIENTS,
|
|
320
185
|
createMcpServer,
|
|
321
|
-
initMcpConfig,
|
|
322
186
|
startMcpServer
|
|
323
187
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -1,283 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import { analyze, loadConfigAndCreateContext } from "@pandacss/node";
|
|
6
|
-
import { TOKEN_CATEGORIES } from "@pandacss/token-dictionary";
|
|
7
|
-
import { resolve } from "path";
|
|
8
|
-
import * as z from "zod/v4";
|
|
9
|
-
var tokenCategorySchema = z.enum(TOKEN_CATEGORIES).optional().describe("Filter by token category");
|
|
10
|
-
var json = (data) => ({
|
|
11
|
-
content: [{ type: "text", text: JSON.stringify(data) }]
|
|
12
|
-
});
|
|
13
|
-
function createMcpServer(options) {
|
|
14
|
-
const { ctx } = options;
|
|
15
|
-
const server = new McpServer({
|
|
16
|
-
name: "@pandacss/mcp",
|
|
17
|
-
version: "1.0.0"
|
|
18
|
-
});
|
|
19
|
-
const recipeNames = ctx.recipes.keys;
|
|
20
|
-
const patternNames = ctx.patterns.keys;
|
|
21
|
-
const recipeNameSchema = recipeNames.length ? z.enum(recipeNames).optional().describe("Filter by recipe name") : z.string().optional().describe("Filter by recipe name");
|
|
22
|
-
const patternNameSchema = patternNames.length ? z.enum(patternNames).optional().describe("Filter by pattern name") : z.string().optional().describe("Filter by pattern name");
|
|
23
|
-
server.registerTool(
|
|
24
|
-
"get_tokens",
|
|
25
|
-
{
|
|
26
|
-
description: "Get all design tokens with their values, CSS variables, and usage examples",
|
|
27
|
-
inputSchema: { category: tokenCategorySchema }
|
|
28
|
-
},
|
|
29
|
-
async ({ category }) => {
|
|
30
|
-
const spec = ctx.getSpecOfType("tokens");
|
|
31
|
-
const data = category ? spec.data.filter((group) => group.type === category) : spec.data;
|
|
32
|
-
return json({ type: spec.type, data });
|
|
33
|
-
}
|
|
34
|
-
);
|
|
35
|
-
server.registerTool(
|
|
36
|
-
"get_semantic_tokens",
|
|
37
|
-
{
|
|
38
|
-
description: "Get semantic tokens with their conditional values (responsive, color modes)",
|
|
39
|
-
inputSchema: { category: tokenCategorySchema }
|
|
40
|
-
},
|
|
41
|
-
async ({ category }) => {
|
|
42
|
-
const spec = ctx.getSpecOfType("semantic-tokens");
|
|
43
|
-
const data = category ? spec.data.filter((group) => group.type === category) : spec.data;
|
|
44
|
-
return json({ type: spec.type, data });
|
|
45
|
-
}
|
|
46
|
-
);
|
|
47
|
-
server.registerTool(
|
|
48
|
-
"get_recipes",
|
|
49
|
-
{
|
|
50
|
-
description: "Get component recipes with their variants, default values, and usage examples",
|
|
51
|
-
inputSchema: { name: recipeNameSchema }
|
|
52
|
-
},
|
|
53
|
-
async ({ name }) => {
|
|
54
|
-
const spec = ctx.getSpecOfType("recipes");
|
|
55
|
-
const data = name ? spec.data.filter((item) => item.name === name) : spec.data;
|
|
56
|
-
return json({ type: spec.type, data });
|
|
57
|
-
}
|
|
58
|
-
);
|
|
59
|
-
server.registerTool(
|
|
60
|
-
"get_patterns",
|
|
61
|
-
{
|
|
62
|
-
description: "Get layout patterns with their properties and usage examples",
|
|
63
|
-
inputSchema: { name: patternNameSchema }
|
|
64
|
-
},
|
|
65
|
-
async ({ name }) => {
|
|
66
|
-
const spec = ctx.getSpecOfType("patterns");
|
|
67
|
-
const data = name ? spec.data.filter((item) => item.name === name) : spec.data;
|
|
68
|
-
return json({ type: spec.type, data });
|
|
69
|
-
}
|
|
70
|
-
);
|
|
71
|
-
server.registerTool(
|
|
72
|
-
"get_conditions",
|
|
73
|
-
{ description: "Get all conditions (breakpoints, pseudo-classes, color modes) and their CSS values" },
|
|
74
|
-
async () => json(ctx.getSpecOfType("conditions"))
|
|
75
|
-
);
|
|
76
|
-
server.registerTool(
|
|
77
|
-
"get_keyframes",
|
|
78
|
-
{ description: "Get keyframe animations defined in the theme" },
|
|
79
|
-
async () => json(ctx.getSpecOfType("keyframes"))
|
|
80
|
-
);
|
|
81
|
-
server.registerTool(
|
|
82
|
-
"get_text_styles",
|
|
83
|
-
{ description: "Get text style compositions for typography" },
|
|
84
|
-
async () => json(ctx.getSpecOfType("text-styles"))
|
|
85
|
-
);
|
|
86
|
-
server.registerTool(
|
|
87
|
-
"get_layer_styles",
|
|
88
|
-
{ description: "Get layer style compositions for visual styling" },
|
|
89
|
-
async () => json(ctx.getSpecOfType("layer-styles"))
|
|
90
|
-
);
|
|
91
|
-
server.registerTool(
|
|
92
|
-
"get_animation_styles",
|
|
93
|
-
{ description: "Get animation style compositions" },
|
|
94
|
-
async () => json(ctx.getSpecOfType("animation-styles"))
|
|
95
|
-
);
|
|
96
|
-
server.registerTool(
|
|
97
|
-
"get_color_palette",
|
|
98
|
-
{ description: "Get the color palette with all color values" },
|
|
99
|
-
async () => json(ctx.getSpecOfType("color-palette"))
|
|
100
|
-
);
|
|
101
|
-
server.registerTool(
|
|
102
|
-
"get_config",
|
|
103
|
-
{ description: "Get the resolved Panda CSS configuration including paths, JSX settings, and output options" },
|
|
104
|
-
async () => json(ctx.config)
|
|
105
|
-
);
|
|
106
|
-
server.registerTool(
|
|
107
|
-
"get_usage_report",
|
|
108
|
-
{
|
|
109
|
-
description: "Get a usage report of design tokens and recipes across the codebase. Shows which tokens/recipes are used, unused, or missing. Useful for auditing, cleanup, and identifying dead code.",
|
|
110
|
-
inputSchema: {
|
|
111
|
-
scope: z.enum(["all", "token", "recipe"]).optional().describe("Analysis scope: token, recipe, or all (default)")
|
|
112
|
-
}
|
|
113
|
-
},
|
|
114
|
-
async ({ scope }) => {
|
|
115
|
-
const result = analyze(ctx);
|
|
116
|
-
const includeTokens = !scope || scope === "all" || scope === "token";
|
|
117
|
-
const includeRecipes = !scope || scope === "all" || scope === "recipe";
|
|
118
|
-
const report = {};
|
|
119
|
-
if (includeTokens && !ctx.tokens.isEmpty) {
|
|
120
|
-
const tokenReport = result.getTokenReport();
|
|
121
|
-
report.tokens = tokenReport.report.getSummary();
|
|
122
|
-
}
|
|
123
|
-
if (includeRecipes && !ctx.recipes.isEmpty()) {
|
|
124
|
-
const recipeReport = result.getRecipeReport();
|
|
125
|
-
report.recipes = recipeReport.report;
|
|
126
|
-
}
|
|
127
|
-
return json(report);
|
|
128
|
-
}
|
|
129
|
-
);
|
|
130
|
-
return server;
|
|
131
|
-
}
|
|
132
|
-
async function startMcpServer(options = {}) {
|
|
133
|
-
const { cwd = process.cwd(), config: configPath, silent = false, transport } = options;
|
|
134
|
-
if (silent) {
|
|
135
|
-
logger.level = "silent";
|
|
136
|
-
}
|
|
137
|
-
const resolvedCwd = resolve(cwd);
|
|
138
|
-
const resolvedConfigPath = configPath ? resolve(configPath) : void 0;
|
|
139
|
-
const ctx = await loadConfigAndCreateContext({
|
|
140
|
-
cwd: resolvedCwd,
|
|
141
|
-
configPath: resolvedConfigPath
|
|
142
|
-
});
|
|
143
|
-
const server = createMcpServer({ ctx });
|
|
144
|
-
const serverTransport = transport ?? new StdioServerTransport();
|
|
145
|
-
await server.connect(serverTransport);
|
|
146
|
-
console.error("Panda CSS MCP server started");
|
|
147
|
-
console.error(`Working directory: ${resolvedCwd}`);
|
|
148
|
-
if (resolvedConfigPath) {
|
|
149
|
-
console.error(`Config path: ${resolvedConfigPath}`);
|
|
150
|
-
}
|
|
151
|
-
return server;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// src/init.ts
|
|
155
|
-
import * as p from "@clack/prompts";
|
|
156
|
-
import { logger as logger2 } from "@pandacss/logger";
|
|
157
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
158
|
-
import { dirname, resolve as resolve2 } from "path";
|
|
159
|
-
|
|
160
|
-
// src/clients.ts
|
|
161
|
-
var MCP_CLIENTS = {
|
|
162
|
-
claude: {
|
|
163
|
-
name: "claude",
|
|
164
|
-
label: "Claude (.mcp.json)",
|
|
165
|
-
configPath: ".mcp.json",
|
|
166
|
-
configKey: "mcpServers"
|
|
167
|
-
},
|
|
168
|
-
cursor: {
|
|
169
|
-
name: "cursor",
|
|
170
|
-
label: "Cursor (.cursor/mcp.json)",
|
|
171
|
-
configPath: ".cursor/mcp.json",
|
|
172
|
-
configKey: "mcpServers"
|
|
173
|
-
},
|
|
174
|
-
vscode: {
|
|
175
|
-
name: "vscode",
|
|
176
|
-
label: "VS Code (.vscode/mcp.json)",
|
|
177
|
-
configPath: ".vscode/mcp.json",
|
|
178
|
-
configKey: "servers"
|
|
179
|
-
},
|
|
180
|
-
windsurf: {
|
|
181
|
-
name: "windsurf",
|
|
182
|
-
label: "Windsurf (.windsurf/mcp.json)",
|
|
183
|
-
configPath: ".windsurf/mcp.json",
|
|
184
|
-
configKey: "mcpServers"
|
|
185
|
-
},
|
|
186
|
-
codex: {
|
|
187
|
-
name: "codex",
|
|
188
|
-
label: "Codex (.codex/mcp.json)",
|
|
189
|
-
configPath: ".codex/mcp.json",
|
|
190
|
-
configKey: "mcpServers"
|
|
191
|
-
}
|
|
192
|
-
};
|
|
193
|
-
var CLIENT_NAMES = Object.keys(MCP_CLIENTS);
|
|
194
|
-
function isValidClient(client) {
|
|
195
|
-
return CLIENT_NAMES.includes(client);
|
|
196
|
-
}
|
|
197
|
-
function getClientConfig(client) {
|
|
198
|
-
return MCP_CLIENTS[client];
|
|
199
|
-
}
|
|
200
|
-
function generateMcpConfig(clientConfig) {
|
|
201
|
-
const serverConfig = {
|
|
202
|
-
command: "npx",
|
|
203
|
-
args: ["panda", "mcp"]
|
|
204
|
-
};
|
|
205
|
-
return {
|
|
206
|
-
[clientConfig.configKey]: {
|
|
207
|
-
panda: serverConfig
|
|
208
|
-
}
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
// src/init.ts
|
|
213
|
-
async function initMcpConfig(options = {}) {
|
|
214
|
-
const { cwd = process.cwd() } = options;
|
|
215
|
-
let { clients } = options;
|
|
216
|
-
p.intro("Panda MCP Setup");
|
|
217
|
-
if (!clients || clients.length === 0) {
|
|
218
|
-
const selected = await p.multiselect({
|
|
219
|
-
message: "Select AI clients to configure:",
|
|
220
|
-
options: CLIENT_NAMES.map((client) => ({
|
|
221
|
-
value: client,
|
|
222
|
-
label: MCP_CLIENTS[client].label
|
|
223
|
-
})),
|
|
224
|
-
required: true
|
|
225
|
-
});
|
|
226
|
-
if (p.isCancel(selected)) {
|
|
227
|
-
p.cancel("Setup cancelled.");
|
|
228
|
-
process.exit(0);
|
|
229
|
-
}
|
|
230
|
-
clients = selected;
|
|
231
|
-
}
|
|
232
|
-
const validClients = clients.filter((client) => {
|
|
233
|
-
if (!isValidClient(client)) {
|
|
234
|
-
logger2.warn("mcp:init", `Unknown client: ${client}`);
|
|
235
|
-
return false;
|
|
236
|
-
}
|
|
237
|
-
return true;
|
|
238
|
-
});
|
|
239
|
-
if (validClients.length === 0) {
|
|
240
|
-
p.cancel("No valid clients selected.");
|
|
241
|
-
process.exit(1);
|
|
242
|
-
}
|
|
243
|
-
const results = [];
|
|
244
|
-
for (const client of validClients) {
|
|
245
|
-
const clientConfig = getClientConfig(client);
|
|
246
|
-
const configPath = resolve2(cwd, clientConfig.configPath);
|
|
247
|
-
const configDir = dirname(configPath);
|
|
248
|
-
if (!existsSync(configDir)) {
|
|
249
|
-
mkdirSync(configDir, { recursive: true });
|
|
250
|
-
}
|
|
251
|
-
const newConfig = generateMcpConfig(clientConfig);
|
|
252
|
-
let finalConfig = newConfig;
|
|
253
|
-
if (existsSync(configPath)) {
|
|
254
|
-
try {
|
|
255
|
-
const existingContent = readFileSync(configPath, "utf-8");
|
|
256
|
-
const existingConfig = JSON.parse(existingContent);
|
|
257
|
-
finalConfig = {
|
|
258
|
-
...existingConfig,
|
|
259
|
-
[clientConfig.configKey]: {
|
|
260
|
-
...existingConfig[clientConfig.configKey],
|
|
261
|
-
...newConfig[clientConfig.configKey]
|
|
262
|
-
}
|
|
263
|
-
};
|
|
264
|
-
} catch {
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
writeFileSync(configPath, JSON.stringify(finalConfig, null, 2));
|
|
268
|
-
results.push({
|
|
269
|
-
client,
|
|
270
|
-
path: clientConfig.configPath,
|
|
271
|
-
created: true
|
|
272
|
-
});
|
|
273
|
-
}
|
|
274
|
-
p.note(results.map((r) => `${r.client}: ${r.path}`).join("\n"), "Created MCP configurations");
|
|
275
|
-
p.outro("MCP setup complete! Your AI assistants can now use Panda CSS tools.");
|
|
276
|
-
return results;
|
|
277
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
createMcpServer,
|
|
3
|
+
startMcpServer
|
|
4
|
+
} from "./chunk-OBOPWZHX.mjs";
|
|
278
5
|
export {
|
|
279
|
-
MCP_CLIENTS,
|
|
280
6
|
createMcpServer,
|
|
281
|
-
initMcpConfig,
|
|
282
7
|
startMcpServer
|
|
283
8
|
};
|
package/package.json
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pandacss/mcp",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0-beta.0",
|
|
4
4
|
"description": "MCP server for Panda CSS AI assistants",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"panda-mcp": "bin.js"
|
|
10
|
+
},
|
|
8
11
|
"author": "Segun Adebayo <joseshegs@gmail.com>",
|
|
9
12
|
"license": "MIT",
|
|
10
13
|
"exports": {
|
|
@@ -30,20 +33,18 @@
|
|
|
30
33
|
"access": "public"
|
|
31
34
|
},
|
|
32
35
|
"files": [
|
|
33
|
-
"dist"
|
|
36
|
+
"dist",
|
|
37
|
+
"bin.js"
|
|
34
38
|
],
|
|
35
39
|
"dependencies": {
|
|
36
|
-
"@clack/prompts": "0.11.0",
|
|
37
40
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
41
|
+
"citty": "0.1.6",
|
|
38
42
|
"zod": "^4.0.0",
|
|
39
|
-
"@pandacss/
|
|
40
|
-
"@pandacss/node": "1.11.2",
|
|
41
|
-
"@pandacss/token-dictionary": "1.11.2",
|
|
42
|
-
"@pandacss/types": "1.11.2"
|
|
43
|
+
"@pandacss/compiler": "2.0.0-beta.0"
|
|
43
44
|
},
|
|
44
45
|
"scripts": {
|
|
45
|
-
"build": "tsup src/index.ts --format=esm,cjs",
|
|
46
|
-
"build
|
|
47
|
-
"dev": "pnpm build
|
|
46
|
+
"build": "tsup src/index.ts src/cli.ts --format=esm,cjs",
|
|
47
|
+
"build:fast": "tsup src/index.ts src/cli.ts --format=esm,cjs",
|
|
48
|
+
"dev": "pnpm build:fast --watch"
|
|
48
49
|
}
|
|
49
50
|
}
|