@zackbart/connecta 0.21.0 → 0.21.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/CHANGELOG.md CHANGED
@@ -2,6 +2,50 @@
2
2
 
3
3
  All notable changes to this package are documented here.
4
4
 
5
+ ## 0.21.1 — 2026-08-30
6
+
7
+ This patch aligns the handwritten Cloudflare and Notion contracts and the four
8
+ hosted-provider manifests with their current catalogs. Existing deployments
9
+ need no configuration or storage migration. Cloudflare programs that depend on
10
+ provider fields outside the maintained `get_zone_setting` or
11
+ `get_worker_settings` projections should pass `raw: true`. Stripe's server has
12
+ retired three dedicated tool names, so programs that hardcoded them must search
13
+ the current catalog and use the generic API tools or `stripe_analytics`.
14
+
15
+ ### Added
16
+
17
+ - **Current Cloudflare jurisdictions.** All eight R2 bucket tools accept the
18
+ `us` jurisdiction alongside `default`, `eu`, and `fedramp`. KV namespace
19
+ creation accepts its separate `eu`, `fedramp`, and `us` set and preserves
20
+ jurisdiction on namespace reads (#498, #499).
21
+ - **Current hosted-provider classifications.** Linear's workspace, template,
22
+ and issue-sharing tools join its plan-aware reviewed superset. RevenueCat's
23
+ refund-request preferences are read-only, and Mixpanel's metadata fill is a
24
+ destructive Lexicon update (#512).
25
+
26
+ ### Changed
27
+
28
+ - **Useful Cloudflare result schemas.** All 48 named tools now declare their
29
+ maintained output keys. Zone settings and Worker settings project stable
30
+ camel-case fields by default and expose the provider response through
31
+ `raw: true`; rulesets, deployments, KV bulk operations, R2 CORS, and Pages
32
+ reuse named schemas instead of an empty object contract (#488).
33
+ - **Stripe's current eleven tools.** Account listing, account-management links,
34
+ and analytics replace the retired account-info, refund, and report tools.
35
+ The integration planner and analytics are additive writes because their tool
36
+ boundaries can create provider-side guide or query-run state (#512).
37
+
38
+ ### Fixed
39
+
40
+ - Worker settings retain VPC binding identity and observability fields,
41
+ rulesets retain origin-range metadata, and zone setting ids include
42
+ Cloudflare's current WebMCP settings (#500, #501, #502, #503).
43
+ - Notion preserves every documented `verification.does_not_equal` value, and
44
+ Cloudflare's recorded KV bulk and zone-setting specifications match the
45
+ current published documents (#504, #509).
46
+ - Mixpanel records the current schemas for all 64 classified tools, including
47
+ the three experiment contracts that changed since the prior review (#512).
48
+
5
49
  ## 0.21.0 — 2026-08-28
6
50
 
7
51
  Cloudflare Access becomes the canonical interactive-auth path for Worker
@@ -375,6 +375,15 @@ function projectZone(value) {
375
375
  modifiedOn: zone["modified_on"],
376
376
  });
377
377
  }
378
+ function projectZoneSetting(value) {
379
+ const setting = asRecord(value);
380
+ return compact({
381
+ id: setting["id"],
382
+ value: setting["value"],
383
+ editable: setting["editable"],
384
+ modifiedOn: setting["modified_on"],
385
+ });
386
+ }
378
387
  function projectDnsRecord(value) {
379
388
  const record = asRecord(value);
380
389
  const comment = record["comment"] ? record["comment"] : undefined;
@@ -404,12 +413,38 @@ function projectWorkerScript(value) {
404
413
  usageModel: script["usage_model"],
405
414
  });
406
415
  }
416
+ function projectWorkerSettings(value) {
417
+ const settings = asRecord(value);
418
+ return compact({
419
+ compatibilityDate: settings["compatibility_date"],
420
+ compatibilityFlags: settings["compatibility_flags"],
421
+ bindings: settings["bindings"],
422
+ limits: settings["limits"],
423
+ observability: settings["observability"],
424
+ placement: settings["placement"],
425
+ usageModel: settings["usage_model"],
426
+ tailConsumers: settings["tail_consumers"],
427
+ logpush: settings["logpush"],
428
+ });
429
+ }
407
430
  function projectKvNamespace(value) {
408
431
  const namespace = asRecord(value);
409
432
  return compact({
410
433
  id: namespace["id"],
411
434
  title: namespace["title"],
412
435
  supportsUrlEncoding: namespace["supports_url_encoding"],
436
+ jurisdiction: namespace["jurisdiction"],
437
+ });
438
+ }
439
+ function projectKvBulkValues(value) {
440
+ const result = asRecord(value);
441
+ return compact({ values: result["values"] });
442
+ }
443
+ function projectKvBulkResult(value) {
444
+ const result = asRecord(value);
445
+ return compact({
446
+ successfulKeyCount: result["successful_key_count"],
447
+ unsuccessfulKeys: result["unsuccessful_keys"],
413
448
  });
414
449
  }
415
450
  function projectR2Bucket(value) {
@@ -434,6 +469,10 @@ function projectR2Object(value) {
434
469
  customMetadata: object["custom_metadata"],
435
470
  });
436
471
  }
472
+ function projectR2Cors(value) {
473
+ const cors = asRecord(value);
474
+ return compact({ rules: cors["rules"] });
475
+ }
437
476
  function projectKvKey(value) {
438
477
  const key = asRecord(value);
439
478
  return compact({
@@ -825,10 +864,137 @@ function uploadBody(args) {
825
864
  },
826
865
  };
827
866
  }
828
- const OPEN_OBJECT_OUTPUT_SCHEMA = {
867
+ const ZONE_SETTING_SCHEMA = {
868
+ type: "object",
869
+ properties: {
870
+ id: { type: "string" },
871
+ value: {
872
+ type: ["string", "number", "boolean", "array", "object", "null"],
873
+ items: {},
874
+ additionalProperties: true,
875
+ },
876
+ editable: { type: "boolean" },
877
+ modifiedOn: { type: "string" },
878
+ },
879
+ required: ["id", "value"],
880
+ };
881
+ const RULESET_SCHEMA = {
882
+ type: "object",
883
+ properties: {
884
+ id: { type: "string" },
885
+ name: { type: "string" },
886
+ kind: { type: "string" },
887
+ phase: { type: "string" },
888
+ description: { type: "string" },
889
+ version: { type: "string" },
890
+ lastUpdated: { type: "string" },
891
+ rules: {
892
+ type: "array",
893
+ items: { type: "object", additionalProperties: true },
894
+ },
895
+ },
896
+ required: ["id", "name"],
897
+ };
898
+ const WORKER_SETTINGS_SCHEMA = {
899
+ type: "object",
900
+ properties: {
901
+ compatibilityDate: { type: "string" },
902
+ compatibilityFlags: { type: "array", items: { type: "string" } },
903
+ bindings: { type: "array", items: { type: "object", additionalProperties: true } },
904
+ limits: { type: "object", additionalProperties: true },
905
+ observability: { type: "object", additionalProperties: true },
906
+ placement: { type: "object", additionalProperties: true },
907
+ usageModel: { type: "string" },
908
+ tailConsumers: { type: "array", items: { type: "object", additionalProperties: true } },
909
+ logpush: { type: "boolean" },
910
+ },
911
+ };
912
+ const WORKER_DEPLOYMENT_SCHEMA = {
913
+ type: "object",
914
+ properties: {
915
+ id: { type: "string" },
916
+ createdOn: { type: "string" },
917
+ source: { type: "string" },
918
+ strategy: { type: "string" },
919
+ versions: { type: "array", items: { type: "object", additionalProperties: true } },
920
+ },
921
+ required: ["id"],
922
+ };
923
+ const KV_NAMESPACE_SCHEMA = {
924
+ type: "object",
925
+ properties: {
926
+ id: { type: "string" },
927
+ title: { type: "string" },
928
+ supportsUrlEncoding: { type: "boolean" },
929
+ jurisdiction: { type: "string", enum: ["eu", "fedramp", "us"] },
930
+ renamed: { type: "boolean" },
931
+ namespaceId: { type: "string" },
932
+ },
933
+ };
934
+ const KV_BULK_VALUES_SCHEMA = {
935
+ type: "object",
936
+ properties: {
937
+ values: {
938
+ type: "object",
939
+ additionalProperties: true,
940
+ },
941
+ },
942
+ required: ["values"],
943
+ };
944
+ const KV_BULK_RESULT_SCHEMA = {
945
+ type: "object",
946
+ properties: {
947
+ successfulKeyCount: { type: "number" },
948
+ unsuccessfulKeys: { type: "array", items: { type: "string" } },
949
+ },
950
+ };
951
+ const R2_CORS_SCHEMA = {
952
+ type: "object",
953
+ properties: {
954
+ rules: {
955
+ type: "array",
956
+ items: { type: "object", additionalProperties: true },
957
+ },
958
+ },
959
+ required: ["rules"],
960
+ };
961
+ const PAGES_DEPLOYMENT_SCHEMA = {
962
+ type: "object",
963
+ properties: {
964
+ id: { type: "string" },
965
+ projectName: { type: "string" },
966
+ environment: { type: "string" },
967
+ url: { type: "string" },
968
+ aliases: { type: "array", items: { type: "string" } },
969
+ stage: { type: "object", additionalProperties: true },
970
+ latestStage: { type: "object", additionalProperties: true },
971
+ createdOn: { type: "string" },
972
+ modifiedOn: { type: "string" },
973
+ },
974
+ required: ["id"],
975
+ };
976
+ const PAGES_DOMAIN_SCHEMA = {
977
+ type: "object",
978
+ properties: {
979
+ id: { type: "string" },
980
+ name: { type: "string" },
981
+ status: { type: "string" },
982
+ verificationData: { type: "object", additionalProperties: true },
983
+ createdOn: { type: "string" },
984
+ },
985
+ required: ["name"],
986
+ };
987
+ const PAGES_PROJECT_SCHEMA = {
829
988
  type: "object",
830
- description: "Cloudflare's result object. Its fields depend on the endpoint.",
831
- additionalProperties: true,
989
+ properties: {
990
+ name: { type: "string" },
991
+ subdomain: { type: "string" },
992
+ domains: { type: "array", items: { type: "string" } },
993
+ productionBranch: { type: "string" },
994
+ createdOn: { type: "string" },
995
+ latestDeployment: PAGES_DEPLOYMENT_SCHEMA,
996
+ },
997
+ required: ["name"],
832
998
  };
833
999
  const QUERY_INPUT_PROPERTY = {
834
1000
  type: "array",
@@ -859,8 +1025,13 @@ const HEADERS_INPUT_PROPERTY = {
859
1025
  };
860
1026
  const R2_JURISDICTION_PROPERTY = {
861
1027
  type: "string",
862
- enum: ["default", "eu", "fedramp"],
863
- description: "Bucket jurisdiction. Omit for ordinary buckets; set eu or fedramp for jurisdictional buckets.",
1028
+ enum: ["default", "eu", "us", "fedramp"],
1029
+ description: "Bucket jurisdiction. Omit for ordinary buckets; set eu, us, or fedramp for jurisdictional buckets.",
1030
+ };
1031
+ const KV_JURISDICTION_PROPERTY = {
1032
+ type: "string",
1033
+ enum: ["eu", "fedramp", "us"],
1034
+ description: "Creation-only namespace jurisdiction. Omit for an ordinary namespace; it cannot be changed by rename_kv_namespace.",
864
1035
  };
865
1036
  const R2_BUCKET_NAME_PROPERTY = {
866
1037
  type: "string",
@@ -921,7 +1092,7 @@ const DELETE_PROJECT_NAME_PROPERTY = {
921
1092
  const SETTING_ID_PROPERTY = {
922
1093
  type: "string",
923
1094
  minLength: 1,
924
- description: "Cloudflare zone setting id, such as ssl, brotli, http3, or min_tls_version.",
1095
+ description: "Cloudflare zone setting id, such as ssl, brotli, webmcp_enabled, or webmcp_packs.",
925
1096
  };
926
1097
  const RECORD_ID_PROPERTY = {
927
1098
  type: "string",
@@ -933,7 +1104,7 @@ const R2_BUCKET_SCHEMA = {
933
1104
  name: { type: "string" },
934
1105
  location: { type: "string" },
935
1106
  storageClass: { type: "string" },
936
- jurisdiction: { type: "string" },
1107
+ jurisdiction: { type: "string", enum: ["default", "eu", "us", "fedramp"] },
937
1108
  creationDate: { type: "string" },
938
1109
  },
939
1110
  required: ["name"],
@@ -1251,11 +1422,12 @@ function buildTools(scope, authentication) {
1251
1422
  }, [], ZONE_SCHEMA, getResult(send, (args) => ({ method: "GET", path: `/zones/${encodeURIComponent(zoneArg(args))}` }), (result, args) => args["raw"] === true ? result : projectZone(result))),
1252
1423
  // Removed tools: documentation/cloudflare.md#what-the-named-surface-deliberately-leaves-out.
1253
1424
  cfTool("get_zone_setting", "Get one zone setting by its Cloudflare setting id, such as ssl, always_use_https, min_tls_version, brotli, or development_mode.", readOnly, "zoneId", scope.zoneId, {
1254
- settingId: SETTING_ID_PROPERTY
1255
- }, ["settingId"], OPEN_OBJECT_OUTPUT_SCHEMA, getResult(send, (args) => ({
1425
+ settingId: SETTING_ID_PROPERTY,
1426
+ raw: RAW_INPUT_PROPERTY
1427
+ }, ["settingId"], ZONE_SETTING_SCHEMA, getResult(send, (args) => ({
1256
1428
  method: "GET",
1257
1429
  path: `/zones/${encodeURIComponent(zoneArg(args))}/settings/${encodeURIComponent(requireString(args, "settingId"))}`,
1258
- }))),
1430
+ }), (result, args) => args["raw"] === true ? result : projectZoneSetting(result))),
1259
1431
  cfTool("update_zone_setting", "Set one editable zone setting. Read it first: allowed value types and plan restrictions differ by setting.", { readOnlyHint: false, destructiveHint: true }, "zoneId", scope.zoneId, {
1260
1432
  settingId: SETTING_ID_PROPERTY,
1261
1433
  value: {
@@ -1263,13 +1435,13 @@ function buildTools(scope, authentication) {
1263
1435
  description: "New setting value in the type returned by get_zone_setting. Arrays must contain strings.",
1264
1436
  items: { type: "string" },
1265
1437
  }
1266
- }, ["settingId", "value"], OPEN_OBJECT_OUTPUT_SCHEMA, async (args, ctx) => {
1438
+ }, ["settingId", "value"], ZONE_SETTING_SCHEMA, async (args, ctx) => {
1267
1439
  const { result } = await callCloudflare(send, {
1268
1440
  method: "PATCH",
1269
1441
  path: `/zones/${encodeURIComponent(zoneArg(args))}/settings/${encodeURIComponent(requireString(args, "settingId"))}`,
1270
1442
  body: { value: args["value"] },
1271
1443
  }, ctx);
1272
- return result;
1444
+ return projectZoneSetting(result);
1273
1445
  }),
1274
1446
  cfTool("list_zone_rulesets", "List zone rulesets for WAF, redirects, transforms, cache rules, configuration rules, and other Ruleset Engine phases.", readOnly, "zoneId", scope.zoneId, {
1275
1447
  perPage: {
@@ -1282,7 +1454,7 @@ function buildTools(scope, authentication) {
1282
1454
  }, [], {
1283
1455
  type: "object",
1284
1456
  properties: {
1285
- rulesets: { type: "array", items: OPEN_OBJECT_OUTPUT_SCHEMA },
1457
+ rulesets: { type: "array", items: RULESET_SCHEMA },
1286
1458
  nextCursor: NEXT_CURSOR_OUTPUT_PROPERTY,
1287
1459
  },
1288
1460
  required: ["rulesets"],
@@ -1307,7 +1479,7 @@ function buildTools(scope, authentication) {
1307
1479
  minLength: 1,
1308
1480
  description: "Ruleset id from list_zone_rulesets.",
1309
1481
  }
1310
- }, ["rulesetId"], OPEN_OBJECT_OUTPUT_SCHEMA, getResult(send, (args) => ({
1482
+ }, ["rulesetId"], RULESET_SCHEMA, getResult(send, (args) => ({
1311
1483
  method: "GET",
1312
1484
  path: `/zones/${encodeURIComponent(zoneArg(args))}/rulesets/${encodeURIComponent(requireString(args, "rulesetId"))}`,
1313
1485
  }), projectRuleset)),
@@ -1385,14 +1557,15 @@ function buildTools(scope, authentication) {
1385
1557
  return pagedList("scripts", projectWorkerScript)(result, resultInfo, args["raw"] === true);
1386
1558
  }),
1387
1559
  cfTool("get_worker_settings", "Get a Worker's compatibility date and flags, bindings, limits, observability, placement, usage model, and other script settings.", readOnly, "accountId", scope.accountId, {
1388
- scriptName: SCRIPT_NAME_PROPERTY
1389
- }, ["scriptName"], OPEN_OBJECT_OUTPUT_SCHEMA, getResult(send, (args) => ({
1560
+ scriptName: SCRIPT_NAME_PROPERTY,
1561
+ raw: RAW_INPUT_PROPERTY
1562
+ }, ["scriptName"], WORKER_SETTINGS_SCHEMA, getResult(send, (args) => ({
1390
1563
  method: "GET",
1391
1564
  path: `/accounts/${encodeURIComponent(accountArg(args))}/workers/scripts/${encodeURIComponent(requireString(args, "scriptName"))}/settings`,
1392
- }))),
1565
+ }), (result, args) => args["raw"] === true ? result : projectWorkerSettings(result))),
1393
1566
  cfTool("list_worker_deployments", "List deployments of a Worker script, including version traffic allocations and deployment strategy.", readOnly, "accountId", scope.accountId, {
1394
1567
  scriptName: SCRIPT_NAME_PROPERTY
1395
- }, ["scriptName"], listOutputSchema("deployments", OPEN_OBJECT_OUTPUT_SCHEMA), async (args, ctx) => {
1568
+ }, ["scriptName"], listOutputSchema("deployments", WORKER_DEPLOYMENT_SCHEMA), async (args, ctx) => {
1396
1569
  const { result } = await callCloudflare(send, {
1397
1570
  method: "GET",
1398
1571
  path: `/accounts/${encodeURIComponent(accountArg(args))}/workers/scripts/${encodeURIComponent(requireString(args, "scriptName"))}/deployments`,
@@ -1406,7 +1579,7 @@ function buildTools(scope, authentication) {
1406
1579
  cfTool("get_worker_deployment", "Get one Worker deployment and its version traffic allocations.", readOnly, "accountId", scope.accountId, {
1407
1580
  scriptName: SCRIPT_NAME_PROPERTY,
1408
1581
  deploymentId: WORKER_DEPLOYMENT_ID_PROPERTY
1409
- }, ["scriptName", "deploymentId"], OPEN_OBJECT_OUTPUT_SCHEMA, getResult(send, (args) => ({
1582
+ }, ["scriptName", "deploymentId"], WORKER_DEPLOYMENT_SCHEMA, getResult(send, (args) => ({
1410
1583
  method: "GET",
1411
1584
  path: `/accounts/${encodeURIComponent(accountArg(args))}/workers/scripts/${encodeURIComponent(requireString(args, "scriptName"))}/deployments/${encodeURIComponent(requireString(args, "deploymentId"))}`,
1412
1585
  }), projectWorkerDeployment)),
@@ -1437,6 +1610,7 @@ function buildTools(scope, authentication) {
1437
1610
  id: { type: "string" },
1438
1611
  title: { type: "string" },
1439
1612
  supportsUrlEncoding: { type: "boolean" },
1613
+ jurisdiction: { type: "string", enum: ["eu", "fedramp", "us"] },
1440
1614
  },
1441
1615
  required: ["id", "title"],
1442
1616
  }), async (args, ctx) => {
@@ -1452,7 +1626,7 @@ function buildTools(scope, authentication) {
1452
1626
  }),
1453
1627
  cfTool("get_kv_namespace", "Get one Workers KV namespace by id.", readOnly, "accountId", scope.accountId, {
1454
1628
  namespaceId: NAMESPACE_ID_PROPERTY
1455
- }, ["namespaceId"], OPEN_OBJECT_OUTPUT_SCHEMA, getResult(send, (args) => ({
1629
+ }, ["namespaceId"], KV_NAMESPACE_SCHEMA, getResult(send, (args) => ({
1456
1630
  method: "GET",
1457
1631
  path: `/accounts/${encodeURIComponent(accountArg(args))}/storage/kv/namespaces/${encodeURIComponent(requireString(args, "namespaceId"))}`,
1458
1632
  }), projectKvNamespace)),
@@ -1462,12 +1636,16 @@ function buildTools(scope, authentication) {
1462
1636
  minLength: 1,
1463
1637
  maxLength: 512,
1464
1638
  description: "Human-readable namespace title.",
1465
- }
1466
- }, ["title"], OPEN_OBJECT_OUTPUT_SCHEMA, async (args, ctx) => {
1639
+ },
1640
+ jurisdiction: KV_JURISDICTION_PROPERTY
1641
+ }, ["title"], KV_NAMESPACE_SCHEMA, async (args, ctx) => {
1467
1642
  const { result } = await callCloudflare(send, {
1468
1643
  method: "POST",
1469
1644
  path: `/accounts/${encodeURIComponent(accountArg(args))}/storage/kv/namespaces`,
1470
- body: { title: requireString(args, "title") },
1645
+ body: compact({
1646
+ title: requireString(args, "title"),
1647
+ jurisdiction: args["jurisdiction"],
1648
+ }),
1471
1649
  }, ctx);
1472
1650
  return projectKvNamespace(result);
1473
1651
  }),
@@ -1479,13 +1657,15 @@ function buildTools(scope, authentication) {
1479
1657
  maxLength: 512,
1480
1658
  description: "Replacement namespace title.",
1481
1659
  }
1482
- }, ["namespaceId", "title"], OPEN_OBJECT_OUTPUT_SCHEMA, async (args, ctx) => {
1660
+ }, ["namespaceId", "title"], KV_NAMESPACE_SCHEMA, async (args, ctx) => {
1483
1661
  const { result } = await callCloudflare(send, {
1484
1662
  method: "PUT",
1485
1663
  path: `/accounts/${encodeURIComponent(accountArg(args))}/storage/kv/namespaces/${encodeURIComponent(requireString(args, "namespaceId"))}`,
1486
1664
  body: { title: requireString(args, "title") },
1487
1665
  }, ctx);
1488
- return result ?? { renamed: true, namespaceId: args["namespaceId"] };
1666
+ return result
1667
+ ? projectKvNamespace(result)
1668
+ : { renamed: true, namespaceId: args["namespaceId"] };
1489
1669
  }),
1490
1670
  cfTool("delete_kv_namespace", "Permanently delete a Workers KV namespace and every key stored in it.", { readOnlyHint: false, destructiveHint: true }, "accountId", scope.accountId, {
1491
1671
  namespaceId: NAMESPACE_ID_PROPERTY
@@ -1516,7 +1696,18 @@ function buildTools(scope, authentication) {
1516
1696
  }, ["namespaceId"], {
1517
1697
  type: "object",
1518
1698
  properties: {
1519
- keys: { type: "array", items: OPEN_OBJECT_OUTPUT_SCHEMA },
1699
+ keys: {
1700
+ type: "array",
1701
+ items: {
1702
+ type: "object",
1703
+ properties: {
1704
+ name: { type: "string" },
1705
+ expiration: { type: "number" },
1706
+ metadata: {},
1707
+ },
1708
+ required: ["name"],
1709
+ },
1710
+ },
1520
1711
  nextCursor: NEXT_CURSOR_OUTPUT_PROPERTY,
1521
1712
  },
1522
1713
  required: ["keys"],
@@ -1554,7 +1745,7 @@ function buildTools(scope, authentication) {
1554
1745
  enum: ["text", "json"],
1555
1746
  description: "Return strings as stored, or parse JSON values before returning them.",
1556
1747
  }
1557
- }, ["namespaceId", "keys"], OPEN_OBJECT_OUTPUT_SCHEMA, async (args, ctx) => {
1748
+ }, ["namespaceId", "keys"], KV_BULK_VALUES_SCHEMA, async (args, ctx) => {
1558
1749
  const { result } = await callCloudflare(send, {
1559
1750
  method: "POST",
1560
1751
  path: `/accounts/${encodeURIComponent(accountArg(args))}/storage/kv/namespaces/${encodeURIComponent(requireString(args, "namespaceId"))}/bulk/get`,
@@ -1564,7 +1755,7 @@ function buildTools(scope, authentication) {
1564
1755
  type: args["type"],
1565
1756
  }),
1566
1757
  }, ctx);
1567
- return asRecord(result);
1758
+ return projectKvBulkValues(result);
1568
1759
  }),
1569
1760
  cfTool("bulk_write_kv_values", "Create or replace multiple Workers KV values, with optional expirations and JSON metadata.", { readOnlyHint: false, destructiveHint: true }, "accountId", scope.accountId, {
1570
1761
  namespaceId: NAMESPACE_ID_PROPERTY,
@@ -1609,13 +1800,13 @@ function buildTools(scope, authentication) {
1609
1800
  additionalProperties: false,
1610
1801
  },
1611
1802
  }
1612
- }, ["namespaceId", "entries"], OPEN_OBJECT_OUTPUT_SCHEMA, async (args, ctx) => {
1803
+ }, ["namespaceId", "entries"], KV_BULK_RESULT_SCHEMA, async (args, ctx) => {
1613
1804
  const { result } = await callCloudflare(send, {
1614
1805
  method: "PUT",
1615
1806
  path: `/accounts/${encodeURIComponent(accountArg(args))}/storage/kv/namespaces/${encodeURIComponent(requireString(args, "namespaceId"))}/bulk`,
1616
1807
  body: args["entries"],
1617
1808
  }, ctx);
1618
- return asRecord(result);
1809
+ return projectKvBulkResult(result);
1619
1810
  }),
1620
1811
  cfTool("bulk_delete_kv_values", "Permanently delete multiple keys from a Workers KV namespace.", { readOnlyHint: false, destructiveHint: true }, "accountId", scope.accountId, {
1621
1812
  namespaceId: NAMESPACE_ID_PROPERTY,
@@ -1626,13 +1817,13 @@ function buildTools(scope, authentication) {
1626
1817
  items: { type: "string", minLength: 1, maxLength: 512 },
1627
1818
  description: "Key names to delete, up to Cloudflare's 10,000-key bulk limit.",
1628
1819
  }
1629
- }, ["namespaceId", "keys"], OPEN_OBJECT_OUTPUT_SCHEMA, async (args, ctx) => {
1820
+ }, ["namespaceId", "keys"], KV_BULK_RESULT_SCHEMA, async (args, ctx) => {
1630
1821
  const { result } = await callCloudflare(send, {
1631
1822
  method: "POST",
1632
1823
  path: `/accounts/${encodeURIComponent(accountArg(args))}/storage/kv/namespaces/${encodeURIComponent(requireString(args, "namespaceId"))}/bulk/delete`,
1633
1824
  body: args["keys"],
1634
1825
  }, ctx);
1635
- return asRecord(result);
1826
+ return projectKvBulkResult(result);
1636
1827
  }),
1637
1828
  cfTool("list_r2_buckets", "List R2 buckets in an account, with location and storage class.", readOnly, "accountId", scope.accountId, {
1638
1829
  nameContains: {
@@ -1829,34 +2020,15 @@ function buildTools(scope, authentication) {
1829
2020
  cfTool("get_r2_cors", "Get the browser CORS rules configured on an R2 bucket.", readOnly, "accountId", scope.accountId, {
1830
2021
  bucketName: R2_BUCKET_NAME_PROPERTY,
1831
2022
  jurisdiction: R2_JURISDICTION_PROPERTY
1832
- }, ["bucketName"], OPEN_OBJECT_OUTPUT_SCHEMA, getResult(send, (args) => ({
2023
+ }, ["bucketName"], R2_CORS_SCHEMA, getResult(send, (args) => ({
1833
2024
  method: "GET",
1834
2025
  path: `/accounts/${encodeURIComponent(accountArg(args))}/r2/buckets/${encodeURIComponent(requireString(args, "bucketName"))}/cors`,
1835
2026
  headers: r2Headers(args),
1836
- }), asRecord)),
2027
+ }), projectR2Cors)),
1837
2028
  cfTool("list_pages_projects", "List Cloudflare Pages projects in an account, with their production branch and latest deployment.", readOnly, "accountId", scope.accountId, {
1838
2029
  ...pagingInputProperties(1, 100, { bounds: "undocumented" }),
1839
2030
  raw: RAW_INPUT_PROPERTY
1840
- }, [], listOutputSchema("projects", {
1841
- type: "object",
1842
- properties: {
1843
- name: { type: "string" },
1844
- subdomain: { type: "string" },
1845
- domains: { type: "array", items: { type: "string" } },
1846
- productionBranch: { type: "string" },
1847
- createdOn: { type: "string" },
1848
- latestDeployment: {
1849
- type: "object",
1850
- properties: {
1851
- id: { type: "string" },
1852
- environment: { type: "string" },
1853
- url: { type: "string" },
1854
- createdOn: { type: "string" },
1855
- },
1856
- },
1857
- },
1858
- required: ["name"],
1859
- }), async (args, ctx) => {
2031
+ }, [], listOutputSchema("projects", PAGES_PROJECT_SCHEMA), async (args, ctx) => {
1860
2032
  const { result, resultInfo } = await callCloudflare(send, {
1861
2033
  method: "GET",
1862
2034
  path: `/accounts/${encodeURIComponent(accountArg(args))}/pages/projects`,
@@ -1870,7 +2042,7 @@ function buildTools(scope, authentication) {
1870
2042
  cfTool("get_pages_project", "Get one Pages project, including build configuration, deployment configuration, domains, and latest deployment.", readOnly, "accountId", scope.accountId, {
1871
2043
  projectName: PROJECT_NAME_PROPERTY,
1872
2044
  raw: RAW_INPUT_PROPERTY
1873
- }, ["projectName"], OPEN_OBJECT_OUTPUT_SCHEMA, getResult(send, (args) => ({
2045
+ }, ["projectName"], PAGES_PROJECT_SCHEMA, getResult(send, (args) => ({
1874
2046
  method: "GET",
1875
2047
  path: `/accounts/${encodeURIComponent(accountArg(args))}/pages/projects/${encodeURIComponent(requireString(args, "projectName"))}`,
1876
2048
  }), (result, args) => args["raw"] === true ? result : projectPagesProject(result))),
@@ -1882,7 +2054,7 @@ function buildTools(scope, authentication) {
1882
2054
  description: "Optional deployment environment filter.",
1883
2055
  },
1884
2056
  ...pagingInputProperties(1, 100, { bounds: "undocumented" })
1885
- }, ["projectName"], listOutputSchema("deployments", OPEN_OBJECT_OUTPUT_SCHEMA), async (args, ctx) => {
2057
+ }, ["projectName"], listOutputSchema("deployments", PAGES_DEPLOYMENT_SCHEMA), async (args, ctx) => {
1886
2058
  const { result, resultInfo } = await callCloudflare(send, {
1887
2059
  method: "GET",
1888
2060
  path: `/accounts/${encodeURIComponent(accountArg(args))}/pages/projects/${encodeURIComponent(requireString(args, "projectName"))}/deployments`,
@@ -1901,14 +2073,14 @@ function buildTools(scope, authentication) {
1901
2073
  projectName: PROJECT_NAME_PROPERTY,
1902
2074
  deploymentId: DEPLOYMENT_ID_PROPERTY,
1903
2075
  raw: RAW_INPUT_PROPERTY
1904
- }, ["projectName", "deploymentId"], OPEN_OBJECT_OUTPUT_SCHEMA, getResult(send, (args) => ({
2076
+ }, ["projectName", "deploymentId"], PAGES_DEPLOYMENT_SCHEMA, getResult(send, (args) => ({
1905
2077
  method: "GET",
1906
2078
  path: `/accounts/${encodeURIComponent(accountArg(args))}/pages/projects/${encodeURIComponent(requireString(args, "projectName"))}/deployments/${encodeURIComponent(requireString(args, "deploymentId"))}`,
1907
2079
  }), (result, args) => args["raw"] === true ? result : projectPagesDeployment(result))),
1908
2080
  cfTool("retry_pages_deployment", "Retry a failed or cancelled Pages deployment using its existing source and build configuration.", { readOnlyHint: false }, "accountId", scope.accountId, {
1909
2081
  projectName: PAGES_PROJECT_NAME_PROPERTY,
1910
2082
  deploymentId: RETRY_DEPLOYMENT_ID_PROPERTY
1911
- }, ["projectName", "deploymentId"], OPEN_OBJECT_OUTPUT_SCHEMA, async (args, ctx) => {
2083
+ }, ["projectName", "deploymentId"], PAGES_DEPLOYMENT_SCHEMA, async (args, ctx) => {
1912
2084
  const { result } = await callCloudflare(send, {
1913
2085
  method: "POST",
1914
2086
  path: `/accounts/${encodeURIComponent(accountArg(args))}/pages/projects/${encodeURIComponent(requireString(args, "projectName"))}/deployments/${encodeURIComponent(requireString(args, "deploymentId"))}/retry`,
@@ -1918,7 +2090,7 @@ function buildTools(scope, authentication) {
1918
2090
  cfTool("rollback_pages_deployment", "Promote a previous Pages deployment to production, replacing the currently served production deployment.", { readOnlyHint: false, destructiveHint: true }, "accountId", scope.accountId, {
1919
2091
  projectName: PAGES_PROJECT_NAME_PROPERTY,
1920
2092
  deploymentId: ROLLBACK_DEPLOYMENT_ID_PROPERTY
1921
- }, ["projectName", "deploymentId"], OPEN_OBJECT_OUTPUT_SCHEMA, async (args, ctx) => {
2093
+ }, ["projectName", "deploymentId"], PAGES_DEPLOYMENT_SCHEMA, async (args, ctx) => {
1922
2094
  const { result } = await callCloudflare(send, {
1923
2095
  method: "POST",
1924
2096
  path: `/accounts/${encodeURIComponent(accountArg(args))}/pages/projects/${encodeURIComponent(requireString(args, "projectName"))}/deployments/${encodeURIComponent(requireString(args, "deploymentId"))}/rollback`,
@@ -1934,7 +2106,7 @@ function buildTools(scope, authentication) {
1934
2106
  }))),
1935
2107
  cfTool("list_pages_domains", "List custom domains attached to a Pages project and their validation status.", readOnly, "accountId", scope.accountId, {
1936
2108
  projectName: PAGES_PROJECT_NAME_PROPERTY
1937
- }, ["projectName"], listOutputSchema("domains", OPEN_OBJECT_OUTPUT_SCHEMA), async (args, ctx) => {
2109
+ }, ["projectName"], listOutputSchema("domains", PAGES_DOMAIN_SCHEMA), async (args, ctx) => {
1938
2110
  const { result } = await callCloudflare(send, {
1939
2111
  method: "GET",
1940
2112
  path: `/accounts/${encodeURIComponent(accountArg(args))}/pages/projects/${encodeURIComponent(requireString(args, "projectName"))}/domains`,
@@ -1944,7 +2116,7 @@ function buildTools(scope, authentication) {
1944
2116
  cfTool("add_pages_domain", "Attach a custom domain to a Pages project. DNS ownership and validation still apply.", { readOnlyHint: false }, "accountId", scope.accountId, {
1945
2117
  projectName: PAGES_PROJECT_NAME_PROPERTY,
1946
2118
  domain: { type: "string", minLength: 1, description: "Fully qualified custom domain to attach." }
1947
- }, ["projectName", "domain"], OPEN_OBJECT_OUTPUT_SCHEMA, async (args, ctx) => {
2119
+ }, ["projectName", "domain"], PAGES_DOMAIN_SCHEMA, async (args, ctx) => {
1948
2120
  const { result } = await callCloudflare(send, {
1949
2121
  method: "POST",
1950
2122
  path: `/accounts/${encodeURIComponent(accountArg(args))}/pages/projects/${encodeURIComponent(requireString(args, "projectName"))}/domains`,
@@ -42,6 +42,10 @@ const READ_ONLY_TOOLS = new Set([
42
42
  "get_team",
43
43
  "list_users",
44
44
  "get_user",
45
+ "get_workspace",
46
+ // Templates
47
+ "list_templates",
48
+ "get_template",
45
49
  // Status updates
46
50
  "get_status_updates",
47
51
  // Releases
@@ -103,6 +107,9 @@ const WRITE_TOOLS = new Map([
103
107
  ["create_attachment_from_upload", "additive"],
104
108
  ["create_attachment", "additive"],
105
109
  ["delete_attachment", "destructive"],
110
+ // Explicit issue access
111
+ ["share_issue", "destructive"],
112
+ ["unshare_issue", "destructive"],
106
113
  // Customer requests (plan-gated)
107
114
  ["save_customer", "destructive"],
108
115
  ["delete_customer", "destructive"],
@@ -74,15 +74,16 @@ const WRITE_TOOLS = new Map([
74
74
  ["Update-Experiment", "destructive"],
75
75
  ["Create-Feature-Flag", "additive"],
76
76
  ["Update-Feature-Flag", "destructive"],
77
+ ["Fill-Event-Metadata", "destructive"],
77
78
  ]);
78
- /** Live US hosted-MCP schemas reviewed read-only on 2026-08-13 (#395). */
79
+ /** Live US hosted-MCP schemas reviewed read-only on 2026-08-30 (#395, #512). */
79
80
  const MIXPANEL_SCHEMA_DIGESTS = {
80
81
  "Bulk-Edit-Events": "sha256:94512138df153de95436371f5a313e32b97faffebda3be6c0c69d09d1ff2b340",
81
82
  "Bulk-Edit-Properties": "sha256:93481eb896ded45b623c678612e2156439efbaad5b4d660da1f2b087e7409ee3",
82
83
  "Create-Cohort": "sha256:ea687f4bc607f8bfb5b1949e060239d6f7d629d3ec80fb0b72eae6cc6156ed03",
83
84
  "Create-Custom-Property": "sha256:d22818b812f3fd0e785a5bbbee26cf099eaa911d5b6f383f94cf458a2ed26294",
84
85
  "Create-Dashboard": "sha256:bd3b6e5134d27dafb04ccdf04d19e54dd23e6e2dc16989e418006e484268037b",
85
- "Create-Experiment": "sha256:3307bd7202f5483adbc28a9ef1d562095d6942eb2c3a15308f458072c93e6888",
86
+ "Create-Experiment": "sha256:1cfc2edeb2ac2d329a531d2095671a0653ab5b94b9e233b34268ff29a48c5ac5",
86
87
  "Create-Feature-Flag": "sha256:3460d11d726727349cac62db5c19915ab589b7f1d8387042f0a3783356b252c4",
87
88
  "Create-Lookup-Table": "sha256:c2fefa33a4f19fc65f394fecdc7126cab0ae874f7c97018cf003d8462a049e4c",
88
89
  "Create-Metric": "sha256:315766d0c197d87bb44aedd16732f6e69fbfc93661d1fcfc177cadc1751f26ce",
@@ -98,13 +99,14 @@ const MIXPANEL_SCHEMA_DIGESTS = {
98
99
  "Edit-Event": "sha256:28c47da0b56f57da0f11eb11435441a39ecd5175600f854442744c66a379ef93",
99
100
  "Edit-Property": "sha256:11975587d2a566edc468db7cb24df70167d12068f30c1fe52c84f543cf4e2399",
100
101
  "Explain-Experiment-Health-Check": "sha256:a50b1263247012dc78521bf6c1dd18584a7b08d46221a444b1ca49c81d3286e5",
102
+ "Fill-Event-Metadata": "sha256:53accc988f216bdd5d7a259d731f6df82549e4e6146b191f1815a0d1a72a1abe",
101
103
  "Find-Duplicate-Groups": "sha256:8f944cef9a147eab3c51bfcf1b873cef1409e5a6c21565d34e7ed20d23dcebb7",
102
104
  "Get-Business-Context": "sha256:309f5ba864c90132061096b4f0ebc1e78544a6486bac3a45bd661d16bcab2b6c",
103
105
  "Get-Cohort": "sha256:e18c500459edd9c2b6a614a3f6c97b668786be9abf72929a0a50086bdadb1dae",
104
106
  "Get-Custom-Property": "sha256:d1cbce906cee66d422846c8ef1a745bbeac2c058ecad6b1ee8dcdd2120fa86be",
105
107
  "Get-Dashboard": "sha256:56659fa3277723b75e24f3b4ca142ac9cd62120fb97e6c9252c221d00cdf8509",
106
108
  "Get-Events": "sha256:d206fe30ab47d64bf6090bffdb4d119a80cfc2a35963bbe7fd52d56060090ded",
107
- "Get-Experiment": "sha256:f9f04a2bb136809c754ea612963e1cdfb57c2c9ecc34a53ac6e1730f8758798f",
109
+ "Get-Experiment": "sha256:ab685aa985aa2ec36d9cbeb1b3c1ef298b020e552e8fdce12e75abbeb4706f2b",
108
110
  "Get-Experiment-Results-Interpretation-Guidance": "sha256:e517d9759f66f4a7ad15b0b67ffaabfb605e80949afcf41d007dfafd8f3e9574",
109
111
  "Get-Experiment-Setup-Guidance": "sha256:e517d9759f66f4a7ad15b0b67ffaabfb605e80949afcf41d007dfafd8f3e9574",
110
112
  "Get-Feature-Flag": "sha256:129de58b379ffba272bdbcee2b5759262e586dd415edc2067a69e9844d4d0877",
@@ -136,7 +138,7 @@ const MIXPANEL_SCHEMA_DIGESTS = {
136
138
  "Update-Cohort": "sha256:ebe0d5afcc00e23eef55f079cd1816c851c2c647dff9565b7045f1f1615663f2",
137
139
  "Update-Custom-Property": "sha256:781aaaab41c1ab5958062dc393d02b1df2ef2a09a28d3c4f21ae3177f4f53c86",
138
140
  "Update-Dashboard": "sha256:2cc179ba75eda476ba7488f01503d947f023a4460aa98c4806ef0ab10c3b3ce8",
139
- "Update-Experiment": "sha256:52ebf7595e48a40e218ff463ed72942a4818abc3ce93d8da6fafa8d358326437",
141
+ "Update-Experiment": "sha256:3ea3902555c146f45127fc563b36ffb7ff04b7594765dac9ae98cc09dc432808",
140
142
  "Update-Feature-Flag": "sha256:9b34b19164168938d08a75d268c9becf8d189c85a1789a45061ae304041faf7c",
141
143
  "Update-Lookup-Table": "sha256:ef28f1ec9c9484a7a53b5e2b6659e70f79a8e71e55bda17025aa4ab3c23b6a63",
142
144
  "Update-Metric": "sha256:739bb6abdab19282afd4a6644a96183daabe9098a5322c44a77b840608a5ee9d",
@@ -41,6 +41,7 @@ const READ_ONLY_TOOLS = new Set([
41
41
  // Customers and subscriptions
42
42
  "get-customer",
43
43
  "get-customer-center-config",
44
+ "get-refund-request-preferences",
44
45
  "get-subscription",
45
46
  "list-customer-events",
46
47
  "list-customers",
@@ -157,7 +158,7 @@ function sharedUsageGuide() {
157
158
  - \`get-chart-data\` is the metrics path: read \`get-chart-options-schema\` for the chart you want before calling it, rather than guessing an option name. \`get-overview-metrics\` and \`get-revenue-metric\` answer the summary questions in one call.
158
159
  - \`create-paywall-ai\`, \`edit-paywall-ai\`, and \`set-product-store-state\` are asynchronous. They return a task or operation id; poll it with \`get-paywall-ai-task\` or \`get-product-store-state-operation\` rather than assuming the work finished when the call returned.
159
160
  - This connection's tool list is not a fixed set. RevenueCat gates parts of its MCP catalog by plan, platform, and beta enrollment — paywall AI editing, benchmarks, experiments, virtual currencies, and the account-billing tools are the usual absentees — so search this connector for what it actually exposes rather than assuming a documented tool is here.
160
- - \`render-paywall-screenshot\` is unclassified on purpose: RevenueCat's reference gives it no access column, so it fails closed onto \`call_destructive_tool\` until a release reviews it.
161
+ - \`render-paywall-screenshot\` is unclassified on purpose because RevenueCat's reference gives it no access column. The current server marks it read-only, which Connecta preserves; without that annotation it fails closed onto \`call_destructive_tool\`.
161
162
  - RevenueCat meters API v2 per minute and per domain, and the domains differ: 480 requests per minute for customer information and virtual currencies, 60 for project configuration and audiences, 25 for charts and metrics. It answers a breach with \`429\`, a \`Retry-After\` header, and a \`backoff_ms\` field. Back off on that rather than retrying immediately, and expect chart sweeps to hit the ceiling long before customer reads do.
162
163
  - Treat every create, update, archive, unarchive, attach, detach, delete, publish, unpublish, grant, assign, and submit operation as a write. Connecta routes the maintained write catalog through \`call_destructive_tool\`; newly added tools also fail closed until a release classifies them.
163
164
  - An \`auth_required\` failure means this connector's RevenueCat authorization is missing or expired: run \`authorize_connector\` for this connector id, then retry the same call unchanged. A rejected argument, a permission gap, or a plan restriction comes back in RevenueCat's own words instead — read it rather than re-authorizing.
@@ -37,16 +37,16 @@ const READ_ONLY_TOOLS = new Set([
37
37
  "stripe_api_search",
38
38
  "stripe_api_details",
39
39
  "stripe_api_read",
40
- "get_stripe_account_info",
41
40
  "get_balance_summary",
41
+ "list_available_accounts_or_orgs",
42
+ "manage_stripe_accounts",
42
43
  "search_stripe_documentation",
43
- "stripe_implementation_planner",
44
44
  ]);
45
- /** Reviewed writes, including refund rationale: `documentation/stripe.md`. */
45
+ /** Reviewed writes, including mixed read/create tools: `documentation/stripe.md`. */
46
46
  const WRITE_TOOLS = new Map([
47
47
  ["stripe_api_write", "destructive"],
48
- ["create_refund", "destructive"],
49
- ["stripe_report", "additive"],
48
+ ["stripe_implementation_planner", "additive"],
49
+ ["stripe_analytics", "additive"],
50
50
  ["send_stripe_mcp_feedback", "additive"],
51
51
  ]);
52
52
  /** Release-reviewed manifest; see provider conventions P5 and P13. */
@@ -149,7 +149,8 @@ ${accountInstructions
149
149
  function sharedUsageGuide(rate) {
150
150
  return `
151
151
  - Four generic tools reach any Stripe API method. Find the method with \`stripe_api_search\`, read its parameters with \`stripe_api_details\`, then call \`stripe_api_read\` (GET) or \`stripe_api_write\` (POST/PATCH/PUT/DELETE). Never guess a path or a parameter name — \`stripe_api_details\` is cheaper than a rejected write.
152
- - Prefer a dedicated tool when one covers the task: \`get_stripe_account_info\` for account information, \`get_balance_summary\` for balances, \`create_refund\` for refunds, \`stripe_report\` for reports. One call instead of three, and a refund named \`create_refund\` reads far more clearly in the approval a human sees than the same refund buried in \`stripe_api_write\` arguments.
152
+ - Prefer a dedicated tool when one covers the task: \`get_balance_summary\` for balances and \`stripe_analytics\` for Sigma or Metrics reporting. Use \`stripe_api_search\` for everything else instead of assuming a retired dedicated tool still exists.
153
+ - \`stripe_implementation_planner\` and the query-execution intents of \`stripe_analytics\` create provider-side planning or query-run state. Connecta therefore routes both through \`call_destructive_tool\` as non-destructive writes; their retrieval paths stay behind the same tool boundary.
153
154
  - \`stripe_api_write\` carries the blast radius of the entire write API — every POST, PATCH, PUT, and DELETE, from a customer edit to a subscription cancellation. State the method and path explicitly; expect approval on every call.
154
155
  - Lists are cursor-paginated: \`limit\` defaults to 10 and caps at 100, \`starting_after\` and \`ending_before\` take an object id and are mutually exclusive, and \`has_more\` says whether to continue. Page inside \`execute_code\`.
155
156
  - Any \`stripe_api_read\` list or \`stripe_api_search\` that returns full objects belongs inside \`execute_code\`, projected to the fields the question needs before \`return\`. Neither \`limit\` nor \`expand\` substitutes for that: an unprojected list of customers or invoices truncates long before it answers, and a projected one keeps the customer's name, email, and address out of the transcript.
package/dist/version.d.ts CHANGED
@@ -4,4 +4,4 @@
4
4
  * a bump that forgets this file fails the build rather than shipping a stale
5
5
  * version to `/health` and to downstream MCP handshakes.
6
6
  */
7
- export declare const CONNECTA_VERSION = "0.21.0";
7
+ export declare const CONNECTA_VERSION = "0.21.1";
package/dist/version.js CHANGED
@@ -4,4 +4,4 @@
4
4
  * a bump that forgets this file fails the build rather than shipping a stale
5
5
  * version to `/health` and to downstream MCP handshakes.
6
6
  */
7
- export const CONNECTA_VERSION = "0.21.0";
7
+ export const CONNECTA_VERSION = "0.21.1";
@@ -65,7 +65,7 @@ Worker-level Access runs before every connecta route. Consequently:
65
65
  OAuth discovery paths when Managed OAuth is enabled.
66
66
 
67
67
  The [Worker example](../examples/worker/) carries the complete deployment shape
68
- and the [upgrade guide](./upgrading.md#0200--0210) gives the reversible Clerk
68
+ and the [upgrade guide](./upgrading.md#0200--0211) gives the reversible Clerk
69
69
  migration.
70
70
 
71
71
  ## Clerk configuration is checked at construction
@@ -153,6 +153,18 @@ every constrained field, endpoint-specific pagination bounds, and a description
153
153
  on every property. `test/cloudflare-provider.test.ts` walks the surface and
154
154
  asserts those properties rather than leaving them as a claim.
155
155
 
156
+ The per-setting zone tools accept Cloudflare's current non-empty setting ids,
157
+ including `webmcp_enabled` and `webmcp_packs`. Cloudflare's
158
+ [rendered setting reference](https://developers.cloudflare.com/api/resources/zones/subresources/settings/)
159
+ and current OpenAPI now agree on both beta ids. Results preserve the value and
160
+ the actual `editable` flag Cloudflare returned; Connecta does not apply the
161
+ document's defaults locally.
162
+
163
+ KV namespace jurisdiction is creation-only. `create_kv_namespace` accepts
164
+ `eu`, `fedramp`, or `us`, and namespace reads preserve the returned value.
165
+ R2 uses a different enum: `default`, `eu`, `us`, or `fedramp`, sent through
166
+ `cf-r2-jurisdiction` by all eight named R2 operations.
167
+
156
168
  ### What the named surface deliberately leaves out
157
169
 
158
170
  A named tool is a permanent line item in every deployment's catalog, so the
@@ -206,7 +218,7 @@ connection *calls*, dropping the tool drops the row — so
206
218
  rather than by a recorded exception. A path reached only through a hatch is
207
219
  named by the caller, so it was never a touched endpoint.
208
220
 
209
- The surviving 47 named tools all refuse malformed arguments locally, which is
221
+ The surviving 48 named tools all refuse malformed arguments locally, which is
210
222
  the one thing no escape hatch can do: a hatch's path is an opaque string, so it
211
223
  can only check that a path is a path.
212
224
 
@@ -318,6 +330,12 @@ renamed to `camelCase`. A zone comes back as `id`, `name`, `status`, `paused`,
318
330
  `type`, `accountId`, `accountName`, `plan`, `nameServers`, and timestamps —
319
331
  not the forty-field object Cloudflare sends.
320
332
 
333
+ Every named tool declares useful top-level output keys. Zone settings, Worker
334
+ settings and deployments, KV namespaces and bulk operations, rulesets, R2 CORS,
335
+ and Pages resources use maintained result schemas instead of an open
336
+ "Cloudflare object" declaration. The three raw escape hatches remain open by
337
+ design because their result fields depend on the caller-supplied endpoint.
338
+
321
339
  Paginated lists add a `page` object derived from `result_info`:
322
340
  `{ page, perPage, count, totalCount, totalPages, hasMore }`. `hasMore` is the
323
341
  field to branch on.
@@ -110,9 +110,10 @@ the connector is present and reports `auth_required`. See
110
110
 
111
111
  The wrapper classifies Linear's documented `list_*`, `get_*`, and
112
112
  `search_documentation` tools as reads, and its `save_*`, `create_*`, `delete_*`,
113
- `resolve_*`, `submit_*`, and `merge_*` tools as writes. An unfamiliar tool the
114
- downstream leaves unannotated fails closed onto `call_destructive_tool` until a
115
- Connecta release reviews it.
113
+ `resolve_*`, `submit_*`, `merge_*`, `share_issue`, and `unshare_issue` tools as
114
+ writes. Sharing changes an existing issue's access, so both halves are
115
+ destructive. An unfamiliar tool the downstream leaves unannotated fails closed
116
+ onto `call_destructive_tool` until a Connecta release reviews it.
116
117
 
117
118
  That classification fills in downstream silence and otherwise preserves
118
119
  explicit annotations. A tool on the read allowlist arriving with
@@ -136,7 +137,8 @@ though some calls only create. The genuine creates are `create_issue_label` and
136
137
  ## The catalog is not a fixed set
137
138
 
138
139
  Linear's hosted `tools/list` varies by workspace plan and enabled features:
139
- customer requests, releases, and code review do not appear in every workspace.
140
+ customer requests, releases, code review, templates, and explicit issue sharing
141
+ do not appear in every workspace.
140
142
  The maintained allowlists are therefore a superset — a classified name a
141
143
  workspace never returns costs nothing, and a genuinely new tool fails closed.
142
144
  Agents should search this connector's catalog for what the workspace actually
@@ -84,7 +84,7 @@ the maintained guide carries the missing call guidance:
84
84
  A read-only live audit on 2026-08-13 confirmed all three refusals against the
85
85
  US hosted endpoint. They are reported upstream as
86
86
  [`mixpanel/mixpanel-headless#202`](https://github.com/mixpanel/mixpanel-headless/issues/202).
87
- The vetted catalog records the same audit's schema digests for all 63 tools,
87
+ The vetted catalog records current schema digests for all 64 tools,
88
88
  so a later schema correction or regression appears by tool name in the
89
89
  maintainer drift check. The guide can then shrink when the downstream schema
90
90
  becomes complete; Connecta does not absorb the defect permanently.
@@ -110,8 +110,10 @@ rest) leave `destructiveHint` unset; `readOnlyHint: false` already routes them
110
110
  through the destructive path, and asserting destruction only inflates the
111
111
  approval copy the host shows a human.
112
112
 
113
- Experiments and Feature Flags 15 of the 63 classified tools — are Mixpanel
114
- beta surfaces. Expect their names and schemas to move faster than the rest.
113
+ Experiments and Feature Flags are Mixpanel beta surfaces. Their three changed
114
+ schemas were reviewed again on 2026-08-30. The same review added
115
+ `Fill-Event-Metadata` as a destructive write because it applies generated names
116
+ and descriptions to existing Lexicon events.
115
117
 
116
118
  ## Rate limits
117
119
 
@@ -233,7 +233,7 @@ in.
233
233
  | `catalog.test.ts` | lexical ranking and the compact schema renderer — `const`, `allOf` beside siblings, `$ref`, the depth limit, per-schema caching, and 2020-12 keyword compatibility |
234
234
  | `clerk.test.ts` | protected-resource metadata, the browser sign-in config, OAuth and session tokens, cached best-effort activity labels with their caps, the hand-applied `azp` rejection, and the `allowedDomains` allowlist including every lookalike that must not be repaired into a match |
235
235
  | `cloudflare-access-auth.test.ts` | trusted `ctx.access` human and service identities, absent/error fail-closed behavior, service-token MCP admission without operator mutation, human same-origin mutation, and the Clerk-to-ambient shell switch |
236
- | `cloudflare-provider.test.ts` | `cloudflare()` construction, tool surface, request building, projections, typed failures, and credential test |
236
+ | `cloudflare-provider.test.ts` | `cloudflare()` construction, tool surface, current R2 and KV jurisdictions, useful output declarations, request building, projections including additive provider fields, typed failures, and credential test |
237
237
  | `code-first-surface.test.ts` | the seven-tool surface itself — an executor required, every removed option and top-level tool refused, compact always-loaded routing pinned below 1,000 characters, complete on-demand usage served, and `connecta.ui` findable before connector search |
238
238
  | `codemode-compat.test.ts` | the `Executor` seam staying structurally compatible with `@cloudflare/codemode`'s `DynamicWorkerExecutor`, enforced by `tsc` |
239
239
  | `config.test.ts` | the grouped `ConnectaConfig` boundary — each group forwarding to its internals, malformed admission bounds failing construction, and unknown own-properties rejected by their complete path before construction does work |
@@ -247,11 +247,11 @@ in.
247
247
  | `executor-admission.test.ts` | the portable bounded FIFO both pools use: active and queue ceilings, stable retryable overload, queue timeout, cancellation removal, idempotent release, shutdown |
248
248
  | `guarded-fetch.test.ts` | the guarded transport — construction, request building, destination confinement, and response handling |
249
249
  | `guest-api-contract.test.ts` | the shared guest contract on the Dynamic Worker, including caught call, typed inline describe recovery, discovery, utility, batch, and budget failure codes; plus the real authority boundary — local `data:` fetch, denied egress, unresolved DNS, empty environment paths, unavailable filesystem/HTTP builtins, and present runtime globals |
250
- | `linear-provider.test.ts` | the Linear proxy's construction, classification, and guide |
250
+ | `linear-provider.test.ts` | the Linear proxy's construction, guide, plan-aware catalog superset, and current workspace, template, and issue-sharing classifications |
251
251
  | `meta-tools-call.test.ts` | registry-backed calls: structured errors, truncation and `get_result`, per-connector result bounds, JSON representation failures, MCP content bounds, and offset alignment |
252
252
  | `meta-tools-search.test.ts` | registry-backed discovery: bounded search with page and address maxima, compact and JSON schemas with constraints, typed describe recovery and suggestions, and structured-result compatibility |
253
253
  | `meta-tools.test.ts` | the remaining registry-backed meta-tools: the complete on-demand usage skill, connector-guide selection and summary bounds, stored-credential drift, catalog health, authorization, probe timeouts, and unavailable or unknown browse recovery |
254
- | `mixpanel-provider.test.ts` | the Mixpanel proxy, its conditional-input guide and complete reviewed schema-digest manifest |
254
+ | `mixpanel-provider.test.ts` | the Mixpanel proxy, its conditional-input guide, destructive metadata fill, and complete 64-tool schema-digest manifest |
255
255
  | `notion-provider.test.ts` | Notion's deliberate tool surface, including declined expanded page inputs, request construction, lean projections, both pagination conventions, error mapping, and writes |
256
256
  | `operator-boundary.test.ts` | the operator row of the decisions table, after every mutation route: authentication material managed without moving a declared structure, and the one honest exception — a credential write making a remote catalog appear, which is discovery arriving, not an operator editing the deployment |
257
257
  | `operator-store.test.ts` | `src/operator-ui/app/store.ts` against a fake browser: the Clerk listener, ambient Access requests without a browser-readable token, `gate()`, the generation fence, and the request path |
@@ -263,11 +263,11 @@ in.
263
263
  | `remote-mcp-pagination.test.ts` | the `tools/list` cursor chain in both directions — exact cursor handoff, first-wins dedup, a failed later page rejecting rather than returning its prefix, the runaway backstops, the tool-metadata re-prime across pages, and paginated catalogs reaching the discovery path |
264
264
  | `request-admission.test.ts` | `/mcp` bounded before auth, the stable 503 and `Retry-After`, health and operator responsiveness under saturation, payload-free counters, queued cancellation, shutdown rejection while active work drains, and the separate fallback code pool |
265
265
  | `result-shapes.test.ts` | passive output-shape learning: value-free bounded inference, merging, 256-entry LRU eviction, 24-hour expiry, runtime isolation, read-only admission, declared-schema precedence, definition-change invalidation, discovery provenance, and failure isolation |
266
- | `revenuecat-provider.test.ts` | the RevenueCat proxy's per-project key scoping and account-wide OAuth guides, its purpose-bearing summary, the argued borderline verdicts in its digest-free manifest, and the deliberately unclassified `render-paywall-screenshot` |
266
+ | `revenuecat-provider.test.ts` | the RevenueCat proxy's per-project key scoping and account-wide OAuth guides, its purpose-bearing summary, the refund-preference read and argued borderline verdicts in its digest-free manifest, and the deliberately unclassified `render-paywall-screenshot` |
267
267
  | `server.test.ts` | end-to-end `/mcp` (401 → compact initialize instructions → seven compact definitions with bounded connector inventory and exact model-only Apps metadata → complete usage skill → `call_tool`), conditional guide pointers, open routes, Clerk `.well-known` metadata without network, code mode, and deferred catalog reads through both discovery surfaces |
268
268
  | `server-route-contracts.test.ts` | the route contracts `server.ts` must keep byte-identical: every built-in answered ahead of connector routes inside the security wrapper, open data-free shells with framing denied, per-route auth and same-origin requirements with exact 401/403/405 bodies, and OAuth `verifyState`-before-`finishAuth` ordering |
269
269
  | `startup-warnings.test.ts` | every construction-time `logger.warn` and, as importantly, the conditions that must *not* trigger one: open mode with a credential or OAuth connector, `publicUrl` unset beside OAuth, dropped branding and `uiAuth` URLs, a missing `verifyState`, a credential test-hook mismatch, and an unusable `calls.maxResultBytes` |
270
- | `stripe-provider.test.ts` | the Stripe proxy's mixed-mode OAuth and fixed-mode header contracts, admission, exact account selectors, and no-guess rule |
270
+ | `stripe-provider.test.ts` | the Stripe proxy's mixed-mode OAuth and fixed-mode header contracts, current eleven-tool classifications, admission, exact account selectors, and no-guess rule |
271
271
  | `operator-view.test.ts` | the app's pure state rules from `view.ts`: filtering, page routing, capability states, activity summaries, drift display, and identity reset |
272
272
  | `ui-credentials.test.ts` | credential-management routes: save, test, delete, validation, authentication, same-origin checks, and multi-field credential shapes |
273
273
  | `ui.test.ts` | the server shell and remaining `/ui/*` routes: gated `/ui/data` with broken-connector isolation and registry-owned catalog-observation containment, plus the URL safety gates |
@@ -693,8 +693,10 @@ Cloudflare keep/prune half of that judgment was made in
693
693
  [#350](https://github.com/zackbart/connecta/issues/350): 30 keep, 18 improve,
694
694
  3 prune, measured per tool in
695
695
  [`eval/current-version/results/issue-350-evidence.md`](https://github.com/zackbart/connecta/blob/main/eval/current-version/results/issue-350-evidence.md).
696
- Its eighteen `improve` rows are H8 and H9 misses on tools that clearly earn
697
- their place, so they are this audit's work, not a second removal argument.
696
+ Its eighteen `improve` rows were H8 and H9 misses on tools that clearly earned
697
+ their place. Issue #488 resolved them with useful output keys and maintained
698
+ projections; the measurements remain the reason those tools stayed rather than
699
+ a second removal argument.
698
700
 
699
701
  Each provider's own guide ([Cloudflare](./cloudflare.md),
700
702
  [Linear](./linear.md), [Mixpanel](./mixpanel.md), [Notion](./notion.md),
@@ -152,17 +152,18 @@ names the `authorize_connector` recovery. A permission gap, a plan restriction,
152
152
  or a rejected argument arrives as RevenueCat wrote it and is not an
153
153
  authorization problem.
154
154
 
155
- ## The ninety-five tools, and what they are classified as
155
+ ## The ninety-six tools, and what they are classified as
156
156
 
157
157
  RevenueCat's
158
158
  [tool reference](https://www.revenuecat.com/docs/tools/mcp/tools-reference),
159
- read on **2026-08-18**, documents ninety-five tools in a Read/Write table.
160
- Ninety-four carry an access column and are classified here: **50 read-only, 15
161
- additive writes, 29 destructive writes.**
159
+ read on **2026-08-30**, documents ninety-six tools. Ninety-five carry an access
160
+ column and are classified here: **51 read-only, 15 additive writes, 29
161
+ destructive writes.**
162
162
 
163
163
  Reads are every `Read` row, verbatim — the nine project and app reads, the four
164
164
  product reads, the entitlement, offering, targeting, paywall, customer, virtual
165
- currency, chart, webhook, and SDK reads, and `get-paywall-ai-task`.
165
+ currency, chart, webhook, and SDK reads, `get-paywall-ai-task`, and
166
+ `get-refund-request-preferences`.
166
167
 
167
168
  Writes follow the verb where the verb is honest: `archive-*` and `unarchive-*`
168
169
  flip an existing object's active state, `update-*`, `delete-*`, `publish-*`,
@@ -191,14 +192,15 @@ beside the row:
191
192
  `create-webhook-integration` deserves a sentence too. No existing integration
192
193
  changes, so the verb reads additive — but with filters omitted the new one
193
194
  "starts delivering" every customer event in the project to a URL the caller
194
- typed. Customer data leaving the account is the `create_refund` argument again:
195
- filed destructive on consequence, so the approval copy says what is at stake.
195
+ typed. Customer data leaving the account makes it destructive on consequence,
196
+ so the approval copy says what is at stake.
196
197
 
197
198
  **`render-paywall-screenshot` is deliberately unclassified.** RevenueCat's
198
- reference gives it no access column at all, so no release has reviewed what it
199
- does. It fails closed onto `call_destructive_tool` rather than being guessed
200
- into the read path because its name sounds harmless (P5). The guide names it,
201
- so an agent does not read the approval prompt as a bug.
199
+ reference gives it no access column. The current live server explicitly marks
200
+ it read-only, so that catalog keeps it callable from `execute_code`; if a later
201
+ catalog omits the annotation, it fails closed onto `call_destructive_tool`.
202
+ Connecta preserves the provider's current annotation without inventing a
203
+ release classification from the tool's harmless-sounding name (P5).
202
204
 
203
205
  That classification fills in downstream silence and otherwise preserves explicit
204
206
  annotations. A tool on the read allowlist arriving with `destructiveHint: true`
@@ -242,7 +244,7 @@ API v2 meters per minute and **per domain**
242
244
  | Charts & Metrics | 25 |
243
245
 
244
246
  A `ConnectorCallAdmissionPolicy` carries exactly one rule, so a connector-wide
245
- budget has to pick one of those six numbers for all ninety-five tools.
247
+ budget has to pick one of those six numbers for all ninety-six tools.
246
248
  Transcribing 25 would throttle a customer read loop to a nineteenth of its
247
249
  documented allowance; transcribing 480 would leave a chart sweep unprotected.
248
250
  Neither is the provider's limit, and both would look like RevenueCat being
@@ -281,15 +283,13 @@ still needs restrained use.
281
283
 
282
284
  ## What is not verified
283
285
 
284
- - **Every tool name is transcribed from RevenueCat's published reference on
285
- 2026-08-18, not read from a live catalog.** No maintainer ran this against a
286
- project with a real key before it shipped. A name the reference lists and the
287
- server does not serve costs nothing; a tool the server serves and the
288
- reference omits fails closed. The maintainer-run drift check with
289
- `CONNECTA_DRIFT_REVENUECAT_KEY` set is what turns that into a finding with a
290
- name attached.
291
- - **No input or output schema has been read**, which is why the manifest
292
- carries no digests.
286
+ - **The 2026-08-30 live review used a project-scoped catalog.** It proves the
287
+ additions that catalog serves, including `get-refund-request-preferences`,
288
+ but cannot prove a globally documented tool was removed. The manifest stays
289
+ a superset because plan, platform, and credential scope hide tools.
290
+ - **No complete schema set has been recorded**, which is why the manifest
291
+ carries no digests. The review read the new live schemas, but its scoped
292
+ catalog omitted many classified writes.
293
293
  - **Whether `render-paywall-screenshot` mutates anything.** It has no access
294
294
  column, and guessing is exactly what P5 exists to prevent.
295
295
 
@@ -139,38 +139,39 @@ boots but cannot list tools is usually a dashboard toggle, not a bad key.
139
139
 
140
140
  ## The eleven tools, and what they are classified as
141
141
 
142
- Stripe documents eleven tools on the hosted server. Seven are reads:
142
+ Stripe currently serves eleven tools. Seven are reads:
143
143
 
144
144
  `stripe_api_search`, `stripe_api_details`, `stripe_api_read`,
145
- `get_stripe_account_info`, `get_balance_summary`,
146
- `search_stripe_documentation`, `stripe_implementation_planner`.
145
+ `get_balance_summary`, `list_available_accounts_or_orgs`,
146
+ `manage_stripe_accounts`, and `search_stripe_documentation`.
147
147
 
148
148
  Four are writes:
149
149
 
150
- `stripe_api_write` and `create_refund` are classified destructive;
151
- `stripe_report` and `send_stripe_mcp_feedback` are additive.
150
+ `stripe_api_write` is destructive. `stripe_implementation_planner`,
151
+ `stripe_analytics`, and `send_stripe_mcp_feedback` are additive.
152
152
 
153
153
  Two of those deserve a sentence. `stripe_api_read` is a read because Stripe
154
154
  documents it as the `GET` half of a generic pair — the tool is the read
155
155
  boundary, not whichever endpoint an agent names inside it, and its sibling
156
156
  `stripe_api_write` carries every `POST`, `PATCH`, `PUT`, and `DELETE`.
157
- `create_refund` is filed destructive despite its name: it reverses a settled
158
- charge and moves money back out, which is a mutation of something that already
159
- exists rather than a fresh object appearing beside it. Additive writes
160
- (`stripe_report`, `send_stripe_mcp_feedback`) leave `destructiveHint` unset;
157
+ `stripe_implementation_planner` creates and continues provider-side guide
158
+ state. `stripe_analytics` combines retrieval with query-run creation behind one
159
+ tool. Stripe marks both not read-only and not destructive, so Connecta records
160
+ them as additive writes. They leave `destructiveHint` unset. Their explicit
161
161
  `readOnlyHint: false` already routes them through `call_destructive_tool`, and
162
- asserting destruction only inflates the approval copy the host shows a human.
162
+ asserting destruction would misstate their effect.
163
163
 
164
164
  That classification fills in downstream silence and otherwise preserves
165
- explicit annotations. It supplies the annotations Stripe leaves unset Stripe
166
- documents no MCP annotations at all. A tool on the read allowlist arriving with
165
+ explicit annotations. The current server annotates all eleven tools, while the
166
+ manifest records what this release reviewed and exposes later contradictions.
167
+ A tool on the read allowlist arriving with
167
168
  `destructiveHint: true` or `readOnlyHint: false` keeps exactly what the
168
169
  downstream said and stays behind `call_destructive_tool`. A tool on neither
169
170
  maintained list arriving with `readOnlyHint: true` keeps that too, and stays
170
171
  callable from `execute_code`. Both are the downstream telling you this release's
171
172
  allowlist is stale, and on a name no release has reviewed its word is the only
172
173
  evidence there is. One narrow fail-closed exception applies to a name this
173
- release reviewed and filed destructive: a `create_refund` claiming
174
+ release reviewed and filed destructive: `stripe_api_write` claiming
174
175
  `readOnlyHint: true` is a downstream bug rather than news, and stays on the
175
176
  approval path.
176
177
 
@@ -57,7 +57,7 @@ exist so far:
57
57
  | --- | --- | --- |
58
58
  | **pre-template** | before 0.10.2 | no `connecta init` existed; hand-written, or copied from the retired `examples/node` |
59
59
  | **A** | 0.10.2 – 0.15.1 | `.env.example`, `.gitignore`, `AGENTS.md`, `CLAUDE.md`, `README.md`, `package.json`, `src/index.ts`, `tsconfig.json` |
60
- | **B** | 0.16.0 – 0.21.0 | adds `.dockerignore`, `Dockerfile`, `docker-compose.yml`, and `src/file-activity.ts`; `src/index.ts` grows the four commented operator blocks; `.env.example` ships `CONNECTA_TOKEN=` empty |
60
+ | **B** | 0.16.0 – 0.21.1 | adds `.dockerignore`, `Dockerfile`, `docker-compose.yml`, and `src/file-activity.ts`; `src/index.ts` grows the four commented operator blocks; `.env.example` ships `CONNECTA_TOKEN=` empty |
61
61
 
62
62
  Generation A is a decade in template years and identifying it precisely does
63
63
  not matter, because you are about to reconstruct it exactly rather than guess
@@ -106,7 +106,7 @@ know what to preserve, once to know what to re-verify at the end.
106
106
  ### Bump the pin and install
107
107
 
108
108
  ```sh
109
- npm pkg set dependencies.@zackbart/connecta=0.21.0
109
+ npm pkg set dependencies.@zackbart/connecta=0.21.1
110
110
  npm install
111
111
  ```
112
112
 
@@ -130,7 +130,7 @@ Generate the *current* template beside the base you already made, into the same
130
130
  `$SCRATCH`:
131
131
 
132
132
  ```sh
133
- (cd "$SCRATCH" && npx @zackbart/connecta@0.21.0 init current)
133
+ (cd "$SCRATCH" && npx @zackbart/connecta@0.21.1 init current)
134
134
  ```
135
135
 
136
136
  You now have a three-way merge with a real base: `$SCRATCH/base` is what this
@@ -186,7 +186,7 @@ A deployment older than 0.10.2 has no base to diff against. Do not try to
186
186
  manufacture one. Instead:
187
187
 
188
188
  1. `SCRATCH=$(mktemp -d)`, then
189
- `(cd "$SCRATCH" && npx @zackbart/connecta@0.21.0 init current)` — there is no
189
+ `(cd "$SCRATCH" && npx @zackbart/connecta@0.21.1 init current)` — there is no
190
190
  `base` leg here, only the current template to read from.
191
191
  2. Copy `$SCRATCH/current` into the deployment file by file, **skipping
192
192
  `src/index.ts`**.
@@ -207,9 +207,10 @@ first, so cross them bottom-up: start at the oldest one still above this
207
207
  deployment's pin and work back up the page, because each boundary assumes the
208
208
  older ones are already done.
209
209
 
210
- ### 0.20.0 → 0.21.0
210
+ ### 0.20.0 → 0.21.1
211
211
 
212
- This is additive for Node and existing Clerk deployments. The new Worker path
212
+ 0.21.1 adds no deployment migration beyond 0.21.0. The boundary is additive
213
+ for Node and existing Clerk deployments. The new Worker path
213
214
  uses Cloudflare Access identity directly and removes Clerk only after the edge
214
215
  cutover has been verified. An agent can perform every repository edit; a human
215
216
  must attach Access, choose its policy, create service credentials, and enable
@@ -217,7 +218,7 @@ Managed OAuth in the Cloudflare dashboard.
217
218
 
218
219
  For a Worker currently using Clerk, keep rollback live through the cutover:
219
220
 
220
- 1. Bump and install 0.21.0. Add the new provider **before** the existing Clerk
221
+ 1. Bump and install 0.21.1. Add the new provider **before** the existing Clerk
221
222
  provider, but remove nothing:
222
223
 
223
224
  ```ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zackbart/connecta",
3
- "version": "0.21.0",
3
+ "version": "0.21.1",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "description": "One MCP to rule them all — a single MCP endpoint aggregating many downstream connectors behind a code-first surface of seven meta-tools.",
@@ -15,7 +15,7 @@
15
15
  "typecheck": "tsc --noEmit"
16
16
  },
17
17
  "dependencies": {
18
- "@zackbart/connecta": "0.21.0",
18
+ "@zackbart/connecta": "0.21.1",
19
19
  "quickjs-emscripten": "0.32.0"
20
20
  },
21
21
  "devDependencies": {