@abraracs/better-shopify-wc-mcp 1.0.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.
Files changed (51) hide show
  1. package/README.md +110 -0
  2. package/dist/index.d.ts +10 -0
  3. package/dist/index.js +325 -0
  4. package/docs/avatar.md +481 -0
  5. package/docs/badge.md +266 -0
  6. package/docs/banner.md +350 -0
  7. package/docs/box.md +618 -0
  8. package/docs/button.md +604 -0
  9. package/docs/buttongroup.md +251 -0
  10. package/docs/checkbox.md +346 -0
  11. package/docs/chip.md +261 -0
  12. package/docs/choicelist.md +416 -0
  13. package/docs/clickable.md +703 -0
  14. package/docs/clickablechip.md +377 -0
  15. package/docs/colorfield.md +416 -0
  16. package/docs/colorpicker.md +152 -0
  17. package/docs/datefield.md +706 -0
  18. package/docs/datepicker.md +443 -0
  19. package/docs/divider.md +263 -0
  20. package/docs/dropzone.md +331 -0
  21. package/docs/emailfield.md +377 -0
  22. package/docs/grid.md +1246 -0
  23. package/docs/heading.md +201 -0
  24. package/docs/icon.md +295 -0
  25. package/docs/image.md +517 -0
  26. package/docs/link.md +456 -0
  27. package/docs/menu.md +331 -0
  28. package/docs/modal.md +640 -0
  29. package/docs/moneyfield.md +385 -0
  30. package/docs/numberfield.md +393 -0
  31. package/docs/orderedlist.md +224 -0
  32. package/docs/page.md +319 -0
  33. package/docs/paragraph.md +333 -0
  34. package/docs/passwordfield.md +381 -0
  35. package/docs/popover.md +419 -0
  36. package/docs/querycontainer.md +121 -0
  37. package/docs/searchfield.md +319 -0
  38. package/docs/section.md +267 -0
  39. package/docs/select.md +449 -0
  40. package/docs/spinner.md +121 -0
  41. package/docs/stack.md +748 -0
  42. package/docs/switch.md +365 -0
  43. package/docs/table.md +805 -0
  44. package/docs/text.md +339 -0
  45. package/docs/textarea.md +328 -0
  46. package/docs/textfield.md +425 -0
  47. package/docs/thumbnail.md +245 -0
  48. package/docs/tooltip.md +130 -0
  49. package/docs/unorderedlist.md +135 -0
  50. package/docs/urlfield.md +314 -0
  51. package/package.json +43 -0
package/README.md ADDED
@@ -0,0 +1,110 @@
1
+ # Better Shopify Web Components MCP
2
+
3
+ An MCP (Model Context Protocol) server that provides accurate Shopify Polaris web component documentation to AI tools like Cursor, GitHub Copilot, and Claude.
4
+
5
+ ## Why This Exists
6
+
7
+ Shopify's official MCP often **hallucinates attributes** because:
8
+
9
+ - Polaris web components have **specialized attributes only**
10
+ - Standard HTML attributes (`style`, `class`, `onclick`) **don't work**
11
+ - AI models haven't learned the correct patterns yet
12
+
13
+ This MCP provides:
14
+
15
+ - ✅ **Only valid attributes** from official docs
16
+ - ✅ **Workaround patterns** for styling limitations
17
+ - ✅ **System prompts** with Polaris-specific rules
18
+
19
+ ## Installation
20
+
21
+ ### Cursor
22
+
23
+ Add to `~/.cursor/mcp.json`:
24
+
25
+ ```json
26
+ {
27
+ "mcpServers": {
28
+ "polaris": {
29
+ "command": "npx",
30
+ "args": ["-y", "@abraracs/better-shopify-wc-mcp"]
31
+ }
32
+ }
33
+ }
34
+ ```
35
+
36
+ ### GitHub Copilot (VS Code)
37
+
38
+ Add to `.vscode/mcp.json`:
39
+
40
+ ```json
41
+ {
42
+ "servers": {
43
+ "polaris": {
44
+ "command": "npx",
45
+ "args": ["-y", "@abraracs/better-shopify-wc-mcp"]
46
+ }
47
+ }
48
+ }
49
+ ```
50
+
51
+ ### Claude Desktop
52
+
53
+ Add to `claude_desktop_config.json`:
54
+
55
+ ```json
56
+ {
57
+ "mcpServers": {
58
+ "polaris": {
59
+ "command": "npx",
60
+ "args": ["-y", "@abraracs/better-shopify-wc-mcp"]
61
+ }
62
+ }
63
+ }
64
+ ```
65
+
66
+ ## Usage
67
+
68
+ Once configured, the AI will have access to:
69
+
70
+ ### Tools
71
+
72
+ - `list_components` - List all 47 Polaris components
73
+ - `get_component` - Get full documentation for a component
74
+ - `search_components` - Search by keyword
75
+
76
+ ### Resources
77
+
78
+ - `polaris://components/{name}` - Direct access to component docs
79
+
80
+ ### Prompts
81
+
82
+ - `polaris_rules` - Critical rules and workaround patterns
83
+
84
+ ## Key Concept: Styling Workarounds
85
+
86
+ Polaris web components don't support `style` or `class` attributes. When you need custom styling, put it **INSIDE** the component:
87
+
88
+ ```html
89
+ <!-- ❌ WRONG: style on component does nothing -->
90
+ <s-paragraph style="text-align: center;">Text</s-paragraph>
91
+
92
+ <!-- ✅ CORRECT: style on inner element -->
93
+ <s-paragraph>
94
+ <div style="text-align: center;">Text</div>
95
+ </s-paragraph>
96
+ ```
97
+
98
+ ## Components Included
99
+
100
+ 47 Polaris web components including:
101
+
102
+ - Actions: `button`, `buttongroup`, `link`, `menu`
103
+ - Forms: `textfield`, `select`, `checkbox`, `datepicker`
104
+ - Layout: `box`, `stack`, `grid`, `section`, `page`
105
+ - Feedback: `banner`, `modal`, `popover`, `tooltip`
106
+ - Display: `text`, `heading`, `badge`, `avatar`, `icon`
107
+
108
+ ## License
109
+
110
+ MIT
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Better Shopify Web Components MCP Server
4
+ *
5
+ * Provides accurate Polaris web component documentation with:
6
+ * - Only valid attributes (no hallucinations)
7
+ * - Workaround patterns for styling limitations
8
+ * - System prompts with Polaris-specific rules
9
+ */
10
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,325 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Better Shopify Web Components MCP Server
4
+ *
5
+ * Provides accurate Polaris web component documentation with:
6
+ * - Only valid attributes (no hallucinations)
7
+ * - Workaround patterns for styling limitations
8
+ * - System prompts with Polaris-specific rules
9
+ */
10
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
11
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
12
+ import { CallToolRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListToolsRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
13
+ import * as fs from "fs";
14
+ import * as path from "path";
15
+ import { fileURLToPath } from "url";
16
+ const __filename = fileURLToPath(import.meta.url);
17
+ const __dirname = path.dirname(__filename);
18
+ const DOCS_DIR = path.join(__dirname, "..", "docs");
19
+ function loadDocs() {
20
+ const docs = [];
21
+ const files = fs.readdirSync(DOCS_DIR).filter(f => f.endsWith(".md"));
22
+ for (const file of files) {
23
+ const content = fs.readFileSync(path.join(DOCS_DIR, file), "utf-8");
24
+ const name = file.replace(".md", "");
25
+ // Extract description from frontmatter or first paragraph
26
+ let description = "";
27
+ const descMatch = content.match(/description:\s*>-?\s*\n\s+(.+?)(?:\n[a-z_]+:|---)/s);
28
+ if (descMatch) {
29
+ description = descMatch[1].replace(/\n\s+/g, " ").trim();
30
+ }
31
+ docs.push({ name, filename: file, content, description });
32
+ }
33
+ return docs;
34
+ }
35
+ const componentDocs = loadDocs();
36
+ // Create server
37
+ const server = new Server({
38
+ name: "better-shopify-wc-mcp",
39
+ version: "1.0.0",
40
+ }, {
41
+ capabilities: {
42
+ resources: {},
43
+ tools: {},
44
+ prompts: {},
45
+ },
46
+ });
47
+ // ============ RESOURCES ============
48
+ server.setRequestHandler(ListResourcesRequestSchema, async () => {
49
+ return {
50
+ resources: componentDocs.map(doc => ({
51
+ uri: `polaris://components/${doc.name}`,
52
+ name: doc.name,
53
+ description: doc.description || `Documentation for ${doc.name} component`,
54
+ mimeType: "text/markdown",
55
+ })),
56
+ };
57
+ });
58
+ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
59
+ const uri = request.params.uri;
60
+ const match = uri.match(/^polaris:\/\/components\/(.+)$/);
61
+ if (!match) {
62
+ throw new Error(`Invalid resource URI: ${uri}`);
63
+ }
64
+ const componentName = match[1].toLowerCase();
65
+ const doc = componentDocs.find(d => d.name.toLowerCase() === componentName);
66
+ if (!doc) {
67
+ throw new Error(`Component not found: ${componentName}`);
68
+ }
69
+ return {
70
+ contents: [
71
+ {
72
+ uri,
73
+ mimeType: "text/markdown",
74
+ text: doc.content,
75
+ },
76
+ ],
77
+ };
78
+ });
79
+ // ============ TOOLS ============
80
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
81
+ return {
82
+ tools: [
83
+ {
84
+ name: "list_components",
85
+ description: "List all available Shopify Polaris web components",
86
+ inputSchema: {
87
+ type: "object",
88
+ properties: {},
89
+ },
90
+ },
91
+ {
92
+ name: "get_component",
93
+ description: "Get full documentation for a specific Polaris component including all valid attributes",
94
+ inputSchema: {
95
+ type: "object",
96
+ properties: {
97
+ name: {
98
+ type: "string",
99
+ description: "Component name (e.g., 'button', 'modal', 'stack')",
100
+ },
101
+ },
102
+ required: ["name"],
103
+ },
104
+ },
105
+ {
106
+ name: "search_components",
107
+ description: "Search for Polaris components by keyword in name or description",
108
+ inputSchema: {
109
+ type: "object",
110
+ properties: {
111
+ query: {
112
+ type: "string",
113
+ description: "Search keyword",
114
+ },
115
+ },
116
+ required: ["query"],
117
+ },
118
+ },
119
+ ],
120
+ };
121
+ });
122
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
123
+ const { name, arguments: args } = request.params;
124
+ switch (name) {
125
+ case "list_components": {
126
+ const list = componentDocs.map(d => ({
127
+ name: d.name,
128
+ tag: `<s-${d.name}>`,
129
+ description: d.description.slice(0, 100) + (d.description.length > 100 ? "..." : ""),
130
+ }));
131
+ return {
132
+ content: [
133
+ {
134
+ type: "text",
135
+ text: JSON.stringify(list, null, 2),
136
+ },
137
+ ],
138
+ };
139
+ }
140
+ case "get_component": {
141
+ const componentName = args.name.toLowerCase();
142
+ const doc = componentDocs.find(d => d.name.toLowerCase() === componentName);
143
+ if (!doc) {
144
+ return {
145
+ content: [
146
+ {
147
+ type: "text",
148
+ text: `Component "${componentName}" not found. Use list_components to see available components.`,
149
+ },
150
+ ],
151
+ isError: true,
152
+ };
153
+ }
154
+ return {
155
+ content: [
156
+ {
157
+ type: "text",
158
+ text: doc.content,
159
+ },
160
+ ],
161
+ };
162
+ }
163
+ case "search_components": {
164
+ const query = args.query.toLowerCase();
165
+ const results = componentDocs.filter(d => d.name.toLowerCase().includes(query) ||
166
+ d.description.toLowerCase().includes(query) ||
167
+ d.content.toLowerCase().includes(query));
168
+ if (results.length === 0) {
169
+ return {
170
+ content: [
171
+ {
172
+ type: "text",
173
+ text: `No components found matching "${query}"`,
174
+ },
175
+ ],
176
+ };
177
+ }
178
+ const summary = results.map(d => ({
179
+ name: d.name,
180
+ tag: `<s-${d.name}>`,
181
+ description: d.description.slice(0, 150) + (d.description.length > 150 ? "..." : ""),
182
+ }));
183
+ return {
184
+ content: [
185
+ {
186
+ type: "text",
187
+ text: JSON.stringify(summary, null, 2),
188
+ },
189
+ ],
190
+ };
191
+ }
192
+ default:
193
+ throw new Error(`Unknown tool: ${name}`);
194
+ }
195
+ });
196
+ // ============ PROMPTS ============
197
+ server.setRequestHandler(ListPromptsRequestSchema, async () => {
198
+ return {
199
+ prompts: [
200
+ {
201
+ name: "polaris_rules",
202
+ description: "Critical rules for working with Shopify Polaris web components - MUST READ before generating any Polaris UI code",
203
+ },
204
+ ],
205
+ };
206
+ });
207
+ server.setRequestHandler(GetPromptRequestSchema, async (request) => {
208
+ if (request.params.name === "polaris_rules") {
209
+ return {
210
+ description: "Critical rules for Shopify Polaris web components",
211
+ messages: [
212
+ {
213
+ role: "user",
214
+ content: {
215
+ type: "text",
216
+ text: POLARIS_RULES_PROMPT,
217
+ },
218
+ },
219
+ ],
220
+ };
221
+ }
222
+ throw new Error(`Unknown prompt: ${request.params.name}`);
223
+ });
224
+ // ============ SYSTEM PROMPT ============
225
+ const POLARIS_RULES_PROMPT = `# Shopify Polaris Web Components - Critical Rules
226
+
227
+ You are working with Shopify Polaris web components (tags starting with \`s-\`).
228
+ These are SPECIALIZED WEB COMPONENTS with strict rules. Follow them exactly.
229
+
230
+ ## ⚠️ CRITICAL: Attribute Rules
231
+
232
+ 1. **ONLY use attributes documented for each component**
233
+ 2. **DO NOT use standard HTML attributes** - they will NOT work:
234
+ - ❌ style
235
+ - ❌ class
236
+ - ❌ id
237
+ - ❌ onclick / onchange / on*
238
+ - ❌ data-*
239
+
240
+ 3. Each component has its OWN specific attributes (e.g., \`variant\`, \`tone\`, \`gap\`)
241
+
242
+ ## 🔧 Styling Workarounds
243
+
244
+ When you need styling that's not available as a component attribute,
245
+ put the override **INSIDE** the web component using standard HTML:
246
+
247
+ ### Example: Center-aligned text
248
+ \`\`\`html
249
+ <!-- ❌ WRONG: style attribute on s-paragraph does nothing -->
250
+ <s-paragraph style="text-align: center;">Text</s-paragraph>
251
+
252
+ <!-- ✅ CORRECT: put styled div INSIDE the component -->
253
+ <s-paragraph>
254
+ <div style="text-align: center;">Text</div>
255
+ </s-paragraph>
256
+ \`\`\`
257
+
258
+ ### Example: Custom spacing
259
+ \`\`\`html
260
+ <!-- ❌ WRONG: margin on component does nothing -->
261
+ <s-button style="margin-top: 20px;">Click</s-button>
262
+
263
+ <!-- ✅ CORRECT: use s-box or s-stack for spacing -->
264
+ <s-stack gap="large">
265
+ <s-text>Some text above</s-text>
266
+ <s-button>Click</s-button>
267
+ </s-stack>
268
+ \`\`\`
269
+
270
+ ### Example: Flex / Grid layouts
271
+ \`\`\`html
272
+ <!-- ✅ Use s-stack with direction for flex-like layouts -->
273
+ <s-stack direction="inline" gap="base">
274
+ <s-button>Button 1</s-button>
275
+ <s-button>Button 2</s-button>
276
+ </s-stack>
277
+
278
+ <!-- ✅ Use s-grid for grid layouts -->
279
+ <s-grid columns="2">
280
+ <s-box>Cell 1</s-box>
281
+ <s-box>Cell 2</s-box>
282
+ </s-grid>
283
+ \`\`\`
284
+
285
+ ## 📋 Common Workaround Patterns
286
+
287
+ | Need | Wrong Approach | Correct Pattern |
288
+ |------|----------------|-----------------|
289
+ | Center text | \`<s-paragraph style="text-align:center">\` | \`<s-paragraph><div style="text-align:center">text</div></s-paragraph>\` |
290
+ | Custom margins | \`<s-button style="margin:...">\` | Use \`<s-stack>\` or \`<s-box>\` with gap/padding attrs |
291
+ | Inline layout | \`<div style="display:flex">\` | \`<s-stack direction="inline">\` |
292
+ | Colors | \`<s-text style="color:red">\` | Use \`tone\` attribute if available |
293
+ | Visibility | \`style="display:none"\` | Wrap in \`<div>\` with display logic |
294
+
295
+ ## 🏷️ Component Tag Format
296
+
297
+ All Polaris web components use the \`s-\` prefix:
298
+ - \`<s-button>\` - Buttons
299
+ - \`<s-stack>\` - Flex layouts
300
+ - \`<s-box>\` - Container with padding
301
+ - \`<s-modal>\` - Modal dialogs
302
+ - \`<s-text>\` - Text display
303
+ - etc.
304
+
305
+ ## 📚 Before Using Any Component
306
+
307
+ 1. Use \`get_component\` tool to fetch its documentation
308
+ 2. Check the **Properties** section for valid attributes
309
+ 3. Check **Examples** for proper usage patterns
310
+ 4. NEVER assume an attribute exists - verify in docs first
311
+
312
+ ## 🚫 Common Mistakes to Avoid
313
+
314
+ 1. Using \`className\` or \`class\` - use component's own styling props
315
+ 2. Using inline \`style\` on components - put styles on inner elements
316
+ 3. Using React event handlers (\`onClick\`) - components have their own events
317
+ 4. Assuming HTML attributes work - they don't on web components
318
+ `;
319
+ // ============ START SERVER ============
320
+ async function main() {
321
+ const transport = new StdioServerTransport();
322
+ await server.connect(transport);
323
+ console.error("Better Shopify WC MCP server running on stdio");
324
+ }
325
+ main().catch(console.error);