@zackbart/connecta 0.38.0 → 0.40.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.
Files changed (180) hide show
  1. package/CHANGELOG.md +91 -0
  2. package/README.md +3 -2
  3. package/bin/connecta.mjs +4 -8
  4. package/bin/version.mjs +1 -1
  5. package/dist/access-tokens.js +6 -4
  6. package/dist/agent-routes.js +231 -0
  7. package/dist/auth/downstream-oauth/consent.js +519 -0
  8. package/dist/auth/downstream-oauth/grant-store.js +439 -0
  9. package/dist/auth/downstream-oauth/refresh-coordinator.js +562 -0
  10. package/dist/auth/downstream-oauth/refresh-records.js +447 -0
  11. package/dist/auth/downstream-oauth/sdk-hooks.js +242 -0
  12. package/dist/auth/downstream-oauth.js +66 -2382
  13. package/dist/auth/native.js +37 -0
  14. package/dist/auth/oauth-grant.js +13 -0
  15. package/dist/auth/static-oauth.js +153 -131
  16. package/dist/auth-elicitation.js +7 -1
  17. package/dist/authorization-handoff.js +11 -5
  18. package/dist/catalog-cache.js +219 -59
  19. package/dist/catalog-policy.js +18 -0
  20. package/dist/catalog-service.js +284 -47
  21. package/dist/catalog.js +18 -2
  22. package/dist/config.d.ts +16 -11
  23. package/dist/config.js +9 -6
  24. package/dist/connector-caller.d.ts +1 -1
  25. package/dist/connector-health.js +59 -0
  26. package/dist/connector-status.js +117 -0
  27. package/dist/connectors/api-connector.d.ts +7 -2
  28. package/dist/connectors/api-connector.js +7 -4
  29. package/dist/connectors/negotiation-cache.js +22 -4
  30. package/dist/connectors/remote-mcp/call.js +164 -0
  31. package/dist/connectors/remote-mcp/catalog.js +278 -0
  32. package/dist/connectors/remote-mcp/config.js +263 -0
  33. package/dist/connectors/remote-mcp/connection.js +682 -0
  34. package/dist/connectors/remote-mcp/errors.js +488 -0
  35. package/dist/connectors/remote-mcp/oauth.js +473 -0
  36. package/dist/connectors/remote-mcp/resources.js +473 -0
  37. package/dist/connectors/remote-mcp/runtime.js +1 -0
  38. package/dist/connectors/remote-mcp/transport.js +555 -0
  39. package/dist/connectors/remote-mcp.js +62 -2863
  40. package/dist/credential-contract.d.ts +23 -0
  41. package/dist/credential-reads.js +17 -0
  42. package/dist/credential-verification.js +53 -0
  43. package/dist/credentials.d.ts +7 -0
  44. package/dist/credentials.js +60 -25
  45. package/dist/describe-config.d.ts +12 -2
  46. package/dist/describe-config.js +2 -0
  47. package/dist/discovery-health.js +199 -0
  48. package/dist/downstream-input.js +2 -0
  49. package/dist/errors.d.ts +55 -17
  50. package/dist/errors.js +95 -41
  51. package/dist/execute.js +152 -114
  52. package/dist/executor-result.js +3 -1
  53. package/dist/guest-functions.js +83 -0
  54. package/dist/guest-runtime.js +60 -19
  55. package/dist/guest-types.d.ts +19 -5
  56. package/dist/http/argument-problems.js +35 -0
  57. package/dist/http/errors.js +5 -4
  58. package/dist/http/fields.js +192 -13
  59. package/dist/http/hatch-response.js +73 -0
  60. package/dist/http/hatch.js +88 -23
  61. package/dist/http/oauth.js +3 -2
  62. package/dist/http/provider.js +32 -4
  63. package/dist/http/safety.js +8 -0
  64. package/dist/http/tools.js +44 -23
  65. package/dist/index.d.ts +1 -1
  66. package/dist/index.js +9 -2
  67. package/dist/invocation.js +26 -8
  68. package/dist/membership.d.ts +13 -5
  69. package/dist/membership.js +34 -2
  70. package/dist/meta-tools.js +54 -31
  71. package/dist/native-recovery.js +4 -16
  72. package/dist/native-tools.js +5 -2
  73. package/dist/oauth-sealing.js +10 -0
  74. package/dist/operation-vocabulary.js +135 -13
  75. package/dist/operator-record.d.ts +2 -2
  76. package/dist/operator-record.js +1 -0
  77. package/dist/operator-ui/contract.d.ts +10 -0
  78. package/dist/operator-ui/generated.js +2 -2
  79. package/dist/operator-ui/model.d.ts +22 -1
  80. package/dist/provider-call-facts.js +6 -2
  81. package/dist/providers/_shared/rest/operation-index.js +48 -50
  82. package/dist/providers/_shared/rest/value-safety.js +80 -0
  83. package/dist/providers/breeze/api.js +7 -1
  84. package/dist/providers/breeze/skill.generated.js +1 -1
  85. package/dist/providers/breeze/tools.js +4 -3
  86. package/dist/providers/ccb/api.js +2 -1
  87. package/dist/providers/ccb/index.js +5 -0
  88. package/dist/providers/ccb/skill.generated.js +1 -1
  89. package/dist/providers/cloudflare/api.js +8 -1
  90. package/dist/providers/cloudflare/skill.generated.js +1 -1
  91. package/dist/providers/docs/lib/schemas.js +24 -22
  92. package/dist/providers/docs/safety.js +2 -0
  93. package/dist/providers/docs/skill.generated.js +1 -1
  94. package/dist/providers/docs/tools.js +2 -4
  95. package/dist/providers/drive/api.js +1 -0
  96. package/dist/providers/drive/lib/contracts.js +8 -5
  97. package/dist/providers/drive/skill.generated.js +1 -1
  98. package/dist/providers/drive/tools.js +11 -16
  99. package/dist/providers/forms/api.js +1 -0
  100. package/dist/providers/forms/skill.generated.js +1 -1
  101. package/dist/providers/forms/tools.js +10 -7
  102. package/dist/providers/github/api.js +1 -0
  103. package/dist/providers/github/lib/discovery.js +1 -1
  104. package/dist/providers/github/skill.generated.js +1 -1
  105. package/dist/providers/github/tools.js +61 -17
  106. package/dist/providers/gmail/lib/schemas.js +60 -50
  107. package/dist/providers/gmail/skill.generated.js +1 -1
  108. package/dist/providers/gmail/tools.js +7 -5
  109. package/dist/providers/granola/index.js +2 -0
  110. package/dist/providers/granola/skill.generated.js +1 -1
  111. package/dist/providers/overflow/api.js +7 -1
  112. package/dist/providers/overflow/skill.generated.js +1 -1
  113. package/dist/providers/planning-center/api.js +3 -1
  114. package/dist/providers/planning-center/lib/constants.d.ts +1 -1
  115. package/dist/providers/planning-center/skill.generated.js +1 -1
  116. package/dist/providers/quickbooks/safety.js +80 -39
  117. package/dist/providers/quickbooks/skill.generated.js +1 -1
  118. package/dist/providers/sheets/api.js +1 -0
  119. package/dist/providers/sheets/skill.generated.js +1 -1
  120. package/dist/providers/sheets/tools.js +13 -14
  121. package/dist/providers/slides/skill.generated.js +1 -1
  122. package/dist/providers/slides/tools.js +15 -13
  123. package/dist/providers/stripe/skill.generated.js +1 -1
  124. package/dist/providers/tithely/api.js +3 -1
  125. package/dist/providers/tithely/skill.generated.js +1 -1
  126. package/dist/providers/vercel/api.js +1 -1
  127. package/dist/providers/vercel/skill.generated.js +1 -1
  128. package/dist/providers/vercel/tools.js +4 -3
  129. package/dist/registry.d.ts +10 -4
  130. package/dist/registry.js +41 -13
  131. package/dist/routes/credentials.js +129 -60
  132. package/dist/routes/dispatch.js +5 -1
  133. package/dist/routes/mcp.js +30 -14
  134. package/dist/routes/operator.js +2 -2
  135. package/dist/routes/shared.d.ts +6 -1
  136. package/dist/routes/shared.js +7 -1
  137. package/dist/routes/ui-config.js +2 -2
  138. package/dist/routes/ui-data.js +126 -20
  139. package/dist/routes/ui.js +16 -0
  140. package/dist/runtime/call.js +7 -2
  141. package/dist/runtime/native-storage.js +12 -0
  142. package/dist/runtime/request-reads.js +207 -0
  143. package/dist/runtime/request-scope.js +16 -0
  144. package/dist/runtime/storage.js +12 -0
  145. package/dist/skills.js +37 -20
  146. package/dist/storage/keys.js +53 -3
  147. package/dist/storage/memory.js +8 -2
  148. package/dist/storage/sql-native.js +53 -1
  149. package/dist/storage/sql.js +12 -2
  150. package/dist/storage-digest.js +32 -0
  151. package/dist/timeout.js +8 -0
  152. package/dist/types.d.ts +33 -0
  153. package/dist/usage-guide.js +16 -35
  154. package/dist/validate.d.ts +3 -0
  155. package/dist/validate.js +220 -158
  156. package/dist/version.d.ts +1 -1
  157. package/dist/version.js +1 -1
  158. package/dist/write-outcome.js +0 -3
  159. package/documentation/README.md +13 -13
  160. package/documentation/architecture.md +385 -20
  161. package/documentation/auth.md +233 -64
  162. package/documentation/code-mode.md +122 -39
  163. package/documentation/deploying.md +6 -3
  164. package/documentation/integrating.md +16 -2
  165. package/documentation/meta-tools.md +240 -49
  166. package/documentation/migration-0.33.md +5 -1
  167. package/documentation/migration-0.34.md +3 -1
  168. package/documentation/operator-tests.md +1 -1
  169. package/documentation/operator-ui.md +105 -12
  170. package/documentation/pool-membership-upgrade.md +44 -0
  171. package/documentation/providers.md +105 -0
  172. package/examples/worker/AGENTS.md +10 -10
  173. package/examples/worker/README.md +4 -3
  174. package/examples/worker/src/connecta.config.ts +1 -0
  175. package/guides/connecting-agents.md +2 -1
  176. package/guides/how-it-works.md +4 -2
  177. package/package.json +1 -1
  178. package/templates/node/AGENTS.md +13 -12
  179. package/templates/node/package.json +1 -1
  180. package/templates/node/src/connecta.config.ts +1 -0
@@ -49,7 +49,12 @@ write tools from `search_tools` results and describe, and refuses every write
49
49
  call. Connector `readOnly` applies the same restriction on every endpoint; effective read-only is endpoint OR connector. Neither setting changes connector visibility or read grants. Guides
50
50
  (`queryAnalysis.guideSummary`, `skills`, `connecta.skill`, skill
51
51
  `resources/read`) are documentation and may name tools the endpoint refuses. The four tools with structured-only success results
52
- advertise `outputSchema`. The two direct-call tools omit it because their default
52
+ advertise `outputSchema`. `search_tools`'s schema defines its typed failure,
53
+ including every authorization-handoff field, once under `$defs.failure`;
54
+ `catalogErrors[]` references it through `allOf` with `connector` required, and
55
+ `queryAnalysis.catalogError` references it directly. The schema declares no
56
+ `$schema`, and validators for drafts 4, 7, 2019-09 and 2020-12 accept the same
57
+ pages. The two direct-call tools omit it because their default
53
58
  mode returns native `content`. Default-mode successes declare
54
59
  `_meta["dev.connecta/format"]: "json" | "text"`; value mode places the value in
55
60
  `data` and declares `format` in its complete result envelope.
@@ -134,16 +139,25 @@ Live connector probing is not a fourth: the operator pages and `/health` own it.
134
139
 
135
140
  ## Discovery context
136
141
 
137
- The deployment-derived `execute_code` description carries a live connector
138
- inventory before any catalog search — registry order, each canonical id, and a
139
- distinct configured title, with no second name minted for programs. Titles
140
- normalize whitespace and cap at 48 UTF-8 bytes, the complete line caps at 256,
141
- entries stay whole, and a truncated line ends with the exact `+N more` count, so
142
- account and environment hints cannot eat the inventory. It reads only the
143
- configured registry: no catalog load, no credential probe, no capability, and no
144
- replacement for canonical discovery or addressing. Program search results carry
145
- the same bounded `connectorTitle` per tool, so choosing an account or
146
- environment costs no provider read. The inventory does not probe live access.
142
+ The deployment-derived `execute_code` description carries a connector
143
+ inventory before any catalog search — registry order and each canonical id,
144
+ with no second name minted for programs. An entry adds the configured title
145
+ only when it says more than the id: a title whose words the id already spells,
146
+ such as `Google Calendar` for `google_calendar`, is dropped. Titles normalize
147
+ whitespace and cap at 48 UTF-8 bytes. A connector with a guide says how to
148
+ fetch it: `read first: skills({name:"connector:<id>"})` for a required guide,
149
+ `guide: skills({name:"connector:<id>"})` otherwise. For example:
150
+ `Connectors: crm (Customer CRM; read first: skills({name:"connector:crm"})), tickets.`
151
+
152
+ The complete line caps at 1,024 UTF-8 bytes, which names every connector of a
153
+ typical deployment. Past the cap, detail degrades before names do: titles are
154
+ dropped first, then optional guide pointers. Only when bare ids and required
155
+ guide pointers still exceed it do whole entries give way, in registry order, to
156
+ an exact `+N more` count. The inventory reads only the configured registry: no
157
+ catalog load, no credential probe, no live status, no capability, and no
158
+ replacement for canonical discovery or addressing. Search pages carry the same
159
+ bounded title once per connector in `connectors[<id>].title`, so choosing an
160
+ account or environment costs no provider read.
147
161
 
148
162
  Read-only lookup belongs in `connecta.search` inside the program; top-level
149
163
  `search_tools` stays for explicit catalog inspection and approval-required
@@ -171,6 +185,56 @@ read/write filter. On `approvalRequired` searches the returned discovery tool
171
185
  is still a read. Hidden tools, missing grants and read-only restrictions remain
172
186
  in force. Browsing does not consult operation vocabulary.
173
187
 
188
+ When a matched operation's call is fully determined, the first page also
189
+ carries it in `readyCalls`, so a program can call it without operation search or
190
+ details:
191
+
192
+ ```json
193
+ {
194
+ "readyCalls": [
195
+ {
196
+ "address": "notes.notes_api_read",
197
+ "args": { "path": "/v1/notes" },
198
+ "classification": "read",
199
+ "summary": "List notes"
200
+ }
201
+ ]
202
+ }
203
+ ```
204
+
205
+ Pass `args` unchanged to `connecta.call(address, args)` or `call_tool`. An
206
+ operation is fully determined only when it is a reviewed read served by the
207
+ hatch's `_api_read` tool itself (no named tool), uses GET, the read tool's
208
+ default method, and declares no path template, required parameter or required
209
+ body. Anything needing an id, a method choice or an argument the agent must
210
+ fill in stays behind `_api_search` and `_api_details`. Ready calls pass the same
211
+ endpoint, connector read-only, safety, hidden-tool and grant checks as the
212
+ vocabulary match, through a visible read tool in the caller's view. They are
213
+ computed offline from the construction-time index, read no account data, and
214
+ start no authorization.
215
+
216
+ A ready call must also be what the query names. Each path segment, and the
217
+ operationId without its action and version words, is one whole resource name:
218
+ `event_destinations` is the name "event destination", never "event". Every
219
+ query word other than an action (`list`, `get`, `count`, `show`, `create`,
220
+ `update`, `delete` and their vocabulary aliases) must belong to a resource name
221
+ whose words the query states in order, with singular/plural normalization and
222
+ the provider's declared synonyms. Version segments such as `v1` never count, and
223
+ a summary may supply only actions. A query with no object word gets no ready
224
+ call. Ready calls are omitted entirely when the top result is an exact tool name
225
+ or address, or a complete match on an authored tool, not the hatch's own search
226
+ or read tool, whose name adds nothing to the query: each of its name words is an
227
+ action or a query word, up to plural/singular and declared synonyms. For
228
+ example, `list teams` returns `list_teams` and no ready call, even when other
229
+ operations mention teams in their summaries, while `list projects` still offers
230
+ `/v10/projects` beside `list_project_env_vars`, whose name adds `env` and `vars`.
231
+ Each hatch offers only its top-ranked operation: a last path segment naming the
232
+ resource first, then the fewest resource words the query did not ask for, then
233
+ the shortest path. A connector offers at most one ready call and a page at most
234
+ three, in connector order. Later pages carry none. A ready
235
+ call keeps its read tool's `guideRequired` and `guideRequiredReasons`, and its
236
+ connector appears in `connectors`.
237
+
174
238
  Vocabulary is bounded: queries at most 200 characters and eight terms; each
175
239
  hatch caches at most 8,192 rows and 2,097,152 characters, with at most 1,024
176
240
  characters per row and 128 query intersections. Longer queries and vocabulary
@@ -281,9 +345,11 @@ guide's first meaningful body paragraph. `required: true` is reserved for
281
345
  generic API wrappers and cross-operation conventions a complete downstream
282
346
  schema cannot express.
283
347
 
284
- Search and describe results carry a `guide: "connector:<id>"` pointer and a
285
- `guideSummary`. A matching tool also carries `guideRequired: true` and
286
- `guideRequiredReasons` when Connecta can prove review is necessary:
348
+ Describe results carry a `guide: "connector:<id>"` pointer and a
349
+ `guideSummary`; a search page carries both once per connector in
350
+ `connectors[<id>]`. A matching tool row or description also carries
351
+ `guideRequired: true` and `guideRequiredReasons` when Connecta can prove review
352
+ is necessary:
287
353
 
288
354
  | Reason | Raised by | Survives exact schema expansion |
289
355
  | -------------------- | ------------------------------------ | -------------------------------------------------------- |
@@ -297,8 +363,17 @@ is merely told to fetch the guide first, for any reason listed. Otherwise the
297
363
  bounded summary decides — connector-specific sequencing, units, pagination,
298
364
  aliases, and generic API conventions still need the guide when they affect the
299
365
  task, while a complete and unambiguous one-read schema proceeds directly. Guide
300
- lookup always uses an exact name returned by `skills({})`, search, or describe;
301
- callers never manufacture `connector:<id>` from an unmarked connector.
366
+ lookup uses an exact name returned by `skills({})`, search, describe, or the
367
+ `execute_code` inventory; callers never manufacture `connector:<id>` from an
368
+ unmarked connector. A bare connector id, such as `skills({ name: "crm" })` or
369
+ `connecta.skill("crm")`, also serves that connector's guide. Built-in skill
370
+ names stay reserved: `usage` and `investigate` always fetch the built-in skill,
371
+ even when a connector has that id, whose guide stays at `connector:usage` or
372
+ `connector:investigate`. A bare id naming a connector without a guide fails with
373
+ `Connector "<id>" has no usage guide.`; any other unknown name fails as an
374
+ unknown skill. Names containing `:`, including URIs, never fall back to a bare
375
+ id. MCP `skills/get` resolves names the same way; `resources/read` accepts only
376
+ document URIs.
302
377
 
303
378
  A connector-scoped lexical miss keeps that connector's guide metadata under
304
379
  `queryAnalysis`. This matters for generic wrappers whose broad tool name
@@ -307,12 +382,29 @@ disappearing with the zero-tool page.
307
382
 
308
383
  Two built-in skills are byte-identical across deployments. `usage` is fetched
309
384
  only for missing guidance or program repair, and owns program selection detail, examples, runtime
310
- differences, and repair guidance; `investigate` is on-demand guidance for
311
- purchase verification, experiment checks, and customer or deployment
312
- investigations — shared guidance, not a saved workflow and not a source of
313
- deployment-specific ids. The always-loaded instructions and tool definitions keep
385
+ differences, and repair guidance; `investigate` is domain-neutral on-demand
386
+ guidance for an investigation that spans several services — shared guidance,
387
+ not a saved workflow and not a source of deployment-specific ids. `skills`
388
+ lists it; the `execute_code` description does not advertise it. The always-loaded instructions and tool definitions keep
314
389
  route selection, the fail-closed boundary, and the minimum guest syntax, so a
315
390
  client that never fetches a skill can still write a valid first program.
391
+
392
+ The server instructions state the complete routing rule once. Some clients
393
+ drop server instructions, so each tool description stays sufficient for its own
394
+ correct use without restating that rule: `call_tool` names its scope (one
395
+ known-address read) and points other read work to `execute_code`;
396
+ `search_tools` names its scope (catalog inspection, or finding a write) and
397
+ points read work into a program; `execute_code` opens with the terse
398
+ three-route lead (`One known read: call_tool. One known write:
399
+ call_destructive_tool. Everything else: execute_code.`, or the read-only
400
+ two-route form). The `usage` skill points to those two sources instead of
401
+ repeating them.
402
+
403
+ Tool descriptions and output schemas carry deployment configuration only: the
404
+ connector inventory, budgets, the endpoint's read-only setting, and whether any
405
+ visible connector has a guide. No catalog outcome, call, authorization state,
406
+ or other live status reaches `tools/list` or the instructions, so the
407
+ always-loaded surface stays byte-stable for a client's prompt cache.
316
408
  The instructions are the same on every endpoint except one addition: at
317
409
  `/mcp/<pool>` and `/agent/<pool>`, a pool that sets a
318
410
  [`description`](./auth.md#pools) has it appended after `This endpoint: `, so
@@ -618,7 +710,7 @@ a fixed warning without storage error prose. Never repeat a write to recover out
618
710
  page. Select tool rows from `page.tools`.
619
711
  With the same schema format, schema-key option, and scoped registry, both paths
620
712
  return identical data. Top-level search omits schemas unless requested; programs
621
- default to JSON schemas and schema-key metadata.
713
+ default to TypeScript signatures and schema-key metadata.
622
714
 
623
715
  ```json
624
716
  {
@@ -627,12 +719,12 @@ default to JSON schemas and schema-key metadata.
627
719
  {
628
720
  "name": "get_ticket",
629
721
  "address": "tickets.get_ticket",
630
- "connectorTitle": "Tickets",
631
722
  "classification": "read",
632
723
  "schemaFormat": "json",
633
724
  "inputSchema": { "type": "object", "properties": { "id": { "type": "string" } }, "required": ["id"] }
634
725
  }
635
726
  ],
727
+ "connectors": { "tickets": { "title": "Tickets", "guide": "connector:tickets", "guideSummary": "Ticket ids and states." } },
636
728
  "total": 1,
637
729
  "offset": 0,
638
730
  "limit": 8,
@@ -652,8 +744,26 @@ and connector id, never connector-supplied error text. Other failures retain
652
744
  `retryAfterMs`. A scoped search also keeps its bounded failure subset under
653
745
  `queryAnalysis.catalogError` for clients that already use it.
654
746
 
655
- Tool rows carry the address, configured display title when present, guide and
656
- guide summary when available, and stored classification. Requested schemas have
747
+ An unscoped search gives each connector at most 5 seconds (or
748
+ `discovery.probeTimeoutMs` when shorter) and ends within a 9-second discovery
749
+ budget. A connector that recently timed out or failed slowly is skipped for up
750
+ to 60 seconds: its entry keeps the recorded code with `retryable: true`,
751
+ `retryAfterMs`, and the message `Connector "X" was skipped because its catalog
752
+ lookup failed recently (CODE). Search with connector "X" to try it now.` A
753
+ scoped search always probes. Records are kept per owner, admitted endpoint and
754
+ described connector configuration. A healthy connector whose catalog always
755
+ takes more than 5 seconds can stay out of unscoped search; search it with
756
+ `connector`, or let any longer-deadline operation warm its complete catalog.
757
+ See [Discovery health](./architecture.md#storage-credentials-and-connectors).
758
+
759
+ Tool rows carry the address, stored classification, and tool-specific
760
+ `guideRequired` and `guideRequiredReasons`. Facts shared by every row of one
761
+ connector appear once per page in `connectors`, keyed by the connector id that
762
+ prefixes each row's address: the configured display `title` when present and
763
+ `guide` and `guideSummary` when the connector has a guide. The map names only
764
+ connectors with a row or ready call on this page and is omitted when none has
765
+ such facts.
766
+ Requested schemas have
657
767
  `schemaFormat: "json"` for JSON Schema values or `schemaFormat: "text"` for
658
768
  compact schema strings and TypeScript signatures. Compact schemas are text;
659
769
  `inputSchema.properties` is meaningful only in JSON mode. Pagination counts
@@ -666,7 +776,19 @@ rare domain terms above ubiquitous action terms. Exact tool names and canonical
666
776
  addresses rank first, so `get_issue` beats `get_issue_status` even when a
667
777
  connector is named `issue`. Exact configured connector IDs, full display titles,
668
778
  and recognized service names rank next. Complete lexical matches then precede
669
- partial matches, with score and catalog order breaking ties.
779
+ partial matches. Within a tier, a query whose first word outside connector names
780
+ is `list`, `get`, `find`, `search`, `show`, `read`, `fetch`, or `count` ranks
781
+ read rows before write rows; writes stay on the page. Score and catalog order
782
+ break the remaining ties.
783
+
784
+ A maintained provider may declare `searchSynonyms`: groups of single lowercase
785
+ words its users and its vendor use for the same record, such as `household`
786
+ and `family` for Church Community Builder. A query word then matches that
787
+ provider's tools and operation vocabulary through any word in its group, as an
788
+ ordinary whole-token match ranked below the word itself. Synonyms never widen
789
+ another connector's matches. Church Community Builder declares
790
+ `person`/`individual` and `household`/`family`; Granola declares
791
+ `meeting`/`note`.
670
792
  An exact connector ID or title query browses that connector's tools, even when
671
793
  individual tool names or descriptions mention that identity. Connector identity
672
794
  terms that never occur in its tools need not be repeated in every tool description.
@@ -783,6 +905,16 @@ fulfill downstream input.
783
905
 
784
906
  ## Authorization recovery
785
907
 
908
+ Every native pool lists `authorize_connector`, including pools without code.
909
+ If a connector’s tools are missing, use its id from that tool’s granted-connector
910
+ list to request a typed handoff. Give the URL and instructions to the operator;
911
+ after repair the host must refresh its tool list before it can call the repaired
912
+ tools (the cache hint is 300 seconds). A host that keeps its first list needs a
913
+ reconnect or a new conversation; on a pool with `execute_code`, a program can call
914
+ them by address without one.
915
+ Listing never creates a handoff. Authorization accepts only connectors already
916
+ granted to this request; it cannot enable a connector or expand pool scope.
917
+
786
918
  On MCP 2026-07-28, a host declaring `elicitation.url` receives
787
919
  `resultType: "input_required"` when an eligible call or program needs recoverable
788
920
  connector authentication and the admitted identity may manage that connector.
@@ -1027,28 +1159,77 @@ A remote MCP tool's advertised `inputSchema` is checked in the shared invocation
1027
1159
  path before admission and provider dispatch, so a mismatch is the non-retryable
1028
1160
  `invalid_args` identically on `call_tool`, `call_destructive_tool`,
1029
1161
  generated-code failures, and rejected promises. The error names the connector and
1030
- operation and carries `validation.issues`: JSON Pointer `path`, schema-keyword
1031
- `code`, and expected shape, with submitted values never copied into a finding. At
1032
- most three are returned, and `validation.truncated` says when more exist — the
1033
- same three-item bound describe's nearby-address list uses.
1162
+ operation and carries one recovery envelope, `validation`:
1163
+
1164
+ ```json
1165
+ {
1166
+ "issues": [
1167
+ { "path": "/limit", "expected": "at least 5", "received": "4" },
1168
+ { "path": "/mode", "expected": "one of \"fast\", \"safe\"", "received": "string" },
1169
+ { "path": "/<key>", "expected": "one of the accepted keys: mode, limit" }
1170
+ ],
1171
+ "acceptedKeys": ["mode", "limit"],
1172
+ "example": { "mode": "fast", "limit": 5 }
1173
+ }
1174
+ ```
1175
+
1176
+ Every finding is listed, and the message repeats them, so one corrected call
1177
+ fixes them all.
1178
+
1179
+ A refusal contains only names and literals the published schema declares at
1180
+ non-sensitive positions, numbers allowed by the bound rule below, and fixed
1181
+ placeholder text. It never contains a submitted string or object key, in the
1182
+ message, a finding, `acceptedKeys` or the example. A position is sensitive when
1183
+ it or an ancestor is `writeOnly`; a named tool's input schema marks each request
1184
+ secret that way. API hatch findings name only the operation contract's
1185
+ properties and enum members, as `*_api_details` publishes them.
1186
+
1187
+ - `path` is a JSON Pointer naming declared properties and array indices. The
1188
+ first key the schema does not declare (a misspelled argument, a map key)
1189
+ reads `<key>` and ends the path, e.g. `/headers/<key>`.
1190
+ - `expected` states the constraint that failed, then every other constraint
1191
+ the position declares: bounds, property and item counts, `multipleOf`,
1192
+ `pattern`, `format`, `uniqueItems`, enum members, `dependentRequired`
1193
+ (`string (required with tags)`). A sensitive position never renders an enum,
1194
+ `const` or pattern literal. Each position gets one finding.
1195
+ - `received` is the submitted JSON type, `missing`, or, for a numeric bound at
1196
+ a non-sensitive position of a named tool, the submitted number.
1197
+
1198
+ At most eight findings are returned, each field clipped (path and expected 256
1199
+ characters, received 64), and `truncated: true` says something was omitted or
1200
+ clipped.
1201
+
1202
+ `example` is one valid call synthesized from the published schema and checked
1203
+ against the same validator. It never copies a submitted value, and a sensitive
1204
+ position never renders a schema literal (`enum`, `const`, `default`,
1205
+ `examples`). Complex or unsatisfiable schemas get `exampleUnavailable` instead.
1206
+ Synthesis detects recursive references and shares a 128-node work budget.
1207
+ Invocation uses only this schema example, never a connector's copy of the
1208
+ call, unless the connector states `exampleUnavailable`. API hatches
1209
+ (`*_api_read`, `*_api_write`) always do: their generic schema says nothing
1210
+ about an operation's arguments, so the reason points to the operation's
1211
+ `*_api_details`.
1212
+
1213
+ `acceptedKeys` names the tool's top-level arguments. `conditionalRequirements`
1214
+ lists known `dependentRequired` and `dependentSchemas` requirements by
1215
+ property name; `if`/`then`/`else` conditions are schema subtrees and are not
1216
+ rendered. The envelope has a 4 KiB budget:
1217
+ optional detail, then the example, then trailing findings are dropped whole,
1218
+ with `truncated: true`. A `repair` object a custom connector passes contributes
1219
+ its received types and schema facts. A custom connector's own findings must
1220
+ follow the same rule. Operator records contain only checked failure facts,
1221
+ never findings or examples.
1034
1222
 
1035
1223
  `nextAction` points to discovery scoped to the same connector and tool name when
1036
1224
  the compact schema is needed, routed like any other miss: a program to
1037
1225
  `connecta.search`, a top-level call to `search_tools`. `retry` says to correct
1038
- the listed arguments and reissue the original operation. Which keyword a finding
1039
- names, and what the local validator declines to evaluate, is
1040
- [code mode](./code-mode.md#errors)'s `E8`.
1041
-
1042
- `repair` adds agent-only detail from that tool's published schema: accepted
1043
- keys, received JSON types, enum values, numeric/length/item bounds, and known
1044
- conditional requirements such as `dependentRequired` and `if`/`then`/`else`.
1045
- Its `example` is synthesized without submitted values and checked against the
1046
- same validator. Complex or unsatisfiable schemas get `exampleUnavailable`
1047
- rather than an invalid example. Synthesis detects recursive references and
1048
- shares a 128-node work budget. Alternative branches do not emit dependency
1049
- advice unless the branch condition is known. Repair detail has a 4 KiB budget; oversized
1050
- detail is withheld whole with `truncated: true`. Operator records still contain
1051
- only checked failure facts, never findings or examples.
1226
+ the listed arguments and reissue the original operation. What the local
1227
+ validator declines to evaluate is [code mode](./code-mode.md#errors)'s `E8`.
1228
+
1229
+ Earlier releases returned `validation.issues[].code` (the schema keyword)
1230
+ and a separate `repair` object. Both are gone from responses; a custom
1231
+ connector may still pass `code` and `repair` to `ConnectorCallError`, which
1232
+ folds `repair` into `validation`.
1052
1233
 
1053
1234
  Unknown-address errors list `configuredConnectors` from the current endpoint's
1054
1235
  scoped registry, including an empty list when none are accessible. They never
@@ -1146,7 +1327,9 @@ its code and message for diagnostics but is `retryable: false` with
1146
1327
  a program's `writes.unknown`. An HTTP refusal of the call's own write stays
1147
1328
  known only under the refusal rules above and a complete ledger proving the
1148
1329
  refusal covers the whole call; its recovery advice and program accounting both
1149
- report failure. Partial or unknown ledgers remain conservative. An auth failure after entering a write with
1330
+ report failure. A `remoteMcp()` write answered with a 4xx (other than 401, 403,
1331
+ 408 or 429) whose body is not a JSON-RPC error is unknown, never a refusal: a
1332
+ gateway may have answered after the server acted. Partial or unknown ledgers remain conservative. An auth failure after entering a write with
1150
1333
  no call-owned dispatch reports an unknown outcome and requires reconciliation,
1151
1334
  including credential refusals, static-OAuth refresh failures, and `remoteMcp()`
1152
1335
  connect or initialize 401s before `tools/call`. A non-auth refusal before
@@ -1264,10 +1447,10 @@ pool's surface.
1264
1447
  | Each visible downstream tool | Named `<connector>__<tool>`; object input constraints and local references preserved; no `outputSchema`; `_meta["dev.connecta/address"]` is its address |
1265
1448
  | `execute_code` | Unless `executeCode: false`. Each downstream tool's description then ends with `Program address: <connector>.<tool>`, the address `connecta.call` takes |
1266
1449
  | `read_result` | Only with `executeCode: false`: `{ id, offset?, page?, maxBytes? }` pages a stashed result exactly as `connecta.result` does, with the same bindings and rechecks |
1450
+ | `authorize_connector` | Always; requests the existing typed authorization handoff for a granted connector |
1267
1451
  | `skills` | Always |
1268
1452
 
1269
- `search_tools`, `call_tool`, `call_destructive_tool`, and `authorize_connector`
1270
- are not listed. Auth failures still carry their handoff in the error envelope.
1453
+ `search_tools`, `call_tool`, and `call_destructive_tool` are not listed. Auth failures still carry their handoff in the error envelope.
1271
1454
 
1272
1455
  **Names.** A name is a pure function of the connector id and downstream tool
1273
1456
  name, so it survives catalog refreshes. It is `<connector>__<tool>` when the
@@ -1311,7 +1494,7 @@ window, a native `tools/list` carries a 300-second private cache hint, against
1311
1494
  an hour on meta endpoints. This hint does not guarantee that a host refreshes
1312
1495
  its cached annotations; the stale-approval race is accepted on writable pools.
1313
1496
 
1314
- **Listing.** `tools/list` is one page with no cursor (Eve 0.86 reads only the
1497
+ **Listing.** `tools/list` is one page with no cursor (Eve's MCP client reads only the
1315
1498
  first page). A pool listing more than 1,000 tools fails `tools/list` with a
1316
1499
  JSON-RPC error asking the operator to narrow the pool; nothing is silently
1317
1500
  dropped. A connector whose catalog cannot load is left out of that listing
@@ -1325,10 +1508,18 @@ reduced calls; write tools are absent and refused on a read-only endpoint;
1325
1508
  never repeat a write; page a truncated result as its notice says. A pool
1326
1509
  `description` is appended as on meta endpoints.
1327
1510
 
1328
- **Recovery.** Repair and validation fields retain the exact constraint details.
1511
+ **Recovery.** `authorize_connector` remains listed even when a catalog fails.
1512
+ Its description lists all granted connector ids independently of catalog health.
1513
+ Use it for a missing connector, then refresh the host tool list after repair.
1514
+ Endpoint instructions carry the same recovery rule for hosts that fetch them
1515
+ separately. A cached list retains the recovery tool; a refreshed list restores
1516
+ the repaired connector’s whole catalog.
1517
+
1518
+ Repair and validation fields retain the exact constraint details.
1329
1519
  Discovery `nextAction` points to the host's tool search (`host: "search"`), with
1330
1520
  only a `query` argument. Retry actions and retry text name the native tool,
1331
- never a meta wrapper. Auth actions carry `authorizationUrl` or `operatorUrl`;
1521
+ never a meta wrapper; a program on a native pool sees the same native wording
1522
+ in a failure it catches. An unknown name is reported as sent. Auth actions carry `authorizationUrl` or `operatorUrl`;
1332
1523
  give the returned URL and instructions to the user or operator. Capable modern
1333
1524
  clients may resume native auth and downstream form/URL input with the same
1334
1525
  wire name, arguments and returned `requestState`. Changed names, targets or
@@ -40,6 +40,10 @@ the sections in order, then [verify](#verify).
40
40
  | `DELETE /ui/credentials/<id>` on an empty slot answering 204 | 409 `{ "problem": "credential_required" }` |
41
41
  | The `agent_not_maintainer` denial reason | Removed; agents are refused at human endpoints before admission |
42
42
 
43
+ This guide records the 0.33 migration. Current versions require every pool to
44
+ list only people or only agents. If a 0.33 deployment combined them, follow
45
+ [Split mixed pools](./pool-membership-upgrade.md) as well.
46
+
43
47
  ## Maintainers and pool members
44
48
 
45
49
  0.32 combined an identity resolver, a top-level `grant`, and pool `grant`
@@ -349,4 +353,4 @@ pools: {
349
353
  absent: search finds none of their tools and a call fails
350
354
  `unknown_address`. The same holds in any pool without an owner, even one
351
355
  that lists a Workspace connector with a subject mapping.
352
- 6. Confirm each `<agent>-<user>` pool lists no other person in `members`.
356
+ 6. Confirm each `<agent>-<user>` pool lists only the agent in `members` (the current construction rule).
@@ -39,7 +39,9 @@ If an agent needs to act as Alice, put that access in her personal pool and set
39
39
  to use. Confirm the pool's tools and members before adding an owner. Follow
40
40
  [the agent pool layout](./auth.md#organizing-an-agents-pools) for the full
41
41
  configuration. People in the same pool, agents in owned pools and connectors
42
- with a fixed `subject` address keep their behavior.
42
+ with a fixed `subject` address keep their behavior. Current versions also
43
+ require each pool to list only people or only agents; see
44
+ [Split mixed pools](./pool-membership-upgrade.md).
43
45
 
44
46
  ## Optional settings and development tooling
45
47
 
@@ -24,7 +24,7 @@ committed through the deployment's own store, so the contract's `agents` and
24
24
  last seen are fixed. The restricted state is the member fixture from
25
25
  `test/fixtures/operator-contract-v2.ts`, and the endpoint and matrix variants
26
26
  use its maintainer fixture, which covers every runs-as kind and agent pools,
27
- with `test/fixtures/operator-console.ts` crowding the team pool so its avatar
27
+ with `test/fixtures/operator-console.ts` crowding the people-only team pool so its avatar
28
28
  stack collapses to "+3".
29
29
  Collections use their corresponding browser types. Real contract serialization,
30
30
  member projection and secret withholding are exercised through