@donkeylabs/cli 0.4.1 ā 0.4.2
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/package.json +1 -1
- package/src/commands/init.ts +153 -33
- package/src/commands/mcp.ts +305 -0
- package/src/index.ts +6 -0
- package/templates/sveltekit-app/package.json +3 -3
package/package.json
CHANGED
package/src/commands/init.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { mkdir, writeFile, readFile, readdir, copyFile, stat } from "node:fs/pro
|
|
|
8
8
|
import { join, resolve, dirname, basename } from "node:path";
|
|
9
9
|
import { existsSync } from "node:fs";
|
|
10
10
|
import { fileURLToPath } from "node:url";
|
|
11
|
+
import { spawn } from "node:child_process";
|
|
11
12
|
import pc from "picocolors";
|
|
12
13
|
import prompts from "prompts";
|
|
13
14
|
|
|
@@ -38,21 +39,45 @@ const RENAME_MAP: Record<string, string> = {
|
|
|
38
39
|
|
|
39
40
|
export async function initCommand(args: string[]) {
|
|
40
41
|
// Parse --type flag if provided
|
|
41
|
-
let projectDir =
|
|
42
|
+
let projectDir: string | null = null;
|
|
42
43
|
let typeArg: string | null = null;
|
|
43
44
|
|
|
44
45
|
for (let i = 0; i < args.length; i++) {
|
|
45
46
|
if (args[i] === "--type" && args[i + 1]) {
|
|
46
47
|
typeArg = args[i + 1];
|
|
47
48
|
i++; // skip next arg
|
|
48
|
-
} else if (!args[i]
|
|
49
|
-
projectDir = args[i];
|
|
49
|
+
} else if (!args[i]?.startsWith("-")) {
|
|
50
|
+
projectDir = args[i] ?? null;
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
53
|
|
|
53
|
-
|
|
54
|
+
console.log(pc.bold("\nš Create a new @donkeylabs/server project\n"));
|
|
55
|
+
|
|
56
|
+
// If no project directory provided, prompt for it
|
|
57
|
+
if (!projectDir) {
|
|
58
|
+
const { name } = await prompts({
|
|
59
|
+
type: "text",
|
|
60
|
+
name: "name",
|
|
61
|
+
message: "Project name:",
|
|
62
|
+
initial: "my-donkeylabs-app",
|
|
63
|
+
validate: (value) => {
|
|
64
|
+
if (!value) return "Project name is required";
|
|
65
|
+
if (!/^[a-zA-Z0-9-_]+$/.test(value)) {
|
|
66
|
+
return "Project name can only contain letters, numbers, dashes, and underscores";
|
|
67
|
+
}
|
|
68
|
+
return true;
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
if (!name) {
|
|
73
|
+
console.log(pc.yellow("Cancelled."));
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
54
76
|
|
|
55
|
-
|
|
77
|
+
projectDir = name;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const targetDir = resolve(process.cwd(), projectDir!);
|
|
56
81
|
|
|
57
82
|
let projectType: ProjectType;
|
|
58
83
|
|
|
@@ -130,45 +155,140 @@ export async function initCommand(args: string[]) {
|
|
|
130
155
|
await writeFile(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
131
156
|
}
|
|
132
157
|
|
|
133
|
-
|
|
134
|
-
if (projectType === "server") {
|
|
135
|
-
console.log(`
|
|
136
|
-
${pc.bold(pc.green("Success!"))} Server project initialized.
|
|
158
|
+
console.log(pc.green("\nā Project files created\n"));
|
|
137
159
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
160
|
+
// Auto-install dependencies
|
|
161
|
+
console.log(pc.cyan("Installing dependencies...\n"));
|
|
162
|
+
const installSuccess = await runCommand("bun", ["install"], targetDir);
|
|
141
163
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
3. Generate types after adding plugins:
|
|
146
|
-
${pc.cyan("bun run gen:types")}
|
|
147
|
-
`);
|
|
164
|
+
if (!installSuccess) {
|
|
165
|
+
console.log(pc.yellow("\nā Dependency installation failed."));
|
|
166
|
+
console.log(pc.dim(" Run 'bun install' manually to install dependencies.\n"));
|
|
148
167
|
} else {
|
|
149
|
-
console.log(
|
|
150
|
-
|
|
168
|
+
console.log(pc.green("\nā Dependencies installed\n"));
|
|
169
|
+
}
|
|
151
170
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
171
|
+
// Ask about MCP setup
|
|
172
|
+
const { setupMcp } = await prompts({
|
|
173
|
+
type: "confirm",
|
|
174
|
+
name: "setupMcp",
|
|
175
|
+
message: `Setup MCP for AI-assisted development? ${pc.dim("(Highly recommended)")}`,
|
|
176
|
+
initial: true,
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
if (setupMcp) {
|
|
180
|
+
// Ask which IDE
|
|
181
|
+
const { ide } = await prompts({
|
|
182
|
+
type: "select",
|
|
183
|
+
name: "ide",
|
|
184
|
+
message: "Which AI IDE are you using?",
|
|
185
|
+
choices: [
|
|
186
|
+
{ title: "Claude Code", value: "claude", description: "Anthropic's Claude Code CLI" },
|
|
187
|
+
{ title: "Cursor", value: "cursor", description: "Cursor AI IDE" },
|
|
188
|
+
{ title: "Windsurf", value: "windsurf", description: "Codeium Windsurf" },
|
|
189
|
+
{ title: "Other / Skip instructions", value: "skip" },
|
|
190
|
+
],
|
|
191
|
+
});
|
|
155
192
|
|
|
156
|
-
|
|
157
|
-
|
|
193
|
+
// Install @donkeylabs/mcp
|
|
194
|
+
console.log(pc.cyan("\nInstalling @donkeylabs/mcp...\n"));
|
|
195
|
+
const mcpInstallSuccess = await runCommand("bun", ["add", "-d", "@donkeylabs/mcp"], targetDir);
|
|
196
|
+
|
|
197
|
+
if (mcpInstallSuccess) {
|
|
198
|
+
console.log(pc.green("ā Installed @donkeylabs/mcp\n"));
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Create .mcp.json
|
|
202
|
+
const mcpConfig = {
|
|
203
|
+
mcpServers: {
|
|
204
|
+
donkeylabs: {
|
|
205
|
+
command: "bunx",
|
|
206
|
+
args: ["@donkeylabs/mcp"],
|
|
207
|
+
cwd: "${workspaceFolder}",
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
await writeFile(join(targetDir, ".mcp.json"), JSON.stringify(mcpConfig, null, 2) + "\n");
|
|
213
|
+
console.log(pc.green("ā Created .mcp.json\n"));
|
|
214
|
+
|
|
215
|
+
// Show IDE-specific instructions
|
|
216
|
+
if (ide === "claude") {
|
|
217
|
+
console.log(pc.cyan("Claude Code Setup:"));
|
|
218
|
+
console.log(pc.dim("ā".repeat(40)));
|
|
219
|
+
console.log(`
|
|
220
|
+
The .mcp.json file has been created in your project.
|
|
221
|
+
Claude Code will automatically detect and use this configuration.
|
|
222
|
+
|
|
223
|
+
${pc.bold("To verify:")}
|
|
224
|
+
1. Open Claude Code in this project directory
|
|
225
|
+
2. The MCP tools should be available automatically
|
|
226
|
+
3. Try asking Claude to "list plugins" or "get project info"
|
|
227
|
+
`);
|
|
228
|
+
} else if (ide === "cursor") {
|
|
229
|
+
console.log(pc.cyan("Cursor Setup:"));
|
|
230
|
+
console.log(pc.dim("ā".repeat(40)));
|
|
231
|
+
console.log(`
|
|
232
|
+
${pc.bold("To configure Cursor:")}
|
|
233
|
+
1. Open Cursor Settings (Cmd/Ctrl + ,)
|
|
234
|
+
2. Search for "MCP" or "Model Context Protocol"
|
|
235
|
+
3. Add the donkeylabs server from .mcp.json
|
|
236
|
+
4. Restart Cursor to apply changes
|
|
237
|
+
`);
|
|
238
|
+
} else if (ide === "windsurf") {
|
|
239
|
+
console.log(pc.cyan("Windsurf Setup:"));
|
|
240
|
+
console.log(pc.dim("ā".repeat(40)));
|
|
241
|
+
console.log(`
|
|
242
|
+
${pc.bold("To configure Windsurf:")}
|
|
243
|
+
1. Open Windsurf settings
|
|
244
|
+
2. Navigate to AI / MCP configuration
|
|
245
|
+
3. Add the donkeylabs server from .mcp.json
|
|
246
|
+
`);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
158
249
|
|
|
159
|
-
|
|
160
|
-
|
|
250
|
+
// Print final success message
|
|
251
|
+
console.log(pc.bold(pc.green("\nš Project ready!\n")));
|
|
161
252
|
|
|
162
|
-
|
|
163
|
-
|
|
253
|
+
if (projectType === "server") {
|
|
254
|
+
console.log(`${pc.bold("Start development:")}
|
|
255
|
+
${pc.cyan("cd " + (projectDir !== "." ? projectDir : ""))}
|
|
256
|
+
${pc.cyan("bun run dev")}
|
|
257
|
+
`);
|
|
258
|
+
} else {
|
|
259
|
+
console.log(`${pc.bold("Start development:")}
|
|
260
|
+
${projectDir !== "." ? pc.cyan("cd " + projectDir) + "\n " : ""}${pc.cyan("bun run dev")}
|
|
164
261
|
|
|
165
262
|
${pc.bold("Project structure:")}
|
|
166
|
-
src/server/
|
|
167
|
-
src/lib/api.ts
|
|
168
|
-
src/routes/
|
|
169
|
-
src/hooks.server.ts - Server hooks for SSR
|
|
263
|
+
src/server/ - @donkeylabs/server API
|
|
264
|
+
src/lib/api.ts - Typed API client
|
|
265
|
+
src/routes/ - SvelteKit pages
|
|
170
266
|
`);
|
|
171
267
|
}
|
|
268
|
+
|
|
269
|
+
if (setupMcp) {
|
|
270
|
+
console.log(pc.dim("MCP is configured. Your AI assistant can now help you build!"));
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Run a command and return success status
|
|
276
|
+
*/
|
|
277
|
+
async function runCommand(cmd: string, args: string[], cwd: string): Promise<boolean> {
|
|
278
|
+
return new Promise((resolve) => {
|
|
279
|
+
const child = spawn(cmd, args, {
|
|
280
|
+
stdio: "inherit",
|
|
281
|
+
cwd,
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
child.on("close", (code) => {
|
|
285
|
+
resolve(code === 0);
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
child.on("error", () => {
|
|
289
|
+
resolve(false);
|
|
290
|
+
});
|
|
291
|
+
});
|
|
172
292
|
}
|
|
173
293
|
|
|
174
294
|
/**
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP (Model Context Protocol) setup command
|
|
3
|
+
*
|
|
4
|
+
* Sets up the @donkeylabs/mcp server for AI-assisted development
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { existsSync } from "node:fs";
|
|
8
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
import { spawn } from "node:child_process";
|
|
11
|
+
import pc from "picocolors";
|
|
12
|
+
import prompts from "prompts";
|
|
13
|
+
|
|
14
|
+
interface McpConfig {
|
|
15
|
+
mcpServers?: Record<string, {
|
|
16
|
+
command: string;
|
|
17
|
+
args: string[];
|
|
18
|
+
cwd?: string;
|
|
19
|
+
env?: Record<string, string>;
|
|
20
|
+
}>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async function detectPackageManager(): Promise<"bun" | "npm" | "pnpm" | "yarn"> {
|
|
24
|
+
if (existsSync("bun.lockb") || existsSync("bun.lock")) return "bun";
|
|
25
|
+
if (existsSync("pnpm-lock.yaml")) return "pnpm";
|
|
26
|
+
if (existsSync("yarn.lock")) return "yarn";
|
|
27
|
+
return "npm";
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function installPackage(pkg: string, dev: boolean = true): Promise<boolean> {
|
|
31
|
+
const pm = await detectPackageManager();
|
|
32
|
+
|
|
33
|
+
const args: string[] = [];
|
|
34
|
+
switch (pm) {
|
|
35
|
+
case "bun":
|
|
36
|
+
args.push("add", dev ? "-d" : "", pkg);
|
|
37
|
+
break;
|
|
38
|
+
case "pnpm":
|
|
39
|
+
args.push("add", dev ? "-D" : "", pkg);
|
|
40
|
+
break;
|
|
41
|
+
case "yarn":
|
|
42
|
+
args.push("add", dev ? "-D" : "", pkg);
|
|
43
|
+
break;
|
|
44
|
+
default:
|
|
45
|
+
args.push("install", dev ? "--save-dev" : "--save", pkg);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
console.log(pc.dim(`$ ${pm} ${args.filter(Boolean).join(" ")}`));
|
|
49
|
+
|
|
50
|
+
return new Promise((resolve) => {
|
|
51
|
+
const child = spawn(pm, args.filter(Boolean), {
|
|
52
|
+
stdio: "inherit",
|
|
53
|
+
cwd: process.cwd(),
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
child.on("close", (code) => {
|
|
57
|
+
resolve(code === 0);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
child.on("error", () => {
|
|
61
|
+
resolve(false);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async function readMcpConfig(): Promise<McpConfig> {
|
|
67
|
+
const configPath = join(process.cwd(), ".mcp.json");
|
|
68
|
+
|
|
69
|
+
if (!existsSync(configPath)) {
|
|
70
|
+
return {};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
const content = await readFile(configPath, "utf-8");
|
|
75
|
+
return JSON.parse(content);
|
|
76
|
+
} catch {
|
|
77
|
+
return {};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async function writeMcpConfig(config: McpConfig): Promise<void> {
|
|
82
|
+
const configPath = join(process.cwd(), ".mcp.json");
|
|
83
|
+
await writeFile(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async function setupClaudeCode(): Promise<void> {
|
|
87
|
+
console.log(pc.cyan("\nClaude Code Setup:"));
|
|
88
|
+
console.log(pc.dim("ā".repeat(40)));
|
|
89
|
+
console.log(`
|
|
90
|
+
The .mcp.json file has been created in your project root.
|
|
91
|
+
Claude Code will automatically detect and use this configuration.
|
|
92
|
+
|
|
93
|
+
${pc.bold("To verify:")}
|
|
94
|
+
1. Open Claude Code in this project
|
|
95
|
+
2. The MCP tools should be available automatically
|
|
96
|
+
3. Try asking Claude to "list plugins" or "get project info"
|
|
97
|
+
|
|
98
|
+
${pc.bold("Manual setup (if needed):")}
|
|
99
|
+
Add to your Claude Code settings:
|
|
100
|
+
${pc.dim(JSON.stringify({
|
|
101
|
+
"mcpServers": {
|
|
102
|
+
"donkeylabs": {
|
|
103
|
+
"command": "bunx",
|
|
104
|
+
"args": ["@donkeylabs/mcp"],
|
|
105
|
+
"cwd": "${workspaceFolder}"
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}, null, 2))}
|
|
109
|
+
`);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async function setupCursor(): Promise<void> {
|
|
113
|
+
console.log(pc.cyan("\nCursor Setup:"));
|
|
114
|
+
console.log(pc.dim("ā".repeat(40)));
|
|
115
|
+
console.log(`
|
|
116
|
+
${pc.bold("To configure Cursor:")}
|
|
117
|
+
1. Open Cursor Settings (Cmd/Ctrl + ,)
|
|
118
|
+
2. Search for "MCP" or "Model Context Protocol"
|
|
119
|
+
3. Add the donkeylabs server configuration:
|
|
120
|
+
|
|
121
|
+
${pc.dim(JSON.stringify({
|
|
122
|
+
"donkeylabs": {
|
|
123
|
+
"command": "bunx",
|
|
124
|
+
"args": ["@donkeylabs/mcp"],
|
|
125
|
+
"cwd": "${workspaceFolder}"
|
|
126
|
+
}
|
|
127
|
+
}, null, 2))}
|
|
128
|
+
|
|
129
|
+
4. Restart Cursor to apply changes
|
|
130
|
+
`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
async function setupWindsurf(): Promise<void> {
|
|
134
|
+
console.log(pc.cyan("\nWindsurf Setup:"));
|
|
135
|
+
console.log(pc.dim("ā".repeat(40)));
|
|
136
|
+
console.log(`
|
|
137
|
+
${pc.bold("To configure Windsurf:")}
|
|
138
|
+
1. Open Windsurf settings
|
|
139
|
+
2. Navigate to AI / MCP configuration
|
|
140
|
+
3. Add the donkeylabs server:
|
|
141
|
+
|
|
142
|
+
${pc.dim(JSON.stringify({
|
|
143
|
+
"donkeylabs": {
|
|
144
|
+
"command": "bunx",
|
|
145
|
+
"args": ["@donkeylabs/mcp"],
|
|
146
|
+
"cwd": "${workspaceFolder}"
|
|
147
|
+
}
|
|
148
|
+
}, null, 2))}
|
|
149
|
+
`);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export async function mcpCommand(args: string[]): Promise<void> {
|
|
153
|
+
const subcommand = args[0];
|
|
154
|
+
|
|
155
|
+
if (!subcommand || subcommand === "setup") {
|
|
156
|
+
await setupMcp(args.slice(1));
|
|
157
|
+
} else if (subcommand === "help" || subcommand === "--help") {
|
|
158
|
+
printMcpHelp();
|
|
159
|
+
} else {
|
|
160
|
+
console.error(pc.red(`Unknown mcp subcommand: ${subcommand}`));
|
|
161
|
+
printMcpHelp();
|
|
162
|
+
process.exit(1);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function printMcpHelp(): void {
|
|
167
|
+
console.log(`
|
|
168
|
+
${pc.bold("donkeylabs mcp")} - Setup MCP server for AI-assisted development
|
|
169
|
+
|
|
170
|
+
${pc.bold("Usage:")}
|
|
171
|
+
donkeylabs mcp Interactive MCP setup
|
|
172
|
+
donkeylabs mcp setup Setup MCP (interactive)
|
|
173
|
+
donkeylabs mcp setup --claude Setup for Claude Code
|
|
174
|
+
donkeylabs mcp setup --cursor Setup for Cursor
|
|
175
|
+
donkeylabs mcp setup --all Setup for all IDEs
|
|
176
|
+
|
|
177
|
+
${pc.bold("Options:")}
|
|
178
|
+
--claude Configure for Claude Code
|
|
179
|
+
--cursor Configure for Cursor
|
|
180
|
+
--windsurf Configure for Windsurf
|
|
181
|
+
--all Show setup for all IDEs
|
|
182
|
+
--skip-install Skip installing @donkeylabs/mcp package
|
|
183
|
+
|
|
184
|
+
${pc.bold("What this does:")}
|
|
185
|
+
1. Installs @donkeylabs/mcp as a dev dependency
|
|
186
|
+
2. Creates/updates .mcp.json in your project
|
|
187
|
+
3. Provides IDE-specific setup instructions
|
|
188
|
+
|
|
189
|
+
${pc.bold("MCP Tools Available:")}
|
|
190
|
+
- get_project_info - View project structure and routes
|
|
191
|
+
- create_plugin - Create new plugins
|
|
192
|
+
- add_service_method - Add methods to plugin services
|
|
193
|
+
- add_migration - Create database migrations
|
|
194
|
+
- create_router - Create new routers
|
|
195
|
+
- add_route - Add routes to routers
|
|
196
|
+
- add_cron - Schedule cron jobs
|
|
197
|
+
- add_event - Register events
|
|
198
|
+
- add_async_job - Register background jobs
|
|
199
|
+
- generate_types - Regenerate types
|
|
200
|
+
- generate_client - Generate API client
|
|
201
|
+
`);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
async function setupMcp(args: string[]): Promise<void> {
|
|
205
|
+
console.log(pc.bold("\nš§ Setting up @donkeylabs/mcp\n"));
|
|
206
|
+
|
|
207
|
+
// Check if we're in a donkeylabs project
|
|
208
|
+
const configPath = join(process.cwd(), "donkeylabs.config.ts");
|
|
209
|
+
const hasConfig = existsSync(configPath);
|
|
210
|
+
|
|
211
|
+
if (!hasConfig) {
|
|
212
|
+
console.log(pc.yellow("ā No donkeylabs.config.ts found in current directory."));
|
|
213
|
+
console.log(pc.dim(" The MCP server works best in a @donkeylabs/server project."));
|
|
214
|
+
console.log(pc.dim(" Run 'donkeylabs init' to create a new project first.\n"));
|
|
215
|
+
|
|
216
|
+
const { proceed } = await prompts({
|
|
217
|
+
type: "confirm",
|
|
218
|
+
name: "proceed",
|
|
219
|
+
message: "Continue anyway?",
|
|
220
|
+
initial: false,
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
if (!proceed) {
|
|
224
|
+
console.log(pc.dim("Aborted."));
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Parse args for flags
|
|
230
|
+
const skipInstall = args.includes("--skip-install");
|
|
231
|
+
const forClaude = args.includes("--claude");
|
|
232
|
+
const forCursor = args.includes("--cursor");
|
|
233
|
+
const forWindsurf = args.includes("--windsurf");
|
|
234
|
+
const forAll = args.includes("--all");
|
|
235
|
+
|
|
236
|
+
// Install @donkeylabs/mcp if not skipped
|
|
237
|
+
if (!skipInstall) {
|
|
238
|
+
console.log(pc.cyan("Installing @donkeylabs/mcp..."));
|
|
239
|
+
const success = await installPackage("@donkeylabs/mcp");
|
|
240
|
+
|
|
241
|
+
if (!success) {
|
|
242
|
+
console.log(pc.yellow("\nā Package installation failed, but continuing with config setup."));
|
|
243
|
+
console.log(pc.dim(" You can manually install with: bun add -d @donkeylabs/mcp\n"));
|
|
244
|
+
} else {
|
|
245
|
+
console.log(pc.green("ā Installed @donkeylabs/mcp\n"));
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Create/update .mcp.json
|
|
250
|
+
console.log(pc.cyan("Configuring .mcp.json..."));
|
|
251
|
+
|
|
252
|
+
const config = await readMcpConfig();
|
|
253
|
+
config.mcpServers = config.mcpServers || {};
|
|
254
|
+
|
|
255
|
+
config.mcpServers.donkeylabs = {
|
|
256
|
+
command: "bunx",
|
|
257
|
+
args: ["@donkeylabs/mcp"],
|
|
258
|
+
cwd: "${workspaceFolder}",
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
await writeMcpConfig(config);
|
|
262
|
+
console.log(pc.green("ā Created .mcp.json\n"));
|
|
263
|
+
|
|
264
|
+
// Show IDE-specific instructions
|
|
265
|
+
if (forAll || (!forClaude && !forCursor && !forWindsurf)) {
|
|
266
|
+
// Interactive mode or --all
|
|
267
|
+
if (!forClaude && !forCursor && !forWindsurf && !forAll) {
|
|
268
|
+
const { ide } = await prompts({
|
|
269
|
+
type: "select",
|
|
270
|
+
name: "ide",
|
|
271
|
+
message: "Which IDE are you using?",
|
|
272
|
+
choices: [
|
|
273
|
+
{ title: "Claude Code", value: "claude" },
|
|
274
|
+
{ title: "Cursor", value: "cursor" },
|
|
275
|
+
{ title: "Windsurf", value: "windsurf" },
|
|
276
|
+
{ title: "Show all", value: "all" },
|
|
277
|
+
],
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
if (ide === "claude") await setupClaudeCode();
|
|
281
|
+
else if (ide === "cursor") await setupCursor();
|
|
282
|
+
else if (ide === "windsurf") await setupWindsurf();
|
|
283
|
+
else {
|
|
284
|
+
await setupClaudeCode();
|
|
285
|
+
await setupCursor();
|
|
286
|
+
await setupWindsurf();
|
|
287
|
+
}
|
|
288
|
+
} else {
|
|
289
|
+
await setupClaudeCode();
|
|
290
|
+
await setupCursor();
|
|
291
|
+
await setupWindsurf();
|
|
292
|
+
}
|
|
293
|
+
} else {
|
|
294
|
+
if (forClaude) await setupClaudeCode();
|
|
295
|
+
if (forCursor) await setupCursor();
|
|
296
|
+
if (forWindsurf) await setupWindsurf();
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
console.log(pc.green("\nā MCP setup complete!\n"));
|
|
300
|
+
console.log(pc.dim("The AI assistant can now help you with:"));
|
|
301
|
+
console.log(pc.dim(" - Creating plugins, routes, and handlers"));
|
|
302
|
+
console.log(pc.dim(" - Adding migrations and service methods"));
|
|
303
|
+
console.log(pc.dim(" - Setting up cron jobs and background tasks"));
|
|
304
|
+
console.log(pc.dim(" - Generating types and API clients\n"));
|
|
305
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -35,6 +35,7 @@ ${pc.bold("Commands:")}
|
|
|
35
35
|
${pc.cyan("init")} Initialize a new project
|
|
36
36
|
${pc.cyan("generate")} Generate types (registry, context, client)
|
|
37
37
|
${pc.cyan("plugin")} Plugin management
|
|
38
|
+
${pc.cyan("mcp")} Setup MCP server for AI-assisted development
|
|
38
39
|
|
|
39
40
|
${pc.bold("Options:")}
|
|
40
41
|
-h, --help Show this help message
|
|
@@ -95,6 +96,11 @@ async function main() {
|
|
|
95
96
|
await pluginCommand(positionals.slice(1));
|
|
96
97
|
break;
|
|
97
98
|
|
|
99
|
+
case "mcp":
|
|
100
|
+
const { mcpCommand } = await import("./commands/mcp");
|
|
101
|
+
await mcpCommand(positionals.slice(1));
|
|
102
|
+
break;
|
|
103
|
+
|
|
98
104
|
default:
|
|
99
105
|
console.error(pc.red(`Unknown command: ${command}`));
|
|
100
106
|
console.log(`Run ${pc.cyan("donkeylabs --help")} for available commands.`);
|
|
@@ -24,9 +24,9 @@
|
|
|
24
24
|
"vite": "^7.2.6"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@donkeylabs/cli": "^0.4.
|
|
28
|
-
"@donkeylabs/adapter-sveltekit": "^0.4.
|
|
29
|
-
"@donkeylabs/server": "^0.4.
|
|
27
|
+
"@donkeylabs/cli": "^0.4.2",
|
|
28
|
+
"@donkeylabs/adapter-sveltekit": "^0.4.2",
|
|
29
|
+
"@donkeylabs/server": "^0.4.2",
|
|
30
30
|
"bits-ui": "^2.15.4",
|
|
31
31
|
"clsx": "^2.1.1",
|
|
32
32
|
"kysely": "^0.27.6",
|