@zackbart/connecta 0.15.1 → 0.16.1
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/AGENTS.md +40 -20
- package/CHANGELOG.md +653 -0
- package/README.md +25 -5
- package/bin/connecta.mjs +44 -3
- package/dist/access-tokens.d.ts +0 -1
- package/dist/access-tokens.js +0 -1
- package/dist/activity.d.ts +50 -2
- package/dist/activity.js +34 -1
- package/dist/apps-shell.d.ts +0 -1
- package/dist/apps-shell.js +0 -1
- package/dist/auth/bearer.d.ts +0 -1
- package/dist/auth/bearer.js +0 -1
- package/dist/auth/clerk.d.ts +0 -1
- package/dist/auth/clerk.js +45 -9
- package/dist/auth/downstream-oauth.d.ts +0 -1
- package/dist/auth/downstream-oauth.js +0 -1
- package/dist/call-admission.d.ts +0 -1
- package/dist/call-admission.js +0 -1
- package/dist/catalog-drift.d.ts +99 -0
- package/dist/catalog-drift.js +251 -0
- package/dist/catalog-fingerprint.d.ts +0 -1
- package/dist/catalog-fingerprint.js +0 -1
- package/dist/catalog-limits.d.ts +0 -1
- package/dist/catalog-limits.js +0 -1
- package/dist/catalog-service.d.ts +0 -1
- package/dist/catalog-service.js +41 -5
- package/dist/catalog.d.ts +11 -1
- package/dist/catalog.js +20 -1
- package/dist/concurrency.d.ts +0 -1
- package/dist/concurrency.js +0 -1
- package/dist/connector-scope.d.ts +0 -1
- package/dist/connector-scope.js +0 -1
- package/dist/connectors/api.d.ts +29 -21
- package/dist/connectors/api.js +45 -19
- package/dist/connectors/guarded-fetch.d.ts +106 -0
- package/dist/connectors/guarded-fetch.js +289 -0
- package/dist/connectors/remote-mcp.d.ts +0 -1
- package/dist/connectors/remote-mcp.js +0 -1
- package/dist/credentials.d.ts +0 -1
- package/dist/credentials.js +0 -1
- package/dist/errors.d.ts +30 -3
- package/dist/errors.js +1 -1
- package/dist/execute.d.ts +0 -1
- package/dist/execute.js +0 -1
- package/dist/executor-admission.d.ts +11 -1
- package/dist/executor-admission.js +28 -1
- package/dist/executor-result.d.ts +0 -1
- package/dist/executor-result.js +0 -1
- package/dist/executors/quickjs-child.d.ts +0 -1
- package/dist/executors/quickjs-child.js +0 -1
- package/dist/executors/quickjs-protocol.d.ts +0 -1
- package/dist/executors/quickjs-protocol.js +0 -1
- package/dist/executors/quickjs-runtime.d.ts +0 -1
- package/dist/executors/quickjs-runtime.js +0 -1
- package/dist/executors/quickjs.d.ts +0 -1
- package/dist/executors/quickjs.js +2 -1
- package/dist/favicon.d.ts +0 -1
- package/dist/favicon.js +0 -1
- package/dist/index.d.ts +2 -3
- package/dist/index.js +24 -7
- package/dist/invocation.d.ts +0 -1
- package/dist/invocation.js +0 -1
- package/dist/json-schema.d.ts +0 -1
- package/dist/json-schema.js +0 -1
- package/dist/mcp-result.d.ts +0 -1
- package/dist/mcp-result.js +0 -1
- package/dist/meta-tools.d.ts +0 -1
- package/dist/meta-tools.js +0 -1
- package/dist/node.d.ts +0 -1
- package/dist/node.js +0 -1
- package/dist/operator-ui/generated.d.ts +2 -3
- package/dist/operator-ui/generated.js +3 -4
- package/dist/operator-ui/model.d.ts +10 -1
- package/dist/operator-ui/model.js +0 -1
- package/dist/operator-ui/view.d.ts +167 -0
- package/dist/operator-ui/view.js +270 -0
- package/dist/providers/cloudflare.d.ts +0 -1
- package/dist/providers/cloudflare.js +261 -299
- package/dist/providers/linear.d.ts +26 -5
- package/dist/providers/linear.js +32 -61
- package/dist/providers/mixpanel.d.ts +35 -4
- package/dist/providers/mixpanel.js +53 -79
- package/dist/providers/notion.d.ts +0 -1
- package/dist/providers/notion.js +87 -42
- package/dist/providers/stripe.d.ts +13 -1
- package/dist/providers/stripe.js +31 -60
- package/dist/registry.d.ts +34 -2
- package/dist/registry.js +85 -5
- package/dist/retired-toolkits.d.ts +0 -1
- package/dist/retired-toolkits.js +0 -1
- package/dist/routes/access-tokens.d.ts +0 -1
- package/dist/routes/access-tokens.js +0 -1
- package/dist/routes/activity.d.ts +0 -1
- package/dist/routes/activity.js +0 -1
- package/dist/routes/credentials.d.ts +0 -1
- package/dist/routes/credentials.js +0 -1
- package/dist/routes/mcp.d.ts +0 -1
- package/dist/routes/mcp.js +0 -1
- package/dist/routes/oauth.d.ts +0 -1
- package/dist/routes/oauth.js +0 -1
- package/dist/routes/shared.d.ts +2 -1
- package/dist/routes/shared.js +0 -1
- package/dist/routes/ui.d.ts +0 -1
- package/dist/routes/ui.js +0 -1
- package/dist/server.d.ts +0 -1
- package/dist/server.js +11 -1
- package/dist/skills.d.ts +0 -1
- package/dist/skills.js +0 -1
- package/dist/storage/file.d.ts +0 -1
- package/dist/storage/file.js +0 -1
- package/dist/storage/memory.d.ts +0 -1
- package/dist/storage/memory.js +0 -1
- package/dist/timeout.d.ts +0 -1
- package/dist/timeout.js +0 -1
- package/dist/tool-safety.d.ts +0 -1
- package/dist/tool-safety.js +0 -1
- package/dist/types.d.ts +45 -1
- package/dist/types.js +0 -1
- package/dist/ui.d.ts +0 -1
- package/dist/ui.js +13 -137
- package/dist/validate.d.ts +13 -15
- package/dist/validate.js +24 -11
- package/dist/version.d.ts +1 -2
- package/dist/version.js +1 -2
- package/documentation/architecture.md +186 -5
- package/documentation/auth.md +11 -0
- package/documentation/call-admission.md +142 -6
- package/documentation/cloudflare.md +92 -10
- package/documentation/code-first-exploration.md +2 -2
- package/documentation/code-mode.md +14 -14
- package/documentation/connector-guides.md +172 -5
- package/documentation/connectors.md +89 -0
- package/documentation/linear.md +20 -2
- package/documentation/mcp-ui-design.md +2 -2
- package/documentation/meta-tools.md +7 -1
- package/documentation/mixpanel.md +42 -9
- package/documentation/notion.md +23 -2
- package/documentation/operations.md +325 -5
- package/documentation/operator-ui.md +120 -5
- package/documentation/provider-audit.md +160 -0
- package/documentation/provider-conventions.md +667 -0
- package/documentation/request-admission.md +167 -5
- package/documentation/rich-output-design.md +1 -2
- package/documentation/stripe.md +15 -0
- package/documentation/upgrading.md +454 -0
- package/ethos.md +14 -9
- package/examples/worker/README.md +102 -12
- package/examples/worker/src/index.ts +46 -1
- package/examples/worker/wrangler.jsonc +14 -1
- package/package.json +10 -6
- package/templates/node/.dockerignore +10 -0
- package/templates/node/.env.example +40 -3
- package/templates/node/AGENTS.md +16 -1
- package/templates/node/Dockerfile +49 -0
- package/templates/node/README.md +117 -2
- package/templates/node/docker-compose.yml +39 -0
- package/templates/node/package.json +1 -1
- package/templates/node/src/file-activity.ts +182 -0
- package/templates/node/src/index.ts +80 -4
- package/assets/connecta-clay-hero.png +0 -0
- package/dist/access-tokens.d.ts.map +0 -1
- package/dist/access-tokens.js.map +0 -1
- package/dist/activity.d.ts.map +0 -1
- package/dist/activity.js.map +0 -1
- package/dist/apps-shell.d.ts.map +0 -1
- package/dist/apps-shell.js.map +0 -1
- package/dist/auth/bearer.d.ts.map +0 -1
- package/dist/auth/bearer.js.map +0 -1
- package/dist/auth/clerk.d.ts.map +0 -1
- package/dist/auth/clerk.js.map +0 -1
- package/dist/auth/downstream-oauth.d.ts.map +0 -1
- package/dist/auth/downstream-oauth.js.map +0 -1
- package/dist/call-admission.d.ts.map +0 -1
- package/dist/call-admission.js.map +0 -1
- package/dist/catalog-fingerprint.d.ts.map +0 -1
- package/dist/catalog-fingerprint.js.map +0 -1
- package/dist/catalog-limits.d.ts.map +0 -1
- package/dist/catalog-limits.js.map +0 -1
- package/dist/catalog-service.d.ts.map +0 -1
- package/dist/catalog-service.js.map +0 -1
- package/dist/catalog.d.ts.map +0 -1
- package/dist/catalog.js.map +0 -1
- package/dist/concurrency.d.ts.map +0 -1
- package/dist/concurrency.js.map +0 -1
- package/dist/connector-scope.d.ts.map +0 -1
- package/dist/connector-scope.js.map +0 -1
- package/dist/connectors/api.d.ts.map +0 -1
- package/dist/connectors/api.js.map +0 -1
- package/dist/connectors/remote-mcp.d.ts.map +0 -1
- package/dist/connectors/remote-mcp.js.map +0 -1
- package/dist/credentials.d.ts.map +0 -1
- package/dist/credentials.js.map +0 -1
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js.map +0 -1
- package/dist/execute.d.ts.map +0 -1
- package/dist/execute.js.map +0 -1
- package/dist/executor-admission.d.ts.map +0 -1
- package/dist/executor-admission.js.map +0 -1
- package/dist/executor-result.d.ts.map +0 -1
- package/dist/executor-result.js.map +0 -1
- package/dist/executors/quickjs-child.d.ts.map +0 -1
- package/dist/executors/quickjs-child.js.map +0 -1
- package/dist/executors/quickjs-protocol.d.ts.map +0 -1
- package/dist/executors/quickjs-protocol.js.map +0 -1
- package/dist/executors/quickjs-runtime.d.ts.map +0 -1
- package/dist/executors/quickjs-runtime.js.map +0 -1
- package/dist/executors/quickjs.d.ts.map +0 -1
- package/dist/executors/quickjs.js.map +0 -1
- package/dist/favicon.d.ts.map +0 -1
- package/dist/favicon.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/invocation.d.ts.map +0 -1
- package/dist/invocation.js.map +0 -1
- package/dist/json-schema.d.ts.map +0 -1
- package/dist/json-schema.js.map +0 -1
- package/dist/mcp-result.d.ts.map +0 -1
- package/dist/mcp-result.js.map +0 -1
- package/dist/meta-tools.d.ts.map +0 -1
- package/dist/meta-tools.js.map +0 -1
- package/dist/node.d.ts.map +0 -1
- package/dist/node.js.map +0 -1
- package/dist/operator-ui/generated.d.ts.map +0 -1
- package/dist/operator-ui/generated.js.map +0 -1
- package/dist/operator-ui/model.d.ts.map +0 -1
- package/dist/operator-ui/model.js.map +0 -1
- package/dist/providers/cloudflare.d.ts.map +0 -1
- package/dist/providers/cloudflare.js.map +0 -1
- package/dist/providers/linear.d.ts.map +0 -1
- package/dist/providers/linear.js.map +0 -1
- package/dist/providers/mixpanel.d.ts.map +0 -1
- package/dist/providers/mixpanel.js.map +0 -1
- package/dist/providers/notion.d.ts.map +0 -1
- package/dist/providers/notion.js.map +0 -1
- package/dist/providers/stripe.d.ts.map +0 -1
- package/dist/providers/stripe.js.map +0 -1
- package/dist/registry.d.ts.map +0 -1
- package/dist/registry.js.map +0 -1
- package/dist/retired-toolkits.d.ts.map +0 -1
- package/dist/retired-toolkits.js.map +0 -1
- package/dist/routes/access-tokens.d.ts.map +0 -1
- package/dist/routes/access-tokens.js.map +0 -1
- package/dist/routes/activity.d.ts.map +0 -1
- package/dist/routes/activity.js.map +0 -1
- package/dist/routes/credentials.d.ts.map +0 -1
- package/dist/routes/credentials.js.map +0 -1
- package/dist/routes/mcp.d.ts.map +0 -1
- package/dist/routes/mcp.js.map +0 -1
- package/dist/routes/oauth.d.ts.map +0 -1
- package/dist/routes/oauth.js.map +0 -1
- package/dist/routes/shared.d.ts.map +0 -1
- package/dist/routes/shared.js.map +0 -1
- package/dist/routes/ui.d.ts.map +0 -1
- package/dist/routes/ui.js.map +0 -1
- package/dist/server.d.ts.map +0 -1
- package/dist/server.js.map +0 -1
- package/dist/skills.d.ts.map +0 -1
- package/dist/skills.js.map +0 -1
- package/dist/storage/file.d.ts.map +0 -1
- package/dist/storage/file.js.map +0 -1
- package/dist/storage/memory.d.ts.map +0 -1
- package/dist/storage/memory.js.map +0 -1
- package/dist/timeout.d.ts.map +0 -1
- package/dist/timeout.js.map +0 -1
- package/dist/tool-safety.d.ts.map +0 -1
- package/dist/tool-safety.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/ui.d.ts.map +0 -1
- package/dist/ui.js.map +0 -1
- package/dist/validate.d.ts.map +0 -1
- package/dist/validate.js.map +0 -1
- package/dist/version.d.ts.map +0 -1
- package/dist/version.js.map +0 -1
- package/examples/node/README.md +0 -52
- package/examples/node/src/index.ts +0 -71
- package/src/access-tokens.ts +0 -289
- package/src/activity.ts +0 -234
- package/src/apps-shell.ts +0 -370
- package/src/auth/bearer.ts +0 -61
- package/src/auth/clerk.ts +0 -553
- package/src/auth/downstream-oauth.ts +0 -575
- package/src/call-admission.ts +0 -521
- package/src/catalog-fingerprint.ts +0 -52
- package/src/catalog-limits.ts +0 -11
- package/src/catalog-service.ts +0 -1153
- package/src/catalog.ts +0 -790
- package/src/concurrency.ts +0 -39
- package/src/connector-scope.ts +0 -66
- package/src/connectors/api.ts +0 -159
- package/src/connectors/remote-mcp.ts +0 -1090
- package/src/credentials.ts +0 -428
- package/src/errors.ts +0 -364
- package/src/execute.ts +0 -1406
- package/src/executor-admission.ts +0 -328
- package/src/executor-result.ts +0 -107
- package/src/executors/quickjs-child.ts +0 -172
- package/src/executors/quickjs-protocol.ts +0 -99
- package/src/executors/quickjs-runtime.ts +0 -470
- package/src/executors/quickjs.ts +0 -776
- package/src/favicon.ts +0 -53
- package/src/index.ts +0 -666
- package/src/invocation.ts +0 -655
- package/src/json-schema.ts +0 -11
- package/src/mcp-result.ts +0 -43
- package/src/meta-tools.ts +0 -1607
- package/src/node.ts +0 -206
- package/src/operator-ui/browser.css +0 -423
- package/src/operator-ui/browser.ts +0 -1281
- package/src/operator-ui/generated.ts +0 -4
- package/src/operator-ui/model.ts +0 -111
- package/src/providers/cloudflare.ts +0 -3999
- package/src/providers/linear.ts +0 -302
- package/src/providers/mixpanel.ts +0 -229
- package/src/providers/notion.ts +0 -1879
- package/src/providers/stripe.ts +0 -307
- package/src/registry.ts +0 -1085
- package/src/retired-toolkits.ts +0 -14
- package/src/routes/access-tokens.ts +0 -115
- package/src/routes/activity.ts +0 -215
- package/src/routes/credentials.ts +0 -254
- package/src/routes/mcp.ts +0 -429
- package/src/routes/oauth.ts +0 -322
- package/src/routes/shared.ts +0 -247
- package/src/routes/ui.ts +0 -152
- package/src/server.ts +0 -195
- package/src/skills.ts +0 -271
- package/src/storage/file.ts +0 -123
- package/src/storage/memory.ts +0 -44
- package/src/timeout.ts +0 -84
- package/src/tool-safety.ts +0 -15
- package/src/types.ts +0 -523
- package/src/ui.ts +0 -744
- package/src/validate.ts +0 -387
- package/src/version.ts +0 -7
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* required-key list, and a declared output shape.
|
|
17
17
|
*/
|
|
18
18
|
import { api } from "../connectors/api.js";
|
|
19
|
+
import { guardedFetch, } from "../connectors/guarded-fetch.js";
|
|
19
20
|
import { ConnectorCallError } from "../errors.js";
|
|
20
21
|
/** Cloudflare's v4 REST base. Override only for a proxy or a test double. */
|
|
21
22
|
export const CLOUDFLARE_API_BASE = "https://api.cloudflare.com/client/v4";
|
|
@@ -234,14 +235,28 @@ function failureFor(status, headers, errors) {
|
|
|
234
235
|
if (status === 400 || status === 409 || status === 422) {
|
|
235
236
|
return new ConnectorCallError("invalid_args", `Cloudflare rejected the request (HTTP ${status}). ${detail}`);
|
|
236
237
|
}
|
|
238
|
+
// Cloudflare's 404 is an honest absence: a token that may not touch a
|
|
239
|
+
// resource is refused with 401 or 403 above, not hidden behind a miss, so
|
|
240
|
+
// this is the unambiguous case `not_found` exists for — re-address, do not
|
|
241
|
+
// retry and do not re-authorize.
|
|
237
242
|
if (status === 404) {
|
|
238
|
-
return new ConnectorCallError("
|
|
243
|
+
return new ConnectorCallError("not_found", `Cloudflare found no such resource (HTTP 404). ${detail} Confirm the zone or account id with list_zones or list_accounts.`);
|
|
239
244
|
}
|
|
240
245
|
if (status >= 500) {
|
|
241
246
|
return new ConnectorCallError("unavailable", `Cloudflare is unavailable (HTTP ${status}). ${detail}`);
|
|
242
247
|
}
|
|
243
248
|
return new ConnectorCallError("connector_call_failed", `Cloudflare request failed (HTTP ${status}). ${detail}`);
|
|
244
249
|
}
|
|
250
|
+
// --- The request path --------------------------------------------------------
|
|
251
|
+
/**
|
|
252
|
+
* The largest response this connection will read.
|
|
253
|
+
*
|
|
254
|
+
* Generous rather than tight, because `cloudflare_api_get` legitimately
|
|
255
|
+
* downloads Worker scripts and R2 objects. It is a ceiling on absurdity, not a
|
|
256
|
+
* quota: anything approaching it is already far past whatever `maxResultBytes`
|
|
257
|
+
* the deployment set, so the caller was never going to see it whole.
|
|
258
|
+
*/
|
|
259
|
+
const CLOUDFLARE_MAX_RESPONSE_BYTES = 8 * 1024 * 1024;
|
|
245
260
|
const AUTHENTICATION_CONTEXT = Symbol("cloudflareAuthentication");
|
|
246
261
|
function withAuthentication(ctx, authentication) {
|
|
247
262
|
return { ...ctx, [AUTHENTICATION_CONTEXT]: authentication };
|
|
@@ -262,72 +277,63 @@ async function readAuthenticationHeaders(ctx) {
|
|
|
262
277
|
}
|
|
263
278
|
return { Authorization: `Bearer ${token}` };
|
|
264
279
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
response = await fetch(buildUrl(base, spec), {
|
|
282
|
-
method: spec.method,
|
|
283
|
-
headers: {
|
|
284
|
-
...authenticationHeaders,
|
|
285
|
-
Accept: "application/json",
|
|
286
|
-
...(spec.body !== undefined
|
|
287
|
-
? { "Content-Type": "application/json" }
|
|
288
|
-
: {}),
|
|
289
|
-
...Object.fromEntries(Object.entries(spec.headers ?? {}).filter((entry) => entry[1] !== undefined)),
|
|
290
|
-
},
|
|
291
|
-
...(spec.body !== undefined
|
|
292
|
-
? { body: JSON.stringify(spec.body) }
|
|
293
|
-
: spec.rawBody !== undefined
|
|
294
|
-
? { body: spec.rawBody }
|
|
295
|
-
: {}),
|
|
296
|
-
...(ctx.signal ? { signal: ctx.signal } : {}),
|
|
297
|
-
});
|
|
298
|
-
}
|
|
299
|
-
catch (cause) {
|
|
300
|
-
throw new ConnectorCallError("unavailable", `Could not reach the Cloudflare API: ${cause instanceof Error ? cause.message : String(cause)}`, { cause });
|
|
301
|
-
}
|
|
302
|
-
return response;
|
|
280
|
+
/**
|
|
281
|
+
* The one transport every Cloudflare tool goes through.
|
|
282
|
+
*
|
|
283
|
+
* URL confinement, `ctx.signal`, redirect refusal, bounded reads, and the
|
|
284
|
+
* "could not reach the provider" normalization all live in the shared helper.
|
|
285
|
+
* What stays here is what only Cloudflare knows: which headers prove identity,
|
|
286
|
+
* and what a status code means once it arrives.
|
|
287
|
+
*/
|
|
288
|
+
function cloudflareTransport(baseUrl) {
|
|
289
|
+
return guardedFetch({
|
|
290
|
+
provider: "Cloudflare",
|
|
291
|
+
baseUrl,
|
|
292
|
+
headers: { Accept: "application/json" },
|
|
293
|
+
maxResponseBytes: CLOUDFLARE_MAX_RESPONSE_BYTES,
|
|
294
|
+
authenticate: (ctx) => readAuthenticationHeaders(ctx),
|
|
295
|
+
});
|
|
303
296
|
}
|
|
304
|
-
async function callCloudflare(
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
297
|
+
async function callCloudflare(send, spec, ctx) {
|
|
298
|
+
return await send(spec, ctx, async (response) => {
|
|
299
|
+
let envelope;
|
|
300
|
+
let parseFailure;
|
|
301
|
+
try {
|
|
302
|
+
envelope = (await response.json());
|
|
303
|
+
}
|
|
304
|
+
catch (cause) {
|
|
305
|
+
// A transport failure is not a parse failure. The connector's byte
|
|
306
|
+
// ceiling fires from inside this read and is deliberately non-retryable;
|
|
307
|
+
// routing it through the branch below would relabel it as a retryable
|
|
308
|
+
// `unavailable` and tell an agent to retry a response that will exceed
|
|
309
|
+
// the ceiling every time.
|
|
310
|
+
if (cause instanceof ConnectorCallError)
|
|
311
|
+
throw cause;
|
|
312
|
+
parseFailure = cause;
|
|
313
|
+
}
|
|
314
|
+
if (envelope === undefined) {
|
|
315
|
+
// A gateway error page or an empty body, not an envelope: the status is
|
|
316
|
+
// the only real signal left.
|
|
317
|
+
throw response.ok
|
|
318
|
+
? new ConnectorCallError("unavailable", "Cloudflare returned a non-JSON body for a successful status.", parseFailure !== undefined ? { cause: parseFailure } : {})
|
|
319
|
+
: failureFor(response.status, response.headers, []);
|
|
320
|
+
}
|
|
321
|
+
const errors = Array.isArray(envelope.errors) ? envelope.errors : [];
|
|
322
|
+
if (!response.ok || envelope.success === false) {
|
|
323
|
+
throw failureFor(response.status, response.headers, errors);
|
|
324
|
+
}
|
|
325
|
+
const isV4Envelope = "success" in envelope ||
|
|
326
|
+
"result" in envelope ||
|
|
327
|
+
"result_info" in envelope ||
|
|
328
|
+
"messages" in envelope;
|
|
329
|
+
return {
|
|
330
|
+
// `/graphql` and a small number of product APIs return ordinary JSON
|
|
331
|
+
// instead of the standard v4 envelope. Preserve that document whole so
|
|
332
|
+
// the raw tools cover them too.
|
|
333
|
+
result: isV4Envelope ? envelope.result : envelope,
|
|
334
|
+
resultInfo: isV4Envelope ? envelope.result_info : undefined,
|
|
335
|
+
};
|
|
336
|
+
});
|
|
331
337
|
}
|
|
332
338
|
function base64FromBytes(bytes) {
|
|
333
339
|
let binary = "";
|
|
@@ -336,33 +342,34 @@ function base64FromBytes(bytes) {
|
|
|
336
342
|
}
|
|
337
343
|
return btoa(binary);
|
|
338
344
|
}
|
|
339
|
-
async function callCloudflareContent(
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
345
|
+
async function callCloudflareContent(send, spec, ctx, responseType) {
|
|
346
|
+
return await send(spec, ctx, async (response) => {
|
|
347
|
+
if (!response.ok) {
|
|
348
|
+
let errors = [];
|
|
349
|
+
try {
|
|
350
|
+
const envelope = (await response.json());
|
|
351
|
+
if (envelope && Array.isArray(envelope.errors))
|
|
352
|
+
errors = envelope.errors;
|
|
353
|
+
}
|
|
354
|
+
catch {
|
|
355
|
+
// A raw or gateway error body has no structured detail to preserve,
|
|
356
|
+
// and one past the byte ceiling has none worth reporting over the
|
|
357
|
+
// status that already failed this call. Either way the throw below
|
|
358
|
+
// classifies the status, so nothing is swallowed into a success.
|
|
359
|
+
}
|
|
360
|
+
throw failureFor(response.status, response.headers, errors);
|
|
347
361
|
}
|
|
348
|
-
|
|
349
|
-
|
|
362
|
+
const common = {
|
|
363
|
+
contentType: response.headers.get("content-type") ?? "application/octet-stream",
|
|
364
|
+
...(response.headers.get("etag")
|
|
365
|
+
? { etag: response.headers.get("etag") }
|
|
366
|
+
: {}),
|
|
367
|
+
};
|
|
368
|
+
if (responseType === "text") {
|
|
369
|
+
return { ...common, text: await response.text() };
|
|
350
370
|
}
|
|
351
|
-
|
|
352
|
-
}
|
|
353
|
-
const common = {
|
|
354
|
-
contentType: response.headers.get("content-type") ?? "application/octet-stream",
|
|
355
|
-
...(response.headers.get("etag")
|
|
356
|
-
? { etag: response.headers.get("etag") }
|
|
357
|
-
: {}),
|
|
358
|
-
};
|
|
359
|
-
if (responseType === "text") {
|
|
360
|
-
return { ...common, text: await response.text() };
|
|
361
|
-
}
|
|
362
|
-
return {
|
|
363
|
-
...common,
|
|
364
|
-
base64: base64FromBytes(new Uint8Array(await response.arrayBuffer())),
|
|
365
|
-
};
|
|
371
|
+
return { ...common, base64: base64FromBytes(await response.bytes()) };
|
|
372
|
+
});
|
|
366
373
|
}
|
|
367
374
|
/**
|
|
368
375
|
* Cloudflare's `result_info` reshaped into the one question an agent actually
|
|
@@ -631,8 +638,8 @@ const RAW_INPUT_PROPERTY = {
|
|
|
631
638
|
* an out-of-range value with a 400, so each caller passes its own. Encoding
|
|
632
639
|
* them in the schema turns a wasted round trip into a local repair — but only
|
|
633
640
|
* where the bound is really Cloudflare's. `bounds` records who chose the
|
|
634
|
-
* range, because `
|
|
635
|
-
*
|
|
641
|
+
* range, because `api()` refuses an out-of-range `perPage` locally and an
|
|
642
|
+
* agent deserves to know whether the wall it hit is the API's or ours:
|
|
636
643
|
*
|
|
637
644
|
* - `"cloudflare"` — the schema's own documented minimum and maximum.
|
|
638
645
|
* - `"clamped"` — Cloudflare accepts more; this connection caps it lower.
|
|
@@ -663,6 +670,24 @@ function pagingInputProperties(minPerPage, maxPerPage, options = {}) {
|
|
|
663
670
|
},
|
|
664
671
|
};
|
|
665
672
|
}
|
|
673
|
+
/**
|
|
674
|
+
* The second pagination convention, and the schemas say so.
|
|
675
|
+
*
|
|
676
|
+
* Rulesets, KV keys, and both R2 listings page by cursor rather than by page
|
|
677
|
+
* number, because that is how Cloudflare built them. The guide names the four,
|
|
678
|
+
* but an agent reading one tool's schema should not have to fetch the guide to
|
|
679
|
+
* learn that the `page` object it expected is not coming: absence of
|
|
680
|
+
* `nextCursor` is the loop condition here, and it is stated on both ends
|
|
681
|
+
* ([#342](https://github.com/zackbart/connecta/issues/342)).
|
|
682
|
+
*/
|
|
683
|
+
const CURSOR_INPUT_PROPERTY = {
|
|
684
|
+
type: "string",
|
|
685
|
+
description: "Opaque cursor from a previous call's nextCursor. This endpoint pages by cursor, not page number.",
|
|
686
|
+
};
|
|
687
|
+
const NEXT_CURSOR_OUTPUT_PROPERTY = {
|
|
688
|
+
type: "string",
|
|
689
|
+
description: "Pass back as `cursor` to continue. Absent when the listing is complete — this is the only signal; there is no page object.",
|
|
690
|
+
};
|
|
666
691
|
function listOutputSchema(key, item) {
|
|
667
692
|
return {
|
|
668
693
|
type: "object",
|
|
@@ -928,7 +953,7 @@ const OPEN_OBJECT_OUTPUT_SCHEMA = {
|
|
|
928
953
|
};
|
|
929
954
|
const QUERY_INPUT_PROPERTY = {
|
|
930
955
|
type: "array",
|
|
931
|
-
description: "
|
|
956
|
+
description: "Query parameters as name/value pairs; each name may appear once.",
|
|
932
957
|
items: {
|
|
933
958
|
type: "object",
|
|
934
959
|
properties: {
|
|
@@ -939,9 +964,14 @@ const QUERY_INPUT_PROPERTY = {
|
|
|
939
964
|
additionalProperties: false,
|
|
940
965
|
},
|
|
941
966
|
};
|
|
967
|
+
// Shared by all three escape hatches, and the compact renderer inlines it
|
|
968
|
+
// three times over. The refused-header list is the connector's boundary rather
|
|
969
|
+
// than a fact the caller composes with, so it lives in the usage guide; keeping
|
|
970
|
+
// it here pushed cloudflare_api_upload's compact input past the 1,024-byte
|
|
971
|
+
// budget ([#342](https://github.com/zackbart/connecta/issues/342)).
|
|
942
972
|
const HEADERS_INPUT_PROPERTY = {
|
|
943
973
|
type: "array",
|
|
944
|
-
description: "
|
|
974
|
+
description: "Endpoint headers as name/value pairs, e.g. cf-r2-jurisdiction or Range. Connector-owned headers are refused.",
|
|
945
975
|
items: {
|
|
946
976
|
type: "object",
|
|
947
977
|
properties: {
|
|
@@ -988,7 +1018,7 @@ const R2_OBJECT_SCHEMA = {
|
|
|
988
1018
|
required: ["key"],
|
|
989
1019
|
};
|
|
990
1020
|
function buildTools(scope, authentication) {
|
|
991
|
-
const {
|
|
1021
|
+
const { send } = scope;
|
|
992
1022
|
const zoneArg = (args) => requireScope(args["zoneId"], scope.zoneId, "zoneId");
|
|
993
1023
|
const accountArg = (args) => requireScope(args["accountId"], scope.accountId, "accountId");
|
|
994
1024
|
const readOnly = { readOnlyHint: true, destructiveHint: false };
|
|
@@ -1018,7 +1048,7 @@ function buildTools(scope, authentication) {
|
|
|
1018
1048
|
required: ["status"],
|
|
1019
1049
|
},
|
|
1020
1050
|
handler: async (_args, ctx) => {
|
|
1021
|
-
const { result } = await callCloudflare(
|
|
1051
|
+
const { result } = await callCloudflare(send, { method: "GET", path: "/user/tokens/verify" }, ctx);
|
|
1022
1052
|
const token = asRecord(result);
|
|
1023
1053
|
return {
|
|
1024
1054
|
id: token["id"],
|
|
@@ -1055,14 +1085,14 @@ function buildTools(scope, authentication) {
|
|
|
1055
1085
|
required: ["email", "status"],
|
|
1056
1086
|
},
|
|
1057
1087
|
handler: async (_args, ctx) => {
|
|
1058
|
-
const { result } = await callCloudflare(
|
|
1088
|
+
const { result } = await callCloudflare(send, { method: "GET", path: "/user" }, ctx);
|
|
1059
1089
|
const user = asRecord(result);
|
|
1060
1090
|
return { id: user["id"], email: user["email"], status: "active" };
|
|
1061
1091
|
},
|
|
1062
1092
|
},
|
|
1063
1093
|
{
|
|
1064
1094
|
name: "cloudflare_api_get",
|
|
1065
|
-
description: "Call any GET endpoint under Cloudflare's v4 API with this connector's credential.
|
|
1095
|
+
description: "Call any GET endpoint under Cloudflare's v4 API with this connector's credential. Prefer a named tool when one exists; this read-only hatch covers the products the named surface does not reach, such as Images, Stream, D1, and Queues.",
|
|
1066
1096
|
annotations: readOnly,
|
|
1067
1097
|
inputSchema: {
|
|
1068
1098
|
type: "object",
|
|
@@ -1111,9 +1141,9 @@ function buildTools(scope, authentication) {
|
|
|
1111
1141
|
...(headers !== undefined ? { headers } : {}),
|
|
1112
1142
|
};
|
|
1113
1143
|
if (responseType === "text" || responseType === "base64") {
|
|
1114
|
-
return await callCloudflareContent(
|
|
1144
|
+
return await callCloudflareContent(send, spec, ctx, responseType);
|
|
1115
1145
|
}
|
|
1116
|
-
const { result, resultInfo } = await callCloudflare(
|
|
1146
|
+
const { result, resultInfo } = await callCloudflare(send, spec, ctx);
|
|
1117
1147
|
return {
|
|
1118
1148
|
result,
|
|
1119
1149
|
...(resultInfo !== undefined ? { resultInfo } : {}),
|
|
@@ -1122,7 +1152,7 @@ function buildTools(scope, authentication) {
|
|
|
1122
1152
|
},
|
|
1123
1153
|
{
|
|
1124
1154
|
name: "cloudflare_api_mutate",
|
|
1125
|
-
description: "Call any JSON POST, PUT, PATCH, or DELETE endpoint under Cloudflare's v4 API with this connector's credential.
|
|
1155
|
+
description: "Call any JSON POST, PUT, PATCH, or DELETE endpoint under Cloudflare's v4 API with this connector's credential. The approval-gated write hatch for products the named surface does not reach. No multipart or binary uploads.",
|
|
1126
1156
|
annotations: { readOnlyHint: false, destructiveHint: true },
|
|
1127
1157
|
inputSchema: {
|
|
1128
1158
|
type: "object",
|
|
@@ -1164,7 +1194,7 @@ function buildTools(scope, authentication) {
|
|
|
1164
1194
|
const method = String(args["method"]);
|
|
1165
1195
|
const query = queryFromArgs(args["query"]);
|
|
1166
1196
|
const headers = headersFromArgs(args["headers"]);
|
|
1167
|
-
const { result, resultInfo } = await callCloudflare(
|
|
1197
|
+
const { result, resultInfo } = await callCloudflare(send, {
|
|
1168
1198
|
method,
|
|
1169
1199
|
path: cloudflareApiPath(args["path"]),
|
|
1170
1200
|
...(query !== undefined ? { query } : {}),
|
|
@@ -1187,31 +1217,31 @@ function buildTools(scope, authentication) {
|
|
|
1187
1217
|
method: {
|
|
1188
1218
|
type: "string",
|
|
1189
1219
|
enum: ["POST", "PUT"],
|
|
1190
|
-
description: "
|
|
1220
|
+
description: "Upload method the Cloudflare endpoint requires.",
|
|
1191
1221
|
},
|
|
1192
1222
|
path: {
|
|
1193
1223
|
type: "string",
|
|
1194
1224
|
minLength: 1,
|
|
1195
|
-
description: "
|
|
1225
|
+
description: "Path below /client/v4, beginning with '/'. No query string.",
|
|
1196
1226
|
},
|
|
1197
1227
|
query: QUERY_INPUT_PROPERTY,
|
|
1198
1228
|
headers: HEADERS_INPUT_PROPERTY,
|
|
1199
1229
|
contentType: {
|
|
1200
1230
|
type: "string",
|
|
1201
1231
|
minLength: 1,
|
|
1202
|
-
description: "Content-Type for a raw text
|
|
1232
|
+
description: "Content-Type for a raw text or base64 body. Omit for multipart.",
|
|
1203
1233
|
},
|
|
1204
1234
|
textBody: {
|
|
1205
1235
|
type: "string",
|
|
1206
|
-
description: "Raw UTF-8
|
|
1236
|
+
description: "Raw UTF-8 body. Exclusive with base64Body and fields/files.",
|
|
1207
1237
|
},
|
|
1208
1238
|
base64Body: {
|
|
1209
1239
|
type: "string",
|
|
1210
|
-
description: "Base64-encoded
|
|
1240
|
+
description: "Base64-encoded body bytes. Exclusive with textBody and fields/files.",
|
|
1211
1241
|
},
|
|
1212
1242
|
fields: {
|
|
1213
1243
|
type: "array",
|
|
1214
|
-
description: "String fields
|
|
1244
|
+
description: "String fields of a multipart/form-data request.",
|
|
1215
1245
|
items: {
|
|
1216
1246
|
type: "object",
|
|
1217
1247
|
properties: {
|
|
@@ -1226,7 +1256,7 @@ function buildTools(scope, authentication) {
|
|
|
1226
1256
|
},
|
|
1227
1257
|
files: {
|
|
1228
1258
|
type: "array",
|
|
1229
|
-
description: "
|
|
1259
|
+
description: "Multipart file parts. Each needs exactly one of text or base64.",
|
|
1230
1260
|
items: {
|
|
1231
1261
|
type: "object",
|
|
1232
1262
|
properties: {
|
|
@@ -1257,7 +1287,7 @@ function buildTools(scope, authentication) {
|
|
|
1257
1287
|
const query = queryFromArgs(args["query"]);
|
|
1258
1288
|
const headers = headersFromArgs(args["headers"]);
|
|
1259
1289
|
const upload = uploadBody(args);
|
|
1260
|
-
const { result } = await callCloudflare(
|
|
1290
|
+
const { result } = await callCloudflare(send, {
|
|
1261
1291
|
method: String(args["method"]),
|
|
1262
1292
|
path: cloudflareApiPath(args["path"]),
|
|
1263
1293
|
...(query !== undefined ? { query } : {}),
|
|
@@ -1288,7 +1318,7 @@ function buildTools(scope, authentication) {
|
|
|
1288
1318
|
},
|
|
1289
1319
|
outputSchema: listOutputSchema("accounts", ACCOUNT_SCHEMA),
|
|
1290
1320
|
handler: async (args, ctx) => {
|
|
1291
|
-
const { result, resultInfo } = await callCloudflare(
|
|
1321
|
+
const { result, resultInfo } = await callCloudflare(send, {
|
|
1292
1322
|
method: "GET",
|
|
1293
1323
|
path: "/accounts",
|
|
1294
1324
|
query: {
|
|
@@ -1333,7 +1363,7 @@ function buildTools(scope, authentication) {
|
|
|
1333
1363
|
},
|
|
1334
1364
|
outputSchema: listOutputSchema("zones", ZONE_SCHEMA),
|
|
1335
1365
|
handler: async (args, ctx) => {
|
|
1336
|
-
const { result, resultInfo } = await callCloudflare(
|
|
1366
|
+
const { result, resultInfo } = await callCloudflare(send, {
|
|
1337
1367
|
method: "GET",
|
|
1338
1368
|
path: "/zones",
|
|
1339
1369
|
query: {
|
|
@@ -1371,31 +1401,15 @@ function buildTools(scope, authentication) {
|
|
|
1371
1401
|
},
|
|
1372
1402
|
outputSchema: ZONE_SCHEMA,
|
|
1373
1403
|
handler: async (args, ctx) => {
|
|
1374
|
-
const { result } = await callCloudflare(
|
|
1404
|
+
const { result } = await callCloudflare(send, { method: "GET", path: `/zones/${encodeURIComponent(zoneArg(args))}` }, ctx);
|
|
1375
1405
|
return args["raw"] === true ? result : projectZone(result);
|
|
1376
1406
|
},
|
|
1377
1407
|
},
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
type: "object",
|
|
1384
|
-
properties: {
|
|
1385
|
-
zoneId: scopeProperty("zoneId", scope.zoneId),
|
|
1386
|
-
},
|
|
1387
|
-
required: scopeRequired("zoneId", scope.zoneId),
|
|
1388
|
-
additionalProperties: false,
|
|
1389
|
-
},
|
|
1390
|
-
outputSchema: listOutputSchema("settings", OPEN_OBJECT_OUTPUT_SCHEMA),
|
|
1391
|
-
handler: async (args, ctx) => {
|
|
1392
|
-
const { result, resultInfo } = await callCloudflare(base, {
|
|
1393
|
-
method: "GET",
|
|
1394
|
-
path: `/zones/${encodePathSegment(zoneArg(args))}/settings`,
|
|
1395
|
-
}, ctx);
|
|
1396
|
-
return { settings: asArray(result), page: pageInfo(resultInfo) };
|
|
1397
|
-
},
|
|
1398
|
-
},
|
|
1408
|
+
// There is deliberately no bulk zone-settings read here. Cloudflare
|
|
1409
|
+
// publishes `GET /zones/{zone_id}/settings` as deprecated (#361), the
|
|
1410
|
+
// per-setting operations below are not, and the tool that wrapped the bulk
|
|
1411
|
+
// read projected nothing. See the Cloudflare guide's "What the named
|
|
1412
|
+
// surface deliberately leaves out".
|
|
1399
1413
|
{
|
|
1400
1414
|
name: "get_zone_setting",
|
|
1401
1415
|
description: "Get one zone setting by its Cloudflare setting id, such as ssl, always_use_https, min_tls_version, brotli, or development_mode.",
|
|
@@ -1407,7 +1421,7 @@ function buildTools(scope, authentication) {
|
|
|
1407
1421
|
settingId: {
|
|
1408
1422
|
type: "string",
|
|
1409
1423
|
minLength: 1,
|
|
1410
|
-
description: "Cloudflare zone setting id
|
|
1424
|
+
description: "Cloudflare zone setting id, such as ssl, brotli, http3, or min_tls_version.",
|
|
1411
1425
|
},
|
|
1412
1426
|
},
|
|
1413
1427
|
required: [...scopeRequired("zoneId", scope.zoneId), "settingId"],
|
|
@@ -1415,7 +1429,7 @@ function buildTools(scope, authentication) {
|
|
|
1415
1429
|
},
|
|
1416
1430
|
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
1417
1431
|
handler: async (args, ctx) => {
|
|
1418
|
-
const { result } = await callCloudflare(
|
|
1432
|
+
const { result } = await callCloudflare(send, {
|
|
1419
1433
|
method: "GET",
|
|
1420
1434
|
path: `/zones/${encodePathSegment(zoneArg(args))}/settings/${encodePathSegment(requireString(args, "settingId"))}`,
|
|
1421
1435
|
}, ctx);
|
|
@@ -1433,7 +1447,7 @@ function buildTools(scope, authentication) {
|
|
|
1433
1447
|
settingId: {
|
|
1434
1448
|
type: "string",
|
|
1435
1449
|
minLength: 1,
|
|
1436
|
-
description: "Cloudflare zone setting id
|
|
1450
|
+
description: "Cloudflare zone setting id, such as ssl, brotli, http3, or min_tls_version.",
|
|
1437
1451
|
},
|
|
1438
1452
|
value: {
|
|
1439
1453
|
type: ["string", "number", "boolean", "array"],
|
|
@@ -1446,7 +1460,7 @@ function buildTools(scope, authentication) {
|
|
|
1446
1460
|
},
|
|
1447
1461
|
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
1448
1462
|
handler: async (args, ctx) => {
|
|
1449
|
-
const { result } = await callCloudflare(
|
|
1463
|
+
const { result } = await callCloudflare(send, {
|
|
1450
1464
|
method: "PATCH",
|
|
1451
1465
|
path: `/zones/${encodePathSegment(zoneArg(args))}/settings/${encodePathSegment(requireString(args, "settingId"))}`,
|
|
1452
1466
|
body: { value: args["value"] },
|
|
@@ -1468,10 +1482,7 @@ function buildTools(scope, authentication) {
|
|
|
1468
1482
|
maximum: 50,
|
|
1469
1483
|
description: "Rulesets per request, 1 to 50.",
|
|
1470
1484
|
},
|
|
1471
|
-
cursor:
|
|
1472
|
-
type: "string",
|
|
1473
|
-
description: "Opaque cursor returned as nextCursor by the previous call.",
|
|
1474
|
-
},
|
|
1485
|
+
cursor: CURSOR_INPUT_PROPERTY,
|
|
1475
1486
|
},
|
|
1476
1487
|
required: scopeRequired("zoneId", scope.zoneId),
|
|
1477
1488
|
additionalProperties: false,
|
|
@@ -1480,12 +1491,12 @@ function buildTools(scope, authentication) {
|
|
|
1480
1491
|
type: "object",
|
|
1481
1492
|
properties: {
|
|
1482
1493
|
rulesets: { type: "array", items: OPEN_OBJECT_OUTPUT_SCHEMA },
|
|
1483
|
-
nextCursor:
|
|
1494
|
+
nextCursor: NEXT_CURSOR_OUTPUT_PROPERTY,
|
|
1484
1495
|
},
|
|
1485
1496
|
required: ["rulesets"],
|
|
1486
1497
|
},
|
|
1487
1498
|
handler: async (args, ctx) => {
|
|
1488
|
-
const { result, resultInfo } = await callCloudflare(
|
|
1499
|
+
const { result, resultInfo } = await callCloudflare(send, {
|
|
1489
1500
|
method: "GET",
|
|
1490
1501
|
path: `/zones/${encodePathSegment(zoneArg(args))}/rulesets`,
|
|
1491
1502
|
query: {
|
|
@@ -1521,7 +1532,7 @@ function buildTools(scope, authentication) {
|
|
|
1521
1532
|
},
|
|
1522
1533
|
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
1523
1534
|
handler: async (args, ctx) => {
|
|
1524
|
-
const { result } = await callCloudflare(
|
|
1535
|
+
const { result } = await callCloudflare(send, {
|
|
1525
1536
|
method: "GET",
|
|
1526
1537
|
path: `/zones/${encodePathSegment(zoneArg(args))}/rulesets/${encodePathSegment(requireString(args, "rulesetId"))}`,
|
|
1527
1538
|
}, ctx);
|
|
@@ -1573,7 +1584,7 @@ function buildTools(scope, authentication) {
|
|
|
1573
1584
|
},
|
|
1574
1585
|
outputSchema: listOutputSchema("records", DNS_RECORD_SCHEMA),
|
|
1575
1586
|
handler: async (args, ctx) => {
|
|
1576
|
-
const { result, resultInfo } = await callCloudflare(
|
|
1587
|
+
const { result, resultInfo } = await callCloudflare(send, {
|
|
1577
1588
|
method: "GET",
|
|
1578
1589
|
path: `/zones/${encodeURIComponent(zoneArg(args))}/dns_records`,
|
|
1579
1590
|
query: {
|
|
@@ -1613,7 +1624,7 @@ function buildTools(scope, authentication) {
|
|
|
1613
1624
|
},
|
|
1614
1625
|
outputSchema: DNS_RECORD_SCHEMA,
|
|
1615
1626
|
handler: async (args, ctx) => {
|
|
1616
|
-
const { result } = await callCloudflare(
|
|
1627
|
+
const { result } = await callCloudflare(send, {
|
|
1617
1628
|
method: "GET",
|
|
1618
1629
|
path: `/zones/${encodeURIComponent(zoneArg(args))}/dns_records/${encodeURIComponent(String(args["recordId"]))}`,
|
|
1619
1630
|
}, ctx);
|
|
@@ -1644,7 +1655,7 @@ function buildTools(scope, authentication) {
|
|
|
1644
1655
|
required: ["id"],
|
|
1645
1656
|
}),
|
|
1646
1657
|
handler: async (args, ctx) => {
|
|
1647
|
-
const { result, resultInfo } = await callCloudflare(
|
|
1658
|
+
const { result, resultInfo } = await callCloudflare(send, {
|
|
1648
1659
|
method: "GET",
|
|
1649
1660
|
path: `/accounts/${encodeURIComponent(accountArg(args))}/workers/scripts`,
|
|
1650
1661
|
}, ctx);
|
|
@@ -1675,7 +1686,7 @@ function buildTools(scope, authentication) {
|
|
|
1675
1686
|
},
|
|
1676
1687
|
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
1677
1688
|
handler: async (args, ctx) => {
|
|
1678
|
-
const { result } = await callCloudflare(
|
|
1689
|
+
const { result } = await callCloudflare(send, {
|
|
1679
1690
|
method: "GET",
|
|
1680
1691
|
path: `/accounts/${encodePathSegment(accountArg(args))}/workers/scripts/${encodePathSegment(requireString(args, "scriptName"))}/settings`,
|
|
1681
1692
|
}, ctx);
|
|
@@ -1701,7 +1712,7 @@ function buildTools(scope, authentication) {
|
|
|
1701
1712
|
},
|
|
1702
1713
|
outputSchema: listOutputSchema("deployments", OPEN_OBJECT_OUTPUT_SCHEMA),
|
|
1703
1714
|
handler: async (args, ctx) => {
|
|
1704
|
-
const { result } = await callCloudflare(
|
|
1715
|
+
const { result } = await callCloudflare(send, {
|
|
1705
1716
|
method: "GET",
|
|
1706
1717
|
path: `/accounts/${encodePathSegment(accountArg(args))}/workers/scripts/${encodePathSegment(requireString(args, "scriptName"))}/deployments`,
|
|
1707
1718
|
}, ctx);
|
|
@@ -1740,7 +1751,7 @@ function buildTools(scope, authentication) {
|
|
|
1740
1751
|
},
|
|
1741
1752
|
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
1742
1753
|
handler: async (args, ctx) => {
|
|
1743
|
-
const { result } = await callCloudflare(
|
|
1754
|
+
const { result } = await callCloudflare(send, {
|
|
1744
1755
|
method: "GET",
|
|
1745
1756
|
path: `/accounts/${encodePathSegment(accountArg(args))}/workers/scripts/${encodePathSegment(requireString(args, "scriptName"))}/deployments/${encodePathSegment(requireString(args, "deploymentId"))}`,
|
|
1746
1757
|
}, ctx);
|
|
@@ -1778,7 +1789,7 @@ function buildTools(scope, authentication) {
|
|
|
1778
1789
|
},
|
|
1779
1790
|
handler: async (args, ctx) => {
|
|
1780
1791
|
const scriptName = requireString(args, "scriptName");
|
|
1781
|
-
await callCloudflare(
|
|
1792
|
+
await callCloudflare(send, {
|
|
1782
1793
|
method: "DELETE",
|
|
1783
1794
|
path: `/accounts/${encodePathSegment(accountArg(args))}/workers/scripts/${encodePathSegment(scriptName)}`,
|
|
1784
1795
|
query: { force: optionalBoolean(args, "force") },
|
|
@@ -1810,7 +1821,7 @@ function buildTools(scope, authentication) {
|
|
|
1810
1821
|
required: ["id", "title"],
|
|
1811
1822
|
}),
|
|
1812
1823
|
handler: async (args, ctx) => {
|
|
1813
|
-
const { result, resultInfo } = await callCloudflare(
|
|
1824
|
+
const { result, resultInfo } = await callCloudflare(send, {
|
|
1814
1825
|
method: "GET",
|
|
1815
1826
|
path: `/accounts/${encodeURIComponent(accountArg(args))}/storage/kv/namespaces`,
|
|
1816
1827
|
query: {
|
|
@@ -1845,7 +1856,7 @@ function buildTools(scope, authentication) {
|
|
|
1845
1856
|
},
|
|
1846
1857
|
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
1847
1858
|
handler: async (args, ctx) => {
|
|
1848
|
-
const { result } = await callCloudflare(
|
|
1859
|
+
const { result } = await callCloudflare(send, {
|
|
1849
1860
|
method: "GET",
|
|
1850
1861
|
path: `/accounts/${encodePathSegment(accountArg(args))}/storage/kv/namespaces/${encodePathSegment(requireString(args, "namespaceId"))}`,
|
|
1851
1862
|
}, ctx);
|
|
@@ -1872,7 +1883,7 @@ function buildTools(scope, authentication) {
|
|
|
1872
1883
|
},
|
|
1873
1884
|
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
1874
1885
|
handler: async (args, ctx) => {
|
|
1875
|
-
const { result } = await callCloudflare(
|
|
1886
|
+
const { result } = await callCloudflare(send, {
|
|
1876
1887
|
method: "POST",
|
|
1877
1888
|
path: `/accounts/${encodePathSegment(accountArg(args))}/storage/kv/namespaces`,
|
|
1878
1889
|
body: { title: requireString(args, "title") },
|
|
@@ -1909,7 +1920,7 @@ function buildTools(scope, authentication) {
|
|
|
1909
1920
|
},
|
|
1910
1921
|
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
1911
1922
|
handler: async (args, ctx) => {
|
|
1912
|
-
const { result } = await callCloudflare(
|
|
1923
|
+
const { result } = await callCloudflare(send, {
|
|
1913
1924
|
method: "PUT",
|
|
1914
1925
|
path: `/accounts/${encodePathSegment(accountArg(args))}/storage/kv/namespaces/${encodePathSegment(requireString(args, "namespaceId"))}`,
|
|
1915
1926
|
body: { title: requireString(args, "title") },
|
|
@@ -1944,7 +1955,7 @@ function buildTools(scope, authentication) {
|
|
|
1944
1955
|
},
|
|
1945
1956
|
handler: async (args, ctx) => {
|
|
1946
1957
|
const namespaceId = requireString(args, "namespaceId");
|
|
1947
|
-
await callCloudflare(
|
|
1958
|
+
await callCloudflare(send, {
|
|
1948
1959
|
method: "DELETE",
|
|
1949
1960
|
path: `/accounts/${encodePathSegment(accountArg(args))}/storage/kv/namespaces/${encodePathSegment(namespaceId)}`,
|
|
1950
1961
|
}, ctx);
|
|
@@ -1974,10 +1985,7 @@ function buildTools(scope, authentication) {
|
|
|
1974
1985
|
maximum: 1000,
|
|
1975
1986
|
description: "Keys per request, 10 to 1000. Defaults to 1000.",
|
|
1976
1987
|
},
|
|
1977
|
-
cursor:
|
|
1978
|
-
type: "string",
|
|
1979
|
-
description: "Opaque cursor returned as nextCursor by the previous call.",
|
|
1980
|
-
},
|
|
1988
|
+
cursor: CURSOR_INPUT_PROPERTY,
|
|
1981
1989
|
},
|
|
1982
1990
|
required: [...scopeRequired("accountId", scope.accountId), "namespaceId"],
|
|
1983
1991
|
additionalProperties: false,
|
|
@@ -1986,12 +1994,12 @@ function buildTools(scope, authentication) {
|
|
|
1986
1994
|
type: "object",
|
|
1987
1995
|
properties: {
|
|
1988
1996
|
keys: { type: "array", items: OPEN_OBJECT_OUTPUT_SCHEMA },
|
|
1989
|
-
nextCursor:
|
|
1997
|
+
nextCursor: NEXT_CURSOR_OUTPUT_PROPERTY,
|
|
1990
1998
|
},
|
|
1991
1999
|
required: ["keys"],
|
|
1992
2000
|
},
|
|
1993
2001
|
handler: async (args, ctx) => {
|
|
1994
|
-
const { result, resultInfo } = await callCloudflare(
|
|
2002
|
+
const { result, resultInfo } = await callCloudflare(send, {
|
|
1995
2003
|
method: "GET",
|
|
1996
2004
|
path: `/accounts/${encodePathSegment(accountArg(args))}/storage/kv/namespaces/${encodePathSegment(requireString(args, "namespaceId"))}/keys`,
|
|
1997
2005
|
query: {
|
|
@@ -2048,7 +2056,7 @@ function buildTools(scope, authentication) {
|
|
|
2048
2056
|
},
|
|
2049
2057
|
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
2050
2058
|
handler: async (args, ctx) => {
|
|
2051
|
-
const { result } = await callCloudflare(
|
|
2059
|
+
const { result } = await callCloudflare(send, {
|
|
2052
2060
|
method: "POST",
|
|
2053
2061
|
path: `/accounts/${encodePathSegment(accountArg(args))}/storage/kv/namespaces/${encodePathSegment(requireString(args, "namespaceId"))}/bulk/get`,
|
|
2054
2062
|
body: {
|
|
@@ -2083,12 +2091,34 @@ function buildTools(scope, authentication) {
|
|
|
2083
2091
|
items: {
|
|
2084
2092
|
type: "object",
|
|
2085
2093
|
properties: {
|
|
2086
|
-
key: {
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2094
|
+
key: {
|
|
2095
|
+
type: "string",
|
|
2096
|
+
minLength: 1,
|
|
2097
|
+
maxLength: 512,
|
|
2098
|
+
description: "Key name, up to Cloudflare's 512 bytes.",
|
|
2099
|
+
},
|
|
2100
|
+
value: {
|
|
2101
|
+
type: "string",
|
|
2102
|
+
maxLength: 26_214_400,
|
|
2103
|
+
description: "Value, up to Cloudflare's 25 MiB.",
|
|
2104
|
+
},
|
|
2105
|
+
expiration: {
|
|
2106
|
+
type: "number",
|
|
2107
|
+
description: "Absolute expiry as a Unix timestamp in seconds.",
|
|
2108
|
+
},
|
|
2109
|
+
expiration_ttl: {
|
|
2110
|
+
type: "number",
|
|
2111
|
+
minimum: 60,
|
|
2112
|
+
description: "Relative expiry in seconds; Cloudflare's floor is 60.",
|
|
2113
|
+
},
|
|
2114
|
+
metadata: {
|
|
2115
|
+
type: ["object", "array", "string", "number", "boolean", "null"],
|
|
2116
|
+
description: "JSON metadata returned beside the key by list_kv_keys.",
|
|
2117
|
+
},
|
|
2118
|
+
base64: {
|
|
2119
|
+
type: "boolean",
|
|
2120
|
+
description: "Treat value as base64 and store the decoded bytes.",
|
|
2121
|
+
},
|
|
2092
2122
|
},
|
|
2093
2123
|
required: ["key", "value"],
|
|
2094
2124
|
additionalProperties: false,
|
|
@@ -2104,7 +2134,7 @@ function buildTools(scope, authentication) {
|
|
|
2104
2134
|
},
|
|
2105
2135
|
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
2106
2136
|
handler: async (args, ctx) => {
|
|
2107
|
-
const { result } = await callCloudflare(
|
|
2137
|
+
const { result } = await callCloudflare(send, {
|
|
2108
2138
|
method: "PUT",
|
|
2109
2139
|
path: `/accounts/${encodePathSegment(accountArg(args))}/storage/kv/namespaces/${encodePathSegment(requireString(args, "namespaceId"))}/bulk`,
|
|
2110
2140
|
body: args["entries"],
|
|
@@ -2142,7 +2172,7 @@ function buildTools(scope, authentication) {
|
|
|
2142
2172
|
},
|
|
2143
2173
|
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
2144
2174
|
handler: async (args, ctx) => {
|
|
2145
|
-
const { result } = await callCloudflare(
|
|
2175
|
+
const { result } = await callCloudflare(send, {
|
|
2146
2176
|
method: "POST",
|
|
2147
2177
|
path: `/accounts/${encodePathSegment(accountArg(args))}/storage/kv/namespaces/${encodePathSegment(requireString(args, "namespaceId"))}/bulk/delete`,
|
|
2148
2178
|
body: args["keys"],
|
|
@@ -2168,10 +2198,7 @@ function buildTools(scope, authentication) {
|
|
|
2168
2198
|
maximum: 1000,
|
|
2169
2199
|
description: "Buckets per request, 1 to 1000. Defaults to 20.",
|
|
2170
2200
|
},
|
|
2171
|
-
cursor:
|
|
2172
|
-
type: "string",
|
|
2173
|
-
description: "Opaque cursor from a previous call's nextCursor. R2 paginates by cursor, not page number.",
|
|
2174
|
-
},
|
|
2201
|
+
cursor: CURSOR_INPUT_PROPERTY,
|
|
2175
2202
|
jurisdiction: R2_JURISDICTION_PROPERTY,
|
|
2176
2203
|
raw: RAW_INPUT_PROPERTY,
|
|
2177
2204
|
},
|
|
@@ -2195,15 +2222,12 @@ function buildTools(scope, authentication) {
|
|
|
2195
2222
|
required: ["name"],
|
|
2196
2223
|
},
|
|
2197
2224
|
},
|
|
2198
|
-
nextCursor:
|
|
2199
|
-
type: "string",
|
|
2200
|
-
description: "Pass back as `cursor` to continue. Absent when the listing is complete.",
|
|
2201
|
-
},
|
|
2225
|
+
nextCursor: NEXT_CURSOR_OUTPUT_PROPERTY,
|
|
2202
2226
|
},
|
|
2203
2227
|
required: ["buckets"],
|
|
2204
2228
|
},
|
|
2205
2229
|
handler: async (args, ctx) => {
|
|
2206
|
-
const { result, resultInfo } = await callCloudflare(
|
|
2230
|
+
const { result, resultInfo } = await callCloudflare(send, {
|
|
2207
2231
|
method: "GET",
|
|
2208
2232
|
path: `/accounts/${encodeURIComponent(accountArg(args))}/r2/buckets`,
|
|
2209
2233
|
query: {
|
|
@@ -2243,7 +2267,7 @@ function buildTools(scope, authentication) {
|
|
|
2243
2267
|
},
|
|
2244
2268
|
outputSchema: R2_BUCKET_SCHEMA,
|
|
2245
2269
|
handler: async (args, ctx) => {
|
|
2246
|
-
const { result } = await callCloudflare(
|
|
2270
|
+
const { result } = await callCloudflare(send, {
|
|
2247
2271
|
method: "GET",
|
|
2248
2272
|
path: `/accounts/${encodePathSegment(accountArg(args))}/r2/buckets/${encodePathSegment(requireString(args, "bucketName"))}`,
|
|
2249
2273
|
headers: r2Headers(args),
|
|
@@ -2277,7 +2301,7 @@ function buildTools(scope, authentication) {
|
|
|
2277
2301
|
},
|
|
2278
2302
|
outputSchema: R2_BUCKET_SCHEMA,
|
|
2279
2303
|
handler: async (args, ctx) => {
|
|
2280
|
-
const { result } = await callCloudflare(
|
|
2304
|
+
const { result } = await callCloudflare(send, {
|
|
2281
2305
|
method: "POST",
|
|
2282
2306
|
path: `/accounts/${encodePathSegment(accountArg(args))}/r2/buckets`,
|
|
2283
2307
|
headers: r2Headers(args),
|
|
@@ -2319,7 +2343,7 @@ function buildTools(scope, authentication) {
|
|
|
2319
2343
|
},
|
|
2320
2344
|
outputSchema: R2_BUCKET_SCHEMA,
|
|
2321
2345
|
handler: async (args, ctx) => {
|
|
2322
|
-
const { result } = await callCloudflare(
|
|
2346
|
+
const { result } = await callCloudflare(send, {
|
|
2323
2347
|
method: "PATCH",
|
|
2324
2348
|
path: `/accounts/${encodePathSegment(accountArg(args))}/r2/buckets/${encodePathSegment(requireString(args, "bucketName"))}`,
|
|
2325
2349
|
headers: {
|
|
@@ -2354,7 +2378,7 @@ function buildTools(scope, authentication) {
|
|
|
2354
2378
|
},
|
|
2355
2379
|
handler: async (args, ctx) => {
|
|
2356
2380
|
const bucketName = requireString(args, "bucketName");
|
|
2357
|
-
await callCloudflare(
|
|
2381
|
+
await callCloudflare(send, {
|
|
2358
2382
|
method: "DELETE",
|
|
2359
2383
|
path: `/accounts/${encodePathSegment(accountArg(args))}/r2/buckets/${encodePathSegment(bucketName)}`,
|
|
2360
2384
|
headers: r2Headers(args),
|
|
@@ -2392,10 +2416,7 @@ function buildTools(scope, authentication) {
|
|
|
2392
2416
|
maximum: 1000,
|
|
2393
2417
|
description: "Objects per request, 1 to 1000.",
|
|
2394
2418
|
},
|
|
2395
|
-
cursor:
|
|
2396
|
-
type: "string",
|
|
2397
|
-
description: "Opaque cursor returned as nextCursor by the previous call.",
|
|
2398
|
-
},
|
|
2419
|
+
cursor: CURSOR_INPUT_PROPERTY,
|
|
2399
2420
|
},
|
|
2400
2421
|
required: [...scopeRequired("accountId", scope.accountId), "bucketName"],
|
|
2401
2422
|
additionalProperties: false,
|
|
@@ -2405,13 +2426,13 @@ function buildTools(scope, authentication) {
|
|
|
2405
2426
|
properties: {
|
|
2406
2427
|
objects: { type: "array", items: R2_OBJECT_SCHEMA },
|
|
2407
2428
|
commonPrefixes: { type: "array", items: { type: "string" } },
|
|
2408
|
-
nextCursor:
|
|
2429
|
+
nextCursor: NEXT_CURSOR_OUTPUT_PROPERTY,
|
|
2409
2430
|
truncated: { type: "boolean" },
|
|
2410
2431
|
},
|
|
2411
2432
|
required: ["objects", "truncated"],
|
|
2412
2433
|
},
|
|
2413
2434
|
handler: async (args, ctx) => {
|
|
2414
|
-
const { result, resultInfo } = await callCloudflare(
|
|
2435
|
+
const { result, resultInfo } = await callCloudflare(send, {
|
|
2415
2436
|
method: "GET",
|
|
2416
2437
|
path: `/accounts/${encodePathSegment(accountArg(args))}/r2/buckets/${encodePathSegment(requireString(args, "bucketName"))}/objects`,
|
|
2417
2438
|
headers: r2Headers(args),
|
|
@@ -2469,7 +2490,7 @@ function buildTools(scope, authentication) {
|
|
|
2469
2490
|
},
|
|
2470
2491
|
handler: async (args, ctx) => {
|
|
2471
2492
|
const objectKey = requireString(args, "objectKey");
|
|
2472
|
-
await callCloudflare(
|
|
2493
|
+
await callCloudflare(send, {
|
|
2473
2494
|
method: "DELETE",
|
|
2474
2495
|
path: `/accounts/${encodePathSegment(accountArg(args))}/r2/buckets/${encodePathSegment(requireString(args, "bucketName"))}/objects/${encodeObjectKey(objectKey)}`,
|
|
2475
2496
|
headers: r2Headers(args),
|
|
@@ -2477,25 +2498,17 @@ function buildTools(scope, authentication) {
|
|
|
2477
2498
|
return { deleted: true, objectKey };
|
|
2478
2499
|
},
|
|
2479
2500
|
},
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
handler: async (args, ctx) => {
|
|
2492
|
-
const { result } = await callCloudflare(base, {
|
|
2493
|
-
method: "GET",
|
|
2494
|
-
path: `/accounts/${encodePathSegment(accountArg(args))}/r2/metrics`,
|
|
2495
|
-
}, ctx);
|
|
2496
|
-
return asRecord(result);
|
|
2497
|
-
},
|
|
2498
|
-
},
|
|
2501
|
+
// No `get_r2_metrics`, `set_r2_cors`, or `delete_r2_cors` here on purpose.
|
|
2502
|
+
// The #350 measurement found `get_r2_metrics` an unprojected,
|
|
2503
|
+
// output-schema-less wrapper around a path, and `set_r2_cors` carrying a
|
|
2504
|
+
// free-form `additionalProperties: true` rule body, so its schema did not
|
|
2505
|
+
// validate the part of the call that actually fails. `delete_r2_cors`
|
|
2506
|
+
// measured clean — a fixed `{deleted}` confirmation behind a closed output
|
|
2507
|
+
// schema — and went anyway, as the other half of one policy pair: with the
|
|
2508
|
+
// write unnamed, a named delete would change a CORS policy through a
|
|
2509
|
+
// different route than setting it does. Reading a policy is still named;
|
|
2510
|
+
// changing one takes the approval-gated raw route, exactly as
|
|
2511
|
+
// structured-data DNS records already do.
|
|
2499
2512
|
{
|
|
2500
2513
|
name: "get_r2_cors",
|
|
2501
2514
|
description: "Get the browser CORS rules configured on an R2 bucket.",
|
|
@@ -2512,7 +2525,7 @@ function buildTools(scope, authentication) {
|
|
|
2512
2525
|
},
|
|
2513
2526
|
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
2514
2527
|
handler: async (args, ctx) => {
|
|
2515
|
-
const { result } = await callCloudflare(
|
|
2528
|
+
const { result } = await callCloudflare(send, {
|
|
2516
2529
|
method: "GET",
|
|
2517
2530
|
path: `/accounts/${encodePathSegment(accountArg(args))}/r2/buckets/${encodePathSegment(requireString(args, "bucketName"))}/cors`,
|
|
2518
2531
|
headers: r2Headers(args),
|
|
@@ -2520,65 +2533,6 @@ function buildTools(scope, authentication) {
|
|
|
2520
2533
|
return asRecord(result);
|
|
2521
2534
|
},
|
|
2522
2535
|
},
|
|
2523
|
-
{
|
|
2524
|
-
name: "set_r2_cors",
|
|
2525
|
-
description: "Replace an R2 bucket's CORS policy. Supply the complete desired rule list; omitted existing rules are removed.",
|
|
2526
|
-
annotations: { readOnlyHint: false, destructiveHint: true },
|
|
2527
|
-
inputSchema: {
|
|
2528
|
-
type: "object",
|
|
2529
|
-
properties: {
|
|
2530
|
-
accountId: scopeProperty("accountId", scope.accountId),
|
|
2531
|
-
bucketName: R2_BUCKET_NAME_PROPERTY,
|
|
2532
|
-
jurisdiction: R2_JURISDICTION_PROPERTY,
|
|
2533
|
-
rules: {
|
|
2534
|
-
type: "array",
|
|
2535
|
-
maxItems: 100,
|
|
2536
|
-
description: "Complete CORS rule list using Cloudflare fields: allowed.methods, allowed.origins, optional allowed.headers, id, exposeHeaders, and maxAgeSeconds.",
|
|
2537
|
-
items: { type: "object", additionalProperties: true },
|
|
2538
|
-
},
|
|
2539
|
-
},
|
|
2540
|
-
required: [...scopeRequired("accountId", scope.accountId), "bucketName", "rules"],
|
|
2541
|
-
additionalProperties: false,
|
|
2542
|
-
},
|
|
2543
|
-
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
2544
|
-
handler: async (args, ctx) => {
|
|
2545
|
-
const { result } = await callCloudflare(base, {
|
|
2546
|
-
method: "PUT",
|
|
2547
|
-
path: `/accounts/${encodePathSegment(accountArg(args))}/r2/buckets/${encodePathSegment(requireString(args, "bucketName"))}/cors`,
|
|
2548
|
-
headers: r2Headers(args),
|
|
2549
|
-
body: { rules: args["rules"] },
|
|
2550
|
-
}, ctx);
|
|
2551
|
-
return asRecord(result);
|
|
2552
|
-
},
|
|
2553
|
-
},
|
|
2554
|
-
{
|
|
2555
|
-
name: "delete_r2_cors",
|
|
2556
|
-
description: "Remove the complete CORS policy from an R2 bucket.",
|
|
2557
|
-
annotations: { readOnlyHint: false, destructiveHint: true },
|
|
2558
|
-
inputSchema: {
|
|
2559
|
-
type: "object",
|
|
2560
|
-
properties: {
|
|
2561
|
-
accountId: scopeProperty("accountId", scope.accountId),
|
|
2562
|
-
bucketName: R2_BUCKET_NAME_PROPERTY,
|
|
2563
|
-
jurisdiction: R2_JURISDICTION_PROPERTY,
|
|
2564
|
-
},
|
|
2565
|
-
required: [...scopeRequired("accountId", scope.accountId), "bucketName"],
|
|
2566
|
-
additionalProperties: false,
|
|
2567
|
-
},
|
|
2568
|
-
outputSchema: {
|
|
2569
|
-
type: "object",
|
|
2570
|
-
properties: { deleted: { type: "boolean" } },
|
|
2571
|
-
required: ["deleted"],
|
|
2572
|
-
},
|
|
2573
|
-
handler: async (args, ctx) => {
|
|
2574
|
-
await callCloudflare(base, {
|
|
2575
|
-
method: "DELETE",
|
|
2576
|
-
path: `/accounts/${encodePathSegment(accountArg(args))}/r2/buckets/${encodePathSegment(requireString(args, "bucketName"))}/cors`,
|
|
2577
|
-
headers: r2Headers(args),
|
|
2578
|
-
}, ctx);
|
|
2579
|
-
return { deleted: true };
|
|
2580
|
-
},
|
|
2581
|
-
},
|
|
2582
2536
|
{
|
|
2583
2537
|
name: "list_pages_projects",
|
|
2584
2538
|
description: "List Cloudflare Pages projects in an account, with their production branch and latest deployment.",
|
|
@@ -2614,7 +2568,7 @@ function buildTools(scope, authentication) {
|
|
|
2614
2568
|
required: ["name"],
|
|
2615
2569
|
}),
|
|
2616
2570
|
handler: async (args, ctx) => {
|
|
2617
|
-
const { result, resultInfo } = await callCloudflare(
|
|
2571
|
+
const { result, resultInfo } = await callCloudflare(send, {
|
|
2618
2572
|
method: "GET",
|
|
2619
2573
|
path: `/accounts/${encodeURIComponent(accountArg(args))}/pages/projects`,
|
|
2620
2574
|
query: {
|
|
@@ -2650,7 +2604,7 @@ function buildTools(scope, authentication) {
|
|
|
2650
2604
|
},
|
|
2651
2605
|
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
2652
2606
|
handler: async (args, ctx) => {
|
|
2653
|
-
const { result } = await callCloudflare(
|
|
2607
|
+
const { result } = await callCloudflare(send, {
|
|
2654
2608
|
method: "GET",
|
|
2655
2609
|
path: `/accounts/${encodePathSegment(accountArg(args))}/pages/projects/${encodePathSegment(requireString(args, "projectName"))}`,
|
|
2656
2610
|
}, ctx);
|
|
@@ -2682,7 +2636,7 @@ function buildTools(scope, authentication) {
|
|
|
2682
2636
|
},
|
|
2683
2637
|
outputSchema: listOutputSchema("deployments", OPEN_OBJECT_OUTPUT_SCHEMA),
|
|
2684
2638
|
handler: async (args, ctx) => {
|
|
2685
|
-
const { result, resultInfo } = await callCloudflare(
|
|
2639
|
+
const { result, resultInfo } = await callCloudflare(send, {
|
|
2686
2640
|
method: "GET",
|
|
2687
2641
|
path: `/accounts/${encodePathSegment(accountArg(args))}/pages/projects/${encodePathSegment(requireString(args, "projectName"))}/deployments`,
|
|
2688
2642
|
query: {
|
|
@@ -2726,7 +2680,7 @@ function buildTools(scope, authentication) {
|
|
|
2726
2680
|
},
|
|
2727
2681
|
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
2728
2682
|
handler: async (args, ctx) => {
|
|
2729
|
-
const { result } = await callCloudflare(
|
|
2683
|
+
const { result } = await callCloudflare(send, {
|
|
2730
2684
|
method: "GET",
|
|
2731
2685
|
path: `/accounts/${encodePathSegment(accountArg(args))}/pages/projects/${encodePathSegment(requireString(args, "projectName"))}/deployments/${encodePathSegment(requireString(args, "deploymentId"))}`,
|
|
2732
2686
|
}, ctx);
|
|
@@ -2749,7 +2703,7 @@ function buildTools(scope, authentication) {
|
|
|
2749
2703
|
},
|
|
2750
2704
|
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
2751
2705
|
handler: async (args, ctx) => {
|
|
2752
|
-
const { result } = await callCloudflare(
|
|
2706
|
+
const { result } = await callCloudflare(send, {
|
|
2753
2707
|
method: "POST",
|
|
2754
2708
|
path: `/accounts/${encodePathSegment(accountArg(args))}/pages/projects/${encodePathSegment(requireString(args, "projectName"))}/deployments/${encodePathSegment(requireString(args, "deploymentId"))}/retry`,
|
|
2755
2709
|
}, ctx);
|
|
@@ -2772,7 +2726,7 @@ function buildTools(scope, authentication) {
|
|
|
2772
2726
|
},
|
|
2773
2727
|
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
2774
2728
|
handler: async (args, ctx) => {
|
|
2775
|
-
const { result } = await callCloudflare(
|
|
2729
|
+
const { result } = await callCloudflare(send, {
|
|
2776
2730
|
method: "POST",
|
|
2777
2731
|
path: `/accounts/${encodePathSegment(accountArg(args))}/pages/projects/${encodePathSegment(requireString(args, "projectName"))}/deployments/${encodePathSegment(requireString(args, "deploymentId"))}/rollback`,
|
|
2778
2732
|
}, ctx);
|
|
@@ -2796,7 +2750,7 @@ function buildTools(scope, authentication) {
|
|
|
2796
2750
|
outputSchema: { type: "object", properties: { deleted: { type: "boolean" }, deploymentId: { type: "string" } }, required: ["deleted", "deploymentId"] },
|
|
2797
2751
|
handler: async (args, ctx) => {
|
|
2798
2752
|
const deploymentId = requireString(args, "deploymentId");
|
|
2799
|
-
await callCloudflare(
|
|
2753
|
+
await callCloudflare(send, {
|
|
2800
2754
|
method: "DELETE",
|
|
2801
2755
|
path: `/accounts/${encodePathSegment(accountArg(args))}/pages/projects/${encodePathSegment(requireString(args, "projectName"))}/deployments/${encodePathSegment(deploymentId)}`,
|
|
2802
2756
|
}, ctx);
|
|
@@ -2818,7 +2772,7 @@ function buildTools(scope, authentication) {
|
|
|
2818
2772
|
},
|
|
2819
2773
|
outputSchema: listOutputSchema("domains", OPEN_OBJECT_OUTPUT_SCHEMA),
|
|
2820
2774
|
handler: async (args, ctx) => {
|
|
2821
|
-
const { result } = await callCloudflare(
|
|
2775
|
+
const { result } = await callCloudflare(send, {
|
|
2822
2776
|
method: "GET",
|
|
2823
2777
|
path: `/accounts/${encodePathSegment(accountArg(args))}/pages/projects/${encodePathSegment(requireString(args, "projectName"))}/domains`,
|
|
2824
2778
|
}, ctx);
|
|
@@ -2841,7 +2795,7 @@ function buildTools(scope, authentication) {
|
|
|
2841
2795
|
},
|
|
2842
2796
|
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
2843
2797
|
handler: async (args, ctx) => {
|
|
2844
|
-
const { result } = await callCloudflare(
|
|
2798
|
+
const { result } = await callCloudflare(send, {
|
|
2845
2799
|
method: "POST",
|
|
2846
2800
|
path: `/accounts/${encodePathSegment(accountArg(args))}/pages/projects/${encodePathSegment(requireString(args, "projectName"))}/domains`,
|
|
2847
2801
|
body: { name: requireString(args, "domain") },
|
|
@@ -2866,7 +2820,7 @@ function buildTools(scope, authentication) {
|
|
|
2866
2820
|
outputSchema: { type: "object", properties: { deleted: { type: "boolean" }, domain: { type: "string" } }, required: ["deleted", "domain"] },
|
|
2867
2821
|
handler: async (args, ctx) => {
|
|
2868
2822
|
const domain = requireString(args, "domain");
|
|
2869
|
-
await callCloudflare(
|
|
2823
|
+
await callCloudflare(send, {
|
|
2870
2824
|
method: "DELETE",
|
|
2871
2825
|
path: `/accounts/${encodePathSegment(accountArg(args))}/pages/projects/${encodePathSegment(requireString(args, "projectName"))}/domains/${encodePathSegment(domain)}`,
|
|
2872
2826
|
}, ctx);
|
|
@@ -2888,7 +2842,7 @@ function buildTools(scope, authentication) {
|
|
|
2888
2842
|
},
|
|
2889
2843
|
outputSchema: { type: "object", properties: { purged: { type: "boolean" } }, required: ["purged"] },
|
|
2890
2844
|
handler: async (args, ctx) => {
|
|
2891
|
-
await callCloudflare(
|
|
2845
|
+
await callCloudflare(send, {
|
|
2892
2846
|
method: "POST",
|
|
2893
2847
|
path: `/accounts/${encodePathSegment(accountArg(args))}/pages/projects/${encodePathSegment(requireString(args, "projectName"))}/purge_build_cache`,
|
|
2894
2848
|
}, ctx);
|
|
@@ -2911,7 +2865,7 @@ function buildTools(scope, authentication) {
|
|
|
2911
2865
|
outputSchema: { type: "object", properties: { deleted: { type: "boolean" }, projectName: { type: "string" } }, required: ["deleted", "projectName"] },
|
|
2912
2866
|
handler: async (args, ctx) => {
|
|
2913
2867
|
const projectName = requireString(args, "projectName");
|
|
2914
|
-
await callCloudflare(
|
|
2868
|
+
await callCloudflare(send, {
|
|
2915
2869
|
method: "DELETE",
|
|
2916
2870
|
path: `/accounts/${encodePathSegment(accountArg(args))}/pages/projects/${encodePathSegment(projectName)}`,
|
|
2917
2871
|
}, ctx);
|
|
@@ -2923,7 +2877,7 @@ function buildTools(scope, authentication) {
|
|
|
2923
2877
|
// `destructiveHint` stays unset. `readOnlyHint: false` already routes it
|
|
2924
2878
|
// through call_destructive_tool.
|
|
2925
2879
|
name: "create_dns_record",
|
|
2926
|
-
description: "Create a content-based DNS record
|
|
2880
|
+
description: "Create a content-based DNS record in a zone; the type enum lists the creatable types. Check list_dns_records first — Cloudflare rejects a duplicate rather than replacing it. Structured types like SRV and CAA are readable but not creatable.",
|
|
2927
2881
|
annotations: { readOnlyHint: false },
|
|
2928
2882
|
inputSchema: {
|
|
2929
2883
|
type: "object",
|
|
@@ -2978,7 +2932,7 @@ function buildTools(scope, authentication) {
|
|
|
2978
2932
|
},
|
|
2979
2933
|
outputSchema: DNS_RECORD_SCHEMA,
|
|
2980
2934
|
handler: async (args, ctx) => {
|
|
2981
|
-
const { result } = await callCloudflare(
|
|
2935
|
+
const { result } = await callCloudflare(send, {
|
|
2982
2936
|
method: "POST",
|
|
2983
2937
|
path: `/zones/${encodeURIComponent(zoneArg(args))}/dns_records`,
|
|
2984
2938
|
body: {
|
|
@@ -3079,7 +3033,7 @@ function buildTools(scope, authentication) {
|
|
|
3079
3033
|
},
|
|
3080
3034
|
});
|
|
3081
3035
|
}
|
|
3082
|
-
const { result } = await callCloudflare(
|
|
3036
|
+
const { result } = await callCloudflare(send, {
|
|
3083
3037
|
method: "PATCH",
|
|
3084
3038
|
path: `/zones/${encodeURIComponent(zoneArg(args))}/dns_records/${encodeURIComponent(String(args["recordId"]))}`,
|
|
3085
3039
|
body,
|
|
@@ -3113,7 +3067,7 @@ function buildTools(scope, authentication) {
|
|
|
3113
3067
|
},
|
|
3114
3068
|
handler: async (args, ctx) => {
|
|
3115
3069
|
const recordId = String(args["recordId"]);
|
|
3116
|
-
await callCloudflare(
|
|
3070
|
+
await callCloudflare(send, {
|
|
3117
3071
|
method: "DELETE",
|
|
3118
3072
|
path: `/zones/${encodeURIComponent(zoneArg(args))}/dns_records/${encodeURIComponent(recordId)}`,
|
|
3119
3073
|
}, ctx);
|
|
@@ -3213,7 +3167,7 @@ function buildTools(scope, authentication) {
|
|
|
3213
3167
|
});
|
|
3214
3168
|
}
|
|
3215
3169
|
const variant = everything ? "everything" : targeted[0];
|
|
3216
|
-
await callCloudflare(
|
|
3170
|
+
await callCloudflare(send, {
|
|
3217
3171
|
method: "POST",
|
|
3218
3172
|
path: `/zones/${encodeURIComponent(zoneId)}/purge_cache`,
|
|
3219
3173
|
body: everything
|
|
@@ -3246,10 +3200,11 @@ Account purpose: ${purpose}
|
|
|
3246
3200
|
|
|
3247
3201
|
- ${zoneLine}
|
|
3248
3202
|
- ${accountLine}
|
|
3249
|
-
- Prefer a named tool: its schema is complete, projected, and enough to call it without provider documentation. For an operation without a named tool, use \`cloudflare_api_get\` for GET, \`cloudflare_api_mutate\` for JSON POST/PUT/PATCH/DELETE, or \`cloudflare_api_upload\` for raw and multipart content. Raw tools take a path below \`/client/v4\`; their argument schemas are complete, but endpoint-specific query, header, and body fields come from Cloudflare's API reference. Use \`headers\` for endpoint-specific controls such as \`cf-r2-jurisdiction\`,
|
|
3203
|
+
- Prefer a named tool: its schema is complete, projected, and enough to call it without provider documentation. For an operation without a named tool, use \`cloudflare_api_get\` for GET, \`cloudflare_api_mutate\` for JSON POST/PUT/PATCH/DELETE, or \`cloudflare_api_upload\` for raw and multipart content. Raw tools take a path below \`/client/v4\`; their argument schemas are complete, but endpoint-specific query, header, and body fields come from Cloudflare's API reference. Use \`headers\` for endpoint-specific controls such as \`cf-r2-jurisdiction\`, \`Range\`, \`If-None-Match\`, and Cloudflare product metadata. \`Authorization\`, \`Cookie\`, \`Host\`, \`Content-Length\`, \`Content-Type\`, and \`Transfer-Encoding\` are connector-owned and refused: authentication, host, content type, and request framing are not the caller's to set.
|
|
3250
3204
|
- The raw tools cover the wider control plane without weakening routing: GET is explicitly read-only; every mutation and upload is destructive and must cross the host's approval boundary. The configured Cloudflare credential remains the hard provider-side permission boundary. Absolute URLs, traversal, and query strings embedded in \`path\` are refused locally.
|
|
3251
3205
|
- Useful raw paths include \`/accounts/{accountId}/images/v1\` (Images), \`/accounts/{accountId}/stream\` (Stream), \`/zones/{zoneId}/email/routing/rules\` (Email Routing), \`/accounts/{accountId}/d1/database\` (D1), and \`/accounts/{accountId}/queues\` (Queues). On GET, use \`responseType: "text"\` or \`"base64"\` for non-JSON content. Direct-upload endpoints can issue upload URLs; \`cloudflare_api_upload\` can also send explicit text, base64 bytes, or multipart fields/files.
|
|
3252
|
-
-
|
|
3206
|
+
- Three areas are deliberately unnamed. Read a bucket's CORS policy with \`get_r2_cors\`, then change it with \`cloudflare_api_mutate\` — \`PUT\` or \`DELETE /accounts/{accountId}/r2/buckets/{bucketName}/cors\`, rule fields per Cloudflare's reference — and read account storage totals with \`cloudflare_api_get\` at \`/accounts/{accountId}/r2/metrics\`. Zone settings are read one at a time with \`get_zone_setting\`: Cloudflare deprecated the bulk \`/zones/{zoneId}/settings\` read and published no replacement for it, so reach for the whole set through \`cloudflare_api_get\` only when one setting genuinely will not do.
|
|
3207
|
+
- Lists paginate with \`page\` and \`perPage\` and return a \`page\` object; request the next page only when \`page.hasMore\` is true. \`list_zone_rulesets\`, \`list_r2_buckets\`, \`list_r2_objects\`, and \`list_kv_keys\` page by cursor instead: pass \`cursor\`, continue while \`nextCursor\` is present, and expect no \`page\` object. Their schemas say so too. \`list_worker_scripts\` is unpaginated.
|
|
3253
3208
|
- Results are projected to the fields that identify and describe a resource. Pass \`raw: true\` on a read when you genuinely need a field the projection drops.
|
|
3254
3209
|
- ${authenticationLine}
|
|
3255
3210
|
- A \`rate_limited\` failure carries the wait window. Cloudflare's limit is 1,200 requests per five minutes per user, counted across the dashboard and every token, so do not fan out speculatively; filter server-side with \`name\`, \`type\`, and \`content\` instead of listing everything and filtering locally.
|
|
@@ -3273,7 +3228,7 @@ export function cloudflare(id, options) {
|
|
|
3273
3228
|
throw new Error('cloudflare() authentication must be "apiToken" or "globalApiKey".');
|
|
3274
3229
|
}
|
|
3275
3230
|
const scope = {
|
|
3276
|
-
|
|
3231
|
+
send: cloudflareTransport(options.baseUrl?.trim() || CLOUDFLARE_API_BASE),
|
|
3277
3232
|
accountId: options.accountId?.trim() || undefined,
|
|
3278
3233
|
zoneId: options.zoneId?.trim() || undefined,
|
|
3279
3234
|
};
|
|
@@ -3282,10 +3237,18 @@ export function cloudflare(id, options) {
|
|
|
3282
3237
|
description: `Cloudflare control-plane access for zones, DNS, Workers, KV, R2, Pages, media, email, and other v4 APIs — ${purpose}`,
|
|
3283
3238
|
credential: credentialConfig(authentication, options.credential),
|
|
3284
3239
|
callAdmission: admissionPolicy(maxConcurrency),
|
|
3285
|
-
usageGuide:
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3240
|
+
usageGuide: {
|
|
3241
|
+
content: usageGuide(purpose, scope, options.instructions, authentication),
|
|
3242
|
+
// Explicit rather than derived: the first content line is the zone
|
|
3243
|
+
// scoping rule, which varies per deployment and reads as an instruction
|
|
3244
|
+
// rather than as the routing fact a browsing agent needs.
|
|
3245
|
+
summary: "Zone and account scoping, named-vs-raw routing, two pagination shapes, and lean-vs-raw results.",
|
|
3246
|
+
// Deliberately not `required`. Every named tool's schema is complete
|
|
3247
|
+
// enough to call it correctly on its own, and the scoping convention the
|
|
3248
|
+
// guide carries is repeated on each `zoneId` and `accountId` property —
|
|
3249
|
+
// so forcing the guide into context before every operation would spend
|
|
3250
|
+
// tokens on a sequence the schemas already express.
|
|
3251
|
+
},
|
|
3289
3252
|
...(options.maxResultBytes !== undefined
|
|
3290
3253
|
? { maxResultBytes: options.maxResultBytes }
|
|
3291
3254
|
: {}),
|
|
@@ -3294,7 +3257,7 @@ export function cloudflare(id, options) {
|
|
|
3294
3257
|
? {
|
|
3295
3258
|
async testCredential(value, ctx) {
|
|
3296
3259
|
try {
|
|
3297
|
-
const { result } = await callCloudflare(scope.
|
|
3260
|
+
const { result } = await callCloudflare(scope.send, { method: "GET", path: "/user/tokens/verify" }, withAuthentication({
|
|
3298
3261
|
...ctx,
|
|
3299
3262
|
credential: {
|
|
3300
3263
|
get: async () => value,
|
|
@@ -3317,7 +3280,7 @@ export function cloudflare(id, options) {
|
|
|
3317
3280
|
: {
|
|
3318
3281
|
async testCredentials(values, ctx) {
|
|
3319
3282
|
try {
|
|
3320
|
-
const { result } = await callCloudflare(scope.
|
|
3283
|
+
const { result } = await callCloudflare(scope.send, { method: "GET", path: "/user" }, withAuthentication({
|
|
3321
3284
|
...ctx,
|
|
3322
3285
|
credential: {
|
|
3323
3286
|
get: async (field) => field ? values[field] ?? null : null,
|
|
@@ -3340,4 +3303,3 @@ export function cloudflare(id, options) {
|
|
|
3340
3303
|
}),
|
|
3341
3304
|
});
|
|
3342
3305
|
}
|
|
3343
|
-
//# sourceMappingURL=cloudflare.js.map
|