@zackbart/connecta 0.12.0 → 0.12.2
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 +80 -0
- package/dist/apps-shell.d.ts +13 -11
- package/dist/apps-shell.d.ts.map +1 -1
- package/dist/apps-shell.js +221 -30
- package/dist/apps-shell.js.map +1 -1
- package/dist/execute.d.ts +12 -4
- package/dist/execute.d.ts.map +1 -1
- package/dist/execute.js +140 -20
- package/dist/execute.js.map +1 -1
- package/dist/meta-tools.d.ts.map +1 -1
- package/dist/meta-tools.js +9 -0
- package/dist/meta-tools.js.map +1 -1
- package/dist/skills.d.ts +2 -2
- package/dist/skills.d.ts.map +1 -1
- package/dist/skills.js +19 -14
- package/dist/skills.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/documentation/code-mode.md +38 -15
- package/documentation/mcp-ui-design.md +8 -8
- package/documentation/program-ui-read-calls.md +213 -0
- package/ethos.md +3 -1
- package/package.json +1 -1
- package/src/apps-shell.ts +221 -30
- package/src/execute.ts +207 -21
- package/src/meta-tools.ts +9 -0
- package/src/skills.ts +19 -14
- package/src/version.ts +1 -1
- package/templates/node/package.json +1 -1
package/dist/skills.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Connector } from "./types.js";
|
|
2
|
-
export declare const CONNECTA_INSTRUCTIONS = "Connecta exposes
|
|
3
|
-
export declare const USAGE_SKILL = "# Connecta usage\n\n## The surface\n\nSeven tools: `execute_code`, `search_tools`, `call_tool`, `call_destructive_tool`, `authorize_connector`, `get_result`, `skills`. Broad discovery and multi-call work live
|
|
2
|
+
export declare const CONNECTA_INSTRUCTIONS = "Connecta exposes seven meta-tools. execute_code is primary: use connecta.search, describe, call, and batch for discovery, multiple or dependent calls, loops, joins, and result reduction. connecta.ui(html) is a guest function inside execute_code, never a connector address or search_tools result; pass one HTML string for display-only, or bind named read-only refresh/drill-down calls in its optional reads argument, and return the same initial summary data the HTML renders. For one read at an unknown address, search_tools with 2\u20134 distinctive action/object terms and includeSchemas=\"compact\", then one call_tool \u2014 a lone cold call is cheaper direct than a program. Use call_destructive_tool individually for unannotated, write-capable, or destructive tools; authorize_connector follows auth_required; get_result follows truncation. If this routing is unfamiliar, fetch skills({ name: \"usage\" }).";
|
|
3
|
+
export declare const USAGE_SKILL = "# Connecta usage\n\n## The surface\n\nSeven tools: `execute_code`, `search_tools`, `call_tool`, `call_destructive_tool`, `authorize_connector`, `get_result`, `skills`. Broad discovery and multi-call work live in a program, not in top-level tools.\n\n## Choose the smallest execution tool\n\nUse exact addresses from discovery; never invent one. Search 2\u20134 distinctive action/object terms, not the whole request.\n\n- One read at an unknown address: `search_tools({ query, includeSchemas: \"compact\" })`, then `call_tool` once \u2014 one cold call is cheaper direct than a program.\n- Anything wider \u2014 two or more calls, dependent steps, loops, joins, branching, a whole-catalog browse, or a result to reduce: one `execute_code` run.\n- Any unannotated, write-capable, or destructive call: `call_destructive_tool`, one at a time, after reviewing its schema and consequences.\n- Truncated result: retry with `fields`, else page it with `get_result`.\n- `auth_required`: `authorize_connector`, hand its recovery text to the operator, retry the call.\n\n## Inside a program\n\nOne async arrow function. The only capabilities are one global per connector (`<connectorId>.<toolName>(args)`), the `connecta` functions, and `console.log`.\n\n- `connecta.search({})` browses every catalog; `safety: \"readOnly\"` narrows to calls a program can execute, `connector: \"<id>\"` to one. This filters results, not authority; matches carry `address` and annotations.\n- Exact schemas: `connecta.describe({ address: \"connector.tool\" })` for one, `{ addresses: [...] }` for many; `format: \"json\"` only for exact constraints.\n- Two to ten independent calls: `connecta.batch([...])`. Each outcome is `{ address, ok: true, data }` or `{ address, ok: false, error, errorDetails: { code, retryable } }` \u2014 how a program tells a policy refusal from a transient failure.\n- Search inside the run, not before it; return only the reduction the answer needs, never raw payloads.\n- Only tools annotated `readOnlyHint: true` are reachable; the gate, credentials, and admission are enforced below the sandbox \u2014 nothing a program does widens its reach.\n\n## Rendering a view\n\n`connecta.ui(html)` renders a display-only view on success for the client, never for the model. Fetch first, check the shape in code. On a surprise \u2014 empty array, missing key \u2014 return a trimmed first record instead of rendering: the wrong view becomes the sample you needed. Otherwise render from the variables you return; the model reads the return value, not the view.\n\n";
|
|
4
4
|
/**
|
|
5
5
|
* Appended to USAGE_SKILL only when the deployment actually has at least one
|
|
6
6
|
* connector guide. A deployment with none — every deployment that has not
|
package/dist/skills.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../src/skills.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,eAAO,MAAM,qBAAqB
|
|
1
|
+
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../src/skills.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,eAAO,MAAM,qBAAqB,o5BACm2B,CAAC;AAEt4B,eAAO,MAAM,WAAW,mgFA8BvB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,2eAIpC,CAAC;AAEF,mDAAmD;AACnD,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED,oEAAoE;AACpE,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,GAAG,OAAO,CAI5E;AA0BD,uDAAuD;AACvD,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED,kFAAkF;AAClF,wBAAgB,cAAc,CAAC,SAAS,EAAE,SAAS,GAAG,MAAM,GAAG,SAAS,CAGvE;AAyDD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,GAAG,YAAY,EAAE,CAc3E;AAED,MAAM,MAAM,WAAW,GACrB;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvE;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,SAAS,SAAS,EAAE,GAC/B,WAAW,CAwCb"}
|
package/dist/skills.js
CHANGED
|
@@ -1,29 +1,34 @@
|
|
|
1
|
-
export const CONNECTA_INSTRUCTIONS = 'Connecta exposes
|
|
1
|
+
export const CONNECTA_INSTRUCTIONS = 'Connecta exposes seven meta-tools. execute_code is primary: use connecta.search, describe, call, and batch for discovery, multiple or dependent calls, loops, joins, and result reduction. connecta.ui(html) is a guest function inside execute_code, never a connector address or search_tools result; pass one HTML string for display-only, or bind named read-only refresh/drill-down calls in its optional reads argument, and return the same initial summary data the HTML renders. For one read at an unknown address, search_tools with 2–4 distinctive action/object terms and includeSchemas="compact", then one call_tool — a lone cold call is cheaper direct than a program. Use call_destructive_tool individually for unannotated, write-capable, or destructive tools; authorize_connector follows auth_required; get_result follows truncation. If this routing is unfamiliar, fetch skills({ name: "usage" }).';
|
|
2
2
|
export const USAGE_SKILL = `# Connecta usage
|
|
3
3
|
|
|
4
4
|
## The surface
|
|
5
5
|
|
|
6
|
-
Seven tools: \`execute_code\`, \`search_tools\`, \`call_tool\`, \`call_destructive_tool\`, \`authorize_connector\`, \`get_result\`, \`skills\`. Broad discovery and multi-call work live
|
|
6
|
+
Seven tools: \`execute_code\`, \`search_tools\`, \`call_tool\`, \`call_destructive_tool\`, \`authorize_connector\`, \`get_result\`, \`skills\`. Broad discovery and multi-call work live in a program, not in top-level tools.
|
|
7
7
|
|
|
8
8
|
## Choose the smallest execution tool
|
|
9
9
|
|
|
10
|
-
Use exact addresses
|
|
10
|
+
Use exact addresses from discovery; never invent one. Search 2–4 distinctive action/object terms, not the whole request.
|
|
11
11
|
|
|
12
|
-
- One read at an unknown address: \`search_tools({ query, includeSchemas: "compact" })\`, then \`call_tool\` once
|
|
13
|
-
- Anything wider — two or more calls, dependent steps, loops, joins, branching,
|
|
14
|
-
- Any unannotated, write-capable, or destructive call: \`call_destructive_tool\`,
|
|
15
|
-
- Truncated result: retry with \`fields
|
|
16
|
-
- \`auth_required\`:
|
|
12
|
+
- One read at an unknown address: \`search_tools({ query, includeSchemas: "compact" })\`, then \`call_tool\` once — one cold call is cheaper direct than a program.
|
|
13
|
+
- Anything wider — two or more calls, dependent steps, loops, joins, branching, a whole-catalog browse, or a result to reduce: one \`execute_code\` run.
|
|
14
|
+
- Any unannotated, write-capable, or destructive call: \`call_destructive_tool\`, one at a time, after reviewing its schema and consequences.
|
|
15
|
+
- Truncated result: retry with \`fields\`, else page it with \`get_result\`.
|
|
16
|
+
- \`auth_required\`: \`authorize_connector\`, hand its recovery text to the operator, retry the call.
|
|
17
17
|
|
|
18
18
|
## Inside a program
|
|
19
19
|
|
|
20
|
-
One async arrow function. The only capabilities are one global per connector (\`<connectorId>.<toolName>(args)\`), the
|
|
20
|
+
One async arrow function. The only capabilities are one global per connector (\`<connectorId>.<toolName>(args)\`), the \`connecta\` functions, and \`console.log\`.
|
|
21
|
+
|
|
22
|
+
- \`connecta.search({})\` browses every catalog; \`safety: "readOnly"\` narrows to calls a program can execute, \`connector: "<id>"\` to one. This filters results, not authority; matches carry \`address\` and annotations.
|
|
23
|
+
- Exact schemas: \`connecta.describe({ address: "connector.tool" })\` for one, \`{ addresses: [...] }\` for many; \`format: "json"\` only for exact constraints.
|
|
24
|
+
- Two to ten independent calls: \`connecta.batch([...])\`. Each outcome is \`{ address, ok: true, data }\` or \`{ address, ok: false, error, errorDetails: { code, retryable } }\` — how a program tells a policy refusal from a transient failure.
|
|
25
|
+
- Search inside the run, not before it; return only the reduction the answer needs, never raw payloads.
|
|
26
|
+
- Only tools annotated \`readOnlyHint: true\` are reachable; the gate, credentials, and admission are enforced below the sandbox — nothing a program does widens its reach.
|
|
27
|
+
|
|
28
|
+
## Rendering a view
|
|
29
|
+
|
|
30
|
+
\`connecta.ui(html)\` renders a display-only view on success for the client, never for the model. Fetch first, check the shape in code. On a surprise — empty array, missing key — return a trimmed first record instead of rendering: the wrong view becomes the sample you needed. Otherwise render from the variables you return; the model reads the return value, not the view.
|
|
21
31
|
|
|
22
|
-
- What exists: \`connecta.search({})\` browses every catalog; add \`safety: "readOnly"\` for only calls the program can execute, and \`connector: "<id>"\` to browse one. This filters discovery results, not authority, and each match carries its \`address\` and annotations.
|
|
23
|
-
- Exact schemas for known addresses: \`connecta.describe({ address: "connector.tool" })\` for one or \`connecta.describe({ addresses: [...] })\` for many; \`format: "json"\` only for exact constraints.
|
|
24
|
-
- Two to ten independent calls: \`connecta.batch([...])\`. Each outcome is \`{ address, ok: true, data }\` or \`{ address, ok: false, error, errorDetails: { code, retryable } }\`, which is also how a program tells a policy refusal from a transient failure.
|
|
25
|
-
- Search inside the run rather than searching first, and return only the reduction the answer needs — never raw payloads.
|
|
26
|
-
- Only tools annotated \`readOnlyHint: true\` are reachable; the read-only gate, credentials, and admission are enforced below the sandbox, so nothing a program does widens what it can reach.
|
|
27
32
|
`;
|
|
28
33
|
/**
|
|
29
34
|
* Appended to USAGE_SKILL only when the deployment actually has at least one
|
package/dist/skills.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skills.js","sourceRoot":"","sources":["../src/skills.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,qBAAqB,GAChC,
|
|
1
|
+
{"version":3,"file":"skills.js","sourceRoot":"","sources":["../src/skills.ts"],"names":[],"mappings":"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"}
|
package/dist/version.d.ts
CHANGED
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
* a bump that forgets this file fails the build rather than shipping a stale
|
|
5
5
|
* version to `/health` and to downstream MCP handshakes.
|
|
6
6
|
*/
|
|
7
|
-
export declare const CONNECTA_VERSION = "0.12.
|
|
7
|
+
export declare const CONNECTA_VERSION = "0.12.2";
|
|
8
8
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/version.js
CHANGED
|
@@ -326,7 +326,8 @@ classify, use `errorDetails`; to hand a failure to the model with its type
|
|
|
326
326
|
intact, let it escape uncaught — connecta re-attaches the typed details on the
|
|
327
327
|
way out. The model-facing version of this lives in `execute_code`'s description,
|
|
328
328
|
not in the always-loaded usage skill, which `test/meta-tools.test.ts` caps at
|
|
329
|
-
|
|
329
|
+
2,500 bytes — a budget the guide already spends nearly all of, so new text there
|
|
330
|
+
displaces old rather than adding to what every request pays for.
|
|
330
331
|
|
|
331
332
|
**E2.** The taxonomy. `retryable` is what connecta reports; `Y3` says what a
|
|
332
333
|
program may do about it.
|
|
@@ -502,10 +503,9 @@ the security posture live in the [design record](./mcp-ui-design.md)
|
|
|
502
503
|
[#277](https://github.com/zackbart/connecta/issues/277)); this section is the
|
|
503
504
|
contract, and it wins where the two disagree.
|
|
504
505
|
|
|
505
|
-
**U1.** `connecta.ui(html)` accepts
|
|
506
|
-
|
|
507
|
-
throws catchably and nothing
|
|
508
|
-
sugar form, for `M1`'s reason: sugar is how a one-shape contract grows hair.
|
|
506
|
+
**U1.** `connecta.ui(html, options?)` accepts one non-empty HTML string and at
|
|
507
|
+
most the bounded read manifest `V1` defines. The one-argument call stays
|
|
508
|
+
display-only; every other shape throws catchably and accepts nothing.
|
|
509
509
|
|
|
510
510
|
**U2.** At most one payload per run. A second call throws catchably, naming the
|
|
511
511
|
constraint; the first accepted payload stands. One tool result renders one view,
|
|
@@ -513,7 +513,7 @@ and last-wins would silently discard a payload the program deliberately
|
|
|
513
513
|
supplied.
|
|
514
514
|
|
|
515
515
|
**U3.** Delivered on success only, and out of model context: the tool result
|
|
516
|
-
gains `_meta["connecta/ui"] = { html }` and the JSON envelope gains `ui: true`,
|
|
516
|
+
gains `_meta["connecta/ui"] = { html, reads? }` and the JSON envelope gains `ui: true`,
|
|
517
517
|
so the model learns a view rendered without seeing its bytes. `structuredContent`
|
|
518
518
|
stays the envelope alone. The single-label `connecta/ui` prefix is deliberate —
|
|
519
519
|
connecta has no domain to reverse, and fabricating one to satisfy MCP's
|
|
@@ -526,27 +526,27 @@ with `emittedDiscarded: N` when one failure discards both.
|
|
|
526
526
|
|
|
527
527
|
**U4.** The payload spends the aggregate emit byte budget
|
|
528
528
|
(`ConnectaConfig.execute.maxEmittedBytes`), measured at the call as the
|
|
529
|
-
serialized bytes of `{ html }` — `M5`'s measurement. Over budget throws
|
|
529
|
+
serialized bytes of `{ html, reads? }` — `M5`'s measurement. Over budget throws
|
|
530
530
|
catchably, naming the budget and the room remaining, with nothing partially
|
|
531
531
|
accepted. It spends no block count (`maxEmittedBlocks`: it is not a block) and no
|
|
532
532
|
host-call budget (`L4`). One transport bound covers everything rich a program
|
|
533
533
|
delivers.
|
|
534
534
|
|
|
535
535
|
**U5.** One static shell: a connecta-authored HTML5 document at
|
|
536
|
-
`ui://connecta/program-ui/
|
|
536
|
+
`ui://connecta/program-ui/v2`, mimeType `text/html;profile=mcp-app`, declared on
|
|
537
537
|
`execute_code` via `_meta.ui.resourceUri` together with an explicit
|
|
538
|
-
`_meta.ui.visibility: ["model"]
|
|
539
|
-
|
|
538
|
+
`_meta.ui.visibility: ["model"]`. Only `call_tool` declares app visibility; all
|
|
539
|
+
other tools say model-only. A `resources/read` handler answers exactly that
|
|
540
540
|
URI and fails on any other; `resources/list` is served and returns an empty list.
|
|
541
541
|
The version segment bumps whenever the shell's bytes change, because hosts cache
|
|
542
542
|
templates by URI.
|
|
543
543
|
|
|
544
|
-
**U6.** The shell
|
|
544
|
+
**U6.** The shell renders the payload in a nested iframe
|
|
545
545
|
(`srcdoc`, `sandbox="allow-scripts"`, no `allow-same-origin`) and declares no CSP
|
|
546
546
|
domains, so the host applies its restrictive default and the `about:srcdoc` frame
|
|
547
|
-
inherits `default-src 'none'; connect-src 'none'`.
|
|
548
|
-
|
|
549
|
-
|
|
547
|
+
inherits `default-src 'none'; connect-src 'none'`. One argument stays display-only;
|
|
548
|
+
a `V1` manifest installs only named `connecta.read`, with no direct network, raw
|
|
549
|
+
tool calls, discovery, conversation, writes, or links. The shell participates in the Apps lifecycle —
|
|
550
550
|
initialize, tool-result, size-changed, resource-teardown — and forwards no
|
|
551
551
|
channel whatsoever from the inner frame to the host. That isolation makes
|
|
552
552
|
program views fixed-height by construction: with no bridge there is no
|
|
@@ -580,6 +580,27 @@ host fetches the shell, and the whole design is inert. Reading the *client's*
|
|
|
580
580
|
declaration in order to register tool metadata conditionally stays refused
|
|
581
581
|
(`U10`), knowingly against a spec SHOULD.
|
|
582
582
|
|
|
583
|
+
**U12.** The return value, not the view, is what the model reads. `U3` puts the
|
|
584
|
+
view out of model context, so a program that renders one also returns the summary
|
|
585
|
+
the model should reason over, built from the same variables the initial view renders — a
|
|
586
|
+
view the return value does not mirror is a view nobody in the loop can check.
|
|
587
|
+
This binds program authors and nothing else: connecta never reads the HTML, diffs
|
|
588
|
+
it against the return, or enforces the correspondence. A heuristic there would be
|
|
589
|
+
the same mistake as automatic host-side projection, refused in `ethos.md`
|
|
590
|
+
([#282](https://github.com/zackbart/connecta/issues/282)).
|
|
591
|
+
|
|
592
|
+
**U13.** The always-loaded MCP instructions locate `connecta.ui(html)` before an
|
|
593
|
+
agent chooses a route: it is a guest function inside `execute_code`, never a
|
|
594
|
+
connector address or catalog result, takes one HTML string, and carries `U12`'s
|
|
595
|
+
mirrored-return duty. The detailed tool description proved too late to stop cold
|
|
596
|
+
agents from searching downstream catalogs for UI; the location distinction
|
|
597
|
+
therefore rides `initialize`, under a 1,000-character ceiling for the complete
|
|
598
|
+
instructions string. This promotes existing contract, not capability: the
|
|
599
|
+
seven-tool surface, guest API, catalog, Apps delivery, and runtime do not change
|
|
600
|
+
([#286](https://github.com/zackbart/connecta/issues/286)).
|
|
601
|
+
|
|
602
|
+
Bounded view reads follow normative [`V1`–`V8`](./program-ui-read-calls.md) ([#287](https://github.com/zackbart/connecta/issues/287), [#289](https://github.com/zackbart/connecta/issues/289)).
|
|
603
|
+
|
|
583
604
|
## Retry semantics
|
|
584
605
|
|
|
585
606
|
**Y1.** Connecta retries nothing beneath a program. `call_tool` accepts an
|
|
@@ -794,7 +815,7 @@ Two surfaces were added since, both additive by construction and each with its
|
|
|
794
815
|
byte-for-byte no-call promise pinned by test:
|
|
795
816
|
[emitted output](#emitted-output) (`M1`–`M10`,
|
|
796
817
|
[#270](https://github.com/zackbart/connecta/issues/270)) and
|
|
797
|
-
[rendered output](#rendered-output) (`U1`–`
|
|
818
|
+
[rendered output](#rendered-output) (`U1`–`U12`,
|
|
798
819
|
[#277](https://github.com/zackbart/connecta/issues/277)).
|
|
799
820
|
|
|
800
821
|
## Verification
|
|
@@ -861,6 +882,8 @@ the upstream `Executor` shape assignable.
|
|
|
861
882
|
| `U6` | `test/execute-ui.test.ts` (valid HTML5, `srcdoc` and sandbox attributes, no `allow-same-origin`, no path from the inner frame to the host) |
|
|
862
883
|
| `U7`, `U8` | two arms passing one case table, `test/codemode-compat.test.ts` |
|
|
863
884
|
| `U9` | `test/execute-ui.test.ts` (a `ui` byte aggregate distinct from `emitted`, absent when nothing was accepted) |
|
|
885
|
+
| `U12` | `test/server.test.ts` (the `connecta.ui` bullet carries the return-value clause); a duty on program authors, so the description is the only place it can be enforced |
|
|
886
|
+
| `U13` | `test/code-first-surface.test.ts`, `test/server.test.ts` (served `initialize.instructions` locate UI inside `execute_code`, exclude it from catalog search, state the one-string call and mirrored return, and stay within the complete 1,000-character budget) |
|
|
864
887
|
| `X3` | `test/quickjs-executor.test.ts` (cancels a running child) |
|
|
865
888
|
| `X4` | `test/guest-api-contract.test.ts` (string logs only) |
|
|
866
889
|
| `X6` | `test/quickjs-executor.test.ts` (never-settling await) |
|
|
@@ -319,14 +319,14 @@ official spec at all — it survives there as background prose, not as a deferre
|
|
|
319
319
|
item with a queue position. Adopting a payload format the official spec never
|
|
320
320
|
took, on the path the official spec superseded, is two bets on one square.
|
|
321
321
|
|
|
322
|
-
**View-initiated tool calls from program UI.**
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
322
|
+
**View-initiated tool calls from program UI.** This original gate was split by
|
|
323
|
+
[#287](https://github.com/zackbart/connecta/issues/287) on 2026-08-02. Bounded
|
|
324
|
+
refresh, pagination, and drill-down reads are accepted through named bindings
|
|
325
|
+
and the existing `call_tool`; mutations remain gated. The evidence, threat
|
|
326
|
+
trace, and boundary between live reads and Executor's artifact product live in
|
|
327
|
+
[`program-ui-read-calls.md`](./program-ui-read-calls.md). The normative contract
|
|
328
|
+
is `V1`–`V8` in [`code-mode.md`](./code-mode.md); it supersedes this record's
|
|
329
|
+
display-only clauses where they disagree.
|
|
330
330
|
|
|
331
331
|
**Downstream MCP Apps template passthrough** (downstream connectors declaring
|
|
332
332
|
their own `ui://` templates, proxied through connecta's `resources/read`).
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
# Bounded reads from program UI — evidence and decision
|
|
2
|
+
|
|
3
|
+
Decision note for [#287](https://github.com/zackbart/connecta/issues/287),
|
|
4
|
+
2026-08-02. The implementation contract is [#289](https://github.com/zackbart/connecta/issues/289)
|
|
5
|
+
and the normative clauses are `V1`–`V8` in [code-mode.md](./code-mode.md).
|
|
6
|
+
|
|
7
|
+
## Verdict
|
|
8
|
+
|
|
9
|
+
Accept explicitly bound, host-mediated **read-only** calls for refresh,
|
|
10
|
+
pagination, and drill-down. Keep mutations gated. Keep the one-string
|
|
11
|
+
`connecta.ui(html)` call display-only.
|
|
12
|
+
|
|
13
|
+
This is not an acceptance of interactive applications in general. It adds no
|
|
14
|
+
persistence, artifact catalog, sharing, component runtime, generated-code
|
|
15
|
+
library, deep link, direct network, conversation channel, or write path. One
|
|
16
|
+
successful program still delivers one request-local view and one ordinary text
|
|
17
|
+
result.
|
|
18
|
+
|
|
19
|
+
## What display-only could not do
|
|
20
|
+
|
|
21
|
+
The current shell and the read-bound browser fixture were walked through with
|
|
22
|
+
the same three shapes. In the display-only arm, local JavaScript could sort,
|
|
23
|
+
filter, chart, expand already-delivered fields, and rerender indefinitely; every
|
|
24
|
+
attempt to obtain bytes not present in the original HTML stopped at the nested
|
|
25
|
+
frame. The read-bound arm exercised the same-origin-free nested frame, two
|
|
26
|
+
concurrent refreshes, fixed and view-supplied arguments, a refused fabricated
|
|
27
|
+
binding, a refused extra argument, and a host error.
|
|
28
|
+
|
|
29
|
+
| Workflow | Display-only attempt | Is a fresh program run adequate? | Decision |
|
|
30
|
+
| --- | --- | --- | --- |
|
|
31
|
+
| Refresh a current status or metrics view | A button can repaint only the original snapshot. Putting a timer around it changes no data. | No. It spends another model turn, reruns composition, and creates another view merely to repeat the same read. | Accept an exact named read with optional filter or cursor keys. |
|
|
32
|
+
| Page a cursor-backed list | The initial program can include the known next cursor, but the view cannot exchange it for the next page. Fetching every page up front defeats projection and can cross call/result budgets. | No. The model is an expensive pagination controller and has to reconstruct UI state it did not need. | Accept a binding whose declared `viewArgs` includes the cursor field. |
|
|
33
|
+
| Drill from a projected list into one record | Local expansion can show only fields prefetched for every row. Prefetching every detail multiplies calls and payload for records the human never opens. | Usually no. A new prompt can fetch the record, but loses the direct row selection and creates a second result instead of filling the existing view. | Accept a binding whose declared `viewArgs` includes the record identifier. |
|
|
34
|
+
| Sort, filter, chart, compare, or expand delivered data | Local HTML/JavaScript completes the interaction. | Yes; usually no new run is needed at all. | No call capability earned. |
|
|
35
|
+
| Change, delete, approve, send, or deploy | Display-only correctly cannot act. | Yes. The ordinary `call_destructive_tool` path keeps the proposed effect and host approval in the transcript. | Remain gated. A click is not approval, and this decision adds no mutation bridge. |
|
|
36
|
+
|
|
37
|
+
The accepted utility is therefore *live reads*, not “interactivity.” Local
|
|
38
|
+
interactivity already existed.
|
|
39
|
+
|
|
40
|
+
## Executor comparison
|
|
41
|
+
|
|
42
|
+
Executor's inspected revision demonstrates a useful separation:
|
|
43
|
+
|
|
44
|
+
- its generated iframe disables direct `fetch`, XHR, WebSocket, EventSource,
|
|
45
|
+
workers, and related network primitives;
|
|
46
|
+
- declarative `tools.*` operations become one proxy-shaped call through a
|
|
47
|
+
trusted shell and an app-only action tool;
|
|
48
|
+
- integration roles resolve against server-owned saved bindings, and writes
|
|
49
|
+
can pause for shell-owned interaction handling.
|
|
50
|
+
|
|
51
|
+
That is evidence that a narrow bridge can keep untrusted markup away from raw
|
|
52
|
+
network and credentials. It is not evidence for Executor's React runtime,
|
|
53
|
+
saved artifacts, editing, previews, persistence, or deep-link fallback; those
|
|
54
|
+
features provide longevity and authoring ergonomics, not the refresh,
|
|
55
|
+
pagination, or drill-down read itself.
|
|
56
|
+
|
|
57
|
+
Connecta takes the smaller shape. The trusted shell maps names to the already
|
|
58
|
+
existing `call_tool`; bindings live in the completed result, not a database;
|
|
59
|
+
and the ordinary fail-closed read path remains the authority. No app-only tool
|
|
60
|
+
or eighth meta-tool is needed.
|
|
61
|
+
|
|
62
|
+
Inspected Executor sources:
|
|
63
|
+
|
|
64
|
+
- [artifact and app-only action registration](https://github.com/UsefulSoftwareCo/executor/blob/837e404acbebdf32924059d6b76f715565329307/packages/hosts/mcp/src/tool-server.ts#L1906-L2157)
|
|
65
|
+
- [single proxy-shaped action grammar](https://github.com/UsefulSoftwareCo/executor/blob/837e404acbebdf32924059d6b76f715565329307/packages/hosts/mcp-apps-shell/src/shell/proxy.ts#L38-L140)
|
|
66
|
+
- [disabled direct network primitives](https://github.com/UsefulSoftwareCo/executor/blob/837e404acbebdf32924059d6b76f715565329307/packages/hosts/mcp-apps-shell/src/shell/inner-renderer.tsx#L84-L131)
|
|
67
|
+
|
|
68
|
+
## Contract in one pass
|
|
69
|
+
|
|
70
|
+
```js
|
|
71
|
+
await connecta.ui(html, {
|
|
72
|
+
reads: {
|
|
73
|
+
refresh: {
|
|
74
|
+
address: "metrics.current",
|
|
75
|
+
fixedArgs: { service: "api" },
|
|
76
|
+
viewArgs: ["window", "cursor"],
|
|
77
|
+
},
|
|
78
|
+
detail: {
|
|
79
|
+
address: "incidents.get",
|
|
80
|
+
viewArgs: ["id"],
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Program markup calls `await connecta.read("detail", { id })`. It never receives
|
|
87
|
+
the address table. The outer shell checks the frame source, resolves `detail`,
|
|
88
|
+
rejects keys other than `id`, merges the arguments, and asks the host to call
|
|
89
|
+
the existing `call_tool` with `resultMode: "value"`.
|
|
90
|
+
|
|
91
|
+
The declaration-time catalog lookup proves the view was not born broken or
|
|
92
|
+
write-capable. The use-time `call_tool` lookup proves it is still read-only now.
|
|
93
|
+
|
|
94
|
+
## Normative contract
|
|
95
|
+
|
|
96
|
+
**V1. Manifest.** The second argument is exactly
|
|
97
|
+
`{ reads: { name: { address, fixedArgs?, viewArgs? } } }`: 1–32 names matching
|
|
98
|
+
`[A-Za-z][A-Za-z0-9_-]{0,63}`, one non-empty address per name, optional fixed
|
|
99
|
+
arguments, and at most 32 distinct view-supplied keys. Extra fields, unsafe
|
|
100
|
+
control names (`__proto__`, `constructor`, `prototype`), a view key colliding
|
|
101
|
+
with a fixed key, and non-serializable content throw before acceptance.
|
|
102
|
+
|
|
103
|
+
**V2. Declaration admission.** Every address resolves through the request-local
|
|
104
|
+
catalog and passes the fail-closed `isExplicitlyReadOnly` classification before
|
|
105
|
+
the payload is accepted. The lookup dispatches nothing and spends no host-call
|
|
106
|
+
budget. `call_tool` repeats resolution and classification at use time.
|
|
107
|
+
|
|
108
|
+
**V3. Delivery.** Bindings ride beside `html` under `_meta["connecta/ui"]`,
|
|
109
|
+
share the existing emitted-byte aggregate, appear on success only, and never
|
|
110
|
+
enter `content` or `structuredContent`. The one-string payload stays exactly
|
|
111
|
+
`{ html }`.
|
|
112
|
+
|
|
113
|
+
**V4. Inner bridge.** A manifest alone installs `connecta.read(name, args?)`.
|
|
114
|
+
The outer shell accepts only its nested frame's exact `WindowProxy`, rejects an
|
|
115
|
+
unknown name, non-object arguments, undeclared keys, and more than eight
|
|
116
|
+
concurrent reads, then merges supplied keys into a null-prototype copy of fixed
|
|
117
|
+
arguments. The inner frame receives no address table or raw JSON-RPC.
|
|
118
|
+
|
|
119
|
+
**V5. Seven-tool boundary.** The shell calls only existing `call_tool` with
|
|
120
|
+
`resultMode: "value"`. That tool alone is app-visible; the other six are
|
|
121
|
+
explicitly model-only. No new MCP tool exists and the view cannot reach the
|
|
122
|
+
destructive boundary.
|
|
123
|
+
|
|
124
|
+
**V6. Ordinary admission.** A view read is a new MCP request crossing inbound
|
|
125
|
+
auth, request admission, current catalog and credentials, fail-closed safety,
|
|
126
|
+
connector admission, timeout, retry, result-size, and payload-free activity
|
|
127
|
+
exactly as ordinary `call_tool` does. No server-side grant or pending promise
|
|
128
|
+
survives the originating request.
|
|
129
|
+
|
|
130
|
+
**V7. Stale and replayed views.** A stale view retains no frozen authority:
|
|
131
|
+
removed tools, changed annotations, revoked credentials, lost inbound auth, and
|
|
132
|
+
new policy fail current admission. Replay repeats a read and may spend rate
|
|
133
|
+
limits, but cannot write. Cross-caller use is admitted as the current caller on
|
|
134
|
+
the host's originating connection; deployment remains the audience boundary.
|
|
135
|
+
|
|
136
|
+
**V8. Context, fallback, and parity.** Reads update only the human-visible view;
|
|
137
|
+
the return summarizes the initial snapshot and refreshed data must be labelled
|
|
138
|
+
as such. A host without app server tools keeps the ordinary result and initial
|
|
139
|
+
view while a read fails locally. The existing provider bridge carries the
|
|
140
|
+
manifest identically on both executors without changing `ExecuteResult`.
|
|
141
|
+
|
|
142
|
+
## Threat and consent trace
|
|
143
|
+
|
|
144
|
+
1. **Untrusted program declaration.** The guest supplies HTML and a strictly
|
|
145
|
+
shaped read manifest. The host rejects extra fields, unsafe control names,
|
|
146
|
+
fixed/view collisions, overlarge lists, unknown addresses, and anything not
|
|
147
|
+
explicitly read-only. This lookup executes nothing.
|
|
148
|
+
2. **Result delivery.** On successful program completion only, HTML and
|
|
149
|
+
bindings ride result `_meta` under the existing aggregate byte budget. A
|
|
150
|
+
failed program delivers neither. The model sees only `ui: true` and the
|
|
151
|
+
program's initial summary.
|
|
152
|
+
3. **Nested-frame request.** Only the exact payload `WindowProxy` may send the
|
|
153
|
+
`connecta/read` dialect to the trusted shell. A fabricated name fails before
|
|
154
|
+
a host call. Fabricated or prototype-shaped argument keys fail unless they
|
|
155
|
+
are explicitly declared; fixed keys cannot be overridden. Direct JSON-RPC
|
|
156
|
+
from the nested frame is ignored.
|
|
157
|
+
4. **Host mediation.** The shell checks that the host advertised server-tool
|
|
158
|
+
calls, caps concurrent work, and emits one `tools/call` for `call_tool`.
|
|
159
|
+
`execute_code`, discovery, authorization, result paging, and the destructive
|
|
160
|
+
tool are model-only. The Apps host accepts calls only on the originating MCP
|
|
161
|
+
server connection.
|
|
162
|
+
5. **Connecta admission.** The app call is a new authenticated request with a
|
|
163
|
+
fresh request scope. It crosses request admission, current catalog and
|
|
164
|
+
credential resolution, fail-closed read classification, connector call
|
|
165
|
+
admission, timeout, retry policy, result-size handling, and payload-free
|
|
166
|
+
activity recording. There is no UI bypass below the shell.
|
|
167
|
+
6. **Result delivery.** The shell unwraps the ordinary value result and settles
|
|
168
|
+
only the matching inner-frame promise. Protocol errors and tool errors
|
|
169
|
+
reject it. It sends no result to model or conversation context.
|
|
170
|
+
|
|
171
|
+
### Named failures
|
|
172
|
+
|
|
173
|
+
- **Fabricated address:** markup cannot submit an address; raw JSON-RPC is not
|
|
174
|
+
forwarded. A declaration-time invented address fails catalog resolution.
|
|
175
|
+
- **Fabricated binding name:** rejected by own-property lookup in the shell.
|
|
176
|
+
- **Fabricated argument:** an undeclared key or non-object argument is rejected;
|
|
177
|
+
a declared value still faces the downstream input schema and policy.
|
|
178
|
+
- **Stale view:** the later request reauthenticates and re-resolves the catalog.
|
|
179
|
+
A removed tool, newly unsafe annotation, revoked credential, or changed
|
|
180
|
+
admission policy fails current checks. No frozen grant exists server-side.
|
|
181
|
+
- **Replay:** it repeats a read and may consume rate limits, but cannot cross to
|
|
182
|
+
a write. The view should disable duplicate controls while its promise is
|
|
183
|
+
pending; the shell also bounds concurrency.
|
|
184
|
+
- **Cross-caller use:** the later request is admitted as the caller behind the
|
|
185
|
+
host's current originating connection. Connecta does not use identity to
|
|
186
|
+
scope tools inside one deployment; separate audiences remain separate
|
|
187
|
+
deployments. A copied manifest is no credential and grants nothing outside
|
|
188
|
+
ordinary inbound auth.
|
|
189
|
+
- **Destructive call:** the shell names only `call_tool`, and that handler
|
|
190
|
+
refuses missing, false, or contradictory read-only annotation. The
|
|
191
|
+
destructive meta-tool is not app-visible. No human gesture is interpreted as
|
|
192
|
+
write consent.
|
|
193
|
+
|
|
194
|
+
## Invariants and parity
|
|
195
|
+
|
|
196
|
+
- **Seven tools:** unchanged; metadata makes one existing tool app-callable and
|
|
197
|
+
makes the other six explicitly model-only.
|
|
198
|
+
- **Stateless request scope:** binding state survives only in the client's
|
|
199
|
+
completed result and trusted shell. The server stores no grant or pending
|
|
200
|
+
promise.
|
|
201
|
+
- **Import-graph purity:** the shell remains a build-time string using browser
|
|
202
|
+
and Web APIs only.
|
|
203
|
+
- **Workers/Node parity:** the second argument crosses the existing provider
|
|
204
|
+
bridge, leaving `Executor` and `ExecuteResult` unchanged; the same contract
|
|
205
|
+
case runs on both executors and both Vitest projects.
|
|
206
|
+
- **Payload-free activity:** later reads use ordinary `call_tool` events, whose
|
|
207
|
+
schema has no arguments or results.
|
|
208
|
+
- **Fallback:** hosts without Apps keep the ordinary result; Apps hosts without
|
|
209
|
+
server-tool calls keep the initial view and fail a read locally.
|
|
210
|
+
|
|
211
|
+
The remaining gate is intentionally crisp: a mutation proposal needs real
|
|
212
|
+
workflow evidence plus a host-tested consent and replay story. Read utility is
|
|
213
|
+
not permission to smuggle that decision into this bridge.
|
package/ethos.md
CHANGED
|
@@ -95,7 +95,9 @@ proposing one without a new argument is not.
|
|
|
95
95
|
| 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)) |
|
|
96
96
|
| 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)) |
|
|
97
97
|
| 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)) |
|
|
98
|
-
| View-initiated
|
|
98
|
+
| 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)) |
|
|
99
|
+
| 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)) |
|
|
100
|
+
| 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)) |
|
|
99
101
|
| 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)) |
|
|
100
102
|
|
|
101
103
|
## Invariants
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zackbart/connecta",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.2",
|
|
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.",
|