@mkrlbs/mcp-adonisjs 1.0.2 → 1.1.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 +64 -98
- package/build/index.js +298 -130
- package/build/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +406 -190
package/src/index.ts
CHANGED
|
@@ -1,264 +1,480 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
2
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
4
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
4
|
import {
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
CallToolRequestSchema,
|
|
6
|
+
ListToolsRequestSchema,
|
|
8
7
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
9
8
|
import { z } from "zod";
|
|
10
9
|
import { execSync } from "child_process";
|
|
10
|
+
import fs from "fs";
|
|
11
|
+
import path from "path";
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* Blacklisted commands that are considered dangerous
|
|
14
15
|
*/
|
|
15
16
|
const BLACKLISTED_COMMANDS = [
|
|
16
|
-
|
|
17
|
-
"migration:fresh",
|
|
18
|
-
"migration:refresh",
|
|
19
|
-
"migration:reset",
|
|
17
|
+
"migration:fresh",
|
|
20
18
|
];
|
|
21
19
|
|
|
22
20
|
/**
|
|
23
21
|
* Shell injection characters that are not allowed in command arguments
|
|
24
22
|
*/
|
|
25
|
-
const SHELL_INJECTION_PATTERN = /[
|
|
23
|
+
const SHELL_INJECTION_PATTERN = /[;&|`$<>\\]/;
|
|
26
24
|
|
|
27
25
|
/**
|
|
28
26
|
* Validates that command arguments don't contain shell injection characters
|
|
29
27
|
*/
|
|
30
28
|
function validateArguments(args: string[]): void {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
29
|
+
for (const arg of args) {
|
|
30
|
+
if (SHELL_INJECTION_PATTERN.test(arg)) {
|
|
31
|
+
throw new Error(
|
|
32
|
+
`Invalid argument "${arg}": contains potentially dangerous characters`
|
|
33
|
+
);
|
|
34
|
+
}
|
|
36
35
|
}
|
|
37
|
-
}
|
|
38
36
|
}
|
|
39
37
|
|
|
40
38
|
/**
|
|
41
39
|
* Checks if a command is blacklisted
|
|
42
40
|
*/
|
|
43
41
|
function isBlacklisted(command: string): boolean {
|
|
44
|
-
|
|
42
|
+
return BLACKLISTED_COMMANDS.includes(command);
|
|
45
43
|
}
|
|
46
44
|
|
|
47
45
|
/**
|
|
48
|
-
*
|
|
46
|
+
* Verify that we are in an AdonisJS project
|
|
49
47
|
*/
|
|
50
|
-
function
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
// Build the command
|
|
62
|
-
const fullCommand = `node ace ${command} ${args.join(" ")}`.trim();
|
|
63
|
-
|
|
64
|
-
try {
|
|
65
|
-
const output = execSync(fullCommand, {
|
|
66
|
-
cwd: process.cwd(),
|
|
67
|
-
encoding: "utf-8",
|
|
68
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
69
|
-
});
|
|
70
|
-
return output;
|
|
71
|
-
} catch (error: any) {
|
|
72
|
-
throw new Error(
|
|
73
|
-
`Command execution failed: ${error.message}\nStderr: ${error.stderr || "N/A"}`
|
|
74
|
-
);
|
|
75
|
-
}
|
|
48
|
+
function verifyAdonisProject(): void {
|
|
49
|
+
const acePath = path.join(process.cwd(), "ace");
|
|
50
|
+
const aceJsPath = path.join(process.cwd(), "ace.js");
|
|
51
|
+
|
|
52
|
+
if (!fs.existsSync(acePath) && !fs.existsSync(aceJsPath)) {
|
|
53
|
+
throw new Error(
|
|
54
|
+
`AdonisJS 'ace' entry point not found in current directory (${process.cwd()}).\n` +
|
|
55
|
+
`Please ensure the MCP server is running in the root of your AdonisJS project.`
|
|
56
|
+
);
|
|
57
|
+
}
|
|
76
58
|
}
|
|
77
59
|
|
|
78
60
|
/**
|
|
79
|
-
*
|
|
61
|
+
* Executes an Ace command safely
|
|
80
62
|
*/
|
|
63
|
+
function executeAceCommand(command: string, args: string[] = []): string {
|
|
64
|
+
verifyAdonisProject();
|
|
65
|
+
|
|
66
|
+
if (isBlacklisted(command)) {
|
|
67
|
+
throw new Error(
|
|
68
|
+
`Command "${command}" is blacklisted for security reasons. Blocked commands: ${BLACKLISTED_COMMANDS.join(", ")}`
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
validateArguments(args);
|
|
73
|
+
|
|
74
|
+
const fullCommand = `node ace ${command} ${args.join(" ")}`.trim();
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
const output = execSync(fullCommand, {
|
|
78
|
+
cwd: process.cwd(),
|
|
79
|
+
encoding: "utf-8",
|
|
80
|
+
timeout: 30_000,
|
|
81
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
82
|
+
});
|
|
83
|
+
return output;
|
|
84
|
+
} catch (error: any) {
|
|
85
|
+
throw new Error(
|
|
86
|
+
`Command execution failed: ${error.message}\nStderr: ${error.stderr || "N/A"}`
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ─── Schema Definitions ─────────────────────────────────────────────────────
|
|
92
|
+
|
|
81
93
|
const MakeControllerArgsSchema = z.object({
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
.boolean()
|
|
85
|
-
.optional()
|
|
86
|
-
.default(false)
|
|
87
|
-
.describe("Whether to create a resource controller"),
|
|
94
|
+
name: z.string().describe("Name of the controller to create"),
|
|
95
|
+
resource: z.boolean().optional().default(false).describe("Whether to create a resource controller"),
|
|
88
96
|
});
|
|
89
97
|
|
|
90
98
|
const MakeServiceArgsSchema = z.object({
|
|
91
|
-
|
|
99
|
+
name: z.string().describe("Name of the service to create"),
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const MakeMigrationArgsSchema = z.object({
|
|
103
|
+
name: z.string().describe("Name of the migration (e.g., 'create_projects_table')"),
|
|
104
|
+
withModel: z.boolean().optional().default(false).describe("Also create the corresponding model (-m flag)"),
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
const MakeModelArgsSchema = z.object({
|
|
108
|
+
name: z.string().describe("Name of the model to create (e.g., 'Project')"),
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
const MakeValidatorArgsSchema = z.object({
|
|
112
|
+
name: z.string().describe("Name of the validator to create (e.g., 'project')"),
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
const MakeSeederArgsSchema = z.object({
|
|
116
|
+
name: z.string().describe("Name of the seeder to create (e.g., 'project')"),
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
const MakeExceptionArgsSchema = z.object({
|
|
120
|
+
name: z.string().describe("Name of the exception to create (e.g., 'UnauthorizedException')"),
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
const MakeMiddlewareArgsSchema = z.object({
|
|
124
|
+
name: z.string().describe("Name of the middleware to create (e.g., 'auth')"),
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
const MakeTestArgsSchema = z.object({
|
|
128
|
+
name: z.string().describe("Name of the test file to create (e.g., 'users/list')"),
|
|
129
|
+
suite: z.enum(["unit", "functional", "browser"]).optional().describe("Test suite to create the test in"),
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
const MakeFactoryArgsSchema = z.object({
|
|
133
|
+
name: z.string().describe("Name of the factory to create (e.g., 'User')"),
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
const MakePolicyArgsSchema = z.object({
|
|
137
|
+
name: z.string().describe("Name of the policy to create (e.g., 'project')"),
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
const MakeEventArgsSchema = z.object({
|
|
141
|
+
name: z.string().describe("Name of the event to create (e.g., 'UserRegistered')"),
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
const MakeListenerArgsSchema = z.object({
|
|
145
|
+
name: z.string().describe("Name of the listener to create (e.g., 'SendWelcomeEmail')"),
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
const MakeMailerArgsSchema = z.object({
|
|
149
|
+
name: z.string().describe("Name of the mailer to create (e.g., 'VerificationMailer')"),
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
const MakeCommandArgsSchema = z.object({
|
|
153
|
+
name: z.string().describe("Name of the command to create (e.g., 'SyncUsers')"),
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
const MigrationRunArgsSchema = z.object({
|
|
157
|
+
force: z.boolean().optional().default(false).describe("Force run in production"),
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
const MigrationRollbackArgsSchema = z.object({
|
|
161
|
+
batch: z.number().optional().describe("Batch number to rollback to (default: last batch)"),
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
const DbSeedArgsSchema = z.object({
|
|
165
|
+
files: z.string().optional().describe("Specific seeder file to run (e.g., 'database/seeders/user_seeder')"),
|
|
92
166
|
});
|
|
93
167
|
|
|
94
168
|
const RunAceCommandArgsSchema = z.object({
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
.array(z.string())
|
|
98
|
-
.optional()
|
|
99
|
-
.default([])
|
|
100
|
-
.describe("Arguments to pass to the command"),
|
|
169
|
+
command: z.string().describe("The Ace command to run (e.g., 'make:model')"),
|
|
170
|
+
args: z.array(z.string()).optional().default([]).describe("Arguments to pass to the command"),
|
|
101
171
|
});
|
|
102
172
|
|
|
103
|
-
|
|
104
|
-
* Initialize the MCP server
|
|
105
|
-
*/
|
|
106
|
-
const server = new Server(
|
|
107
|
-
{
|
|
108
|
-
name: "adonisjs-mcp-server",
|
|
109
|
-
version: "0.1.0",
|
|
110
|
-
},
|
|
111
|
-
{
|
|
112
|
-
capabilities: {
|
|
113
|
-
tools: {},
|
|
114
|
-
},
|
|
115
|
-
}
|
|
116
|
-
);
|
|
173
|
+
// ─── Tool Definitions ────────────────────────────────────────────────────────
|
|
117
174
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
175
|
+
interface ToolDef {
|
|
176
|
+
name: string;
|
|
177
|
+
description: string;
|
|
178
|
+
inputSchema: Record<string, any>;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function simpleNameTool(name: string, description: string, paramDesc: string): ToolDef {
|
|
182
|
+
return {
|
|
183
|
+
name,
|
|
184
|
+
description,
|
|
185
|
+
inputSchema: {
|
|
186
|
+
type: "object",
|
|
187
|
+
properties: {
|
|
188
|
+
name: { type: "string", description: paramDesc },
|
|
189
|
+
},
|
|
190
|
+
required: ["name"],
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const TOOLS: ToolDef[] = [
|
|
196
|
+
{
|
|
125
197
|
name: "make_controller",
|
|
126
|
-
description:
|
|
127
|
-
|
|
198
|
+
description: "Creates an AdonisJS controller using 'node ace make:controller'",
|
|
199
|
+
inputSchema: {
|
|
200
|
+
type: "object",
|
|
201
|
+
properties: {
|
|
202
|
+
name: { type: "string", description: "Name of the controller to create" },
|
|
203
|
+
resource: { type: "boolean", description: "Whether to create a resource controller", default: false },
|
|
204
|
+
},
|
|
205
|
+
required: ["name"],
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
simpleNameTool("make_service", "Creates an AdonisJS service using 'node ace make:service'", "Name of the service"),
|
|
209
|
+
{
|
|
210
|
+
name: "make_migration",
|
|
211
|
+
description: "Creates an AdonisJS migration using 'node ace make:migration'. Use withModel to also create the model (-m flag).",
|
|
128
212
|
inputSchema: {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
description: "Name of the controller to create",
|
|
213
|
+
type: "object",
|
|
214
|
+
properties: {
|
|
215
|
+
name: { type: "string", description: "Name of the migration (e.g., 'create_projects_table')" },
|
|
216
|
+
withModel: { type: "boolean", description: "Also create the corresponding model (-m flag)", default: false },
|
|
134
217
|
},
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
218
|
+
required: ["name"],
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
simpleNameTool("make_model", "Creates an AdonisJS Lucid model using 'node ace make:model'", "Name of the model (e.g., 'Project')"),
|
|
222
|
+
simpleNameTool("make_validator", "Creates an AdonisJS VineJS validator using 'node ace make:validator'", "Name of the validator (e.g., 'project')"),
|
|
223
|
+
simpleNameTool("make_seeder", "Creates an AdonisJS database seeder using 'node ace make:seeder'", "Name of the seeder (e.g., 'project')"),
|
|
224
|
+
simpleNameTool("make_exception", "Creates an AdonisJS custom exception using 'node ace make:exception'", "Name of the exception (e.g., 'UnauthorizedException')"),
|
|
225
|
+
simpleNameTool("make_middleware", "Creates an AdonisJS middleware using 'node ace make:middleware'", "Name of the middleware (e.g., 'auth')"),
|
|
226
|
+
{
|
|
227
|
+
name: "make_test",
|
|
228
|
+
description: "Creates a Japa test file using 'node ace make:test'",
|
|
229
|
+
inputSchema: {
|
|
230
|
+
type: "object",
|
|
231
|
+
properties: {
|
|
232
|
+
name: { type: "string", description: "Name of the test (e.g., 'users/list')" },
|
|
233
|
+
suite: { type: "string", enum: ["unit", "functional", "browser"], description: "Test suite" },
|
|
139
234
|
},
|
|
140
|
-
|
|
141
|
-
required: ["name"],
|
|
235
|
+
required: ["name"],
|
|
142
236
|
},
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
237
|
+
},
|
|
238
|
+
simpleNameTool("make_factory", "Creates a Lucid model factory using 'node ace make:factory'", "Name of the factory (e.g., 'User')"),
|
|
239
|
+
simpleNameTool("make_policy", "Creates a bouncer policy using 'node ace make:policy'", "Name of the policy (e.g., 'project')"),
|
|
240
|
+
simpleNameTool("make_event", "Creates an AdonisJS event using 'node ace make:event'", "Name of the event (e.g., 'UserRegistered')"),
|
|
241
|
+
simpleNameTool("make_listener", "Creates an AdonisJS event listener using 'node ace make:listener'", "Name of the listener (e.g., 'SendWelcomeEmail')"),
|
|
242
|
+
simpleNameTool("make_mailer", "Creates an AdonisJS mailer using 'node ace make:mailer'", "Name of the mailer (e.g., 'VerificationMailer')"),
|
|
243
|
+
simpleNameTool("make_command", "Creates an AdonisJS Ace command using 'node ace make:command'", "Name of the command (e.g., 'SyncUsers')"),
|
|
244
|
+
{
|
|
245
|
+
name: "migration_run",
|
|
246
|
+
description: "Runs pending database migrations using 'node ace migration:run'. Auto-generates database/schema.ts.",
|
|
148
247
|
inputSchema: {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
type: "string",
|
|
153
|
-
description: "Name of the service to create",
|
|
248
|
+
type: "object",
|
|
249
|
+
properties: {
|
|
250
|
+
force: { type: "boolean", description: "Force run in production", default: false },
|
|
154
251
|
},
|
|
155
|
-
},
|
|
156
|
-
required: ["name"],
|
|
157
252
|
},
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
name: "
|
|
161
|
-
description:
|
|
162
|
-
"Executes an AdonisJS Ace command with security checks. Blacklisted commands: " +
|
|
163
|
-
BLACKLISTED_COMMANDS.join(", "),
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
name: "migration_rollback",
|
|
256
|
+
description: "Rolls back the last batch of migrations using 'node ace migration:rollback'",
|
|
164
257
|
inputSchema: {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
type: "string",
|
|
169
|
-
description: "The Ace command to run (e.g., 'make:model')",
|
|
258
|
+
type: "object",
|
|
259
|
+
properties: {
|
|
260
|
+
batch: { type: "number", description: "Batch number to rollback to (default: last batch)" },
|
|
170
261
|
},
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
name: "migration_status",
|
|
266
|
+
description: "Shows the status of all migrations using 'node ace migration:status'",
|
|
267
|
+
inputSchema: { type: "object", properties: {} },
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
name: "db_seed",
|
|
271
|
+
description: "Runs database seeders using 'node ace db:seed'",
|
|
272
|
+
inputSchema: {
|
|
273
|
+
type: "object",
|
|
274
|
+
properties: {
|
|
275
|
+
files: { type: "string", description: "Specific seeder file to run (e.g., 'database/seeders/user_seeder')" },
|
|
178
276
|
},
|
|
179
|
-
},
|
|
180
|
-
required: ["command"],
|
|
181
277
|
},
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
name: "list_routes",
|
|
281
|
+
description: "Lists all registered routes using 'node ace list:routes'",
|
|
282
|
+
inputSchema: { type: "object", properties: {} },
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
name: "run_ace_command",
|
|
286
|
+
description: "Executes any AdonisJS Ace command with security checks. Use this for commands without a dedicated tool. Blacklisted: " + BLACKLISTED_COMMANDS.join(", "),
|
|
287
|
+
inputSchema: {
|
|
288
|
+
type: "object",
|
|
289
|
+
properties: {
|
|
290
|
+
command: { type: "string", description: "The Ace command to run" },
|
|
291
|
+
args: { type: "array", items: { type: "string" }, description: "Arguments to pass", default: [] },
|
|
292
|
+
},
|
|
293
|
+
required: ["command"],
|
|
294
|
+
},
|
|
295
|
+
},
|
|
296
|
+
];
|
|
297
|
+
|
|
298
|
+
// ─── Server Setup ────────────────────────────────────────────────────────────
|
|
299
|
+
|
|
300
|
+
const server = new Server(
|
|
301
|
+
{ name: "adonisjs-mcp-server", version: "1.1.1" },
|
|
302
|
+
{ capabilities: { tools: {} } }
|
|
303
|
+
);
|
|
304
|
+
|
|
305
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
306
|
+
return { tools: TOOLS };
|
|
185
307
|
});
|
|
186
308
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
*/
|
|
309
|
+
// ─── Tool Handlers ───────────────────────────────────────────────────────────
|
|
310
|
+
|
|
190
311
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
switch (name) {
|
|
195
|
-
case "make_controller": {
|
|
196
|
-
const parsed = MakeControllerArgsSchema.parse(args);
|
|
197
|
-
const commandArgs = parsed.resource ? [parsed.name, "--resource"] : [parsed.name];
|
|
198
|
-
const output = executeAceCommand("make:controller", commandArgs);
|
|
199
|
-
return {
|
|
200
|
-
content: [
|
|
201
|
-
{
|
|
202
|
-
type: "text",
|
|
203
|
-
text: `Controller created successfully:\n${output}`,
|
|
204
|
-
},
|
|
205
|
-
],
|
|
206
|
-
};
|
|
207
|
-
}
|
|
312
|
+
try {
|
|
313
|
+
const { name, arguments: args } = request.params;
|
|
208
314
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
315
|
+
switch (name) {
|
|
316
|
+
case "make_controller": {
|
|
317
|
+
const parsed = MakeControllerArgsSchema.parse(args);
|
|
318
|
+
const cmdArgs = parsed.resource ? [parsed.name, "--resource"] : [parsed.name];
|
|
319
|
+
const output = executeAceCommand("make:controller", cmdArgs);
|
|
320
|
+
return { content: [{ type: "text", text: `Controller created successfully:\n${output}` }] };
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
case "make_service": {
|
|
324
|
+
const parsed = MakeServiceArgsSchema.parse(args);
|
|
325
|
+
const output = executeAceCommand("make:service", [parsed.name]);
|
|
326
|
+
return { content: [{ type: "text", text: `Service created successfully:\n${output}` }] };
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
case "make_migration": {
|
|
330
|
+
const parsed = MakeMigrationArgsSchema.parse(args);
|
|
331
|
+
const cmdArgs = parsed.withModel ? [parsed.name, "-m"] : [parsed.name];
|
|
332
|
+
const output = executeAceCommand("make:migration", cmdArgs);
|
|
333
|
+
return { content: [{ type: "text", text: `Migration created successfully:\n${output}` }] };
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
case "make_model": {
|
|
337
|
+
const parsed = MakeModelArgsSchema.parse(args);
|
|
338
|
+
const output = executeAceCommand("make:model", [parsed.name]);
|
|
339
|
+
return { content: [{ type: "text", text: `Model created successfully:\n${output}` }] };
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
case "make_validator": {
|
|
343
|
+
const parsed = MakeValidatorArgsSchema.parse(args);
|
|
344
|
+
const output = executeAceCommand("make:validator", [parsed.name]);
|
|
345
|
+
return { content: [{ type: "text", text: `Validator created successfully:\n${output}` }] };
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
case "make_seeder": {
|
|
349
|
+
const parsed = MakeSeederArgsSchema.parse(args);
|
|
350
|
+
const output = executeAceCommand("make:seeder", [parsed.name]);
|
|
351
|
+
return { content: [{ type: "text", text: `Seeder created successfully:\n${output}` }] };
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
case "make_exception": {
|
|
355
|
+
const parsed = MakeExceptionArgsSchema.parse(args);
|
|
356
|
+
const output = executeAceCommand("make:exception", [parsed.name]);
|
|
357
|
+
return { content: [{ type: "text", text: `Exception created successfully:\n${output}` }] };
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
case "make_middleware": {
|
|
361
|
+
const parsed = MakeMiddlewareArgsSchema.parse(args);
|
|
362
|
+
const output = executeAceCommand("make:middleware", [parsed.name]);
|
|
363
|
+
return { content: [{ type: "text", text: `Middleware created successfully:\n${output}` }] };
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
case "make_test": {
|
|
367
|
+
const parsed = MakeTestArgsSchema.parse(args);
|
|
368
|
+
const cmdArgs = [parsed.name];
|
|
369
|
+
if (parsed.suite) cmdArgs.push("--suite", parsed.suite);
|
|
370
|
+
const output = executeAceCommand("make:test", cmdArgs);
|
|
371
|
+
return { content: [{ type: "text", text: `Test created successfully:\n${output}` }] };
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
case "make_factory": {
|
|
375
|
+
const parsed = MakeFactoryArgsSchema.parse(args);
|
|
376
|
+
const output = executeAceCommand("make:factory", [parsed.name]);
|
|
377
|
+
return { content: [{ type: "text", text: `Factory created successfully:\n${output}` }] };
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
case "make_policy": {
|
|
381
|
+
const parsed = MakePolicyArgsSchema.parse(args);
|
|
382
|
+
const output = executeAceCommand("make:policy", [parsed.name]);
|
|
383
|
+
return { content: [{ type: "text", text: `Policy created successfully:\n${output}` }] };
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
case "make_event": {
|
|
387
|
+
const parsed = MakeEventArgsSchema.parse(args);
|
|
388
|
+
const output = executeAceCommand("make:event", [parsed.name]);
|
|
389
|
+
return { content: [{ type: "text", text: `Event created successfully:\n${output}` }] };
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
case "make_listener": {
|
|
393
|
+
const parsed = MakeListenerArgsSchema.parse(args);
|
|
394
|
+
const output = executeAceCommand("make:listener", [parsed.name]);
|
|
395
|
+
return { content: [{ type: "text", text: `Listener created successfully:\n${output}` }] };
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
case "make_mailer": {
|
|
399
|
+
const parsed = MakeMailerArgsSchema.parse(args);
|
|
400
|
+
const output = executeAceCommand("make:mailer", [parsed.name]);
|
|
401
|
+
return { content: [{ type: "text", text: `Mailer created successfully:\n${output}` }] };
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
case "make_command": {
|
|
405
|
+
const parsed = MakeCommandArgsSchema.parse(args);
|
|
406
|
+
const output = executeAceCommand("make:command", [parsed.name]);
|
|
407
|
+
return { content: [{ type: "text", text: `Command created successfully:\n${output}` }] };
|
|
408
|
+
}
|
|
221
409
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
410
|
+
case "migration_run": {
|
|
411
|
+
const parsed = MigrationRunArgsSchema.parse(args);
|
|
412
|
+
const cmdArgs = parsed.force ? ["--force"] : [];
|
|
413
|
+
const output = executeAceCommand("migration:run", cmdArgs);
|
|
414
|
+
return { content: [{ type: "text", text: `Migrations executed successfully:\n${output}` }] };
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
case "migration_rollback": {
|
|
418
|
+
const parsed = MigrationRollbackArgsSchema.parse(args);
|
|
419
|
+
const cmdArgs = parsed.batch ? ["--batch", String(parsed.batch)] : [];
|
|
420
|
+
const output = executeAceCommand("migration:rollback", cmdArgs);
|
|
421
|
+
return { content: [{ type: "text", text: `Rollback completed:\n${output}` }] };
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
case "migration_status": {
|
|
425
|
+
const output = executeAceCommand("migration:status");
|
|
426
|
+
return { content: [{ type: "text", text: `Migration status:\n${output}` }] };
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
case "db_seed": {
|
|
430
|
+
const parsed = DbSeedArgsSchema.parse(args);
|
|
431
|
+
const cmdArgs = parsed.files ? ["--files", parsed.files] : [];
|
|
432
|
+
const output = executeAceCommand("db:seed", cmdArgs);
|
|
433
|
+
return { content: [{ type: "text", text: `Seeding completed:\n${output}` }] };
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
case "list_routes": {
|
|
437
|
+
const output = executeAceCommand("list:routes");
|
|
438
|
+
return { content: [{ type: "text", text: `Routes:\n${output}` }] };
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
case "run_ace_command": {
|
|
442
|
+
const parsed = RunAceCommandArgsSchema.parse(args);
|
|
443
|
+
const output = executeAceCommand(parsed.command, parsed.args);
|
|
444
|
+
return { content: [{ type: "text", text: `Command executed successfully:\n${output}` }] };
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
default:
|
|
448
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
449
|
+
}
|
|
450
|
+
} catch (error: any) {
|
|
225
451
|
return {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
type: "text",
|
|
229
|
-
text: `Command executed successfully:\n${output}`,
|
|
230
|
-
},
|
|
231
|
-
],
|
|
452
|
+
content: [{ type: "text", text: `Error: ${error.message}` }],
|
|
453
|
+
isError: true,
|
|
232
454
|
};
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
default:
|
|
236
|
-
throw new Error(`Unknown tool: ${name}`);
|
|
237
455
|
}
|
|
238
|
-
} catch (error: any) {
|
|
239
|
-
return {
|
|
240
|
-
content: [
|
|
241
|
-
{
|
|
242
|
-
type: "text",
|
|
243
|
-
text: `Error: ${error.message}`,
|
|
244
|
-
},
|
|
245
|
-
],
|
|
246
|
-
isError: true,
|
|
247
|
-
};
|
|
248
|
-
}
|
|
249
456
|
});
|
|
250
457
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
*/
|
|
458
|
+
// ─── Start ───────────────────────────────────────────────────────────────────
|
|
459
|
+
|
|
254
460
|
async function main() {
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
461
|
+
const targetCwd = process.env.cwd || process.env.CWD;
|
|
462
|
+
if (targetCwd) {
|
|
463
|
+
try {
|
|
464
|
+
process.chdir(targetCwd);
|
|
465
|
+
console.error(`Changed working directory to: ${targetCwd}`);
|
|
466
|
+
} catch (err) {
|
|
467
|
+
console.error(`Failed to change working directory to ${targetCwd}:`, err);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
const transport = new StdioServerTransport();
|
|
472
|
+
await server.connect(transport);
|
|
473
|
+
console.error("AdonisJS MCP Server running on stdio");
|
|
474
|
+
console.error(`Current working directory: ${process.cwd()}`);
|
|
259
475
|
}
|
|
260
476
|
|
|
261
477
|
main().catch((error) => {
|
|
262
|
-
|
|
263
|
-
|
|
478
|
+
console.error("Fatal error:", error);
|
|
479
|
+
process.exit(1);
|
|
264
480
|
});
|