@opensaas/stack-cli 0.5.0 → 0.6.1
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 +76 -0
- package/dist/commands/migrate.d.ts.map +1 -1
- package/dist/commands/migrate.js +94 -268
- package/dist/commands/migrate.js.map +1 -1
- package/package.json +7 -2
- package/.turbo/turbo-build.log +0 -4
- package/CHANGELOG.md +0 -462
- package/CLAUDE.md +0 -298
- package/src/commands/__snapshots__/generate.test.ts.snap +0 -413
- package/src/commands/dev.test.ts +0 -215
- package/src/commands/dev.ts +0 -48
- package/src/commands/generate.test.ts +0 -282
- package/src/commands/generate.ts +0 -182
- package/src/commands/init.ts +0 -34
- package/src/commands/mcp.ts +0 -135
- package/src/commands/migrate.ts +0 -534
- package/src/generator/__snapshots__/context.test.ts.snap +0 -361
- package/src/generator/__snapshots__/prisma.test.ts.snap +0 -174
- package/src/generator/__snapshots__/types.test.ts.snap +0 -1702
- package/src/generator/context.test.ts +0 -139
- package/src/generator/context.ts +0 -227
- package/src/generator/index.ts +0 -7
- package/src/generator/lists.test.ts +0 -335
- package/src/generator/lists.ts +0 -140
- package/src/generator/plugin-types.ts +0 -147
- package/src/generator/prisma-config.ts +0 -46
- package/src/generator/prisma-extensions.ts +0 -159
- package/src/generator/prisma.test.ts +0 -211
- package/src/generator/prisma.ts +0 -161
- package/src/generator/types.test.ts +0 -268
- package/src/generator/types.ts +0 -537
- package/src/index.ts +0 -46
- package/src/mcp/lib/documentation-provider.ts +0 -710
- package/src/mcp/lib/features/catalog.ts +0 -301
- package/src/mcp/lib/generators/feature-generator.ts +0 -598
- package/src/mcp/lib/types.ts +0 -89
- package/src/mcp/lib/wizards/migration-wizard.ts +0 -584
- package/src/mcp/lib/wizards/wizard-engine.ts +0 -427
- package/src/mcp/server/index.ts +0 -361
- package/src/mcp/server/stack-mcp-server.ts +0 -544
- package/src/migration/generators/migration-generator.ts +0 -675
- package/src/migration/introspectors/index.ts +0 -12
- package/src/migration/introspectors/keystone-introspector.ts +0 -296
- package/src/migration/introspectors/nextjs-introspector.ts +0 -209
- package/src/migration/introspectors/prisma-introspector.ts +0 -233
- package/src/migration/types.ts +0 -92
- package/tests/introspectors/keystone-introspector.test.ts +0 -255
- package/tests/introspectors/nextjs-introspector.test.ts +0 -302
- package/tests/introspectors/prisma-introspector.test.ts +0 -268
- package/tests/migration-generator.test.ts +0 -592
- package/tests/migration-wizard.test.ts +0 -442
- package/tsconfig.json +0 -13
- package/tsconfig.tsbuildinfo +0 -1
- package/vitest.config.ts +0 -26
package/src/mcp/server/index.ts
DELETED
|
@@ -1,361 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* OpenSaaS Stack MCP Server - Main entry point
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { Server } from '@modelcontextprotocol/sdk/server/index.js'
|
|
6
|
-
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
|
|
7
|
-
import {
|
|
8
|
-
ListToolsRequestSchema,
|
|
9
|
-
CallToolRequestSchema,
|
|
10
|
-
type Tool,
|
|
11
|
-
} from '@modelcontextprotocol/sdk/types.js'
|
|
12
|
-
import { StackMCPServer } from './stack-mcp-server.js'
|
|
13
|
-
|
|
14
|
-
// Tool definitions
|
|
15
|
-
const TOOLS: Tool[] = [
|
|
16
|
-
{
|
|
17
|
-
name: 'opensaas_implement_feature',
|
|
18
|
-
description:
|
|
19
|
-
'Start an interactive wizard to implement a complete feature (authentication, blog, comments, file-upload, semantic-search, or custom). Returns step-by-step guidance.',
|
|
20
|
-
inputSchema: {
|
|
21
|
-
type: 'object',
|
|
22
|
-
properties: {
|
|
23
|
-
feature: {
|
|
24
|
-
type: 'string',
|
|
25
|
-
description:
|
|
26
|
-
'Feature to implement: "authentication", "blog", "comments", "file-upload", "semantic-search", or "custom"',
|
|
27
|
-
enum: ['authentication', 'blog', 'comments', 'file-upload', 'semantic-search', 'custom'],
|
|
28
|
-
},
|
|
29
|
-
description: {
|
|
30
|
-
type: 'string',
|
|
31
|
-
description: 'Required if feature is "custom" - describe what you want to build',
|
|
32
|
-
},
|
|
33
|
-
},
|
|
34
|
-
required: ['feature'],
|
|
35
|
-
},
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
name: 'opensaas_answer_feature',
|
|
39
|
-
description:
|
|
40
|
-
'Answer a question in the feature implementation wizard. Use this after opensaas_implement_feature to progress through the wizard.',
|
|
41
|
-
inputSchema: {
|
|
42
|
-
type: 'object',
|
|
43
|
-
properties: {
|
|
44
|
-
sessionId: {
|
|
45
|
-
type: 'string',
|
|
46
|
-
description: 'Session ID from the wizard',
|
|
47
|
-
},
|
|
48
|
-
answer: {
|
|
49
|
-
description: 'Your answer to the current question',
|
|
50
|
-
oneOf: [
|
|
51
|
-
{ type: 'string' },
|
|
52
|
-
{ type: 'boolean' },
|
|
53
|
-
{ type: 'array', items: { type: 'string' } },
|
|
54
|
-
],
|
|
55
|
-
},
|
|
56
|
-
},
|
|
57
|
-
required: ['sessionId', 'answer'],
|
|
58
|
-
},
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
name: 'opensaas_answer_followup',
|
|
62
|
-
description: 'Answer a follow-up question in the wizard flow',
|
|
63
|
-
inputSchema: {
|
|
64
|
-
type: 'object',
|
|
65
|
-
properties: {
|
|
66
|
-
sessionId: {
|
|
67
|
-
type: 'string',
|
|
68
|
-
description: 'Session ID from the wizard',
|
|
69
|
-
},
|
|
70
|
-
answer: {
|
|
71
|
-
type: 'string',
|
|
72
|
-
description: 'Your answer to the follow-up question',
|
|
73
|
-
},
|
|
74
|
-
},
|
|
75
|
-
required: ['sessionId', 'answer'],
|
|
76
|
-
},
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
name: 'opensaas_feature_docs',
|
|
80
|
-
description:
|
|
81
|
-
'Search OpenSaaS Stack documentation for a specific topic. Returns relevant docs with code examples.',
|
|
82
|
-
inputSchema: {
|
|
83
|
-
type: 'object',
|
|
84
|
-
properties: {
|
|
85
|
-
topic: {
|
|
86
|
-
type: 'string',
|
|
87
|
-
description:
|
|
88
|
-
'Topic to search for (e.g., "access control", "field types", "hooks", "authentication")',
|
|
89
|
-
},
|
|
90
|
-
},
|
|
91
|
-
required: ['topic'],
|
|
92
|
-
},
|
|
93
|
-
},
|
|
94
|
-
{
|
|
95
|
-
name: 'opensaas_list_features',
|
|
96
|
-
description: 'List all available features that can be implemented with the wizard',
|
|
97
|
-
inputSchema: {
|
|
98
|
-
type: 'object',
|
|
99
|
-
properties: {},
|
|
100
|
-
},
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
name: 'opensaas_suggest_features',
|
|
104
|
-
description: 'Get feature suggestions based on what features are already implemented',
|
|
105
|
-
inputSchema: {
|
|
106
|
-
type: 'object',
|
|
107
|
-
properties: {
|
|
108
|
-
currentFeatures: {
|
|
109
|
-
type: 'array',
|
|
110
|
-
items: { type: 'string' },
|
|
111
|
-
description: 'List of features already implemented (e.g., ["authentication", "blog"])',
|
|
112
|
-
},
|
|
113
|
-
},
|
|
114
|
-
},
|
|
115
|
-
},
|
|
116
|
-
{
|
|
117
|
-
name: 'opensaas_validate_feature',
|
|
118
|
-
description: 'Validate that a feature is properly implemented according to best practices',
|
|
119
|
-
inputSchema: {
|
|
120
|
-
type: 'object',
|
|
121
|
-
properties: {
|
|
122
|
-
feature: {
|
|
123
|
-
type: 'string',
|
|
124
|
-
description: 'Feature to validate (e.g., "authentication")',
|
|
125
|
-
},
|
|
126
|
-
configPath: {
|
|
127
|
-
type: 'string',
|
|
128
|
-
description: 'Path to opensaas.config.ts (optional)',
|
|
129
|
-
},
|
|
130
|
-
},
|
|
131
|
-
required: ['feature'],
|
|
132
|
-
},
|
|
133
|
-
},
|
|
134
|
-
{
|
|
135
|
-
name: 'opensaas_start_migration',
|
|
136
|
-
description:
|
|
137
|
-
'Start the migration wizard for an existing project. Returns the first question to begin the migration process.',
|
|
138
|
-
inputSchema: {
|
|
139
|
-
type: 'object',
|
|
140
|
-
properties: {
|
|
141
|
-
projectType: {
|
|
142
|
-
type: 'string',
|
|
143
|
-
description: 'Type of project being migrated',
|
|
144
|
-
enum: ['prisma', 'keystone', 'nextjs'],
|
|
145
|
-
},
|
|
146
|
-
},
|
|
147
|
-
required: ['projectType'],
|
|
148
|
-
},
|
|
149
|
-
},
|
|
150
|
-
{
|
|
151
|
-
name: 'opensaas_answer_migration',
|
|
152
|
-
description:
|
|
153
|
-
'Answer a question in the migration wizard. Use this after opensaas_start_migration to progress through the migration.',
|
|
154
|
-
inputSchema: {
|
|
155
|
-
type: 'object',
|
|
156
|
-
properties: {
|
|
157
|
-
sessionId: {
|
|
158
|
-
type: 'string',
|
|
159
|
-
description: 'Migration session ID from the wizard',
|
|
160
|
-
},
|
|
161
|
-
answer: {
|
|
162
|
-
description: 'Answer to the current question',
|
|
163
|
-
oneOf: [
|
|
164
|
-
{ type: 'string' },
|
|
165
|
-
{ type: 'boolean' },
|
|
166
|
-
{ type: 'array', items: { type: 'string' } },
|
|
167
|
-
],
|
|
168
|
-
},
|
|
169
|
-
},
|
|
170
|
-
required: ['sessionId', 'answer'],
|
|
171
|
-
},
|
|
172
|
-
},
|
|
173
|
-
{
|
|
174
|
-
name: 'opensaas_introspect_prisma',
|
|
175
|
-
description:
|
|
176
|
-
'Analyze a Prisma schema file and return detailed information about models, fields, and relationships. This helps you understand your existing schema before migration.',
|
|
177
|
-
inputSchema: {
|
|
178
|
-
type: 'object',
|
|
179
|
-
properties: {
|
|
180
|
-
schemaPath: {
|
|
181
|
-
type: 'string',
|
|
182
|
-
description: 'Path to schema.prisma (defaults to prisma/schema.prisma)',
|
|
183
|
-
},
|
|
184
|
-
},
|
|
185
|
-
},
|
|
186
|
-
},
|
|
187
|
-
{
|
|
188
|
-
name: 'opensaas_introspect_keystone',
|
|
189
|
-
description:
|
|
190
|
-
'Analyze a KeystoneJS config file and return information about lists and fields. This helps you understand your existing schema before migration.',
|
|
191
|
-
inputSchema: {
|
|
192
|
-
type: 'object',
|
|
193
|
-
properties: {
|
|
194
|
-
configPath: {
|
|
195
|
-
type: 'string',
|
|
196
|
-
description: 'Path to keystone.config.ts (defaults to keystone.config.ts)',
|
|
197
|
-
},
|
|
198
|
-
},
|
|
199
|
-
},
|
|
200
|
-
},
|
|
201
|
-
{
|
|
202
|
-
name: 'opensaas_search_migration_docs',
|
|
203
|
-
description:
|
|
204
|
-
'Search OpenSaaS Stack documentation for migration-related topics. Searches both local CLAUDE.md files and online documentation.',
|
|
205
|
-
inputSchema: {
|
|
206
|
-
type: 'object',
|
|
207
|
-
properties: {
|
|
208
|
-
query: {
|
|
209
|
-
type: 'string',
|
|
210
|
-
description:
|
|
211
|
-
'Search query (e.g., "prisma to opensaas", "access control patterns", "field types")',
|
|
212
|
-
},
|
|
213
|
-
},
|
|
214
|
-
required: ['query'],
|
|
215
|
-
},
|
|
216
|
-
},
|
|
217
|
-
{
|
|
218
|
-
name: 'opensaas_get_example',
|
|
219
|
-
description:
|
|
220
|
-
'Get example code for a specific feature or pattern. Returns code snippets from the examples directory.',
|
|
221
|
-
inputSchema: {
|
|
222
|
-
type: 'object',
|
|
223
|
-
properties: {
|
|
224
|
-
feature: {
|
|
225
|
-
type: 'string',
|
|
226
|
-
description:
|
|
227
|
-
'Feature to get example for (e.g., "blog-with-auth", "access-control", "relationships", "hooks", "custom-fields")',
|
|
228
|
-
},
|
|
229
|
-
},
|
|
230
|
-
required: ['feature'],
|
|
231
|
-
},
|
|
232
|
-
},
|
|
233
|
-
]
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* Create and start the MCP server
|
|
237
|
-
*/
|
|
238
|
-
export async function startMCPServer() {
|
|
239
|
-
const server = new Server(
|
|
240
|
-
{
|
|
241
|
-
name: 'opensaas-stack-mcp',
|
|
242
|
-
version: '0.1.0',
|
|
243
|
-
},
|
|
244
|
-
{
|
|
245
|
-
capabilities: {
|
|
246
|
-
tools: {},
|
|
247
|
-
},
|
|
248
|
-
},
|
|
249
|
-
)
|
|
250
|
-
|
|
251
|
-
const stackServer = new StackMCPServer()
|
|
252
|
-
|
|
253
|
-
// Register tool list handler
|
|
254
|
-
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
255
|
-
return { tools: TOOLS }
|
|
256
|
-
})
|
|
257
|
-
|
|
258
|
-
// Register tool call handler
|
|
259
|
-
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
260
|
-
const { name, arguments: args } = request.params
|
|
261
|
-
|
|
262
|
-
try {
|
|
263
|
-
switch (name) {
|
|
264
|
-
case 'opensaas_implement_feature':
|
|
265
|
-
return await stackServer.implementFeature(
|
|
266
|
-
args as { feature: string; description?: string },
|
|
267
|
-
)
|
|
268
|
-
|
|
269
|
-
case 'opensaas_answer_feature':
|
|
270
|
-
return await stackServer.answerFeatureQuestion(
|
|
271
|
-
args as { sessionId: string; answer: string | boolean | string[] },
|
|
272
|
-
)
|
|
273
|
-
|
|
274
|
-
case 'opensaas_answer_followup':
|
|
275
|
-
return await stackServer.answerFollowUpQuestion(
|
|
276
|
-
args as { sessionId: string; answer: string },
|
|
277
|
-
)
|
|
278
|
-
|
|
279
|
-
case 'opensaas_feature_docs':
|
|
280
|
-
return await stackServer.searchFeatureDocs(args as { topic: string })
|
|
281
|
-
|
|
282
|
-
case 'opensaas_list_features':
|
|
283
|
-
return await stackServer.listFeatures()
|
|
284
|
-
|
|
285
|
-
case 'opensaas_suggest_features':
|
|
286
|
-
return await stackServer.suggestFeatures(args as { currentFeatures?: string[] })
|
|
287
|
-
|
|
288
|
-
case 'opensaas_validate_feature':
|
|
289
|
-
return await stackServer.validateFeature(args as { feature: string; configPath?: string })
|
|
290
|
-
|
|
291
|
-
case 'opensaas_start_migration':
|
|
292
|
-
return await stackServer.startMigration(
|
|
293
|
-
args as { projectType: 'prisma' | 'keystone' | 'nextjs' },
|
|
294
|
-
)
|
|
295
|
-
|
|
296
|
-
case 'opensaas_answer_migration':
|
|
297
|
-
return await stackServer.answerMigration(
|
|
298
|
-
args as { sessionId: string; answer: string | boolean | string[] },
|
|
299
|
-
)
|
|
300
|
-
|
|
301
|
-
case 'opensaas_introspect_prisma':
|
|
302
|
-
return await stackServer.introspectPrisma(args as { schemaPath?: string })
|
|
303
|
-
|
|
304
|
-
case 'opensaas_introspect_keystone':
|
|
305
|
-
return await stackServer.introspectKeystone(args as { configPath?: string })
|
|
306
|
-
|
|
307
|
-
case 'opensaas_search_migration_docs':
|
|
308
|
-
return await stackServer.searchMigrationDocs(args as { query: string })
|
|
309
|
-
|
|
310
|
-
case 'opensaas_get_example':
|
|
311
|
-
return await stackServer.getExample(args as { feature: string })
|
|
312
|
-
|
|
313
|
-
default:
|
|
314
|
-
return {
|
|
315
|
-
content: [
|
|
316
|
-
{
|
|
317
|
-
type: 'text' as const,
|
|
318
|
-
text: `Unknown tool: ${name}`,
|
|
319
|
-
},
|
|
320
|
-
],
|
|
321
|
-
isError: true,
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
} catch (error) {
|
|
325
|
-
const errorMessage = error instanceof Error ? error.message : String(error)
|
|
326
|
-
console.error(`Error executing tool ${name}:`, error)
|
|
327
|
-
|
|
328
|
-
return {
|
|
329
|
-
content: [
|
|
330
|
-
{
|
|
331
|
-
type: 'text' as const,
|
|
332
|
-
text: `Error: ${errorMessage}`,
|
|
333
|
-
},
|
|
334
|
-
],
|
|
335
|
-
isError: true,
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
})
|
|
339
|
-
|
|
340
|
-
// Periodic cleanup
|
|
341
|
-
setInterval(
|
|
342
|
-
() => {
|
|
343
|
-
stackServer.cleanup()
|
|
344
|
-
},
|
|
345
|
-
1000 * 60 * 15,
|
|
346
|
-
) // Every 15 minutes
|
|
347
|
-
|
|
348
|
-
// Start server
|
|
349
|
-
const transport = new StdioServerTransport()
|
|
350
|
-
await server.connect(transport)
|
|
351
|
-
|
|
352
|
-
console.error('OpenSaaS Stack MCP server running on stdio')
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
// Start if run directly
|
|
356
|
-
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
357
|
-
startMCPServer().catch((error) => {
|
|
358
|
-
console.error('Failed to start MCP server:', error)
|
|
359
|
-
process.exit(1)
|
|
360
|
-
})
|
|
361
|
-
}
|