@apicircle/mcp-server 1.0.7 → 1.0.9
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/dist/bin/mcp-server.cjs +290 -120
- package/dist/bin/mcp-server.cjs.map +1 -1
- package/dist/index.cjs +280 -117
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +20 -6
- package/dist/index.d.ts +20 -6
- package/dist/index.js +279 -116
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -41,7 +41,7 @@ var import_zod = require("zod");
|
|
|
41
41
|
// package.json
|
|
42
42
|
var package_default = {
|
|
43
43
|
name: "@apicircle/mcp-server",
|
|
44
|
-
version: "1.0.
|
|
44
|
+
version: "1.0.9",
|
|
45
45
|
private: false,
|
|
46
46
|
type: "module",
|
|
47
47
|
description: "Model Context Protocol server exposing API Circle Studio's workspace as a tool catalog. Used by Claude Desktop, ChatGPT, Cursor, GitHub Copilot, and any other MCP-compatible AI client.",
|
|
@@ -2143,15 +2143,143 @@ var promptSetEndpointMultipliersTool = {
|
|
|
2143
2143
|
}
|
|
2144
2144
|
};
|
|
2145
2145
|
|
|
2146
|
-
// src/tools/
|
|
2146
|
+
// src/tools/globalAssets.ts
|
|
2147
2147
|
var import_zod10 = require("zod");
|
|
2148
2148
|
var import_shared4 = require("@apicircle/shared");
|
|
2149
|
+
function deriveState(asset, hasPendingUpload) {
|
|
2150
|
+
const w = asset.workingBranchRef ?? null;
|
|
2151
|
+
const b = asset.baseBranchRef ?? null;
|
|
2152
|
+
if (w && b) {
|
|
2153
|
+
if (w.blobSha && b.blobSha && w.blobSha !== b.blobSha) return "diverged";
|
|
2154
|
+
return "merged";
|
|
2155
|
+
}
|
|
2156
|
+
if (w && !b) return "workingOnly";
|
|
2157
|
+
if (!w && b) return "baseOnly";
|
|
2158
|
+
if (hasPendingUpload) return "uploading";
|
|
2159
|
+
return "missing";
|
|
2160
|
+
}
|
|
2161
|
+
var globalAssetsFilesListTool = {
|
|
2162
|
+
name: "assets.list_files",
|
|
2163
|
+
description: "List every Global File Asset with its provenance state and reference count. Each entry includes id, name, filename, size, mimeType, sha256, state (uploading | workingOnly | merged | baseOnly | missing | diverged), workingBranchRef, baseBranchRef, and usage { requests, mockEndpoints, total }.",
|
|
2164
|
+
inputSchema: import_zod10.z.object({}).strict(),
|
|
2165
|
+
async handler(_input, ctx) {
|
|
2166
|
+
const state = await ctx.workspace.read();
|
|
2167
|
+
const files = state.synced.globalAssets.files ?? {};
|
|
2168
|
+
const pending = state.local.pendingFileUploads ?? {};
|
|
2169
|
+
const usage = state.local.assetUsageIndex ?? {};
|
|
2170
|
+
const items = Object.values(files).map((asset) => {
|
|
2171
|
+
const hasPending = Boolean(pending[asset.id]);
|
|
2172
|
+
const u = usage[asset.id] ?? { requests: [], mockEndpoints: [], total: 0 };
|
|
2173
|
+
return {
|
|
2174
|
+
id: asset.id,
|
|
2175
|
+
name: asset.name,
|
|
2176
|
+
description: asset.description ?? null,
|
|
2177
|
+
filename: asset.filename,
|
|
2178
|
+
size: asset.size,
|
|
2179
|
+
mimeType: asset.mimeType,
|
|
2180
|
+
sha256: asset.sha256 ?? null,
|
|
2181
|
+
state: deriveState(asset, hasPending),
|
|
2182
|
+
workingBranchRef: asset.workingBranchRef ?? null,
|
|
2183
|
+
baseBranchRef: asset.baseBranchRef ?? null,
|
|
2184
|
+
usage: { ...u }
|
|
2185
|
+
};
|
|
2186
|
+
});
|
|
2187
|
+
return { count: items.length, files: items };
|
|
2188
|
+
}
|
|
2189
|
+
};
|
|
2190
|
+
var globalAssetsFilesCreateTool = {
|
|
2191
|
+
name: "assets.create_file",
|
|
2192
|
+
description: 'Register a Global File Asset entry. Bytes are NOT carried \u2014 MCP returns the new asset id and the asset enters the "missing" state. The user fills the bytes from the Global Assets panel (a "Fill bytes" button surfaces on missing-state assets) which preserves the slot id and queues the bytes for the next push. Use this when an AI client wants to claim an asset slot for a file the user will provide later.',
|
|
2193
|
+
inputSchema: import_zod10.z.object({
|
|
2194
|
+
name: import_zod10.z.string().min(1, "name is required"),
|
|
2195
|
+
description: import_zod10.z.string().optional(),
|
|
2196
|
+
filename: import_zod10.z.string().min(1, "filename is required"),
|
|
2197
|
+
size: import_zod10.z.number().int().nonnegative(),
|
|
2198
|
+
mimeType: import_zod10.z.string().default("application/octet-stream"),
|
|
2199
|
+
sha256: import_zod10.z.string().optional()
|
|
2200
|
+
}).strict(),
|
|
2201
|
+
async handler(input, ctx) {
|
|
2202
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2203
|
+
const file = {
|
|
2204
|
+
id: (0, import_shared4.generateId)(),
|
|
2205
|
+
name: input.name,
|
|
2206
|
+
description: input.description,
|
|
2207
|
+
slotId: (0, import_shared4.generateId)(),
|
|
2208
|
+
filename: input.filename,
|
|
2209
|
+
size: input.size,
|
|
2210
|
+
mimeType: input.mimeType,
|
|
2211
|
+
sha256: input.sha256,
|
|
2212
|
+
createdAt: now,
|
|
2213
|
+
updatedAt: now
|
|
2214
|
+
};
|
|
2215
|
+
const out = await ctx.workspace.apply({ kind: "globalAsset.upsertFile", file });
|
|
2216
|
+
return { id: file.id, slotId: file.slotId, changedIds: out.changedIds };
|
|
2217
|
+
}
|
|
2218
|
+
};
|
|
2219
|
+
var globalAssetsFilesUpdateTool = {
|
|
2220
|
+
name: "assets.update_file",
|
|
2221
|
+
description: "Rename or re-describe a Global File Asset. Provenance refs (workingBranchRef, baseBranchRef) and binary metadata (slotId, sha256, size, mimeType) are preserved verbatim.",
|
|
2222
|
+
inputSchema: import_zod10.z.object({
|
|
2223
|
+
id: import_zod10.z.string().min(1),
|
|
2224
|
+
patch: import_zod10.z.object({
|
|
2225
|
+
name: import_zod10.z.string().optional(),
|
|
2226
|
+
description: import_zod10.z.string().nullable().optional()
|
|
2227
|
+
}).strict()
|
|
2228
|
+
}).strict(),
|
|
2229
|
+
async handler(input, ctx) {
|
|
2230
|
+
const state = await ctx.workspace.read();
|
|
2231
|
+
const existing = state.synced.globalAssets.files?.[input.id];
|
|
2232
|
+
if (!existing) {
|
|
2233
|
+
return { found: false, changedIds: [] };
|
|
2234
|
+
}
|
|
2235
|
+
const next = {
|
|
2236
|
+
...existing,
|
|
2237
|
+
name: input.patch.name ?? existing.name,
|
|
2238
|
+
description: input.patch.description === null ? void 0 : input.patch.description ?? existing.description
|
|
2239
|
+
};
|
|
2240
|
+
const out = await ctx.workspace.apply({ kind: "globalAsset.upsertFile", file: next });
|
|
2241
|
+
return { found: true, id: next.id, changedIds: out.changedIds };
|
|
2242
|
+
}
|
|
2243
|
+
};
|
|
2244
|
+
var globalAssetsFilesDeleteTool = {
|
|
2245
|
+
name: "assets.delete_file",
|
|
2246
|
+
description: "Delete a Global File Asset. Cascades \u2014 every request body and mock-response body that referenced the asset is unbound in the same mutation. The result envelope includes the consumer list that was cleared so the caller can report what changed.",
|
|
2247
|
+
inputSchema: import_zod10.z.object({ id: import_zod10.z.string().min(1) }).strict(),
|
|
2248
|
+
async handler(input, ctx) {
|
|
2249
|
+
const before = await ctx.workspace.read();
|
|
2250
|
+
const usage = before.local.assetUsageIndex?.[input.id] ?? {
|
|
2251
|
+
requests: [],
|
|
2252
|
+
mockEndpoints: [],
|
|
2253
|
+
total: 0
|
|
2254
|
+
};
|
|
2255
|
+
const existing = before.synced.globalAssets.files?.[input.id];
|
|
2256
|
+
if (!existing) {
|
|
2257
|
+
return { found: false, changedIds: [] };
|
|
2258
|
+
}
|
|
2259
|
+
const out = await ctx.workspace.apply({ kind: "globalAsset.removeFile", id: input.id });
|
|
2260
|
+
return {
|
|
2261
|
+
found: true,
|
|
2262
|
+
id: input.id,
|
|
2263
|
+
filename: existing.filename,
|
|
2264
|
+
unbound: {
|
|
2265
|
+
requests: usage.requests,
|
|
2266
|
+
mockEndpoints: usage.mockEndpoints,
|
|
2267
|
+
total: usage.total
|
|
2268
|
+
},
|
|
2269
|
+
changedIds: out.changedIds
|
|
2270
|
+
};
|
|
2271
|
+
}
|
|
2272
|
+
};
|
|
2273
|
+
|
|
2274
|
+
// src/tools/mocks.ts
|
|
2275
|
+
var import_zod11 = require("zod");
|
|
2276
|
+
var import_shared5 = require("@apicircle/shared");
|
|
2149
2277
|
var import_mock_server_core2 = require("@apicircle/mock-server-core");
|
|
2150
2278
|
async function ingestSource(source, name) {
|
|
2151
2279
|
const { endpoints, warnings } = await (0, import_mock_server_core2.parseSourceToEndpoints)(source);
|
|
2152
2280
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2153
2281
|
const mock = {
|
|
2154
|
-
id: (0,
|
|
2282
|
+
id: (0, import_shared5.generateId)(),
|
|
2155
2283
|
name,
|
|
2156
2284
|
source,
|
|
2157
2285
|
endpoints,
|
|
@@ -2167,10 +2295,10 @@ async function ingestSource(source, name) {
|
|
|
2167
2295
|
var mockCreateFromOpenApiTool = {
|
|
2168
2296
|
name: "mock.create_from_openapi",
|
|
2169
2297
|
description: "Create a mock server from an OpenAPI / Swagger spec (YAML or JSON).",
|
|
2170
|
-
inputSchema:
|
|
2171
|
-
name:
|
|
2172
|
-
spec:
|
|
2173
|
-
format:
|
|
2298
|
+
inputSchema: import_zod11.z.object({
|
|
2299
|
+
name: import_zod11.z.string(),
|
|
2300
|
+
spec: import_zod11.z.string().min(1),
|
|
2301
|
+
format: import_zod11.z.enum(["json", "yaml"]).default("json")
|
|
2174
2302
|
}),
|
|
2175
2303
|
async handler(input, ctx) {
|
|
2176
2304
|
const { mock, warnings } = await ingestSource(
|
|
@@ -2189,7 +2317,7 @@ var mockCreateFromOpenApiTool = {
|
|
|
2189
2317
|
var mockCreateFromPostmanTool = {
|
|
2190
2318
|
name: "mock.create_from_postman",
|
|
2191
2319
|
description: "Create a mock server from a Postman v2/v2.1 collection.",
|
|
2192
|
-
inputSchema:
|
|
2320
|
+
inputSchema: import_zod11.z.object({ name: import_zod11.z.string(), collection: import_zod11.z.string().min(1) }),
|
|
2193
2321
|
async handler(input, ctx) {
|
|
2194
2322
|
const { mock, warnings } = await ingestSource(
|
|
2195
2323
|
{ kind: "postman", collection: input.collection },
|
|
@@ -2207,7 +2335,7 @@ var mockCreateFromPostmanTool = {
|
|
|
2207
2335
|
var mockCreateFromInsomniaTool = {
|
|
2208
2336
|
name: "mock.create_from_insomnia",
|
|
2209
2337
|
description: "Create a mock server from an Insomnia v4 export.",
|
|
2210
|
-
inputSchema:
|
|
2338
|
+
inputSchema: import_zod11.z.object({ name: import_zod11.z.string(), export: import_zod11.z.string().min(1) }),
|
|
2211
2339
|
async handler(input, ctx) {
|
|
2212
2340
|
const { mock, warnings } = await ingestSource(
|
|
2213
2341
|
{ kind: "insomnia", export: input.export },
|
|
@@ -2225,7 +2353,7 @@ var mockCreateFromInsomniaTool = {
|
|
|
2225
2353
|
var mockImportPostmanMockCollectionTool = {
|
|
2226
2354
|
name: "mock.import_postman_mock_collection",
|
|
2227
2355
|
description: "Import a Postman Mock Collection (collections previously hosted on Postman's mock service). Same parser as a regular Postman collection but marked as a mock import.",
|
|
2228
|
-
inputSchema:
|
|
2356
|
+
inputSchema: import_zod11.z.object({ name: import_zod11.z.string(), collection: import_zod11.z.string().min(1) }),
|
|
2229
2357
|
async handler(input, ctx) {
|
|
2230
2358
|
const { mock, warnings } = await ingestSource(
|
|
2231
2359
|
{ kind: "postman", collection: input.collection },
|
|
@@ -2243,7 +2371,7 @@ var mockImportPostmanMockCollectionTool = {
|
|
|
2243
2371
|
var mockListTool = {
|
|
2244
2372
|
name: "mock.list",
|
|
2245
2373
|
description: "List all mock servers in the workspace plus their runtime status (running / stopped, port).",
|
|
2246
|
-
inputSchema:
|
|
2374
|
+
inputSchema: import_zod11.z.object({}),
|
|
2247
2375
|
async handler(_input, ctx) {
|
|
2248
2376
|
const state = await ctx.workspace.read();
|
|
2249
2377
|
const running = await ctx.mock.list();
|
|
@@ -2265,9 +2393,9 @@ var mockListTool = {
|
|
|
2265
2393
|
var mockStartTool = {
|
|
2266
2394
|
name: "mock.start",
|
|
2267
2395
|
description: "Start a mock server by id. Returns the bound port. Errors if the mock is already running or the requested port is in use.",
|
|
2268
|
-
inputSchema:
|
|
2269
|
-
id:
|
|
2270
|
-
port:
|
|
2396
|
+
inputSchema: import_zod11.z.object({
|
|
2397
|
+
id: import_zod11.z.string(),
|
|
2398
|
+
port: import_zod11.z.number().int().positive().optional()
|
|
2271
2399
|
}),
|
|
2272
2400
|
async handler(input, ctx) {
|
|
2273
2401
|
const state = await ctx.workspace.read();
|
|
@@ -2284,7 +2412,7 @@ var mockStartTool = {
|
|
|
2284
2412
|
var mockStopTool = {
|
|
2285
2413
|
name: "mock.stop",
|
|
2286
2414
|
description: "Stop a running mock server by id (no-op if not running).",
|
|
2287
|
-
inputSchema:
|
|
2415
|
+
inputSchema: import_zod11.z.object({ id: import_zod11.z.string() }),
|
|
2288
2416
|
async handler(input, ctx) {
|
|
2289
2417
|
try {
|
|
2290
2418
|
await ctx.mock.stop(input.id);
|
|
@@ -2297,7 +2425,7 @@ var mockStopTool = {
|
|
|
2297
2425
|
var mockDeleteTool = {
|
|
2298
2426
|
name: "mock.delete",
|
|
2299
2427
|
description: "Delete a mock server definition. Stops it first if it's running.",
|
|
2300
|
-
inputSchema:
|
|
2428
|
+
inputSchema: import_zod11.z.object({ id: import_zod11.z.string() }),
|
|
2301
2429
|
async handler(input, ctx) {
|
|
2302
2430
|
try {
|
|
2303
2431
|
await ctx.mock.stop(input.id);
|
|
@@ -2307,18 +2435,18 @@ var mockDeleteTool = {
|
|
|
2307
2435
|
return { ok: true, changedIds: out.changedIds };
|
|
2308
2436
|
}
|
|
2309
2437
|
};
|
|
2310
|
-
var HTTP_METHOD3 =
|
|
2438
|
+
var HTTP_METHOD3 = import_zod11.z.enum(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
|
|
2311
2439
|
var mockCreateManualTool = {
|
|
2312
2440
|
name: "mock.create_manual",
|
|
2313
2441
|
description: "Create an empty manual-mode mock server. Use `mock.add_endpoint` afterward to populate it. CORS defaults to off (same-origin only); enable + list explicit origins via `mock.update_cors` if cross-origin access is needed.",
|
|
2314
|
-
inputSchema:
|
|
2315
|
-
name:
|
|
2316
|
-
defaultPort:
|
|
2442
|
+
inputSchema: import_zod11.z.object({
|
|
2443
|
+
name: import_zod11.z.string().min(1),
|
|
2444
|
+
defaultPort: import_zod11.z.number().int().positive().nullable().optional()
|
|
2317
2445
|
}),
|
|
2318
2446
|
async handler(input, ctx) {
|
|
2319
2447
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2320
2448
|
const mock = {
|
|
2321
|
-
id: (0,
|
|
2449
|
+
id: (0, import_shared5.generateId)(),
|
|
2322
2450
|
name: input.name,
|
|
2323
2451
|
source: { kind: "manual", endpoints: [] },
|
|
2324
2452
|
endpoints: [],
|
|
@@ -2336,7 +2464,7 @@ var mockCreateManualTool = {
|
|
|
2336
2464
|
var mockListEndpointsTool = {
|
|
2337
2465
|
name: "mock.list_endpoints",
|
|
2338
2466
|
description: "List endpoints for a mock server (id, method, path, name).",
|
|
2339
|
-
inputSchema:
|
|
2467
|
+
inputSchema: import_zod11.z.object({ mockId: import_zod11.z.string() }),
|
|
2340
2468
|
async handler(input, ctx) {
|
|
2341
2469
|
const state = await ctx.workspace.read();
|
|
2342
2470
|
const mock = state.synced.mockServers[input.mockId];
|
|
@@ -2355,10 +2483,10 @@ var mockListEndpointsTool = {
|
|
|
2355
2483
|
};
|
|
2356
2484
|
}
|
|
2357
2485
|
};
|
|
2358
|
-
var ENDPOINT_RESPONSE2 =
|
|
2359
|
-
status:
|
|
2360
|
-
jsonBody:
|
|
2361
|
-
contentType:
|
|
2486
|
+
var ENDPOINT_RESPONSE2 = import_zod11.z.object({
|
|
2487
|
+
status: import_zod11.z.number().int().min(100).max(599).default(200),
|
|
2488
|
+
jsonBody: import_zod11.z.string().default("{}"),
|
|
2489
|
+
contentType: import_zod11.z.string().default("application/json")
|
|
2362
2490
|
});
|
|
2363
2491
|
function buildDefaultEndpoint(args) {
|
|
2364
2492
|
const response = args.response ?? {
|
|
@@ -2368,16 +2496,16 @@ function buildDefaultEndpoint(args) {
|
|
|
2368
2496
|
};
|
|
2369
2497
|
const headers = [{ key: "Content-Type", value: response.contentType, enabled: true }];
|
|
2370
2498
|
return {
|
|
2371
|
-
id: (0,
|
|
2499
|
+
id: (0, import_shared5.generateId)(),
|
|
2372
2500
|
name: args.name ?? `${args.method} ${args.pathPattern}`,
|
|
2373
2501
|
method: args.method,
|
|
2374
2502
|
pathPattern: args.pathPattern,
|
|
2375
2503
|
description: args.description,
|
|
2376
|
-
requestSchema: (0,
|
|
2504
|
+
requestSchema: (0, import_shared5.makeDefaultRequestSchema)(),
|
|
2377
2505
|
requestValidation: [],
|
|
2378
2506
|
responseRules: [],
|
|
2379
2507
|
defaultResponse: {
|
|
2380
|
-
...(0,
|
|
2508
|
+
...(0, import_shared5.makeDefaultMockResponse)(),
|
|
2381
2509
|
status: response.status,
|
|
2382
2510
|
headers,
|
|
2383
2511
|
body: { type: "json", content: response.jsonBody }
|
|
@@ -2387,12 +2515,12 @@ function buildDefaultEndpoint(args) {
|
|
|
2387
2515
|
var mockAddEndpointTool = {
|
|
2388
2516
|
name: "mock.add_endpoint",
|
|
2389
2517
|
description: "Append a new endpoint to a mock server. Defaults to a 200 JSON response of `{}`. Returns the new endpoint id.",
|
|
2390
|
-
inputSchema:
|
|
2391
|
-
mockId:
|
|
2518
|
+
inputSchema: import_zod11.z.object({
|
|
2519
|
+
mockId: import_zod11.z.string(),
|
|
2392
2520
|
method: HTTP_METHOD3,
|
|
2393
|
-
pathPattern:
|
|
2394
|
-
name:
|
|
2395
|
-
description:
|
|
2521
|
+
pathPattern: import_zod11.z.string().min(1),
|
|
2522
|
+
name: import_zod11.z.string().optional(),
|
|
2523
|
+
description: import_zod11.z.string().optional(),
|
|
2396
2524
|
response: ENDPOINT_RESPONSE2.optional()
|
|
2397
2525
|
}),
|
|
2398
2526
|
async handler(input, ctx) {
|
|
@@ -2415,13 +2543,13 @@ var mockAddEndpointTool = {
|
|
|
2415
2543
|
var mockUpdateEndpointTool = {
|
|
2416
2544
|
name: "mock.update_endpoint",
|
|
2417
2545
|
description: "Patch fields on a single mock endpoint (method, pathPattern, name, description, defaultResponse status / contentType / json body). Pass only the fields you want to change.",
|
|
2418
|
-
inputSchema:
|
|
2419
|
-
mockId:
|
|
2420
|
-
endpointId:
|
|
2546
|
+
inputSchema: import_zod11.z.object({
|
|
2547
|
+
mockId: import_zod11.z.string(),
|
|
2548
|
+
endpointId: import_zod11.z.string(),
|
|
2421
2549
|
method: HTTP_METHOD3.optional(),
|
|
2422
|
-
pathPattern:
|
|
2423
|
-
name:
|
|
2424
|
-
description:
|
|
2550
|
+
pathPattern: import_zod11.z.string().optional(),
|
|
2551
|
+
name: import_zod11.z.string().optional(),
|
|
2552
|
+
description: import_zod11.z.string().optional(),
|
|
2425
2553
|
response: ENDPOINT_RESPONSE2.partial().optional()
|
|
2426
2554
|
}),
|
|
2427
2555
|
async handler(input, ctx) {
|
|
@@ -2462,7 +2590,7 @@ var mockUpdateEndpointTool = {
|
|
|
2462
2590
|
var mockDeleteEndpointTool = {
|
|
2463
2591
|
name: "mock.delete_endpoint",
|
|
2464
2592
|
description: "Remove an endpoint from a mock server.",
|
|
2465
|
-
inputSchema:
|
|
2593
|
+
inputSchema: import_zod11.z.object({ mockId: import_zod11.z.string(), endpointId: import_zod11.z.string() }),
|
|
2466
2594
|
async handler(input, ctx) {
|
|
2467
2595
|
const state = await ctx.workspace.read();
|
|
2468
2596
|
const mock = state.synced.mockServers[input.mockId];
|
|
@@ -2482,9 +2610,9 @@ var mockDeleteEndpointTool = {
|
|
|
2482
2610
|
return { ok: true, changedIds: out.changedIds };
|
|
2483
2611
|
}
|
|
2484
2612
|
};
|
|
2485
|
-
var VALIDATION_RULE =
|
|
2486
|
-
id:
|
|
2487
|
-
kind:
|
|
2613
|
+
var VALIDATION_RULE = import_zod11.z.object({
|
|
2614
|
+
id: import_zod11.z.string().optional(),
|
|
2615
|
+
kind: import_zod11.z.enum([
|
|
2488
2616
|
"header-required",
|
|
2489
2617
|
"header-equals",
|
|
2490
2618
|
"header-matches",
|
|
@@ -2495,43 +2623,43 @@ var VALIDATION_RULE = import_zod10.z.object({
|
|
|
2495
2623
|
"body-required",
|
|
2496
2624
|
"content-type-equals"
|
|
2497
2625
|
]),
|
|
2498
|
-
target:
|
|
2499
|
-
expected:
|
|
2500
|
-
message:
|
|
2501
|
-
enabled:
|
|
2502
|
-
failResponse:
|
|
2503
|
-
status:
|
|
2504
|
-
jsonBody:
|
|
2626
|
+
target: import_zod11.z.string().default(""),
|
|
2627
|
+
expected: import_zod11.z.string().optional(),
|
|
2628
|
+
message: import_zod11.z.string().optional(),
|
|
2629
|
+
enabled: import_zod11.z.boolean().default(true),
|
|
2630
|
+
failResponse: import_zod11.z.object({
|
|
2631
|
+
status: import_zod11.z.number().int().min(100).max(599).default(400),
|
|
2632
|
+
jsonBody: import_zod11.z.string().default('{"error":"validation failed"}')
|
|
2505
2633
|
}).default({})
|
|
2506
2634
|
});
|
|
2507
|
-
var CONDITION_CLAUSE =
|
|
2508
|
-
id:
|
|
2509
|
-
scope:
|
|
2510
|
-
target:
|
|
2511
|
-
op:
|
|
2512
|
-
value:
|
|
2635
|
+
var CONDITION_CLAUSE = import_zod11.z.object({
|
|
2636
|
+
id: import_zod11.z.string().optional(),
|
|
2637
|
+
scope: import_zod11.z.enum(["query", "pathParam", "header", "cookie", "body-json-path"]),
|
|
2638
|
+
target: import_zod11.z.string(),
|
|
2639
|
+
op: import_zod11.z.enum(["equals", "not-equals", "matches", "gt", "lt", "gte", "lte", "present", "absent"]),
|
|
2640
|
+
value: import_zod11.z.string().optional()
|
|
2513
2641
|
});
|
|
2514
|
-
var RESPONSE_RULE =
|
|
2515
|
-
id:
|
|
2516
|
-
name:
|
|
2517
|
-
enabled:
|
|
2518
|
-
when:
|
|
2519
|
-
response:
|
|
2520
|
-
status:
|
|
2521
|
-
jsonBody:
|
|
2642
|
+
var RESPONSE_RULE = import_zod11.z.object({
|
|
2643
|
+
id: import_zod11.z.string().optional(),
|
|
2644
|
+
name: import_zod11.z.string(),
|
|
2645
|
+
enabled: import_zod11.z.boolean().default(true),
|
|
2646
|
+
when: import_zod11.z.array(CONDITION_CLAUSE).default([]),
|
|
2647
|
+
response: import_zod11.z.object({
|
|
2648
|
+
status: import_zod11.z.number().int().min(100).max(599).default(200),
|
|
2649
|
+
jsonBody: import_zod11.z.string().default("{}")
|
|
2522
2650
|
}).default({})
|
|
2523
2651
|
});
|
|
2524
|
-
var MULTIPLIER =
|
|
2525
|
-
id:
|
|
2526
|
-
name:
|
|
2527
|
-
source:
|
|
2528
|
-
kind:
|
|
2529
|
-
key:
|
|
2652
|
+
var MULTIPLIER = import_zod11.z.object({
|
|
2653
|
+
id: import_zod11.z.string().optional(),
|
|
2654
|
+
name: import_zod11.z.string().optional(),
|
|
2655
|
+
source: import_zod11.z.object({
|
|
2656
|
+
kind: import_zod11.z.enum(["query", "pathParam", "header", "body-json-path"]),
|
|
2657
|
+
key: import_zod11.z.string()
|
|
2530
2658
|
}),
|
|
2531
|
-
targetJsonPath:
|
|
2532
|
-
defaultCount:
|
|
2533
|
-
min:
|
|
2534
|
-
max:
|
|
2659
|
+
targetJsonPath: import_zod11.z.string(),
|
|
2660
|
+
defaultCount: import_zod11.z.number().int().nonnegative().default(0),
|
|
2661
|
+
min: import_zod11.z.number().int().nonnegative().optional(),
|
|
2662
|
+
max: import_zod11.z.number().int().nonnegative().optional()
|
|
2535
2663
|
});
|
|
2536
2664
|
function defaultJsonResponseConfig(args) {
|
|
2537
2665
|
return {
|
|
@@ -2556,10 +2684,10 @@ function patchEndpoint2(mock, endpointId, patcher) {
|
|
|
2556
2684
|
var mockSetValidationRulesTool = {
|
|
2557
2685
|
name: "mock.set_validation_rules",
|
|
2558
2686
|
description: "Replace an endpoint's validation rules. Rules without an `id` get a fresh one; existing rules can keep theirs to preserve client-side selection state. Empty array clears all rules.",
|
|
2559
|
-
inputSchema:
|
|
2560
|
-
mockId:
|
|
2561
|
-
endpointId:
|
|
2562
|
-
rules:
|
|
2687
|
+
inputSchema: import_zod11.z.object({
|
|
2688
|
+
mockId: import_zod11.z.string(),
|
|
2689
|
+
endpointId: import_zod11.z.string(),
|
|
2690
|
+
rules: import_zod11.z.array(VALIDATION_RULE)
|
|
2563
2691
|
}),
|
|
2564
2692
|
async handler(input, ctx) {
|
|
2565
2693
|
const state = await ctx.workspace.read();
|
|
@@ -2569,7 +2697,7 @@ var mockSetValidationRulesTool = {
|
|
|
2569
2697
|
const next = patchEndpoint2(mock, input.endpointId, (e) => ({
|
|
2570
2698
|
...e,
|
|
2571
2699
|
requestValidation: rules.map((r) => ({
|
|
2572
|
-
id: r.id ?? (0,
|
|
2700
|
+
id: r.id ?? (0, import_shared5.generateId)(),
|
|
2573
2701
|
kind: r.kind,
|
|
2574
2702
|
target: r.target,
|
|
2575
2703
|
expected: r.expected,
|
|
@@ -2586,10 +2714,10 @@ var mockSetValidationRulesTool = {
|
|
|
2586
2714
|
var mockSetResponseRulesTool = {
|
|
2587
2715
|
name: "mock.set_response_rules",
|
|
2588
2716
|
description: "Replace an endpoint's conditional response rules. Rules fire in order; the first whose every clause matches wins. Disabled rules are skipped. Empty array falls back to defaultResponse.",
|
|
2589
|
-
inputSchema:
|
|
2590
|
-
mockId:
|
|
2591
|
-
endpointId:
|
|
2592
|
-
rules:
|
|
2717
|
+
inputSchema: import_zod11.z.object({
|
|
2718
|
+
mockId: import_zod11.z.string(),
|
|
2719
|
+
endpointId: import_zod11.z.string(),
|
|
2720
|
+
rules: import_zod11.z.array(RESPONSE_RULE)
|
|
2593
2721
|
}),
|
|
2594
2722
|
async handler(input, ctx) {
|
|
2595
2723
|
const state = await ctx.workspace.read();
|
|
@@ -2599,11 +2727,11 @@ var mockSetResponseRulesTool = {
|
|
|
2599
2727
|
const next = patchEndpoint2(mock, input.endpointId, (e) => ({
|
|
2600
2728
|
...e,
|
|
2601
2729
|
responseRules: rules.map((r) => ({
|
|
2602
|
-
id: r.id ?? (0,
|
|
2730
|
+
id: r.id ?? (0, import_shared5.generateId)(),
|
|
2603
2731
|
name: r.name,
|
|
2604
2732
|
enabled: r.enabled,
|
|
2605
2733
|
when: r.when.map((c) => ({
|
|
2606
|
-
id: c.id ?? (0,
|
|
2734
|
+
id: c.id ?? (0, import_shared5.generateId)(),
|
|
2607
2735
|
scope: c.scope,
|
|
2608
2736
|
target: c.target,
|
|
2609
2737
|
op: c.op,
|
|
@@ -2620,10 +2748,10 @@ var mockSetResponseRulesTool = {
|
|
|
2620
2748
|
var mockSetMultipliersTool = {
|
|
2621
2749
|
name: "mock.set_multipliers",
|
|
2622
2750
|
description: "Replace the response multipliers on an endpoint's defaultResponse. Multipliers expand an array at `targetJsonPath` to a count derived from a request value. Empty array clears all multipliers.",
|
|
2623
|
-
inputSchema:
|
|
2624
|
-
mockId:
|
|
2625
|
-
endpointId:
|
|
2626
|
-
multipliers:
|
|
2751
|
+
inputSchema: import_zod11.z.object({
|
|
2752
|
+
mockId: import_zod11.z.string(),
|
|
2753
|
+
endpointId: import_zod11.z.string(),
|
|
2754
|
+
multipliers: import_zod11.z.array(MULTIPLIER)
|
|
2627
2755
|
}),
|
|
2628
2756
|
async handler(input, ctx) {
|
|
2629
2757
|
const state = await ctx.workspace.read();
|
|
@@ -2635,7 +2763,7 @@ var mockSetMultipliersTool = {
|
|
|
2635
2763
|
defaultResponse: {
|
|
2636
2764
|
...e.defaultResponse,
|
|
2637
2765
|
multipliers: multipliers.length === 0 ? void 0 : multipliers.map((m) => ({
|
|
2638
|
-
id: m.id ?? (0,
|
|
2766
|
+
id: m.id ?? (0, import_shared5.generateId)(),
|
|
2639
2767
|
name: m.name,
|
|
2640
2768
|
source: { kind: m.source.kind, key: m.source.key },
|
|
2641
2769
|
targetJsonPath: m.targetJsonPath,
|
|
@@ -2711,6 +2839,10 @@ var TOOL_REGISTRY = [
|
|
|
2711
2839
|
promptSetEndpointValidationRulesTool,
|
|
2712
2840
|
promptSetEndpointResponseRulesTool,
|
|
2713
2841
|
promptSetEndpointMultipliersTool,
|
|
2842
|
+
globalAssetsFilesListTool,
|
|
2843
|
+
globalAssetsFilesCreateTool,
|
|
2844
|
+
globalAssetsFilesUpdateTool,
|
|
2845
|
+
globalAssetsFilesDeleteTool,
|
|
2714
2846
|
mockCreateFromOpenApiTool,
|
|
2715
2847
|
mockCreateFromPostmanTool,
|
|
2716
2848
|
mockCreateFromInsomniaTool,
|
|
@@ -2851,17 +2983,58 @@ var FileBackedWorkspaceProvider = class {
|
|
|
2851
2983
|
|
|
2852
2984
|
// src/providers/MultiWorkspaceProvider.ts
|
|
2853
2985
|
var import_registry = require("@apicircle/core/workspace/registry");
|
|
2986
|
+
var LazyActiveWorkspaceProvider = class {
|
|
2987
|
+
constructor(registryRoot, onActiveResolved) {
|
|
2988
|
+
this.registryRoot = registryRoot;
|
|
2989
|
+
this.onActiveResolved = onActiveResolved;
|
|
2990
|
+
}
|
|
2991
|
+
registryRoot;
|
|
2992
|
+
onActiveResolved;
|
|
2993
|
+
async resolveActive() {
|
|
2994
|
+
const registry = await (0, import_registry.loadRegistry)(this.registryRoot);
|
|
2995
|
+
const activeId = registry?.activeWorkspaceId ?? null;
|
|
2996
|
+
if (!activeId) {
|
|
2997
|
+
throw new Error(
|
|
2998
|
+
"No active workspace. Open the desktop app at least once, or run `apicircle workspaces create <name>`."
|
|
2999
|
+
);
|
|
3000
|
+
}
|
|
3001
|
+
this.onActiveResolved(activeId);
|
|
3002
|
+
return new FileBackedWorkspaceProvider((0, import_registry.workspaceDirFor)(this.registryRoot, activeId));
|
|
3003
|
+
}
|
|
3004
|
+
async read() {
|
|
3005
|
+
const provider = await this.resolveActive();
|
|
3006
|
+
return provider.read();
|
|
3007
|
+
}
|
|
3008
|
+
async apply(patch) {
|
|
3009
|
+
const provider = await this.resolveActive();
|
|
3010
|
+
return provider.apply(patch);
|
|
3011
|
+
}
|
|
3012
|
+
async write(next) {
|
|
3013
|
+
const provider = await this.resolveActive();
|
|
3014
|
+
return provider.write(next);
|
|
3015
|
+
}
|
|
3016
|
+
};
|
|
2854
3017
|
var MultiWorkspaceProvider = class {
|
|
2855
3018
|
constructor(registryRoot) {
|
|
2856
3019
|
this.registryRoot = registryRoot;
|
|
3020
|
+
this.lazyProvider = new LazyActiveWorkspaceProvider(this.registryRoot, (id) => {
|
|
3021
|
+
this.activeWorkspaceId = id;
|
|
3022
|
+
});
|
|
2857
3023
|
}
|
|
2858
3024
|
registryRoot;
|
|
2859
|
-
active
|
|
3025
|
+
/** Last-known active workspace id. Refreshed every time the lazy
|
|
3026
|
+
* provider resolves; reflects what the most recent operation saw on
|
|
3027
|
+
* disk, not a stale boot-time snapshot. */
|
|
2860
3028
|
activeWorkspaceId = null;
|
|
3029
|
+
/** The lazy provider tool handlers consume as `ctx.workspace`. Holds a
|
|
3030
|
+
* reference back to this instance so each call updates
|
|
3031
|
+
* `activeWorkspaceId` for `activeId()` callers + diagnostic logs. */
|
|
3032
|
+
lazyProvider;
|
|
2861
3033
|
/**
|
|
2862
|
-
*
|
|
2863
|
-
*
|
|
2864
|
-
* registry
|
|
3034
|
+
* Read the registry from disk so the host can log a boot banner. Does
|
|
3035
|
+
* NOT cache a per-id provider — each `activeProvider()` call re-reads
|
|
3036
|
+
* the registry, so a workspace switch in the desktop is picked up by
|
|
3037
|
+
* the next tool call without restarting the MCP server.
|
|
2865
3038
|
*/
|
|
2866
3039
|
async init() {
|
|
2867
3040
|
const registry = await (0, import_registry.loadRegistry)(this.registryRoot) ?? {
|
|
@@ -2869,22 +3042,18 @@ var MultiWorkspaceProvider = class {
|
|
|
2869
3042
|
activeWorkspaceId: null,
|
|
2870
3043
|
workspaces: []
|
|
2871
3044
|
};
|
|
2872
|
-
|
|
2873
|
-
this.activeWorkspaceId = registry.activeWorkspaceId;
|
|
2874
|
-
this.active = new FileBackedWorkspaceProvider(
|
|
2875
|
-
(0, import_registry.workspaceDirFor)(this.registryRoot, registry.activeWorkspaceId)
|
|
2876
|
-
);
|
|
2877
|
-
}
|
|
3045
|
+
this.activeWorkspaceId = registry.activeWorkspaceId;
|
|
2878
3046
|
return registry;
|
|
2879
3047
|
}
|
|
2880
|
-
/**
|
|
3048
|
+
/**
|
|
3049
|
+
* The provider tool handlers see as `ctx.workspace`. Returns a lazy
|
|
3050
|
+
* provider whose `read` / `apply` / `write` calls re-read
|
|
3051
|
+
* `registry.json` so the right active workspace is always targeted
|
|
3052
|
+
* even if the desktop switched workspaces since this MCP process
|
|
3053
|
+
* started.
|
|
3054
|
+
*/
|
|
2881
3055
|
activeProvider() {
|
|
2882
|
-
|
|
2883
|
-
throw new Error(
|
|
2884
|
-
"No active workspace. Open the desktop app at least once, or run `apicircle workspaces create <name>`."
|
|
2885
|
-
);
|
|
2886
|
-
}
|
|
2887
|
-
return this.active;
|
|
3056
|
+
return this.lazyProvider;
|
|
2888
3057
|
}
|
|
2889
3058
|
// ─── Workspaces interface ──────────────────────────────────────────────────
|
|
2890
3059
|
async list() {
|
|
@@ -2932,23 +3101,17 @@ var MultiWorkspaceProvider = class {
|
|
|
2932
3101
|
if (!registry || !registry.workspaces.some((w) => w.id === workspaceId)) {
|
|
2933
3102
|
throw new WorkspaceNotFoundError(workspaceId);
|
|
2934
3103
|
}
|
|
2935
|
-
|
|
2936
|
-
void next;
|
|
3104
|
+
await (0, import_registry.setActiveWorkspace)(this.registryRoot, workspaceId);
|
|
2937
3105
|
this.activeWorkspaceId = workspaceId;
|
|
2938
|
-
this.active = new FileBackedWorkspaceProvider((0, import_registry.workspaceDirFor)(this.registryRoot, workspaceId));
|
|
2939
3106
|
}
|
|
2940
3107
|
/**
|
|
2941
3108
|
* Idempotent registry write — used by tests / tools that need to
|
|
2942
|
-
* persist registry updates that didn't go through `setActive`.
|
|
3109
|
+
* persist registry updates that didn't go through `setActive`. The
|
|
3110
|
+
* lazy active provider picks the new id up on its next operation.
|
|
2943
3111
|
*/
|
|
2944
3112
|
async writeRegistry(registry) {
|
|
2945
3113
|
await (0, import_registry.saveRegistry)(this.registryRoot, registry);
|
|
2946
3114
|
this.activeWorkspaceId = registry.activeWorkspaceId;
|
|
2947
|
-
if (registry.activeWorkspaceId) {
|
|
2948
|
-
this.active = new FileBackedWorkspaceProvider(
|
|
2949
|
-
(0, import_registry.workspaceDirFor)(this.registryRoot, registry.activeWorkspaceId)
|
|
2950
|
-
);
|
|
2951
|
-
}
|
|
2952
3115
|
}
|
|
2953
3116
|
};
|
|
2954
3117
|
|