@zackbart/connecta 0.18.3 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +131 -4
- package/dist/apps-shell.d.ts +10 -12
- package/dist/apps-shell.js +29 -220
- package/dist/catalog-service.d.ts +16 -13
- package/dist/catalog-service.js +106 -115
- package/dist/catalog.js +29 -46
- package/dist/connector-scope.js +2 -7
- package/dist/connectors/api.d.ts +4 -16
- package/dist/connectors/api.js +19 -46
- package/dist/connectors/guarded-fetch.d.ts +9 -23
- package/dist/connectors/guarded-fetch.js +38 -76
- package/dist/connectors/remote-mcp.js +36 -79
- package/dist/errors.d.ts +6 -27
- package/dist/errors.js +8 -5
- package/dist/execute.d.ts +23 -28
- package/dist/execute.js +101 -257
- package/dist/executor-result.d.ts +1 -0
- package/dist/executor-result.js +4 -11
- package/dist/executors/quickjs-child.js +1 -3
- package/dist/executors/quickjs-runtime.js +1 -3
- package/dist/executors/quickjs.js +1 -3
- package/dist/index.js +134 -123
- package/dist/invocation.d.ts +1 -1
- package/dist/invocation.js +113 -183
- package/dist/meta-tools.d.ts +15 -29
- package/dist/meta-tools.js +41 -582
- package/dist/operator-ui/generated.d.ts +2 -2
- package/dist/providers/cloudflare.d.ts +2 -18
- package/dist/providers/cloudflare.js +1460 -2451
- package/dist/providers/linear.d.ts +4 -41
- package/dist/providers/linear.js +8 -39
- package/dist/providers/mixpanel.d.ts +3 -25
- package/dist/providers/mixpanel.js +7 -22
- package/dist/providers/notion.d.ts +1 -15
- package/dist/providers/notion.js +44 -173
- package/dist/providers/revenuecat.d.ts +4 -57
- package/dist/providers/revenuecat.js +10 -93
- package/dist/providers/stripe.d.ts +1 -12
- package/dist/providers/stripe.js +7 -45
- package/dist/registry.d.ts +9 -34
- package/dist/registry.js +9 -103
- package/dist/routes/mcp.js +1 -1
- package/dist/routes/oauth.js +3 -3
- package/dist/routes/shared.d.ts +15 -15
- package/dist/routes/shared.js +1 -3
- package/dist/skills.d.ts +1 -1
- package/dist/skills.js +5 -5
- package/dist/timeout.d.ts +8 -7
- package/dist/timeout.js +47 -38
- package/dist/types.d.ts +3 -3
- package/dist/ui.d.ts +1 -25
- package/dist/ui.js +18 -45
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/documentation/call-admission.md +1 -1
- package/documentation/cloudflare.md +1 -1
- package/documentation/code-mode.md +25 -25
- package/documentation/connectors.md +24 -1
- package/documentation/linear.md +1 -1
- package/documentation/meta-tools.md +4 -30
- package/documentation/mixpanel.md +1 -1
- package/documentation/notion.md +1 -1
- package/documentation/operations.md +29 -25
- package/documentation/provider-conventions.md +4 -5
- package/documentation/revenuecat.md +1 -1
- package/documentation/stripe.md +1 -1
- package/documentation/upgrading.md +43 -8
- package/ethos.md +75 -121
- package/package.json +3 -4
- package/templates/node/package.json +1 -1
- package/documentation/code-first-exploration.md +0 -292
- package/documentation/mcp-2026-07-28.md +0 -46
- package/documentation/mcp-ui-design.md +0 -382
- package/documentation/program-ui-read-calls.md +0 -213
- package/documentation/provider-audit.md +0 -198
- package/documentation/rich-output-design.md +0 -211
package/ethos.md
CHANGED
|
@@ -1,149 +1,103 @@
|
|
|
1
1
|
# connecta — ethos
|
|
2
2
|
|
|
3
3
|
What connecta is, what it refuses to be, and the invariants every change must
|
|
4
|
-
preserve.
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
preserve. Deliberately terse: when a change contradicts a line here, either the
|
|
5
|
+
change is wrong or this file needs amending — in that order, and amending it is
|
|
6
|
+
a design decision, not a drive-by edit.
|
|
7
7
|
|
|
8
8
|
## What this is
|
|
9
9
|
|
|
10
|
-
- **One MCP endpoint, one programmable surface.** Every integration you
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
boundaries code must not cross, and for the jobs a program is the wrong
|
|
14
|
-
shape for.
|
|
10
|
+
- **One MCP endpoint, one programmable surface.** Every integration you chose
|
|
11
|
+
sits behind a capability catalog that agents reach by writing JavaScript,
|
|
12
|
+
ringed by a few explicit tools for the boundaries code must not cross.
|
|
15
13
|
- **A deployment is a small config-as-code file.** Changing what agents can
|
|
16
|
-
reach is an edit and a redeploy. One deployment, one tenant, one audience
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
known-good endpoint, authentication defaults, tool ergonomics, and concise
|
|
21
|
-
usage guidance. `remoteMcp()` and `api()` remain equal, first-class
|
|
22
|
-
primitives for custom and unsupported integrations. Every path produces the
|
|
23
|
-
same `Connector`: same addresses, same catalog, same safety rules.
|
|
14
|
+
reach is an edit and a redeploy. One deployment, one tenant, one audience.
|
|
15
|
+
- **Curated when available, open when not.** Prefer a maintained prebuilt
|
|
16
|
+
connection; `remoteMcp()` and `api()` stay first-class for everything else.
|
|
17
|
+
Every path yields the same `Connector` with the same rules.
|
|
24
18
|
- **Seven tools, an executor required.** The primary surface is a program, so
|
|
25
|
-
every deployment runs an executor
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
unchanged: required describes the deployment, never the dependencies.
|
|
33
|
-
- **Safe by default.** Only tools explicitly annotated read-only are callable
|
|
34
|
-
without crossing the destructive boundary — directly or from generated code;
|
|
35
|
-
everything else goes through `call_destructive_tool`, where the MCP host can
|
|
36
|
-
put the question to a human. Approval is the host's job; connecta makes the
|
|
37
|
-
question visible.
|
|
38
|
-
- **One fetch-native core, two runtimes.** The same code runs unchanged on
|
|
39
|
-
Cloudflare Workers and in Node — a Worker or a Docker stack, your pick. Web
|
|
40
|
-
APIs only in the core; Node touches live behind explicit subpaths.
|
|
19
|
+
every deployment runs an executor and one without refuses to boot. A
|
|
20
|
+
capability earns a top-level tool only by being inexpressible as a program.
|
|
21
|
+
- **Safe by default.** Only tools explicitly annotated read-only run without
|
|
22
|
+
crossing `call_destructive_tool`, where the host can ask a human. Approval is
|
|
23
|
+
the host's job; connecta makes the question visible.
|
|
24
|
+
- **One fetch-native core, two runtimes.** Web APIs only in the core; Node
|
|
25
|
+
touches live behind explicit subpaths. Cloudflare Worker or Docker, your pick.
|
|
41
26
|
- **Observable, actionable only over authentication material.** Operator pages
|
|
42
|
-
show
|
|
43
|
-
|
|
44
|
-
downstream OAuth flow. Declared capability is what they cannot touch.
|
|
27
|
+
show status and payload-free activity and may rotate credentials, issue
|
|
28
|
+
tokens, and run OAuth. Declared capability they cannot touch.
|
|
45
29
|
|
|
46
30
|
## What this isn't
|
|
47
31
|
|
|
48
|
-
- **Not a platform.** No runtime
|
|
49
|
-
|
|
50
|
-
- **Not a schema ingester.** No OpenAPI or GraphQL → tools.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
- **Not a
|
|
57
|
-
|
|
58
|
-
first, published openly. Breaking changes are cheap and the version number
|
|
59
|
-
signals change, not stability.
|
|
32
|
+
- **Not a platform.** No runtime registration, admin-editable capability,
|
|
33
|
+
policy engine, approvals, or pauses.
|
|
34
|
+
- **Not a schema ingester.** No OpenAPI or GraphQL → tools.
|
|
35
|
+
- **Not multi-tenant.** No account model or per-user credential store; scope
|
|
36
|
+
stays connector-level, and ambiguity stops rather than guesses.
|
|
37
|
+
- **Not stateful.** No protocol sessions, no server push; scope resolves per
|
|
38
|
+
request.
|
|
39
|
+
- **Not a nanny.** Credentials fail loudly at use; nothing probes one.
|
|
40
|
+
- **Not a promise to strangers — yet.** Breaking changes are cheap; the version
|
|
41
|
+
number signals change, not stability.
|
|
60
42
|
|
|
61
43
|
## Decisions
|
|
62
44
|
|
|
63
|
-
|
|
64
|
-
|
|
45
|
+
Shapes considered and turned down. Proposing one again without a new argument
|
|
46
|
+
is not allowed. Accepted designs live in their subsystem guide and the
|
|
47
|
+
CHANGELOG, not here.
|
|
65
48
|
|
|
66
49
|
| Decision | Verdict | Why |
|
|
67
50
|
| --- | --- | --- |
|
|
68
|
-
| OpenAPI / GraphQL ingestion | refused |
|
|
69
|
-
| Multi-tenancy / account model | refused | one deployment per tenant; deploy again
|
|
51
|
+
| OpenAPI / GraphQL ingestion | refused | the disease is a tool nobody chose — a document authored it; hand-written literals, even through a shared factory, are still authorship |
|
|
52
|
+
| Multi-tenancy / account model | refused | one deployment per tenant; deploy again |
|
|
70
53
|
| Policy engine, approvals, pauses | refused | the host asks the human; connecta only annotates |
|
|
71
54
|
| Runtime connector registration | refused | config-as-code is the security model |
|
|
72
|
-
|
|
|
73
|
-
|
|
|
74
|
-
| Expanded Notion page create/update options | refused | the maintained writes own explicit parents, authored content, property replacement, and reversible trash; workspace-private creation, placement, richer media, coordination locks, asynchronous templates, and irreversible child erasure are different ownership, ordering, file, coordination, or deletion workflows, not missing fields — keep the approval names honest and use a custom `api()` connector when a deployment needs one ([#408](https://github.com/zackbart/connecta/issues/408), [#409](https://github.com/zackbart/connecta/issues/409)) |
|
|
75
|
-
| Hosted-provider drift detection during catalog refreshes | accepted | a vetted classification is a claim about somebody else's catalog, and an allowlist nobody can tell is stale is an allowlist that is wrong — so each maintained hosted-MCP proxy ships the tool names, classifications, and (once a release records them) schemas it reviewed, and compares them against the live listing *inside* a catalog refresh the deployment already asked for; the boundary is the piggyback itself, which is what keeps this from being proactive credential liveness wearing a new hat ([#179](https://github.com/zackbart/connecta/issues/179)): no scheduled job, no background request, no credential probe, and not one byte of network traffic that would not have happened anyway; what it produces is four counts — unclassified additions, names no longer served, explicit annotation conflicts, schema changes — on connector status, `connecta doctor`, and one payload-free activity event with nowhere to put a tool name or a schema; the two read surfaces answer for the runtime that served the refresh, because the observation is isolate-local and only the activity event is durable, and unknown tools already fail closed, so drift costs approval round trips and stale guidance rather than capability ([#343](https://github.com/zackbart/connecta/issues/343)) |
|
|
76
|
-
| Provider registry / integration marketplace | refused | prebuilt connections are imports, not listings; discovery happens in documentation, never at runtime ([#297](https://github.com/zackbart/connecta/issues/297)) |
|
|
55
|
+
| Provider registry / marketplace | refused | prebuilt connections are imports; discovery happens in docs ([#297](https://github.com/zackbart/connecta/issues/297)) |
|
|
56
|
+
| Expanded Notion page create/update options | refused | different workflows, not missing fields; use `api()` ([#408](https://github.com/zackbart/connecta/issues/408)) |
|
|
77
57
|
| Protocol sessions & server push | refused | stateless per request |
|
|
78
|
-
| Resources & prompts aggregation | refused | tools only;
|
|
58
|
+
| Resources & prompts aggregation | refused | tools only; the Apps shell is the one `resources/read` carve-out ([#266](https://github.com/zackbart/connecta/issues/266)) |
|
|
79
59
|
| Elicitation passthrough | refused | no route through a stateless aggregator |
|
|
80
60
|
| Repository formatter | refused | style is authored, not enforced |
|
|
81
|
-
|
|
|
61
|
+
| Host-side projection of program results | refused | a program projects; a heuristic drops fields invisibly ([#223](https://github.com/zackbart/connecta/issues/223)) |
|
|
62
|
+
| `get_result` paging for program results | refused | paging rewards the unprojected return code mode exists to remove ([#223](https://github.com/zackbart/connecta/issues/223)) |
|
|
63
|
+
| Native Tasks for oversized results | refused | tasks solve duration, `get_result` solves size ([#176](https://github.com/zackbart/connecta/issues/176)) |
|
|
64
|
+
| Widening the `Executor` result contract | refused | `{ result, error?, logs? }` is the `@cloudflare/codemode` parity guarantee ([#267](https://github.com/zackbart/connecta/issues/267)) |
|
|
65
|
+
| Erasable TypeScript in `execute_code` | refused | 24 MB dependency in the core, no measured agent benefit ([#419](https://github.com/zackbart/connecta/issues/419)) |
|
|
66
|
+
| Guest-minted `resource` / `resource_link` blocks | refused | a program can never mint a URI a client may dereference ([#266](https://github.com/zackbart/connecta/issues/266)) |
|
|
67
|
+
| Provenance tracking for emitted content | refused | everything a program emits is program output ([#267](https://github.com/zackbart/connecta/issues/267)) |
|
|
68
|
+
| Result sampling on the catalog surface | refused | sampling is execution and cannot ride a catalog read ([#282](https://github.com/zackbart/connecta/issues/282)) |
|
|
69
|
+
| Legacy embedded `UIResource` delivery | refused | superseded upstream, rendered by no client we face ([#266](https://github.com/zackbart/connecta/issues/266)) |
|
|
70
|
+
| Effect as the core effect system | refused | −4% of the core for +75 KB gzip and a second async paradigm; re-measure at v4 stable ([#470](https://github.com/zackbart/connecta/issues/470)) |
|
|
71
|
+
| Shared bounded queue under both admission controllers | refused | built and measured −17 lines for a hook-parameterised abstraction ([#453](https://github.com/zackbart/connecta/issues/453)) |
|
|
72
|
+
| Toolkits (scoped views) | removed | deploy per audience ([#178](https://github.com/zackbart/connecta/issues/178)) |
|
|
82
73
|
| Proactive credential liveness | removed | fail-at-use is enough ([#179](https://github.com/zackbart/connecta/issues/179)) |
|
|
83
|
-
|
|
|
84
|
-
|
|
|
85
|
-
|
|
|
86
|
-
|
|
|
87
|
-
|
|
|
88
|
-
|
|
|
89
|
-
|
|
|
90
|
-
|
|
|
91
|
-
|
|
92
|
-
| Connector shortcut namespaces in programs | accepted | sugar over canonical addressing, kept but frozen — every expansion invents a collision class `<connectorId>.<toolName>` already solved ([#223](https://github.com/zackbart/connecta/issues/223)) |
|
|
93
|
-
| Automatic host-side projection of program results | refused | the measured win was program-authored projection; a host heuristic drops fields a program chose to return and is invisible in the transcript ([#223](https://github.com/zackbart/connecta/issues/223)) |
|
|
94
|
-
| Caller-visible execution diagnostics | accepted | optional request-local timing and size aggregates make catalog, connector, and executor costs distinguishable without persisting payloads, adding a tool, or charging normal responses context ([#247](https://github.com/zackbart/connecta/issues/247)) |
|
|
95
|
-
| `get_result` paging for program results | refused | paging rewards the unprojected return code mode exists to remove; a program can shrink anything ([#223](https://github.com/zackbart/connecta/issues/223)) |
|
|
96
|
-
| Stabilized workflows (programs → versioned scripts/skills) | gated | earns a surface only once real traffic shows programs that actually recur ([#225](https://github.com/zackbart/connecta/issues/225)) |
|
|
97
|
-
| Semantic tool search | gated | keyword search has not been shown to be the thing failing; earns its way in through [#222](https://github.com/zackbart/connecta/issues/222)'s harness ([#27](https://github.com/zackbart/connecta/issues/27)) |
|
|
98
|
-
| Per-result lexical query coverage | removed | verbose, indexed, and trailing shapes did not earn their response-token cost: the coverage-off arm beat the verbose wire, the first compact wire regressed efficiency, and the trailing wire failed its precommitted 30-run clean-route gate (13/30 vs 9/30, +13.3 pp, Fisher p=0.422); preserve the mixed complete/partial ranking from [#326](https://github.com/zackbart/connecta/issues/326), but do not revive serialized coverage without new causal evidence ([#322](https://github.com/zackbart/connecta/issues/322), [#323](https://github.com/zackbart/connecta/issues/323)) |
|
|
99
|
-
| MRTR / `input_required` passthrough | gated | statelessly relayable via `requestState`, but no host or downstream emits it yet; fails loudly until adoption evidence ([#176](https://github.com/zackbart/connecta/issues/176)) |
|
|
100
|
-
| Native Tasks for oversized results | refused | tasks solve duration, `get_result` solves size; paging on a polling extension adds round trips for nothing ([#176](https://github.com/zackbart/connecta/issues/176)) |
|
|
101
|
-
| Downstream `ttlMs` cache hints | gated | fixed TTL + fingerprint is battle-tested and catalog reads are ~3 ms; earns its way in with refresh-churn evidence ([#176](https://github.com/zackbart/connecta/issues/176)) |
|
|
102
|
-
| Inbound-demand catalog stale-while-revalidate | accepted | an agent-facing catalog read may return a complete, fingerprint-verified entry inside its configured stale window and move the refresh that same read demanded onto the runtime's existing deferred-work channel; this originates no timer, schedule, warmup, or credential probe, and operator status remains blocking — one refresh per connector is shared across agent and operator requests, a deferred owner uses a fresh bounded signal and connector scope and closes that scope, and invalidation is rechecked before stale publication, so no request-bound capability survives and no partial or pre-invalidation catalog gains authority ([#396](https://github.com/zackbart/connecta/issues/396)) |
|
|
103
|
-
| Rich program output (`connecta.emit`) | accepted | one host-collected emission channel: programs emit strictly validated text/image/audio blocks, delivered after the result envelope on success only; budgets fail loudly at the emit call ([design record](./documentation/rich-output-design.md), [#267](https://github.com/zackbart/connecta/issues/267)) |
|
|
104
|
-
| Result-channel widening of the `Executor` contract | refused | `ExecuteResult` stays `{ result, error?, logs? }` — structural compatibility with `@cloudflare/codemode` is the parity guarantee; emission rides the provider bridge instead ([#267](https://github.com/zackbart/connecta/issues/267)) |
|
|
105
|
-
| Erasable TypeScript in `execute_code` | refused | a location-preserving prototype accepted annotations, return types, assertions, aliases, interfaces, and erased generics at ~8.3 µs median transform cost, but `ts-blank-space` drags a 23.68 MB installed TypeScript dependency into the fetch-native core and no runnable agent arm established a first-run or repair benefit; the plain-JavaScript contract stands until new measured model evidence earns that package and parity cost ([evidence](https://github.com/zackbart/connecta/blob/main/eval/current-version/results/issue-419-evidence.md), [#419](https://github.com/zackbart/connecta/issues/419)) |
|
|
106
|
-
| Guest-emitted `resource` / `resource_link` blocks | refused | a program can never mint a URI a client may dereference, and the carve-out this row waited on does not need one: `connecta.ui` takes HTML content, and the only `ui://` URI is connecta's build-time shell ([design record](./documentation/mcp-ui-design.md), [#266](https://github.com/zackbart/connecta/issues/266), [#267](https://github.com/zackbart/connecta/issues/267)) |
|
|
107
|
-
| Provenance tracking for emitted content | refused | everything a program emits is program output; handles or attribution labels are capability-shaped machinery that changes no client's trust posture ([#267](https://github.com/zackbart/connecta/issues/267)) |
|
|
108
|
-
| Program-generated UI (`connecta.ui` + the Apps shell) | accepted | one MCP Apps view per successful run: the program supplies HTML only, delivered in result `_meta`, which hosts keep out of model context, and rendered by connecta's static shell inside the host's sandboxed frame ([design record](./documentation/mcp-ui-design.md), [#266](https://github.com/zackbart/connecta/issues/266)) |
|
|
109
|
-
| Serving connecta's own UI template via `resources/read` | accepted | a narrow carve-out from the resources-aggregation refusal, not a reversal of it: one static build-time shell at one URI, an empty `resources/list`, nothing downstream ever listed or aggregated ([#266](https://github.com/zackbart/connecta/issues/266)) |
|
|
110
|
-
| Downstream MCP Apps template passthrough | gated | proxying downstream `resources/read` earns its way in when a downstream connector actually ships an Apps template ([#266](https://github.com/zackbart/connecta/issues/266)) |
|
|
111
|
-
| View-initiated read calls from program UI | accepted | named bindings materially improve refresh, cursor pagination, and drill-down without persistence or a new tool; the trusted shell delegates only to the existing fail-closed `call_tool`, and the one-string UI remains display-only ([evidence](./documentation/program-ui-read-calls.md), [#287](https://github.com/zackbart/connecta/issues/287), [#289](https://github.com/zackbart/connecta/issues/289)) |
|
|
112
|
-
| View-initiated mutation calls from program UI | gated | live-read utility says nothing about write consent: a click is not approval, stale/replayed effects need a host-tested story, and the ordinary destructive path keeps the action in the transcript ([#287](https://github.com/zackbart/connecta/issues/287)) |
|
|
113
|
-
| Result sampling on the catalog surface (`sample` / `dryRun`) | refused | sampling is execution and cannot ride a catalog read; most tools carry required arguments no sampler can invent, and undeclared `outputSchema` (measured 0/30 and 3/30 on real deployments) is a real gap that is not a sampleable one — a program that checks the shape before rendering already hands back the first record inside the run it was going to make anyway, at zero new surface ([#282](https://github.com/zackbart/connecta/issues/282)) |
|
|
114
|
-
| Passive observed output schemas | accepted | the sampling refusal stands: discovery originates no call and invents no arguments; instead, a successful explicitly read-only call whose provider declared no `outputSchema` records field names and broad JSON types only, under strict depth, breadth, property-name, node, and byte bounds, then merges that open optional-field shape in a 256-entry process-local cache for 24 hours; property names may be user-authored, search and describe label the shape `outputSchemaSource: "observed"`, a materially changed tool definition cannot inherit it, a provider declaration always wins, and no argument, scalar value, raw result, code, credential, or error is retained; this is new evidence rather than a rewrite of #282's facts: Blacksmith measured a value-free warm shape cache cutting one Linear code-mode task from 116.6 s / $1.91 to 56.6 s / $1.06, while live Connecta catalogs measured 246/378 missing on BePresent and 0/90 missing on OneMany ([study](https://www.blacksmith.sh/blog/code-smith-code-mode), [#442](https://github.com/zackbart/connecta/issues/442)) |
|
|
115
|
-
| Legacy embedded `UIResource` delivery | refused | superseded upstream and rendered by none of the clients connecta faces; per-request minted URIs also fight the caching the Apps spec assumes ([#266](https://github.com/zackbart/connecta/issues/266)) |
|
|
74
|
+
| Classic (executor-free) surface | removed | an executor is mandatory ([#273](https://github.com/zackbart/connecta/issues/273)) |
|
|
75
|
+
| Per-result lexical query coverage | removed | did not earn its response bytes in a precommitted gate ([#323](https://github.com/zackbart/connecta/issues/323)) |
|
|
76
|
+
| Stabilized workflows | gated | needs programs that actually recur ([#225](https://github.com/zackbart/connecta/issues/225)) |
|
|
77
|
+
| Semantic tool search | gated | keyword search has not been shown to fail ([#27](https://github.com/zackbart/connecta/issues/27)) |
|
|
78
|
+
| MRTR / `input_required` passthrough | gated | relayable statelessly; no host or downstream emits it yet ([#176](https://github.com/zackbart/connecta/issues/176)) |
|
|
79
|
+
| Downstream `ttlMs` cache hints | gated | needs refresh-churn evidence ([#206](https://github.com/zackbart/connecta/issues/206)) |
|
|
80
|
+
| Downstream MCP Apps template passthrough | gated | needs a downstream that ships one ([#266](https://github.com/zackbart/connecta/issues/266)) |
|
|
81
|
+
| Program UI tool calls | removed | the read bridge added a second contract without improving agent data retrieval; views are display-only again ([#287](https://github.com/zackbart/connecta/issues/287), [#484](https://github.com/zackbart/connecta/issues/484)) |
|
|
82
|
+
|
|
116
83
|
## Invariants
|
|
117
84
|
|
|
118
|
-
One line each; the enforcing tests live beside the subsystem documentation.
|
|
85
|
+
One line each; the enforcing tests live beside the subsystem documentation.
|
|
86
|
+
Breaking one is a design change wearing a disguise.
|
|
119
87
|
|
|
120
|
-
- **Fail-closed read-only.** A missing, false, or contradictory annotation
|
|
121
|
-
|
|
122
|
-
- **
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
- **
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
- **Nothing
|
|
129
|
-
|
|
130
|
-
- **
|
|
131
|
-
|
|
132
|
-
- **Activity is payload-free by construction.** The event type has nowhere to
|
|
133
|
-
put arguments, results, code, or raw error text.
|
|
134
|
-
- **An observed shape is never a declaration.** It contains field names and broad JSON types only, remains open and optional, is labeled on discovery, and disappears behind any provider-declared output schema.
|
|
135
|
-
- **Credentials never leave the host.** Encrypted at rest, readable only by
|
|
136
|
-
the owning connector, never rendered by any surface.
|
|
137
|
-
- **Import-graph purity.** Nothing reachable from the root entry imports a
|
|
138
|
-
`node:` builtin.
|
|
139
|
-
- **The published surface is a boundary.** Heavyweight or platform-bound code
|
|
140
|
-
goes behind an optional-peer subpath, never into core.
|
|
141
|
-
- **Operator routes manage authentication material, never declared
|
|
142
|
-
capability.** Authenticating a declared capability is allowed; the connector
|
|
143
|
-
set, declared catalog and annotations, OAuth scopes, admission, authorization
|
|
144
|
-
rules, and caller tool scope take a config edit. A downstream catalog is
|
|
145
|
-
discovered, not declared — remote MCP tools appear when its credential does.
|
|
146
|
-
- **Structural mistakes throw at construction.** A deployment that boots into
|
|
147
|
-
the wrong shape is worse than one that refuses to boot.
|
|
88
|
+
- **Fail-closed read-only.** A missing, false, or contradictory annotation never gets the benefit of the doubt.
|
|
89
|
+
- **Generated code cannot mint capabilities.** Admission, credentials, and classification are enforced below the sandbox.
|
|
90
|
+
- **Only explicitly read-only work runs inside the sandbox.** Everything else crosses `call_destructive_tool`.
|
|
91
|
+
- **Nothing request-bound survives a request.** No transport, stream, signal, or awaited promise outlives it.
|
|
92
|
+
- **A downstream catalog is complete or it is a failure.** A partial catalog is never cached, persisted, or served.
|
|
93
|
+
- **Activity is payload-free by construction.** The event type has nowhere to put arguments, results, code, or raw errors.
|
|
94
|
+
- **An observed shape is never a declaration.** Names and broad types only, labeled, and gone behind any declared schema.
|
|
95
|
+
- **Credentials never leave the host.** Encrypted at rest, readable only by the owning connector, rendered by nothing.
|
|
96
|
+
- **Import-graph purity.** Nothing reachable from the root entry imports a `node:` builtin.
|
|
97
|
+
- **The published surface is a boundary.** Heavyweight or platform-bound code goes behind an optional-peer subpath.
|
|
98
|
+
- **Operator routes manage authentication material, never declared capability.** A downstream catalog is discovered, not declared.
|
|
99
|
+
- **Structural mistakes throw at construction.** Booting into the wrong shape is worse than not booting.
|
|
148
100
|
|
|
149
|
-
Connecta began as a radical simplification of
|
|
101
|
+
Connecta began as a radical simplification of
|
|
102
|
+
[executor](https://github.com/UsefulSoftwareCo/executor); this file is the
|
|
103
|
+
record of that simplification holding.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zackbart/connecta",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"description": "One MCP to rule them all — a single MCP endpoint aggregating many downstream connectors behind a code-first surface of seven meta-tools.",
|
|
@@ -105,12 +105,11 @@
|
|
|
105
105
|
"check:examples": "tsc -p tsconfig.template.node.json && tsc -p tsconfig.examples.worker.json",
|
|
106
106
|
"check:security": "npm audit --omit=dev --audit-level=moderate",
|
|
107
107
|
"check:package": "node scripts/check-package.mjs",
|
|
108
|
-
"load:admission": "npm run build && node
|
|
108
|
+
"load:admission": "npm run build && node eval/admission-load.mjs",
|
|
109
109
|
"drift:check": "tsx scripts/drift-check.mjs",
|
|
110
110
|
"check": "npm run check:docs && npm run check:operator-ui && npm run check:lint && npm run check:unused && npm run typecheck && npm run test && npm run build && npm run check:examples",
|
|
111
111
|
"release:check": "npm run check && npm run check:security && npm run check:package",
|
|
112
|
-
"prepack": "npm run check"
|
|
113
|
-
"prepublishOnly": "npm run check:security"
|
|
112
|
+
"prepack": "npm run check"
|
|
114
113
|
},
|
|
115
114
|
"dependencies": {
|
|
116
115
|
"@cfworker/json-schema": "^4.1.1",
|
|
@@ -1,292 +0,0 @@
|
|
|
1
|
-
# Code-first Connecta: exploration findings
|
|
2
|
-
|
|
3
|
-
> **Read as a record, not as current policy.** This is the exploration that
|
|
4
|
-
> started the arc, kept as written. Two of its conclusions have since been
|
|
5
|
-
> overtaken, and [`ethos.md`](../ethos.md)'s decisions table is the authority
|
|
6
|
-
> where they disagree:
|
|
7
|
-
>
|
|
8
|
-
> - **The ~32% definition-size reduction was an estimate.** The shipped fold
|
|
9
|
-
> measures **19.6%** on the same 10-tools-to-7 comparison (10,675B → 8,587B).
|
|
10
|
-
> The prototype's seven descriptions were thinner than the ones connecta
|
|
11
|
-
> actually ships.
|
|
12
|
-
> - **The "require repeated pinned-model evaluation before changing the default"
|
|
13
|
-
> constraint below was dropped.** The owner decided the default directly on
|
|
14
|
-
> 2026-07-30 and [#224](https://github.com/zackbart/connecta/issues/224)
|
|
15
|
-
> shipped it; the ethos records the eval-as-gate as `removed` and
|
|
16
|
-
> [`eval/code-first-gate`](https://github.com/zackbart/connecta/blob/main/eval/code-first-gate/README.md) continues as
|
|
17
|
-
> measurement that nothing waits on.
|
|
18
|
-
|
|
19
|
-
## Executive summary
|
|
20
|
-
|
|
21
|
-
We explored whether Connecta should make code execution the primary interface
|
|
22
|
-
for connector work instead of exposing a growing collection of top-level
|
|
23
|
-
meta-tools.
|
|
24
|
-
|
|
25
|
-
The experiment supports that direction.
|
|
26
|
-
|
|
27
|
-
A code-first surface was easier for a cold-start model to use than expected,
|
|
28
|
-
materially reduced fixed tool-schema context, and was especially effective for
|
|
29
|
-
workflows involving discovery, fan-out, joins, retries, and large-result
|
|
30
|
-
projection. QuickJS added measurable runtime overhead, but not enough to be
|
|
31
|
-
meaningful beside model generation and downstream service latency in normal
|
|
32
|
-
agent work.
|
|
33
|
-
|
|
34
|
-
The recommendation is to evolve Connecta toward:
|
|
35
|
-
|
|
36
|
-
- one programmable, read-oriented execution surface;
|
|
37
|
-
- a very small set of explicit tools for consequential writes, authorization,
|
|
38
|
-
and result retrieval;
|
|
39
|
-
- policy, credentials, egress, and auditing enforced below generated code; and
|
|
40
|
-
- the current tool surface retained as a compatibility path and evaluation
|
|
41
|
-
control while the new path matures — a retention that ended with #273, which
|
|
42
|
-
made the executor mandatory and deleted the classic surface outright.
|
|
43
|
-
|
|
44
|
-
This was an exploratory spike, not a production implementation. The next agent
|
|
45
|
-
should use these findings as a design brief rather than porting the prototype
|
|
46
|
-
wholesale.
|
|
47
|
-
|
|
48
|
-
## What we were testing
|
|
49
|
-
|
|
50
|
-
The central question was:
|
|
51
|
-
|
|
52
|
-
> Can a model use ordinary JavaScript against typed Connecta capabilities as
|
|
53
|
-
> its default tool interface, while preserving Connecta's safety boundaries and
|
|
54
|
-
> improving context efficiency?
|
|
55
|
-
|
|
56
|
-
The prototype made `execute_code` the normal path for reads and composition.
|
|
57
|
-
Generated code could discover tools, call read-only connector operations,
|
|
58
|
-
parallelize work, join results, retry transient failures, and project large
|
|
59
|
-
responses before returning anything to the model.
|
|
60
|
-
|
|
61
|
-
High-consequence operations did not move into the sandbox. Writes still had to
|
|
62
|
-
cross the explicit destructive-call boundary, where policy and human approval
|
|
63
|
-
remain visible.
|
|
64
|
-
|
|
65
|
-
We compared this with the existing surface using the same in-memory connectors
|
|
66
|
-
and scenarios. We also gave the code-first interface to a pinned Terra model
|
|
67
|
-
with no conversation history to test whether the interface was legible without
|
|
68
|
-
the context of the experiment.
|
|
69
|
-
|
|
70
|
-
## What we observed
|
|
71
|
-
|
|
72
|
-
### 1. The model-facing surface became smaller
|
|
73
|
-
|
|
74
|
-
The prototype reduced the visible surface from 10 tools to 7 and reduced
|
|
75
|
-
serialized tool definitions by about 32%.
|
|
76
|
-
|
|
77
|
-
That reduction matters beyond the raw token count. It removes overlapping
|
|
78
|
-
routing choices between direct calls, batches, discovery, and execution. The
|
|
79
|
-
model decides what program to write; JavaScript handles the deterministic
|
|
80
|
-
control flow between capabilities.
|
|
81
|
-
|
|
82
|
-
This is likely the largest long-term simplification. New connectors can expand
|
|
83
|
-
the typed capability catalog without expanding the always-loaded top-level
|
|
84
|
-
toolbox at the same rate.
|
|
85
|
-
|
|
86
|
-
### 2. Composition is where code mode clearly wins
|
|
87
|
-
|
|
88
|
-
The most compelling results came from tasks where intermediate data did not
|
|
89
|
-
need to return to the model:
|
|
90
|
-
|
|
91
|
-
- Discovery performed inside a workflow used one MCP call instead of two and
|
|
92
|
-
returned about 77% fewer bytes.
|
|
93
|
-
- Projecting a large event export down to three identifiers returned about 93%
|
|
94
|
-
fewer bytes.
|
|
95
|
-
- A dependent account-and-usage join reduced three MCP calls to two.
|
|
96
|
-
- Parallel fan-out and repeated warm reads returned fewer bytes while keeping
|
|
97
|
-
orchestration deterministic inside one execution.
|
|
98
|
-
|
|
99
|
-
These are not merely transport savings. They also reduce the number of points
|
|
100
|
-
where the model must inspect an intermediate result and decide the next action.
|
|
101
|
-
|
|
102
|
-
### 3. Simple calls do not become intrinsically cheaper
|
|
103
|
-
|
|
104
|
-
A single cold lookup returned more bytes and took longer through code mode than
|
|
105
|
-
through a direct tool call. A retry scenario showed the same tradeoff.
|
|
106
|
-
|
|
107
|
-
This does not undermine code-first as the model-facing abstraction. It does
|
|
108
|
-
mean we should not confuse a simpler interface with a universally faster
|
|
109
|
-
execution path. Connecta can preserve one code-shaped interface while
|
|
110
|
-
optimizing simple calls beneath it later, if measurement shows that is useful.
|
|
111
|
-
|
|
112
|
-
### 4. Perceived user speed should be effectively unchanged
|
|
113
|
-
|
|
114
|
-
With the built package, the first QuickJS execution was roughly 63–67 ms.
|
|
115
|
-
Later executions in the same child were generally 1.6–2.8 ms. QuickJS/WASM
|
|
116
|
-
initialization itself was only about 6 ms; most cold cost came from starting
|
|
117
|
-
the Node child, loading modules, and IPC.
|
|
118
|
-
|
|
119
|
-
That overhead is real but normally small compared with model inference and
|
|
120
|
-
network-bound connector calls. Users are unlikely to perceive it as a distinct
|
|
121
|
-
delay. Optimizing the child lifecycle may eventually be worthwhile, but it
|
|
122
|
-
should not block the product direction.
|
|
123
|
-
|
|
124
|
-
### 5. A cold-start model could use the interface successfully
|
|
125
|
-
|
|
126
|
-
The pinned Terra sample completed all 10 behavioral scenarios. It made no
|
|
127
|
-
invalid top-level tool selections, and every ordinary first program was valid
|
|
128
|
-
JavaScript that ran without repair. The one repair was deliberately induced by
|
|
129
|
-
giving it malformed discovery arguments.
|
|
130
|
-
|
|
131
|
-
The scenarios covered:
|
|
132
|
-
|
|
133
|
-
- a simple lookup;
|
|
134
|
-
- parallel fan-out;
|
|
135
|
-
- a dependent join;
|
|
136
|
-
- discovery within execution;
|
|
137
|
-
- projection of a large result;
|
|
138
|
-
- a safely retried read;
|
|
139
|
-
- colliding connector names addressed canonically;
|
|
140
|
-
- typed batch failures;
|
|
141
|
-
- malformed-argument repair; and
|
|
142
|
-
- discovery of a destructive operation followed by sandbox refusal.
|
|
143
|
-
|
|
144
|
-
This is encouraging evidence of interface legibility, not a statistical model
|
|
145
|
-
benchmark. It was one sample from one pinned model.
|
|
146
|
-
|
|
147
|
-
### 6. The safety boundary belongs below generated code
|
|
148
|
-
|
|
149
|
-
The experiment reinforced that sandboxing alone is not the security model.
|
|
150
|
-
Generated code must remain unable to grant itself capabilities.
|
|
151
|
-
|
|
152
|
-
Connecta's durable boundary should continue to provide:
|
|
153
|
-
|
|
154
|
-
- short-lived, brokered credentials rather than raw secrets;
|
|
155
|
-
- request-scoped capability and connector policy;
|
|
156
|
-
- read-only identities and narrowly scoped OAuth grants;
|
|
157
|
-
- controlled network egress;
|
|
158
|
-
- an explicit path for destructive or irreversible operations;
|
|
159
|
-
- complete traces of programs, calls, outputs, and policy decisions; and
|
|
160
|
-
- retry semantics appropriate to each operation.
|
|
161
|
-
|
|
162
|
-
The sandbox should be treated as an additional containment layer. Admission,
|
|
163
|
-
authorization, credentials, and destructive-action policy remain authoritative
|
|
164
|
-
outside it.
|
|
165
|
-
|
|
166
|
-
### 7. QuickJS remains the right default runtime for now
|
|
167
|
-
|
|
168
|
-
We compared the available Bellard QuickJS and QuickJS-NG variants. Both
|
|
169
|
-
initialized in roughly 6 ms, and their local transformation performance was
|
|
170
|
-
effectively equivalent for this use case. The comparison provided no reason to
|
|
171
|
-
switch engines.
|
|
172
|
-
|
|
173
|
-
QuickJS remains a good Node default because it provides explicit memory, stack,
|
|
174
|
-
and interrupt limits behind a small host interface. Running it in a child
|
|
175
|
-
process also contains interpreter and WASM failure. Cloudflare deployments
|
|
176
|
-
should continue using the platform-native Dynamic Worker executor.
|
|
177
|
-
|
|
178
|
-
The current binding can be upgraded and re-evaluated separately. Changing the
|
|
179
|
-
engine is not the solution to child-process startup cost.
|
|
180
|
-
|
|
181
|
-
## What the experiment proved—and what it did not
|
|
182
|
-
|
|
183
|
-
The evidence is strong enough to treat code-first as Connecta's intended
|
|
184
|
-
product direction. It showed that the interface can be smaller, that a capable
|
|
185
|
-
model can understand it cold, that composition and projection produce large
|
|
186
|
-
context savings, and that the explicit write boundary can remain intact.
|
|
187
|
-
|
|
188
|
-
It did not establish:
|
|
189
|
-
|
|
190
|
-
- success rates across repeated prompt variations;
|
|
191
|
-
- behavior across multiple model families and versions;
|
|
192
|
-
- performance against a large real-world connector catalog;
|
|
193
|
-
- production reliability under concurrency and partial failure;
|
|
194
|
-
- the best final guest API; or
|
|
195
|
-
- whether direct connector shortcut namespaces are worth their additional
|
|
196
|
-
complexity.
|
|
197
|
-
|
|
198
|
-
The existing surface should therefore remain available during the transition
|
|
199
|
-
as a compatibility mode, rollback path, and experimental control. It was, and
|
|
200
|
-
then it was not: #224 made code-first the default and #273 removed the second
|
|
201
|
-
shape entirely. The open questions above outlived the control arm rather than
|
|
202
|
-
being settled by it.
|
|
203
|
-
|
|
204
|
-
## Recommended product shape
|
|
205
|
-
|
|
206
|
-
The smallest promising surface is:
|
|
207
|
-
|
|
208
|
-
1. `execute_code` as the default read, discovery, transformation, and
|
|
209
|
-
composition interface.
|
|
210
|
-
2. A canonical in-program API such as `connecta.search`,
|
|
211
|
-
`connecta.describe`, `connecta.call`, and `connecta.batch`.
|
|
212
|
-
3. An explicit destructive-call tool for writes and irreversible actions.
|
|
213
|
-
4. Explicit authorization and deferred-result tools where those boundaries
|
|
214
|
-
cannot safely live inside execution.
|
|
215
|
-
5. Skills that teach domain playbooks without adding more always-loaded verbs.
|
|
216
|
-
|
|
217
|
-
Canonical addressing should remain available even if ergonomic connector
|
|
218
|
-
shortcuts are offered. It prevents sanitized-name collisions and gives
|
|
219
|
-
generated programs a stable escape hatch.
|
|
220
|
-
|
|
221
|
-
## Suggested implementation sequence
|
|
222
|
-
|
|
223
|
-
### Phase 1: establish the evaluation gate
|
|
224
|
-
|
|
225
|
-
Turn the exploratory scenarios into a repeatable evaluation suite before
|
|
226
|
-
changing the default surface. Run at least 20 independent samples per task and
|
|
227
|
-
model, with prompt variation.
|
|
228
|
-
|
|
229
|
-
That suite was built under
|
|
230
|
-
[`eval/code-first-gate`](https://github.com/zackbart/connecta/blob/main/eval/code-first-gate/README.md). Its recorded results
|
|
231
|
-
remain as measurement history; the runnable comparison was retired when #273
|
|
232
|
-
removed the alternate deployment shapes.
|
|
233
|
-
|
|
234
|
-
Capture:
|
|
235
|
-
|
|
236
|
-
- task success;
|
|
237
|
-
- invalid tool selection;
|
|
238
|
-
- syntax and runtime failures;
|
|
239
|
-
- repair turns;
|
|
240
|
-
- MCP calls;
|
|
241
|
-
- request, response, and total transcript tokens;
|
|
242
|
-
- time to first correct answer; and
|
|
243
|
-
- attempted safety-boundary violations.
|
|
244
|
-
|
|
245
|
-
Keep results separated by model and version. The model's ability to write and
|
|
246
|
-
repair code is the independent variable, so blended scores would hide the
|
|
247
|
-
signal we care about.
|
|
248
|
-
|
|
249
|
-
### Phase 2: define the code-first contract
|
|
250
|
-
|
|
251
|
-
Specify the guest API, error shapes, projection behavior, retry semantics,
|
|
252
|
-
canonical addressing, cancellation, limits, and audit events before optimizing
|
|
253
|
-
the runtime.
|
|
254
|
-
|
|
255
|
-
The current architecture already has useful foundations: request-local
|
|
256
|
-
catalogs, centralized invocation, admission control, and lazy connector
|
|
257
|
-
capabilities. Build the new surface on those rather than recreating parallel
|
|
258
|
-
logic in the executor.
|
|
259
|
-
|
|
260
|
-
### Phase 3: consolidate the surface
|
|
261
|
-
|
|
262
|
-
This phase is complete: code-first became the default in #224, then #273 made
|
|
263
|
-
the executor mandatory and removed the deployment choice. Consequential writes
|
|
264
|
-
remain outside the sandbox. New top-level read tools still require a measured
|
|
265
|
-
case that cannot be expressed safely or clearly through the programmable
|
|
266
|
-
surface.
|
|
267
|
-
|
|
268
|
-
### Phase 4: stabilize successful workflows
|
|
269
|
-
|
|
270
|
-
When an agent repeatedly discovers the same successful program, allow it to
|
|
271
|
-
become a versioned script, test, or skill. Run that stabilized workflow
|
|
272
|
-
deterministically and bring the model back only when inputs or interfaces
|
|
273
|
-
change.
|
|
274
|
-
|
|
275
|
-
This progression—tool mode to code mode to stabilized mode—is where the
|
|
276
|
-
largest reliability and cost gains are likely to emerge.
|
|
277
|
-
|
|
278
|
-
## Decision
|
|
279
|
-
|
|
280
|
-
Proceed with code-first as the next direction for Connecta, with three
|
|
281
|
-
constraints:
|
|
282
|
-
|
|
283
|
-
1. Treat the current evidence as a strong exploratory result, not a completed
|
|
284
|
-
production validation.
|
|
285
|
-
2. Preserve explicit external governance for writes and other consequential
|
|
286
|
-
actions.
|
|
287
|
-
3. Require repeated pinned-model evaluation before changing the default for
|
|
288
|
-
users.
|
|
289
|
-
|
|
290
|
-
The next implementation should optimize for a coherent, minimal contract and
|
|
291
|
-
measurable behavior—not for preserving every detail of the exploratory
|
|
292
|
-
prototype.
|