@zackbart/connecta 0.16.0 → 0.17.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/AGENTS.md +12 -5
- package/CHANGELOG.md +289 -0
- package/README.md +6 -1
- package/dist/catalog-service.d.ts +4 -0
- package/dist/catalog-service.js +49 -5
- package/dist/catalog.d.ts +11 -0
- package/dist/catalog.js +134 -12
- package/dist/errors.d.ts +28 -2
- package/dist/errors.js +1 -0
- package/dist/execute.d.ts +5 -0
- package/dist/execute.js +229 -161
- package/dist/invocation.js +3 -1
- package/dist/meta-tools.d.ts +4 -0
- package/dist/meta-tools.js +46 -14
- package/dist/operator-ui/generated.d.ts +1 -1
- package/dist/operator-ui/generated.js +1 -1
- package/dist/operator-ui/model.d.ts +3 -1
- package/dist/providers/cloudflare.js +13 -25
- package/dist/providers/mixpanel.d.ts +3 -5
- package/dist/providers/mixpanel.js +73 -5
- package/dist/providers/stripe.d.ts +2 -2
- package/dist/providers/stripe.js +13 -11
- package/dist/registry.d.ts +32 -9
- package/dist/registry.js +217 -33
- package/dist/routes/mcp.js +6 -0
- package/dist/skills.d.ts +4 -0
- package/dist/skills.js +157 -18
- package/dist/types.d.ts +14 -2
- package/dist/ui.js +4 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/documentation/architecture.md +7 -4
- package/documentation/cloudflare.md +40 -8
- package/documentation/code-first-exploration.md +2 -2
- package/documentation/code-mode.md +45 -53
- package/documentation/connector-guides.md +24 -19
- package/documentation/connectors.md +13 -1
- package/documentation/meta-tools.md +33 -18
- package/documentation/mixpanel.md +20 -0
- package/documentation/notion.md +7 -2
- package/documentation/operations.md +74 -29
- package/documentation/operator-ui.md +12 -2
- package/documentation/provider-audit.md +4 -4
- package/documentation/provider-conventions.md +68 -19
- package/documentation/stripe.md +45 -14
- package/documentation/upgrading.md +478 -0
- package/ethos.md +4 -4
- package/examples/worker/README.md +13 -6
- package/package.json +7 -2
- package/templates/node/AGENTS.md +5 -0
- package/templates/node/package.json +1 -1
|
@@ -8,15 +8,27 @@ needs most.
|
|
|
8
8
|
|
|
9
9
|
`createConnecta(config)` returns `{ fetch, registry, close }`. `fetch` takes
|
|
10
10
|
the Workers `(request, env, ctx)` signature; passing `ctx` through is what lets
|
|
11
|
-
connecta hand deferred work
|
|
12
|
-
|
|
11
|
+
connecta hand deferred work to `ctx.waitUntil` instead of losing it when the
|
|
12
|
+
response returns. That work is best-effort activity writes and the bounded
|
|
13
|
+
refresh an agent catalog read already demanded while it served a complete stale
|
|
14
|
+
entry. Node's adapter tracks the same promises and drains them on shutdown.
|
|
13
15
|
|
|
14
16
|
An `executor` is required. A deployment without one throws at construction
|
|
15
17
|
rather than serving a smaller surface
|
|
16
18
|
([#273](https://github.com/zackbart/connecta/issues/273)): Node uses
|
|
17
19
|
`quickJsExecutor()` from `@zackbart/connecta/quickjs`, Workers use
|
|
18
20
|
`new DynamicWorkerExecutor({ loader: env.LOADER })` from
|
|
19
|
-
`@cloudflare/codemode`.
|
|
21
|
+
`@cloudflare/codemode`. The Worker executor must stay loader-only: `bindings`,
|
|
22
|
+
`modules`, and `globalOutbound` grant ambient guest authority.
|
|
23
|
+
|
|
24
|
+
Both executor packages are optional peers: they never install with connecta,
|
|
25
|
+
and a deployment installs the one its runtime needs. The manifest publishes the
|
|
26
|
+
range each release supports — `^0.32.0` for `quickjs-emscripten`,
|
|
27
|
+
`^0.4.4 || ^0.5.0` for `@cloudflare/codemode` — so npm answers the version
|
|
28
|
+
question at install time rather than leaving a deployment to discover the skew
|
|
29
|
+
when a program runs ([#376](https://github.com/zackbart/connecta/issues/376)).
|
|
30
|
+
The version this repository tests against is one the published range admits,
|
|
31
|
+
and `test/package-surface.test.ts` fails if the two ever drift apart.
|
|
20
32
|
|
|
21
33
|
There are exactly two deployment shapes.
|
|
22
34
|
[`templates/node/`](../templates/node/) is what `connecta init` copies — the
|
|
@@ -75,7 +87,7 @@ optional.
|
|
|
75
87
|
| `discovery.concurrency?` | 4 | connector catalogs/status probes in flight at once |
|
|
76
88
|
| `discovery.catalogTtlSeconds?` | 300 | fresh TTL for cached tool lists |
|
|
77
89
|
| `discovery.persistCatalog?` | true | persist serializable catalogs as a manifest plus revision-addressed chunks |
|
|
78
|
-
| `discovery.staleCatalogSeconds?` | 3600 | how long
|
|
90
|
+
| `discovery.staleCatalogSeconds?` | 3600 | how long a complete expired catalog stays usable for agent SWR and as a refresh-failure fallback |
|
|
79
91
|
| `discovery.probeTimeoutMs?` | 30_000 | per-connector deadline for catalog fan-out; a timed-out connector degrades alone. Not a tool-call deadline |
|
|
80
92
|
| `calls.defaultTimeoutMs?` | **unset (opt-in)** | deadline for calls that pass no `timeoutMs`. Bounds one attempt, so retries can still extend total duration |
|
|
81
93
|
| `calls.maxResultBytes?` | 50_000 | inline result cap before truncation and `get_result` paging; a connector may override it. Invalid values warn and fall back |
|
|
@@ -108,9 +120,13 @@ deployment repository
|
|
|
108
120
|
```
|
|
109
121
|
|
|
110
122
|
An upgrade is an intentional dependency change followed by a normal build.
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
123
|
+
Doing it to a deployment somebody else generated — reading its pin, diffing it
|
|
124
|
+
against the template generation it came from, and crossing the version
|
|
125
|
+
boundaries that break construction — is [upgrading](./upgrading.md), which is
|
|
126
|
+
written for the agent sitting inside that deployment rather than inside this
|
|
127
|
+
repository. Instances must not share KV namespaces, D1 databases, secrets, or
|
|
128
|
+
encryption keys. Keeping deployment configuration private is sensible even
|
|
129
|
+
though this package is public.
|
|
114
130
|
|
|
115
131
|
## Verification
|
|
116
132
|
|
|
@@ -118,7 +134,7 @@ package is public.
|
|
|
118
134
|
|
|
119
135
|
| Script | What it gates |
|
|
120
136
|
| --- | --- |
|
|
121
|
-
| `check:docs` | local Markdown targets and fragments
|
|
137
|
+
| `check:docs` | local Markdown targets and fragments — including the `github.com` and `raw.githubusercontent.com` URLs that point back into this repository — guide and ethos size caps, duplicate heading anchors, a resurrected `docs/`, stale manual references |
|
|
122
138
|
| `check:operator-ui` | the committed browser bundle matches its source, byte for byte |
|
|
123
139
|
| `check:lint` | Oxlint's correctness category only — style is authored, not enforced |
|
|
124
140
|
| `check:unused` | Knip's unused-export and dependency gate |
|
|
@@ -130,11 +146,38 @@ package is public.
|
|
|
130
146
|
`npm run release:check` adds `check:security` (`npm audit --omit=dev
|
|
131
147
|
--audit-level=moderate`) and `check:package`, and is what CI runs on every push
|
|
132
148
|
and pull request. `check:package` packs the tarball, asserts the required files
|
|
133
|
-
are in it and that no
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
149
|
+
are in it and that no unshippable path leaked in — including any
|
|
150
|
+
Cloudflare-named connector or storage path (`connectors/cloudflare`,
|
|
151
|
+
`storage/cloudflare`) anywhere in the artifact, `dist/` and `examples/` alike —
|
|
152
|
+
derives the shipped guide list from which guides still carry a stub marker,
|
|
153
|
+
hands the packed path list to `scripts/check-packed-links.mjs`, and then runs
|
|
154
|
+
`connecta init` and builds and runs the generated deployment's own container.
|
|
155
|
+
|
|
156
|
+
That last step enforces the packed-link policy, which is one sentence: **every
|
|
157
|
+
relative link in shipped Markdown must resolve to a path the tarball carries,
|
|
158
|
+
and a target that is repository-only is cited as an absolute
|
|
159
|
+
`https://github.com/zackbart/connecta/blob/main/...` URL** (the
|
|
160
|
+
`raw.githubusercontent.com` form for an image, which is how the README hero
|
|
161
|
+
still renders on npmjs.com). The tarball is built output, not a checkout: it
|
|
162
|
+
carries no `eval/`, `test/`, `scripts/`, or `assets/`, so a relative pointer
|
|
163
|
+
into any of them is a dead end for the reader who installed the package, and
|
|
164
|
+
the fix is never to ship those directories — that would undo the trim of
|
|
165
|
+
[#346](https://github.com/zackbart/connecta/issues/346). A repository URL keeps
|
|
166
|
+
the citation verifiable in both directions: an outside reader can follow it, and
|
|
167
|
+
`check:docs` resolves it back to the checkout and fails when the cited file
|
|
168
|
+
moves ([#378](https://github.com/zackbart/connecta/issues/378)). `CHANGELOG.md`
|
|
169
|
+
is exempt from both gates, because release notes quote the paths that existed
|
|
170
|
+
when they shipped.
|
|
171
|
+
|
|
172
|
+
The Worker example ships in the tarball, its Cloudflare KV and D1 adapters
|
|
173
|
+
included: it is the Workers starting template a consumer copies. That is not a
|
|
174
|
+
hole in the published surface, because nothing under `examples/` appears in the
|
|
175
|
+
`exports` map — every export target resolves into `dist/`, so those adapters
|
|
176
|
+
are reference source rather than an importable subpath. They also clear the
|
|
177
|
+
platform-specific gate above on their names (`cloudflare-kv.ts`,
|
|
178
|
+
`d1-activity.ts`) rather than by exemption: that gate is a blunt pattern over
|
|
179
|
+
the whole artifact, so an example file renamed into `storage/cloudflare` would
|
|
180
|
+
fail the pack even though nothing about the published surface had changed.
|
|
138
181
|
|
|
139
182
|
Two more runners are deliberately outside `check`:
|
|
140
183
|
|
|
@@ -181,7 +224,7 @@ in.
|
|
|
181
224
|
| `catalog.test.ts` | lexical ranking and the compact schema renderer — `const`, `allOf` beside siblings, `$ref`, the depth limit, per-schema caching, and 2020-12 keyword compatibility |
|
|
182
225
|
| `clerk.test.ts` | protected-resource metadata, the browser sign-in config, OAuth and session tokens, cached best-effort activity labels with their caps, the hand-applied `azp` rejection, and the `allowedDomains` allowlist including every lookalike that must not be repaired into a match |
|
|
183
226
|
| `cloudflare-provider.test.ts` | `cloudflare()` construction, tool surface, request building, projections, typed failures, and credential test |
|
|
184
|
-
| `cloudflare-registry.test.ts` | the same provider inside a real deployment: discovery, addressing, and admission through the registry |
|
|
227
|
+
| `cloudflare-registry.test.ts` | the same provider inside a real deployment: discovery including compact page bounds, addressing, and admission through the registry |
|
|
185
228
|
| `code-first-surface.test.ts` | the seven-tool surface itself — an executor required and both runtime configurations named, every removed option and removed top-level tool refused, and `connecta.ui` findable before an agent chooses catalog search |
|
|
186
229
|
| `codemode-compat.test.ts` | the `Executor` seam staying structurally compatible with `@cloudflare/codemode`'s `DynamicWorkerExecutor`, enforced by `tsc` |
|
|
187
230
|
| `config.test.ts` | the grouped `ConnectaConfig` boundary — each group forwarding to its internals, malformed admission bounds failing construction, and one complete migration error for legacy own-properties |
|
|
@@ -189,28 +232,28 @@ in.
|
|
|
189
232
|
| `d1-activity-example.test.ts` | the Worker example's deployment-owned D1 activity store: actor namespace round-trip, payload-free friction reconstructed from the persisted code, and agreement with the package's friction table |
|
|
190
233
|
| `downstream-oauth.test.ts` | `KvOAuthProvider` round-trips and races, `auth_required` versus `error`, `startAuth`/`finishAuth`, callback refusal equality, bounded diagnostics, and HTML escaping |
|
|
191
234
|
| `errors.test.ts` | `ConnectorCallError` codes, retryable defaults and overrides, `retryAfterMs` round-trip, typed-over-heuristic classification, `AbortError` as a retryable timeout, and framing errors |
|
|
192
|
-
| `execute.test.ts` | the code-mode host bridge: identifier sanitization, MCP-result unwrapping, sandbox provider construction, fail-closed filtering of destructive and unannotated tools, and MCP/code-mode invocation parity |
|
|
235
|
+
| `execute.test.ts` | the code-mode host bridge: identifier sanitization, MCP-result unwrapping, sandbox provider construction, authenticated thrown-failure framing, fail-closed filtering of destructive and unannotated tools, and MCP/code-mode invocation parity |
|
|
193
236
|
| `execute-emit.test.ts` | `connecta.emit` (M1–M10) — block validation, budgets, the provider, delivery after the result envelope on success only, and the defaults |
|
|
194
237
|
| `execute-ui.test.ts` | `connecta.ui` (U1–U9) — validation, multiplicity and budget, the provider, `_meta` delivery, and the Apps shell |
|
|
195
238
|
| `executor-admission.test.ts` | the portable bounded FIFO both pools use: active and queue ceilings, stable retryable overload, queue timeout, cancellation removal, idempotent release, shutdown |
|
|
196
239
|
| `guarded-fetch.test.ts` | the guarded transport — construction, request building, destination confinement, and response handling |
|
|
197
|
-
| `guest-api-contract.test.ts` | the
|
|
240
|
+
| `guest-api-contract.test.ts` | the shared guest contract on the Dynamic Worker, including caught call, discovery, utility, batch, and budget failure codes; plus the real authority boundary — local `data:` fetch, denied egress, unresolved DNS, empty environment paths, unavailable filesystem/HTTP builtins, and present runtime globals |
|
|
198
241
|
| `linear-provider.test.ts` / `linear-registry.test.ts` | the Linear proxy's construction, classification, and guide; then the same connector inside a real deployment |
|
|
199
|
-
| `meta-tools.test.ts` | the registry-backed meta-tools: bounded discovery with page and address maxima, concise and full descriptions, compact and JSON schemas, structured errors, `skills` and connector-guide selection, stored-credential drift, catalog-lookup health accounting, `fields` selection, truncation and `get_result` offset validation and character alignment, per-connector `maxResultBytes`, probe timeouts, and empty-query browse of an unavailable or unconfigured catalog |
|
|
200
|
-
| `mixpanel-provider.test.ts` / `mixpanel-registry.test.ts` | the Mixpanel proxy, then the same connector inside a real deployment |
|
|
242
|
+
| `meta-tools.test.ts` | the registry-backed meta-tools: bounded discovery with page and address maxima, concise and full descriptions, compact and JSON schemas with numeric and string constraints, structured errors, `skills` and connector-guide selection including paragraph-aware summaries and configured-summary construction bounds, stored-credential drift, catalog-lookup health accounting, `fields` selection including total and partial misses below nested arrays, truncation and `get_result` offset validation and character alignment, per-connector `maxResultBytes`, probe timeouts, and empty-query browse of an unavailable or unconfigured catalog |
|
|
243
|
+
| `mixpanel-provider.test.ts` / `mixpanel-registry.test.ts` | the Mixpanel proxy, its conditional-input guide and complete reviewed schema-digest manifest, then the same connector inside a real deployment |
|
|
201
244
|
| `notion-provider.test.ts` / `notion-registry.test.ts` | Notion's tool surface, request construction, lean projections, both pagination conventions, error mapping, and writes; then the connector in a real deployment |
|
|
202
245
|
| `operator-boundary.test.ts` | the operator row of the decisions table, after every mutation route: authentication material managed without moving a declared structure, and the one honest exception — a credential write making a remote catalog appear, which is discovery arriving, not an operator editing the deployment |
|
|
203
246
|
| `operator-store.test.ts` | `src/operator-ui/app/store.ts` against a fake browser: the Clerk listener, `gate()`, the generation fence, and the request path |
|
|
204
|
-
| `provider-conventions.test.ts` | the conventions a test can hold: hand-written providers refusing schemas they cannot enforce (H5), Cloudflare stating its second pagination convention in the schema (H10), and Notion saying it has no escape hatch (H14) |
|
|
205
|
-
| `registry.test.ts` | construction and id validation, startup
|
|
247
|
+
| `provider-conventions.test.ts` | the conventions a test can hold: hand-written providers refusing schemas they cannot enforce (H5), their compact discovery schemas staying complete (H7), Cloudflare stating its second pagination convention in the schema (H10), and Notion saying it has no escape hatch (H14) |
|
|
248
|
+
| `registry.test.ts` | construction and id validation, startup warnings, address resolution, catalog TTL/persistence/completeness, agent-only stale-while-revalidate with cross-request single-flight shared with blocking reads in both start orders, owned teardown, invalidation/fingerprint guards, blocking diagnostics, and broken-connector isolation |
|
|
206
249
|
| `remote-mcp.test.ts` | `remoteMcp()` against an in-process server through the `_transportFactory` seam: passthrough, downstream `isError`, Workers-safe output-schema validation, request-scoped client reuse and at-most-once scope close; plus the real transport's manual redirect policy, destination guard, credential containment, and downstream session termination |
|
|
207
250
|
| `remote-mcp-pagination.test.ts` | the `tools/list` cursor chain in both directions — exact cursor handoff, first-wins dedup, a failed later page rejecting rather than returning its prefix, the runaway backstops, the tool-metadata re-prime across pages, and paginated catalogs reaching the discovery path |
|
|
208
251
|
| `request-admission.test.ts` | `/mcp` bounded before auth, the stable 503 and `Retry-After`, health and operator responsiveness under saturation, payload-free counters, queued cancellation, shutdown rejection while active work drains, and the separate fallback code pool |
|
|
209
|
-
| `server.test.ts` | end-to-end `/mcp` (401 → initialize instructions → seven tools → usage skill → `call_tool`), the open routes, Clerk `.well-known` metadata with no network,
|
|
252
|
+
| `server.test.ts` | end-to-end `/mcp` (401 → initialize instructions → seven tools → usage skill → `call_tool`), the open routes, Clerk `.well-known` metadata with no network, an end-to-end code-mode run, and `waitUntil` reaching agent catalog reads through both `search_tools` and `execute_code` |
|
|
210
253
|
| `server-route-contracts.test.ts` | the route contracts `server.ts` must keep byte-identical: every built-in answered ahead of connector routes inside the security wrapper, open data-free shells with framing denied, per-route auth and same-origin requirements with exact 401/403/405 bodies, and OAuth `verifyState`-before-`finishAuth` ordering |
|
|
211
254
|
| `startup-warnings.test.ts` | every construction-time `logger.warn` and, as importantly, the conditions that must *not* trigger one: open mode with a credential or OAuth connector, `publicUrl` unset beside OAuth, dropped branding and `uiAuth` URLs, a missing `verifyState`, a credential test-hook mismatch, and an unusable `calls.maxResultBytes` |
|
|
212
|
-
| `stripe-provider.test.ts` / `stripe-registry.test.ts` | the Stripe proxy's endpoint modes
|
|
213
|
-
| `ui.test.ts` | the server shell and `/ui/*` routes and the app's pure state rules from `view.ts` — filtering, page routing and capability states, credential management, gated `/ui/data` with broken-connector isolation, and the URL safety gates |
|
|
255
|
+
| `stripe-provider.test.ts` / `stripe-registry.test.ts` | the Stripe proxy's endpoint modes, admission, multi-account OAuth guidance, and no-guess account selection; then the connector in a real deployment |
|
|
256
|
+
| `ui.test.ts` | the server shell and `/ui/*` routes and the app's pure state rules from `view.ts` — filtering, page routing and capability states, credential management, gated `/ui/data` with broken-connector isolation and registry-owned catalog-observation containment, and the URL safety gates |
|
|
214
257
|
| `validate.test.ts` | `validateToolInput()` — a returned (not thrown) `invalid_args` naming the path, `additionalProperties: false` enforcement, per-schema validator caching, and an unusable schema passed through with one warning |
|
|
215
258
|
|
|
216
259
|
### Node-bound (`NODE_ONLY_SUITES`)
|
|
@@ -220,14 +263,15 @@ justification for *not* re-running it in workerd, so "it was easier" is not one.
|
|
|
220
263
|
|
|
221
264
|
| Suite | Covers | Why Node |
|
|
222
265
|
| --- | --- | --- |
|
|
223
|
-
| `deployment-shapes.test.ts` | the Worker as the only example, one Node template that is also its own container, the same source running locally and in the container, the full operator surface in both, a template that cannot start on its own `.env.example`, a Worker README naming every optional peer its entrypoint imports, and the initializer's `.gitignore` staying in step | walks the template and example trees with Node filesystem APIs |
|
|
224
|
-
| `doc-links.test.ts` | the documentation checker itself — local file and fragment resolution, duplicate heading slugs, fenced-code exclusion, and useful failures | spawns the Node checker against filesystem fixtures |
|
|
266
|
+
| `deployment-shapes.test.ts` | the Worker as the only example with a loader-only sandbox, one Node template that is also its own container, the same source running locally and in the container, the full operator surface in both, a template that cannot start on its own `.env.example`, a Worker README naming every optional peer its entrypoint imports, and the initializer's `.gitignore` staying in step | walks the template and example trees with Node filesystem APIs |
|
|
267
|
+
| `doc-links.test.ts` | the documentation checker itself — local file and fragment resolution, repository URLs resolved back to the checkout, duplicate heading slugs, fenced-code exclusion, and useful failures | spawns the Node checker against filesystem fixtures |
|
|
225
268
|
| `doctor-cli.test.ts` | `connecta doctor`'s executor line end to end — the sandbox the deployment reports is the one named, an unidentifiable executor gets an executor-neutral line, and a hostile name is bounded and stripped before it reaches a terminal | spawns the CLI against a Node HTTP deployment over real sockets |
|
|
226
|
-
| `drift-check.test.ts` | the maintainer drift checker — recorded touched endpoints, a quiet revision bump, clear failures for an unavailable spec/manifest/credential, `$ref` traversal, and one well-formed row per endpoint | spawns the Node checker against filesystem fixtures |
|
|
269
|
+
| `drift-check.test.ts` | the maintainer drift checker — hosted-provider credential framing, recorded touched endpoints, a quiet revision bump, clear failures for an unavailable spec/manifest/credential, `$ref` traversal, and one well-formed row per endpoint | spawns the Node checker against filesystem fixtures |
|
|
227
270
|
| `file-storage.test.ts` | `fileStorage()` across instances, logical TTL plus physical pruning without clobbering a newer value, and corrupt-file quarantine | exercises the Node filesystem storage adapter |
|
|
228
|
-
| `guest-api-contract-quickjs.test.ts` | the shared guest-contract cases on the real QuickJS executor | runs the contract cases on the Node QuickJS executor |
|
|
271
|
+
| `guest-api-contract-quickjs.test.ts` | the shared guest-contract cases on the real QuickJS executor, including identical caught failure codes, its exact absent globals, and blocked runtime imports | runs the contract cases on the Node QuickJS executor |
|
|
229
272
|
| `node.test.ts` | the `listen()` adapter propagating an HTTP client disconnect through the Web `Request` and the MCP handler into a program's connector call, releasing both admission permits | exercises the Node HTTP adapter over real TCP sockets |
|
|
230
|
-
| `
|
|
273
|
+
| `packed-links.test.ts` | the packed-link gate itself — shipped targets and repository URLs accepted, relative links into unshipped paths and directories rejected with the citation to write instead, reference definitions seen, fenced examples ignored, the changelog exempt | spawns the Node packed-link gate against filesystem fixtures |
|
|
274
|
+
| `package-surface.test.ts` | the published boundary — built output shipped, the `exports` map carrying exactly the documented subpaths plus `./package.json`, only generic factories, platform storage kept in examples, Clerk and QuickJS behind optional subpaths, every provider independently importable, and the Cloudflare provider free of bare specifiers | walks the package tree with Node filesystem APIs |
|
|
231
275
|
| `purity.test.ts` | the import-graph guardrail ([architecture](./architecture.md#import-graph-purity)) — the core stays Workers-clean | walks the source import graph with Node filesystem APIs |
|
|
232
276
|
| `quickjs-child-entry.test.ts` | a missing QuickJS child entry failing before `fork()`, with the expected path and the bundler-externalization constraint | mocks Node child-process and filesystem APIs |
|
|
233
277
|
| `quickjs-child-stderr.test.ts` | abnormal child exits retaining only an 8 KiB stderr tail, included in the parent-side diagnostic | mocks Node child-process streams |
|
|
@@ -235,13 +279,14 @@ justification for *not* re-running it in workerd, so "it was easier" is not one.
|
|
|
235
279
|
| `quickjs-log-limits.test.ts` | bounded `console.*` capture — per-entry cut, cumulative character and transport budgets, escape-heavy floods preserving the guest result | runs the Node QuickJS child-process executor |
|
|
236
280
|
| `suite-partition.test.ts` | this partition, including itself: every `*.test.ts` in exactly one list, stale entries and empty reasons refused | walks the test directory to guard the partition |
|
|
237
281
|
| `template-file-activity.test.ts` | the Node template's own activity store — persistence across restart, torn-line repair, newest-first paging, and compaction past the slack window | runs it against real files |
|
|
282
|
+
| `upgrade-guide.test.ts` | the [upgrade guide](./upgrading.md)'s claims about somebody else's deployment — the generated file inventory, the seven tool names doctor demands, version boundaries that actually shipped, a bump target that is this release, and the three places a reader finds it | reads the guide, the template tree, and the CLI with Node filesystem APIs |
|
|
238
283
|
| `version.test.ts` | `CONNECTA_VERSION` matching `package.json` | reads `package.json` with Node filesystem APIs |
|
|
239
284
|
|
|
240
285
|
### Outside `npm run check`
|
|
241
286
|
|
|
242
287
|
| Suite | Covers |
|
|
243
288
|
| --- | --- |
|
|
244
|
-
| `browser/operator-ui.spec.ts` | the operator wiring in a real browser: the shell staying open until authentication, credential and access-token and OAuth flows end to end, drift shown without naming a tool, and every failure and empty state |
|
|
289
|
+
| `browser/operator-ui.spec.ts` | the operator wiring in a real browser: Clerk loader order across its version redirect and a real load failure, the shell staying open until authentication, credential and access-token and OAuth flows end to end, drift shown without naming a tool, and every failure and empty state |
|
|
245
290
|
| `browser/program-ui.spec.ts` | the Apps shell in a real browser: a bound view merging fixed and declared arguments and correlating concurrent reads, and the one-string payload receiving no read bridge ([program UI read calls](./program-ui-read-calls.md)) |
|
|
246
291
|
|
|
247
292
|
**The `_transportFactory` seam.** `RemoteMcpOptions._transportFactory` is
|
|
@@ -44,6 +44,14 @@ every operator-configured URL stay in `src/ui.ts`, where they are gated before
|
|
|
44
44
|
they can become an attribute; the bundle renders everything that has a state.
|
|
45
45
|
Two roots share one store: `#operatorNav` and `#operatorContent`.
|
|
46
46
|
|
|
47
|
+
The Clerk loader is intentionally blocking. The inline operator bundle calls
|
|
48
|
+
`boot()` as soon as the parser reaches the end of the body, so a deferred Clerk
|
|
49
|
+
script would make an expected parse-time gap look like a permanent network
|
|
50
|
+
failure. Blocking also preserves the existing failure path: after a real
|
|
51
|
+
loader error, the parser continues and `boot()` renders the Clerk load message.
|
|
52
|
+
Clerk's redirect from the major-version loader URL to its pinned asset keeps
|
|
53
|
+
the same ordering.
|
|
54
|
+
|
|
47
55
|
## Rules that are not obvious
|
|
48
56
|
|
|
49
57
|
- **No operator data in the shell.** Every page serves the same markup. Connector,
|
|
@@ -93,9 +101,11 @@ well as Node and there is no DOM in either:
|
|
|
93
101
|
something calls them when the identity actually changes. It typechecks in the
|
|
94
102
|
DOM-lib program (`tsconfig.operator-ui.json`) because it imports the store.
|
|
95
103
|
- `test/browser/operator-ui.spec.ts` — the wiring, in a real browser:
|
|
104
|
+
Clerk loader order across its version redirect and a real load failure, plus
|
|
96
105
|
credential, token, and OAuth flows end to end, including their failure and
|
|
97
|
-
empty states. Run it with `npm run test:browser`
|
|
98
|
-
once, for Chromium). It is not part of
|
|
106
|
+
empty states. Run it with `npm run test:browser`
|
|
107
|
+
(`npm run test:browser:install` once, for Chromium). It is not part of
|
|
108
|
+
`npm run check`.
|
|
99
109
|
|
|
100
110
|
## Why the bundle is committed
|
|
101
111
|
|
|
@@ -14,7 +14,7 @@ error, not a finding, so the proxy reports have no H rows.
|
|
|
14
14
|
Every miss below is fixed in the same change that recorded it
|
|
15
15
|
([#342](https://github.com/zackbart/connecta/issues/342)), except where the row
|
|
16
16
|
says otherwise. The mechanically checkable half of the hand-written bar is now
|
|
17
|
-
a test — [`test/provider-conventions.test.ts`](
|
|
17
|
+
a test — [`test/provider-conventions.test.ts`](https://github.com/zackbart/connecta/blob/main/test/provider-conventions.test.ts)
|
|
18
18
|
walks the shipped surface of both `api()` providers on every run, so these
|
|
19
19
|
verdicts cannot rot quietly back into prose. The proxies' mechanical rows live
|
|
20
20
|
in their own suites, because what they assert is the wrapper's identity,
|
|
@@ -104,14 +104,14 @@ deliberate surface.
|
|
|
104
104
|
| Convention | Verdict | Notes |
|
|
105
105
|
| --- | --- | --- |
|
|
106
106
|
| P1 add, never rewrite | meets | annotations only |
|
|
107
|
-
| P2 identity | meets | required `purpose`, `instructions` appended, classification untouchable from there |
|
|
107
|
+
| P2 identity | meets | required `purpose`, `instructions` appended, classification untouchable from there; purpose states deployment routing intent and the guide says it is not proof of authenticated account identity |
|
|
108
108
|
| P3 routing fact | meets | production versus sandbox appears in the title, the description, and the guide's first line |
|
|
109
109
|
| P4 endpoint default | meets | exemplary, and the model for the second clause: one published endpoint, `mode` required with no default, and construction throws when a recognizable key prefix contradicts the declared mode without reading anything it cannot classify |
|
|
110
110
|
| P5 classification | meets | including the two verdicts that needed an argument — `stripe_api_read` is a read because the tool is the boundary, `create_refund` is destructive despite its name |
|
|
111
111
|
| P6 catalog varies | **missed → fixed** | the doc already knew this (`get_balance_summary` is Treasury and gated; a `create_customer` example survives in Stripe's prose but not its tool table), but the *guide* did not say it, and the guide is what reaches the agent. Added |
|
|
112
112
|
| P7 reduction advice | **missed → fixed** | bare string; the derived summary was "Mode: production. Account purpose: …", spending the 120-character budget on the operator's prose. Now a declared, mode-shaped summary. `required` unset: the four generic tools are the routing decision and the mode warning already rides the title and description |
|
|
113
|
-
| P8 identity resolution | **missed → fixed** | Stripe's writes take ids and the guide never said where they come from. Added: the typed prefixes (`cus_`, `sub_`, `ch_`, `pi_`, `in_`, `acct_`), the rule that a plausible-looking
|
|
114
|
-
| P9 authentication | meets | OAuth default, `requireHttps`, restricted key documented as a secret and paired with the narrowest scope. The `auth_required` → `authorize_connector` route was added
|
|
113
|
+
| P8 identity resolution | **missed → fixed** | Stripe's writes take ids and the guide never said where they come from. Added: the typed prefixes (`cus_`, `sub_`, `ch_`, `pi_`, `in_`, `acct_`), the rule that a plausible-looking one belongs to a different object or to nobody, and the read tools that produce a real one. The guide now also accounts for OAuth sessions tied to several organization accounts: connector metadata is not identity proof, the exact selector must come from the live tool schema, and an ambiguous target or selection mechanism stops rather than becoming a guessed argument or header ([#404](https://github.com/zackbart/connecta/issues/404)) |
|
|
114
|
+
| P9 authentication | meets | OAuth default, `requireHttps`, restricted key documented as a secret and paired with the narrowest scope. The guide distinguishes organization accounts within an OAuth session from Connect connected accounts, whose calls reject OAuth and use a deployment-configured restricted key plus `Stripe-Account`. The `auth_required` → `authorize_connector` route was added alongside P8, since a proxy's only recovery instruction lives there |
|
|
115
115
|
| P10 no credential test | meets | no credential slot; the mode/key contradiction throws at construction instead, which is where P10 says the H12 guarantee gets paid |
|
|
116
116
|
| P11 transport vs tool error | meets | inherited from `remoteMcp()`; the guide now also says that a rejected argument or plan restriction arrives in Stripe's own words and is not an authorization problem |
|
|
117
117
|
| P12 admission budget | meets | a citable documented number (100/s live, 25/s sandbox), transcribed per mode, with `maxConcurrency` labeled as Connecta's own conservative choice |
|
|
@@ -50,21 +50,28 @@ floor. From `src/catalog.ts` and `src/catalog-service.ts`:
|
|
|
50
50
|
`fullDescriptions: true`. Prose past those points reaches an agent only when
|
|
51
51
|
it pays for the expansion.
|
|
52
52
|
- **A compact schema renders into at most 1,024 UTF-8 bytes**, and any single
|
|
53
|
-
enum
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
enum or constraint annotation into at most 256. Numeric bounds, string
|
|
54
|
+
length bounds, patterns, and formats ride beside their TypeScript-like type.
|
|
55
|
+
Past a cap the renderer keeps what fits and degrades the rest — a prefix of
|
|
56
|
+
the enum plus `unknown`, a shape without the constraints that did not fit, a
|
|
57
|
+
required-first object with `unknown` types, or
|
|
58
|
+
`unknown /* truncated */` — and flags the match, which costs a describe
|
|
59
|
+
round trip to recover.
|
|
57
60
|
- **`inputKeys`, `requiredInputKeys`, and `outputKeys` come only from bounded
|
|
58
61
|
plain-object schemas.** A top-level `anyOf` has no keys to list, so a caller
|
|
59
62
|
learns nothing about the arguments without expanding the schema.
|
|
60
|
-
- **A guide summary is
|
|
61
|
-
|
|
63
|
+
- **A guide summary is bounded at 120 characters.** A configured value past
|
|
64
|
+
the bound refuses construction. An omitted one defaults to the guide's first
|
|
65
|
+
meaningful body paragraph, joined across physical line wraps and shortened
|
|
66
|
+
at a readable boundary.
|
|
62
67
|
- **Search returns a connector's `id`, `title`, `guide`, and `guideSummary` —
|
|
63
68
|
never its `description`.** The description reaches an agent only as the
|
|
64
|
-
fallback summary for a guide with no usable body
|
|
65
|
-
in the title and the guide's
|
|
69
|
+
fallback summary for a guide with no usable body paragraph. Routing facts belong
|
|
70
|
+
in the title and the guide's opening paragraph; a routing fact that lives only in
|
|
66
71
|
the connector description has been written into a field the model does not
|
|
67
|
-
read.
|
|
72
|
+
read. Neither the `id` nor the `title` is a lexical document, so a term drawn
|
|
73
|
+
from one of them is not a search hit — it is a no-match whose guidance names
|
|
74
|
+
the connector and points at a scoped browse.
|
|
68
75
|
|
|
69
76
|
Two construction-time checks enforce the floor beneath all of this. The hard
|
|
70
77
|
one is `api()` itself: since
|
|
@@ -108,7 +115,10 @@ write never hides behind a neutral one. Escape hatches are named
|
|
|
108
115
|
`<provider>_api_<class>` so they sort together and read as generic.
|
|
109
116
|
|
|
110
117
|
*Why:* the name is the only thing lexical search indexes besides the
|
|
111
|
-
description, and it is what an agent skims first.
|
|
118
|
+
description, and it is what an agent skims first. A connector's `id` and
|
|
119
|
+
`title` are displayed, not indexed — a search for one of them matches no tool,
|
|
120
|
+
and the miss is answered by guidance naming that connector rather than by a
|
|
121
|
+
ranked result. *Cost:* wrong-tool selection.
|
|
112
122
|
|
|
113
123
|
### H3 — The selection sentence fits in 160 characters; the whole description in 240
|
|
114
124
|
|
|
@@ -136,7 +146,8 @@ wrong-tool selection.
|
|
|
136
146
|
Every tool carries a hand-written `inputSchema`: a plain object at the top
|
|
137
147
|
level, `additionalProperties: false`, an accurate `required` list, an `enum` on
|
|
138
148
|
every constrained field, explicit numeric bounds on every page size and count,
|
|
139
|
-
|
|
149
|
+
explicit string bounds where length or shape is constrained, and a description
|
|
150
|
+
on every property — nested objects and array items included,
|
|
140
151
|
because a caller composing an array element is reading that element's fields,
|
|
141
152
|
not the parent's prose. `api()` enforces the enforceability half for free since
|
|
142
153
|
[#340](https://github.com/zackbart/connecta/issues/340): a schema the validator
|
|
@@ -160,10 +171,12 @@ argument retries.
|
|
|
160
171
|
### H7 — Schemas fit the compact renderer, or selection does not depend on the part that is cut
|
|
161
172
|
|
|
162
173
|
Keep the common path's compact input and output shapes inside 1,024 bytes and
|
|
163
|
-
each enum
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
174
|
+
each enum or constraint annotation inside 256. Numeric and string constraints
|
|
175
|
+
render when they fit. Search drops complete constraints that do not fit and
|
|
176
|
+
sets the existing truncation flag; compact describe keeps them. Where a
|
|
177
|
+
legitimate enum genuinely cannot fit — 21 DNS record types — the truncation is
|
|
178
|
+
acceptable only if the tool's name and description already carry enough for
|
|
179
|
+
selection, so the caller expands the schema to *call*, not to *choose*.
|
|
167
180
|
|
|
168
181
|
*Why:* a truncated compact shape costs a describe round trip. *Cost:* discovery
|
|
169
182
|
tokens.
|
|
@@ -217,6 +230,37 @@ convenient reading. A call that can only fail is refused locally as
|
|
|
217
230
|
`invalid_args` before the round trip. Provider error prose is never parsed to
|
|
218
231
|
invent a classification.
|
|
219
232
|
|
|
233
|
+
**A downstream 404 is `not_found` — when the provider means it.** The code
|
|
234
|
+
exists because the next move is none of the others': you do not wait, you do
|
|
235
|
+
not send the agent to `authorize_connector`, you do not repair the argument
|
|
236
|
+
object. You re-address — look the id up again, or accept the absence and carry
|
|
237
|
+
on — and a program looping over ids inside `execute_code` can continue past
|
|
238
|
+
`not_found` where `connector_call_failed` would have to abort the run, reading
|
|
239
|
+
the code off a `connecta.batch` entry's `errorDetails` rather than off a caught
|
|
240
|
+
error, which the guest bridge has already stripped to prose. That
|
|
241
|
+
control-flow difference is the H11 test being met; it is not a label for the
|
|
242
|
+
cause.
|
|
243
|
+
|
|
244
|
+
The qualifier is the whole rule. Map a status to `not_found` only where the
|
|
245
|
+
provider distinguishes absence from a permission gap. Where it does not —
|
|
246
|
+
Notion returns `object_not_found` both for an object that is gone and for one
|
|
247
|
+
that was never shared with the integration, and will not say which — the honest
|
|
248
|
+
code stays `connector_call_failed` (or `auth_required`, where a credential
|
|
249
|
+
really is the fix) and the message states the ambiguity, exactly as the
|
|
250
|
+
paragraph above requires. Cloudflare is the other side of the pair: a token
|
|
251
|
+
that may not touch a resource is refused with 401 or 403, so its 404 is an
|
|
252
|
+
absence and maps to `not_found`. Neither connector's mapping changed shape when
|
|
253
|
+
the code arrived; one of them changed codes.
|
|
254
|
+
|
|
255
|
+
Two boundaries. `not_found` is about a resource the *downstream* owns: an
|
|
256
|
+
address connecta cannot resolve is already framed as `unknown_address` or
|
|
257
|
+
`unknown_tool` and never reaches a connector. And it never appears on the
|
|
258
|
+
hosted-MCP proxy path, because `P1` forbids re-shaping downstream framing and
|
|
259
|
+
prose is never parsed to invent a classification — a proxied server's own
|
|
260
|
+
missing-resource error arrives as that server wrote it. The two paths do not
|
|
261
|
+
diverge on the rule; they diverge on who is entitled to apply it, which is the
|
|
262
|
+
same split every other code already has.
|
|
263
|
+
|
|
220
264
|
*Why:* a misrouted error sends an agent down a recovery path that cannot
|
|
221
265
|
succeed. *Cost:* argument retries.
|
|
222
266
|
|
|
@@ -508,7 +552,7 @@ whether or not anybody noticed it arrived.
|
|
|
508
552
|
([#351](https://github.com/zackbart/connecta/issues/351)): a human at a laptop,
|
|
509
553
|
before a release, with local credentials and the published specifications in
|
|
510
554
|
front of them. It lives in
|
|
511
|
-
[`scripts/drift-check.mjs`](
|
|
555
|
+
[`scripts/drift-check.mjs`](https://github.com/zackbart/connecta/blob/main/scripts/drift-check.mjs) and ships nowhere —
|
|
512
556
|
`scripts/` is outside the package, no runtime module imports it, and nothing it
|
|
513
557
|
reads becomes a runtime input.
|
|
514
558
|
|
|
@@ -525,10 +569,15 @@ One credential per provider comes from the environment —
|
|
|
525
569
|
`CONNECTA_DRIFT_LINEAR_KEY`, `CONNECTA_DRIFT_STRIPE_KEY`,
|
|
526
570
|
`CONNECTA_DRIFT_MIXPANEL_KEY` — and a missing or dead one stops the run with a
|
|
527
571
|
message naming it rather than reporting an empty catalog as mass removal.
|
|
572
|
+
Linear and bare Stripe values use their documented bearer or Basic framing.
|
|
573
|
+
Mixpanel's beta service-account form is provider-specific:
|
|
574
|
+
`user:secret` becomes `Bearer Basic <base64(user:secret)>`, exactly as its MCP
|
|
575
|
+
documentation requires. A value that already includes whitespace is treated
|
|
576
|
+
as a complete Authorization value and passes through unchanged.
|
|
528
577
|
|
|
529
578
|
**Touched endpoints.** A hand-written provider is written against a published
|
|
530
579
|
OpenAPI document and calls a few dozen of its operations, so
|
|
531
|
-
[`scripts/drift/`](
|
|
580
|
+
[`scripts/drift/`](https://github.com/zackbart/connecta/tree/main/scripts/drift) commits exactly those: method, path, the
|
|
532
581
|
specification revision a release reviewed the endpoint at, whether the
|
|
533
582
|
operation was deprecated at that revision, and a digest of that endpoint's
|
|
534
583
|
contract. `--specs` fetches each provider's published document and reports four
|
|
@@ -580,7 +629,7 @@ the reason). A convention is never quietly skipped, and an accepted miss is
|
|
|
580
629
|
recorded as a provider-specific exception with its argument, not left blank.
|
|
581
630
|
Its five reports live in [provider-audit.md](./provider-audit.md), and the
|
|
582
631
|
mechanically checkable half of the hand-written bar runs on every test run in
|
|
583
|
-
[`test/provider-conventions.test.ts`](
|
|
632
|
+
[`test/provider-conventions.test.ts`](https://github.com/zackbart/connecta/blob/main/test/provider-conventions.test.ts) —
|
|
584
633
|
so a convention that was met once stays met, or fails loudly.
|
|
585
634
|
|
|
586
635
|
Hand-written providers are audited against H1–H14; hosted-MCP proxies against
|
|
@@ -620,7 +669,7 @@ beats the escape hatch — is a reading, and the audit reports it as one. The
|
|
|
620
669
|
Cloudflare keep/prune half of that judgment was made in
|
|
621
670
|
[#350](https://github.com/zackbart/connecta/issues/350): 30 keep, 18 improve,
|
|
622
671
|
3 prune, measured per tool in
|
|
623
|
-
[`eval/current-version/results/issue-350-evidence.md`](
|
|
672
|
+
[`eval/current-version/results/issue-350-evidence.md`](https://github.com/zackbart/connecta/blob/main/eval/current-version/results/issue-350-evidence.md).
|
|
624
673
|
Its eighteen `improve` rows are H8 and H9 misses on tools that clearly earn
|
|
625
674
|
their place, so they are this audit's work, not a second removal argument.
|
|
626
675
|
|
package/documentation/stripe.md
CHANGED
|
@@ -17,9 +17,15 @@ const billing = stripe("stripe_live", {
|
|
|
17
17
|
});
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
The `id` owns the ordinary connector namespaces
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
The `id` owns the ordinary connector namespaces. Choose a connector boundary
|
|
21
|
+
for its credential or OAuth session, mode, and business purpose — not
|
|
22
|
+
automatically for each Stripe account. One OAuth session may cover more than
|
|
23
|
+
one account in the same Stripe organization. Use separate connectors when the
|
|
24
|
+
credential, production/sandbox mode, or business purpose differs.
|
|
25
|
+
|
|
26
|
+
`purpose` is required because it tells an agent where the deployment intends
|
|
27
|
+
to route a question. The connector id, title, and purpose are configuration,
|
|
28
|
+
not proof of which account the authenticated Stripe session will use. Account
|
|
23
29
|
`instructions` are appended to the maintained guide and cannot change the
|
|
24
30
|
connector's safety classification.
|
|
25
31
|
|
|
@@ -53,9 +59,9 @@ one. That check reads nothing it cannot classify — an OAuth connector, or a
|
|
|
53
59
|
credential shape this release does not recognize, is left alone rather than
|
|
54
60
|
guessed at — and the error names only the two modes, never the key.
|
|
55
61
|
|
|
56
|
-
Deploy
|
|
57
|
-
hand-written connectors with different ids: separate addresses,
|
|
58
|
-
credentials, storage, admission counters, and health.
|
|
62
|
+
Deploy production and sandbox side by side. Two instances are isolated exactly
|
|
63
|
+
like two hand-written connectors with different ids: separate addresses,
|
|
64
|
+
catalogs, credentials, storage, admission counters, and health.
|
|
59
65
|
|
|
60
66
|
```ts
|
|
61
67
|
connectors: [
|
|
@@ -74,7 +80,20 @@ connectors: [
|
|
|
74
80
|
|
|
75
81
|
OAuth is the default and the option Stripe recommends: it supports dynamic
|
|
76
82
|
client registration and PKCE, and each connector instance keeps its own flow
|
|
77
|
-
and tokens in connector-scoped storage. Stripe
|
|
83
|
+
and tokens in connector-scoped storage. Stripe's current
|
|
84
|
+
[session-management documentation](https://docs.stripe.com/mcp#manage-mcp-client-sessions)
|
|
85
|
+
says one OAuth session can be tied to more than one account in the same Stripe
|
|
86
|
+
organization. It does not say every session has multiple accounts.
|
|
87
|
+
|
|
88
|
+
That scope changes what an agent must prove before an account-scoped call. It
|
|
89
|
+
must resolve the intended organization account, inspect the selected tool's
|
|
90
|
+
live input schema, and carry only the exact account or context field that
|
|
91
|
+
schema exposes. If more than one account fits, or the live schema exposes no
|
|
92
|
+
clear selection mechanism, the agent stops and asks. It never guesses from the
|
|
93
|
+
connector id, title, or purpose, and it never invents an MCP argument or
|
|
94
|
+
request header.
|
|
95
|
+
|
|
96
|
+
Stripe also accepts a
|
|
78
97
|
[restricted API key](https://docs.stripe.com/keys#create-restricted-api-key) as
|
|
79
98
|
a bearer token for headless agents:
|
|
80
99
|
|
|
@@ -93,9 +112,12 @@ Use a restricted key, not a secret key, and scope it to the operations the
|
|
|
93
112
|
agent actually needs; Stripe's own guidance is to "limit your agent's access to
|
|
94
113
|
exactly the functionality it requires". Keep it in the runtime's secret store.
|
|
95
114
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
115
|
+
Organization accounts in one OAuth session are not Stripe Connect connected
|
|
116
|
+
accounts. Connect platforms can act as a connected account with
|
|
117
|
+
`connectedAccount`, which adds Stripe's documented `Stripe-Account` header at
|
|
118
|
+
connector construction. Stripe does not support OAuth for connected-account
|
|
119
|
+
calls, so this requires a restricted key through `headers` auth and throws
|
|
120
|
+
otherwise:
|
|
99
121
|
|
|
100
122
|
```ts
|
|
101
123
|
stripe("merchant_42", {
|
|
@@ -109,9 +131,10 @@ stripe("merchant_42", {
|
|
|
109
131
|
});
|
|
110
132
|
```
|
|
111
133
|
|
|
112
|
-
Administrators must enable MCP access in the Stripe Dashboard
|
|
113
|
-
|
|
114
|
-
boots but cannot list tools is usually a dashboard
|
|
134
|
+
Administrators must enable MCP access in the Stripe Dashboard. Stripe scopes
|
|
135
|
+
OAuth session management and MCP access **separately for sandbox and live
|
|
136
|
+
mode**. A connector that boots but cannot list tools is usually a dashboard
|
|
137
|
+
toggle, not a bad key.
|
|
115
138
|
|
|
116
139
|
## The eleven tools, and what they are classified as
|
|
117
140
|
|
|
@@ -158,7 +181,7 @@ serves, an unclassified and unannotated `create_customer` lands on the approval
|
|
|
158
181
|
path. Expect the undocumented Treasury tools Stripe alludes to to arrive
|
|
159
182
|
unclassified as well — annotated ones will be taken at their word.
|
|
160
183
|
|
|
161
|
-
The upshot is that this
|
|
184
|
+
The upshot is that this connection's tool list is not a fixed set, and the usage
|
|
162
185
|
guide tells the agent so: search this connector for what it actually exposes
|
|
163
186
|
rather than assuming a documented tool is present. The guide also names the id
|
|
164
187
|
discipline the downstream schemas cannot enforce — Stripe ids are typed
|
|
@@ -166,6 +189,14 @@ prefixes (`cus_`, `sub_`, `ch_`, `pi_`, `in_`, `acct_`), a plausible-looking one
|
|
|
166
189
|
belongs to a different object or to nobody, and the id a write takes comes from
|
|
167
190
|
`stripe_api_search` or a list read rather than from a guess.
|
|
168
191
|
|
|
192
|
+
Account selection comes before that object-id rule. The served guide warns
|
|
193
|
+
that the connector metadata states routing intent rather than authenticated
|
|
194
|
+
identity. It tells the agent to use only selectors in the live tool schema and
|
|
195
|
+
to stop when the account or selection mechanism is ambiguous. It also keeps
|
|
196
|
+
organization-account selection separate from the restricted-key-only Connect
|
|
197
|
+
path, so an agent cannot repair uncertainty by fabricating `Stripe-Account` as
|
|
198
|
+
a tool argument.
|
|
199
|
+
|
|
169
200
|
Stripe publishes no stability or deprecation policy for this tool set and
|
|
170
201
|
invites tool requests by email, so treat the list as unversioned. `get_balance_summary`
|
|
171
202
|
is Treasury, which Stripe labels public preview and gates behind an access
|