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,158 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getTenantSchema = getTenantSchema;
|
|
4
|
+
const api_client_1 = require("../lib/api-client");
|
|
5
|
+
const device_flow_1 = require("../lib/device-flow");
|
|
6
|
+
/**
|
|
7
|
+
* Resolve a project identifier to a tenant ID
|
|
8
|
+
* Accepts either a UUID or a project name
|
|
9
|
+
*/
|
|
10
|
+
async function resolveProjectId(projectIdentifier) {
|
|
11
|
+
// Check if it looks like a UUID
|
|
12
|
+
const uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
13
|
+
if (uuidPattern.test(projectIdentifier)) {
|
|
14
|
+
// It's already a UUID, use it directly
|
|
15
|
+
return { tenantId: projectIdentifier };
|
|
16
|
+
}
|
|
17
|
+
// Otherwise, look up by name using /api/tenants
|
|
18
|
+
const response = await (0, api_client_1.apiRequest)('/api/tenants');
|
|
19
|
+
if ((0, api_client_1.isApiError)(response)) {
|
|
20
|
+
return { error: `Failed to look up project: ${response.error}` };
|
|
21
|
+
}
|
|
22
|
+
const projects = response.data;
|
|
23
|
+
// Find by exact name match (case-insensitive)
|
|
24
|
+
const match = projects.find(p => p.name.toLowerCase() === projectIdentifier.toLowerCase());
|
|
25
|
+
if (match) {
|
|
26
|
+
return { tenantId: match.id };
|
|
27
|
+
}
|
|
28
|
+
// Try partial match
|
|
29
|
+
const partialMatch = projects.find(p => p.name.toLowerCase().includes(projectIdentifier.toLowerCase()));
|
|
30
|
+
if (partialMatch) {
|
|
31
|
+
return { tenantId: partialMatch.id };
|
|
32
|
+
}
|
|
33
|
+
// List available projects for the user
|
|
34
|
+
const availableProjects = projects.map(p => `- ${p.name} (${p.id})`).join('\n');
|
|
35
|
+
return {
|
|
36
|
+
error: `Project "${projectIdentifier}" not found.\n\nAvailable projects:\n${availableProjects || 'None'}\n\nUse list_projects to see all your projects.`
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Fetches the complete schema for a specific project including:
|
|
41
|
+
* - All custom collections with their fields
|
|
42
|
+
* - Field tokens, types, and descriptions for AI context
|
|
43
|
+
* - Template patterns and example usage
|
|
44
|
+
*
|
|
45
|
+
* Each field includes:
|
|
46
|
+
* - Field Name (display name)
|
|
47
|
+
* - Token (the exact syntax to use in templates)
|
|
48
|
+
* - Type (text, richText, image, etc.)
|
|
49
|
+
* - Description (help text for context)
|
|
50
|
+
*
|
|
51
|
+
* Uses stored credentials or triggers device flow for authentication.
|
|
52
|
+
*
|
|
53
|
+
* @param projectId - Project ID (UUID) or project name
|
|
54
|
+
*/
|
|
55
|
+
async function getTenantSchema(projectId) {
|
|
56
|
+
// Check if we need to authenticate
|
|
57
|
+
if (await (0, api_client_1.needsAuthentication)()) {
|
|
58
|
+
const authResult = await (0, device_flow_1.ensureAuthenticated)();
|
|
59
|
+
if (!authResult.authenticated) {
|
|
60
|
+
return authResult.message;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// Resolve project identifier to tenant ID
|
|
64
|
+
const resolved = await resolveProjectId(projectId);
|
|
65
|
+
if ('error' in resolved) {
|
|
66
|
+
return `# Project Not Found
|
|
67
|
+
|
|
68
|
+
${resolved.error}
|
|
69
|
+
`;
|
|
70
|
+
}
|
|
71
|
+
const { tenantId } = resolved;
|
|
72
|
+
const apiUrl = (0, api_client_1.getApiUrl)();
|
|
73
|
+
// Fetch the AI prompt for this tenant
|
|
74
|
+
const response = await (0, api_client_1.apiRequest)('/api/collections/ai-prompt', {
|
|
75
|
+
tenantId,
|
|
76
|
+
});
|
|
77
|
+
if ((0, api_client_1.isApiError)(response)) {
|
|
78
|
+
// If auth error, try to re-authenticate
|
|
79
|
+
if ((0, api_client_1.needsAuthError)(response)) {
|
|
80
|
+
const authResult = await (0, device_flow_1.ensureAuthenticated)();
|
|
81
|
+
if (!authResult.authenticated) {
|
|
82
|
+
return authResult.message;
|
|
83
|
+
}
|
|
84
|
+
// Retry the request
|
|
85
|
+
const retryResponse = await (0, api_client_1.apiRequest)('/api/collections/ai-prompt', {
|
|
86
|
+
tenantId,
|
|
87
|
+
});
|
|
88
|
+
if ((0, api_client_1.isApiError)(retryResponse)) {
|
|
89
|
+
return `# API Error
|
|
90
|
+
|
|
91
|
+
Failed to fetch project schema: ${retryResponse.error}
|
|
92
|
+
|
|
93
|
+
**Project ID:** ${tenantId}
|
|
94
|
+
**Status:** ${retryResponse.statusCode}
|
|
95
|
+
|
|
96
|
+
Please try authenticating again.
|
|
97
|
+
`;
|
|
98
|
+
}
|
|
99
|
+
return formatSchemaResponse(retryResponse.data, tenantId);
|
|
100
|
+
}
|
|
101
|
+
if (response.statusCode === 403) {
|
|
102
|
+
return `# Authorization Error
|
|
103
|
+
|
|
104
|
+
You don't have permission to access this project's schema.
|
|
105
|
+
|
|
106
|
+
**Project ID:** ${tenantId}
|
|
107
|
+
|
|
108
|
+
Make sure:
|
|
109
|
+
1. You have membership in this project
|
|
110
|
+
2. Try running \`list_projects\` to see your accessible projects
|
|
111
|
+
`;
|
|
112
|
+
}
|
|
113
|
+
return `# API Error
|
|
114
|
+
|
|
115
|
+
Failed to fetch project schema: ${response.error}
|
|
116
|
+
|
|
117
|
+
**Project ID:** ${tenantId}
|
|
118
|
+
**API URL:** ${apiUrl}
|
|
119
|
+
**Status:** ${response.statusCode}
|
|
120
|
+
|
|
121
|
+
Please verify:
|
|
122
|
+
1. The project ID is correct
|
|
123
|
+
2. You have network connectivity
|
|
124
|
+
`;
|
|
125
|
+
}
|
|
126
|
+
return formatSchemaResponse(response.data, tenantId);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Format the schema response for display
|
|
130
|
+
*/
|
|
131
|
+
function formatSchemaResponse(data, tenantId) {
|
|
132
|
+
if (!data?.prompt) {
|
|
133
|
+
return `# Unexpected Response
|
|
134
|
+
|
|
135
|
+
The API returned a successful response but the prompt data was missing.
|
|
136
|
+
|
|
137
|
+
**Project ID:** ${tenantId}
|
|
138
|
+
**Response:** ${JSON.stringify(data, null, 2).slice(0, 500)}
|
|
139
|
+
`;
|
|
140
|
+
}
|
|
141
|
+
// Return the full AI prompt which includes all schema information
|
|
142
|
+
return `# Project Schema
|
|
143
|
+
|
|
144
|
+
**Project ID:** \`${tenantId}\`
|
|
145
|
+
|
|
146
|
+
This schema is specific to this project and includes all collections with their fields.
|
|
147
|
+
|
|
148
|
+
**Field Table Format:**
|
|
149
|
+
- **Field Name** - Display name for the field
|
|
150
|
+
- **Token** - The exact token to use in templates (use triple braces for richText)
|
|
151
|
+
- **Type** - Field type (text, richText, image, url, videoEmbed, boolean, number, date, select, relation)
|
|
152
|
+
- **Description** - Help text explaining what the field is for
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
${data.prompt}
|
|
157
|
+
`;
|
|
158
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-projects.d.ts","sourceRoot":"","sources":["../../src/tools/list-projects.ts"],"names":[],"mappings":"AAmBA;;GAEG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,CAkDpD"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.listProjects = listProjects;
|
|
4
|
+
const api_client_1 = require("../lib/api-client");
|
|
5
|
+
const device_flow_1 = require("../lib/device-flow");
|
|
6
|
+
/**
|
|
7
|
+
* List all FastMode projects the authenticated user has access to
|
|
8
|
+
*/
|
|
9
|
+
async function listProjects() {
|
|
10
|
+
// Check if we need to authenticate
|
|
11
|
+
if (await (0, api_client_1.needsAuthentication)()) {
|
|
12
|
+
const authResult = await (0, device_flow_1.ensureAuthenticated)();
|
|
13
|
+
if (!authResult.authenticated) {
|
|
14
|
+
return authResult.message;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
// Fetch user's tenants/projects
|
|
18
|
+
const response = await (0, api_client_1.apiRequest)('/api/tenants');
|
|
19
|
+
if ((0, api_client_1.isApiError)(response)) {
|
|
20
|
+
// If auth error, try to re-authenticate
|
|
21
|
+
if ((0, api_client_1.needsAuthError)(response)) {
|
|
22
|
+
const authResult = await (0, device_flow_1.ensureAuthenticated)();
|
|
23
|
+
if (!authResult.authenticated) {
|
|
24
|
+
return authResult.message;
|
|
25
|
+
}
|
|
26
|
+
// Retry the request
|
|
27
|
+
const retryResponse = await (0, api_client_1.apiRequest)('/api/tenants');
|
|
28
|
+
if ((0, api_client_1.isApiError)(retryResponse)) {
|
|
29
|
+
return `# API Error
|
|
30
|
+
|
|
31
|
+
Failed to fetch projects: ${retryResponse.error}
|
|
32
|
+
|
|
33
|
+
**Status:** ${retryResponse.statusCode}
|
|
34
|
+
|
|
35
|
+
Please try authenticating again.
|
|
36
|
+
`;
|
|
37
|
+
}
|
|
38
|
+
return formatProjectList(retryResponse.data);
|
|
39
|
+
}
|
|
40
|
+
return `# API Error
|
|
41
|
+
|
|
42
|
+
Failed to fetch projects: ${response.error}
|
|
43
|
+
|
|
44
|
+
**Status:** ${response.statusCode}
|
|
45
|
+
|
|
46
|
+
Please check:
|
|
47
|
+
1. Your authentication is valid
|
|
48
|
+
2. The API URL is correct
|
|
49
|
+
3. You have network connectivity
|
|
50
|
+
`;
|
|
51
|
+
}
|
|
52
|
+
return formatProjectList(response.data);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Format the project list for display
|
|
56
|
+
*/
|
|
57
|
+
function formatProjectList(projects) {
|
|
58
|
+
if (!projects || projects.length === 0) {
|
|
59
|
+
return `# No Projects Found
|
|
60
|
+
|
|
61
|
+
You don't have access to any FastMode projects.
|
|
62
|
+
|
|
63
|
+
**To create a project:**
|
|
64
|
+
1. Go to app.fastmode.ai
|
|
65
|
+
2. Click "Create New Project"
|
|
66
|
+
3. Run \`list_projects\` again to see it here
|
|
67
|
+
`;
|
|
68
|
+
}
|
|
69
|
+
// Format the project list
|
|
70
|
+
let output = `# Your FastMode Projects
|
|
71
|
+
|
|
72
|
+
Found ${projects.length} project${projects.length > 1 ? 's' : ''}:
|
|
73
|
+
|
|
74
|
+
`;
|
|
75
|
+
projects.forEach((project, index) => {
|
|
76
|
+
const siteStatus = project.site?.status || 'pending';
|
|
77
|
+
output += `## ${index + 1}. ${project.name}
|
|
78
|
+
|
|
79
|
+
- **Project ID:** \`${project.id}\`
|
|
80
|
+
- **Subdomain:** ${project.subdomain}.fastmode.ai
|
|
81
|
+
${project.customDomain ? `- **Custom Domain:** ${project.customDomain}\n` : ''}- **Your Role:** ${project.role}
|
|
82
|
+
- **Site Status:** ${siteStatus}
|
|
83
|
+
|
|
84
|
+
`;
|
|
85
|
+
});
|
|
86
|
+
output += `---
|
|
87
|
+
|
|
88
|
+
## How to Use
|
|
89
|
+
|
|
90
|
+
To get the schema for a project, use:
|
|
91
|
+
\`\`\`
|
|
92
|
+
get_tenant_schema(projectId: "${projects[0]?.id || 'project-id-here'}")
|
|
93
|
+
\`\`\`
|
|
94
|
+
|
|
95
|
+
Or use the project name:
|
|
96
|
+
\`\`\`
|
|
97
|
+
get_tenant_schema(projectId: "${projects[0]?.name || 'Project Name'}")
|
|
98
|
+
\`\`\`
|
|
99
|
+
`;
|
|
100
|
+
return output;
|
|
101
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sync Schema Tool
|
|
3
|
+
*
|
|
4
|
+
* Creates collections and/or fields in Fast Mode.
|
|
5
|
+
* Requires authentication. Will skip duplicates.
|
|
6
|
+
*/
|
|
7
|
+
interface FieldToCreate {
|
|
8
|
+
slug: string;
|
|
9
|
+
name: string;
|
|
10
|
+
type: string;
|
|
11
|
+
description?: string;
|
|
12
|
+
isRequired?: boolean;
|
|
13
|
+
options?: string;
|
|
14
|
+
referenceCollection?: string;
|
|
15
|
+
}
|
|
16
|
+
interface CollectionToCreate {
|
|
17
|
+
slug: string;
|
|
18
|
+
name: string;
|
|
19
|
+
nameSingular: string;
|
|
20
|
+
description?: string;
|
|
21
|
+
hasSlug?: boolean;
|
|
22
|
+
fields?: FieldToCreate[];
|
|
23
|
+
}
|
|
24
|
+
interface FieldsToAdd {
|
|
25
|
+
collectionSlug: string;
|
|
26
|
+
isBuiltin?: boolean;
|
|
27
|
+
fields: FieldToCreate[];
|
|
28
|
+
}
|
|
29
|
+
interface SyncSchemaInput {
|
|
30
|
+
projectId: string;
|
|
31
|
+
collections?: CollectionToCreate[];
|
|
32
|
+
fieldsToAdd?: FieldsToAdd[];
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Sync schema - create collections and/or fields
|
|
36
|
+
*
|
|
37
|
+
* @param input - The sync schema input with projectId, collections, and/or fieldsToAdd
|
|
38
|
+
*/
|
|
39
|
+
export declare function syncSchema(input: SyncSchemaInput): Promise<string>;
|
|
40
|
+
export {};
|
|
41
|
+
//# sourceMappingURL=sync-schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-schema.d.ts","sourceRoot":"","sources":["../../src/tools/sync-schema.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAYH,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,UAAU,kBAAkB;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,aAAa,EAAE,CAAC;CAC1B;AAED,UAAU,WAAW;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,aAAa,EAAE,CAAC;CACzB;AAED,UAAU,eAAe;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,kBAAkB,EAAE,CAAC;IACnC,WAAW,CAAC,EAAE,WAAW,EAAE,CAAC;CAC7B;AA2KD;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAkZxE"}
|