@zackbart/connecta 0.23.0 → 0.24.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +5 -0
- package/CHANGELOG.md +53 -0
- package/README.md +18 -10
- package/dist/activity-friction.d.ts +3 -0
- package/dist/activity-friction.js +19 -0
- package/dist/activity.d.ts +11 -2
- package/dist/activity.js +15 -19
- package/dist/auth/downstream-oauth.d.ts +2 -1
- package/dist/auth/downstream-oauth.js +10 -1
- package/dist/branding.d.ts +67 -0
- package/dist/branding.js +176 -0
- package/dist/connectors/remote-mcp.js +3 -5
- package/dist/credential-contract.d.ts +24 -0
- package/dist/credential-contract.js +1 -0
- package/dist/credential-rules.d.ts +85 -0
- package/dist/credential-rules.js +107 -0
- package/dist/credentials.d.ts +4 -100
- package/dist/credentials.js +3 -107
- package/dist/execute.d.ts +6 -0
- package/dist/execute.js +17 -7
- package/dist/index.d.ts +35 -56
- package/dist/index.js +34 -58
- package/dist/invocation.js +19 -4
- package/dist/meta-tools.d.ts +4 -0
- package/dist/meta-tools.js +8 -4
- package/dist/module-contracts.d.ts +19 -0
- package/dist/module-contracts.js +1 -0
- package/dist/operator-ui/generated.js +2 -2
- package/dist/operator-ui/model.d.ts +6 -3
- package/dist/operator-ui/view.d.ts +2 -18
- package/dist/operator-ui/view.js +3 -20
- package/dist/registry.d.ts +4 -1
- package/dist/registry.js +4 -6
- package/dist/routes/activity.js +1 -1
- package/dist/routes/credentials.js +5 -2
- package/dist/routes/mcp.js +13 -3
- package/dist/routes/oauth-management.d.ts +2 -0
- package/dist/routes/oauth-management.js +108 -0
- package/dist/routes/oauth.d.ts +0 -1
- package/dist/routes/oauth.js +21 -121
- package/dist/routes/shared.d.ts +23 -17
- package/dist/routes/shared.js +48 -44
- package/dist/routes/ui.js +36 -33
- package/dist/server.js +6 -26
- package/dist/types.d.ts +2 -0
- package/dist/ui.d.ts +15 -70
- package/dist/ui.js +176 -317
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/documentation/architecture.md +26 -17
- package/documentation/auth.md +61 -106
- package/documentation/cloudflare.md +1 -1
- package/documentation/code-mode.md +2 -2
- package/documentation/connectors.md +1 -1
- package/documentation/linear.md +1 -1
- package/documentation/meta-tools.md +6 -4
- package/documentation/mixpanel.md +1 -1
- package/documentation/notion.md +2 -2
- package/documentation/operations.md +14 -14
- package/documentation/operator-ui.md +82 -104
- package/documentation/optional-modules-upgrade.md +243 -0
- package/documentation/provider-conventions.md +5 -3
- package/documentation/revenuecat.md +1 -1
- package/documentation/storage-and-credentials.md +59 -40
- package/documentation/stripe.md +1 -1
- package/documentation/upgrading.md +33 -4
- package/ethos.md +22 -30
- package/examples/worker/AGENTS.md +3 -1
- package/examples/worker/README.md +68 -84
- package/examples/worker/src/d1-activity.ts +1 -1
- package/examples/worker/src/index.ts +11 -6
- package/package.json +17 -1
- package/templates/node/AGENTS.md +8 -6
- package/templates/node/README.md +56 -67
- package/templates/node/package.json +1 -1
- package/templates/node/src/file-activity.ts +1 -1
- package/templates/node/src/index.ts +11 -12
- package/dist/access-tokens.d.ts +0 -31
- package/dist/access-tokens.js +0 -236
- package/dist/routes/access-tokens.d.ts +0 -6
- package/dist/routes/access-tokens.js +0 -83
package/documentation/auth.md
CHANGED
|
@@ -1,67 +1,60 @@
|
|
|
1
1
|
# Inbound auth
|
|
2
2
|
|
|
3
|
-
Inbound auth decides who may reach the MCP endpoint.
|
|
4
|
-
|
|
5
|
-
Access
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
Inbound auth decides who may reach the MCP endpoint. Import configured bearer
|
|
4
|
+
support from `@zackbart/connecta/auth/bearer`, Clerk from `/auth/clerk`, or
|
|
5
|
+
Cloudflare Access from `/auth/cloudflare-access`. Providers may be combined;
|
|
6
|
+
static bearers are checked first, then other providers in configuration order.
|
|
7
|
+
Connecta no longer issues `cta_` tokens or serves token-management routes.
|
|
8
8
|
|
|
9
9
|
## Principals, visibility, and operators
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
results such as `get_result` pages. The principal is the human owner of personal
|
|
11
|
+
The actor identifies the caller in activity. The subject owns transient results
|
|
12
|
+
such as `get_result` pages. The principal is the human owner of personal
|
|
14
13
|
connector auth. An interactive Clerk or Access user supplies all three. A
|
|
15
|
-
Cloudflare service identity has an actor and subject but no principal.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
`
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
14
|
+
Cloudflare service identity has an actor and subject but no principal.
|
|
15
|
+
|
|
16
|
+
`identity.connectorAccess` returns `"all"` or declared connector ids. It governs
|
|
17
|
+
discovery and use, and defaults to all connectors. Visibility alone grants no
|
|
18
|
+
authentication-management permission. Two independent resolvers return
|
|
19
|
+
`"all"`, `"none"`, or declared connector ids:
|
|
20
|
+
|
|
21
|
+
- `credentialAdministration` allows an interactive human to manage shared
|
|
22
|
+
credentials and shared OAuth grants.
|
|
23
|
+
- `personalConnection` allows an interactive human to manage their own
|
|
24
|
+
credentials and OAuth grants on personal connectors.
|
|
25
|
+
|
|
26
|
+
Both default to `"none"`. Each action requires visibility and the relevant
|
|
27
|
+
permission. Personal actions also require a stable namespaced principal and
|
|
28
|
+
always use that principal's partition. Resolver exceptions and unknown ids
|
|
29
|
+
fail closed. Permissions come from authenticated identity, never caller input.
|
|
30
|
+
|
|
31
|
+
The management resolvers receive `Readonly<AuthenticatedIdentity>`.
|
|
32
|
+
`identity.activityAccess` receives `Readonly<IdentityReference>` with `id` and
|
|
33
|
+
`namespace`, and controls reading global activity. Its default admits
|
|
34
|
+
interactive humans, so team deployments should set it explicitly if the event
|
|
35
|
+
stream should be restricted. It replaces `operatorAccess`; there is no general
|
|
36
|
+
administrator role or token-management authority.
|
|
37
37
|
|
|
38
38
|
```ts
|
|
39
39
|
createConnecta({
|
|
40
40
|
auth: cloudflareAccessAuth(),
|
|
41
41
|
identity: {
|
|
42
42
|
connectorAccess: ({ principal }) =>
|
|
43
|
-
principal?.id === "
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
principal?.id === "owner-id" ? "all" : ["shared_docs", "personal_linear"],
|
|
44
|
+
credentialAdministration: ({ principal }) =>
|
|
45
|
+
principal?.id === "owner-id" ? "all" : "none",
|
|
46
|
+
personalConnection: () => ["personal_linear"],
|
|
47
|
+
activityAccess: ({ id }) => id === "owner-id",
|
|
47
48
|
},
|
|
48
|
-
connectors
|
|
49
|
-
remoteMcp("shared_docs", { url: "https://example.com/mcp" }),
|
|
50
|
-
remoteMcp("personal_linear", {
|
|
51
|
-
url: "https://mcp.linear.app/mcp",
|
|
52
|
-
authScope: "personal",
|
|
53
|
-
auth: { type: "oauth" },
|
|
54
|
-
}),
|
|
55
|
-
],
|
|
49
|
+
connectors,
|
|
56
50
|
executor,
|
|
57
51
|
});
|
|
58
52
|
```
|
|
59
53
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
storage.
|
|
54
|
+
Built-in Clerk and Access providers supply identity namespaces. A custom
|
|
55
|
+
interactive provider must set `activityActorNamespace` before its users can
|
|
56
|
+
own personal auth. Keep the namespace and principal ids stable across upgrades;
|
|
57
|
+
changing them selects different personal storage partitions.
|
|
65
58
|
|
|
66
59
|
## Cloudflare Access on Workers
|
|
67
60
|
|
|
@@ -92,12 +85,11 @@ also means it is deliberately not a Node or `cloudflared` origin adapter, and
|
|
|
92
85
|
it does not survive a Service Binding hop: those shapes need their own explicit
|
|
93
86
|
trust boundary.
|
|
94
87
|
|
|
95
|
-
A human identity gets
|
|
96
|
-
|
|
97
|
-
identity
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
email domains, groups, or device posture into a second policy layer.
|
|
88
|
+
A human identity gets a code-derived MCP view. Managing connection auth requires
|
|
89
|
+
an explicit `credentialAdministration` or `personalConnection` grant. An Access
|
|
90
|
+
service identity has no human principal and cannot mutate connection auth.
|
|
91
|
+
Access decides admission and identity; Connecta configuration selects connector
|
|
92
|
+
access and these narrower permissions.
|
|
101
93
|
|
|
102
94
|
Protect the Worker with a Worker-level Access application whose destination is
|
|
103
95
|
`{ "type": "worker", "worker_id": "<the Worker script tag>" }`. A traditional
|
|
@@ -135,8 +127,7 @@ Worker-level Access runs before every connecta route. Consequently:
|
|
|
135
127
|
|
|
136
128
|
- `/health`, operator pages, downstream OAuth callbacks, and `/mcp` all require Access unless a more-specific hostname/path
|
|
137
129
|
policy says otherwise;
|
|
138
|
-
- a static
|
|
139
|
-
credentials, because Cloudflare rejects them before connecta sees them; and
|
|
130
|
+
- a static Connecta bearer is not a standalone edge credential, because Cloudflare rejects them before connecta sees them; and
|
|
140
131
|
- custom public webhooks belong to the deployment outside Connecta and need
|
|
141
132
|
their own Access routing policy. Keep Connecta's OAuth discovery paths
|
|
142
133
|
protected when Managed OAuth is enabled.
|
|
@@ -156,57 +147,21 @@ publishable slot, and a startup error is a log line. A deployment that builds
|
|
|
156
147
|
per request, as the Workers shape does, sees the same error on its first
|
|
157
148
|
request instead of a base64 stack on every route.
|
|
158
149
|
|
|
159
|
-
##
|
|
150
|
+
## Human authentication management
|
|
160
151
|
|
|
161
|
-
|
|
162
|
-
|
|
152
|
+
Credential and OAuth mutation require an admitted interactive human, connector
|
|
153
|
+
visibility, the appropriate shared or personal permission, and an exact
|
|
154
|
+
same-origin `Origin` for browser requests. A configured MCP bearer never becomes
|
|
155
|
+
a browser management credential.
|
|
163
156
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
});
|
|
171
|
-
```
|
|
157
|
+
With `ui: operatorUi()` and a vault, static credential recovery can return a
|
|
158
|
+
secret-free handoff to the connection UI. Without the UI, that recovery is
|
|
159
|
+
`unavailable`; Connecta does not return a link to a missing page. An authorized
|
|
160
|
+
interactive MCP caller can still start downstream OAuth through
|
|
161
|
+
`authorize_connector` without the UI. Core owns the callback and verifies state
|
|
162
|
+
and principal ownership independently of the optional browser application.
|
|
172
163
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
secure.
|
|
178
|
-
|
|
179
|
-
Each token has an immutable ID. Activity records store that ID and resolve its
|
|
180
|
-
current friendly name only while an authorized operator reads activity.
|
|
181
|
-
Revoked records remain as metadata tombstones so historical calls keep their
|
|
182
|
-
friendly attribution. New tokens also retain the creating principal. Their MCP
|
|
183
|
-
requests use that principal's connector visibility and personal auth while the
|
|
184
|
-
token itself remains the activity actor and result owner.
|
|
185
|
-
|
|
186
|
-
Access tokens authenticate MCP clients; they are never operator credentials.
|
|
187
|
-
Creation, rename, and revocation require the same eligible human identity and
|
|
188
|
-
same-origin mutation boundary as connector credentials. `maxActive` defaults
|
|
189
|
-
to 100 and can be set from 1 through 1,000.
|
|
190
|
-
|
|
191
|
-
Issuance and revocation inherit the consistency guarantees of the configured
|
|
192
|
-
storage adapter. Use strongly consistent storage when either change must take
|
|
193
|
-
effect globally without a convergence window.
|
|
194
|
-
|
|
195
|
-
Human credential mutation is a separate, narrower boundary. The
|
|
196
|
-
`/credentials` shell contains no secret data before authentication, and the
|
|
197
|
-
mutation API requires same-origin requests from an admitted interactive human.
|
|
198
|
-
That human may mutate only visible connector slots. An MCP bearer is never
|
|
199
|
-
treated as a browser credential, even when it can call every connector.
|
|
200
|
-
|
|
201
|
-
This split is visible in recovery:
|
|
202
|
-
|
|
203
|
-
- a bearer-authenticated agent may receive `recovery: "operator_config"` and
|
|
204
|
-
pass its `operatorUrl` to a human;
|
|
205
|
-
- an interactive human with connector access opens that URL, signs in, and updates the
|
|
206
|
-
credential; and
|
|
207
|
-
- a bearer-only deployment still returns the handoff honestly, but mutation
|
|
208
|
-
remains unavailable until interactive user auth is configured.
|
|
209
|
-
|
|
210
|
-
See [meta-tools](./meta-tools.md#authorization-recovery) for the stable recovery
|
|
211
|
-
envelope and [storage and credentials](./storage-and-credentials.md) for vault
|
|
212
|
-
rules.
|
|
164
|
+
See [meta-tools](./meta-tools.md#authorization-recovery) and
|
|
165
|
+
[storage and credentials](./storage-and-credentials.md). The
|
|
166
|
+
[upgrade guide](./upgrading.md#0240-optional-modules) covers moving clients
|
|
167
|
+
off removed Connecta-issued tokens before changing deployment configuration.
|
|
@@ -135,7 +135,7 @@ Dashboard and API tabs.
|
|
|
135
135
|
|
|
136
136
|
`verify_api_token` needs no permission beyond the token existing. In legacy
|
|
137
137
|
mode, `verify_global_api_key` reads `/user` to confirm the email and key pair.
|
|
138
|
-
The
|
|
138
|
+
The connection UI Test action at `/` runs the matching check before storage.
|
|
139
139
|
|
|
140
140
|
Cloudflare rate-limits *authentication failures* aggressively and separately
|
|
141
141
|
from the global limit: a few requests with a bad token return HTTP 429 with
|
|
@@ -302,7 +302,7 @@ Program-authored errors stay untyped, and code must never parse error prose.
|
|
|
302
302
|
| `input_required_unsupported` | a downstream asked for mid-call input | false |
|
|
303
303
|
| `rate_limited` | the downstream reported a rate limit | true |
|
|
304
304
|
| `unavailable` | the downstream is down or unreachable | true |
|
|
305
|
-
| `timeout` | the per-call 15
|
|
305
|
+
| `timeout` | the per-call deadline (`execute.hostCallTimeoutMs`, default 15 s) expired | true |
|
|
306
306
|
| `cancelled` | the run ended while this call was in flight (`E5`) | false |
|
|
307
307
|
| `connector_call_failed` | anything else the connector threw | per message |
|
|
308
308
|
| `catalog_lookup_failed` | the connector's catalog could not be loaded | per cause |
|
|
@@ -492,7 +492,7 @@ because connecta enforces them above the sandbox:
|
|
|
492
492
|
| Bound | Value |
|
|
493
493
|
| --- | --- |
|
|
494
494
|
| Host calls per execution | 20 |
|
|
495
|
-
| Deadline per host call | 15 s |
|
|
495
|
+
| Deadline per host call | 15 s, `execute.hostCallTimeoutMs` |
|
|
496
496
|
| Discovery page | ≤ 100 tools, ≤ 256,000 serialized bytes |
|
|
497
497
|
| `describe` addresses | ≤ 100 |
|
|
498
498
|
| `describe` nearby suggestions | ≤ 3 canonical addresses per failed entry |
|
|
@@ -367,7 +367,7 @@ A remote MCP connector that authenticates with a static key has two ways to
|
|
|
367
367
|
receive one. `{ type: "headers", headers }` bakes the literal value into the
|
|
368
368
|
deployment file, which suits a secret the runtime already holds.
|
|
369
369
|
`{ type: "credential" }` declares the slot instead and lets an operator paste
|
|
370
|
-
the key at
|
|
370
|
+
the key at the connection UI at `/`, where it is encrypted at rest and rotatable without
|
|
371
371
|
a redeploy:
|
|
372
372
|
|
|
373
373
|
```ts
|
package/documentation/linear.md
CHANGED
|
@@ -88,7 +88,7 @@ configuration. A personal API key carries the acting user's full workspace
|
|
|
88
88
|
permissions, so pair it with `access: "read-only"` unless the deployment
|
|
89
89
|
genuinely writes.
|
|
90
90
|
|
|
91
|
-
The same key can arrive from
|
|
91
|
+
The same key can arrive from the connection UI at `/` instead, which is what a deployment
|
|
92
92
|
with no secret store — or an operator who rotates keys without a redeploy —
|
|
93
93
|
wants:
|
|
94
94
|
|
|
@@ -316,19 +316,21 @@ Every typed `auth_required` call failure uses the same envelope:
|
|
|
316
316
|
handoff:
|
|
317
317
|
|
|
318
318
|
- `oauth`: an `authorizationUrl` and consent instructions;
|
|
319
|
-
- `operator_config`: an `operatorUrl`
|
|
319
|
+
- `operator_config`: an `operatorUrl` to the mounted connection UI, plus the
|
|
320
320
|
declared credential label and field names/guidance; or
|
|
321
321
|
- `unavailable`: an honest deployment/configuration message.
|
|
322
322
|
|
|
323
323
|
The class follows what the connector declares, not how it was authored: a
|
|
324
324
|
`remoteMcp()` connection using `auth: { type: "credential" }` declares a slot
|
|
325
|
-
and no OAuth flow, so it
|
|
326
|
-
|
|
325
|
+
and no OAuth flow, so it uses `operator_config` when both vault and UI are
|
|
326
|
+
configured. Without either it returns `unavailable`, never a dead UI link.
|
|
327
327
|
|
|
328
328
|
The tool accepts no secret. `force` applies only to OAuth and may discard its
|
|
329
329
|
stored grant before restarting consent. Static credential values are written
|
|
330
330
|
only through the same-origin interactive-user credential route, and only for a
|
|
331
|
-
connector visible to that user
|
|
331
|
+
connector visible to that user with the relevant shared or personal management
|
|
332
|
+
permission. OAuth start, including `force`, requires that permission too. Core
|
|
333
|
+
callbacks work without the UI for authorized interactive callers. After OAuth consent or a human update, retry
|
|
332
334
|
the original operation; a static update is read from the vault on the next call
|
|
333
335
|
and needs no redeploy.
|
|
334
336
|
|
|
@@ -50,7 +50,7 @@ password, not ordinary configuration. Mixpanel currently labels service-account
|
|
|
50
50
|
MCP authentication beta. Prefer OAuth unless the deployment is intentionally
|
|
51
51
|
headless.
|
|
52
52
|
|
|
53
|
-
The same service account can arrive from
|
|
53
|
+
The same service account can arrive from the connection UI at `/` instead, and there the
|
|
54
54
|
operator pastes the readable pair rather than an encoded blob:
|
|
55
55
|
|
|
56
56
|
```ts
|
package/documentation/notion.md
CHANGED
|
@@ -58,7 +58,7 @@ it does not assume the REST interface's endpoint budget describes MCP traffic.
|
|
|
58
58
|
|
|
59
59
|
One operator-managed credential: an internal integration token from
|
|
60
60
|
[notion.so/profile/integrations](https://www.notion.so/profile/integrations).
|
|
61
|
-
The deployment needs `
|
|
61
|
+
The deployment needs `vault: encryptedCredentialVault(storage, encryptionKey)` configured, or the token
|
|
62
62
|
cannot be stored and every call fails `auth_required` at use.
|
|
63
63
|
|
|
64
64
|
Two Notion-specific facts decide whether a working token is enough:
|
|
@@ -69,7 +69,7 @@ Two Notion-specific facts decide whether a working token is enough:
|
|
|
69
69
|
default. `list_comments` and `add_comment` fail with 403 until an operator
|
|
70
70
|
turns them on in Notion.
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
The connection UI at `/` offers a Test action, which calls `GET /v1/users/me` — the
|
|
73
73
|
cheapest call that proves a token is live — and reports the workspace it
|
|
74
74
|
authenticated into.
|
|
75
75
|
|
|
@@ -33,8 +33,7 @@ and `test/package-surface.test.ts` fails if the two ever drift apart.
|
|
|
33
33
|
There are exactly two deployment shapes.
|
|
34
34
|
[`templates/node/`](../templates/node/) is what `connecta init` copies — the
|
|
35
35
|
one standalone Node project, Docker-ready rather than Docker-only — and
|
|
36
|
-
[`examples/worker/`](../examples/worker/) is the Cloudflare shape. Both
|
|
37
|
-
the whole operator feature set; each README walks through its own enablement.
|
|
36
|
+
[`examples/worker/`](../examples/worker/) is the Cloudflare shape. Both show explicit optional modules; each README walks through enablement.
|
|
38
37
|
A third scaffold that is a diff away from either is the shape
|
|
39
38
|
[#344](https://github.com/zackbart/connecta/issues/344) deleted, so do not add
|
|
40
39
|
one.
|
|
@@ -84,16 +83,15 @@ optional.
|
|
|
84
83
|
| `connectors` | — (required) | the connector set ([connectors](./connectors.md)) |
|
|
85
84
|
| `executor` | — (required) | the sandbox `execute_code` runs in ([code mode](./code-mode.md#what-an-executor-must-implement)) |
|
|
86
85
|
| `auth?` | none ⇒ open (dev only) | one `InboundAuth` or an array; bearer providers are checked before interactive providers ([inbound auth](./auth.md)) |
|
|
87
|
-
| `identity?` | all
|
|
88
|
-
| `storage?` | `memoryStorage()` |
|
|
86
|
+
| `identity?` | all visible; auth management denied; interactive activity reads | `{ connectorAccess?, credentialAdministration?, personalConnection?, activityAccess? }` derives separate use and management permissions ([identity](./auth.md#principals-visibility-and-operators)) |
|
|
87
|
+
| `storage?` | `memoryStorage()` | connector state, catalogs, and result paging; pass storage explicitly to the optional vault ([storage](./storage-and-credentials.md)) |
|
|
89
88
|
| `publicUrl?` | per-request origin | public base URL; an HTTPS value also redirects inbound HTTP |
|
|
90
|
-
| `logger?` | `console`, prefixed `[connecta]` | `{ debug, info, warn, error }` |
|
|
91
|
-
| `
|
|
89
|
+
| `logger?` | `console`, prefixed `[connecta]` | `{ debug, info, warn, error }`, or `"silent"` to suppress diagnostic output; independent of activity history |
|
|
90
|
+
| `ui?` | unset | `operatorUi({ branding? })` from `/ui`; omitted means no browser UI routes or bundle imports |
|
|
92
91
|
| `serverInfo?` | `connecta` / package version | `{ name, version, title?, websiteUrl?, icons? }` per the MCP icons spec |
|
|
93
92
|
| `deploymentInfo?` | unset | arbitrary metadata exposed by `/health` |
|
|
94
|
-
| `activity?` | unset | `{ store, readGate?, deploymentId? }`
|
|
95
|
-
| `
|
|
96
|
-
| `accessTokens?` | unset | `{ maxActive? }` (default 100) for operator-issued MCP bearer tokens. Requires an interactive operator provider, or construction throws ([access tokens](./auth.md#operator-issued-access-tokens)) |
|
|
93
|
+
| `activity?` | unset | `activityHistory({ store, readGate?, deploymentId? })` from `/activity`; omitted means no event recording or history reads |
|
|
94
|
+
| `vault?` | unset | `CredentialVault`; `encryptedCredentialVault(storage, encryptionKey)` from `/credentials` supplies the built-in encrypted implementation |
|
|
97
95
|
| `discovery.concurrency?` | 4 | connector catalogs/status probes in flight at once |
|
|
98
96
|
| `discovery.catalogTtlSeconds?` | 300 | fresh TTL for cached tool lists |
|
|
99
97
|
| `discovery.persistCatalog?` | true | persist serializable catalogs as a manifest plus revision-addressed chunks |
|
|
@@ -103,6 +101,8 @@ optional.
|
|
|
103
101
|
| `calls.maxResultBytes?` | 50_000 | inline result cap before truncation and `get_result` paging; a connector may override it. Invalid values warn and fall back |
|
|
104
102
|
| `execute.maxEmittedBytes?` | 4_000_000 | aggregate `connecta.emit` bytes per run — a transport bound, not a context bound |
|
|
105
103
|
| `execute.maxEmittedBlocks?` | 32 | content blocks `connecta.emit` accepts per run |
|
|
104
|
+
| `execute.maxHostCalls?` | 20 | connector calls one `execute_code` program may make |
|
|
105
|
+
| `execute.hostCallTimeoutMs?` | 15_000 | deadline per `execute_code` host call; raise it for providers whose legitimate calls run longer. `call_tool`'s `timeoutMs` is separate |
|
|
106
106
|
| `admission.requests?` | 16 active / 32 queued / 5 s / 1 s | global FIFO `/mcp` capacity, taken before auth ([request admission](./request-admission.md)) |
|
|
107
107
|
| `admission.code?` | 2 active / 8 queued / 5 s / 1 s | fallback pool for an executor that owns no `acquire()`; ignored with a warning when it does |
|
|
108
108
|
|
|
@@ -229,7 +229,6 @@ in.
|
|
|
229
229
|
|
|
230
230
|
| Suite | Covers |
|
|
231
231
|
| --- | --- |
|
|
232
|
-
| `access-tokens.test.ts` | the `AccessTokenManager` — a one-time secret created, authenticated, renamed, and revoked, bounded names and active count, enumerable storage required, a deployment with no interactive operator refused — and the operator-only routes, down to historical activity still resolving a revoked token's name |
|
|
233
232
|
| `activity.test.ts` | payload-free delivery: a rejected async write attaches to `waitUntil` instead of throwing, approved destructive calls record under their real entry point, result-size friction records without retaining the result, and a hallucinated connector id or invented identity is clamped so the event still cannot carry a payload |
|
|
234
233
|
| `api-connector.test.ts` | `api()` — kind, description, tool defs, dispatch, default args, unknown tools, handler throws, argument validation, and the construction contract |
|
|
235
234
|
| `bearer.test.ts` | constant-time bearer compare, case-insensitive scheme, 401 challenges, and the retired audience options refusing rather than silently unbinding |
|
|
@@ -252,7 +251,7 @@ in.
|
|
|
252
251
|
| `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 |
|
|
253
252
|
| `guarded-fetch.test.ts` | the guarded transport — construction, request building, destination confinement, and response handling |
|
|
254
253
|
| `guest-api-contract.test.ts` | the shared guest contract on the Dynamic Worker, including caught call, typed inline describe recovery, discovery, utility, parallel-call, 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 |
|
|
255
|
-
| `identity-scope.test.ts` | identity-derived connector visibility, personal credential isolation, shared-auth
|
|
254
|
+
| `identity-scope.test.ts` | identity-derived connector visibility, personal credential isolation, separate shared-auth and personal-auth management permissions, and personal OAuth callback ownership |
|
|
256
255
|
| `linear-provider.test.ts` | the Linear proxy's construction, guide, plan-aware catalog superset, and current workspace, template, and issue-sharing classifications |
|
|
257
256
|
| `meta-tools-call.test.ts` | registry-backed calls: structured errors, truncation and `get_result`, per-connector result bounds, JSON representation failures, MCP content bounds, and offset alignment |
|
|
258
257
|
| `meta-tools-search.test.ts` | registry-backed discovery: bounded search with page and address maxima, compact and JSON schemas with constraints, typed describe recovery and suggestions, and structured-result compatibility |
|
|
@@ -261,11 +260,12 @@ in.
|
|
|
261
260
|
| `notion-provider.test.ts` | Notion's API and MCP construction, the hosted safety manifest and drift behavior, the deliberate REST surface including declined expanded page inputs, request construction, lean projections, both pagination conventions, error mapping, and writes |
|
|
262
261
|
| `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 |
|
|
263
262
|
| `operator-store.test.ts` | `src/operator-ui/app/store.ts` against a fake browser: the Clerk listener, ambient Access requests without a browser-readable token, `gate()`, the generation fence, and the request path |
|
|
263
|
+
| `optional-modules.test.ts` | absent modules, UI-free OAuth, fast lists and independent detail deadlines, explicit auth-management grants, invalid-resolver refusal, and passive OAuth consent-state protection |
|
|
264
264
|
| `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) |
|
|
265
265
|
| `provider-registry.test.ts` | all seven maintained providers inside real deployments: boot, description, address, catalog, storage, credential, admission, and activity isolation; plus provider-specific discovery and guide contracts |
|
|
266
266
|
| `registry.test.ts` | construction and id validation, startup warnings, address resolution, version 2 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 |
|
|
267
267
|
| `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 |
|
|
268
|
-
| `remote-mcp-credential.test.ts` | `remoteMcp()` drawing a static key from
|
|
268
|
+
| `remote-mcp-credential.test.ts` | `remoteMcp()` drawing a static key from the connection UI: the declared slot and its refusal of named fields and bad header names, header framing (bearer, bare, and the two `Basic` forms) observed on the wire, an empty slot failing as `auth_required` rather than reaching the downstream, a value carrying a control character refused before framing and absent from every surface — `call_tool`, `status`, the Test result, the payload-free activity event, and the thrown error — rotation replacing the cached client and a connect already in flight while a wiped value fails the next call, the Test action's catalog probe and scope close, the cleartext-destination warning, and the vault and `authorize_connector` handoff end to end |
|
|
269
269
|
| `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 |
|
|
270
270
|
| `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 |
|
|
271
271
|
| `result-shapes.test.ts` | passive output-shape learning: value-free bounded inference, merging, 256-entry LRU eviction, 24-hour expiry, runtime isolation, read-only admission, declared-schema precedence, definition-change invalidation, discovery provenance, and failure isolation |
|
|
@@ -287,7 +287,7 @@ justification for *not* re-running it in workerd, so "it was easier" is not one.
|
|
|
287
287
|
|
|
288
288
|
| Suite | Covers | Why Node |
|
|
289
289
|
| --- | --- | --- |
|
|
290
|
-
| `deployment-shapes.test.ts` | the Worker as the only example with a loader-only sandbox, its agent instructions and setup guide pinning Claude and both ChatGPT Managed OAuth callback forms, one Node template that is also its own container, the same source running locally and in the container, the Node template's pinned esbuild install-script approval,
|
|
290
|
+
| `deployment-shapes.test.ts` | the Worker as the only example with a loader-only sandbox, its agent instructions and setup guide pinning Claude and both ChatGPT Managed OAuth callback forms, one Node template that is also its own container, the same source running locally and in the container, the Node template's pinned esbuild install-script approval, explicit optional modules 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 |
|
|
291
291
|
| `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 |
|
|
292
292
|
| `doctor-cli.test.ts` | `connecta doctor`'s executor line and credentials end to end — the sandbox the deployment reports is the one named, an unidentifiable executor gets an executor-neutral line, a hostile name is bounded, and a complete Cloudflare Access service-token pair is accepted while a partial pair is refused | spawns the CLI against a Node HTTP deployment over real sockets |
|
|
293
293
|
| `drift-check.test.ts` | the credential-free maintainer drift checker: recorded touched endpoints, heading, table, and inline MCP inventories, setup-only providers, live-schema ownership, a quiet revision bump, clear failures for unavailable inputs, `$ref` traversal, and one well-formed row per endpoint | spawns the checker against filesystem fixtures |
|
|
@@ -310,7 +310,7 @@ justification for *not* re-running it in workerd, so "it was easier" is not one.
|
|
|
310
310
|
|
|
311
311
|
| Suite | Covers |
|
|
312
312
|
| --- | --- |
|
|
313
|
-
| `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
|
|
313
|
+
| `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 OAuth flows end to end, drift shown without naming a tool, and every failure and empty state |
|
|
314
314
|
|
|
315
315
|
**The `_transportFactory` seam.** `RemoteMcpOptions._transportFactory` is
|
|
316
316
|
internal, not public API: when set, `remoteMcp()` uses that `Transport` instead
|