@getjack/jack 0.1.26 → 0.1.27
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/logs.ts +74 -12
- package/src/commands/services.ts +255 -4
- package/src/index.ts +4 -1
- package/src/lib/control-plane.ts +39 -0
- package/src/lib/services/db-execute.ts +6 -3
- package/src/lib/services/storage-config.ts +669 -0
- package/src/lib/services/storage-create.ts +152 -0
- package/src/lib/services/storage-delete.ts +89 -0
- package/src/lib/services/storage-info.ts +105 -0
- package/src/lib/services/storage-list.ts +42 -0
- package/src/mcp/resources/index.ts +1 -1
- package/src/mcp/tools/index.ts +480 -0
package/src/mcp/tools/index.ts
CHANGED
|
@@ -2,6 +2,9 @@ import type { Server as McpServer } from "@modelcontextprotocol/sdk/server/index
|
|
|
2
2
|
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { JackError, JackErrorCode } from "../../lib/errors.ts";
|
|
5
|
+
import { authFetch } from "../../lib/auth/index.ts";
|
|
6
|
+
import { getControlApiUrl, startLogSession } from "../../lib/control-plane.ts";
|
|
7
|
+
import { getDeployMode, getProjectId } from "../../lib/project-link.ts";
|
|
5
8
|
import { createProject, deployProject, getProjectStatus } from "../../lib/project-operations.ts";
|
|
6
9
|
import { listAllProjects } from "../../lib/project-resolver.ts";
|
|
7
10
|
import { createDatabase } from "../../lib/services/db-create.ts";
|
|
@@ -12,6 +15,10 @@ import {
|
|
|
12
15
|
wrapResultsForMcp,
|
|
13
16
|
} from "../../lib/services/db-execute.ts";
|
|
14
17
|
import { listDatabases } from "../../lib/services/db-list.ts";
|
|
18
|
+
import { createStorageBucket } from "../../lib/services/storage-create.ts";
|
|
19
|
+
import { deleteStorageBucket } from "../../lib/services/storage-delete.ts";
|
|
20
|
+
import { getStorageBucketInfo } from "../../lib/services/storage-info.ts";
|
|
21
|
+
import { listStorageBuckets } from "../../lib/services/storage-list.ts";
|
|
15
22
|
import { createVectorizeIndex } from "../../lib/services/vectorize-create.ts";
|
|
16
23
|
import { deleteVectorizeIndex } from "../../lib/services/vectorize-delete.ts";
|
|
17
24
|
import { getVectorizeInfo } from "../../lib/services/vectorize-info.ts";
|
|
@@ -119,6 +126,69 @@ const GetVectorizeInfoSchema = z.object({
|
|
|
119
126
|
.describe("Path to project directory (defaults to current directory)"),
|
|
120
127
|
});
|
|
121
128
|
|
|
129
|
+
const CreateStorageBucketSchema = z.object({
|
|
130
|
+
name: z.string().optional().describe("Bucket name (auto-generated if not provided)"),
|
|
131
|
+
project_path: z
|
|
132
|
+
.string()
|
|
133
|
+
.optional()
|
|
134
|
+
.describe("Path to project directory (defaults to current directory)"),
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
const ListStorageBucketsSchema = z.object({
|
|
138
|
+
project_path: z
|
|
139
|
+
.string()
|
|
140
|
+
.optional()
|
|
141
|
+
.describe("Path to project directory (defaults to current directory)"),
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
const GetStorageInfoSchema = z.object({
|
|
145
|
+
name: z.string().optional().describe("Bucket name (defaults to first bucket if not provided)"),
|
|
146
|
+
project_path: z
|
|
147
|
+
.string()
|
|
148
|
+
.optional()
|
|
149
|
+
.describe("Path to project directory (defaults to current directory)"),
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
const DeleteStorageBucketSchema = z.object({
|
|
153
|
+
name: z.string().describe("Bucket name to delete"),
|
|
154
|
+
project_path: z
|
|
155
|
+
.string()
|
|
156
|
+
.optional()
|
|
157
|
+
.describe("Path to project directory (defaults to current directory)"),
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
const StartLogSessionSchema = z.object({
|
|
161
|
+
project_path: z
|
|
162
|
+
.string()
|
|
163
|
+
.optional()
|
|
164
|
+
.describe("Path to project directory (defaults to current directory)"),
|
|
165
|
+
label: z.string().optional().describe("Optional short tag/description for the log session"),
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
const TailLogsSchema = z.object({
|
|
169
|
+
project_path: z
|
|
170
|
+
.string()
|
|
171
|
+
.optional()
|
|
172
|
+
.describe("Path to project directory (defaults to current directory)"),
|
|
173
|
+
label: z.string().optional().describe("Optional short tag/description for the log session"),
|
|
174
|
+
max_events: z
|
|
175
|
+
.number()
|
|
176
|
+
.int()
|
|
177
|
+
.min(1)
|
|
178
|
+
.max(200)
|
|
179
|
+
.optional()
|
|
180
|
+
.default(50)
|
|
181
|
+
.describe("Maximum number of log events to collect (default: 50, max: 200)"),
|
|
182
|
+
duration_ms: z
|
|
183
|
+
.number()
|
|
184
|
+
.int()
|
|
185
|
+
.min(100)
|
|
186
|
+
.max(10_000)
|
|
187
|
+
.optional()
|
|
188
|
+
.default(2_000)
|
|
189
|
+
.describe("How long to listen before returning (default: 2000ms, max: 10000ms)"),
|
|
190
|
+
});
|
|
191
|
+
|
|
122
192
|
export function registerTools(server: McpServer, _options: McpServerOptions, debug: DebugLogger) {
|
|
123
193
|
// Register tool list handler
|
|
124
194
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
@@ -190,6 +260,50 @@ export function registerTools(server: McpServer, _options: McpServerOptions, deb
|
|
|
190
260
|
},
|
|
191
261
|
},
|
|
192
262
|
},
|
|
263
|
+
{
|
|
264
|
+
name: "start_log_session",
|
|
265
|
+
description:
|
|
266
|
+
"Start or renew a 1-hour real-time log session for a managed (jack cloud) project. Returns an SSE stream URL.",
|
|
267
|
+
inputSchema: {
|
|
268
|
+
type: "object",
|
|
269
|
+
properties: {
|
|
270
|
+
project_path: {
|
|
271
|
+
type: "string",
|
|
272
|
+
description: "Path to project directory (defaults to current directory)",
|
|
273
|
+
},
|
|
274
|
+
label: {
|
|
275
|
+
type: "string",
|
|
276
|
+
description: "Optional short tag/description for the session",
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
},
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
name: "tail_logs",
|
|
283
|
+
description:
|
|
284
|
+
"Collect a short sample of live log events (JSON) from a managed (jack cloud) project. Useful for agentic debugging.",
|
|
285
|
+
inputSchema: {
|
|
286
|
+
type: "object",
|
|
287
|
+
properties: {
|
|
288
|
+
project_path: {
|
|
289
|
+
type: "string",
|
|
290
|
+
description: "Path to project directory (defaults to current directory)",
|
|
291
|
+
},
|
|
292
|
+
label: {
|
|
293
|
+
type: "string",
|
|
294
|
+
description: "Optional short tag/description for the session",
|
|
295
|
+
},
|
|
296
|
+
max_events: {
|
|
297
|
+
type: "number",
|
|
298
|
+
description: "Maximum number of events to collect (default: 50, max: 200)",
|
|
299
|
+
},
|
|
300
|
+
duration_ms: {
|
|
301
|
+
type: "number",
|
|
302
|
+
description: "How long to listen before returning (default: 2000ms, max: 10000ms)",
|
|
303
|
+
},
|
|
304
|
+
},
|
|
305
|
+
},
|
|
306
|
+
},
|
|
193
307
|
{
|
|
194
308
|
name: "create_database",
|
|
195
309
|
description:
|
|
@@ -332,6 +446,72 @@ export function registerTools(server: McpServer, _options: McpServerOptions, deb
|
|
|
332
446
|
required: ["name"],
|
|
333
447
|
},
|
|
334
448
|
},
|
|
449
|
+
{
|
|
450
|
+
name: "create_storage_bucket",
|
|
451
|
+
description:
|
|
452
|
+
"Create an R2 storage bucket for a project. Returns deploy_required=true since binding needs deploy to activate.",
|
|
453
|
+
inputSchema: {
|
|
454
|
+
type: "object",
|
|
455
|
+
properties: {
|
|
456
|
+
name: {
|
|
457
|
+
type: "string",
|
|
458
|
+
description: "Bucket name (auto-generated if not provided)",
|
|
459
|
+
},
|
|
460
|
+
project_path: {
|
|
461
|
+
type: "string",
|
|
462
|
+
description: "Path to project directory (defaults to current directory)",
|
|
463
|
+
},
|
|
464
|
+
},
|
|
465
|
+
},
|
|
466
|
+
},
|
|
467
|
+
{
|
|
468
|
+
name: "list_storage_buckets",
|
|
469
|
+
description: "List all R2 storage buckets for a project.",
|
|
470
|
+
inputSchema: {
|
|
471
|
+
type: "object",
|
|
472
|
+
properties: {
|
|
473
|
+
project_path: {
|
|
474
|
+
type: "string",
|
|
475
|
+
description: "Path to project directory (defaults to current directory)",
|
|
476
|
+
},
|
|
477
|
+
},
|
|
478
|
+
},
|
|
479
|
+
},
|
|
480
|
+
{
|
|
481
|
+
name: "get_storage_info",
|
|
482
|
+
description: "Get information about an R2 storage bucket.",
|
|
483
|
+
inputSchema: {
|
|
484
|
+
type: "object",
|
|
485
|
+
properties: {
|
|
486
|
+
name: {
|
|
487
|
+
type: "string",
|
|
488
|
+
description: "Bucket name (defaults to first bucket if not provided)",
|
|
489
|
+
},
|
|
490
|
+
project_path: {
|
|
491
|
+
type: "string",
|
|
492
|
+
description: "Path to project directory (defaults to current directory)",
|
|
493
|
+
},
|
|
494
|
+
},
|
|
495
|
+
},
|
|
496
|
+
},
|
|
497
|
+
{
|
|
498
|
+
name: "delete_storage_bucket",
|
|
499
|
+
description: "Delete an R2 storage bucket.",
|
|
500
|
+
inputSchema: {
|
|
501
|
+
type: "object",
|
|
502
|
+
properties: {
|
|
503
|
+
name: {
|
|
504
|
+
type: "string",
|
|
505
|
+
description: "Bucket name to delete",
|
|
506
|
+
},
|
|
507
|
+
project_path: {
|
|
508
|
+
type: "string",
|
|
509
|
+
description: "Path to project directory (defaults to current directory)",
|
|
510
|
+
},
|
|
511
|
+
},
|
|
512
|
+
required: ["name"],
|
|
513
|
+
},
|
|
514
|
+
},
|
|
335
515
|
],
|
|
336
516
|
};
|
|
337
517
|
});
|
|
@@ -492,6 +672,162 @@ export function registerTools(server: McpServer, _options: McpServerOptions, deb
|
|
|
492
672
|
};
|
|
493
673
|
}
|
|
494
674
|
|
|
675
|
+
case "start_log_session": {
|
|
676
|
+
const args = StartLogSessionSchema.parse(request.params.arguments ?? {});
|
|
677
|
+
const projectPath = args.project_path ?? process.cwd();
|
|
678
|
+
|
|
679
|
+
const deployMode = await getDeployMode(projectPath);
|
|
680
|
+
if (deployMode !== "managed") {
|
|
681
|
+
throw new JackError(
|
|
682
|
+
JackErrorCode.VALIDATION_ERROR,
|
|
683
|
+
"Real-time logs are only available for managed (jack cloud) projects",
|
|
684
|
+
"For BYOC projects, use Cloudflare dashboard logs or 'wrangler tail'.",
|
|
685
|
+
);
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
const projectId = await getProjectId(projectPath);
|
|
689
|
+
if (!projectId) {
|
|
690
|
+
throw new JackError(
|
|
691
|
+
JackErrorCode.PROJECT_NOT_FOUND,
|
|
692
|
+
"Project not found",
|
|
693
|
+
"Run this from a linked jack cloud project directory (has .jack/project.json).",
|
|
694
|
+
);
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
const wrappedStartLogSession = withTelemetry(
|
|
698
|
+
"start_log_session",
|
|
699
|
+
async (id: string, label?: string) => startLogSession(id, label),
|
|
700
|
+
{ platform: "mcp" },
|
|
701
|
+
);
|
|
702
|
+
|
|
703
|
+
const result = await wrappedStartLogSession(projectId, args.label);
|
|
704
|
+
|
|
705
|
+
return {
|
|
706
|
+
content: [
|
|
707
|
+
{
|
|
708
|
+
type: "text",
|
|
709
|
+
text: JSON.stringify(formatSuccessResponse(result, startTime), null, 2),
|
|
710
|
+
},
|
|
711
|
+
],
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
case "tail_logs": {
|
|
716
|
+
const args = TailLogsSchema.parse(request.params.arguments ?? {});
|
|
717
|
+
const projectPath = args.project_path ?? process.cwd();
|
|
718
|
+
|
|
719
|
+
const deployMode = await getDeployMode(projectPath);
|
|
720
|
+
if (deployMode !== "managed") {
|
|
721
|
+
throw new JackError(
|
|
722
|
+
JackErrorCode.VALIDATION_ERROR,
|
|
723
|
+
"Real-time logs are only available for managed (jack cloud) projects",
|
|
724
|
+
"For BYOC projects, use Cloudflare dashboard logs or 'wrangler tail'.",
|
|
725
|
+
);
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
const projectId = await getProjectId(projectPath);
|
|
729
|
+
if (!projectId) {
|
|
730
|
+
throw new JackError(
|
|
731
|
+
JackErrorCode.PROJECT_NOT_FOUND,
|
|
732
|
+
"Project not found",
|
|
733
|
+
"Run this from a linked jack cloud project directory (has .jack/project.json).",
|
|
734
|
+
);
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
const wrappedTailLogs = withTelemetry(
|
|
738
|
+
"tail_logs",
|
|
739
|
+
async (id: string, label: string | undefined, maxEvents: number, durationMs: number) => {
|
|
740
|
+
const session = await startLogSession(id, label);
|
|
741
|
+
const streamUrl = `${getControlApiUrl()}${session.stream.url}`;
|
|
742
|
+
|
|
743
|
+
const controller = new AbortController();
|
|
744
|
+
const timeout = setTimeout(() => controller.abort(), durationMs);
|
|
745
|
+
|
|
746
|
+
const events: unknown[] = [];
|
|
747
|
+
let truncated = false;
|
|
748
|
+
|
|
749
|
+
try {
|
|
750
|
+
const response = await authFetch(streamUrl, {
|
|
751
|
+
method: "GET",
|
|
752
|
+
headers: { Accept: "text/event-stream" },
|
|
753
|
+
signal: controller.signal,
|
|
754
|
+
});
|
|
755
|
+
|
|
756
|
+
if (!response.ok || !response.body) {
|
|
757
|
+
const err = (await response
|
|
758
|
+
.json()
|
|
759
|
+
.catch(() => ({ message: "Failed to open log stream" }))) as {
|
|
760
|
+
message?: string;
|
|
761
|
+
};
|
|
762
|
+
throw new Error(err.message || `Failed to open log stream: ${response.status}`);
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
const reader = response.body.getReader();
|
|
766
|
+
const decoder = new TextDecoder();
|
|
767
|
+
let buffer = "";
|
|
768
|
+
|
|
769
|
+
while (events.length < maxEvents) {
|
|
770
|
+
const { done, value } = await reader.read();
|
|
771
|
+
if (done) break;
|
|
772
|
+
|
|
773
|
+
buffer += decoder.decode(value, { stream: true });
|
|
774
|
+
const lines = buffer.split("\n");
|
|
775
|
+
buffer = lines.pop() || "";
|
|
776
|
+
|
|
777
|
+
for (const line of lines) {
|
|
778
|
+
if (!line.startsWith("data:")) continue;
|
|
779
|
+
const data = line.slice(5).trim();
|
|
780
|
+
if (!data) continue;
|
|
781
|
+
|
|
782
|
+
let parsed: { type?: string } | null = null;
|
|
783
|
+
try {
|
|
784
|
+
parsed = JSON.parse(data) as { type?: string };
|
|
785
|
+
} catch {
|
|
786
|
+
continue;
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
if (parsed?.type !== "event") continue;
|
|
790
|
+
events.push(parsed);
|
|
791
|
+
|
|
792
|
+
if (events.length >= maxEvents) {
|
|
793
|
+
truncated = true;
|
|
794
|
+
controller.abort();
|
|
795
|
+
break;
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
} catch (error) {
|
|
800
|
+
// Treat abort as a normal exit (duration elapsed or max events reached).
|
|
801
|
+
if (!(error instanceof Error && error.name === "AbortError")) {
|
|
802
|
+
throw error;
|
|
803
|
+
}
|
|
804
|
+
} finally {
|
|
805
|
+
clearTimeout(timeout);
|
|
806
|
+
controller.abort();
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
return { session: session.session, events, truncated };
|
|
810
|
+
},
|
|
811
|
+
{ platform: "mcp" },
|
|
812
|
+
);
|
|
813
|
+
|
|
814
|
+
const result = await wrappedTailLogs(
|
|
815
|
+
projectId,
|
|
816
|
+
args.label,
|
|
817
|
+
args.max_events,
|
|
818
|
+
args.duration_ms,
|
|
819
|
+
);
|
|
820
|
+
|
|
821
|
+
return {
|
|
822
|
+
content: [
|
|
823
|
+
{
|
|
824
|
+
type: "text",
|
|
825
|
+
text: JSON.stringify(formatSuccessResponse(result, startTime), null, 2),
|
|
826
|
+
},
|
|
827
|
+
],
|
|
828
|
+
};
|
|
829
|
+
}
|
|
830
|
+
|
|
495
831
|
case "create_database": {
|
|
496
832
|
const args = CreateDatabaseSchema.parse(request.params.arguments ?? {});
|
|
497
833
|
const projectPath = args.project_path ?? process.cwd();
|
|
@@ -832,6 +1168,150 @@ export function registerTools(server: McpServer, _options: McpServerOptions, deb
|
|
|
832
1168
|
};
|
|
833
1169
|
}
|
|
834
1170
|
|
|
1171
|
+
case "create_storage_bucket": {
|
|
1172
|
+
const args = CreateStorageBucketSchema.parse(request.params.arguments ?? {});
|
|
1173
|
+
const projectPath = args.project_path ?? process.cwd();
|
|
1174
|
+
|
|
1175
|
+
const wrappedCreateStorageBucket = withTelemetry(
|
|
1176
|
+
"create_storage_bucket",
|
|
1177
|
+
async (projectDir: string, name?: string) => {
|
|
1178
|
+
const result = await createStorageBucket(projectDir, {
|
|
1179
|
+
name,
|
|
1180
|
+
interactive: false,
|
|
1181
|
+
});
|
|
1182
|
+
|
|
1183
|
+
// Track business event
|
|
1184
|
+
track(Events.SERVICE_CREATED, {
|
|
1185
|
+
service_type: "r2",
|
|
1186
|
+
platform: "mcp",
|
|
1187
|
+
});
|
|
1188
|
+
|
|
1189
|
+
return {
|
|
1190
|
+
bucket_name: result.bucketName,
|
|
1191
|
+
binding_name: result.bindingName,
|
|
1192
|
+
created: result.created,
|
|
1193
|
+
deploy_required: true,
|
|
1194
|
+
};
|
|
1195
|
+
},
|
|
1196
|
+
{ platform: "mcp" },
|
|
1197
|
+
);
|
|
1198
|
+
|
|
1199
|
+
const result = await wrappedCreateStorageBucket(projectPath, args.name);
|
|
1200
|
+
|
|
1201
|
+
return {
|
|
1202
|
+
content: [
|
|
1203
|
+
{
|
|
1204
|
+
type: "text",
|
|
1205
|
+
text: JSON.stringify(formatSuccessResponse(result, startTime), null, 2),
|
|
1206
|
+
},
|
|
1207
|
+
],
|
|
1208
|
+
};
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1211
|
+
case "list_storage_buckets": {
|
|
1212
|
+
const args = ListStorageBucketsSchema.parse(request.params.arguments ?? {});
|
|
1213
|
+
const projectPath = args.project_path ?? process.cwd();
|
|
1214
|
+
|
|
1215
|
+
const wrappedListStorageBuckets = withTelemetry(
|
|
1216
|
+
"list_storage_buckets",
|
|
1217
|
+
async (projectDir: string) => {
|
|
1218
|
+
const buckets = await listStorageBuckets(projectDir);
|
|
1219
|
+
return {
|
|
1220
|
+
buckets: buckets.map((bucket) => ({
|
|
1221
|
+
name: bucket.name,
|
|
1222
|
+
binding: bucket.binding,
|
|
1223
|
+
})),
|
|
1224
|
+
};
|
|
1225
|
+
},
|
|
1226
|
+
{ platform: "mcp" },
|
|
1227
|
+
);
|
|
1228
|
+
|
|
1229
|
+
const result = await wrappedListStorageBuckets(projectPath);
|
|
1230
|
+
|
|
1231
|
+
return {
|
|
1232
|
+
content: [
|
|
1233
|
+
{
|
|
1234
|
+
type: "text",
|
|
1235
|
+
text: JSON.stringify(formatSuccessResponse(result, startTime), null, 2),
|
|
1236
|
+
},
|
|
1237
|
+
],
|
|
1238
|
+
};
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
case "get_storage_info": {
|
|
1242
|
+
const args = GetStorageInfoSchema.parse(request.params.arguments ?? {});
|
|
1243
|
+
const projectPath = args.project_path ?? process.cwd();
|
|
1244
|
+
|
|
1245
|
+
const wrappedGetStorageInfo = withTelemetry(
|
|
1246
|
+
"get_storage_info",
|
|
1247
|
+
async (projectDir: string, bucketName?: string) => {
|
|
1248
|
+
const info = await getStorageBucketInfo(projectDir, bucketName);
|
|
1249
|
+
|
|
1250
|
+
if (!info) {
|
|
1251
|
+
throw new JackError(
|
|
1252
|
+
JackErrorCode.RESOURCE_NOT_FOUND,
|
|
1253
|
+
bucketName ? `Storage bucket '${bucketName}' not found` : "No storage buckets found",
|
|
1254
|
+
"Use list_storage_buckets to see available buckets or create_storage_bucket to create one",
|
|
1255
|
+
);
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
return {
|
|
1259
|
+
name: info.name,
|
|
1260
|
+
binding: info.binding,
|
|
1261
|
+
source: info.source,
|
|
1262
|
+
};
|
|
1263
|
+
},
|
|
1264
|
+
{ platform: "mcp" },
|
|
1265
|
+
);
|
|
1266
|
+
|
|
1267
|
+
const result = await wrappedGetStorageInfo(projectPath, args.name);
|
|
1268
|
+
|
|
1269
|
+
return {
|
|
1270
|
+
content: [
|
|
1271
|
+
{
|
|
1272
|
+
type: "text",
|
|
1273
|
+
text: JSON.stringify(formatSuccessResponse(result, startTime), null, 2),
|
|
1274
|
+
},
|
|
1275
|
+
],
|
|
1276
|
+
};
|
|
1277
|
+
}
|
|
1278
|
+
|
|
1279
|
+
case "delete_storage_bucket": {
|
|
1280
|
+
const args = DeleteStorageBucketSchema.parse(request.params.arguments ?? {});
|
|
1281
|
+
const projectPath = args.project_path ?? process.cwd();
|
|
1282
|
+
|
|
1283
|
+
const wrappedDeleteStorageBucket = withTelemetry(
|
|
1284
|
+
"delete_storage_bucket",
|
|
1285
|
+
async (projectDir: string, bucketName: string) => {
|
|
1286
|
+
const result = await deleteStorageBucket(projectDir, bucketName);
|
|
1287
|
+
|
|
1288
|
+
// Track business event
|
|
1289
|
+
track(Events.SERVICE_DELETED, {
|
|
1290
|
+
service_type: "r2",
|
|
1291
|
+
platform: "mcp",
|
|
1292
|
+
});
|
|
1293
|
+
|
|
1294
|
+
return {
|
|
1295
|
+
bucket_name: result.bucketName,
|
|
1296
|
+
deleted: result.deleted,
|
|
1297
|
+
binding_removed: result.bindingRemoved,
|
|
1298
|
+
};
|
|
1299
|
+
},
|
|
1300
|
+
{ platform: "mcp" },
|
|
1301
|
+
);
|
|
1302
|
+
|
|
1303
|
+
const result = await wrappedDeleteStorageBucket(projectPath, args.name);
|
|
1304
|
+
|
|
1305
|
+
return {
|
|
1306
|
+
content: [
|
|
1307
|
+
{
|
|
1308
|
+
type: "text",
|
|
1309
|
+
text: JSON.stringify(formatSuccessResponse(result, startTime), null, 2),
|
|
1310
|
+
},
|
|
1311
|
+
],
|
|
1312
|
+
};
|
|
1313
|
+
}
|
|
1314
|
+
|
|
835
1315
|
default:
|
|
836
1316
|
throw new Error(`Unknown tool: ${toolName}`);
|
|
837
1317
|
}
|