create-kubojs 0.1.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 +266 -0
- package/dist/chunk-BtN16TXe.mjs +28 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +293 -0
- package/dist/index.d.mts +494 -0
- package/dist/index.mjs +3 -0
- package/dist/src-BAYXN3Za.mjs +7936 -0
- package/dist/virtual.d.mts +5 -0
- package/dist/virtual.mjs +4 -0
- package/package.json +104 -0
package/README.md
ADDED
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
# Create kubojs CLI
|
|
2
|
+
|
|
3
|
+
A modern CLI tool for scaffolding end-to-end type-safe TypeScript projects with best practices and customizable configurations
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
Run without installing globally:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# Using bun (recommended)
|
|
13
|
+
bun create kubojs@latest
|
|
14
|
+
|
|
15
|
+
# Using pnpm
|
|
16
|
+
pnpm create kubojs@latest
|
|
17
|
+
|
|
18
|
+
# Using npm
|
|
19
|
+
npx create-kubojs@latest
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Follow the prompts to configure your project or use the `--yes` flag for defaults.
|
|
23
|
+
|
|
24
|
+
## Features
|
|
25
|
+
|
|
26
|
+
| Category | Options |
|
|
27
|
+
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
28
|
+
| **TypeScript** | End-to-end type safety across all parts of your application |
|
|
29
|
+
| **Frontend** | • React with TanStack Router<br>• React with React Router<br>• React with TanStack Start (SSR)<br>• Next.js<br>• SvelteKit<br>• Nuxt (Vue)<br>• SolidJS<br>• Astro<br>• React Native bare Expo<br>• React Native with NativeWind (via Expo)<br>• React Native with Unistyles (via Expo)<br>• None |
|
|
30
|
+
| **Backend** | • Hono<br>• Express<br>• Elysia<br>• Fastify<br>• Self (fullstack inside the web app)<br>• Convex<br>• None |
|
|
31
|
+
| **API Layer** | • tRPC (type-safe APIs)<br>• oRPC (OpenAPI-compatible type-safe APIs)<br>• None |
|
|
32
|
+
| **Runtime** | • Bun<br>• Node.js<br>• Cloudflare Workers<br>• None |
|
|
33
|
+
| **Database** | • SQLite<br>• PostgreSQL<br>• MySQL<br>• MongoDB<br>• None |
|
|
34
|
+
| **ORM** | • Drizzle (TypeScript-first)<br>• Prisma (feature-rich)<br>• Mongoose (for MongoDB)<br>• None |
|
|
35
|
+
| **Database Setup** | • Turso (SQLite)<br>• Cloudflare D1 (SQLite)<br>• Neon (PostgreSQL)<br>• Supabase (PostgreSQL)<br>• Prisma Postgres<br>• MongoDB Atlas<br>• None (manual setup) |
|
|
36
|
+
| **Authentication** | • Better Auth<br>• Clerk |
|
|
37
|
+
| **Styling** | Tailwind CSS with a shared shadcn/ui package for React web apps |
|
|
38
|
+
| **Addons** | • PWA support<br>• Tauri (desktop applications)<br>• Electrobun (lightweight desktop shell)<br>• Starlight and Fumadocs (documentation sites)<br>• Biome, Oxlint, Ultracite, or Vite+ (linting and formatting)<br>• Lefthook, Husky (Git hooks)<br>• evlog (request logging for server/fullstack backends)<br>• MCP, Skills (agent tooling)<br>• OpenTUI, WXT (platform extensions)<br>• Turborepo, Nx, or Vite+ (monorepo orchestration) |
|
|
39
|
+
| **Examples** | • Todo app<br>• AI Chat interface (using Vercel AI SDK) |
|
|
40
|
+
| **Developer Experience** | • Automatic Git initialization<br>• Package manager choice (npm, pnpm, bun)<br>• Automatic dependency installation |
|
|
41
|
+
|
|
42
|
+
## Usage
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
Usage: kubojs [project-directory] [options]
|
|
46
|
+
|
|
47
|
+
Options:
|
|
48
|
+
-V, --version Output the version number
|
|
49
|
+
-y, --yes Use default configuration
|
|
50
|
+
--template <type> Use a template (mern, pern, t3, uniwind, none)
|
|
51
|
+
--database <type> Database type (none, sqlite, postgres, mysql, mongodb)
|
|
52
|
+
--orm <type> ORM type (none, drizzle, prisma, mongoose)
|
|
53
|
+
--dry-run Validate configuration without writing files
|
|
54
|
+
--auth <provider> Authentication (better-auth, clerk, none)
|
|
55
|
+
--payments <provider> Payments provider (none)
|
|
56
|
+
--frontend <types...> Frontend types (tanstack-router, react-router, tanstack-start, next, nuxt, svelte, solid, astro, native-bare, native-uniwind, native-unistyles, none)
|
|
57
|
+
--addons <types...> Additional addons (pwa, tauri, electrobun, starlight, biome, lefthook, husky, mcp, turborepo, nx, vite-plus, fumadocs, ultracite, oxlint, opentui, wxt, skills, evlog, none)
|
|
58
|
+
--examples <types...> Examples to include (todo, ai, none)
|
|
59
|
+
--git Initialize git repository
|
|
60
|
+
--no-git Skip git initialization
|
|
61
|
+
--package-manager <pm> Package manager (npm, pnpm, bun)
|
|
62
|
+
--install Install dependencies
|
|
63
|
+
--no-install Skip installing dependencies
|
|
64
|
+
--db-setup <setup> Database setup (turso, d1, neon, supabase, prisma-postgres, planetscale, mongodb-atlas, docker, none)
|
|
65
|
+
--web-deploy <setup> Web deployment (cloudflare, docker, vercel, none)
|
|
66
|
+
--server-deploy <setup> Server deployment (cloudflare, docker, vercel, none)
|
|
67
|
+
--backend <framework> Backend framework (hono, express, fastify, elysia, convex, self, none)
|
|
68
|
+
--runtime <runtime> Runtime (bun, node, workers, none)
|
|
69
|
+
--api <type> API type (trpc, orpc, none)
|
|
70
|
+
--directory-conflict <strategy> Directory strategy (merge, overwrite, increment, error)
|
|
71
|
+
--manual-db Skip automatic database setup prompts
|
|
72
|
+
-h, --help Display help
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Agent-Focused Commands
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# Raw JSON payload input (agent-friendly)
|
|
79
|
+
kubojs create-json --input '{"projectName":"my-app","yes":true,"dryRun":true}'
|
|
80
|
+
kubojs add-json --input '{"projectDir":"./my-app","addons":["wxt"],"addonOptions":{"wxt":{"template":"react"}}}'
|
|
81
|
+
kubojs create-json --input '{"projectName":"db-app","database":"postgres","orm":"drizzle","dbSetup":"neon","dbSetupOptions":{"mode":"manual"}}'
|
|
82
|
+
|
|
83
|
+
# Runtime schema/introspection output
|
|
84
|
+
kubojs schema --name all
|
|
85
|
+
kubojs schema --name createInput
|
|
86
|
+
kubojs schema --name addInput
|
|
87
|
+
kubojs schema --name addonOptions
|
|
88
|
+
kubojs schema --name dbSetupOptions
|
|
89
|
+
kubojs schema --name cli
|
|
90
|
+
|
|
91
|
+
# Local stdio MCP server
|
|
92
|
+
npx kubojs@latest mcp
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
To install kubojs into supported agent configs with `add-mcp` and avoid relying on a global CLI install:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
npx -y add-mcp@latest "npx -y kubojs@latest mcp"
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
When you scaffold with the `mcp` addon, kubojs itself can also be installed into supported agent configs through `add-mcp` using a package runner command instead of assuming a global CLI install. For Bun projects, the generated config uses the equivalent `bunx kubojs@latest mcp` server command inside `add-mcp`.
|
|
102
|
+
|
|
103
|
+
For MCP project creation, prefer `install: false`. Long dependency installs can exceed common MCP client request timeouts, so the safest flow is to scaffold first and run your package manager install command afterward in the project directory.
|
|
104
|
+
|
|
105
|
+
## Telemetry
|
|
106
|
+
|
|
107
|
+
This CLI collects anonymous usage data to help improve the tool. The data collected includes:
|
|
108
|
+
|
|
109
|
+
- Configuration options selected
|
|
110
|
+
- CLI version
|
|
111
|
+
- Node.js version
|
|
112
|
+
- Platform (OS)
|
|
113
|
+
|
|
114
|
+
**Telemetry is enabled by default in published versions** to help us understand usage patterns and improve the tool.
|
|
115
|
+
|
|
116
|
+
### Disabling Telemetry
|
|
117
|
+
|
|
118
|
+
You can disable telemetry by setting the `BTS_TELEMETRY_DISABLED` environment variable:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
# Disable telemetry for a single run
|
|
122
|
+
BTS_TELEMETRY_DISABLED=1 npx kubojs
|
|
123
|
+
|
|
124
|
+
# Disable telemetry globally in your shell profile (.bashrc, .zshrc, etc.)
|
|
125
|
+
export BTS_TELEMETRY_DISABLED=1
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Examples
|
|
129
|
+
|
|
130
|
+
Create a project with default configuration:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
npx kubojs --yes
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Validate a command without writing files:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
npx kubojs --yes --dry-run
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Create a project with specific options:
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
npx kubojs --database postgres --orm drizzle --auth better-auth --addons pwa biome
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Create a project with Elysia backend and Node.js runtime:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
npx kubojs --backend elysia --runtime node
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Create a project with multiple frontend options (one web + one native):
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
npx kubojs --frontend tanstack-router native-bare
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Create a project with examples:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
npx kubojs --examples todo ai
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Create a project with Turso database setup:
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
npx kubojs --database sqlite --orm drizzle --db-setup turso
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Create a project with Supabase PostgreSQL setup:
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
npx kubojs --database postgres --orm drizzle --db-setup supabase --auth better-auth
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Create a project with Convex backend:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
npx kubojs --backend convex --frontend tanstack-router
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Create a project with documentation site:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
npx kubojs --addons starlight
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Create a minimal TypeScript project with no backend:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
npx kubojs --backend none --frontend tanstack-router
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Create a backend-only project with no frontend:
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
npx kubojs --frontend none --backend hono --database postgres --orm drizzle
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Create a simple frontend-only project:
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
npx kubojs --backend none --frontend next --addons none --examples none
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Create a Cloudflare Workers project:
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
npx kubojs --backend hono --runtime workers --database sqlite --orm drizzle --db-setup d1
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Create a self-hosted fullstack project on Cloudflare with D1:
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
npx kubojs --backend self --frontend next --api trpc --database sqlite --orm drizzle --db-setup d1 --web-deploy cloudflare
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Create a self-hosted project that ships as Docker containers (web + server + database via Docker Compose):
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
npx kubojs --frontend tanstack-router --backend hono --runtime bun --database postgres --orm drizzle --db-setup docker --web-deploy docker --server-deploy docker
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Create a minimal API-only project:
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
npx kubojs --frontend none --backend hono --api trpc --database none --addons none
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Compatibility Notes
|
|
233
|
+
|
|
234
|
+
- **Convex backend**: Requires `database`, `orm`, `api`, `runtime`, and `server-deploy` to be `none`; auth can be `better-auth`, `clerk`, or `none` depending frontend compatibility
|
|
235
|
+
- **Backend 'none'**: If selected, this option will force related options like API, ORM, database, authentication, and runtime to 'none'. Examples will also be disabled (set to none/empty).
|
|
236
|
+
- **Frontend 'none'**: Creates a backend-only project. When selected, PWA, Tauri, Electrobun, and certain examples may be disabled.
|
|
237
|
+
- **API 'none'**: Disables tRPC/oRPC setup. Can be used with backend frameworks for REST APIs or custom API implementations.
|
|
238
|
+
- **Database 'none'**: Disables database setup and requires ORM to be `none`.
|
|
239
|
+
- **ORM 'none'**: Can be used when you want to handle database operations manually or use a different ORM.
|
|
240
|
+
- **Runtime 'none'**: Only available with Convex backend, backend `none`, or backend `self`.
|
|
241
|
+
- **Cloudflare Workers runtime**: Only compatible with Hono backend. If a database is used, MongoDB is not supported.
|
|
242
|
+
- **Cloudflare D1 setup**: Requires `sqlite` and either `--runtime workers --server-deploy cloudflare` or `--backend self --web-deploy cloudflare`. For `backend self`, D1 is supported on `next`, `tanstack-start`, `nuxt`, `svelte`, and `astro`.
|
|
243
|
+
- **Addons 'none'**: Skips all addons.
|
|
244
|
+
- **Examples 'none'**: Skips all example implementations (todo, AI chat).
|
|
245
|
+
- **Nuxt, Svelte, SolidJS, and Astro** frontends are only compatible with oRPC API layer
|
|
246
|
+
- **PWA support** requires TanStack Router, React Router, Next.js, or SolidJS
|
|
247
|
+
- **Tauri desktop app** requires TanStack Router, React Router, TanStack Start, Next.js, Nuxt, SvelteKit, SolidJS, or Astro
|
|
248
|
+
- **Electrobun desktop app** requires TanStack Router, React Router, TanStack Start, Next.js, Nuxt, SvelteKit, SolidJS, or Astro. Desktop packaging uses static web assets, so SSR-first frontends need a static/export build before desktop builds will work.
|
|
249
|
+
- **AI example** is not compatible with Solid or Astro. With Convex backend, it also excludes Nuxt and Svelte.
|
|
250
|
+
|
|
251
|
+
## Project Structure
|
|
252
|
+
|
|
253
|
+
The created project follows a clean monorepo structure:
|
|
254
|
+
|
|
255
|
+
```
|
|
256
|
+
my-kubo-app/
|
|
257
|
+
├── apps/
|
|
258
|
+
│ ├── web/ # Frontend application
|
|
259
|
+
│ ├── server/ # Backend API
|
|
260
|
+
│ ├── native/ # (optional) Mobile application
|
|
261
|
+
│ └── docs/ # (optional) Documentation site
|
|
262
|
+
├── packages/ # Shared packages
|
|
263
|
+
└── README.md # Auto-generated project documentation
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
After project creation, you'll receive detailed instructions for next steps and additional setup requirements.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
//#region \0rolldown/runtime.js
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __exportAll = (all, no_symbols) => {
|
|
8
|
+
let target = {};
|
|
9
|
+
for (var name in all) __defProp(target, name, {
|
|
10
|
+
get: all[name],
|
|
11
|
+
enumerable: true
|
|
12
|
+
});
|
|
13
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
14
|
+
return target;
|
|
15
|
+
};
|
|
16
|
+
var __copyProps = (to, from, except, desc) => {
|
|
17
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
18
|
+
key = keys[i];
|
|
19
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
20
|
+
get: ((k) => from[k]).bind(null, key),
|
|
21
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
return to;
|
|
25
|
+
};
|
|
26
|
+
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
27
|
+
//#endregion
|
|
28
|
+
export { __reExport as n, __exportAll as t };
|
package/dist/cli.d.mts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
package/dist/cli.mjs
ADDED
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { _ as types_exports, i as SchemaNameSchema, l as create, m as getSchemaResult, s as add, u as createBtsCli, v as getLatestCLIVersion } from "./src-BAYXN3Za.mjs";
|
|
3
|
+
import z from "zod";
|
|
4
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
5
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
6
|
+
//#region src/mcp.ts
|
|
7
|
+
const ToolResponseSchema = z.object({
|
|
8
|
+
ok: z.boolean(),
|
|
9
|
+
data: z.any().optional(),
|
|
10
|
+
error: z.string().optional()
|
|
11
|
+
});
|
|
12
|
+
const SchemaToolInputSchema = z.object({ name: SchemaNameSchema.optional().describe("Schema name to inspect. Defaults to all.") });
|
|
13
|
+
const McpCreateProjectInputSchema = types_exports.CreateInputSchema.safeExtend({
|
|
14
|
+
projectName: z.string().describe("Project name or relative path"),
|
|
15
|
+
frontend: z.array(types_exports.FrontendSchema).describe("Explicit frontend app surfaces. Do not use native frontends as styling options."),
|
|
16
|
+
backend: types_exports.BackendSchema.describe("Explicit backend framework"),
|
|
17
|
+
runtime: types_exports.RuntimeSchema.describe("Explicit runtime environment"),
|
|
18
|
+
database: types_exports.DatabaseSchema.describe("Explicit database choice"),
|
|
19
|
+
orm: types_exports.ORMSchema.describe("Explicit ORM choice"),
|
|
20
|
+
api: types_exports.APISchema.describe("Explicit API layer"),
|
|
21
|
+
auth: types_exports.AuthSchema.describe("Explicit authentication provider"),
|
|
22
|
+
payments: types_exports.PaymentsSchema.describe("Explicit payments provider"),
|
|
23
|
+
addons: z.array(types_exports.AddonsSchema).describe("Explicit addon list. Use [] when no addons are needed."),
|
|
24
|
+
examples: z.array(types_exports.ExamplesSchema).describe("Explicit example list. Use [] when no examples are needed."),
|
|
25
|
+
git: z.boolean().describe("Whether to initialize a git repository"),
|
|
26
|
+
packageManager: types_exports.PackageManagerSchema.describe("Explicit package manager"),
|
|
27
|
+
install: z.boolean().describe("Whether to install dependencies"),
|
|
28
|
+
dbSetup: types_exports.DatabaseSetupSchema.describe("Explicit database setup/provisioning choice"),
|
|
29
|
+
webDeploy: types_exports.WebDeploySchema.describe("Explicit web deployment choice"),
|
|
30
|
+
serverDeploy: types_exports.ServerDeploySchema.describe("Explicit server deployment choice"),
|
|
31
|
+
addonOptions: types_exports.AddonOptionsSchema.optional(),
|
|
32
|
+
dbSetupOptions: types_exports.DbSetupOptionsSchema.optional(),
|
|
33
|
+
directoryConflict: types_exports.DirectoryConflictSchema.optional()
|
|
34
|
+
}).describe("Explicit I dont know project configuration for MCP use. Provide the full stack config instead of relying on inferred defaults.");
|
|
35
|
+
function formatToolSuccess(data) {
|
|
36
|
+
return {
|
|
37
|
+
content: [{
|
|
38
|
+
type: "text",
|
|
39
|
+
text: JSON.stringify(data, null, 2)
|
|
40
|
+
}],
|
|
41
|
+
structuredContent: {
|
|
42
|
+
ok: true,
|
|
43
|
+
data
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function formatToolError(error) {
|
|
48
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
49
|
+
return {
|
|
50
|
+
content: [{
|
|
51
|
+
type: "text",
|
|
52
|
+
text: message
|
|
53
|
+
}],
|
|
54
|
+
structuredContent: {
|
|
55
|
+
ok: false,
|
|
56
|
+
error: message
|
|
57
|
+
},
|
|
58
|
+
isError: true
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function getProjectToolAnnotations() {
|
|
62
|
+
return {
|
|
63
|
+
destructiveHint: true,
|
|
64
|
+
idempotentHint: false,
|
|
65
|
+
openWorldHint: true
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function getMcpInstallTimeoutMessage(packageManager) {
|
|
69
|
+
return [
|
|
70
|
+
"MCP project creation requires `install: false`.",
|
|
71
|
+
"Dependency installation can exceed common MCP client request timeouts and cause the connection to close before the tool returns.",
|
|
72
|
+
`Scaffold the project first, then run \`${packageManager} install\` in the generated project directory from a terminal.`
|
|
73
|
+
].join(" ");
|
|
74
|
+
}
|
|
75
|
+
function getStackGuidance() {
|
|
76
|
+
return {
|
|
77
|
+
workflow: [
|
|
78
|
+
"Call bts_get_schema or bts_get_stack_guidance before constructing a config if the request is ambiguous.",
|
|
79
|
+
"For project creation, build a full explicit config before calling bts_plan_project.",
|
|
80
|
+
"Always call bts_plan_project before bts_create_project.",
|
|
81
|
+
"Only call bts_create_project after the plan succeeds and matches the user's intent.",
|
|
82
|
+
"Use bts_plan_addons before bts_add_addons for existing projects."
|
|
83
|
+
],
|
|
84
|
+
createContract: {
|
|
85
|
+
requiresExplicitFields: [
|
|
86
|
+
"projectName",
|
|
87
|
+
"frontend",
|
|
88
|
+
"backend",
|
|
89
|
+
"runtime",
|
|
90
|
+
"database",
|
|
91
|
+
"orm",
|
|
92
|
+
"api",
|
|
93
|
+
"auth",
|
|
94
|
+
"payments",
|
|
95
|
+
"addons",
|
|
96
|
+
"examples",
|
|
97
|
+
"git",
|
|
98
|
+
"packageManager",
|
|
99
|
+
"install",
|
|
100
|
+
"dbSetup",
|
|
101
|
+
"webDeploy",
|
|
102
|
+
"serverDeploy"
|
|
103
|
+
],
|
|
104
|
+
optionalFields: [
|
|
105
|
+
"addonOptions",
|
|
106
|
+
"dbSetupOptions",
|
|
107
|
+
"directoryConflict"
|
|
108
|
+
],
|
|
109
|
+
rule: "Do not call bts_plan_project or bts_create_project with a partial payload. MCP project creation requires the full explicit stack config."
|
|
110
|
+
},
|
|
111
|
+
fieldNotes: {
|
|
112
|
+
frontend: "frontend is for app surfaces only. Choose explicit app targets such as next, react-router, tanstack-router, native-bare, native-uniwind, or native-unistyles.",
|
|
113
|
+
addons: "addons must be an explicit array. Use [] when no addons are requested.",
|
|
114
|
+
examples: "examples must be an explicit array. Use [] when no examples are requested.",
|
|
115
|
+
dbSetup: "dbSetup is always required. Use 'none' when no managed database provisioning is requested.",
|
|
116
|
+
webDeploy: "webDeploy is always required. Use 'none' when no web deployment target is requested.",
|
|
117
|
+
serverDeploy: "serverDeploy is always required. Use 'none' when no server deployment target is requested.",
|
|
118
|
+
packageManager: "packageManager is always required because installation and reproducible commands depend on it.",
|
|
119
|
+
install: "install is always required. For MCP project creation, prefer false because many clients enforce request timeouts around long-running dependency installs.",
|
|
120
|
+
git: "git is always required. Set it to true or false explicitly instead of relying on defaults."
|
|
121
|
+
},
|
|
122
|
+
ambiguityRules: [
|
|
123
|
+
"If the user request leaves major stack choices unspecified, stop and resolve them before calling bts_plan_project.",
|
|
124
|
+
"Do not infer extra app surfaces, addons, examples, or provisioning choices from a template name or styling preference.",
|
|
125
|
+
"If the user wants the smallest valid stack, still send the full config with explicit 'none', [] , true, or false values where appropriate.",
|
|
126
|
+
"For MCP execution, scaffold with install=false and let the user or agent run dependency installation separately from a terminal session."
|
|
127
|
+
]
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
function createBtsMcpServer() {
|
|
131
|
+
const server = new McpServer({
|
|
132
|
+
name: "kubojs",
|
|
133
|
+
version: getLatestCLIVersion()
|
|
134
|
+
}, { capabilities: { logging: {} } });
|
|
135
|
+
server.registerTool("bts_get_stack_guidance", {
|
|
136
|
+
title: "Get I dont know MCP Guidance",
|
|
137
|
+
description: "Read MCP-specific guidance for choosing valid I dont know configurations. Use this before planning when user intent is ambiguous. This explains the full explicit config required by MCP project creation, plus important field semantics and ambiguity rules.",
|
|
138
|
+
outputSchema: ToolResponseSchema,
|
|
139
|
+
annotations: {
|
|
140
|
+
title: "Get I dont know MCP Guidance",
|
|
141
|
+
readOnlyHint: true,
|
|
142
|
+
destructiveHint: false,
|
|
143
|
+
idempotentHint: true,
|
|
144
|
+
openWorldHint: false
|
|
145
|
+
}
|
|
146
|
+
}, async () => {
|
|
147
|
+
try {
|
|
148
|
+
return formatToolSuccess(getStackGuidance());
|
|
149
|
+
} catch (error) {
|
|
150
|
+
return formatToolError(error);
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
server.registerTool("bts_get_schema", {
|
|
154
|
+
title: "Get I dont know Schemas",
|
|
155
|
+
description: "Inspect I dont know CLI and input schemas so agents can plan valid create/add requests. Use this together with bts_get_stack_guidance before creating a project if any part of the request is ambiguous.",
|
|
156
|
+
inputSchema: SchemaToolInputSchema,
|
|
157
|
+
outputSchema: ToolResponseSchema,
|
|
158
|
+
annotations: {
|
|
159
|
+
title: "Get I dont know Schemas",
|
|
160
|
+
readOnlyHint: true,
|
|
161
|
+
destructiveHint: false,
|
|
162
|
+
idempotentHint: true,
|
|
163
|
+
openWorldHint: false
|
|
164
|
+
}
|
|
165
|
+
}, async ({ name }) => {
|
|
166
|
+
try {
|
|
167
|
+
return formatToolSuccess(getSchemaResult(name ?? "all"));
|
|
168
|
+
} catch (error) {
|
|
169
|
+
return formatToolError(error);
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
server.registerTool("bts_plan_project", {
|
|
173
|
+
title: "Plan I dont know Project",
|
|
174
|
+
description: "Validate and preview an I dont know project creation without writing files or provisioning resources. Always use this before bts_create_project. This tool requires an explicit full stack config rather than a partial payload with inferred defaults.",
|
|
175
|
+
inputSchema: McpCreateProjectInputSchema,
|
|
176
|
+
outputSchema: ToolResponseSchema,
|
|
177
|
+
annotations: {
|
|
178
|
+
title: "Plan I dont know Project",
|
|
179
|
+
readOnlyHint: true,
|
|
180
|
+
destructiveHint: false,
|
|
181
|
+
idempotentHint: true,
|
|
182
|
+
openWorldHint: false
|
|
183
|
+
}
|
|
184
|
+
}, async (input) => {
|
|
185
|
+
try {
|
|
186
|
+
const result = await create(input.projectName, {
|
|
187
|
+
...input,
|
|
188
|
+
dryRun: true,
|
|
189
|
+
disableAnalytics: true
|
|
190
|
+
});
|
|
191
|
+
if (result.isErr()) return formatToolError(result.error);
|
|
192
|
+
return formatToolSuccess(input.install ? {
|
|
193
|
+
...result.value,
|
|
194
|
+
warnings: [getMcpInstallTimeoutMessage(input.packageManager)],
|
|
195
|
+
recommendedMcpExecution: {
|
|
196
|
+
...input,
|
|
197
|
+
install: false
|
|
198
|
+
}
|
|
199
|
+
} : result.value);
|
|
200
|
+
} catch (error) {
|
|
201
|
+
return formatToolError(error);
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
server.registerTool("bts_create_project", {
|
|
205
|
+
title: "Create I dont know Project",
|
|
206
|
+
description: "Create an I dont know project on disk using the same silent programmatic flow as the CLI JSON API. Call this only after bts_plan_project succeeds and the plan clearly matches the user's intent. This tool requires an explicit full stack config.",
|
|
207
|
+
inputSchema: McpCreateProjectInputSchema,
|
|
208
|
+
outputSchema: ToolResponseSchema,
|
|
209
|
+
annotations: {
|
|
210
|
+
title: "Create I dont know Project",
|
|
211
|
+
...getProjectToolAnnotations()
|
|
212
|
+
}
|
|
213
|
+
}, async (input) => {
|
|
214
|
+
try {
|
|
215
|
+
if (input.install) return formatToolError(getMcpInstallTimeoutMessage(input.packageManager));
|
|
216
|
+
const result = await create(input.projectName, {
|
|
217
|
+
...input,
|
|
218
|
+
disableAnalytics: true
|
|
219
|
+
});
|
|
220
|
+
if (result.isErr()) return formatToolError(result.error);
|
|
221
|
+
return formatToolSuccess(result.value);
|
|
222
|
+
} catch (error) {
|
|
223
|
+
return formatToolError(error);
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
server.registerTool("bts_plan_addons", {
|
|
227
|
+
title: "Plan I dont know Addons",
|
|
228
|
+
description: "Validate and preview addon installation for an existing I dont know project without writing files. Always use this before bts_add_addons when the addon set or nested options are uncertain.",
|
|
229
|
+
inputSchema: types_exports.AddInputSchema,
|
|
230
|
+
outputSchema: ToolResponseSchema,
|
|
231
|
+
annotations: {
|
|
232
|
+
title: "Plan I dont know Addons",
|
|
233
|
+
readOnlyHint: true,
|
|
234
|
+
destructiveHint: false,
|
|
235
|
+
idempotentHint: true,
|
|
236
|
+
openWorldHint: false
|
|
237
|
+
}
|
|
238
|
+
}, async (input) => {
|
|
239
|
+
try {
|
|
240
|
+
const result = await add({
|
|
241
|
+
...input,
|
|
242
|
+
dryRun: true
|
|
243
|
+
});
|
|
244
|
+
if (!result?.success) return formatToolError(result?.error ?? "Failed to plan addon installation");
|
|
245
|
+
return formatToolSuccess(result);
|
|
246
|
+
} catch (error) {
|
|
247
|
+
return formatToolError(error);
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
server.registerTool("bts_add_addons", {
|
|
251
|
+
title: "Add I dont know Addons",
|
|
252
|
+
description: "Install addons into an existing I dont know project using the same silent flow as add-json. Call this only after bts_plan_addons succeeds and the planned changes match the user's intent.",
|
|
253
|
+
inputSchema: types_exports.AddInputSchema,
|
|
254
|
+
outputSchema: ToolResponseSchema,
|
|
255
|
+
annotations: {
|
|
256
|
+
title: "Add I dont know Addons",
|
|
257
|
+
destructiveHint: true,
|
|
258
|
+
idempotentHint: false,
|
|
259
|
+
openWorldHint: true
|
|
260
|
+
}
|
|
261
|
+
}, async (input) => {
|
|
262
|
+
try {
|
|
263
|
+
const result = await add(input);
|
|
264
|
+
if (!result?.success) return formatToolError(result?.error ?? "Failed to add addons");
|
|
265
|
+
return formatToolSuccess(result);
|
|
266
|
+
} catch (error) {
|
|
267
|
+
return formatToolError(error);
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
return server;
|
|
271
|
+
}
|
|
272
|
+
async function startBtsMcpServer() {
|
|
273
|
+
const server = createBtsMcpServer();
|
|
274
|
+
const transport = new StdioServerTransport();
|
|
275
|
+
await server.connect(transport);
|
|
276
|
+
}
|
|
277
|
+
//#endregion
|
|
278
|
+
//#region src/cli.ts
|
|
279
|
+
const [, , command, ...args] = process.argv;
|
|
280
|
+
if (command === "mcp") {
|
|
281
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
282
|
+
console.log(`Usage: kubojs mcp
|
|
283
|
+
|
|
284
|
+
Start the I dont know MCP server over stdio.
|
|
285
|
+
|
|
286
|
+
This command is intended to be launched by an MCP client, for example:
|
|
287
|
+
kubojs mcp`);
|
|
288
|
+
process.exit(0);
|
|
289
|
+
}
|
|
290
|
+
await startBtsMcpServer();
|
|
291
|
+
} else await createBtsCli().run();
|
|
292
|
+
//#endregion
|
|
293
|
+
export {};
|