fastmode-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.
- package/README.md +561 -0
- package/bin/run.js +50 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +802 -0
- package/dist/lib/api-client.d.ts +81 -0
- package/dist/lib/api-client.d.ts.map +1 -0
- package/dist/lib/api-client.js +237 -0
- package/dist/lib/auth-state.d.ts +13 -0
- package/dist/lib/auth-state.d.ts.map +1 -0
- package/dist/lib/auth-state.js +24 -0
- package/dist/lib/context-fetcher.d.ts +67 -0
- package/dist/lib/context-fetcher.d.ts.map +1 -0
- package/dist/lib/context-fetcher.js +190 -0
- package/dist/lib/credentials.d.ts +52 -0
- package/dist/lib/credentials.d.ts.map +1 -0
- package/dist/lib/credentials.js +196 -0
- package/dist/lib/device-flow.d.ts +14 -0
- package/dist/lib/device-flow.d.ts.map +1 -0
- package/dist/lib/device-flow.js +244 -0
- package/dist/tools/cms-items.d.ts +56 -0
- package/dist/tools/cms-items.d.ts.map +1 -0
- package/dist/tools/cms-items.js +376 -0
- package/dist/tools/create-site.d.ts +9 -0
- package/dist/tools/create-site.d.ts.map +1 -0
- package/dist/tools/create-site.js +202 -0
- package/dist/tools/deploy-package.d.ts +9 -0
- package/dist/tools/deploy-package.d.ts.map +1 -0
- package/dist/tools/deploy-package.js +434 -0
- package/dist/tools/generate-samples.d.ts +19 -0
- package/dist/tools/generate-samples.d.ts.map +1 -0
- package/dist/tools/generate-samples.js +272 -0
- package/dist/tools/get-conversion-guide.d.ts +7 -0
- package/dist/tools/get-conversion-guide.d.ts.map +1 -0
- package/dist/tools/get-conversion-guide.js +1323 -0
- package/dist/tools/get-example.d.ts +7 -0
- package/dist/tools/get-example.d.ts.map +1 -0
- package/dist/tools/get-example.js +1568 -0
- package/dist/tools/get-field-types.d.ts +30 -0
- package/dist/tools/get-field-types.d.ts.map +1 -0
- package/dist/tools/get-field-types.js +154 -0
- package/dist/tools/get-schema.d.ts +5 -0
- package/dist/tools/get-schema.d.ts.map +1 -0
- package/dist/tools/get-schema.js +320 -0
- package/dist/tools/get-started.d.ts +21 -0
- package/dist/tools/get-started.d.ts.map +1 -0
- package/dist/tools/get-started.js +624 -0
- package/dist/tools/get-tenant-schema.d.ts +18 -0
- package/dist/tools/get-tenant-schema.d.ts.map +1 -0
- package/dist/tools/get-tenant-schema.js +158 -0
- package/dist/tools/list-projects.d.ts +5 -0
- package/dist/tools/list-projects.d.ts.map +1 -0
- package/dist/tools/list-projects.js +101 -0
- package/dist/tools/sync-schema.d.ts +41 -0
- package/dist/tools/sync-schema.d.ts.map +1 -0
- package/dist/tools/sync-schema.js +483 -0
- package/dist/tools/validate-manifest.d.ts +5 -0
- package/dist/tools/validate-manifest.d.ts.map +1 -0
- package/dist/tools/validate-manifest.js +311 -0
- package/dist/tools/validate-package.d.ts +5 -0
- package/dist/tools/validate-package.d.ts.map +1 -0
- package/dist/tools/validate-package.js +337 -0
- package/dist/tools/validate-template.d.ts +12 -0
- package/dist/tools/validate-template.d.ts.map +1 -0
- package/dist/tools/validate-template.js +790 -0
- package/package.json +54 -0
- package/scripts/postinstall.js +129 -0
|
@@ -0,0 +1,624 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Get Started Tool
|
|
4
|
+
*
|
|
5
|
+
* Intelligent entry point for the MCP server that performs:
|
|
6
|
+
* 1. State Detection - Understand project state automatically
|
|
7
|
+
* 2. Intent Inference - Determine what user wants to do
|
|
8
|
+
* 3. Guided Execution - Provide exact tool calls with real values
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.getStarted = getStarted;
|
|
12
|
+
const context_fetcher_1 = require("../lib/context-fetcher");
|
|
13
|
+
const device_flow_1 = require("../lib/device-flow");
|
|
14
|
+
const api_client_1 = require("../lib/api-client");
|
|
15
|
+
// ============ Response Builders ============
|
|
16
|
+
/**
|
|
17
|
+
* Build the explore response - overview of all projects
|
|
18
|
+
*/
|
|
19
|
+
function buildExploreResponse(context) {
|
|
20
|
+
let output = `# Fast Mode MCP - Project Overview
|
|
21
|
+
|
|
22
|
+
## Authentication
|
|
23
|
+
Status: ✓ Authenticated
|
|
24
|
+
|
|
25
|
+
`;
|
|
26
|
+
if (context.projects.length === 0) {
|
|
27
|
+
output += `## No Projects Yet
|
|
28
|
+
|
|
29
|
+
You don't have any projects. Let's create one!
|
|
30
|
+
|
|
31
|
+
### Create Your First Project
|
|
32
|
+
\`\`\`
|
|
33
|
+
create_site(name: "My Website")
|
|
34
|
+
\`\`\`
|
|
35
|
+
|
|
36
|
+
Or get help converting an existing website:
|
|
37
|
+
\`\`\`
|
|
38
|
+
get_started(intent: "convert")
|
|
39
|
+
\`\`\`
|
|
40
|
+
`;
|
|
41
|
+
return output;
|
|
42
|
+
}
|
|
43
|
+
output += `## Your Projects (${context.projects.length})
|
|
44
|
+
|
|
45
|
+
| Project | URL | Collections | Items | Status |
|
|
46
|
+
|---------|-----|-------------|-------|--------|
|
|
47
|
+
`;
|
|
48
|
+
for (const project of context.projects) {
|
|
49
|
+
const url = project.customDomain || `${project.subdomain}.fastmode.ai`;
|
|
50
|
+
output += `| ${project.name} | ${url} | ${project.collectionCount} | ${project.totalItems} | ${project.status} |\n`;
|
|
51
|
+
}
|
|
52
|
+
output += `
|
|
53
|
+
## Quick Actions
|
|
54
|
+
|
|
55
|
+
`;
|
|
56
|
+
// Suggest actions based on project state
|
|
57
|
+
const firstProject = context.projects[0];
|
|
58
|
+
output += `### See project details
|
|
59
|
+
\`\`\`
|
|
60
|
+
get_started(intent: "explore", projectId: "${firstProject.id}")
|
|
61
|
+
\`\`\`
|
|
62
|
+
|
|
63
|
+
### Add content
|
|
64
|
+
\`\`\`
|
|
65
|
+
get_started(intent: "add_content", projectId: "${firstProject.id}")
|
|
66
|
+
\`\`\`
|
|
67
|
+
|
|
68
|
+
### Update schema (add collections/fields)
|
|
69
|
+
\`\`\`
|
|
70
|
+
get_started(intent: "update_schema", projectId: "${firstProject.id}")
|
|
71
|
+
\`\`\`
|
|
72
|
+
|
|
73
|
+
### Deploy a new website
|
|
74
|
+
\`\`\`
|
|
75
|
+
get_started(intent: "deploy", projectId: "${firstProject.id}")
|
|
76
|
+
\`\`\`
|
|
77
|
+
|
|
78
|
+
### Create a new site from scratch
|
|
79
|
+
\`\`\`
|
|
80
|
+
get_started(intent: "convert")
|
|
81
|
+
\`\`\`
|
|
82
|
+
|
|
83
|
+
## Available Intents
|
|
84
|
+
|
|
85
|
+
| Intent | Description |
|
|
86
|
+
|--------|-------------|
|
|
87
|
+
| \`explore\` | See what projects and content exist |
|
|
88
|
+
| \`add_content\` | Create/edit CMS items (blog posts, team, etc.) |
|
|
89
|
+
| \`update_schema\` | Add collections or fields |
|
|
90
|
+
| \`convert\` | Build a new website from scratch |
|
|
91
|
+
| \`deploy\` | Push changes to an existing site |
|
|
92
|
+
`;
|
|
93
|
+
return output;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Build the add_content response with schema details
|
|
97
|
+
*/
|
|
98
|
+
function buildAddContentResponse(project) {
|
|
99
|
+
let output = `# Fast Mode MCP - Add Content
|
|
100
|
+
|
|
101
|
+
## Project: ${project.name}
|
|
102
|
+
**URL:** https://${project.subdomain}.fastmode.ai
|
|
103
|
+
**Status:** ${project.status}
|
|
104
|
+
|
|
105
|
+
`;
|
|
106
|
+
if (project.collections.length === 0) {
|
|
107
|
+
output += `## No Collections Yet
|
|
108
|
+
|
|
109
|
+
This project doesn't have any collections. Create collections first:
|
|
110
|
+
\`\`\`
|
|
111
|
+
get_started(intent: "update_schema", projectId: "${project.id}")
|
|
112
|
+
\`\`\`
|
|
113
|
+
`;
|
|
114
|
+
return output;
|
|
115
|
+
}
|
|
116
|
+
output += `## Collections
|
|
117
|
+
|
|
118
|
+
`;
|
|
119
|
+
for (const collection of project.collections) {
|
|
120
|
+
output += buildCollectionTable(collection);
|
|
121
|
+
}
|
|
122
|
+
output += `---
|
|
123
|
+
|
|
124
|
+
## Workflow: Add Content
|
|
125
|
+
|
|
126
|
+
### Step 1: See existing content
|
|
127
|
+
\`\`\`
|
|
128
|
+
list_cms_items(projectId: "${project.id}", collectionSlug: "${project.collections[0]?.slug || 'posts'}")
|
|
129
|
+
\`\`\`
|
|
130
|
+
|
|
131
|
+
### Step 2: Create new item
|
|
132
|
+
\`\`\`
|
|
133
|
+
create_cms_item(
|
|
134
|
+
projectId: "${project.id}",
|
|
135
|
+
collectionSlug: "${project.collections[0]?.slug || 'posts'}",
|
|
136
|
+
name: "Item Title",
|
|
137
|
+
data: {
|
|
138
|
+
${buildExampleData(project.collections[0])}
|
|
139
|
+
}
|
|
140
|
+
)
|
|
141
|
+
\`\`\`
|
|
142
|
+
|
|
143
|
+
### Step 3: Update existing item
|
|
144
|
+
\`\`\`
|
|
145
|
+
update_cms_item(
|
|
146
|
+
projectId: "${project.id}",
|
|
147
|
+
collectionSlug: "${project.collections[0]?.slug || 'posts'}",
|
|
148
|
+
itemSlug: "existing-item-slug",
|
|
149
|
+
data: { fieldToUpdate: "new value" }
|
|
150
|
+
)
|
|
151
|
+
\`\`\`
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## ⚠️ Common Mistakes to Avoid
|
|
156
|
+
|
|
157
|
+
### Rich text fields
|
|
158
|
+
Rich text fields (type: \`richText\`) accept HTML content:
|
|
159
|
+
\`\`\`
|
|
160
|
+
data: { body: "<p>Your content with <strong>formatting</strong></p>" }
|
|
161
|
+
\`\`\`
|
|
162
|
+
|
|
163
|
+
### Relation fields
|
|
164
|
+
Relation fields require the **ID** of the related item, not the name:
|
|
165
|
+
\`\`\`
|
|
166
|
+
// WRONG:
|
|
167
|
+
data: { author: "John Smith" }
|
|
168
|
+
|
|
169
|
+
// CORRECT:
|
|
170
|
+
data: { author: "abc-123-uuid-of-john" }
|
|
171
|
+
\`\`\`
|
|
172
|
+
|
|
173
|
+
To get the ID, first list items in the related collection:
|
|
174
|
+
\`\`\`
|
|
175
|
+
list_cms_items(projectId: "${project.id}", collectionSlug: "authors")
|
|
176
|
+
\`\`\`
|
|
177
|
+
|
|
178
|
+
### Delete requires confirmation
|
|
179
|
+
Always ask the user before deleting:
|
|
180
|
+
\`\`\`
|
|
181
|
+
delete_cms_item(projectId: "...", collectionSlug: "...", itemSlug: "...", confirmDelete: true)
|
|
182
|
+
\`\`\`
|
|
183
|
+
`;
|
|
184
|
+
return output;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Build a table for a collection's fields
|
|
188
|
+
*/
|
|
189
|
+
function buildCollectionTable(collection) {
|
|
190
|
+
let output = `### ${collection.name} (${collection.itemCount} items)
|
|
191
|
+
|
|
192
|
+
| Field | Type | Required | Token |
|
|
193
|
+
|-------|------|----------|-------|
|
|
194
|
+
`;
|
|
195
|
+
for (const field of collection.fields) {
|
|
196
|
+
const token = field.type === 'richText'
|
|
197
|
+
? `\`{{{${field.slug}}}}\``
|
|
198
|
+
: field.type === 'relation'
|
|
199
|
+
? `\`{{${field.slug}.name}}\``
|
|
200
|
+
: `\`{{${field.slug}}}\``;
|
|
201
|
+
const typeDisplay = field.type === 'relation' && field.referenceCollection
|
|
202
|
+
? `relation→${field.referenceCollection}`
|
|
203
|
+
: field.type;
|
|
204
|
+
output += `| ${field.name} | ${typeDisplay} | ${field.isRequired ? 'yes' : 'no'} | ${token} |\n`;
|
|
205
|
+
}
|
|
206
|
+
output += '\n';
|
|
207
|
+
return output;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Build example data object for a collection
|
|
211
|
+
*/
|
|
212
|
+
function buildExampleData(collection) {
|
|
213
|
+
if (!collection || collection.fields.length === 0) {
|
|
214
|
+
return ' // Add your field values here';
|
|
215
|
+
}
|
|
216
|
+
const lines = [];
|
|
217
|
+
for (const field of collection.fields.slice(0, 5)) {
|
|
218
|
+
let exampleValue;
|
|
219
|
+
switch (field.type) {
|
|
220
|
+
case 'text':
|
|
221
|
+
exampleValue = `"Your ${field.name.toLowerCase()}"`;
|
|
222
|
+
break;
|
|
223
|
+
case 'richText':
|
|
224
|
+
exampleValue = `"<p>Your ${field.name.toLowerCase()} content here...</p>"`;
|
|
225
|
+
break;
|
|
226
|
+
case 'number':
|
|
227
|
+
exampleValue = '0';
|
|
228
|
+
break;
|
|
229
|
+
case 'boolean':
|
|
230
|
+
exampleValue = 'true';
|
|
231
|
+
break;
|
|
232
|
+
case 'image':
|
|
233
|
+
case 'url':
|
|
234
|
+
exampleValue = '"https://example.com/..."';
|
|
235
|
+
break;
|
|
236
|
+
case 'relation':
|
|
237
|
+
exampleValue = '"RELATED_ITEM_ID" // Get ID from list_cms_items';
|
|
238
|
+
break;
|
|
239
|
+
default:
|
|
240
|
+
exampleValue = `"..."`;
|
|
241
|
+
}
|
|
242
|
+
lines.push(` ${field.slug}: ${exampleValue}`);
|
|
243
|
+
}
|
|
244
|
+
return lines.join(',\n');
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Build the update_schema response
|
|
248
|
+
*/
|
|
249
|
+
function buildUpdateSchemaResponse(project) {
|
|
250
|
+
let output = `# Fast Mode MCP - Update Schema
|
|
251
|
+
|
|
252
|
+
## Project: ${project.name}
|
|
253
|
+
**Current Collections:** ${project.collections.map(c => c.slug).join(', ') || 'none'}
|
|
254
|
+
|
|
255
|
+
`;
|
|
256
|
+
if (project.collections.length > 0) {
|
|
257
|
+
output += `## Current Schema Summary
|
|
258
|
+
|
|
259
|
+
| Collection | Fields | Items |
|
|
260
|
+
|------------|--------|-------|
|
|
261
|
+
`;
|
|
262
|
+
for (const col of project.collections) {
|
|
263
|
+
const fieldNames = col.fields.slice(0, 4).map(f => f.slug).join(', ');
|
|
264
|
+
const more = col.fields.length > 4 ? ` +${col.fields.length - 4} more` : '';
|
|
265
|
+
output += `| ${col.slug} | ${fieldNames}${more} | ${col.itemCount} |\n`;
|
|
266
|
+
}
|
|
267
|
+
output += '\n';
|
|
268
|
+
}
|
|
269
|
+
output += `---
|
|
270
|
+
|
|
271
|
+
## Workflow: Add New Schema
|
|
272
|
+
|
|
273
|
+
### Option A: Add fields to existing collection
|
|
274
|
+
\`\`\`
|
|
275
|
+
sync_schema(
|
|
276
|
+
projectId: "${project.id}",
|
|
277
|
+
fieldsToAdd: [{
|
|
278
|
+
collectionSlug: "${project.collections[0]?.slug || 'posts'}",
|
|
279
|
+
fields: [
|
|
280
|
+
{ slug: "new_field", name: "New Field", type: "text" },
|
|
281
|
+
{ slug: "featured", name: "Featured", type: "boolean" }
|
|
282
|
+
]
|
|
283
|
+
}]
|
|
284
|
+
)
|
|
285
|
+
\`\`\`
|
|
286
|
+
|
|
287
|
+
### Option B: Create new collection
|
|
288
|
+
\`\`\`
|
|
289
|
+
sync_schema(
|
|
290
|
+
projectId: "${project.id}",
|
|
291
|
+
collections: [{
|
|
292
|
+
slug: "testimonials",
|
|
293
|
+
name: "Testimonials",
|
|
294
|
+
nameSingular: "Testimonial",
|
|
295
|
+
fields: [
|
|
296
|
+
{ slug: "quote", name: "Quote", type: "richText" },
|
|
297
|
+
{ slug: "company", name: "Company", type: "text" },
|
|
298
|
+
{ slug: "photo", name: "Photo", type: "image" }
|
|
299
|
+
]
|
|
300
|
+
}]
|
|
301
|
+
)
|
|
302
|
+
\`\`\`
|
|
303
|
+
|
|
304
|
+
### After creating schema, optionally add sample content:
|
|
305
|
+
\`\`\`
|
|
306
|
+
generate_sample_items(projectId: "${project.id}", collectionSlugs: ["testimonials"])
|
|
307
|
+
\`\`\`
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
## ⚠️ Field Type Guidance
|
|
312
|
+
|
|
313
|
+
### For Video Content
|
|
314
|
+
Use \`videoEmbed\` (NOT \`url\` or \`text\`):
|
|
315
|
+
\`\`\`json
|
|
316
|
+
{ "slug": "video", "name": "Video", "type": "videoEmbed" }
|
|
317
|
+
\`\`\`
|
|
318
|
+
Supports: YouTube, Vimeo, Wistia, Loom
|
|
319
|
+
|
|
320
|
+
### For Linked Content
|
|
321
|
+
Use \`relation\` (NOT \`text\`):
|
|
322
|
+
\`\`\`json
|
|
323
|
+
{
|
|
324
|
+
"slug": "author",
|
|
325
|
+
"name": "Author",
|
|
326
|
+
"type": "relation",
|
|
327
|
+
"referenceCollection": "authors"
|
|
328
|
+
}
|
|
329
|
+
\`\`\`
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
333
|
+
## Available Field Types
|
|
334
|
+
|
|
335
|
+
| Type | Description | Token Usage |
|
|
336
|
+
|------|-------------|-------------|
|
|
337
|
+
| text | Short text | \`{{field}}\` |
|
|
338
|
+
| richText | HTML content | \`{{{field}}}\` (triple braces!) |
|
|
339
|
+
| number | Numeric value | \`{{field}}\` |
|
|
340
|
+
| boolean | True/false | \`{{#if field}}...{{/if}}\` |
|
|
341
|
+
| date | Date picker | \`{{field}}\` |
|
|
342
|
+
| image | Image URL | \`{{field}}\` in src |
|
|
343
|
+
| url | Web link | \`{{field}}\` in href |
|
|
344
|
+
| email | Email address | \`{{field}}\` |
|
|
345
|
+
| videoEmbed | YouTube/Vimeo/etc | \`{{#videoEmbed field}}{{/videoEmbed}}\` |
|
|
346
|
+
| select | Single choice | \`{{field}}\` (requires \`options\`) |
|
|
347
|
+
| multiSelect | Multiple choices | \`{{#each field}}...{{/each}}\` |
|
|
348
|
+
| relation | Link to collection | \`{{field.name}}\`, \`{{field.url}}\` |
|
|
349
|
+
`;
|
|
350
|
+
return output;
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Build the convert response for new websites
|
|
354
|
+
*/
|
|
355
|
+
function buildConvertResponse(context) {
|
|
356
|
+
let output = `# Fast Mode MCP - Convert Website
|
|
357
|
+
|
|
358
|
+
## Getting Started
|
|
359
|
+
|
|
360
|
+
`;
|
|
361
|
+
if (context.projects.length > 0) {
|
|
362
|
+
output += `### Your existing projects:
|
|
363
|
+
`;
|
|
364
|
+
for (const p of context.projects.slice(0, 5)) {
|
|
365
|
+
output += `- ${p.name} (\`${p.id}\`)\n`;
|
|
366
|
+
}
|
|
367
|
+
output += `
|
|
368
|
+
**Ask the user:** "Should I add this website to an existing project, or create a new one?"
|
|
369
|
+
|
|
370
|
+
`;
|
|
371
|
+
}
|
|
372
|
+
output += `### To create a new project:
|
|
373
|
+
\`\`\`
|
|
374
|
+
create_site(name: "New Website Name")
|
|
375
|
+
\`\`\`
|
|
376
|
+
|
|
377
|
+
---
|
|
378
|
+
|
|
379
|
+
## ⚠️ REQUIRED: Read Before Building
|
|
380
|
+
|
|
381
|
+
**DO NOT SKIP THIS STEP.** The conversion guide contains CRITICAL information that prevents common failures:
|
|
382
|
+
|
|
383
|
+
### Step 1: Read common mistakes FIRST
|
|
384
|
+
\`\`\`
|
|
385
|
+
get_conversion_guide(section: "common_mistakes")
|
|
386
|
+
\`\`\`
|
|
387
|
+
|
|
388
|
+
This section covers:
|
|
389
|
+
- **Asset paths** - Why CSS/JS might 404 (MUST use /public/ prefix!)
|
|
390
|
+
- **Form handling** - Why forms might not work (MUST remove original handlers!)
|
|
391
|
+
- **data-edit-key** - Why text won't be editable (REQUIRED for static pages!)
|
|
392
|
+
|
|
393
|
+
### Step 2: Read the full guide
|
|
394
|
+
\`\`\`
|
|
395
|
+
get_conversion_guide(section: "full")
|
|
396
|
+
\`\`\`
|
|
397
|
+
|
|
398
|
+
All sections:
|
|
399
|
+
- \`first_steps\` - Required initial setup
|
|
400
|
+
- \`structure\` - Package folder structure
|
|
401
|
+
- \`manifest\` - manifest.json configuration
|
|
402
|
+
- \`templates\` - Template creation patterns
|
|
403
|
+
- \`tokens\` - CMS token reference
|
|
404
|
+
- \`forms\` - Form submission setup
|
|
405
|
+
- \`common_mistakes\` - Critical errors to avoid
|
|
406
|
+
|
|
407
|
+
### Step 2: Build and validate as you go
|
|
408
|
+
\`\`\`
|
|
409
|
+
validate_manifest(manifest: "{ ... }")
|
|
410
|
+
validate_template(html: "...", templateType: "custom_index", collectionSlug: "posts")
|
|
411
|
+
validate_package(fileList: [...], manifestContent: "...")
|
|
412
|
+
\`\`\`
|
|
413
|
+
|
|
414
|
+
### Step 3: Create schema (if new collections needed)
|
|
415
|
+
\`\`\`
|
|
416
|
+
sync_schema(projectId: "PROJECT_ID", collections: [...])
|
|
417
|
+
\`\`\`
|
|
418
|
+
|
|
419
|
+
### Step 4: Deploy
|
|
420
|
+
\`\`\`
|
|
421
|
+
deploy_package(packagePath: "./my-site.zip", projectId: "PROJECT_ID")
|
|
422
|
+
\`\`\`
|
|
423
|
+
|
|
424
|
+
---
|
|
425
|
+
|
|
426
|
+
## Key Resources
|
|
427
|
+
|
|
428
|
+
| Example | Description |
|
|
429
|
+
|---------|-------------|
|
|
430
|
+
| \`get_example("manifest_basic")\` | Basic manifest.json |
|
|
431
|
+
| \`get_example("blog_post_template")\` | Blog post detail template |
|
|
432
|
+
| \`get_example("blog_index_template")\` | Blog listing template |
|
|
433
|
+
| \`get_example("form_handling")\` | Form submission setup |
|
|
434
|
+
| \`get_example("common_mistakes")\` | What to avoid |
|
|
435
|
+
| \`get_example("relation_fields")\` | Linking collections |
|
|
436
|
+
`;
|
|
437
|
+
return output;
|
|
438
|
+
}
|
|
439
|
+
/**
|
|
440
|
+
* Build the deploy response
|
|
441
|
+
*/
|
|
442
|
+
function buildDeployResponse(project) {
|
|
443
|
+
let output = `# Fast Mode MCP - Deploy Changes
|
|
444
|
+
|
|
445
|
+
## Project: ${project.name}
|
|
446
|
+
**URL:** https://${project.subdomain}.fastmode.ai
|
|
447
|
+
**Status:** ${project.status}
|
|
448
|
+
|
|
449
|
+
## Pre-Deploy Checklist
|
|
450
|
+
|
|
451
|
+
`;
|
|
452
|
+
if (project.githubConnected) {
|
|
453
|
+
output += `⚠️ **GitHub Connected:** Yes
|
|
454
|
+
Consider pushing to GitHub instead for automatic deployment.
|
|
455
|
+
|
|
456
|
+
`;
|
|
457
|
+
}
|
|
458
|
+
else {
|
|
459
|
+
output += `✓ **GitHub Connected:** No (manual deploy available)
|
|
460
|
+
|
|
461
|
+
`;
|
|
462
|
+
}
|
|
463
|
+
if (project.hasPendingChanges) {
|
|
464
|
+
output += `⚠️ **Pending Changes:** Yes
|
|
465
|
+
There are unsaved changes in the editor.
|
|
466
|
+
|
|
467
|
+
`;
|
|
468
|
+
}
|
|
469
|
+
else {
|
|
470
|
+
output += `✓ **Pending Changes:** None
|
|
471
|
+
|
|
472
|
+
`;
|
|
473
|
+
}
|
|
474
|
+
output += `---
|
|
475
|
+
|
|
476
|
+
## Workflow: Deploy
|
|
477
|
+
|
|
478
|
+
### Step 1: Validate your package first
|
|
479
|
+
\`\`\`
|
|
480
|
+
validate_package(
|
|
481
|
+
fileList: ["manifest.json", "pages/index.html", "public/css/style.css", ...],
|
|
482
|
+
manifestContent: "{ ... }"
|
|
483
|
+
)
|
|
484
|
+
\`\`\`
|
|
485
|
+
|
|
486
|
+
### Step 2: If validation passes, deploy
|
|
487
|
+
\`\`\`
|
|
488
|
+
deploy_package(
|
|
489
|
+
packagePath: "./my-site.zip",
|
|
490
|
+
projectId: "${project.id}"
|
|
491
|
+
)
|
|
492
|
+
\`\`\`
|
|
493
|
+
|
|
494
|
+
---
|
|
495
|
+
|
|
496
|
+
## Deployment Notes
|
|
497
|
+
|
|
498
|
+
- **Pre-deploy validation:** deploy_package now validates automatically and blocks if there are errors
|
|
499
|
+
- **Incremental deploys:** CMS item changes trigger automatic page rebuilds
|
|
500
|
+
- **Full deploys:** Package uploads trigger full site rebuild
|
|
501
|
+
- **CDN cache:** Automatically purged after successful deploy
|
|
502
|
+
`;
|
|
503
|
+
return output;
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Build unauthenticated response
|
|
507
|
+
*/
|
|
508
|
+
function buildUnauthenticatedResponse() {
|
|
509
|
+
return `# Fast Mode MCP - Authentication Required
|
|
510
|
+
|
|
511
|
+
You need to authenticate before using Fast Mode tools.
|
|
512
|
+
|
|
513
|
+
## How to Authenticate
|
|
514
|
+
|
|
515
|
+
### Option 1: Environment Variable (Recommended for CI/CD)
|
|
516
|
+
Set the \`FASTMODE_AUTH_TOKEN\` environment variable with your API token.
|
|
517
|
+
|
|
518
|
+
### Option 2: Browser Login
|
|
519
|
+
Run any authenticated command (like \`list_projects\`) and follow the browser-based login flow.
|
|
520
|
+
|
|
521
|
+
## Try It Now
|
|
522
|
+
\`\`\`
|
|
523
|
+
list_projects()
|
|
524
|
+
\`\`\`
|
|
525
|
+
|
|
526
|
+
This will prompt you to authenticate if needed.
|
|
527
|
+
|
|
528
|
+
## After Authentication
|
|
529
|
+
|
|
530
|
+
Call \`get_started()\` again to see your projects and available actions.
|
|
531
|
+
`;
|
|
532
|
+
}
|
|
533
|
+
// ============ Main Function ============
|
|
534
|
+
/**
|
|
535
|
+
* Get Started - Intelligent entry point for the MCP server
|
|
536
|
+
*
|
|
537
|
+
* @param input.intent - What the user wants to do (explore, add_content, update_schema, convert, deploy)
|
|
538
|
+
* @param input.projectId - Specific project to get details for
|
|
539
|
+
*/
|
|
540
|
+
async function getStarted(input) {
|
|
541
|
+
const { intent, projectId } = input;
|
|
542
|
+
// Check authentication first
|
|
543
|
+
if (await (0, api_client_1.needsAuthentication)()) {
|
|
544
|
+
// Try to authenticate
|
|
545
|
+
const authResult = await (0, device_flow_1.ensureAuthenticated)();
|
|
546
|
+
if (!authResult.authenticated) {
|
|
547
|
+
return buildUnauthenticatedResponse();
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
// Fetch project context
|
|
551
|
+
const context = await (0, context_fetcher_1.fetchProjectContext)(projectId);
|
|
552
|
+
if (!context.isAuthenticated) {
|
|
553
|
+
return buildUnauthenticatedResponse();
|
|
554
|
+
}
|
|
555
|
+
// Route based on intent
|
|
556
|
+
switch (intent) {
|
|
557
|
+
case 'add_content':
|
|
558
|
+
if (!context.selectedProject) {
|
|
559
|
+
if (!projectId) {
|
|
560
|
+
return `# Project Required
|
|
561
|
+
|
|
562
|
+
To add content, specify which project:
|
|
563
|
+
\`\`\`
|
|
564
|
+
get_started(intent: "add_content", projectId: "your-project-id")
|
|
565
|
+
\`\`\`
|
|
566
|
+
|
|
567
|
+
${buildExploreResponse(context)}`;
|
|
568
|
+
}
|
|
569
|
+
return `# Project Not Found
|
|
570
|
+
|
|
571
|
+
Could not find project: "${projectId}"
|
|
572
|
+
|
|
573
|
+
Use \`list_projects\` to see available projects.`;
|
|
574
|
+
}
|
|
575
|
+
return buildAddContentResponse(context.selectedProject);
|
|
576
|
+
case 'update_schema':
|
|
577
|
+
if (!context.selectedProject) {
|
|
578
|
+
if (!projectId) {
|
|
579
|
+
return `# Project Required
|
|
580
|
+
|
|
581
|
+
To update schema, specify which project:
|
|
582
|
+
\`\`\`
|
|
583
|
+
get_started(intent: "update_schema", projectId: "your-project-id")
|
|
584
|
+
\`\`\`
|
|
585
|
+
|
|
586
|
+
${buildExploreResponse(context)}`;
|
|
587
|
+
}
|
|
588
|
+
return `# Project Not Found
|
|
589
|
+
|
|
590
|
+
Could not find project: "${projectId}"
|
|
591
|
+
|
|
592
|
+
Use \`list_projects\` to see available projects.`;
|
|
593
|
+
}
|
|
594
|
+
return buildUpdateSchemaResponse(context.selectedProject);
|
|
595
|
+
case 'convert':
|
|
596
|
+
return buildConvertResponse(context);
|
|
597
|
+
case 'deploy':
|
|
598
|
+
if (!context.selectedProject) {
|
|
599
|
+
if (!projectId) {
|
|
600
|
+
return `# Project Required
|
|
601
|
+
|
|
602
|
+
To deploy, specify which project:
|
|
603
|
+
\`\`\`
|
|
604
|
+
get_started(intent: "deploy", projectId: "your-project-id")
|
|
605
|
+
\`\`\`
|
|
606
|
+
|
|
607
|
+
${buildExploreResponse(context)}`;
|
|
608
|
+
}
|
|
609
|
+
return `# Project Not Found
|
|
610
|
+
|
|
611
|
+
Could not find project: "${projectId}"
|
|
612
|
+
|
|
613
|
+
Use \`list_projects\` to see available projects.`;
|
|
614
|
+
}
|
|
615
|
+
return buildDeployResponse(context.selectedProject);
|
|
616
|
+
case 'explore':
|
|
617
|
+
default:
|
|
618
|
+
// If projectId provided, show detailed project info
|
|
619
|
+
if (context.selectedProject) {
|
|
620
|
+
return buildAddContentResponse(context.selectedProject);
|
|
621
|
+
}
|
|
622
|
+
return buildExploreResponse(context);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fetches the complete schema for a specific project including:
|
|
3
|
+
* - All custom collections with their fields
|
|
4
|
+
* - Field tokens, types, and descriptions for AI context
|
|
5
|
+
* - Template patterns and example usage
|
|
6
|
+
*
|
|
7
|
+
* Each field includes:
|
|
8
|
+
* - Field Name (display name)
|
|
9
|
+
* - Token (the exact syntax to use in templates)
|
|
10
|
+
* - Type (text, richText, image, etc.)
|
|
11
|
+
* - Description (help text for context)
|
|
12
|
+
*
|
|
13
|
+
* Uses stored credentials or triggers device flow for authentication.
|
|
14
|
+
*
|
|
15
|
+
* @param projectId - Project ID (UUID) or project name
|
|
16
|
+
*/
|
|
17
|
+
export declare function getTenantSchema(projectId: string): Promise<string>;
|
|
18
|
+
//# sourceMappingURL=get-tenant-schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-tenant-schema.d.ts","sourceRoot":"","sources":["../../src/tools/get-tenant-schema.ts"],"names":[],"mappings":"AA2EA;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAmFxE"}
|