@pandacss/mcp 1.11.3 → 2.0.0-beta.1

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2023 Segun Adebayo
3
+ Copyright (c) 2023 Chakra Systems Inc.
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
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,3 @@
1
+ #!/usr/bin/env node
2
+
3
+ require('./dist/cli.js')
@@ -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 import_logger = require("@pandacss/logger");
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 { ctx } = options;
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 recipeNames = ctx.recipes.keys;
59
- const patternNames = ctx.patterns.keys;
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 spec = ctx.getSpecOfType("tokens");
70
- const data = category ? spec.data.filter((group) => group.type === category) : spec.data;
71
- return json({ type: spec.type, data });
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 spec = ctx.getSpecOfType("semantic-tokens");
82
- const data = category ? spec.data.filter((group) => group.type === category) : spec.data;
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 spec = ctx.getSpecOfType("recipes");
94
- const data = name ? spec.data.filter((item) => item.name === name) : spec.data;
95
- return json({ type: spec.type, data });
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,260 +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(ctx.getSpecOfType("conditions"))
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(ctx.getSpecOfType("keyframes"))
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(ctx.getSpecOfType("text-styles"))
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(ctx.getSpecOfType("layer-styles"))
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(ctx.getSpecOfType("animation-styles"))
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(ctx.getSpecOfType("color-palette"))
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(ctx.config)
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 ctx = await (0, import_node.loadConfigAndCreateContext)({
154
+ const driver = await (0, import_compiler.createNodeDriver)({
179
155
  cwd: resolvedCwd,
180
156
  configPath: resolvedConfigPath
181
157
  });
182
- const server = createMcpServer({ ctx });
158
+ const server = createMcpServer({ driver });
183
159
  const serverTransport = transport ?? new import_stdio.StdioServerTransport();
184
- await server.connect(serverTransport);
185
160
  if (!transport) {
186
- watchProcessLifecycle(server);
161
+ exitOnDisconnect();
187
162
  }
188
- console.error("Panda CSS MCP server started");
189
- console.error(`Working directory: ${resolvedCwd}`);
190
- if (resolvedConfigPath) {
191
- console.error(`Config path: ${resolvedConfigPath}`);
163
+ await server.connect(serverTransport);
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
+ }
192
170
  }
193
171
  return server;
194
172
  }
195
- function watchProcessLifecycle(server, options = {}) {
196
- const proc = options.process ?? process;
173
+ function exitOnDisconnect(options = {}) {
174
+ const stdin = options.stdin ?? process.stdin;
175
+ const on = options.on ?? process.on.bind(process);
197
176
  const exit = options.exit ?? ((code) => process.exit(code));
198
- let exiting = false;
199
- const shutdown = (code) => {
200
- if (exiting) return;
201
- exiting = true;
202
- void Promise.resolve(server.close()).catch(() => void 0);
203
- exit(code);
204
- };
205
- proc.stdin.on("end", () => shutdown(0));
206
- proc.stdin.on("close", () => shutdown(0));
207
- proc.on("SIGINT", () => shutdown(0));
208
- proc.on("SIGTERM", () => shutdown(0));
209
- for (const stream of [proc.stdout, proc.stderr]) {
210
- stream.on("error", (err) => {
211
- if (err?.code === "EPIPE") shutdown(0);
212
- });
213
- }
214
- const onFatal = (label) => (err) => {
215
- try {
216
- proc.stderr.write(`[panda mcp] ${label}, exiting: ${formatError(err)}
217
- `);
218
- } catch {
219
- }
220
- shutdown(1);
221
- };
222
- proc.on("uncaughtException", onFatal("uncaught exception"));
223
- proc.on("unhandledRejection", onFatal("unhandled rejection"));
224
- return shutdown;
225
- }
226
- function formatError(err) {
227
- return err instanceof Error ? err.stack ?? err.message : String(err);
228
- }
229
-
230
- // src/init.ts
231
- var p = __toESM(require("@clack/prompts"));
232
- var import_logger2 = require("@pandacss/logger");
233
- var import_fs = require("fs");
234
- var import_path2 = require("path");
235
-
236
- // src/clients.ts
237
- var MCP_CLIENTS = {
238
- claude: {
239
- name: "claude",
240
- label: "Claude (.mcp.json)",
241
- configPath: ".mcp.json",
242
- configKey: "mcpServers"
243
- },
244
- cursor: {
245
- name: "cursor",
246
- label: "Cursor (.cursor/mcp.json)",
247
- configPath: ".cursor/mcp.json",
248
- configKey: "mcpServers"
249
- },
250
- vscode: {
251
- name: "vscode",
252
- label: "VS Code (.vscode/mcp.json)",
253
- configPath: ".vscode/mcp.json",
254
- configKey: "servers"
255
- },
256
- windsurf: {
257
- name: "windsurf",
258
- label: "Windsurf (.windsurf/mcp.json)",
259
- configPath: ".windsurf/mcp.json",
260
- configKey: "mcpServers"
261
- },
262
- codex: {
263
- name: "codex",
264
- label: "Codex (.codex/mcp.json)",
265
- configPath: ".codex/mcp.json",
266
- configKey: "mcpServers"
267
- }
268
- };
269
- var CLIENT_NAMES = Object.keys(MCP_CLIENTS);
270
- function isValidClient(client) {
271
- return CLIENT_NAMES.includes(client);
272
- }
273
- function getClientConfig(client) {
274
- return MCP_CLIENTS[client];
275
- }
276
- function generateMcpConfig(clientConfig) {
277
- const serverConfig = {
278
- command: "npx",
279
- args: ["panda", "mcp"]
280
- };
281
- return {
282
- [clientConfig.configKey]: {
283
- panda: serverConfig
284
- }
285
- };
286
- }
287
-
288
- // src/init.ts
289
- async function initMcpConfig(options = {}) {
290
- const { cwd = process.cwd() } = options;
291
- let { clients } = options;
292
- p.intro("Panda MCP Setup");
293
- if (!clients || clients.length === 0) {
294
- const selected = await p.multiselect({
295
- message: "Select AI clients to configure:",
296
- options: CLIENT_NAMES.map((client) => ({
297
- value: client,
298
- label: MCP_CLIENTS[client].label
299
- })),
300
- required: true
301
- });
302
- if (p.isCancel(selected)) {
303
- p.cancel("Setup cancelled.");
304
- process.exit(0);
305
- }
306
- clients = selected;
307
- }
308
- const validClients = clients.filter((client) => {
309
- if (!isValidClient(client)) {
310
- import_logger2.logger.warn("mcp:init", `Unknown client: ${client}`);
311
- return false;
312
- }
313
- return true;
314
- });
315
- if (validClients.length === 0) {
316
- p.cancel("No valid clients selected.");
317
- process.exit(1);
318
- }
319
- const results = [];
320
- for (const client of validClients) {
321
- const clientConfig = getClientConfig(client);
322
- const configPath = (0, import_path2.resolve)(cwd, clientConfig.configPath);
323
- const configDir = (0, import_path2.dirname)(configPath);
324
- if (!(0, import_fs.existsSync)(configDir)) {
325
- (0, import_fs.mkdirSync)(configDir, { recursive: true });
326
- }
327
- const newConfig = generateMcpConfig(clientConfig);
328
- let finalConfig = newConfig;
329
- if ((0, import_fs.existsSync)(configPath)) {
330
- try {
331
- const existingContent = (0, import_fs.readFileSync)(configPath, "utf-8");
332
- const existingConfig = JSON.parse(existingContent);
333
- finalConfig = {
334
- ...existingConfig,
335
- [clientConfig.configKey]: {
336
- ...existingConfig[clientConfig.configKey],
337
- ...newConfig[clientConfig.configKey]
338
- }
339
- };
340
- } catch {
341
- }
342
- }
343
- (0, import_fs.writeFileSync)(configPath, JSON.stringify(finalConfig, null, 2));
344
- results.push({
345
- client,
346
- path: clientConfig.configPath,
347
- created: true
348
- });
349
- }
350
- p.note(results.map((r) => `${r.client}: ${r.path}`).join("\n"), "Created MCP configurations");
351
- p.outro("MCP setup complete! Your AI assistants can now use Panda CSS tools.");
352
- return results;
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));
353
182
  }
354
183
  // Annotate the CommonJS export names for ESM import in node:
355
184
  0 && (module.exports = {
356
- MCP_CLIENTS,
357
185
  createMcpServer,
358
- initMcpConfig,
359
186
  startMcpServer
360
187
  });
package/dist/index.mjs CHANGED
@@ -1,320 +1,8 @@
1
- // src/server.ts
2
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
- import { logger } from "@pandacss/logger";
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
- if (!transport) {
147
- watchProcessLifecycle(server);
148
- }
149
- console.error("Panda CSS MCP server started");
150
- console.error(`Working directory: ${resolvedCwd}`);
151
- if (resolvedConfigPath) {
152
- console.error(`Config path: ${resolvedConfigPath}`);
153
- }
154
- return server;
155
- }
156
- function watchProcessLifecycle(server, options = {}) {
157
- const proc = options.process ?? process;
158
- const exit = options.exit ?? ((code) => process.exit(code));
159
- let exiting = false;
160
- const shutdown = (code) => {
161
- if (exiting) return;
162
- exiting = true;
163
- void Promise.resolve(server.close()).catch(() => void 0);
164
- exit(code);
165
- };
166
- proc.stdin.on("end", () => shutdown(0));
167
- proc.stdin.on("close", () => shutdown(0));
168
- proc.on("SIGINT", () => shutdown(0));
169
- proc.on("SIGTERM", () => shutdown(0));
170
- for (const stream of [proc.stdout, proc.stderr]) {
171
- stream.on("error", (err) => {
172
- if (err?.code === "EPIPE") shutdown(0);
173
- });
174
- }
175
- const onFatal = (label) => (err) => {
176
- try {
177
- proc.stderr.write(`[panda mcp] ${label}, exiting: ${formatError(err)}
178
- `);
179
- } catch {
180
- }
181
- shutdown(1);
182
- };
183
- proc.on("uncaughtException", onFatal("uncaught exception"));
184
- proc.on("unhandledRejection", onFatal("unhandled rejection"));
185
- return shutdown;
186
- }
187
- function formatError(err) {
188
- return err instanceof Error ? err.stack ?? err.message : String(err);
189
- }
190
-
191
- // src/init.ts
192
- import * as p from "@clack/prompts";
193
- import { logger as logger2 } from "@pandacss/logger";
194
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
195
- import { dirname, resolve as resolve2 } from "path";
196
-
197
- // src/clients.ts
198
- var MCP_CLIENTS = {
199
- claude: {
200
- name: "claude",
201
- label: "Claude (.mcp.json)",
202
- configPath: ".mcp.json",
203
- configKey: "mcpServers"
204
- },
205
- cursor: {
206
- name: "cursor",
207
- label: "Cursor (.cursor/mcp.json)",
208
- configPath: ".cursor/mcp.json",
209
- configKey: "mcpServers"
210
- },
211
- vscode: {
212
- name: "vscode",
213
- label: "VS Code (.vscode/mcp.json)",
214
- configPath: ".vscode/mcp.json",
215
- configKey: "servers"
216
- },
217
- windsurf: {
218
- name: "windsurf",
219
- label: "Windsurf (.windsurf/mcp.json)",
220
- configPath: ".windsurf/mcp.json",
221
- configKey: "mcpServers"
222
- },
223
- codex: {
224
- name: "codex",
225
- label: "Codex (.codex/mcp.json)",
226
- configPath: ".codex/mcp.json",
227
- configKey: "mcpServers"
228
- }
229
- };
230
- var CLIENT_NAMES = Object.keys(MCP_CLIENTS);
231
- function isValidClient(client) {
232
- return CLIENT_NAMES.includes(client);
233
- }
234
- function getClientConfig(client) {
235
- return MCP_CLIENTS[client];
236
- }
237
- function generateMcpConfig(clientConfig) {
238
- const serverConfig = {
239
- command: "npx",
240
- args: ["panda", "mcp"]
241
- };
242
- return {
243
- [clientConfig.configKey]: {
244
- panda: serverConfig
245
- }
246
- };
247
- }
248
-
249
- // src/init.ts
250
- async function initMcpConfig(options = {}) {
251
- const { cwd = process.cwd() } = options;
252
- let { clients } = options;
253
- p.intro("Panda MCP Setup");
254
- if (!clients || clients.length === 0) {
255
- const selected = await p.multiselect({
256
- message: "Select AI clients to configure:",
257
- options: CLIENT_NAMES.map((client) => ({
258
- value: client,
259
- label: MCP_CLIENTS[client].label
260
- })),
261
- required: true
262
- });
263
- if (p.isCancel(selected)) {
264
- p.cancel("Setup cancelled.");
265
- process.exit(0);
266
- }
267
- clients = selected;
268
- }
269
- const validClients = clients.filter((client) => {
270
- if (!isValidClient(client)) {
271
- logger2.warn("mcp:init", `Unknown client: ${client}`);
272
- return false;
273
- }
274
- return true;
275
- });
276
- if (validClients.length === 0) {
277
- p.cancel("No valid clients selected.");
278
- process.exit(1);
279
- }
280
- const results = [];
281
- for (const client of validClients) {
282
- const clientConfig = getClientConfig(client);
283
- const configPath = resolve2(cwd, clientConfig.configPath);
284
- const configDir = dirname(configPath);
285
- if (!existsSync(configDir)) {
286
- mkdirSync(configDir, { recursive: true });
287
- }
288
- const newConfig = generateMcpConfig(clientConfig);
289
- let finalConfig = newConfig;
290
- if (existsSync(configPath)) {
291
- try {
292
- const existingContent = readFileSync(configPath, "utf-8");
293
- const existingConfig = JSON.parse(existingContent);
294
- finalConfig = {
295
- ...existingConfig,
296
- [clientConfig.configKey]: {
297
- ...existingConfig[clientConfig.configKey],
298
- ...newConfig[clientConfig.configKey]
299
- }
300
- };
301
- } catch {
302
- }
303
- }
304
- writeFileSync(configPath, JSON.stringify(finalConfig, null, 2));
305
- results.push({
306
- client,
307
- path: clientConfig.configPath,
308
- created: true
309
- });
310
- }
311
- p.note(results.map((r) => `${r.client}: ${r.path}`).join("\n"), "Created MCP configurations");
312
- p.outro("MCP setup complete! Your AI assistants can now use Panda CSS tools.");
313
- return results;
314
- }
1
+ import {
2
+ createMcpServer,
3
+ startMcpServer
4
+ } from "./chunk-OBOPWZHX.mjs";
315
5
  export {
316
- MCP_CLIENTS,
317
6
  createMcpServer,
318
- initMcpConfig,
319
7
  startMcpServer
320
8
  };
package/package.json CHANGED
@@ -1,10 +1,13 @@
1
1
  {
2
2
  "name": "@pandacss/mcp",
3
- "version": "1.11.3",
3
+ "version": "2.0.0-beta.1",
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,23 +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/logger": "1.11.3",
40
- "@pandacss/node": "1.11.3",
41
- "@pandacss/token-dictionary": "1.11.3",
42
- "@pandacss/types": "1.11.3"
43
- },
44
- "engines": {
45
- "node": ">=20"
43
+ "@pandacss/compiler": "2.0.0-beta.1"
46
44
  },
47
45
  "scripts": {
48
- "build": "tsup src/index.ts --format=esm,cjs",
49
- "build-fast": "tsup src/index.ts --format=esm,cjs",
50
- "dev": "pnpm build-fast --watch"
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"
51
49
  }
52
50
  }