@zackbart/connecta 0.38.0 → 0.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +91 -0
- package/README.md +3 -2
- package/bin/connecta.mjs +4 -8
- package/bin/version.mjs +1 -1
- package/dist/access-tokens.js +6 -4
- package/dist/agent-routes.js +231 -0
- package/dist/auth/downstream-oauth/consent.js +519 -0
- package/dist/auth/downstream-oauth/grant-store.js +439 -0
- package/dist/auth/downstream-oauth/refresh-coordinator.js +562 -0
- package/dist/auth/downstream-oauth/refresh-records.js +447 -0
- package/dist/auth/downstream-oauth/sdk-hooks.js +242 -0
- package/dist/auth/downstream-oauth.js +66 -2382
- package/dist/auth/native.js +37 -0
- package/dist/auth/oauth-grant.js +13 -0
- package/dist/auth/static-oauth.js +153 -131
- package/dist/auth-elicitation.js +7 -1
- package/dist/authorization-handoff.js +11 -5
- package/dist/catalog-cache.js +219 -59
- package/dist/catalog-policy.js +18 -0
- package/dist/catalog-service.js +284 -47
- package/dist/catalog.js +18 -2
- package/dist/config.d.ts +16 -11
- package/dist/config.js +9 -6
- package/dist/connector-caller.d.ts +1 -1
- package/dist/connector-health.js +59 -0
- package/dist/connector-status.js +117 -0
- package/dist/connectors/api-connector.d.ts +7 -2
- package/dist/connectors/api-connector.js +7 -4
- package/dist/connectors/negotiation-cache.js +22 -4
- package/dist/connectors/remote-mcp/call.js +164 -0
- package/dist/connectors/remote-mcp/catalog.js +278 -0
- package/dist/connectors/remote-mcp/config.js +263 -0
- package/dist/connectors/remote-mcp/connection.js +682 -0
- package/dist/connectors/remote-mcp/errors.js +488 -0
- package/dist/connectors/remote-mcp/oauth.js +473 -0
- package/dist/connectors/remote-mcp/resources.js +473 -0
- package/dist/connectors/remote-mcp/runtime.js +1 -0
- package/dist/connectors/remote-mcp/transport.js +555 -0
- package/dist/connectors/remote-mcp.js +62 -2863
- package/dist/credential-contract.d.ts +23 -0
- package/dist/credential-reads.js +17 -0
- package/dist/credential-verification.js +53 -0
- package/dist/credentials.d.ts +7 -0
- package/dist/credentials.js +60 -25
- package/dist/describe-config.d.ts +12 -2
- package/dist/describe-config.js +2 -0
- package/dist/discovery-health.js +199 -0
- package/dist/downstream-input.js +2 -0
- package/dist/errors.d.ts +55 -17
- package/dist/errors.js +95 -41
- package/dist/execute.js +152 -114
- package/dist/executor-result.js +3 -1
- package/dist/guest-functions.js +83 -0
- package/dist/guest-runtime.js +60 -19
- package/dist/guest-types.d.ts +19 -5
- package/dist/http/argument-problems.js +35 -0
- package/dist/http/errors.js +5 -4
- package/dist/http/fields.js +192 -13
- package/dist/http/hatch-response.js +73 -0
- package/dist/http/hatch.js +88 -23
- package/dist/http/oauth.js +3 -2
- package/dist/http/provider.js +32 -4
- package/dist/http/safety.js +8 -0
- package/dist/http/tools.js +44 -23
- package/dist/index.d.ts +1 -1
- package/dist/index.js +9 -2
- package/dist/invocation.js +26 -8
- package/dist/membership.d.ts +13 -5
- package/dist/membership.js +34 -2
- package/dist/meta-tools.js +54 -31
- package/dist/native-recovery.js +4 -16
- package/dist/native-tools.js +5 -2
- package/dist/oauth-sealing.js +10 -0
- package/dist/operation-vocabulary.js +135 -13
- package/dist/operator-record.d.ts +2 -2
- package/dist/operator-record.js +1 -0
- package/dist/operator-ui/contract.d.ts +10 -0
- package/dist/operator-ui/generated.js +2 -2
- package/dist/operator-ui/model.d.ts +22 -1
- package/dist/provider-call-facts.js +6 -2
- package/dist/providers/_shared/rest/operation-index.js +48 -50
- package/dist/providers/_shared/rest/value-safety.js +80 -0
- package/dist/providers/breeze/api.js +7 -1
- package/dist/providers/breeze/skill.generated.js +1 -1
- package/dist/providers/breeze/tools.js +4 -3
- package/dist/providers/ccb/api.js +2 -1
- package/dist/providers/ccb/index.js +5 -0
- package/dist/providers/ccb/skill.generated.js +1 -1
- package/dist/providers/cloudflare/api.js +8 -1
- package/dist/providers/cloudflare/skill.generated.js +1 -1
- package/dist/providers/docs/lib/schemas.js +24 -22
- package/dist/providers/docs/safety.js +2 -0
- package/dist/providers/docs/skill.generated.js +1 -1
- package/dist/providers/docs/tools.js +2 -4
- package/dist/providers/drive/api.js +1 -0
- package/dist/providers/drive/lib/contracts.js +8 -5
- package/dist/providers/drive/skill.generated.js +1 -1
- package/dist/providers/drive/tools.js +11 -16
- package/dist/providers/forms/api.js +1 -0
- package/dist/providers/forms/skill.generated.js +1 -1
- package/dist/providers/forms/tools.js +10 -7
- package/dist/providers/github/api.js +1 -0
- package/dist/providers/github/lib/discovery.js +1 -1
- package/dist/providers/github/skill.generated.js +1 -1
- package/dist/providers/github/tools.js +61 -17
- package/dist/providers/gmail/lib/schemas.js +60 -50
- package/dist/providers/gmail/skill.generated.js +1 -1
- package/dist/providers/gmail/tools.js +7 -5
- package/dist/providers/granola/index.js +2 -0
- package/dist/providers/granola/skill.generated.js +1 -1
- package/dist/providers/overflow/api.js +7 -1
- package/dist/providers/overflow/skill.generated.js +1 -1
- package/dist/providers/planning-center/api.js +3 -1
- package/dist/providers/planning-center/lib/constants.d.ts +1 -1
- package/dist/providers/planning-center/skill.generated.js +1 -1
- package/dist/providers/quickbooks/safety.js +80 -39
- package/dist/providers/quickbooks/skill.generated.js +1 -1
- package/dist/providers/sheets/api.js +1 -0
- package/dist/providers/sheets/skill.generated.js +1 -1
- package/dist/providers/sheets/tools.js +13 -14
- package/dist/providers/slides/skill.generated.js +1 -1
- package/dist/providers/slides/tools.js +15 -13
- package/dist/providers/stripe/skill.generated.js +1 -1
- package/dist/providers/tithely/api.js +3 -1
- package/dist/providers/tithely/skill.generated.js +1 -1
- package/dist/providers/vercel/api.js +1 -1
- package/dist/providers/vercel/skill.generated.js +1 -1
- package/dist/providers/vercel/tools.js +4 -3
- package/dist/registry.d.ts +10 -4
- package/dist/registry.js +41 -13
- package/dist/routes/credentials.js +129 -60
- package/dist/routes/dispatch.js +5 -1
- package/dist/routes/mcp.js +30 -14
- package/dist/routes/operator.js +2 -2
- package/dist/routes/shared.d.ts +6 -1
- package/dist/routes/shared.js +7 -1
- package/dist/routes/ui-config.js +2 -2
- package/dist/routes/ui-data.js +126 -20
- package/dist/routes/ui.js +16 -0
- package/dist/runtime/call.js +7 -2
- package/dist/runtime/native-storage.js +12 -0
- package/dist/runtime/request-reads.js +207 -0
- package/dist/runtime/request-scope.js +16 -0
- package/dist/runtime/storage.js +12 -0
- package/dist/skills.js +37 -20
- package/dist/storage/keys.js +53 -3
- package/dist/storage/memory.js +8 -2
- package/dist/storage/sql-native.js +53 -1
- package/dist/storage/sql.js +12 -2
- package/dist/storage-digest.js +32 -0
- package/dist/timeout.js +8 -0
- package/dist/types.d.ts +33 -0
- package/dist/usage-guide.js +16 -35
- package/dist/validate.d.ts +3 -0
- package/dist/validate.js +220 -158
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/write-outcome.js +0 -3
- package/documentation/README.md +13 -13
- package/documentation/architecture.md +385 -20
- package/documentation/auth.md +233 -64
- package/documentation/code-mode.md +122 -39
- package/documentation/deploying.md +6 -3
- package/documentation/integrating.md +16 -2
- package/documentation/meta-tools.md +240 -49
- package/documentation/migration-0.33.md +5 -1
- package/documentation/migration-0.34.md +3 -1
- package/documentation/operator-tests.md +1 -1
- package/documentation/operator-ui.md +105 -12
- package/documentation/pool-membership-upgrade.md +44 -0
- package/documentation/providers.md +105 -0
- package/examples/worker/AGENTS.md +10 -10
- package/examples/worker/README.md +4 -3
- package/examples/worker/src/connecta.config.ts +1 -0
- package/guides/connecting-agents.md +2 -1
- package/guides/how-it-works.md +4 -2
- package/package.json +1 -1
- package/templates/node/AGENTS.md +13 -12
- package/templates/node/package.json +1 -1
- package/templates/node/src/connecta.config.ts +1 -0
|
@@ -113,6 +113,12 @@ Pool endpoint rows show the effective surface (`meta` or `native`) and whether
|
|
|
113
113
|
code is on. These are read-only facts from deployment configuration; change
|
|
114
114
|
`surface` and `executeCode` in deployment code.
|
|
115
115
|
|
|
116
|
+
Plain `/mcp` is routed by sign-in: the `/mcp` row and matrix column show the
|
|
117
|
+
whole catalog maintainers receive, and a pool row shows what its people
|
|
118
|
+
receive at both `/mcp/<pool>` and, when they belong to no other pool, plain
|
|
119
|
+
`/mcp`. A note above the rows says so. People in several pools appear in
|
|
120
|
+
`config.peopleInSeveralPools`; plain `/mcp` refuses them.
|
|
121
|
+
|
|
116
122
|
One row each for `/mcp` and every pool: the path, a read-only pill on a
|
|
117
123
|
read-only endpoint, a copyable URL, who can use it, its connectors as colored
|
|
118
124
|
monograms (four, then "+N"), its tool count over a read and write bar, and a
|
|
@@ -121,7 +127,9 @@ Setup button.
|
|
|
121
127
|
- Who can use it is `root.maintainers` on `/mcp` and the pool's `members`
|
|
122
128
|
elsewhere, as an avatar stack named on hover and to screen readers (label,
|
|
123
129
|
raw id when the label is null, or agent name). Four show, then a "+N"
|
|
124
|
-
button. A pool
|
|
130
|
+
button. A pool lists only people or only agents. An agent pool's row
|
|
131
|
+
still shows two URLs labeled People and Agents; the People URL
|
|
132
|
+
(`/mcp/<pool>`) admits no one, because the pool has no people.
|
|
125
133
|
- Expanding a row lists everyone by name, then each connector with what it
|
|
126
134
|
runs as and its tools, write tools amber with a pencil. Runs-as comes from
|
|
127
135
|
the endpoint's matrix cell: "Shared · saved <date>", "Shared · connected
|
|
@@ -194,8 +202,9 @@ tabs:
|
|
|
194
202
|
annotation badges (Destructive, Open world), filtered by search and All,
|
|
195
203
|
Read and Write. A tool opens its schema in a side drawer.
|
|
196
204
|
- **Connection.** An Authentication card (mode, OAuth client mechanism, who
|
|
197
|
-
manages it, OAuth actions, and the credential card
|
|
198
|
-
field states, and Replace, Test and Remove); a
|
|
205
|
+
manages it, the last verification, OAuth actions, and the credential card
|
|
206
|
+
with masked last four, field states, and Replace, Test and Remove); a
|
|
207
|
+
Diagnostics card of tiles
|
|
199
208
|
(catalog age and last call) with a fix prompt beside each
|
|
200
209
|
problem; and a Configuration card. Its badges name the kind (Remote MCP,
|
|
201
210
|
HTTP API or Custom), provider, auth scope, endpoint host and usage guide.
|
|
@@ -340,10 +349,12 @@ connections**, has no tabs; its heading shows the signed-in email when the
|
|
|
340
349
|
sign-in exposes one (Clerk's primary email), and its top bar shows branding and
|
|
341
350
|
an **Account** button with Sign out or Change token. It lists:
|
|
342
351
|
|
|
343
|
-
- **Your endpoints**: one card per
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
352
|
+
- **Your endpoints**: one card per address with a copy button and **Client
|
|
353
|
+
setup**. A member of exactly one pool sees one card for plain `/mcp`, named
|
|
354
|
+
after the pool it serves; a member of several pools sees one
|
|
355
|
+
`/mcp/<pool>` card per pool. For example, Bob, only in pool `team`, copies
|
|
356
|
+
`https://connecta.example.com/mcp` into an MCP client and authenticates as
|
|
357
|
+
Bob.
|
|
347
358
|
- **Your accounts**: the personal connectors in their pools, each with a
|
|
348
359
|
monogram, tool count, one status badge in an aligned column, and only the
|
|
349
360
|
controls its `manage.actions` lists. A saved credential that no longer fits
|
|
@@ -415,7 +426,8 @@ without this capability contribute an unconfirmed count of zero. For example,
|
|
|
415
426
|
The maintainer view carries:
|
|
416
427
|
|
|
417
428
|
- `config`, the construction-time `describeConfig()` snapshot, including
|
|
418
|
-
`maintainers
|
|
429
|
+
`maintainers`, each pool's `members`, `peopleInSeveralPools` (non-maintainer
|
|
430
|
+
people plain `/mcp` refuses because they are in several pools), and `configSources`, which labels
|
|
419
431
|
each serialized leaf as `default` or `config` from option presence rather
|
|
420
432
|
than equality with the default. Factory descriptions carry relative
|
|
421
433
|
`optionSources` paths so resolved module and transport defaults retain their
|
|
@@ -488,7 +500,9 @@ The maintainer view carries:
|
|
|
488
500
|
The member view is exactly that member's projection: `config`,
|
|
489
501
|
`configSources` and `root` are `null`, `live.connectors`, `agents` and
|
|
490
502
|
`matrix` are empty, and `live.activity` is `"forbidden"`. `pools` lists only
|
|
491
|
-
their pools, each with `owner: null` and `members: []`.
|
|
503
|
+
their pools, each with `owner: null` and `members: []`. With exactly one pool,
|
|
504
|
+
its `humanPath` is `/mcp`, the address that serves them that pool, and the
|
|
505
|
+
member's catalog reads carry that pool as plain `/mcp` would. `connectors` lists
|
|
492
506
|
each connector in those pools with its title, the member's pools that serve
|
|
493
507
|
it, its auth scope, the tools those pools grant with their classification,
|
|
494
508
|
`connection` (their own partition's state and problem code for a personal
|
|
@@ -556,6 +570,58 @@ the config snapshot, and never treats a `per_caller` overlay as an error.
|
|
|
556
570
|
complete classified tools with input/output schemas, registration path, catalog
|
|
557
571
|
age, and activity-derived last-call facts under the reader's disclosure policy.
|
|
558
572
|
A failed or timed-out connector releases its own scope; siblings finish independently.
|
|
573
|
+
The status and catalog observation has its own deadline: 8 seconds, or
|
|
574
|
+
`discovery.probeTimeoutMs` when that is shorter, in which case the whole row
|
|
575
|
+
uses that one deadline. The 8-second value is fixed, not configured; agent
|
|
576
|
+
discovery keeps the full `discovery.probeTimeoutMs`. When the deadline ends
|
|
577
|
+
first, the downstream read is aborted and the row returns `status: "error"`
|
|
578
|
+
with `problem: "connector_timeout"` in the row and its overlay. The row still
|
|
579
|
+
carries its credential card and auth permissions, so a slow connector's slot
|
|
580
|
+
stays manageable. Any other failure keeps `connector_unavailable`. The
|
|
581
|
+
connector renders as **Not responding**, with fixed copy, a fix prompt and
|
|
582
|
+
Refresh.
|
|
583
|
+
**Stored status.** Each live `GET /ui/connectors/:id` records one status
|
|
584
|
+
observation for that connector and viewer partition before it answers: its
|
|
585
|
+
state, problem code, tool count and observation time. Authored static catalogs
|
|
586
|
+
such as `api()` connectors are recorded too, since their status still checks
|
|
587
|
+
auth. The record lives in the `connector-health:v1:` family under the same
|
|
588
|
+
owner partition as the catalog cache (principal, subject, caller identity and
|
|
589
|
+
pool, endpoint, described configuration and package version), so a personal
|
|
590
|
+
connector's observation is one person's. It also carries the catalog
|
|
591
|
+
generation read before the probe, through the request's read memo that the
|
|
592
|
+
catalog listing reuses. It holds no tools, schemas, status prose or
|
|
593
|
+
credential facts. It expires 120 seconds after it was observed, and lapses at
|
|
594
|
+
once when a credential change, OAuth connect or disconnect, or invalidation
|
|
595
|
+
rotates the generation. A read that ends at the row's own deadline, including
|
|
596
|
+
a configured `discovery.probeTimeoutMs` shorter than 8 seconds, records
|
|
597
|
+
`connector_timeout` before it answers. An observation is written only while
|
|
598
|
+
the caller is still waiting: a request its caller has already left starts no
|
|
599
|
+
write. A write that has started is never raced against a deadline or
|
|
600
|
+
detached, because a storage write cannot be withdrawn once sent. The request,
|
|
601
|
+
whether it times out or its caller leaves meanwhile, settles only after that
|
|
602
|
+
write does, bounded by the storage layer like every other awaited write, so
|
|
603
|
+
nothing commits after the request ends.
|
|
604
|
+
|
|
605
|
+
`GET /ui/connectors/:id?observation=stored` answers from a current observation
|
|
606
|
+
without probing the downstream. The row and overlay carry `observedAgeMs`, the
|
|
607
|
+
stored `status`, `problem` and `toolCount`, and `tools: []`; the tools stay in
|
|
608
|
+
the catalog cache. The credential card, drift, permissions and any
|
|
609
|
+
authorization link are computed fresh on every request. Without a current
|
|
610
|
+
observation the route does the live read and records it, with no
|
|
611
|
+
`observedAgeMs`. Nothing is refreshed after the response: no deferred work and
|
|
612
|
+
no `ctx.waitUntil`.
|
|
613
|
+
|
|
614
|
+
The browser asks each connector for its stored observation on the page load
|
|
615
|
+
that follows admission, and fixes the observation time once as each stored
|
|
616
|
+
row lands. The list card and the connector page mark a stored row the same
|
|
617
|
+
way, "Stored status, checked … ago", with an age that keeps counting, and
|
|
618
|
+
show its tools as awaiting the live read rather than as none. The browser then
|
|
619
|
+
sends one plain live read per stored row, through the same queue of eight
|
|
620
|
+
detail reads. A stored `connector_timeout` row is not read again on its own;
|
|
621
|
+
its mark says to Refresh, and it waits for Refresh like a live timeout.
|
|
622
|
+
Refresh, a single connector's read, recovery retries and OAuth polls always
|
|
623
|
+
read live.
|
|
624
|
+
|
|
559
625
|
The summary and each detail carry `viewerKey` for the principal admitted to that
|
|
560
626
|
request. The browser publishes the detail and overlay atomically only when that
|
|
561
627
|
key matches admission. A changed viewer key, including an Access switch between
|
|
@@ -568,7 +634,7 @@ screen. The first answer for the new viewer triggers readmission, which clears
|
|
|
568
634
|
everything retained.
|
|
569
635
|
Config observations never
|
|
570
636
|
overwrite a completed detail row. Each connector opens at most one live observation
|
|
571
|
-
per page load; the summary `/ui/data` performs no downstream probes.
|
|
637
|
+
per page load, after its stored read; the summary `/ui/data` performs no downstream probes.
|
|
572
638
|
|
|
573
639
|
`GET /ui/api/config?connector=<id>` narrows the same contract to one connector
|
|
574
640
|
before status and catalog probes. For a maintainer, config, provenance, live
|
|
@@ -628,8 +694,23 @@ bounded at 2, 2, 4 and 8 seconds; a later focus return can try again after backo
|
|
|
628
694
|
|
|
629
695
|
Connector Refresh, focus recovery and mutation follow-ups read only affected
|
|
630
696
|
connectors. Focus probes unhealthy rows, never healthy siblings. All detail reads
|
|
631
|
-
share
|
|
697
|
+
in one tab share an eight-request limit and coalesce per connector, so a page of
|
|
698
|
+
up to eight connectors loads in one round. The limit is fixed, not configured.
|
|
699
|
+
It bounds how many connectors one tab waits on at once; a tab still reads each
|
|
700
|
+
connector once per load, so the limit adds no requests to any one connector.
|
|
701
|
+
Detail reads do not consume `admission.requests` permits, which govern `/mcp`
|
|
702
|
+
only. They still share isolate CPU and memory, D1, and downstream account quotas
|
|
703
|
+
with agent traffic; each tab adds up to eight concurrent downstream reads, and
|
|
704
|
+
several connectors on one vendor account share that vendor's rate limit. Over HTTP/1.1 the browser itself allows about six
|
|
705
|
+
connections per origin.
|
|
706
|
+
Failures retry only their
|
|
632
707
|
connector with the same bounded backoff; recovery never replays a mutation.
|
|
708
|
+
A `connector_timeout` row is parked instead. It spends its automatic retry
|
|
709
|
+
budget, and focus and visibility returns skip it. Only Refresh, a full refresh
|
|
710
|
+
or a mutation follow-up reads it again, so an outage holds a detail slot once
|
|
711
|
+
per explicit request, never repeatedly. An OAuth start's consent-return poll is
|
|
712
|
+
the exception: a timeout during its 30-second window keeps polling, and success
|
|
713
|
+
still stops it.
|
|
633
714
|
Mutations cancel affected reads and advance their publication fence both at
|
|
634
715
|
dispatch and on settlement, including failure. Follow-ups require an observation
|
|
635
716
|
started after settlement, so a Refresh or retry started during the write cannot
|
|
@@ -638,9 +719,21 @@ while identity and full refresh revisions fence the complete view. An explicit
|
|
|
638
719
|
OAuth start polls only that connector every two seconds for up to 30 seconds.
|
|
639
720
|
Concurrent authorizations retain independent cancellation and publication. Success,
|
|
640
721
|
failed reads, disconnect, navigation, unmount and identity reset stop the matching
|
|
641
|
-
poll. Recovery never starts authorization. A scoped result cannot confirm identity,
|
|
722
|
+
poll; a `connector_timeout` result does not. Recovery never starts authorization. A scoped result cannot confirm identity,
|
|
642
723
|
role, token slots or any other deployment-wide admission fact.
|
|
643
724
|
|
|
725
|
+
A credential connector's `/ui/data` and `/ui/connectors/<id>` row carries
|
|
726
|
+
`verification: { outcome, observedAt }` when a record of the stored save
|
|
727
|
+
exists (see [last verification](./auth.md#test-then-save-and-last-verification)).
|
|
728
|
+
The auth facts show it as **Last verified**: Verified, Saved without a test,
|
|
729
|
+
Rejected, Missing permission, Service unreachable, Test timed out or Test
|
|
730
|
+
failed, with its time. A maintainer's credential form on a testable connector
|
|
731
|
+
saves through **Test and save** (`verify: "test"`). A failed test leaves the
|
|
732
|
+
form open with fixed copy for its failure class, and adds **Save without
|
|
733
|
+
testing**, a save without `verify`. Test shows the same per-class copy and reloads
|
|
734
|
+
the connector so its last verification updates. The member page's
|
|
735
|
+
credential form saves without a test and offers Test once a value is stored.
|
|
736
|
+
|
|
644
737
|
Unreadable credential metadata uses `configured: null`, including named fields,
|
|
645
738
|
and renders as unavailable with a retry prompt. It does not claim that the slot
|
|
646
739
|
is empty. Overview, Endpoints, Connectors, connector
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Split mixed pools
|
|
2
|
+
|
|
3
|
+
Every pool must list only people or only `agent:` references. A mixed pool
|
|
4
|
+
throws `ConfigError` at construction naming the pool, for example
|
|
5
|
+
`ConnectaConfig.pools.team.members mixes people and agents; list only one kind.`
|
|
6
|
+
This also applies to personal pools with or without `owner`. Pool names and
|
|
7
|
+
connector ids do not decide membership type. People-only pools may retain an
|
|
8
|
+
`owner`; it never changes the account a person uses.
|
|
9
|
+
|
|
10
|
+
Before upgrading, inspect every pool's `members`, including generated lists.
|
|
11
|
+
For each mixed team pool, define its tool list once and create two pools:
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
const teamTools = ["crm", "tickets"];
|
|
15
|
+
const pools = {
|
|
16
|
+
team: { tools: teamTools, members: ["user_alice", "user_bob"] },
|
|
17
|
+
"assistant-team": { tools: teamTools, members: ["agent:assistant"] },
|
|
18
|
+
};
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Keep the original human pool name when possible so people's existing
|
|
22
|
+
`/mcp/team` address stays valid. Point the agent harness at
|
|
23
|
+
`/agent/assistant-team` and update its tier list to that name. Copy the
|
|
24
|
+
original `readOnly`, `surface`, `executeCode` and `description` settings
|
|
25
|
+
to both new pools as appropriate so each preserves its intended behavior.
|
|
26
|
+
If the mixed pool set `owner`, keep `owner` on the agent pool: it is the
|
|
27
|
+
Workspace address the agent acts as, and without it Workspace connectors with
|
|
28
|
+
a mapping `subject` disappear for the agent. People never use `owner`; they
|
|
29
|
+
always act as themselves, so the people pool does not need it. Agent pools
|
|
30
|
+
never count toward a person's plain `/mcp` routing, so a person who was in
|
|
31
|
+
one mixed pool and no other still reaches the people pool at plain `/mcp`.
|
|
32
|
+
|
|
33
|
+
For personal `assistant-alice` pools, keep only `"agent:assistant"` in
|
|
34
|
+
`members` and retain the owner's Workspace address and tools. Give people
|
|
35
|
+
their own people-only pools. Workspace mapping connectors act as each person;
|
|
36
|
+
shared-auth connectors act as their saved account for every member, so review
|
|
37
|
+
those grants before copying personal tool lists.
|
|
38
|
+
|
|
39
|
+
An agent can still belong to many pools with one token. Tokens, credentials,
|
|
40
|
+
`poolFor` tier selection logic and the Eve helper need no changes beyond pool
|
|
41
|
+
names in client configuration. Rebuild and restart the deployment, then verify
|
|
42
|
+
people and agents can each open their intended endpoints. See
|
|
43
|
+
[Organizing an agent's pools](./auth.md#organizing-an-agents-pools) for the
|
|
44
|
+
complete layout.
|
|
@@ -360,6 +360,67 @@ discovery for your deployment's catalog.
|
|
|
360
360
|
|
|
361
361
|
<!-- provider-inventory:end -->
|
|
362
362
|
|
|
363
|
+
## Field selection with `fields`
|
|
364
|
+
|
|
365
|
+
Every maintained read that projects a result takes an optional `fields`
|
|
366
|
+
argument: up to 50 dot paths, each 1 to 200 characters, that narrow the
|
|
367
|
+
returned data. Selection runs after value safety and privacy filtering, so it
|
|
368
|
+
can only remove values. `a.b` and `a[].b` are equivalent; a list on the way is
|
|
369
|
+
narrowed item by item.
|
|
370
|
+
|
|
371
|
+
Where paths start, the anchor, depends on the tool and is stated in each
|
|
372
|
+
`fields` schema description with one valid example:
|
|
373
|
+
|
|
374
|
+
| Tool | Paths start at | Example |
|
|
375
|
+
| ------------------------------------------ | ---------------------------------- | -------------------------------------------- |
|
|
376
|
+
| A named read (`get_*` and similar) | The result | `["id"]`, `["owner.name"]` |
|
|
377
|
+
| A named list or search (`{ items, page }`) | Each item in `items` | `["id"]`, not `["items.id"]` |
|
|
378
|
+
| `*_api_read` and `*_api_write` | The vendor response body in `data` | `["projects.name"]`, not `["data.projects"]` |
|
|
379
|
+
|
|
380
|
+
A hatch body that is a list is narrowed item by item, so its paths start at
|
|
381
|
+
each item. An enveloping vendor nests records under a root, such as
|
|
382
|
+
`{ "projects": [...] }`; select `projects.name`, not `name`. Copy hatch paths
|
|
383
|
+
from the operation's `*_api_details` `response.fields`, which are already in
|
|
384
|
+
these coordinates. Paging, cut and recovery metadata (`page`, `truncated`)
|
|
385
|
+
remain outside the selection where a tool says so.
|
|
386
|
+
|
|
387
|
+
**Refused before dispatch.** A path outside the declared contract returns
|
|
388
|
+
`invalid_args` before any request. Each finding names the entry position
|
|
389
|
+
(`/fields/1`), the segment where the path left the contract and the properties
|
|
390
|
+
declared there, never the submitted path:
|
|
391
|
+
|
|
392
|
+
- Named tools check the first segment against the properties their published
|
|
393
|
+
output schema declares for the result or item. Deeper segments follow JSON
|
|
394
|
+
Schema's default: an object is closed only where the schema says
|
|
395
|
+
`additionalProperties: false`, and only such an object refuses an undeclared
|
|
396
|
+
property. Paths through other objects, open values such as GitHub
|
|
397
|
+
`search_scoped` rows' `item`, and paths past a scalar are accepted; a miss
|
|
398
|
+
there is omitted from the selection.
|
|
399
|
+
- Hatch reads and writes check the first segment against the operation's
|
|
400
|
+
declared response roots. An operation that declares no response properties
|
|
401
|
+
refuses `fields`. The pinned index does not establish whether deeper levels
|
|
402
|
+
are complete, so deeper segments are not refused.
|
|
403
|
+
|
|
404
|
+
**Declared but absent is not an error.** Optional values, empty lists and
|
|
405
|
+
values that value safety or privacy filtering removed are ordinary. A declared
|
|
406
|
+
path the current response lacks is never refused, and the selection omits it.
|
|
407
|
+
|
|
408
|
+
**Hatch miss warnings.** A hatch answer adds `warnings: string[]` when a
|
|
409
|
+
`fields` entry matched nothing anywhere in a nonempty response. Each warning
|
|
410
|
+
names the entry position, the segment where matching stopped and the
|
|
411
|
+
properties the operation's contract declares there, for example
|
|
412
|
+
`fields/1 matched nothing in this response after value safety and privacy
|
|
413
|
+
filtering, at segment 2; declared there: id, name.` Where the contract
|
|
414
|
+
declares none, such as inside an open map, it says so. A warning never lists
|
|
415
|
+
the response's own keys, which in an open map such as `metadata` are data, and
|
|
416
|
+
never repeats the submitted path. A path that matched in any listed item, a
|
|
417
|
+
path that runs past a scalar (selection keeps the scalar), and any path of an
|
|
418
|
+
empty body (`null`, `[]` or `{}`) produce no warning. Warnings are bounded: each
|
|
419
|
+
is at most 512 characters, at most 10 are kept within 4,096 characters
|
|
420
|
+
together, reviewed vendor warnings included, and a final entry counts the rest
|
|
421
|
+
(`3 more warnings omitted.`). Treat a warning as a repair hint for the next
|
|
422
|
+
call, not as a failure.
|
|
423
|
+
|
|
363
424
|
## API operation discovery and boundaries
|
|
364
425
|
|
|
365
426
|
Standard API operation search accepts resource nouns, actions and conversational
|
|
@@ -418,6 +479,50 @@ then follow `page.nextCursor` to reach operations beyond the leading profile
|
|
|
418
479
|
results. Responses contain at most eight compact hits within 16 KiB; fetch
|
|
419
480
|
operation details separately and keep the same query when continuing.
|
|
420
481
|
|
|
482
|
+
Operation details return the request contract and, for an operation that is
|
|
483
|
+
not refused and declares success-response properties, a `response` section.
|
|
484
|
+
Write `fields` filters and reductions from it without a sampling read:
|
|
485
|
+
|
|
486
|
+
- `anchor` is `data` when paths start at the read result's `data`, or `data[]`
|
|
487
|
+
when the body is a list and each path applies to every item.
|
|
488
|
+
- `fields` lists the declared paths a read can select, in the read and write
|
|
489
|
+
tools' `fields` coordinates; pass them unchanged, such as
|
|
490
|
+
`fields: ["data[].id"]`.
|
|
491
|
+
- `withheld` is a best-effort, incomplete hint: the listed paths whose
|
|
492
|
+
non-null values value safety always withholds or redacts, by a reviewed
|
|
493
|
+
redaction path, a credential name, the deployment's sensitive-field choice
|
|
494
|
+
or a closed projection. A rule that can leave some value unchanged is never
|
|
495
|
+
a hint. Examples are URL sanitizing, reduction to an origin, which returns a
|
|
496
|
+
bare origin unchanged, redaction by a key, type or label, and a credential
|
|
497
|
+
suffix rule that scrubs only strings. A container above a hinted path is
|
|
498
|
+
not hinted either. Every hinted path also appears in `fields`.
|
|
499
|
+
- `omitted` counts declared paths not listed.
|
|
500
|
+
|
|
501
|
+
**`response` promises no readability.** Value safety runs on every read. A
|
|
502
|
+
value at any listed path, hinted or not, may still be withheld or redacted at
|
|
503
|
+
read time. An unlisted path may be too, so never treat it as safe. Many rules
|
|
504
|
+
depend on the values a vendor returns, which no index knows in advance:
|
|
505
|
+
|
|
506
|
+
- An expanded or polymorphic object is redacted by its type: for example, a
|
|
507
|
+
Stripe event's `data` or a Checkout Session's expanded `payment_intent`
|
|
508
|
+
loses a payment intent's `client_secret`.
|
|
509
|
+
- An opaque container is redacted by its contents: Google Docs
|
|
510
|
+
`inlineObjects` loses image `contentUri` capabilities, and Vercel drain
|
|
511
|
+
`headers`, deployment `env` and `protectionBypass` keys are withheld.
|
|
512
|
+
- A labelled or typed record is redacted by its label or type.
|
|
513
|
+
- URLs carrying credentials are sanitized. QuickBooks replaces every http(s)
|
|
514
|
+
URL in a returned string, including ordinary text such as a Customer
|
|
515
|
+
`DisplayName` or `CompanyName`, with `[redacted]`.
|
|
516
|
+
- A value echoing a secret the request sent is redacted.
|
|
517
|
+
|
|
518
|
+
Paths list shallowest first, in index order, up to 100 paths and 4,096
|
|
519
|
+
characters of path JSON, the hint included; a path over 200 characters is
|
|
520
|
+
never listed. The pinned index carries names only, never response types or
|
|
521
|
+
example values. Only the first page of a whole-operation answer carries
|
|
522
|
+
`response`; `param` answers and continuation pages omit it. An operation
|
|
523
|
+
without declared response properties has no `response`, and its reads refuse
|
|
524
|
+
`fields`.
|
|
525
|
+
|
|
421
526
|
Maintained REST hatches validate path parameters against their pinned contracts
|
|
422
527
|
before dispatch. Integer ids use canonical ASCII decimal notation within the
|
|
423
528
|
safe-integer range and obey the operation's declared bounds; for example,
|
|
@@ -95,16 +95,16 @@ tokens, upgrading, and diagnosis with `connecta doctor` to their procedures.
|
|
|
95
95
|
Each agent keeps one Connecta connection whose harness, never the model,
|
|
96
96
|
picks the pool per turn. Tiers are nested pools of shared connectors with
|
|
97
97
|
no `owner`, each spreading the tool list below. Recommended names are
|
|
98
|
-
`<agent>` for the lowest and `<agent>-<tier>` above it
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
directly.
|
|
98
|
+
`<agent>` for the lowest and `<agent>-<tier>` above it. Every pool lists
|
|
99
|
+
only people or only `agent:` references; mixing them throws at
|
|
100
|
+
construction. Tiers and `<agent>-<user>` pools list only the agent. People
|
|
101
|
+
with a tier's reach get their own people-only pool (for example `team`
|
|
102
|
+
beside `assistant-team`) spreading the same tool-list constant. A chat gets
|
|
103
|
+
the most capable tier everyone present is cleared for, and the lowest when
|
|
104
|
+
anyone present is unknown. `<agent>-<user>` (that user's highest tier plus
|
|
105
|
+
their own connector ids, `owner` set to their Workspace address) is used
|
|
106
|
+
only in a one-on-one with that user. Never add a second Connecta connection
|
|
107
|
+
or mount downstream tools directly.
|
|
108
108
|
- Brand the operator UI in `operatorUi({ branding })`: product and owner names,
|
|
109
109
|
description, favicon, and `theme` (`accent`, `radius`, `fontFamily`,
|
|
110
110
|
`monoFamily`, `colorScheme`). Ask the deployment's owner for their brand
|
|
@@ -380,9 +380,10 @@ declared agent, is available to signed-in maintainers.
|
|
|
380
380
|
## Select optional modules
|
|
381
381
|
|
|
382
382
|
`cloudflareAccessAuth()` reads trusted identity after Access admits the Worker
|
|
383
|
-
request. Maintainers use plain `/mcp` and the operator pages; people in a
|
|
384
|
-
use `/mcp/<pool
|
|
385
|
-
|
|
383
|
+
request. Maintainers use plain `/mcp` and the operator pages; people in a
|
|
384
|
+
people pool use `/mcp/<pool>` (or plain `/mcp` when it is their only pool), and
|
|
385
|
+
agents in an agent pool use `/agent/<pool>`; each serves exactly that pool's
|
|
386
|
+
tools. Agents authenticate with `accessTokens(storage)` over the same D1
|
|
386
387
|
database; human endpoints refuse their tokens, and Access service headers alone
|
|
387
388
|
never grant MCP access or interactive authority.
|
|
388
389
|
Keep users, groups, and admission in Access. Connector visibility and management
|
|
@@ -111,6 +111,7 @@ export default defineConfig((env: Env) => {
|
|
|
111
111
|
// Access user ids or "agent:<name>". The starter pool is the agent's base
|
|
112
112
|
// pool (shared connectors, no owner), named after the agent as the agent
|
|
113
113
|
// pool layout requires.
|
|
114
|
+
// Each pool lists only people or only agents; share tool lists across separate pools.
|
|
114
115
|
pools: { ci: { tools: ["echo"], members: ["agent:ci"] } },
|
|
115
116
|
// Connectors that declare a `credential` slot become editable by a
|
|
116
117
|
// maintainer (shared) or by the member it belongs to (personal),
|
|
@@ -11,7 +11,8 @@ has exact setup and verification steps.
|
|
|
11
11
|
|
|
12
12
|
Imagine an agent named `assistant` that helps with CRM records and tickets.
|
|
13
13
|
Its operator creates a pool with the actions needed for that job and adds
|
|
14
|
-
the agent as a member.
|
|
14
|
+
the agent as a member. Agent pools contain only agents; people use separate
|
|
15
|
+
pools that can share the same tool list. The pool can be read-only if updates must be impossible.
|
|
15
16
|
|
|
16
17
|
```mermaid
|
|
17
18
|
flowchart LR
|
package/guides/how-it-works.md
CHANGED
|
@@ -41,7 +41,7 @@ For setup and migrations, see [Integrating services](../documentation/integratin
|
|
|
41
41
|
|
|
42
42
|
A **pool** is a named selection of tools and the people or agents allowed
|
|
43
43
|
to use them. The operator creates it and gives it an **endpoint**: a
|
|
44
|
-
connection address for that pool.
|
|
44
|
+
connection address for that pool. Each pool lists only people or only agents.
|
|
45
45
|
|
|
46
46
|
One pool might let the assistant read CRM records. Another might let a
|
|
47
47
|
person update tickets. Tools and accounts are separate choices: a pool
|
|
@@ -65,7 +65,9 @@ choose the right one for the conversation. The model does not choose its
|
|
|
65
65
|
own access level.
|
|
66
66
|
|
|
67
67
|
Maintainers run the deployment and can reach its whole tool list through
|
|
68
|
-
the main human endpoint
|
|
68
|
+
the main human endpoint, `/mcp`. Other people use their assigned pools. A
|
|
69
|
+
person in exactly one pool can use that same `/mcp` address: their sign-in
|
|
70
|
+
selects the pool, and they get only its tools.
|
|
69
71
|
Agents use shared accounts selected by the operator. They do not inherit
|
|
70
72
|
the account of the person chatting with them.
|
|
71
73
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zackbart/connecta",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.40.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 six meta-tools.",
|
package/templates/node/AGENTS.md
CHANGED
|
@@ -33,8 +33,9 @@ tokens, upgrading, and diagnosis with `connecta doctor` to their procedures.
|
|
|
33
33
|
Issue or rotate an agent's token with `npm run --silent rotate-token -- <agent>`
|
|
34
34
|
against the same configuration and database the server uses; bind a token
|
|
35
35
|
from before agents once with `npm run adopt-token -- <token-id> <agent>`.
|
|
36
|
-
Plain `/mcp` serves `maintainers`
|
|
37
|
-
|
|
36
|
+
Plain `/mcp` serves `maintainers` the whole catalog and each other person
|
|
37
|
+
in exactly one pool that pool; people also reach `/mcp/<pool>` and agents
|
|
38
|
+
`/agent/<pool>` for a pool listing them in `members` (`npm run doctor`
|
|
38
39
|
checks `/agent/local-machine`). Human endpoints refuse `cta_` tokens. `CONNECTA_TOKEN` is only for clients and doctor; never add a configured
|
|
39
40
|
static bearer or an open startup mode.
|
|
40
41
|
All state, activity included, lives in the one SQLite file `CONNECTA_DATABASE`
|
|
@@ -45,16 +46,16 @@ tokens, upgrading, and diagnosis with `connecta doctor` to their procedures.
|
|
|
45
46
|
Each agent keeps one Connecta connection whose harness, never the model,
|
|
46
47
|
picks the pool per turn. Tiers are nested pools of shared connectors with
|
|
47
48
|
no `owner`, each spreading the tool list below. Recommended names are
|
|
48
|
-
`<agent>` for the lowest and `<agent>-<tier>` above it
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
directly.
|
|
49
|
+
`<agent>` for the lowest and `<agent>-<tier>` above it. Every pool lists
|
|
50
|
+
only people or only `agent:` references; mixing them throws at
|
|
51
|
+
construction. Tiers and `<agent>-<user>` pools list only the agent. People
|
|
52
|
+
with a tier's reach get their own people-only pool (for example `team`
|
|
53
|
+
beside `assistant-team`) spreading the same tool-list constant. A chat gets
|
|
54
|
+
the most capable tier everyone present is cleared for, and the lowest when
|
|
55
|
+
anyone present is unknown. `<agent>-<user>` (that user's highest tier plus
|
|
56
|
+
their own connector ids, `owner` set to their Workspace address) is used
|
|
57
|
+
only in a one-on-one with that user. Never add a second Connecta connection
|
|
58
|
+
or mount downstream tools directly.
|
|
58
59
|
- Brand the operator UI in `operatorUi({ branding })`: product and owner names,
|
|
59
60
|
description, favicon, and `theme` (`accent`, `radius`, `fontFamily`,
|
|
60
61
|
`monoFamily`, `colorScheme`). Ask the deployment's owner for their brand
|
|
@@ -102,6 +102,7 @@ export default defineConfig((env: Env) => {
|
|
|
102
102
|
// `npm run doctor` checks /agent/local-machine with its token. The starter
|
|
103
103
|
// pool is the agent's base pool, its lowest tier (shared connectors, no
|
|
104
104
|
// owner), named after the agent as the agent pool layout requires.
|
|
105
|
+
// Each pool lists only people or only agents; share tool lists across separate pools.
|
|
105
106
|
pools: { "local-machine": { tools: ["time"], members: ["agent:local-machine"] } },
|
|
106
107
|
// Machine clients are agents declared here by name, each with one cta_
|
|
107
108
|
// token. Issue or rotate one locally with
|