@zackbart/connecta 0.28.0 → 0.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +961 -5
- package/README.md +62 -39
- package/bin/connecta.mjs +110 -139
- package/bin/meta-tool-names.d.mts +2 -0
- package/bin/meta-tool-names.mjs +9 -0
- package/bin/version.mjs +3 -0
- package/dist/access-tokens.js +53 -63
- package/dist/activity-request.js +8 -0
- package/dist/activity.d.ts +76 -42
- package/dist/activity.js +110 -42
- package/dist/auth/clerk-sdk/client.d.ts +65 -0
- package/dist/auth/clerk-sdk/client.js +5 -0
- package/dist/auth/clerk-sdk/generated.js +1845 -0
- package/dist/auth/clerk-transport.js +19 -0
- package/dist/auth/clerk.d.ts +17 -7
- package/dist/auth/clerk.js +189 -107
- package/dist/auth/cloudflare-access.js +25 -26
- package/dist/auth/downstream-client-metadata.d.ts +29 -0
- package/dist/auth/downstream-client-metadata.js +133 -0
- package/dist/auth/downstream-oauth.js +1632 -1509
- package/dist/auth/downstream-revocation.js +106 -0
- package/dist/auth/oauth-token-response.js +231 -0
- package/dist/auth/oauth-v2-migration.js +116 -0
- package/dist/auth/static-oauth.js +526 -0
- package/dist/auth-elicitation.js +283 -0
- package/dist/branding.d.ts +8 -16
- package/dist/branding.js +26 -59
- package/dist/byte-read-response.js +39 -0
- package/dist/call-admission.js +12 -16
- package/dist/catalog-cache.js +739 -0
- package/dist/catalog-drift.d.ts +50 -15
- package/dist/catalog-drift.js +365 -128
- package/dist/catalog-fingerprint.js +2 -4
- package/dist/catalog-freshness.js +13 -0
- package/dist/catalog-limits.js +2 -2
- package/dist/catalog-service.js +368 -224
- package/dist/catalog.js +43 -84
- package/dist/concurrency.js +3 -4
- package/dist/config-defaults.d.ts +39 -0
- package/dist/config-defaults.js +46 -0
- package/dist/config-schema.d.ts +181 -0
- package/dist/config-schema.js +435 -0
- package/dist/config-value-sources.js +102 -0
- package/dist/config.d.ts +631 -0
- package/dist/config.js +503 -0
- package/dist/connector-access.d.ts +1 -0
- package/dist/connector-access.js +13 -15
- package/dist/connector-caller.d.ts +8 -0
- package/dist/connector-caller.js +15 -6
- package/dist/connector-scope.js +1 -1
- package/dist/connectors/api-connector.d.ts +220 -0
- package/dist/connectors/api-connector.js +214 -0
- package/dist/connectors/api.d.ts +8 -71
- package/dist/connectors/api.js +13 -99
- package/dist/connectors/guarded-fetch.d.ts +144 -0
- package/dist/connectors/guarded-fetch.js +108 -25
- package/dist/connectors/negotiation-cache.js +46 -0
- package/dist/connectors/option-shapes.js +27 -0
- package/dist/connectors/remote-mcp.d.ts +30 -4
- package/dist/connectors/remote-mcp.js +1780 -351
- package/dist/connectors/resource-uri.js +335 -0
- package/dist/credential-contract.d.ts +10 -0
- package/dist/credential-rules.js +1 -3
- package/dist/credential-url.js +108 -0
- package/dist/credentials.d.ts +6 -1
- package/dist/credentials.js +27 -18
- package/dist/d1.d.ts +130 -0
- package/dist/d1.js +290 -0
- package/dist/describe-config.d.ts +165 -0
- package/dist/describe-config.js +315 -0
- package/dist/described.js +106 -0
- package/dist/downstream-input-context.js +119 -0
- package/dist/downstream-input.js +323 -0
- package/dist/errors.d.ts +97 -20
- package/dist/errors.js +158 -80
- package/dist/execute.js +453 -305
- package/dist/executor-admission.d.ts +1 -0
- package/dist/executor-admission.js +11 -15
- package/dist/executor-contract.d.ts +20 -0
- package/dist/executor-contract.js +48 -0
- package/dist/executor-result.js +24 -9
- package/dist/executors/quickjs-child.js +3 -4
- package/dist/executors/quickjs-runtime.js +147 -59
- package/dist/executors/quickjs.js +29 -35
- package/dist/favicon.js +1 -2
- package/dist/fix-prompt.js +1 -3
- package/dist/guest-runtime.js +188 -0
- package/dist/guest-types.d.ts +176 -0
- package/dist/guest-types.js +1 -0
- package/dist/html-security.js +24 -0
- package/dist/identity.js +1 -3
- package/dist/inbound-credential.js +52 -0
- package/dist/index.d.ts +25 -257
- package/dist/index.js +65 -478
- package/dist/invocation-auth.js +69 -0
- package/dist/invocation.js +230 -73
- package/dist/json-schema.d.ts +1 -1
- package/dist/mcp-client-context.js +35 -0
- package/dist/mcp-result.js +11 -7
- package/dist/meta-output.js +76 -0
- package/dist/meta-tool-names.d.ts +2 -0
- package/dist/meta-tool-names.js +3 -0
- package/dist/meta-tools.js +285 -209
- package/dist/module-contracts.d.ts +8 -23
- package/dist/node.d.ts +0 -2
- package/dist/node.js +2 -2
- package/dist/oauth-callback-outcome.js +1 -3
- package/dist/oauth-handoff.js +117 -0
- package/dist/oauth-partition.js +17 -0
- package/dist/oauth-sealing.js +20 -0
- package/dist/operator-record.d.ts +137 -0
- package/dist/operator-record.js +420 -0
- package/dist/operator-ui/assets.js +31 -0
- package/dist/operator-ui/contract.d.ts +72 -0
- package/dist/operator-ui/contract.js +1 -0
- package/dist/operator-ui/fix-prompts.d.ts +18 -0
- package/dist/operator-ui/generated.js +5 -4
- package/dist/operator-ui/model.d.ts +12 -87
- package/dist/operator-ui/model.js +2 -9
- package/dist/operator-ui/setup-commands.js +1 -3
- package/dist/operator-ui/view.d.ts +323 -0
- package/dist/operator-ui/view.js +62 -189
- package/dist/page-styles.js +2 -3
- package/dist/program-source.js +14 -2
- package/dist/{exempt-writes.js → program-writes.js} +55 -18
- package/dist/provider.d.ts +142 -0
- package/dist/provider.js +187 -0
- package/dist/providers/_shared/google/result-size.js +57 -0
- package/dist/providers/_shared/google/service-account.d.ts +58 -0
- package/dist/providers/_shared/google/service-account.js +500 -0
- package/dist/providers/_shared/google/workspace.d.ts +276 -0
- package/dist/providers/_shared/google/workspace.js +518 -0
- package/dist/providers/basecamp/index.d.ts +43 -0
- package/dist/providers/basecamp/index.js +997 -0
- package/dist/providers/basecamp/skill.generated.js +9 -0
- package/dist/providers/breeze/index.d.ts +34 -0
- package/dist/providers/breeze/index.js +1446 -0
- package/dist/providers/breeze/skill.generated.js +9 -0
- package/dist/providers/ccb/index.d.ts +103 -0
- package/dist/providers/ccb/index.js +1725 -0
- package/dist/providers/ccb/skill.generated.js +9 -0
- package/dist/providers/{cloudflare.d.ts → cloudflare/index.d.ts} +8 -7
- package/dist/providers/{cloudflare.js → cloudflare/index.js} +171 -738
- package/dist/providers/cloudflare/skill.generated.js +10 -0
- package/dist/providers/docs/index.d.ts +54 -0
- package/dist/providers/docs/index.js +1237 -0
- package/dist/providers/docs/skill.generated.js +9 -0
- package/dist/providers/drive/index.d.ts +53 -0
- package/dist/providers/drive/index.js +1523 -0
- package/dist/providers/drive/skill.generated.js +9 -0
- package/dist/providers/forms/index.d.ts +54 -0
- package/dist/providers/forms/index.js +1217 -0
- package/dist/providers/forms/skill.generated.js +11 -0
- package/dist/providers/github/auth.d.ts +32 -0
- package/dist/providers/github/auth.js +361 -0
- package/dist/providers/github/hosted.js +218 -0
- package/dist/providers/github/index.d.ts +13 -0
- package/dist/providers/github/index.js +140 -0
- package/dist/providers/github/key.js +100 -0
- package/dist/providers/github/rest.js +321 -0
- package/dist/providers/github/scope.d.ts +29 -0
- package/dist/providers/github/scope.js +124 -0
- package/dist/providers/github/skill.generated.js +8 -0
- package/dist/providers/gmail/index.d.ts +51 -0
- package/dist/providers/gmail/index.js +1436 -0
- package/dist/providers/gmail/skill.generated.js +9 -0
- package/dist/providers/{linear.d.ts → linear/index.d.ts} +11 -14
- package/dist/providers/linear/index.js +352 -0
- package/dist/providers/linear/skill.generated.js +8 -0
- package/dist/providers/{mixpanel.d.ts → mixpanel/index.d.ts} +5 -10
- package/dist/providers/mixpanel/index.js +416 -0
- package/dist/providers/mixpanel/skill.generated.js +9 -0
- package/dist/providers/{notion.d.ts → notion/index.d.ts} +8 -8
- package/dist/providers/{notion.js → notion/index.js} +226 -239
- package/dist/providers/notion/skill.generated.js +10 -0
- package/dist/providers/overflow/index.d.ts +60 -0
- package/dist/providers/overflow/index.js +1535 -0
- package/dist/providers/overflow/skill.generated.js +8 -0
- package/dist/providers/planning-center/index.d.ts +59 -0
- package/dist/providers/planning-center/index.js +2199 -0
- package/dist/providers/planning-center/skill.generated.js +10 -0
- package/dist/providers/{revenuecat.d.ts → revenuecat/index.d.ts} +5 -10
- package/dist/providers/revenuecat/index.js +557 -0
- package/dist/providers/revenuecat/skill.generated.js +11 -0
- package/dist/providers/sheets/index.d.ts +54 -0
- package/dist/providers/sheets/index.js +1237 -0
- package/dist/providers/sheets/skill.generated.js +10 -0
- package/dist/providers/slides/index.d.ts +53 -0
- package/dist/providers/slides/index.js +2645 -0
- package/dist/providers/slides/skill.generated.js +9 -0
- package/dist/providers/{stripe.d.ts → stripe/index.d.ts} +5 -12
- package/dist/providers/stripe/index.js +266 -0
- package/dist/providers/stripe/skill.generated.js +11 -0
- package/dist/providers/tithely/index.d.ts +49 -0
- package/dist/providers/tithely/index.js +1003 -0
- package/dist/providers/tithely/skill.generated.js +8 -0
- package/dist/providers/{vercel.d.ts → vercel/index.d.ts} +8 -8
- package/dist/providers/vercel/index.js +1038 -0
- package/dist/providers/vercel/mcp-ownership.js +212 -0
- package/dist/providers/vercel/skill.generated.js +11 -0
- package/dist/registry.d.ts +108 -171
- package/dist/registry.js +513 -925
- package/dist/request-state.js +21 -0
- package/dist/resource-read.js +100 -0
- package/dist/result-shapes.js +17 -49
- package/dist/retired-toolkits.js +1 -1
- package/dist/routes/access-tokens.js +3 -6
- package/dist/routes/activity-context.js +21 -0
- package/dist/routes/activity-disclosure.js +40 -0
- package/dist/routes/activity.js +59 -21
- package/dist/routes/actor-labels.js +3 -50
- package/dist/routes/connect.js +221 -0
- package/dist/routes/credentials.js +15 -27
- package/dist/routes/mcp.js +356 -130
- package/dist/routes/oauth-client-metadata.js +15 -0
- package/dist/routes/oauth-management.js +45 -107
- package/dist/routes/oauth.js +136 -57
- package/dist/routes/operator.js +3 -3
- package/dist/routes/shared.d.ts +25 -64
- package/dist/routes/shared.js +160 -80
- package/dist/routes/skills.js +30 -0
- package/dist/routes/ui-config.js +225 -0
- package/dist/routes/ui-data.js +40 -35
- package/dist/routes/ui.js +66 -56
- package/dist/runtime/admission.js +4 -2
- package/dist/runtime/call-admission.js +3 -1
- package/dist/runtime/connector-scope.js +1 -4
- package/dist/runtime/run.js +10 -39
- package/dist/runtime/services.js +12 -117
- package/dist/runtime/shared-read.js +1 -3
- package/dist/runtime/storage.js +8 -1
- package/dist/sent-secrets.d.ts +52 -0
- package/dist/sent-secrets.js +474 -0
- package/dist/server.js +28 -71
- package/dist/skills.js +406 -174
- package/dist/sqlite.d.ts +48 -0
- package/dist/sqlite.js +166 -0
- package/dist/storage/keys.js +428 -0
- package/dist/storage/memory.js +7 -0
- package/dist/storage/sql.d.ts +66 -0
- package/dist/storage/sql.js +534 -0
- package/dist/timeout.js +4 -2
- package/dist/tool-name.js +17 -0
- package/dist/tool-safety.d.ts +9 -35
- package/dist/tool-safety.js +20 -40
- package/dist/types.d.ts +320 -54
- package/dist/types.js +0 -1
- package/dist/ui.d.ts +7 -19
- package/dist/ui.js +76 -90
- package/dist/url-safety.js +3 -6
- package/dist/usage-guide.js +137 -0
- package/dist/validate.d.ts +7 -0
- package/dist/validate.js +309 -47
- package/dist/version.d.ts +1 -7
- package/dist/version.js +3 -7
- package/dist/worker.d.ts +11 -0
- package/dist/worker.js +434 -0
- package/documentation/architecture.md +665 -230
- package/documentation/auth.md +962 -458
- package/documentation/code-mode.md +501 -312
- package/documentation/meta-tools.md +449 -200
- package/documentation/operator-tests.md +93 -0
- package/documentation/provider-migration-0.29.md +60 -0
- package/examples/worker/AGENTS.md +34 -12
- package/examples/worker/README.md +286 -255
- package/examples/worker/kv-to-d1.wrangler.jsonc +26 -0
- package/examples/worker/scripts/copy-kv-to-d1.mjs +162 -0
- package/examples/worker/src/connecta.config.ts +151 -0
- package/examples/worker/src/index.ts +14 -197
- package/examples/worker/wrangler.jsonc +15 -35
- package/package.json +125 -35
- package/templates/node/.dockerignore +1 -2
- package/templates/node/.env.example +20 -21
- package/templates/node/AGENTS.md +21 -17
- package/templates/node/Dockerfile +3 -5
- package/templates/node/README.md +133 -58
- package/templates/node/docker-compose.yml +11 -12
- package/templates/node/package.json +4 -2
- package/templates/node/src/connecta.config.ts +119 -0
- package/templates/node/src/index.ts +9 -154
- package/templates/node/src/provision-token.ts +17 -0
- package/AGENTS.md +0 -170
- package/dist/artifacts/connector.d.ts +0 -58
- package/dist/artifacts/connector.js +0 -730
- package/dist/artifacts/document.js +0 -86
- package/dist/artifacts/guide.js +0 -140
- package/dist/artifacts/html-scan.js +0 -329
- package/dist/artifacts/json.js +0 -78
- package/dist/artifacts/kv-store.d.ts +0 -20
- package/dist/artifacts/kv-store.js +0 -140
- package/dist/artifacts/markdown.js +0 -478
- package/dist/artifacts/module.d.ts +0 -37
- package/dist/artifacts/module.js +0 -66
- package/dist/artifacts/operations.d.ts +0 -197
- package/dist/artifacts/operations.js +0 -1002
- package/dist/artifacts/refresh.d.ts +0 -55
- package/dist/artifacts/refresh.js +0 -236
- package/dist/artifacts/routes.js +0 -206
- package/dist/artifacts/types.d.ts +0 -214
- package/dist/artifacts/types.js +0 -22
- package/dist/artifacts/validate.d.ts +0 -62
- package/dist/artifacts/validate.js +0 -651
- package/dist/artifacts.d.ts +0 -6
- package/dist/artifacts.js +0 -9
- package/dist/auth/bearer.d.ts +0 -11
- package/dist/auth/bearer.js +0 -50
- package/dist/providers/linear.js +0 -217
- package/dist/providers/mixpanel.js +0 -247
- package/dist/providers/revenuecat.js +0 -317
- package/dist/providers/stripe.js +0 -253
- package/dist/providers/vercel.js +0 -1253
- package/dist/storage/file.d.ts +0 -15
- package/dist/storage/file.js +0 -455
- package/ethos.md +0 -93
- package/examples/worker/src/cloudflare-kv.ts +0 -43
- package/examples/worker/src/d1-activity-row.ts +0 -155
- package/examples/worker/src/d1-activity.ts +0 -147
- package/examples/worker/src/d1-storage.ts +0 -138
- package/examples/worker/src/r2-artifact-blobs.ts +0 -29
- package/templates/node/src/file-activity.ts +0 -182
|
@@ -1,44 +1,45 @@
|
|
|
1
1
|
# Meta-tools
|
|
2
2
|
|
|
3
3
|
Connecta keeps one small tool surface in model context and resolves downstream
|
|
4
|
-
tools behind it. `search_tools` finds addresses, the call tools enforce
|
|
5
|
-
|
|
4
|
+
tools behind it. `search_tools` finds addresses, the call tools enforce the
|
|
5
|
+
stored classification, `execute_code` runs programs under pool trust, and `connecta.result` inside programs
|
|
6
6
|
pages bounded results.
|
|
7
7
|
|
|
8
8
|
This guide is the contract an MCP client sees. The in-program `connecta.*` API
|
|
9
9
|
those tools imply belongs to [code mode](./code-mode.md); inbound identity and
|
|
10
10
|
credential administration belong to [auth](./auth.md).
|
|
11
11
|
|
|
12
|
-
## The
|
|
12
|
+
## The six tools
|
|
13
13
|
|
|
14
|
-
Every deployment requires an executor, so `tools/list` is exactly
|
|
15
|
-
configuration adds
|
|
14
|
+
Every deployment requires an executor, so `tools/list` is exactly six. No
|
|
15
|
+
configuration adds a seventh or removes one, so a client's cached tool list
|
|
16
16
|
never depends on the storage behind the deployment. There was an eighth,
|
|
17
17
|
`resume_execution`, while programs paused at writes; it left with pausing
|
|
18
18
|
([#672](https://github.com/zackbart/connecta/issues/672)). `execute_code`
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
|
27
|
-
|
|
|
28
|
-
| `
|
|
29
|
-
| `
|
|
30
|
-
| `
|
|
31
|
-
| `
|
|
32
|
-
| `
|
|
19
|
+
is annotated `readOnlyHint: true, destructiveHint: false` on a `read-only`
|
|
20
|
+
endpoint, and `readOnlyHint: false, destructiveHint: true` on a `trusted`
|
|
21
|
+
endpoint. Approval belongs to the host. Pool trust never changes connector
|
|
22
|
+
visibility or tool grants. Every meta-tool advertises `outputSchema` for its
|
|
23
|
+
structured content; raw downstream MCP content stays in `content`. Direct
|
|
24
|
+
results declare `format: "json" | "text"`, and value mode places the value in `data`.
|
|
25
|
+
|
|
26
|
+
| Tool | Arguments | Returns |
|
|
27
|
+
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
|
|
28
|
+
| `execute_code` | `code`, `diagnostics?` | `{ result?, error?, hostCalls }`, plus diagnostics when asked |
|
|
29
|
+
| `search_tools` | `query?`, `connector?`, `safety?`, `limit?`, `offset?`, `fullDescriptions?`, `includeSchemas?: "compact" \| "json" \| "typescript"` | `{ catalogErrors, tools, total, offset, limit, hasMore }`, plus `queryAnalysis` on a partial or failed search |
|
|
30
|
+
| `call_tool` | `address`, `args?`, `resultMode?: "mcp" \| "value"`, `timeoutMs?`, `diagnostics?` | the downstream result, bounded as [result representation](#result-representation) describes |
|
|
31
|
+
| `call_destructive_tool` | the same, plus `reason?` | the same |
|
|
32
|
+
| `authorize_connector` | `connector`, `force?` | the class-specific handoff in [authorization recovery](#authorization-recovery) |
|
|
33
|
+
| `skills` | `name?` | the listing when `name` is absent, that skill's markdown when it is present |
|
|
33
34
|
|
|
34
35
|
`limit` defaults to 8 and is capped at 100, as is one `connecta.describe` batch.
|
|
35
|
-
`
|
|
36
|
+
`connecta.result`'s `offset` is a whole number of bytes ≥ 0 defaulting to 0 and
|
|
36
37
|
`maxBytes` a whole number ≥ 1 that defaults to, and is clamped to, the inline
|
|
37
38
|
cap of the call that stashed the result — 24,000 bytes unless
|
|
38
39
|
`calls.maxResultBytes` or a per-connector override says otherwise
|
|
39
40
|
([why 24,000](#truncated-direct-call-results)). A value outside those domains is
|
|
40
41
|
an input error; a valid `maxBytes` above the cap is an upper bound, not an
|
|
41
|
-
error ([why](#paging-with-
|
|
42
|
+
error ([why](#paging-with-connectaresult)). `reason` is at most 500 characters of context for the host's human
|
|
42
43
|
approval view; Connecta neither treats it as authority nor sends it downstream,
|
|
43
44
|
and an empty or whitespace-only one reads as no reason rather than as grounds to
|
|
44
45
|
refuse a consequential call.
|
|
@@ -50,14 +51,11 @@ aggregates for a caller measuring a workflow: a `diagnostics` block from
|
|
|
50
51
|
and the measurements never contain program source, arguments, values, addresses,
|
|
51
52
|
credentials, logs, or raw error text.
|
|
52
53
|
|
|
53
|
-
Connecta's
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
its own policy. `call_destructive_tool` is where the prompt belongs: its
|
|
59
|
-
arguments are the exact write, so the human approves what will be sent rather
|
|
60
|
-
than a program that might send anything. Its `reason` is dropped before
|
|
54
|
+
Connecta's discovery tools carry read-only hints. `authorize_connector`
|
|
55
|
+
requests interactive authentication changes; `call_destructive_tool` sends
|
|
56
|
+
writes and is annotated destructive. `execute_code` reports the selected pool's
|
|
57
|
+
trust in its description and annotations. Its host may approve the whole
|
|
58
|
+
program on a trusted endpoint. `call_destructive_tool.reason` is dropped before
|
|
61
59
|
anything runs.
|
|
62
60
|
|
|
63
61
|
## Routing between the call surfaces
|
|
@@ -74,36 +72,25 @@ a small sample for inspection before continuing in another call, which avoids
|
|
|
74
72
|
repeated guesses at text formats and collection roots without restoring a
|
|
75
73
|
mandatory discovery-only round trip. A one-time write can return the only copy
|
|
76
74
|
of its result. Inspect and reduce the full value before a program returns, or
|
|
77
|
-
use a direct `call_destructive_tool` result and page it with `
|
|
75
|
+
use a direct `call_destructive_tool` result and page it with `connecta.result` after
|
|
78
76
|
the write runs once. A program return has no page handle; sampling or slicing
|
|
79
77
|
a write's output there can discard the answer.
|
|
80
78
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
there is. So "close the stale issues and post a summary" is one program to find
|
|
88
|
-
the issues and one `call_destructive_tool` per write; the program does the
|
|
89
|
-
reading, and the host sees every write it is asked about. Programs once paused
|
|
90
|
-
at a write for a resume call to approve and replay; hosts approve one tool call
|
|
91
|
-
at a time, so under always-allow that prompt approved nothing and cost a round
|
|
92
|
-
trip and a replay
|
|
93
|
-
([#672](https://github.com/zackbart/connecta/issues/672)). Top-level discovery
|
|
94
|
-
stays for catalog inspection and for finding the address of a write, and the
|
|
95
|
-
MCP instructions say so.
|
|
96
|
-
|
|
97
|
-
The three discovery routes use deliberately different envelopes. These are their
|
|
98
|
-
smallest successful one-tool shapes:
|
|
79
|
+
A `trusted` pool lets the same program discover and dispatch writes.
|
|
80
|
+
A `read-only` pool refuses writes before validation or dispatch with
|
|
81
|
+
`destructive_tool_requires_approval` and a `nextAction` naming
|
|
82
|
+
`call_destructive_tool` and the canonical address. Each write then uses its
|
|
83
|
+
own top-level call. Connecta never pauses, replays, or approves a program.
|
|
84
|
+
Top-level discovery remains available for catalog inspection and write routing.
|
|
99
85
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
86
|
+
Both search routes return the flat page specified under
|
|
87
|
+
[lexical discovery](#lexical-discovery), using the catalog's shared output schema.
|
|
88
|
+
Describe returns an ordered tool list without pagination. Optional row metadata
|
|
89
|
+
is omitted in this example:
|
|
103
90
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
{ tools: [{ name: "get_run", address: "ci.get_run", inputSchema:
|
|
91
|
+
```js
|
|
92
|
+
// connecta.describe defaults to JSON
|
|
93
|
+
{ tools: [{ name: "get_run", address: "ci.get_run", schemaFormat: "json", inputSchema: { type: "object" } }] }
|
|
107
94
|
```
|
|
108
95
|
|
|
109
96
|
Live connector probing is not a fourth: the operator pages and `/health` own it.
|
|
@@ -119,21 +106,20 @@ account and environment hints cannot eat the inventory. It reads only the
|
|
|
119
106
|
configured registry: no catalog load, no credential probe, no capability, and no
|
|
120
107
|
replacement for canonical discovery or addressing. Program search results carry
|
|
121
108
|
the same bounded `connectorTitle` per tool, so choosing an account or
|
|
122
|
-
environment costs no provider read.
|
|
123
|
-
of live access.
|
|
109
|
+
environment costs no provider read. The inventory does not probe live access.
|
|
124
110
|
|
|
125
111
|
Read-only lookup belongs in `connecta.search` inside the program; top-level
|
|
126
112
|
`search_tools` stays for explicit catalog inspection and approval-required
|
|
127
113
|
discovery. Both take the same arguments.
|
|
128
114
|
|
|
129
|
-
| Argument
|
|
130
|
-
|
|
|
131
|
-
| `query`
|
|
132
|
-
| `connector`
|
|
133
|
-
| `safety`
|
|
134
|
-
| `limit` / `offset` | page the ranked results; omit `limit` initially so the default eight-result page stays small
|
|
135
|
-
| `includeSchemas`
|
|
136
|
-
| `fullDescriptions` | unabridged tool purposes, at the obvious cost
|
|
115
|
+
| Argument | What it does |
|
|
116
|
+
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
117
|
+
| `query` | two to four action/object terms; empty or whitespace-only browses |
|
|
118
|
+
| `connector` | scopes to one id, loading that catalog alone instead of fanning out across every configured connector. Set it when the integration is obvious, omit it when the right one is genuinely ambiguous |
|
|
119
|
+
| `safety` | `"readOnly"` selects stored `read` verdicts; `"approvalRequired"` selects stored `write` verdicts; omitted or `"all"` selects both. Each row carries `classification: "read" \| "write"`. These legacy filter names do not describe host approval policy or pool trust. |
|
|
120
|
+
| `limit` / `offset` | page the ranked results; omit `limit` initially so the default eight-result page stays small |
|
|
121
|
+
| `includeSchemas` | `"compact"` for the rendered routing view, `"json"` for the exact schema, `"typescript"` for a function signature ([below](#typescript-signatures)) |
|
|
122
|
+
| `fullDescriptions` | unabridged tool purposes, at the obvious cost |
|
|
137
123
|
|
|
138
124
|
Neither `connector` nor `safety` grants authority or changes invocation
|
|
139
125
|
admission; they select what discovery shows and nothing else.
|
|
@@ -170,7 +156,7 @@ describe, when the exact constraints matter.
|
|
|
170
156
|
### TypeScript signatures
|
|
171
157
|
|
|
172
158
|
`includeSchemas: "typescript"` replaces both schema fields with one
|
|
173
|
-
`signature`: the function `connecta.call(address, args)
|
|
159
|
+
`signature`: the downstream function whose result is `(await connecta.call(address, args)).data`, written
|
|
174
160
|
as a TypeScript type because agents write code against types more reliably
|
|
175
161
|
than against JSON Schema ([executor](https://github.com/UsefulSoftwareCo/executor)'s
|
|
176
162
|
discovery made the same bet).
|
|
@@ -182,8 +168,8 @@ discovery made the same bet).
|
|
|
182
168
|
```
|
|
183
169
|
|
|
184
170
|
It is something to read, not something that runs: programs stay JavaScript,
|
|
185
|
-
and
|
|
186
|
-
([
|
|
171
|
+
and `execute_code` accepts no erasable TypeScript
|
|
172
|
+
([decision history](https://github.com/zackbart/connecta/blob/main/decisions/0001-ethos-verdict-table.md)). The output half is the provider's declared
|
|
187
173
|
schema, else an `S9` observation that opens with the
|
|
188
174
|
`/* observed, not declared */` marker and keeps the `outputSchemaSource`
|
|
189
175
|
field, else `unknown` — runtime evidence never reads as a contract, even when
|
|
@@ -210,7 +196,8 @@ declared schema exactly as they do for compact.
|
|
|
210
196
|
A connector may attach a deployment-owned guide as markdown, keeping the
|
|
211
197
|
original `usageGuide: string` configuration, or as
|
|
212
198
|
`{ content, summary?, required? }` — which registers no connector and creates no
|
|
213
|
-
shared runtime template.
|
|
199
|
+
shared runtime template. The registry prepends Agent Skills frontmatter to
|
|
200
|
+
`content` and preserves the guide body, including its whitespace.
|
|
214
201
|
`summary` is normalized and refuses construction over 120 characters; absent,
|
|
215
202
|
Connecta derives the same bounded fallback the skills listing uses from the
|
|
216
203
|
guide's first meaningful body paragraph. `required: true` is reserved for
|
|
@@ -221,11 +208,11 @@ Search and describe results carry a `guide: "connector:<id>"` pointer and a
|
|
|
221
208
|
`guideSummary`. A matching tool also carries `guideRequired: true` and
|
|
222
209
|
`guideRequiredReasons` when Connecta can prove review is necessary:
|
|
223
210
|
|
|
224
|
-
| Reason
|
|
225
|
-
|
|
|
226
|
-
| `connector_required` | the explicit `required: true` above
|
|
227
|
-
| `approval_required`
|
|
228
|
-
| `schema_truncated`
|
|
211
|
+
| Reason | Raised by | Survives exact schema expansion |
|
|
212
|
+
| -------------------- | ------------------------------------ | -------------------------------------------------------- |
|
|
213
|
+
| `connector_required` | the explicit `required: true` above | yes |
|
|
214
|
+
| `approval_required` | an unannotated or write-capable tool | yes |
|
|
215
|
+
| `schema_truncated` | a requested compact shape was capped | no — the describe that returns the exact shape clears it |
|
|
229
216
|
|
|
230
217
|
Describe reports whatever reasons remain in the same two fields. The boolean is
|
|
231
218
|
an instruction, not a server-side gate: nothing refuses the call, so the agent
|
|
@@ -253,29 +240,92 @@ guides stay scoped to the deployment that listed them even when two deployments
|
|
|
253
240
|
use identical content, and a deployment with no connector guides receives none of
|
|
254
241
|
the short conditional guide pointers in its tool definitions.
|
|
255
242
|
|
|
243
|
+
### Native Skills extension
|
|
244
|
+
|
|
245
|
+
Connecta declares `resources: {}` and `io.modelcontextprotocol/skills`, then
|
|
246
|
+
serves `skills/list`, `skills/get`, `resources/list` and `resources/read` from
|
|
247
|
+
the same registry as `skills` and `connecta.skill`. These methods return
|
|
248
|
+
`resultType: "complete"`, `ttlMs: 0` and `cacheScope: "private"`. Listing pages
|
|
249
|
+
contain at most five complete skills: usage first, required connector guides
|
|
250
|
+
next, other connector guides, downstream skills, then the investigation guide.
|
|
251
|
+
Subsequent pages use `cursor`/`nextCursor`. Local lookup works without listing.
|
|
252
|
+
|
|
253
|
+
The local document URIs are `skill://connecta/usage/SKILL.md` and
|
|
254
|
+
`skill://connecta/connectors/<slug>/SKILL.md`. A valid Agent Skills connector ID
|
|
255
|
+
is its slug; other IDs use `connector-` followed by a stable SHA-256 prefix.
|
|
256
|
+
The suffix makes each
|
|
257
|
+
document a valid Agent Skills file; the roots `skill://connecta/usage` and
|
|
258
|
+
`skill://connecta/connectors/<connector-id>` also resolve. Provider guides are
|
|
259
|
+
built from the generated `src/providers/*/SKILL.md` content with the existing
|
|
260
|
+
connection context and deployment instructions. Local manifests contain a
|
|
261
|
+
SHA-256 digest and UTF-8 byte size of the complete document. `usage` and
|
|
262
|
+
`investigate` remain compatibility names; `connector:<id>` remains a
|
|
263
|
+
one-release alias for its canonical document.
|
|
264
|
+
|
|
265
|
+
Set `remoteMcp(id, { url, skills: true })` to opt into downstream skills.
|
|
266
|
+
Each downstream URI maps under `skill://downstream/<connector-id>/` with an
|
|
267
|
+
encoded origin and the original path tree, preserving relative references.
|
|
268
|
+
The originating authority is repeated as a path segment so an authority-rooted
|
|
269
|
+
skill retains its directory name. All frontmatter fields, manifests and digests
|
|
270
|
+
are preserved except for the namespace prefix on URIs. Listing never retrieves
|
|
271
|
+
file bodies. Reads accept only files advertised in a complete manifest, or the
|
|
272
|
+
main file of a dynamic skill. Non-file URI shapes, query/fragment URIs and
|
|
273
|
+
traversal segments fail closed. No URI is fetched directly over HTTP.
|
|
274
|
+
|
|
275
|
+
Local guides follow connector visibility. Downstream skills require a
|
|
276
|
+
whole-connector grant in the caller's admitted pool; a tool-only grant cannot
|
|
277
|
+
authorize arbitrary files. Each list/read uses that caller's context and
|
|
278
|
+
credential ownership. Downstream skills use uncached `skills/list` and explicit
|
|
279
|
+
`resources/read` requests on the same request-scoped connection as ordinary
|
|
280
|
+
resource reads. The SDK's auth-partitioned resource inventories remain separate
|
|
281
|
+
from skill manifests; neither skill catalogs nor file bodies enter its response
|
|
282
|
+
cache. A failed or malformed opted-in listing fails the entire skills catalog,
|
|
283
|
+
with no partial cache. Known local guides remain readable during an outage.
|
|
284
|
+
|
|
285
|
+
Downstream files are proxied byte-exact, including CRLF and binary supporting
|
|
286
|
+
files, within 512 files and 16 MiB per skill. Catalog metadata is bounded to
|
|
287
|
+
1,024 entries and 8 MiB. The existing request-scoped agent boundary redacts
|
|
288
|
+
sent credential echoes, including a credential in a binary file's wire
|
|
289
|
+
encoding. Binary echoes remain valid base64; mixed UTF-8/JSON escapes and an
|
|
290
|
+
encoding that itself echoes a credential cause the file to be withheld as an
|
|
291
|
+
encoded placeholder. Unmatched binary bytes remain exact. That is the sole
|
|
292
|
+
exception to byte-exactness: digests remain the downstream's originals, so a host's integrity check rejects altered
|
|
293
|
+
content. Refreshing a manifest cannot make credential-bearing content safe to
|
|
294
|
+
load. URI and digest fields containing a sent credential are refused rather
|
|
295
|
+
than repaired, including credentials sent by later catalog or read operations.
|
|
296
|
+
Skill content never reaches operator logs, activity or status. Upward
|
|
297
|
+
`resources/read` is skill-only; downstream general resource reads are the
|
|
298
|
+
separate Phase 3 item 7 program API.
|
|
299
|
+
|
|
300
|
+
The wire contract follows the [Skills extension](https://modelcontextprotocol.io/extensions/skills/overview)
|
|
301
|
+
and [2026-07-28 Resources](https://modelcontextprotocol.io/specification/2026-07-28/server/resources).
|
|
302
|
+
|
|
256
303
|
## Result representation
|
|
257
304
|
|
|
258
305
|
For object results, `structuredContent` is the canonical full-fidelity value and
|
|
259
306
|
`content` carries the same complete value as compact JSON for clients that only
|
|
260
307
|
consume text. Keeping both follows MCP's backwards-compatibility guidance;
|
|
261
308
|
dropping the text copy waits on host-forwarding measurements showing supported
|
|
262
|
-
clients do not need it.
|
|
263
|
-
|
|
309
|
+
clients do not need it. Direct-call failures set `isError: true` and carry the
|
|
310
|
+
same `{ ok: false, error, durationMs, attempts }` envelope in both forms, whether
|
|
311
|
+
`resultMode` is omitted, `"mcp"`, or `"value"`. Plain-text guidance stays
|
|
312
|
+
text-only. A downstream MCP tool's successful native content blocks pass through
|
|
313
|
+
in MCP result mode.
|
|
264
314
|
When no text block exists and `structuredContent` is present, Connecta appends a
|
|
265
315
|
text block carrying its compact JSON and then applies the same content size
|
|
266
316
|
guard, which preserves structured-only results including `null`, arrays, and
|
|
267
317
|
scalars. An existing text mirror stays unchanged; Connecta adds no second copy.
|
|
268
318
|
Newly stashed JSON and downstream content envelopes use compact serialization,
|
|
269
|
-
and a lone text block stashes as its own text, so `
|
|
319
|
+
and a lone text block stashes as its own text, so `connecta.result` offsets and
|
|
270
320
|
totals describe exactly that text.
|
|
271
321
|
|
|
272
|
-
| Bound
|
|
273
|
-
|
|
|
274
|
-
| Stashed result TTL
|
|
275
|
-
| `results.maxStashBytes`
|
|
276
|
-
| `results.maxStashEntries`
|
|
277
|
-
| Top-level discovery result ceiling | 256,000 UTF-8 bytes
|
|
278
|
-
| Downstream MCP `isError` text
|
|
322
|
+
| Bound | Value |
|
|
323
|
+
| ---------------------------------- | ---------------------------------- |
|
|
324
|
+
| Stashed result TTL | 15 minutes |
|
|
325
|
+
| `results.maxStashBytes` | 8 MiB per shared storage ledger |
|
|
326
|
+
| `results.maxStashEntries` | 64 per shared storage ledger |
|
|
327
|
+
| Top-level discovery result ceiling | 256,000 UTF-8 bytes |
|
|
328
|
+
| Downstream MCP `isError` text | 512 UTF-8 bytes plus an `…` marker |
|
|
279
329
|
|
|
280
330
|
The discovery ceiling counts text, `structuredContent`, and JSON escaping
|
|
281
331
|
together, because measuring one copy would advertise half the bytes the adapter
|
|
@@ -286,25 +336,28 @@ subjects and pools; they count the stored ASCII paging envelope, base64 overhead
|
|
|
286
336
|
included, not only the result text. Capacity is reserved before each storage
|
|
287
337
|
write so concurrent requests cannot oversubscribe it, and a full stash refuses
|
|
288
338
|
new entries. A later attempt deletes expired entries before reusing their
|
|
289
|
-
capacity; a failed deletion keeps the charge. These bounds cover
|
|
290
|
-
|
|
291
|
-
|
|
339
|
+
capacity; a failed deletion keeps the charge. These bounds cover all processes and Worker isolates sharing the store.
|
|
340
|
+
Compare-and-set reserves each charge in one storage ledger before any chunk
|
|
341
|
+
is written; chunk TTLs cannot exceed the charge deadline.
|
|
292
342
|
|
|
293
343
|
Results belong to the authenticated subject whenever auth supplies a subject or
|
|
294
344
|
user id, independently of activity configuration, under the provider's namespace
|
|
295
345
|
when it has one and `connecta:auth:<provider kind>` otherwise. Keep subject ids
|
|
296
346
|
distinct within that namespace. An explicit principal is the fallback subject
|
|
297
347
|
when neither id is supplied, and open deployments and auth providers that supply
|
|
298
|
-
no identity share one partition.
|
|
348
|
+
no identity share one partition. Each new stash also binds the principal,
|
|
349
|
+
endpoint/pool, request origin, connector, tool, and classification. A page must
|
|
350
|
+
match those bindings and pass current auth, connector/tool grants, pool membership,
|
|
351
|
+
and trust checks. Old entries lacking bindings fail closed. A random UUID is a
|
|
352
|
+
handle, never an access grant.
|
|
299
353
|
|
|
300
354
|
New entries store UTF-8 bytes in a base64 envelope split across storage keys,
|
|
301
355
|
48 KiB of result text per chunk — widening past roughly 1.5 MB so no result
|
|
302
|
-
occupies more than 33 keys, because every chunk is also a write. `
|
|
356
|
+
occupies more than 33 keys, because every chunk is also a write. `connecta.result`
|
|
303
357
|
reads and decodes only the chunks a page covers plus a few boundary bytes, so
|
|
304
358
|
paging a 1.2 MB result costs the same per page as paging a 300 KB one; it
|
|
305
|
-
neither encodes nor reads the whole result per page.
|
|
306
|
-
single-key
|
|
307
|
-
also pays one full encoding. Offsets and `totalBytes` always describe the
|
|
359
|
+
neither encodes nor reads the whole result per page. Entries without the required identity and invocation bindings fail closed,
|
|
360
|
+
including pre-upgrade single-key envelopes and raw-text entries. Offsets and `totalBytes` always describe the
|
|
308
361
|
original UTF-8 text, not the envelope. A supplied offset inside a character
|
|
309
362
|
moves back to its start; page ends also align to character boundaries, and a
|
|
310
363
|
page smaller than one character widens just enough to make progress.
|
|
@@ -323,7 +376,7 @@ as one text block. Its first line is the truncation notice, one line of compact
|
|
|
323
376
|
JSON; everything after the first newline is the preview:
|
|
324
377
|
|
|
325
378
|
```text
|
|
326
|
-
{"truncated":true,"resultId":"…","totalBytes":161420,"hint":"This write already ran: do not call it again to see its result. Bytes 0-24000 of 161420 follow; page the rest with
|
|
379
|
+
{"truncated":true,"resultId":"…","totalBytes":161420,"hint":"This write already ran: do not call it again to see its result. Bytes 0-24000 of 161420 follow; page the rest with connecta.result using nextAction.","nextOffset":24000,"nextAction":{"tool":"execute_code","arguments":{"code":"async () => await connecta.result(\"…\", { offset: 24000 })"}}}
|
|
327
380
|
{"ts":"2026-09-16T21:31:11.759Z","actor":"sam.ortiz@example.com",…
|
|
328
381
|
```
|
|
329
382
|
|
|
@@ -344,8 +397,8 @@ three models re-ran a billable export three times trying to read its result.
|
|
|
344
397
|
The default cap sits under both lines with room to spare. Preview plus notice
|
|
345
398
|
stays under 25,000 bytes, which is under 50,000 characters for any text, because
|
|
346
399
|
a character is at least one UTF-8 byte, and under 25,000 tokens for any text,
|
|
347
|
-
because a token covers at least one byte. A `
|
|
348
|
-
cap, and 24,000 matches the program result boundary in
|
|
400
|
+
because a token covers at least one byte. A `connecta.result` page is bounded by the same
|
|
401
|
+
inline byte cap, and 24,000 matches the program result boundary in
|
|
349
402
|
[code mode](./code-mode.md). A deployment whose
|
|
350
403
|
clients take more can raise the cap, and one whose clients take less can lower
|
|
351
404
|
it, per connector if need be; a result between 24,000 and 50,000 bytes that
|
|
@@ -354,7 +407,7 @@ the notice whatever its threshold, since the notice is the first few hundred
|
|
|
354
407
|
characters. One that rejects outright — Claude Code with
|
|
355
408
|
`MAX_MCP_OUTPUT_TOKENS` set below 12,500 — needs a cap under twice its limit.
|
|
356
409
|
|
|
357
|
-
The preview is the head of what `
|
|
410
|
+
The preview is the head of what `connecta.result` pages, cut on a character
|
|
358
411
|
boundary, so `nextAction.arguments.offset` continues exactly where it stops. A
|
|
359
412
|
lone text block — including the one synthesized from `structuredContent` — is
|
|
360
413
|
measured, stashed, previewed, and paged as its text: wrapping it in a content
|
|
@@ -373,14 +426,14 @@ The approved write happened; repeating it to look again is how one export
|
|
|
373
426
|
becomes three. For an explicitly read-only call, repeating is the better route,
|
|
374
427
|
so the hint offers it first: to find something specific, repeat the read inside
|
|
375
428
|
`execute_code` with `connecta.call` and filter or search the result there; to
|
|
376
|
-
read it in full, page with `
|
|
429
|
+
read it in full, page with `connecta.result`. Inside a program the inline cap does
|
|
377
430
|
not apply to a host call's result, only to what the program returns (`L6` in
|
|
378
431
|
[code mode](./code-mode.md) bounds a host call far higher), so the reduction
|
|
379
432
|
sees the whole result at once. When the hint named paging alone, the eval's
|
|
380
433
|
weakest model read a 185 KB CI log in 24,000-byte pages, skipped the range
|
|
381
434
|
holding the real failure, and named the flaky test near the top; before the
|
|
382
435
|
notice was visible, it had reduced the log in a program and found the failure.
|
|
383
|
-
`nextAction`
|
|
436
|
+
When paging is available, `nextAction` is the page handle for either kind of call, because paging is
|
|
384
437
|
the one next step connecta can spell out exactly, while a reduction is a
|
|
385
438
|
program the agent has to write. `resultId` stays beside the exact `nextAction`,
|
|
386
439
|
so the handle is actionable without copying an identifier out of prose.
|
|
@@ -388,110 +441,269 @@ Program results and oversized discovery responses carry no such route: paging a
|
|
|
388
441
|
program's return value is a refused shape, because a program can shrink
|
|
389
442
|
anything before it returns.
|
|
390
443
|
|
|
391
|
-
### Paging with
|
|
444
|
+
### Paging with connecta.result
|
|
392
445
|
|
|
393
|
-
|
|
394
|
-
|
|
446
|
+
Paging is a guest operation, never another top-level tool. A direct call's
|
|
447
|
+
notice carries a `resultId`, `nextOffset`, and an executable `execute_code`
|
|
448
|
+
recovery action. Read and reduce the result in one program:
|
|
395
449
|
|
|
396
|
-
```
|
|
397
|
-
{
|
|
398
|
-
|
|
450
|
+
```js
|
|
451
|
+
async () => {
|
|
452
|
+
let text = "", offset = 0, page;
|
|
453
|
+
do {
|
|
454
|
+
page = await connecta.result("result-id", { offset, maxBytes: 8_000 });
|
|
455
|
+
text += page.text;
|
|
456
|
+
offset = page.nextOffset;
|
|
457
|
+
} while (page.hasMore);
|
|
458
|
+
return JSON.parse(text).items.map(item => item.id);
|
|
459
|
+
}
|
|
399
460
|
```
|
|
400
461
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
read
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
preview is cut short enough that its JSON escaping still fits. Entries stashed
|
|
419
|
-
before the cap was recorded page at the deployment cap.
|
|
420
|
-
|
|
421
|
-
A refused or failed stash write cannot undo a downstream success. Both call tools
|
|
422
|
-
then return the same layout with a paging-unavailable notice and no `resultId`
|
|
423
|
-
or paging action — the notice first, then the preview where one is usable, and
|
|
424
|
-
for a write the same warning not to repeat it. Activity records success, and
|
|
425
|
-
the operator logger receives a fixed warning naming the connector and tool
|
|
426
|
-
without storage error prose. For read-only work, reduce the result inside
|
|
427
|
-
`execute_code` — repeating an approved write is not a way to recover its output. Other result-processing failures use a fixed
|
|
428
|
-
`result_processing_failed` message and are never retryable.
|
|
462
|
+
A page is `{ resultId, offset, bytes, totalBytes, hasMore, nextOffset?,
|
|
463
|
+
format: "text", text }`. The page size is clamped to the original call's inline
|
|
464
|
+
cap, with UTF-8 alignment and forward progress. Reassemble inside the sandbox;
|
|
465
|
+
returning pages unchanged can hit the program result cap. The admitted subject
|
|
466
|
+
and principal, endpoint/pool, request origin, connector, and tool bindings must
|
|
467
|
+
match. The host rechecks current access and trust before returning each page; a
|
|
468
|
+
read-only endpoint cannot read a write stash. Caller arguments select no partition.
|
|
469
|
+
|
|
470
|
+
A write on a read-only endpoint returns an inline truncation notice and any
|
|
471
|
+
usable bounded preview. It says paging is unavailable and the write already
|
|
472
|
+
ran; it carries no result handle or recovery action and stores no unreachable
|
|
473
|
+
stash. Write paging remains available on trusted endpoints.
|
|
474
|
+
|
|
475
|
+
A refused stash write cannot undo a downstream success. Both call tools return
|
|
476
|
+
a paging-unavailable notice, without a handle or recovery action. A write's
|
|
477
|
+
notice still says it already ran. Activity records success; operator logs receive
|
|
478
|
+
a fixed warning without storage error prose. Never repeat a write to recover output.
|
|
429
479
|
|
|
430
480
|
## Lexical discovery
|
|
431
481
|
|
|
432
|
-
`search_tools`
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
482
|
+
`search_tools` and in-program `connecta.search` return the same flat discovery
|
|
483
|
+
page. Select tool rows from `page.tools`.
|
|
484
|
+
With the same schema format, schema-key option, and scoped registry, both paths
|
|
485
|
+
return identical data. Top-level search omits schemas unless requested; programs
|
|
486
|
+
default to JSON schemas and schema-key metadata.
|
|
487
|
+
|
|
488
|
+
```json
|
|
489
|
+
{
|
|
490
|
+
"catalogErrors": [],
|
|
491
|
+
"tools": [
|
|
492
|
+
{
|
|
493
|
+
"name": "get_issue",
|
|
494
|
+
"address": "linear.get_issue",
|
|
495
|
+
"connectorTitle": "Linear Production",
|
|
496
|
+
"classification": "read",
|
|
497
|
+
"schemaFormat": "json",
|
|
498
|
+
"inputSchema": { "type": "object", "properties": { "id": { "type": "string" } }, "required": ["id"] }
|
|
499
|
+
}
|
|
500
|
+
],
|
|
501
|
+
"total": 1,
|
|
502
|
+
"offset": 0,
|
|
503
|
+
"limit": 8,
|
|
504
|
+
"hasMore": false
|
|
505
|
+
}
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
`catalogErrors` is always present and serialized before tools. It contains
|
|
509
|
+
bounded typed failures from visible catalogs, including on an unscoped search
|
|
510
|
+
with healthy matches. Credential and permission failures appear first. OAuth
|
|
511
|
+
and operator credential failures carry the codes and `recovery`, `nextAction`,
|
|
512
|
+
and retry instructions described below. `provider_permission_denied` asks the
|
|
513
|
+
resource owner to grant access and carries no reconnect action. Discovery never
|
|
514
|
+
starts recovery. Failure messages use fixed text derived from the error code
|
|
515
|
+
and connector id, never connector-supplied error text. Other failures retain
|
|
516
|
+
`code`, `message`, `retryable`, and any
|
|
517
|
+
`retryAfterMs`. A scoped search also keeps its bounded failure subset under
|
|
518
|
+
`queryAnalysis.catalogError` for clients that already use it.
|
|
519
|
+
|
|
520
|
+
Tool rows carry the address, configured display title when present, guide and
|
|
521
|
+
guide summary when available, and stored classification. Requested schemas have
|
|
522
|
+
`schemaFormat: "json"` for JSON Schema values or `schemaFormat: "text"` for
|
|
523
|
+
compact schema strings and TypeScript signatures. Compact schemas are text;
|
|
524
|
+
`inputSchema.properties` is meaningful only in JSON mode. Pagination counts
|
|
525
|
+
tools across connectors: `nextOffset` is present only when another page remains.
|
|
526
|
+
|
|
527
|
+
Search tokenizes tool names and descriptions at punctuation and camel-case
|
|
528
|
+
boundaries. Whole-token matches and a small set of inflectional variants preserve
|
|
529
|
+
recall without admitting arbitrary mid-word substrings. Document frequency weights
|
|
530
|
+
rare domain terms above ubiquitous action terms. Exact tool names and canonical
|
|
531
|
+
addresses rank first, so `get_issue` beats `get_issue_status` even when a
|
|
532
|
+
connector is named `issue`. Exact configured connector IDs, full display titles,
|
|
533
|
+
and recognized service names rank next. Complete lexical matches then precede
|
|
534
|
+
partial matches, with score and catalog order breaking ties.
|
|
535
|
+
An exact connector ID or title query browses that connector's tools, even when
|
|
536
|
+
individual tool names or descriptions mention that identity. Connector identity
|
|
537
|
+
terms that never occur in its tools need not be repeated in every tool description.
|
|
538
|
+
|
|
539
|
+
An explicit unknown `connector` scope returns no tools and an `absence` record:
|
|
540
|
+
`{ service, message, configuredConnectors }`. The message says
|
|
541
|
+
`No connector for "X" is configured for this endpoint.` Unscoped queries naming
|
|
542
|
+
recognized services such as GitHub, Linear, Mixpanel, Supabase, or PostHog do the
|
|
543
|
+
same when no visible connector ID or title names that service. This service-name
|
|
544
|
+
vocabulary is query interpretation, not an inventory of configured providers.
|
|
545
|
+
For other service names, use the explicit `connector` scope. An unavailable
|
|
546
|
+
catalog is a catalog failure, never an absence. Absence records and catalog
|
|
547
|
+
errors use only the endpoint/pool and grant intersection; a connector hidden by
|
|
548
|
+
that intersection is indistinguishable from an unconfigured one.
|
|
549
|
+
|
|
550
|
+
If no tool covers every search term, wider any-term fallback remains available
|
|
551
|
+
for ordinary action/object searches and the page carries `matchMode: "partial"`.
|
|
552
|
+
A service absence suppresses that fallback, so `GitHub get issue` cannot return
|
|
553
|
+
Linear issues or Mixpanel/Supabase projects. Tool rows expose no scores or
|
|
554
|
+
per-result query coverage. `queryAnalysis` partitions at most eight terms of at
|
|
555
|
+
most 64 characters into `representedTerms`, `otherResultTerms`, and
|
|
556
|
+
`unmatchedTerms`, marking longer input `truncated`. Its guidance distinguishes
|
|
557
|
+
partial matches, unavailable catalogs, unknown scopes, and genuine no-match
|
|
558
|
+
results. A non-empty query with no ASCII lexical terms returns no tools with
|
|
559
|
+
bounded no-match analysis. An empty or whitespace-only query browses.
|
|
560
|
+
|
|
561
|
+
## Downstream input on direct calls
|
|
562
|
+
|
|
563
|
+
On MCP 2026-07-28, `call_tool` and `call_destructive_tool` relay a downstream
|
|
564
|
+
`input_required` through connecta's own `requestState`. This requires an
|
|
565
|
+
authenticated principal and a vault with `requestStateKey`, `seal`, and `open`.
|
|
566
|
+
The original request must be retried with identical arguments. Connecta
|
|
567
|
+
continues only the same connector and resolved address, after the normal
|
|
568
|
+
identity, pool, classification, schema, and admission checks.
|
|
569
|
+
|
|
570
|
+
The signed `createRequestStateCodec` envelope contains a version-2
|
|
571
|
+
`downstream` discriminator, connector id, and vault ciphertext. The encrypted
|
|
572
|
+
payload binds the principal, endpoint including its pool path, meta-tool,
|
|
573
|
+
submitted address and resolved target, arguments digest, round, original expiry,
|
|
574
|
+
and one-use nonce. It carries the opaque downstream state byte-exact, bounded
|
|
575
|
+
private state history from earlier rounds, and a map
|
|
576
|
+
from connecta's numbered `downstream/<connector>/<index>` keys to the original
|
|
577
|
+
downstream keys and elicitation modes. Neither the opaque state nor the original
|
|
578
|
+
keys appear in agent output. Each round consumes a TTL-bound storage CAS before
|
|
579
|
+
dispatch; tampering, expiry, changed arguments, cross-principal/pool reuse, and
|
|
580
|
+
concurrent or repeated consumption are refused.
|
|
581
|
+
|
|
582
|
+
Only well-formed form and URL elicitation declared by the client on that request
|
|
583
|
+
is forwarded. An empty `elicitation: {}` declaration means form support, as in
|
|
584
|
+
the spec. Capabilities are checked again on retry. Unknown response keys are
|
|
585
|
+
ignored; recognized bare responses are validated and renamed back before being
|
|
586
|
+
sent downstream. Accept, decline, and cancel all continue the pending downstream
|
|
587
|
+
call, so the downstream can finish or terminate it. URL acknowledgements and
|
|
588
|
+
decline/cancel carry only their action. Sampling and roots remain unsupported
|
|
589
|
+
under [#703](https://github.com/zackbart/connecta/issues/703).
|
|
590
|
+
|
|
591
|
+
URL elicitation retains the downstream-provided URL unchanged. It must be HTTPS,
|
|
592
|
+
have no URL userinfo or control/space characters, contain no credential known to
|
|
593
|
+
the sent-secret boundary, and remain byte-identical through agent redaction.
|
|
594
|
+
Connecta refuses unsafe URLs instead of rewriting them. Messages begin
|
|
595
|
+
with `Downstream <connector>:` so the host can display who supplied the prompt;
|
|
596
|
+
the host owns consent and browser navigation. Connecta never adds credentials
|
|
597
|
+
or follows the URL. Messages pass the ordinary agent-output redaction boundary.
|
|
598
|
+
A form is refused if that boundary would change its schema, including property
|
|
599
|
+
names, enum values, or annotations; the host never receives a rewritten answer
|
|
600
|
+
contract. Prompts, raw continuation results, discovery, and continuation-time
|
|
601
|
+
catalogs that echo any round's opaque state are refused before redaction, paging,
|
|
602
|
+
stashing, error shaping, schema observation, or cache publication and reuse.
|
|
603
|
+
This includes bounded percent-decoded and JSON-escaped views, encoded echoes,
|
|
604
|
+
short state, and serialized
|
|
605
|
+
numbers, booleans, and null. No prompt, state,
|
|
606
|
+
response, arguments, or raw error reaches activity, logs, or status.
|
|
607
|
+
|
|
608
|
+
Connecta's confidentiality guarantee covers its own handling and persistence of
|
|
609
|
+
`requestState`. Checks for state echoed in downstream content are defense in
|
|
610
|
+
depth; a downstream's deliberate disclosure of its own state is outside that
|
|
611
|
+
guarantee. Binary blobs are not decoded to look for echoes.
|
|
612
|
+
|
|
613
|
+
A write returning `input_required` has not completed its operation: the
|
|
614
|
+
[MRTR spec](https://modelcontextprotocol.io/specification/2026-07-28/basic/patterns/mrtr)
|
|
615
|
+
defines that result as awaiting input before completion. Sending the original
|
|
616
|
+
opaque state and input responses is a continuation, not an automatic replay.
|
|
617
|
+
The sealed arguments digest prevents using that continuation for fresh write
|
|
618
|
+
arguments. A timeout or other failure during a continuation leaves its nonce
|
|
619
|
+
spent, so it cannot authorize a second attempt. Write continuations stop at an
|
|
620
|
+
HTTP 401 or redirect before the SDK can refresh authorization or resend the call.
|
|
621
|
+
HTTP 403 scope escalation also remains disabled. Read continuations retain normal
|
|
622
|
+
OAuth refresh behavior.
|
|
623
|
+
|
|
624
|
+
Auth recovery and downstream input are distinct state variants, with only one
|
|
625
|
+
active in a round. An auth retry can reach downstream input within the same
|
|
626
|
+
three-prompt, ten-minute window. A downstream continuation that fails auth ends
|
|
627
|
+
with the ordinary failure; it does not replace its pending state with an auth
|
|
628
|
+
replay. Downstream payloads and input responses are capped at 64 KiB, with at
|
|
629
|
+
most 16 inputs and 256 characters per downstream key. The combined private
|
|
630
|
+
state history is also capped at 64 KiB. Sealed wire state is
|
|
631
|
+
capped at 128 KiB. `input_required_invalid`, `input_required_limit`,
|
|
632
|
+
`input_required_unsupported`, and `input_required_round_limit` are non-retryable
|
|
633
|
+
typed failures.
|
|
634
|
+
|
|
635
|
+
Programs and in-process meta-tools return `input_required_unsupported`, with a
|
|
636
|
+
`nextAction` naming the equivalent direct call and bounded original arguments.
|
|
637
|
+
Programs never receive downstream state or prompts, and never restart to
|
|
638
|
+
fulfill downstream input.
|
|
487
639
|
|
|
488
640
|
## Authorization recovery
|
|
489
641
|
|
|
490
|
-
|
|
642
|
+
On MCP 2026-07-28, a host declaring `elicitation.url` receives
|
|
643
|
+
`resultType: "input_required"` when an eligible call or program needs recoverable
|
|
644
|
+
connector authentication and the admitted identity may manage that connector.
|
|
645
|
+
Read-classified calls may re-run after a mid-handler auth failure only when
|
|
646
|
+
their classification came from a catalog accepted within its TTL. Stale
|
|
647
|
+
fallback catalogs cannot authorize post-entry recovery. A write may
|
|
648
|
+
elicit only when Connecta's own pre-invocation credential resolution
|
|
649
|
+
reports a missing grant, a missing credential slot, or required consent before
|
|
650
|
+
refresh. Its handler and transport have not been entered. Programs also require
|
|
651
|
+
that every entered call has a fresh read classification during this run.
|
|
652
|
+
The `connecta_auth` input request uses `elicitation/create`,
|
|
653
|
+
`mode: "url"`, fixed copy, and an identity-checked `/connect/<id>` link built
|
|
654
|
+
from configured `publicUrl`. OAuth consent stays in the browser; a credential
|
|
655
|
+
slot uses the authenticated operator UI. `authorize_connector` uses the same
|
|
656
|
+
flow for explicit connect and restart. There is no legacy shim.
|
|
657
|
+
|
|
658
|
+
The host echoes `requestState` and its bare `inputResponses.connecta_auth`
|
|
659
|
+
response on the original `tools/call`. Accept re-runs the original call; it
|
|
660
|
+
does not prove browser consent completed. Decline or cancel ends without
|
|
661
|
+
dispatch, with `auth_declined` or `auth_cancelled`. Three prompts are allowed
|
|
662
|
+
within one ten-minute retry window, then `auth_round_limit` ends the flow.
|
|
663
|
+
Each state can be consumed once; concurrent or repeated retries are refused
|
|
664
|
+
before dispatch. A Continue link from a pending restart requires that restart
|
|
665
|
+
to start successfully before the browser can consume it.
|
|
666
|
+
Host-owned invocation facts record the auth failure's origin and entry into
|
|
667
|
+
all calls, including each classification, catalog freshness and classification
|
|
668
|
+
digest. Raw fetches and custom connector transports cannot establish recovery
|
|
669
|
+
eligibility. Each accept retry rechecks all previously entered reads before
|
|
670
|
+
restarting a program or direct call. A write classification, changed digest, or
|
|
671
|
+
stale catalog returns `auth_replay_refused` and reconciliation guidance.
|
|
672
|
+
Each round also checks its own invocation facts. Normal stale-fallback calls
|
|
673
|
+
retain their existing behavior.
|
|
674
|
+
An auth failure after a write handler or transport was entered keeps its
|
|
675
|
+
ordinary error code,
|
|
676
|
+
`retryable: false`, `reconciliationRequired: true`, and manual `/connect` guidance
|
|
677
|
+
where available. The write may have partially run; reconcile its target before
|
|
678
|
+
retrying after connection. Handler-authored error fields cannot clear this guard.
|
|
679
|
+
|
|
680
|
+
State integrity, expiry, principal, endpoint, and tool failures produce the
|
|
681
|
+
SDK's JSON-RPC `-32602` with `data.reason: "invalid_request_state"` before the
|
|
682
|
+
handler runs. Changed arguments or code produce a typed `invalid_request_state`
|
|
683
|
+
tool failure before dispatch. Retry state grants no access; each request still
|
|
684
|
+
passes current identity, pool, connector visibility, and management checks.
|
|
685
|
+
Hosts without URL support keep the recovery envelope below, with a `/connect`
|
|
686
|
+
URL when this deployment can issue one. Without an interactive provider,
|
|
687
|
+
signing vault, or configured public URL, automatic elicitation is unavailable.
|
|
688
|
+
|
|
689
|
+
`downstream_oauth_required` means the connector needs an OAuth grant.
|
|
690
|
+
`auth_required` means its operator-managed credentials or configuration need
|
|
691
|
+
repair. Both carry the recovery envelope below. `provider_permission_denied`
|
|
692
|
+
means the provider refused a permission or scope; ask its resource owner or
|
|
693
|
+
administrator to grant access before retrying. It does not invite a reconnect.
|
|
694
|
+
|
|
695
|
+
A host rejected before MCP dispatch gets HTTP 401 or 403 with
|
|
696
|
+
`error.code: "host_auth_required"`, `recovery: "host_connection"`, and the auth
|
|
697
|
+
adapter's original `WWW-Authenticate` challenge. Custom streaming or non-JSON
|
|
698
|
+
responses keep their body and expose `Connecta-Error-Code` and
|
|
699
|
+
`Connecta-Recovery` headers instead. Repair the host's connecta
|
|
700
|
+
connection or endpoint grants. This cannot be fixed by `authorize_connector`.
|
|
701
|
+
|
|
702
|
+
An OAuth call failure uses this envelope:
|
|
491
703
|
|
|
492
704
|
```json
|
|
493
705
|
{
|
|
494
|
-
"code": "
|
|
706
|
+
"code": "downstream_oauth_required",
|
|
495
707
|
"message": "...",
|
|
496
708
|
"retryable": false,
|
|
497
709
|
"connector": "service",
|
|
@@ -510,7 +722,8 @@ Every typed `auth_required` call failure uses the same envelope:
|
|
|
510
722
|
`authorize_connector` only after this error. It returns the class-specific
|
|
511
723
|
handoff:
|
|
512
724
|
|
|
513
|
-
- `oauth`: an `authorizationUrl`
|
|
725
|
+
- `oauth`: an `authorizationUrl` to connecta's `/connect/<connector>?h=...` route
|
|
726
|
+
and instructions to sign in as the initiating user;
|
|
514
727
|
- `operator_config`: an `operatorUrl` to the mounted connection UI, plus the
|
|
515
728
|
declared credential label and field names/guidance; or
|
|
516
729
|
- `unavailable`: an honest deployment/configuration message.
|
|
@@ -520,12 +733,18 @@ The class follows what the connector declares, not how it was authored: a
|
|
|
520
733
|
and no OAuth flow, so it uses `operator_config` when both vault and UI are
|
|
521
734
|
configured. Without either it returns `unavailable`, never a dead UI link.
|
|
522
735
|
|
|
523
|
-
The tool accepts no secret. `force` applies
|
|
524
|
-
|
|
736
|
+
The tool accepts no secret and starts no downstream consent. `force` applies
|
|
737
|
+
only to OAuth and requests a restart when the verified browser opens the signed
|
|
738
|
+
link. That visit may discard the stored grant before restarting consent. Static credential values are written
|
|
525
739
|
only through the same-origin interactive-user credential route, and only for a
|
|
526
740
|
connector visible to that user with the relevant shared or personal management
|
|
527
|
-
permission; OAuth
|
|
528
|
-
|
|
741
|
+
permission; Issuing an OAuth link, `force` included, requires that permission too. The
|
|
742
|
+
`/connect` visit and callback both verify the same initiating user under Clerk or
|
|
743
|
+
Cloudflare Access, including for shared connectors. The URL expires after fifteen
|
|
744
|
+
minutes and carries no browser authentication. A signing credential vault is
|
|
745
|
+
required; deployments without either interactive provider return `unavailable`
|
|
746
|
+
with a clear configuration message. Status reads stay passive and never expose
|
|
747
|
+
a downstream authorization-server URL. These routes work without the UI. After OAuth
|
|
529
748
|
consent or a human update, retry the original operation; a static update is read
|
|
530
749
|
from the vault on the next call and needs no redeploy.
|
|
531
750
|
|
|
@@ -540,7 +759,7 @@ the same arguments when the miss happened inside `execute_code`, which has no
|
|
|
540
759
|
way to call a tool. `call_tool` reaching an unannotated, write-capable, or
|
|
541
760
|
destructive tool returns `nextAction` for `call_destructive_tool` with the
|
|
542
761
|
canonical address, and so does the same call inside a program, unless config
|
|
543
|
-
|
|
762
|
+
marks that pool trusted. Nothing is executed by these records.
|
|
544
763
|
|
|
545
764
|
`connecta.describe` keeps its failures inline instead, so one miss cannot
|
|
546
765
|
discard the other schemas; each failed entry carries a human `error`, typed
|
|
@@ -560,12 +779,12 @@ invented address once produced a 200 KB refusal against a 1 KB result cap. Every
|
|
|
560
779
|
caller-authored string a refusal repeats therefore gets 512 UTF-8 bytes, and
|
|
561
780
|
what happens over budget differs by field.
|
|
562
781
|
|
|
563
|
-
| Field
|
|
564
|
-
|
|
|
565
|
-
| `args` on `call_tool` and `connecta.call`
|
|
566
|
-
| the attempted address
|
|
567
|
-
| unknown `
|
|
568
|
-
| `search_tools.connector`
|
|
782
|
+
| Field | Over 512 UTF-8 bytes |
|
|
783
|
+
| ----------------------------------------------------------------------------- | ----------------------------------------------------------- |
|
|
784
|
+
| `args` on `call_tool` and `connecta.call` | dropped whole; `purpose` says to re-send what was just sent |
|
|
785
|
+
| the attempted address | clamped with a trailing `…` |
|
|
786
|
+
| unknown `connecta.result(id)`, `authorize_connector.connector`, `skills.name` | clamped the same way |
|
|
787
|
+
| `search_tools.connector` | rejected with `invalid_args` before catalog lookup |
|
|
569
788
|
|
|
570
789
|
Arguments go all or nothing because the agent already holds what it sent, and
|
|
571
790
|
half of it would describe a call nobody made. The address gets the opposite rule
|
|
@@ -601,3 +820,33 @@ the compact schema is needed, routed like any other miss: a program to
|
|
|
601
820
|
the listed arguments and reissue the original operation. Which keyword a finding
|
|
602
821
|
names, and what the local validator declines to evaluate, is
|
|
603
822
|
[code mode](./code-mode.md#errors)'s `E8`.
|
|
823
|
+
|
|
824
|
+
`repair` adds agent-only detail from that tool's published schema: accepted
|
|
825
|
+
keys, received JSON types, enum values, numeric/length/item bounds, and known
|
|
826
|
+
conditional requirements such as `dependentRequired` and `if`/`then`/`else`.
|
|
827
|
+
Its `example` is synthesized without submitted values and checked against the
|
|
828
|
+
same validator. Complex or unsatisfiable schemas get `exampleUnavailable`
|
|
829
|
+
rather than an invalid example. Synthesis detects recursive references and
|
|
830
|
+
shares a 128-node work budget. Alternative branches do not emit dependency
|
|
831
|
+
advice unless the branch condition is known. Repair detail has a 4 KiB budget; oversized
|
|
832
|
+
detail is withheld whole with `truncated: true`. Operator records still contain
|
|
833
|
+
only checked failure facts, never findings or examples.
|
|
834
|
+
|
|
835
|
+
Unknown-address errors list `configuredConnectors` from the current endpoint's
|
|
836
|
+
scoped registry, including an empty list when none are accessible. They never
|
|
837
|
+
list connectors from another pool or identity's grants.
|
|
838
|
+
|
|
839
|
+
A write that times out after dispatch returns `write_outcome_unknown` with
|
|
840
|
+
`retryable: false` and an agent-only `uncertainCall: { address, args }`. No write
|
|
841
|
+
is automatically replayed. Arguments over the 512-byte echo budget are omitted
|
|
842
|
+
whole with `argsOmitted: true`; use the exact arguments already sent when
|
|
843
|
+
checking the target. A timeout before dispatch remains `timeout`. Trusted
|
|
844
|
+
program write accounting keeps this detail even if the guest catches the
|
|
845
|
+
failure or returns early. Multiple uncertain writes use `uncertainCalls`,
|
|
846
|
+
bounded to ten calls with `uncertainCallsTruncated` when more exist.
|
|
847
|
+
|
|
848
|
+
Retryability comes from typed errors, HTTP status, registered OAuth error codes,
|
|
849
|
+
SDK timeout classes, and runtime network codes. Untyped prose is non-retryable:
|
|
850
|
+
"timeout", "temporarily unavailable", "rate limit", or "503" in a body, tool
|
|
851
|
+
name, or URL never changes the verdict. JSON-RPC `ProtocolError.data` is dropped
|
|
852
|
+
at the downstream boundary, even when the agent may see the error's message.
|