naro-mcp 0.9.0 → 0.10.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 +1 -1
- package/dist/index.js +106 -21
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -65,7 +65,7 @@ Headless/CI agents can skip `naro login` and set a token instead:
|
|
|
65
65
|
| `cancel_deployment` | Stops a build that is still running (QUEUED–BUILDING). Does not undo a deployment that already went live — use `rollback_deployment` for that |
|
|
66
66
|
| `enable_database`, `get_database`, `list_tables` | The project's D1 database: turn it on, status/size/limits, schema (verbose: true for columns, indexes and foreign keys) |
|
|
67
67
|
| `execute_sql` | Run SQL (argument `query`, optional `params` for a single statement; several statements run as one transaction). Destructive; under `--read-only` it stays but accepts a single read statement only |
|
|
68
|
-
| `apply_migration`, `list_migrations`, `generate_typescript_types` | Numbered migrations in the `d1_migrations` ledger wrangler also uses (each file all-or-nothing), and TypeScript types for the schema (text only; its `Database` is what `createClient<Database>()` from
|
|
68
|
+
| `apply_migration`, `list_migrations`, `generate_typescript_types` | Numbered migrations in the `d1_migrations` ledger wrangler also uses (each file all-or-nothing), and TypeScript types for the schema (text only; its `Database` is what `createClient<Database>()` from `naro-js` takes) |
|
|
69
69
|
| `create_table`, `alter_table`, `drop_table`, `create_index`, `drop_index` | Schema changes without SQL: naro renders checked DDL, applies it as one numbered migration (`NNNN_schema_<op>_<table>.sql`) and writes the file like `apply_migration`. `alter_table` adds, renames or drops a column or renames the table. Dropping a table or column needs `confirm`; `alter_table`, `drop_table` and `drop_index` are destructive and hidden under `--read-only`. `dryRun: true` returns the SQL only |
|
|
70
70
|
| `export_database` | SQL dump of the database (`schemaOnly`, `dataOnly`, `tables`): waits up to 5 minutes and returns a signed download link plus `atBookmark`, the point the dump reflects |
|
|
71
71
|
| `restore_database` | Time Travel restore to a `bookmark` or a `timestamp` (last 30 days). Destructive; hidden under `--read-only`. Returns `previousBookmark`, which undoes it |
|
package/dist/index.js
CHANGED
|
@@ -1179,6 +1179,35 @@ function backendInfo(body) {
|
|
|
1179
1179
|
turningOff: body.turningOff === true
|
|
1180
1180
|
};
|
|
1181
1181
|
}
|
|
1182
|
+
function authConfig(body) {
|
|
1183
|
+
return {
|
|
1184
|
+
...body,
|
|
1185
|
+
signupsEnabled: typeof body.signupsEnabled === "boolean" ? body.signupsEnabled : true,
|
|
1186
|
+
passwordMinLength: typeof body.passwordMinLength === "number" ? body.passwordMinLength : 6
|
|
1187
|
+
};
|
|
1188
|
+
}
|
|
1189
|
+
function isRecord(value) {
|
|
1190
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1191
|
+
}
|
|
1192
|
+
async function authChange(answer) {
|
|
1193
|
+
let body;
|
|
1194
|
+
try {
|
|
1195
|
+
body = await answer;
|
|
1196
|
+
} catch (error51) {
|
|
1197
|
+
const details = isNaroError(error51) ? error51.details : void 0;
|
|
1198
|
+
if (isNaroError(error51) && error51.code === "BACKEND_PROVISION_FAILED" && isRecord(details?.auth) && isRecord(details.backend))
|
|
1199
|
+
throw new NaroError(error51.code, error51.message, {
|
|
1200
|
+
...error51.status !== void 0 ? { status: error51.status } : {},
|
|
1201
|
+
details: {
|
|
1202
|
+
...details,
|
|
1203
|
+
auth: authConfig(details.auth),
|
|
1204
|
+
backend: backendInfo(details.backend)
|
|
1205
|
+
}
|
|
1206
|
+
});
|
|
1207
|
+
throw error51;
|
|
1208
|
+
}
|
|
1209
|
+
return { auth: authConfig(body.auth), backend: backendInfo(body.backend) };
|
|
1210
|
+
}
|
|
1182
1211
|
var BackendApi = class {
|
|
1183
1212
|
constructor(client) {
|
|
1184
1213
|
this.client = client;
|
|
@@ -1311,11 +1340,13 @@ var BackendApi = class {
|
|
|
1311
1340
|
* and the callback URLs to register with the providers. Never a secret.
|
|
1312
1341
|
*/
|
|
1313
1342
|
async auth(projectId) {
|
|
1314
|
-
return
|
|
1315
|
-
this.
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1343
|
+
return authConfig(
|
|
1344
|
+
await this.client.request(
|
|
1345
|
+
this.path(projectId, "/auth"),
|
|
1346
|
+
{
|
|
1347
|
+
context: "Read sign-in settings"
|
|
1348
|
+
}
|
|
1349
|
+
)
|
|
1319
1350
|
);
|
|
1320
1351
|
}
|
|
1321
1352
|
/**
|
|
@@ -1324,32 +1355,86 @@ var BackendApi = class {
|
|
|
1324
1355
|
* (nothing is saved), `BACKEND_NOT_READY` before the first provision,
|
|
1325
1356
|
* `BACKEND_OFF` while the backend is turned off (nothing is saved),
|
|
1326
1357
|
* `VERIFICATION_NEEDS_EMAIL` for a state where nobody could sign in. A
|
|
1327
|
-
* failed upload
|
|
1328
|
-
*
|
|
1358
|
+
* failed upload throws `BACKEND_PROVISION_FAILED` (502): the settings are
|
|
1359
|
+
* saved, the message says whether the worker runs them yet, `details`
|
|
1360
|
+
* holds `{ auth, backend }`, and `enable` finishes. (A control plane from
|
|
1361
|
+
* before that resolves with `backend.status` `error` instead.) Two
|
|
1362
|
+
* minutes, like enable.
|
|
1329
1363
|
*/
|
|
1330
1364
|
async setAuth(projectId, patch) {
|
|
1331
|
-
|
|
1332
|
-
this.path(projectId, "/auth"),
|
|
1333
|
-
{
|
|
1365
|
+
return authChange(
|
|
1366
|
+
this.client.request(this.path(projectId, "/auth"), {
|
|
1334
1367
|
method: "PUT",
|
|
1335
1368
|
body: patch,
|
|
1336
1369
|
context: "Change sign-in settings",
|
|
1337
1370
|
timeoutMs: PROVISION_TIMEOUT_MS
|
|
1338
|
-
}
|
|
1371
|
+
})
|
|
1339
1372
|
);
|
|
1340
|
-
return { auth: answer.auth, backend: backendInfo(answer.backend) };
|
|
1341
1373
|
}
|
|
1342
1374
|
/** Removes email or one provider; the same answer as `setAuth`. */
|
|
1343
1375
|
async removeAuth(projectId, target) {
|
|
1376
|
+
return authChange(
|
|
1377
|
+
this.client.request(
|
|
1378
|
+
this.path(projectId, `/auth?target=${encodeURIComponent(target)}`),
|
|
1379
|
+
{
|
|
1380
|
+
method: "DELETE",
|
|
1381
|
+
context: "Change sign-in settings",
|
|
1382
|
+
timeoutMs: PROVISION_TIMEOUT_MS
|
|
1383
|
+
}
|
|
1384
|
+
)
|
|
1385
|
+
);
|
|
1386
|
+
}
|
|
1387
|
+
/**
|
|
1388
|
+
* The project's users, newest first (spec 2026-09-26 §2.2): page 1 and 50
|
|
1389
|
+
* a page unless given, at most 1000. `database.read`. `BACKEND_OFF` while
|
|
1390
|
+
* the backend is turned off, `BACKEND_NOT_READY` before it is ready,
|
|
1391
|
+
* `BACKEND_OUTDATED` while its Naro worker predates user management
|
|
1392
|
+
* (`enable` updates it), `BACKEND_UNAVAILABLE` when it cannot be reached.
|
|
1393
|
+
*/
|
|
1394
|
+
async listUsers(projectId, options2 = {}) {
|
|
1395
|
+
const query = new URLSearchParams();
|
|
1396
|
+
if (options2.page !== void 0) query.set("page", String(options2.page));
|
|
1397
|
+
if (options2.perPage !== void 0)
|
|
1398
|
+
query.set("perPage", String(options2.perPage));
|
|
1399
|
+
const suffix = query.size > 0 ? `?${query.toString()}` : "";
|
|
1400
|
+
const body = await this.client.request(
|
|
1401
|
+
this.path(projectId, `/users${suffix}`),
|
|
1402
|
+
{ context: "List users" }
|
|
1403
|
+
);
|
|
1404
|
+
return { users: body.users, total: body.total };
|
|
1405
|
+
}
|
|
1406
|
+
/**
|
|
1407
|
+
* Creates a user with a password, confirmed unless `emailConfirm: false`
|
|
1408
|
+
* — also while sign-ups are closed and while sign-in waits for a
|
|
1409
|
+
* confirmed email. A username-only user answers `email: null`.
|
|
1410
|
+
* `database.write`. The Naro worker's refusals come through as it said
|
|
1411
|
+
* them: `USERNAME_TAKEN` (409), `USER_ALREADY_EXISTS_USE_ANOTHER_EMAIL`
|
|
1412
|
+
* (422), `PASSWORD_TOO_SHORT` ("Use at least {n} characters."),
|
|
1413
|
+
* `VALIDATION_ERROR`, `WRITE_QUOTA_EXCEEDED` (429, `details.retryAfter`).
|
|
1414
|
+
*/
|
|
1415
|
+
async createUser(projectId, input) {
|
|
1416
|
+
const body = { password: input.password };
|
|
1417
|
+
if (input.email !== void 0) body.email = input.email;
|
|
1418
|
+
if (input.username !== void 0) body.username = input.username;
|
|
1419
|
+
if (input.emailConfirm !== void 0)
|
|
1420
|
+
body.emailConfirm = input.emailConfirm;
|
|
1344
1421
|
const answer = await this.client.request(
|
|
1345
|
-
this.path(projectId,
|
|
1346
|
-
{
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1422
|
+
this.path(projectId, "/users"),
|
|
1423
|
+
{ method: "POST", body, context: "Create user" }
|
|
1424
|
+
);
|
|
1425
|
+
return answer.user;
|
|
1426
|
+
}
|
|
1427
|
+
/**
|
|
1428
|
+
* Deletes a user with its sign-in methods, and ends its sessions. Answers
|
|
1429
|
+
* the user it was. `USER_NOT_FOUND` (404) for an id that is not one.
|
|
1430
|
+
* `database.write`.
|
|
1431
|
+
*/
|
|
1432
|
+
async deleteUser(projectId, userId) {
|
|
1433
|
+
const answer = await this.client.request(
|
|
1434
|
+
this.path(projectId, `/users/${encodeURIComponent(userId)}`),
|
|
1435
|
+
{ method: "DELETE", context: "Delete user" }
|
|
1351
1436
|
);
|
|
1352
|
-
return
|
|
1437
|
+
return answer.user;
|
|
1353
1438
|
}
|
|
1354
1439
|
/** Every stored policy, by table name. Tables without one deny anon and signed-in requests. */
|
|
1355
1440
|
async policies(projectId) {
|
|
@@ -17397,7 +17482,7 @@ var DATABASE_TOOLS = [
|
|
|
17397
17482
|
destructiveHint: false,
|
|
17398
17483
|
idempotentHint: true
|
|
17399
17484
|
},
|
|
17400
|
-
description: `Generates TypeScript types for the D1 schema: one Row interface per table and view, a Database type with Row, Insert and Update per table that createClient<Database>() from
|
|
17485
|
+
description: `Generates TypeScript types for the D1 schema: one Row interface per table and view, a Database type with Row, Insert and Update per table that createClient<Database>() from naro-js reads, the Tables, TablesInsert and TablesUpdate helpers, and an Env with the DB binding. Returns the text only \u2014 write it to a file yourself (for example src/database.types.ts). A view that could not be described is an empty interface in the text and is named under the undescribed key. Where the backend's insert rule for a table is owner, its owner column is optional in Insert (the backend fills it); when the policies cannot be read, the result says policies: "unavailable" with policiesReason, and the owner columns stay required. ${UNTRUSTED}`,
|
|
17401
17486
|
inputSchema: { type: "object", properties: { ...PROJECT_ARGS } },
|
|
17402
17487
|
handler: async (args, deps) => {
|
|
17403
17488
|
assertProjectArgs(args);
|
|
@@ -18339,7 +18424,7 @@ function toolErrorJson(error51) {
|
|
|
18339
18424
|
}
|
|
18340
18425
|
|
|
18341
18426
|
// src/server.ts
|
|
18342
|
-
var SERVER_VERSION = "0.
|
|
18427
|
+
var SERVER_VERSION = "0.10.0";
|
|
18343
18428
|
function visibleTools(options2) {
|
|
18344
18429
|
const { features, readOnly } = options2;
|
|
18345
18430
|
return TOOLS.flatMap((tool) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "naro-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"naro-mcp": "./dist/index.js"
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
20
20
|
"@supabase/supabase-js": "2.112.3",
|
|
21
|
-
"naro-cli": "0.
|
|
21
|
+
"naro-cli": "0.10.0"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"tsup": "8.5.0",
|