@shoppexio/mcp-theme-server 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -85
- package/package.json +2 -2
- package/src/server.mjs +26 -21
package/README.md
CHANGED
|
@@ -1,104 +1,48 @@
|
|
|
1
1
|
# @shoppexio/mcp-theme-server
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
MCP server for Shoppex theme operations.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Use this package when you want an MCP-compatible client like Claude Code, Codex, Cursor, or OpenCode to work against hosted Shoppex themes.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## What It Exposes
|
|
8
|
+
|
|
9
|
+
The server exposes tools for:
|
|
10
|
+
- inspect and diff
|
|
11
|
+
- read and search
|
|
12
|
+
- apply changes
|
|
13
|
+
- create sections and pages
|
|
14
|
+
- validate, preview, publish, and rollback
|
|
15
|
+
|
|
16
|
+
## Runtime Config
|
|
17
|
+
|
|
18
|
+
Set these environment variables before starting the server:
|
|
8
19
|
|
|
9
20
|
```bash
|
|
10
|
-
|
|
21
|
+
export SHOPPEX_API_KEY=shx_your_key
|
|
22
|
+
export SHOPPEX_API_URL=https://api.shoppex.io
|
|
11
23
|
```
|
|
12
24
|
|
|
13
|
-
|
|
25
|
+
## Start
|
|
26
|
+
|
|
27
|
+
Install and run from npm:
|
|
14
28
|
|
|
15
29
|
```bash
|
|
16
30
|
npx -y @shoppexio/mcp-theme-server
|
|
17
31
|
```
|
|
18
32
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
```json
|
|
24
|
-
{
|
|
25
|
-
"mcpServers": {
|
|
26
|
-
"shoppex-themes": {
|
|
27
|
-
"command": "npx",
|
|
28
|
-
"args": ["-y", "@shoppexio/mcp-theme-server"],
|
|
29
|
-
"env": {
|
|
30
|
-
"SHOPPEX_API_KEY": "shx_your_dev_api_key"
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
33
|
+
Or, if you are working from this repo:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
bun packages/mcp-theme-server/bin/shoppex-mcp-theme-server.mjs
|
|
35
37
|
```
|
|
36
38
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
Any MCP client with stdio transport works. Set the same env var and point to `shoppex-mcp-theme-server` as the command.
|
|
42
|
-
|
|
43
|
-
## Tools (19)
|
|
44
|
-
|
|
45
|
-
| Tool | Purpose |
|
|
46
|
-
|------|---------|
|
|
47
|
-
| `theme.inspect` | Inspect theme structure and manifest |
|
|
48
|
-
| `theme.diff` | Diff theme state against a target |
|
|
49
|
-
| `theme.read_file` | Read one file from a theme |
|
|
50
|
-
| `theme.search_files` | Search across theme files |
|
|
51
|
-
| `theme.apply` | Apply a change set to a theme |
|
|
52
|
-
| `theme.accept` | Accept a pending change |
|
|
53
|
-
| `theme.create` | Scaffold a new theme |
|
|
54
|
-
| `theme.create_section` | Add a section |
|
|
55
|
-
| `theme.create_page` | Add a page |
|
|
56
|
-
| `theme.update_config` | Update `theme.config.ts` |
|
|
57
|
-
| `theme.preview` | Start a preview instance |
|
|
58
|
-
| `theme.stop_preview` | Stop a preview instance |
|
|
59
|
-
| `theme.publish` | Publish theme |
|
|
60
|
-
| `theme.publish_status` | Check publish status |
|
|
61
|
-
| `theme.validate` | Validate theme build |
|
|
62
|
-
| `theme.settings_get` | Read theme settings |
|
|
63
|
-
| `theme.settings_update` | Update theme settings |
|
|
64
|
-
| `theme.backups` | List backups |
|
|
65
|
-
| `theme.rollback` | Rollback to a previous version |
|
|
66
|
-
| `theme.latest_run` | Inspect last run result |
|
|
67
|
-
|
|
68
|
-
## Required Scopes
|
|
69
|
-
|
|
70
|
-
Your Shoppex Dev API key needs:
|
|
39
|
+
## Auth
|
|
40
|
+
|
|
41
|
+
Recommended scopes:
|
|
71
42
|
- `themes.read`
|
|
72
43
|
- `themes.write`
|
|
73
44
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
## Environment Variables
|
|
77
|
-
|
|
78
|
-
| Variable | Required | Default |
|
|
79
|
-
|----------|----------|---------|
|
|
80
|
-
| `SHOPPEX_API_KEY` | yes | — |
|
|
81
|
-
| `SHOPPEX_API_URL` | no | `https://api.shoppex.io` |
|
|
82
|
-
|
|
83
|
-
## Example Prompts
|
|
84
|
-
|
|
85
|
-
Once connected in Claude Desktop:
|
|
86
|
-
|
|
87
|
-
- "Inspect the Nebula theme and list its sections."
|
|
88
|
-
- "Create a new Hero section in my Pulse theme with a purple gradient background."
|
|
89
|
-
- "Preview the Classic theme with the accent color set to `#7C3AED`."
|
|
90
|
-
- "Publish the current draft of my Starlight theme."
|
|
91
|
-
|
|
92
|
-
## Companion
|
|
93
|
-
|
|
94
|
-
Pair with [`@shoppexio/mcp-commerce-server`](https://www.npmjs.com/package/@shoppexio/mcp-commerce-server) for products, orders, customers, coupons, and payment links.
|
|
95
|
-
|
|
96
|
-
## Docs
|
|
97
|
-
|
|
98
|
-
- [AI Workflows](https://docs.shoppex.io/themes/ai-workflows)
|
|
99
|
-
- [Build & Customize with AI](https://docs.shoppex.io/themes/build-and-customize-with-ai)
|
|
100
|
-
- [Developer API](https://docs.shoppex.io/api-reference/introduction)
|
|
101
|
-
|
|
102
|
-
## License
|
|
45
|
+
## Related Docs
|
|
103
46
|
|
|
104
|
-
|
|
47
|
+
- AI Workflows: `https://docs.shoppex.io/themes/ai-workflows`
|
|
48
|
+
- Theme Control Plane: `https://docs.shoppex.io/themes/theme-control-plane`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shoppexio/mcp-theme-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Shoppex MCP server for theme control plane operations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -38,6 +38,6 @@
|
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@modelcontextprotocol/sdk": "^1.28.0",
|
|
41
|
-
"@shoppexio/theme-control-client": "
|
|
41
|
+
"@shoppexio/theme-control-client": "^0.1.0"
|
|
42
42
|
}
|
|
43
43
|
}
|
package/src/server.mjs
CHANGED
|
@@ -22,7 +22,7 @@ function jsonContent(value) {
|
|
|
22
22
|
export function createThemeToolCatalog() {
|
|
23
23
|
return [
|
|
24
24
|
{
|
|
25
|
-
name: '
|
|
25
|
+
name: 'theme_inspect',
|
|
26
26
|
description: 'Inspect a Shoppex theme and return editable areas, sections, settings, design tokens, and constraints.',
|
|
27
27
|
inputSchema: {
|
|
28
28
|
theme_id: z.string().min(1),
|
|
@@ -30,7 +30,7 @@ export function createThemeToolCatalog() {
|
|
|
30
30
|
execute: ({ theme_id }, client) => client.inspectTheme(theme_id),
|
|
31
31
|
},
|
|
32
32
|
{
|
|
33
|
-
name: '
|
|
33
|
+
name: 'theme_diff',
|
|
34
34
|
description: 'Show changes between the current draft and the latest published theme snapshot.',
|
|
35
35
|
inputSchema: {
|
|
36
36
|
theme_id: z.string().min(1),
|
|
@@ -38,7 +38,7 @@ export function createThemeToolCatalog() {
|
|
|
38
38
|
execute: ({ theme_id }, client) => client.diffTheme(theme_id),
|
|
39
39
|
},
|
|
40
40
|
{
|
|
41
|
-
name: '
|
|
41
|
+
name: 'theme_read_file',
|
|
42
42
|
description: 'Read a single source file from a Shoppex theme.',
|
|
43
43
|
inputSchema: {
|
|
44
44
|
theme_id: z.string().min(1),
|
|
@@ -47,7 +47,7 @@ export function createThemeToolCatalog() {
|
|
|
47
47
|
execute: ({ theme_id, file_path }, client) => client.readThemeFile(theme_id, file_path),
|
|
48
48
|
},
|
|
49
49
|
{
|
|
50
|
-
name: '
|
|
50
|
+
name: 'theme_search_files',
|
|
51
51
|
description: 'Search theme files by path or content.',
|
|
52
52
|
inputSchema: {
|
|
53
53
|
theme_id: z.string().min(1),
|
|
@@ -57,7 +57,7 @@ export function createThemeToolCatalog() {
|
|
|
57
57
|
execute: ({ theme_id, query, limit }, client) => client.searchThemeFiles(theme_id, query, limit),
|
|
58
58
|
},
|
|
59
59
|
{
|
|
60
|
-
name: '
|
|
60
|
+
name: 'theme_apply',
|
|
61
61
|
description: 'Apply one or more text-file changes to a theme draft with server-side verification.',
|
|
62
62
|
inputSchema: {
|
|
63
63
|
theme_id: z.string().min(1),
|
|
@@ -75,7 +75,7 @@ export function createThemeToolCatalog() {
|
|
|
75
75
|
}),
|
|
76
76
|
},
|
|
77
77
|
{
|
|
78
|
-
name: '
|
|
78
|
+
name: 'theme_accept',
|
|
79
79
|
description: 'Accept an already generated draft patch from a dashboard-agent run.',
|
|
80
80
|
inputSchema: {
|
|
81
81
|
theme_id: z.string().min(1),
|
|
@@ -90,7 +90,7 @@ export function createThemeToolCatalog() {
|
|
|
90
90
|
}),
|
|
91
91
|
},
|
|
92
92
|
{
|
|
93
|
-
name: '
|
|
93
|
+
name: 'theme_create',
|
|
94
94
|
description: 'Create a new theme scaffold from a Shoppex base theme.',
|
|
95
95
|
inputSchema: {
|
|
96
96
|
base: z.enum(['default', 'classic', 'nebula', 'pulse', 'phantom', 'starlight']),
|
|
@@ -104,7 +104,7 @@ export function createThemeToolCatalog() {
|
|
|
104
104
|
}),
|
|
105
105
|
},
|
|
106
106
|
{
|
|
107
|
-
name: '
|
|
107
|
+
name: 'theme_create_section',
|
|
108
108
|
description: 'Scaffold a new theme section and wire it into theme.config.ts.',
|
|
109
109
|
inputSchema: {
|
|
110
110
|
theme_id: z.string().min(1),
|
|
@@ -119,7 +119,7 @@ export function createThemeToolCatalog() {
|
|
|
119
119
|
}),
|
|
120
120
|
},
|
|
121
121
|
{
|
|
122
|
-
name: '
|
|
122
|
+
name: 'theme_create_page',
|
|
123
123
|
description: 'Scaffold a new static page and wire its route into src/App.tsx.',
|
|
124
124
|
inputSchema: {
|
|
125
125
|
theme_id: z.string().min(1),
|
|
@@ -134,7 +134,7 @@ export function createThemeToolCatalog() {
|
|
|
134
134
|
}),
|
|
135
135
|
},
|
|
136
136
|
{
|
|
137
|
-
name: '
|
|
137
|
+
name: 'theme_update_config',
|
|
138
138
|
description: 'Extend theme.config.ts with a new settings field.',
|
|
139
139
|
inputSchema: {
|
|
140
140
|
theme_id: z.string().min(1),
|
|
@@ -149,7 +149,7 @@ export function createThemeToolCatalog() {
|
|
|
149
149
|
}),
|
|
150
150
|
},
|
|
151
151
|
{
|
|
152
|
-
name: '
|
|
152
|
+
name: 'theme_preview',
|
|
153
153
|
description: 'Start or reuse a live preview session for the current theme draft.',
|
|
154
154
|
inputSchema: {
|
|
155
155
|
theme_id: z.string().min(1),
|
|
@@ -157,7 +157,7 @@ export function createThemeToolCatalog() {
|
|
|
157
157
|
execute: ({ theme_id }, client) => client.startThemePreview(theme_id),
|
|
158
158
|
},
|
|
159
159
|
{
|
|
160
|
-
name: '
|
|
160
|
+
name: 'theme_stop_preview',
|
|
161
161
|
description: 'Stop a running live preview session.',
|
|
162
162
|
inputSchema: {
|
|
163
163
|
theme_id: z.string().min(1),
|
|
@@ -166,7 +166,7 @@ export function createThemeToolCatalog() {
|
|
|
166
166
|
execute: ({ theme_id, session_id }, client) => client.stopThemePreview(theme_id, session_id),
|
|
167
167
|
},
|
|
168
168
|
{
|
|
169
|
-
name: '
|
|
169
|
+
name: 'theme_publish',
|
|
170
170
|
description: 'Queue a publish/deploy for the current accepted theme draft.',
|
|
171
171
|
inputSchema: {
|
|
172
172
|
theme_id: z.string().min(1),
|
|
@@ -174,7 +174,7 @@ export function createThemeToolCatalog() {
|
|
|
174
174
|
execute: ({ theme_id }, client) => client.publishTheme(theme_id),
|
|
175
175
|
},
|
|
176
176
|
{
|
|
177
|
-
name: '
|
|
177
|
+
name: 'theme_publish_status',
|
|
178
178
|
description: 'Read the current publish job status.',
|
|
179
179
|
inputSchema: {
|
|
180
180
|
theme_id: z.string().min(1),
|
|
@@ -183,7 +183,7 @@ export function createThemeToolCatalog() {
|
|
|
183
183
|
execute: ({ theme_id, job_id }, client) => client.getThemePublishStatus(theme_id, job_id),
|
|
184
184
|
},
|
|
185
185
|
{
|
|
186
|
-
name: '
|
|
186
|
+
name: 'theme_validate',
|
|
187
187
|
description: 'Run a validation-only build and optional typecheck without publishing.',
|
|
188
188
|
inputSchema: {
|
|
189
189
|
theme_id: z.string().min(1),
|
|
@@ -194,7 +194,7 @@ export function createThemeToolCatalog() {
|
|
|
194
194
|
}),
|
|
195
195
|
},
|
|
196
196
|
{
|
|
197
|
-
name: '
|
|
197
|
+
name: 'theme_settings_get',
|
|
198
198
|
description: 'Read the current builder settings values for a theme.',
|
|
199
199
|
inputSchema: {
|
|
200
200
|
theme_id: z.string().min(1),
|
|
@@ -202,7 +202,7 @@ export function createThemeToolCatalog() {
|
|
|
202
202
|
execute: ({ theme_id }, client) => client.getThemeSettings(theme_id),
|
|
203
203
|
},
|
|
204
204
|
{
|
|
205
|
-
name: '
|
|
205
|
+
name: 'theme_settings_update',
|
|
206
206
|
description: 'Update theme builder settings without editing source files directly.',
|
|
207
207
|
inputSchema: {
|
|
208
208
|
theme_id: z.string().min(1),
|
|
@@ -213,7 +213,7 @@ export function createThemeToolCatalog() {
|
|
|
213
213
|
}),
|
|
214
214
|
},
|
|
215
215
|
{
|
|
216
|
-
name: '
|
|
216
|
+
name: 'theme_backups',
|
|
217
217
|
description: 'List available theme backups for rollback.',
|
|
218
218
|
inputSchema: {
|
|
219
219
|
theme_id: z.string().min(1),
|
|
@@ -221,7 +221,7 @@ export function createThemeToolCatalog() {
|
|
|
221
221
|
execute: ({ theme_id }, client) => client.listThemeBackups(theme_id),
|
|
222
222
|
},
|
|
223
223
|
{
|
|
224
|
-
name: '
|
|
224
|
+
name: 'theme_rollback',
|
|
225
225
|
description: 'Rollback a theme to a previous backup snapshot.',
|
|
226
226
|
inputSchema: {
|
|
227
227
|
theme_id: z.string().min(1),
|
|
@@ -230,7 +230,7 @@ export function createThemeToolCatalog() {
|
|
|
230
230
|
execute: ({ theme_id, backup_id }, client) => client.rollbackTheme(theme_id, backup_id),
|
|
231
231
|
},
|
|
232
232
|
{
|
|
233
|
-
name: '
|
|
233
|
+
name: 'theme_latest_run',
|
|
234
234
|
description: 'Read the latest dashboard-agent run metadata for a theme.',
|
|
235
235
|
inputSchema: {
|
|
236
236
|
theme_id: z.string().min(1),
|
|
@@ -240,8 +240,13 @@ export function createThemeToolCatalog() {
|
|
|
240
240
|
];
|
|
241
241
|
}
|
|
242
242
|
|
|
243
|
+
function normalizeToolName(name) {
|
|
244
|
+
return typeof name === 'string' ? name.replace(/\./g, '_') : name;
|
|
245
|
+
}
|
|
246
|
+
|
|
243
247
|
export async function executeThemeTool(toolName, args, client) {
|
|
244
|
-
const
|
|
248
|
+
const normalized = normalizeToolName(toolName);
|
|
249
|
+
const tool = createThemeToolCatalog().find((entry) => entry.name === normalized);
|
|
245
250
|
if (!tool) {
|
|
246
251
|
throw new Error(`Unknown tool: ${toolName}`);
|
|
247
252
|
}
|