@curenorway/kode-mcp 1.3.0 → 1.4.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 +183 -83
- package/dist/index.js +85 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -2,42 +2,52 @@
|
|
|
2
2
|
|
|
3
3
|
MCP (Model Context Protocol) server that enables AI agents to manage Webflow scripts via Cure Kode CDN.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Features
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
7
|
+
- **Script Management** - List, create, update, and delete scripts
|
|
8
|
+
- **Deployment Control** - Deploy to staging, promote to production, rollback
|
|
9
|
+
- **Page Context** - Cache and retrieve page structures for development
|
|
10
|
+
- **Script Analysis** - Auto-analyze scripts for metadata (selectors, triggers, dependencies)
|
|
11
|
+
- **Production Safety** - Explicit enable required, confirmation for promote
|
|
12
12
|
|
|
13
13
|
## Installation
|
|
14
14
|
|
|
15
15
|
### For Claude Code
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
The easiest way is to run `kode init` in your project, which creates `.mcp.json`:
|
|
18
18
|
|
|
19
19
|
```json
|
|
20
20
|
{
|
|
21
21
|
"mcpServers": {
|
|
22
22
|
"cure-kode": {
|
|
23
|
+
"type": "stdio",
|
|
23
24
|
"command": "npx",
|
|
24
|
-
"args": ["@curenorway/kode-mcp"]
|
|
25
|
+
"args": ["-y", "@curenorway/kode-mcp"]
|
|
25
26
|
}
|
|
26
27
|
}
|
|
27
28
|
}
|
|
28
29
|
```
|
|
29
30
|
|
|
30
|
-
|
|
31
|
+
Then restart Claude Code and approve the MCP when prompted.
|
|
31
32
|
|
|
32
|
-
|
|
33
|
+
### Manual Configuration
|
|
33
34
|
|
|
34
|
-
|
|
35
|
+
Add to your Claude Code configuration (`~/.claude/claude_code_config.json`):
|
|
35
36
|
|
|
36
|
-
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"mcpServers": {
|
|
40
|
+
"cure-kode": {
|
|
41
|
+
"command": "npx",
|
|
42
|
+
"args": ["-y", "@curenorway/kode-mcp"]
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
37
47
|
|
|
38
|
-
|
|
48
|
+
## Configuration
|
|
39
49
|
|
|
40
|
-
|
|
50
|
+
The MCP server reads configuration from `.cure-kode/config.json` (created by `kode init`):
|
|
41
51
|
|
|
42
52
|
```json
|
|
43
53
|
{
|
|
@@ -45,46 +55,151 @@ Run `kode init` in your project to create `.cure-kode/config.json`:
|
|
|
45
55
|
"siteSlug": "my-site",
|
|
46
56
|
"siteName": "My Site",
|
|
47
57
|
"apiKey": "ck_...",
|
|
48
|
-
"scriptsDir": "kode",
|
|
58
|
+
"scriptsDir": ".cure-kode-scripts",
|
|
49
59
|
"environment": "staging"
|
|
50
60
|
}
|
|
51
61
|
```
|
|
52
62
|
|
|
53
|
-
|
|
54
|
-
|
|
63
|
+
Or via environment variables:
|
|
55
64
|
```bash
|
|
56
65
|
export CURE_KODE_API_KEY="ck_..."
|
|
57
66
|
export CURE_KODE_SITE_ID="your-site-uuid"
|
|
58
|
-
export CURE_KODE_API_URL="https://app.cure.no" # optional
|
|
59
67
|
```
|
|
60
68
|
|
|
61
69
|
## Available Tools
|
|
62
70
|
|
|
71
|
+
### Script Management
|
|
72
|
+
|
|
63
73
|
| Tool | Description |
|
|
64
74
|
|------|-------------|
|
|
65
75
|
| `kode_list_scripts` | List all scripts for the site |
|
|
66
|
-
| `kode_get_script` | Get script
|
|
67
|
-
| `kode_create_script` | Create a new script |
|
|
68
|
-
| `kode_update_script` | Update script
|
|
76
|
+
| `kode_get_script` | Get script by slug (supports `includeContent: false` for metadata only) |
|
|
77
|
+
| `kode_create_script` | Create a new script entry (metadata only, no content) |
|
|
78
|
+
| `kode_update_script` | Update script settings (autoLoad, scope, purpose) |
|
|
69
79
|
| `kode_delete_script` | Delete a script |
|
|
70
|
-
| `
|
|
71
|
-
|
|
80
|
+
| `kode_push` | Upload local files from `.cure-kode-scripts/` to server |
|
|
81
|
+
|
|
82
|
+
### Deployment
|
|
83
|
+
|
|
84
|
+
| Tool | Description |
|
|
85
|
+
|------|-------------|
|
|
86
|
+
| `kode_deploy` | Deploy to staging |
|
|
87
|
+
| `kode_promote` | Promote staging to production (**requires `confirmed: true`**) |
|
|
88
|
+
| `kode_rollback` | Rollback to previous deployment |
|
|
72
89
|
| `kode_status` | Get deployment status |
|
|
73
|
-
|
|
74
|
-
|
|
90
|
+
|
|
91
|
+
### Production Management
|
|
92
|
+
|
|
93
|
+
| Tool | Description |
|
|
94
|
+
|------|-------------|
|
|
95
|
+
| `kode_production_enable` | Enable production environment |
|
|
96
|
+
| `kode_production_disable` | Disable production environment |
|
|
97
|
+
|
|
98
|
+
### Page & HTML Analysis
|
|
99
|
+
|
|
100
|
+
| Tool | Description |
|
|
101
|
+
|------|-------------|
|
|
102
|
+
| `kode_fetch_html` | Fetch and parse HTML from URL |
|
|
103
|
+
| `kode_fetch_html_smart` | Fetch with CMS truncation for smaller context |
|
|
104
|
+
| `kode_list_pages` | List page definitions for the site |
|
|
105
|
+
| `kode_assign_script_to_page` | Assign script to specific pages |
|
|
106
|
+
| `kode_remove_script_from_page` | Remove script from page |
|
|
107
|
+
|
|
108
|
+
### Page Context (for AI Development)
|
|
109
|
+
|
|
110
|
+
| Tool | Description |
|
|
111
|
+
|------|-------------|
|
|
112
|
+
| `kode_refresh_page` | Fetch and cache page structure |
|
|
113
|
+
| `kode_get_page_context` | Get cached page context (sections, forms, CTAs, selectors) |
|
|
114
|
+
| `kode_list_pages_context` | List all cached page contexts |
|
|
115
|
+
|
|
116
|
+
### Script Metadata
|
|
117
|
+
|
|
118
|
+
| Tool | Description |
|
|
119
|
+
|------|-------------|
|
|
120
|
+
| `kode_analyze_script` | Analyze script and generate metadata |
|
|
121
|
+
| `kode_get_script_metadata` | Get script metadata and AI summary |
|
|
122
|
+
|
|
123
|
+
### Other
|
|
124
|
+
|
|
125
|
+
| Tool | Description |
|
|
126
|
+
|------|-------------|
|
|
75
127
|
| `kode_site_info` | Get site info and CDN URL |
|
|
128
|
+
| `kode_read_context` | Read AI context file |
|
|
129
|
+
| `kode_update_context` | Update AI context file |
|
|
130
|
+
|
|
131
|
+
## Important: Content Workflow
|
|
132
|
+
|
|
133
|
+
**MCP is the control plane - never send script content through MCP tools.**
|
|
134
|
+
|
|
135
|
+
The correct workflow:
|
|
136
|
+
1. Write script file locally to `.cure-kode-scripts/script-name.js`
|
|
137
|
+
2. Use `kode_push` to upload local files to server
|
|
138
|
+
3. Use `kode_deploy` to deploy
|
|
139
|
+
|
|
140
|
+
```
|
|
141
|
+
AI writes file → kode_push → kode_deploy
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Do NOT** pass content to `kode_create_script` or `kode_update_script` - these only handle metadata.
|
|
145
|
+
|
|
146
|
+
## Safety Features
|
|
147
|
+
|
|
148
|
+
### Production Confirmation
|
|
149
|
+
|
|
150
|
+
`kode_promote` requires explicit confirmation to prevent accidental production deployments:
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
// This will fail:
|
|
154
|
+
kode_promote()
|
|
155
|
+
|
|
156
|
+
// This works:
|
|
157
|
+
kode_promote({ confirmed: true })
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Production Disabled by Default
|
|
161
|
+
|
|
162
|
+
New sites start with production disabled. Must explicitly enable:
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
kode_production_enable()
|
|
166
|
+
// Then can promote
|
|
167
|
+
kode_promote({ confirmed: true })
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Example Usage
|
|
76
171
|
|
|
77
|
-
|
|
172
|
+
### Create and Deploy a Script
|
|
78
173
|
|
|
79
|
-
|
|
174
|
+
```
|
|
175
|
+
1. "Create a new script called tracking.js"
|
|
176
|
+
→ kode_create_script({ name: "tracking", slug: "tracking", type: "javascript" })
|
|
177
|
+
|
|
178
|
+
2. Write the file locally
|
|
179
|
+
→ Write to .cure-kode-scripts/tracking.js
|
|
180
|
+
|
|
181
|
+
3. "Push the changes"
|
|
182
|
+
→ kode_push()
|
|
183
|
+
|
|
184
|
+
4. "Deploy to staging"
|
|
185
|
+
→ kode_deploy()
|
|
186
|
+
|
|
187
|
+
5. "Promote to production"
|
|
188
|
+
→ kode_promote({ confirmed: true })
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Analyze a Page and Add Functionality
|
|
80
192
|
|
|
81
193
|
```
|
|
82
|
-
"
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
"What
|
|
87
|
-
"
|
|
194
|
+
1. "Analyze the homepage"
|
|
195
|
+
→ kode_fetch_html_smart({ url: "https://mysite.com" })
|
|
196
|
+
→ kode_refresh_page({ url: "https://mysite.com" })
|
|
197
|
+
|
|
198
|
+
2. "What sections are on this page?"
|
|
199
|
+
→ kode_get_page_context({ url: "https://mysite.com" })
|
|
200
|
+
|
|
201
|
+
3. "Add a script to animate the hero section"
|
|
202
|
+
→ Create script, write file, push, deploy
|
|
88
203
|
```
|
|
89
204
|
|
|
90
205
|
## How It Works
|
|
@@ -92,88 +207,73 @@ Once configured, you can ask Claude:
|
|
|
92
207
|
```
|
|
93
208
|
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
94
209
|
│ AI Agent │ MCP │ Kode MCP │ REST │ Cure Kode API │
|
|
95
|
-
│ (Claude/etc) │─────▶│ Server │─────▶│ (
|
|
210
|
+
│ (Claude/etc) │─────▶│ Server │─────▶│ (app.cure.no) │
|
|
96
211
|
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
|
97
212
|
│
|
|
98
213
|
▼
|
|
99
214
|
┌─────────────────┐
|
|
100
215
|
│ Local Scripts │
|
|
101
|
-
│
|
|
216
|
+
│(.cure-kode-scripts/)│
|
|
102
217
|
└─────────────────┘
|
|
103
218
|
```
|
|
104
219
|
|
|
105
|
-
1. AI agent calls MCP tools (e.g., `kode_create_script`)
|
|
106
|
-
2. MCP server reads config from `.cure-kode/config.json`
|
|
107
|
-
3. MCP server calls Cure Kode REST API with API key
|
|
108
|
-
4. Results returned to AI agent
|
|
109
|
-
|
|
110
220
|
## Security
|
|
111
221
|
|
|
112
222
|
### API Key Authentication
|
|
113
223
|
|
|
114
|
-
- **
|
|
224
|
+
- **Hashed Storage**: API keys are SHA256/HMAC hashed before server storage
|
|
115
225
|
- **Site-scoped**: Each API key is bound to a specific CDN site
|
|
116
|
-
- **Permission-based**:
|
|
117
|
-
- `read` - List/view scripts and deployments
|
|
118
|
-
- `write` - Create and update scripts
|
|
119
|
-
- `deploy` - Deploy to staging/production
|
|
120
|
-
- `delete` - Delete scripts
|
|
226
|
+
- **Permission-based**: Granular permissions (read, write, deploy, delete)
|
|
121
227
|
- **Expiration**: Keys can have optional expiration dates
|
|
122
228
|
|
|
123
|
-
###
|
|
229
|
+
### CORS Security (v2.6)
|
|
124
230
|
|
|
125
|
-
|
|
126
|
-
-
|
|
127
|
-
-
|
|
231
|
+
Script endpoints restrict CORS to configured domains:
|
|
232
|
+
- Site's domain, staging_domain, production_domain
|
|
233
|
+
- Webflow preview domains (*.webflow.io)
|
|
234
|
+
- Localhost for development
|
|
235
|
+
- **No wildcard CORS** on script endpoints
|
|
128
236
|
|
|
129
|
-
###
|
|
237
|
+
### SSRF Protection
|
|
130
238
|
|
|
131
|
-
|
|
132
|
-
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
- Cloud metadata endpoints (169.254.169.254)
|
|
136
|
-
- Only HTTP/HTTPS protocols allowed
|
|
137
|
-
|
|
138
|
-
### Best Practices
|
|
139
|
-
|
|
140
|
-
- Generate separate API keys for different environments/developers
|
|
141
|
-
- Use read-only keys when full access isn't needed
|
|
142
|
-
- Rotate keys periodically
|
|
143
|
-
- Revoke keys when team members leave
|
|
239
|
+
HTML fetch endpoints block:
|
|
240
|
+
- Private IP ranges (127.0.0.0/8, 10.0.0.0/8, etc.)
|
|
241
|
+
- Cloud metadata endpoints (169.254.169.254)
|
|
242
|
+
- Internal hostnames
|
|
144
243
|
|
|
145
244
|
## Troubleshooting
|
|
146
245
|
|
|
147
246
|
### "Cure Kode not configured"
|
|
148
247
|
|
|
149
|
-
|
|
150
|
-
1. Run `kode init` in your project directory
|
|
151
|
-
2. Set `CURE_KODE_API_KEY` and `CURE_KODE_SITE_ID` environment variables
|
|
248
|
+
Run `kode init` in your project directory to create configuration.
|
|
152
249
|
|
|
153
250
|
### "API key invalid"
|
|
154
251
|
|
|
155
|
-
- Check
|
|
156
|
-
- Verify
|
|
157
|
-
- Ensure
|
|
252
|
+
- Check key starts with `ck_`
|
|
253
|
+
- Verify key hasn't expired
|
|
254
|
+
- Ensure key has required permissions
|
|
158
255
|
|
|
159
|
-
###
|
|
256
|
+
### "Production not enabled"
|
|
160
257
|
|
|
161
|
-
|
|
162
|
-
- Check the MCP server is running: `npx @curenorway/kode-mcp`
|
|
163
|
-
- Verify config file syntax
|
|
258
|
+
Use `kode_production_enable()` before promoting.
|
|
164
259
|
|
|
165
|
-
|
|
260
|
+
### "Promote requires confirmation"
|
|
166
261
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
262
|
+
Add `confirmed: true` parameter:
|
|
263
|
+
```typescript
|
|
264
|
+
kode_promote({ confirmed: true })
|
|
265
|
+
```
|
|
170
266
|
|
|
171
|
-
|
|
172
|
-
pnpm build
|
|
267
|
+
### Tools not appearing in Claude
|
|
173
268
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
269
|
+
1. Restart Claude Code after config changes
|
|
270
|
+
2. Check `.mcp.json` syntax
|
|
271
|
+
3. Verify MCP server runs: `npx @curenorway/kode-mcp`
|
|
272
|
+
|
|
273
|
+
## Requirements
|
|
274
|
+
|
|
275
|
+
- Node.js 18 or later
|
|
276
|
+
- Cure Kode API key (from https://app.cure.no/tools/kode)
|
|
177
277
|
|
|
178
278
|
## License
|
|
179
279
|
|
package/dist/index.js
CHANGED
|
@@ -105,6 +105,15 @@ var KodeApiClient = class {
|
|
|
105
105
|
async getDeploymentStatus(siteId) {
|
|
106
106
|
return this.request(`/api/cdn/sites/${siteId}/deployments/status`);
|
|
107
107
|
}
|
|
108
|
+
async rollback(siteId, environment = "staging") {
|
|
109
|
+
return this.request("/api/cdn/deploy/rollback", {
|
|
110
|
+
method: "POST",
|
|
111
|
+
body: JSON.stringify({
|
|
112
|
+
siteId,
|
|
113
|
+
environment
|
|
114
|
+
})
|
|
115
|
+
});
|
|
116
|
+
}
|
|
108
117
|
// v2.3: Production enabled toggle
|
|
109
118
|
async setProductionEnabled(siteId, enabled, productionDomain) {
|
|
110
119
|
return this.request(`/api/cdn/sites/${siteId}/production`, {
|
|
@@ -408,10 +417,30 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
408
417
|
},
|
|
409
418
|
{
|
|
410
419
|
name: "kode_promote",
|
|
411
|
-
description: "Promote the latest staging deployment to production. Use this after testing on staging.",
|
|
420
|
+
description: "Promote the latest staging deployment to production. Use this after testing on staging. IMPORTANT: Requires confirmed=true to actually promote - this prevents accidental production deployments.",
|
|
412
421
|
inputSchema: {
|
|
413
422
|
type: "object",
|
|
414
|
-
properties: {
|
|
423
|
+
properties: {
|
|
424
|
+
confirmed: {
|
|
425
|
+
type: "boolean",
|
|
426
|
+
description: "Safety confirmation. Must be set to true to proceed with production promotion. If false or missing, returns a preview of what would be promoted."
|
|
427
|
+
}
|
|
428
|
+
},
|
|
429
|
+
required: []
|
|
430
|
+
}
|
|
431
|
+
},
|
|
432
|
+
{
|
|
433
|
+
name: "kode_rollback",
|
|
434
|
+
description: "Rollback to the previous deployment. Copies the previous version back to the active environment. Use this if a deployment caused issues.",
|
|
435
|
+
inputSchema: {
|
|
436
|
+
type: "object",
|
|
437
|
+
properties: {
|
|
438
|
+
environment: {
|
|
439
|
+
type: "string",
|
|
440
|
+
enum: ["staging", "production"],
|
|
441
|
+
description: "Environment to rollback. Default: staging"
|
|
442
|
+
}
|
|
443
|
+
},
|
|
415
444
|
required: []
|
|
416
445
|
}
|
|
417
446
|
},
|
|
@@ -1009,6 +1038,7 @@ Scripts deployed (${scriptSizes.length}):`;
|
|
|
1009
1038
|
};
|
|
1010
1039
|
}
|
|
1011
1040
|
case "kode_promote": {
|
|
1041
|
+
const { confirmed } = args;
|
|
1012
1042
|
const status = await client.getDeploymentStatus(siteId);
|
|
1013
1043
|
if (!status.productionEnabled) {
|
|
1014
1044
|
return {
|
|
@@ -1032,17 +1062,69 @@ Scripts deployed (${scriptSizes.length}):`;
|
|
|
1032
1062
|
isError: true
|
|
1033
1063
|
};
|
|
1034
1064
|
}
|
|
1065
|
+
if (!confirmed) {
|
|
1066
|
+
const stagingVersion = status.staging.lastSuccessful?.version || "unknown";
|
|
1067
|
+
const productionVersion = status.production.lastSuccessful?.version || "(none)";
|
|
1068
|
+
return {
|
|
1069
|
+
content: [
|
|
1070
|
+
{
|
|
1071
|
+
type: "text",
|
|
1072
|
+
text: `\u26A0\uFE0F PRODUCTION PROMOTION CONFIRMATION REQUIRED
|
|
1073
|
+
|
|
1074
|
+
This will deploy to production:
|
|
1075
|
+
Staging version: ${stagingVersion}
|
|
1076
|
+
Current production: ${productionVersion}
|
|
1077
|
+
|
|
1078
|
+
To proceed, call kode_promote with confirmed: true
|
|
1079
|
+
|
|
1080
|
+
Note: Always test on staging first before promoting to production.`
|
|
1081
|
+
}
|
|
1082
|
+
]
|
|
1083
|
+
};
|
|
1084
|
+
}
|
|
1035
1085
|
const deployment = await client.promoteToProduction(siteId);
|
|
1036
1086
|
return {
|
|
1037
1087
|
content: [
|
|
1038
1088
|
{
|
|
1039
1089
|
type: "text",
|
|
1040
|
-
text:
|
|
1090
|
+
text: `\u2705 Promoted ${deployment.version} to production
|
|
1041
1091
|
Status: ${deployment.status}`
|
|
1042
1092
|
}
|
|
1043
1093
|
]
|
|
1044
1094
|
};
|
|
1045
1095
|
}
|
|
1096
|
+
case "kode_rollback": {
|
|
1097
|
+
const { environment = "staging" } = args;
|
|
1098
|
+
if (environment === "production") {
|
|
1099
|
+
const status = await client.getDeploymentStatus(siteId);
|
|
1100
|
+
if (!status.productionEnabled) {
|
|
1101
|
+
return {
|
|
1102
|
+
content: [
|
|
1103
|
+
{
|
|
1104
|
+
type: "text",
|
|
1105
|
+
text: "Cannot rollback production: Production is not enabled for this site."
|
|
1106
|
+
}
|
|
1107
|
+
],
|
|
1108
|
+
isError: true
|
|
1109
|
+
};
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
const result = await client.rollback(siteId, environment);
|
|
1113
|
+
return {
|
|
1114
|
+
content: [
|
|
1115
|
+
{
|
|
1116
|
+
type: "text",
|
|
1117
|
+
text: `\u2705 Rolled back ${environment}
|
|
1118
|
+
|
|
1119
|
+
From: ${result.rolledBackFrom.version}
|
|
1120
|
+
To: ${result.rolledBackTo.version}
|
|
1121
|
+
|
|
1122
|
+
CDN URL: ${result.cdn_url}
|
|
1123
|
+
Duration: ${result.duration_ms}ms`
|
|
1124
|
+
}
|
|
1125
|
+
]
|
|
1126
|
+
};
|
|
1127
|
+
}
|
|
1046
1128
|
case "kode_production_enable": {
|
|
1047
1129
|
const { productionDomain } = args;
|
|
1048
1130
|
const result = await client.setProductionEnabled(siteId, true, productionDomain);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@curenorway/kode-mcp",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "MCP server for Cure Kode - enables AI agents to manage Webflow scripts",
|
|
3
|
+
"version": "1.4.0",
|
|
4
|
+
"description": "MCP server for Cure Kode CDN - enables AI agents to manage, deploy, and analyze Webflow scripts",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"cure-kode-mcp": "./dist/index.js"
|