@donkeylabs/mcp 0.4.6 → 0.4.7
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/server.ts +124 -1
package/package.json
CHANGED
package/src/server.ts
CHANGED
|
@@ -516,6 +516,66 @@ async function generateProjectAnalysis(): Promise<string> {
|
|
|
516
516
|
analysis += `- Not generated yet. Run \`donkeylabs generate\` after adding plugins/routes.\n`;
|
|
517
517
|
}
|
|
518
518
|
|
|
519
|
+
// Generated API Client
|
|
520
|
+
const clientPath = projectConfig.clientOutput || (projectConfig.adapter === "sveltekit" ? "src/lib/api.ts" : null);
|
|
521
|
+
if (clientPath) {
|
|
522
|
+
const fullClientPath = join(projectRoot, clientPath);
|
|
523
|
+
analysis += `\n## Generated API Client\n`;
|
|
524
|
+
if (existsSync(fullClientPath)) {
|
|
525
|
+
analysis += `- Path: ${clientPath}\n`;
|
|
526
|
+
|
|
527
|
+
// Extract available methods from the client
|
|
528
|
+
const clientContent = readFileSync(fullClientPath, "utf-8");
|
|
529
|
+
|
|
530
|
+
// Find namespace properties (e.g., "health = {" or "users = {")
|
|
531
|
+
const namespaceMatches = [...clientContent.matchAll(/^\s+(\w+)\s*=\s*\{/gm)];
|
|
532
|
+
const namespaces: string[] = [];
|
|
533
|
+
for (const match of namespaceMatches) {
|
|
534
|
+
if (match[1] && !["sse", "constructor"].includes(match[1])) {
|
|
535
|
+
namespaces.push(match[1]);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
if (namespaces.length > 0) {
|
|
540
|
+
analysis += `- Available namespaces: ${namespaces.join(", ")}\n`;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
// Extract route type namespaces from "export namespace Routes {"
|
|
544
|
+
const routeTypesMatch = clientContent.match(/export namespace Routes \{([^}]+(?:\{[^}]*\}[^}]*)*)\}/s);
|
|
545
|
+
if (routeTypesMatch) {
|
|
546
|
+
const typeNamespaces = [...routeTypesMatch[1].matchAll(/export namespace (\w+)/g)].map(m => m[1]);
|
|
547
|
+
if (typeNamespaces.length > 0) {
|
|
548
|
+
analysis += `- Route types: Routes.${typeNamespaces.join(", Routes.")}\n`;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
// SvelteKit-specific usage
|
|
553
|
+
if (projectConfig.adapter === "sveltekit") {
|
|
554
|
+
const importPath = clientPath.startsWith("src/lib/") ? "$lib/" + clientPath.slice(8).replace(/\.ts$/, "") : clientPath.replace(/\.ts$/, "");
|
|
555
|
+
analysis += `\n### Usage in SvelteKit\n`;
|
|
556
|
+
analysis += `\`\`\`typescript\n`;
|
|
557
|
+
analysis += `// +page.server.ts (SSR - direct calls, no HTTP)\n`;
|
|
558
|
+
analysis += `import { createApi } from '${importPath}';\n`;
|
|
559
|
+
analysis += `export const load = async ({ locals }) => {\n`;
|
|
560
|
+
analysis += ` const api = createApi({ locals });\n`;
|
|
561
|
+
analysis += ` const data = await api.${namespaces[0] || "namespace"}.methodName({});\n`;
|
|
562
|
+
analysis += ` return { data };\n`;
|
|
563
|
+
analysis += `};\n`;
|
|
564
|
+
analysis += `\`\`\`\n`;
|
|
565
|
+
analysis += `\n\`\`\`svelte\n`;
|
|
566
|
+
analysis += `<!-- +page.svelte (Browser - HTTP calls) -->\n`;
|
|
567
|
+
analysis += `<script>\n`;
|
|
568
|
+
analysis += ` import { createApi } from '${importPath}';\n`;
|
|
569
|
+
analysis += ` const api = createApi();\n`;
|
|
570
|
+
analysis += `</script>\n`;
|
|
571
|
+
analysis += `\`\`\`\n`;
|
|
572
|
+
}
|
|
573
|
+
} else {
|
|
574
|
+
analysis += `- Path: ${clientPath} (not generated yet)\n`;
|
|
575
|
+
analysis += `- Run \`donkeylabs generate\` to create the client\n`;
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
|
|
519
579
|
return analysis;
|
|
520
580
|
}
|
|
521
581
|
|
|
@@ -1098,6 +1158,48 @@ async function getArchitectureGuidance(args: { task: string }): Promise<string>
|
|
|
1098
1158
|
guidance += `- **Browser:** HTTP calls automatically\n`;
|
|
1099
1159
|
}
|
|
1100
1160
|
|
|
1161
|
+
// Common mistakes section
|
|
1162
|
+
guidance += `\n## ⚠️ Common Mistakes to Avoid\n\n`;
|
|
1163
|
+
|
|
1164
|
+
guidance += `### Database Queries\n`;
|
|
1165
|
+
guidance += `- ❌ **NEVER use raw SQL** - always use Kysely query builder\n`;
|
|
1166
|
+
guidance += `- ❌ \`db.execute(sql\\\`SELECT * FROM users\\\`)\` - WRONG\n`;
|
|
1167
|
+
guidance += `- ✅ \`db.selectFrom("users").selectAll().execute()\` - CORRECT\n\n`;
|
|
1168
|
+
|
|
1169
|
+
guidance += `### After Making Changes\n`;
|
|
1170
|
+
guidance += `- ❌ Forgetting to run \`generate_types\` after adding migrations\n`;
|
|
1171
|
+
guidance += `- ❌ Forgetting to run \`generate_client\` after adding routes\n`;
|
|
1172
|
+
guidance += `- ✅ Always regenerate types after schema/route changes\n\n`;
|
|
1173
|
+
|
|
1174
|
+
guidance += `### Plugin Registration\n`;
|
|
1175
|
+
guidance += `- ❌ Creating a plugin but not registering it with \`server.registerPlugin()\`\n`;
|
|
1176
|
+
guidance += `- ❌ Creating routes but not adding router with \`server.use()\`\n`;
|
|
1177
|
+
guidance += `- ✅ Check server entry file to ensure plugin/router is registered\n\n`;
|
|
1178
|
+
|
|
1179
|
+
if (projectConfig.adapter === "sveltekit") {
|
|
1180
|
+
guidance += `### SvelteKit-Specific\n`;
|
|
1181
|
+
guidance += `- ❌ \`createApi()\` in +page.server.ts - WRONG (won't use direct calls)\n`;
|
|
1182
|
+
guidance += `- ✅ \`createApi({ locals })\` in +page.server.ts - CORRECT\n`;
|
|
1183
|
+
guidance += `- ❌ Importing from relative path instead of \`$lib/api\`\n`;
|
|
1184
|
+
guidance += `- ✅ \`import { createApi } from '$lib/api'\`\n\n`;
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
guidance += `### Route Handlers\n`;
|
|
1188
|
+
guidance += `- ❌ Putting business logic directly in route handlers\n`;
|
|
1189
|
+
guidance += `- ✅ Delegate to plugin service methods, keep routes thin\n`;
|
|
1190
|
+
guidance += `- ❌ Returning raw data without proper typing\n`;
|
|
1191
|
+
guidance += `- ✅ Define output schema with Zod for type safety\n\n`;
|
|
1192
|
+
|
|
1193
|
+
guidance += `## 🛑 When to Stop and Ask the User\n\n`;
|
|
1194
|
+
guidance += `**IMPORTANT:** If you're unsure about any of the following, STOP and ask the user before proceeding:\n\n`;
|
|
1195
|
+
guidance += `- **Architecture decisions** - "Should this be a plugin or just a route?"\n`;
|
|
1196
|
+
guidance += `- **Database schema design** - "What columns/relations do you need?"\n`;
|
|
1197
|
+
guidance += `- **Naming conventions** - "What should this entity/route be called?"\n`;
|
|
1198
|
+
guidance += `- **Business logic** - "How should this calculation/validation work?"\n`;
|
|
1199
|
+
guidance += `- **Integration patterns** - "How does this connect to existing code?"\n`;
|
|
1200
|
+
guidance += `- **Something doesn't work** - Don't keep trying different things, ask for help\n\n`;
|
|
1201
|
+
guidance += `It's better to ask ONE clarifying question than to build something wrong and have to redo it.\n\n`;
|
|
1202
|
+
|
|
1101
1203
|
guidance += `\n## Documentation Resources\n`;
|
|
1102
1204
|
guidance += `- \`donkeylabs://docs/database\` - Kysely queries, CRUD, joins, transactions\n`;
|
|
1103
1205
|
guidance += `- \`donkeylabs://docs/plugins\` - Plugin patterns & When to Create a Plugin vs Route\n`;
|
|
@@ -1303,6 +1405,11 @@ ${registrationExample}
|
|
|
1303
1405
|
// In your route handler:
|
|
1304
1406
|
const result = ctx.plugins.${name}.hello();
|
|
1305
1407
|
\`\`\`
|
|
1408
|
+
|
|
1409
|
+
### ⚠️ Reminders
|
|
1410
|
+
- **Don't forget** to register the plugin in your server entry file
|
|
1411
|
+
- **Use Kysely** for all database queries, never raw SQL
|
|
1412
|
+
- **Ask the user** if you're unsure about the schema design or business logic
|
|
1306
1413
|
`;
|
|
1307
1414
|
}
|
|
1308
1415
|
|
|
@@ -1454,6 +1561,11 @@ export const ${pluginName}Plugin = createPlugin
|
|
|
1454
1561
|
\`\`\`
|
|
1455
1562
|
|
|
1456
1563
|
The migration will run automatically on server start.
|
|
1564
|
+
|
|
1565
|
+
### ⚠️ Reminders
|
|
1566
|
+
- **Use Kysely schema builder** - never raw SQL in migrations
|
|
1567
|
+
- **Ask the user** if unsure about column types, relations, or schema design
|
|
1568
|
+
- **Test migrations** by running the server and checking for errors
|
|
1457
1569
|
`;
|
|
1458
1570
|
}
|
|
1459
1571
|
|
|
@@ -1532,6 +1644,11 @@ Routes added to this router will be named \`${prefix}.<routeName>\`:
|
|
|
1532
1644
|
- ${prefix}.list
|
|
1533
1645
|
- ${prefix}.get
|
|
1534
1646
|
- ${prefix}.create
|
|
1647
|
+
|
|
1648
|
+
### ⚠️ Reminders
|
|
1649
|
+
- **Don't forget** to register the router with \`server.use()\` in your server entry
|
|
1650
|
+
- **Run \`generate_client\`** after adding routes to update the typed client
|
|
1651
|
+
- **Keep routes thin** - delegate business logic to plugin service methods
|
|
1535
1652
|
`;
|
|
1536
1653
|
}
|
|
1537
1654
|
|
|
@@ -1679,8 +1796,14 @@ ${outputType ? `\n**Output:** ${outputType}` : ""}
|
|
|
1679
1796
|
### Next Steps
|
|
1680
1797
|
|
|
1681
1798
|
1. ${useClassHandler ? "Implement the handler logic in the handler file" : "The route is ready to use"}
|
|
1682
|
-
2. Run \`donkeylabs generate\` to update types
|
|
1799
|
+
2. Run \`donkeylabs generate\` to update types and regenerate the API client
|
|
1683
1800
|
3. Test the route
|
|
1801
|
+
|
|
1802
|
+
### ⚠️ Reminders
|
|
1803
|
+
- **Run \`generate_client\`** to update the typed API client after adding routes
|
|
1804
|
+
- **Keep handler thin** - call plugin service methods for business logic
|
|
1805
|
+
- **Use Kysely** for database queries in your service methods, never raw SQL
|
|
1806
|
+
${projectConfig.adapter === "sveltekit" ? "- **SvelteKit:** Use \\`createApi({ locals })\\` in +page.server.ts for direct calls" : ""}
|
|
1684
1807
|
`;
|
|
1685
1808
|
}
|
|
1686
1809
|
|