@zackbart/connecta 0.19.0 → 0.21.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 +107 -0
- package/README.md +3 -1
- package/bin/connecta.mjs +23 -6
- package/dist/apps-shell.d.ts +10 -12
- package/dist/apps-shell.js +29 -220
- package/dist/auth/bearer.d.ts +2 -2
- package/dist/auth/bearer.js +2 -2
- package/dist/auth/clerk.js +1 -0
- package/dist/auth/cloudflare-access.d.ts +8 -0
- package/dist/auth/cloudflare-access.js +66 -0
- package/dist/execute.d.ts +0 -7
- package/dist/execute.js +20 -123
- package/dist/index.d.ts +2 -2
- package/dist/index.js +110 -69
- package/dist/invocation.d.ts +1 -1
- package/dist/meta-tools.d.ts +0 -1
- package/dist/meta-tools.js +10 -495
- package/dist/operator-ui/generated.d.ts +2 -2
- package/dist/operator-ui/generated.js +1 -1
- package/dist/operator-ui/model.d.ts +3 -3
- package/dist/operator-ui/view.d.ts +1 -1
- package/dist/operator-ui/view.js +6 -3
- package/dist/routes/access-tokens.d.ts +1 -1
- package/dist/routes/access-tokens.js +2 -2
- package/dist/routes/activity.js +2 -2
- package/dist/routes/credentials.js +1 -1
- package/dist/routes/mcp.js +1 -1
- package/dist/routes/oauth.js +1 -1
- package/dist/routes/shared.d.ts +4 -4
- package/dist/routes/shared.js +10 -10
- package/dist/routes/ui.js +12 -9
- package/dist/skills.d.ts +1 -1
- package/dist/skills.js +11 -8
- package/dist/types.d.ts +37 -22
- package/dist/ui.d.ts +1 -1
- package/dist/ui.js +3 -3
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/documentation/architecture.md +7 -4
- package/documentation/auth.md +71 -7
- package/documentation/code-mode.md +23 -23
- package/documentation/meta-tools.md +26 -50
- package/documentation/operations.md +36 -21
- package/documentation/operator-ui.md +21 -5
- package/documentation/provider-conventions.md +3 -4
- package/documentation/upgrading.md +106 -8
- package/ethos.md +3 -4
- package/examples/worker/README.md +52 -32
- package/examples/worker/src/index.ts +32 -38
- package/examples/worker/wrangler.jsonc +12 -4
- package/package.json +5 -1
- package/templates/node/package.json +1 -1
package/ethos.md
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
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
|
-
change is wrong or this file needs amending — in that order, and amending it is
|
|
6
|
-
a design decision, not a drive-by edit.
|
|
4
|
+
preserve. A contradiction needs a design decision, not a drive-by edit.
|
|
7
5
|
|
|
8
6
|
## What this is
|
|
9
7
|
|
|
@@ -78,7 +76,8 @@ CHANGELOG, not here.
|
|
|
78
76
|
| MRTR / `input_required` passthrough | gated | relayable statelessly; no host or downstream emits it yet ([#176](https://github.com/zackbart/connecta/issues/176)) |
|
|
79
77
|
| Downstream `ttlMs` cache hints | gated | needs refresh-churn evidence ([#206](https://github.com/zackbart/connecta/issues/206)) |
|
|
80
78
|
| Downstream MCP Apps template passthrough | gated | needs a downstream that ships one ([#266](https://github.com/zackbart/connecta/issues/266)) |
|
|
81
|
-
|
|
|
79
|
+
| Worker Access inbound auth | provisional | Managed OAuth and Clerk migration need production evidence ([#506](https://github.com/zackbart/connecta/issues/506)) |
|
|
80
|
+
| 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
81
|
|
|
83
82
|
## Invariants
|
|
84
83
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# connecta — Cloudflare Worker example
|
|
2
2
|
|
|
3
3
|
A deployable Worker that aggregates a downstream remote MCP and an in-code HTTP
|
|
4
|
-
API connector, guarded by
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
API connector, guarded by Cloudflare Access, with state in a KV namespace. Its
|
|
5
|
+
required Worker Loader binding backs the seven-tool surface and requires the
|
|
6
|
+
Workers Paid plan.
|
|
7
7
|
|
|
8
8
|
This is also the **starting template for a deployment**: a real deployment
|
|
9
9
|
should be its own repository that pins an exact `@zackbart/connecta` version and
|
|
@@ -37,18 +37,27 @@ npm install # from the package root
|
|
|
37
37
|
wrangler kv namespace create CONNECTA_KV # paste the id into wrangler.jsonc
|
|
38
38
|
|
|
39
39
|
cd examples/worker
|
|
40
|
-
wrangler secret put SUPPORT_TOKEN # one headless client
|
|
41
|
-
wrangler secret put EXEC_TOKEN # another headless client
|
|
42
|
-
wrangler secret put CLERK_SECRET_KEY
|
|
43
40
|
wrangler secret put DOWNSTREAM_TOKEN
|
|
44
41
|
wrangler secret put CREDENTIAL_ENCRYPTION_KEY # base64 32-byte AES key
|
|
45
42
|
wrangler deploy
|
|
46
43
|
```
|
|
47
44
|
|
|
48
|
-
`PUBLIC_URL`
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
45
|
+
`PUBLIC_URL` is a plain var in `wrangler.jsonc`. After the first deploy, attach
|
|
46
|
+
Cloudflare Access to the Worker itself (the API destination type is `worker`,
|
|
47
|
+
not a hostname application) and choose the account, email-domain, or
|
|
48
|
+
advanced Zero Trust policy that owns admission. Enable **Managed OAuth** on
|
|
49
|
+
that Access application for interactive MCP clients. Access then serves OAuth
|
|
50
|
+
discovery and turns the client's opaque token into the trusted `ctx.access`
|
|
51
|
+
identity connecta reads. A cron job or CI client uses an Access service token
|
|
52
|
+
instead.
|
|
53
|
+
|
|
54
|
+
Cloudflare's [Worker Access guide](https://developers.cloudflare.com/workers/configuration/cloudflare-access/)
|
|
55
|
+
owns the dashboard/API steps; its [Managed OAuth guide](https://developers.cloudflare.com/cloudflare-one/access-controls/applications/http-apps/managed-oauth/)
|
|
56
|
+
owns client registration, redirect allowlists, and token lifetimes.
|
|
57
|
+
|
|
58
|
+
The checked-in `access.dev` block gives `wrangler dev` a local operator
|
|
59
|
+
identity. Remove the block to test the missing-Access refusal. It has no effect
|
|
60
|
+
on a deployed Worker's production identity.
|
|
52
61
|
|
|
53
62
|
### Copied into its own repository
|
|
54
63
|
|
|
@@ -57,24 +66,22 @@ dependency this file imports. A copy with its own `package.json` installs three
|
|
|
57
66
|
things, because two of them are not part of connecta and never install with it:
|
|
58
67
|
|
|
59
68
|
```sh
|
|
60
|
-
npm install @zackbart/connecta @cloudflare/codemode
|
|
69
|
+
npm install @zackbart/connecta @cloudflare/codemode
|
|
61
70
|
```
|
|
62
71
|
|
|
63
|
-
|
|
64
|
-
never installed with it, and
|
|
65
|
-
`@cloudflare/codemode` is the executor behind `execute_code`, published as
|
|
72
|
+
`@cloudflare/codemode` is the optional peer behind `execute_code`, declared in
|
|
73
|
+
connecta's manifest but never installed with it, and published as
|
|
66
74
|
`^0.4.4 || ^0.5.0`: install a version inside that and npm stays quiet, install
|
|
67
75
|
one outside and npm says so at install time instead of leaving a Worker to
|
|
68
76
|
discover the skew in production ([#376](https://github.com/zackbart/connecta/issues/376)).
|
|
69
77
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
without it can never write a credential or issue an access token.
|
|
78
|
+
`cloudflareAccessAuth()` has no dependency of its own. A deployment keeping
|
|
79
|
+
Clerk for rollback still installs `@clerk/backend` and keeps the commented
|
|
80
|
+
provider shape in `src/index.ts` until the migration is verified.
|
|
81
|
+
|
|
82
|
+
```sh
|
|
83
|
+
npm install @clerk/backend # migration window only
|
|
84
|
+
```
|
|
78
85
|
|
|
79
86
|
Then point an MCP client at `<PUBLIC_URL>/mcp`, and open `<PUBLIC_URL>/` for
|
|
80
87
|
Connections. Credentials is at `/credentials`, named MCP access tokens are at
|
|
@@ -87,11 +94,11 @@ the next section for what turns each one on.
|
|
|
87
94
|
This example ships the whole operator feature set. Three quarters of it is on
|
|
88
95
|
as deployed; the fourth needs a database, so it is commented in place.
|
|
89
96
|
|
|
90
|
-
**Operator sign-in** is the `
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
97
|
+
**Operator sign-in** is the `cloudflareAccessAuth()` entry in `src/index.ts`.
|
|
98
|
+
Access authenticates before the Worker runs. A human Access identity can use
|
|
99
|
+
MCP and operator pages; a service-token identity can use MCP but cannot write a
|
|
100
|
+
credential, run downstream OAuth, or issue a connecta token. Narrow admission
|
|
101
|
+
in the Access policy rather than repeating email domains or groups in code.
|
|
95
102
|
|
|
96
103
|
**The credential vault** is `credentials: { encryptionKey: … }`, backed by the
|
|
97
104
|
same KV namespace as everything else and encrypted with the
|
|
@@ -116,12 +123,18 @@ shape on `echo` is exactly it) or use a provider connector such as `notion()`,
|
|
|
116
123
|
which declares its own, and Credentials appears for a signed-in operator on the
|
|
117
124
|
next load.
|
|
118
125
|
|
|
119
|
-
**Access tokens** are `accessTokens: {}`. A signed-in operator mints named,
|
|
126
|
+
**Access tokens** are `accessTokens: {}`. A signed-in human operator mints named,
|
|
120
127
|
revocable Bearer tokens at `/tokens` for header-capable clients that will not do
|
|
121
128
|
OAuth. Secrets are shown once and only their hashes enter KV; a lost token is
|
|
122
129
|
reissued, never recovered. Note the KV caveat above — revocation is visible
|
|
123
130
|
everywhere only as fast as the namespace converges.
|
|
124
131
|
|
|
132
|
+
Worker-level Access still runs before these tokens. A `cta_…` token therefore
|
|
133
|
+
does not reach connecta by itself; retain the feature as a rollback path or for
|
|
134
|
+
a caller that already supplies separate Access service-token headers. Normal
|
|
135
|
+
interactive MCP clients should use Managed OAuth, and unattended clients should
|
|
136
|
+
use Access service tokens.
|
|
137
|
+
|
|
125
138
|
**Activity** is the commented block in `src/index.ts` and the commented
|
|
126
139
|
`d1_databases` binding in `wrangler.jsonc`; the section below creates the
|
|
127
140
|
database and applies the schema.
|
|
@@ -134,10 +147,17 @@ never the connector set, the tool catalog, or its annotations.
|
|
|
134
147
|
this on: connector count, executor, seven tools. The executor it names is this
|
|
135
148
|
one — `DynamicWorkerExecutor executed`, not the Node template's QuickJS, which
|
|
136
149
|
is what doctor used to claim everywhere
|
|
137
|
-
([#368](https://github.com/zackbart/connecta/issues/368)).
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
150
|
+
([#368](https://github.com/zackbart/connecta/issues/368)). Against Access it
|
|
151
|
+
carries `CF_ACCESS_CLIENT_ID` and `CF_ACCESS_CLIENT_SECRET`, and the service
|
|
152
|
+
identity learns the model-facing surface rather than deployment topology:
|
|
153
|
+
|
|
154
|
+
```sh
|
|
155
|
+
CF_ACCESS_CLIENT_ID=… CF_ACCESS_CLIENT_SECRET=… \
|
|
156
|
+
npx connecta doctor --url "$PUBLIC_URL"
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Confirm the operator surface the way an operator will: sign in at
|
|
160
|
+
`<PUBLIC_URL>/` and check that Tokens is live. Credentials joins it
|
|
141
161
|
once a connector declares a `credential` slot, and Activity once the D1 wiring
|
|
142
162
|
below is on — the nav shows a page when the deployment can actually serve it,
|
|
143
163
|
so a missing page is the honest report that its half is still off.
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
* connecta on Cloudflare Workers.
|
|
3
3
|
*
|
|
4
4
|
* One MCP endpoint aggregating a downstream remote MCP and an HTTP API, guarded
|
|
5
|
-
* by
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* by Cloudflare Access, with OAuth/cache state in a KV namespace. Access
|
|
6
|
+
* authenticates the request before this Worker runs and supplies the trusted
|
|
7
|
+
* identity through ctx.access. The required Worker Loader binding in
|
|
8
|
+
* wrangler.jsonc backs the seven-tool surface.
|
|
8
9
|
*
|
|
9
10
|
* The operator surface is wired here except for activity history, which needs
|
|
10
11
|
* a database this example does not create for you: sign-in, the credential
|
|
@@ -15,19 +16,16 @@
|
|
|
15
16
|
* installed `@zackbart/connecta` package):
|
|
16
17
|
* 1. `npm install` in the connecta package root (../../ from here) so the
|
|
17
18
|
* package import and wrangler resolve. A copy in its own repository
|
|
18
|
-
* installs `@zackbart/connecta @cloudflare/codemode
|
|
19
|
-
*
|
|
20
|
-
*
|
|
19
|
+
* installs `@zackbart/connecta @cloudflare/codemode` instead. Codemode is
|
|
20
|
+
* an optional peer; a migrating deployment also keeps `@clerk/backend`
|
|
21
|
+
* until it removes the commented rollback provider below.
|
|
21
22
|
* 2. Create a KV namespace and put its id in wrangler.jsonc under `kv_namespaces`.
|
|
22
23
|
* 3. Set secrets:
|
|
23
|
-
* wrangler secret put SUPPORT_TOKEN
|
|
24
|
-
* wrangler secret put EXEC_TOKEN
|
|
25
|
-
* wrangler secret put CLERK_SECRET_KEY
|
|
26
24
|
* wrangler secret put DOWNSTREAM_TOKEN
|
|
27
25
|
* wrangler secret put CREDENTIAL_ENCRYPTION_KEY
|
|
28
|
-
* and
|
|
29
|
-
* 4.
|
|
30
|
-
*
|
|
26
|
+
* and PUBLIC_URL as a plain var in wrangler.jsonc.
|
|
27
|
+
* 4. Attach Cloudflare Access to this Worker. Enable Managed OAuth on the
|
|
28
|
+
* Access application for interactive MCP clients.
|
|
31
29
|
* 5. Use the Workers Paid plan required by the `worker_loaders` binding.
|
|
32
30
|
* 6. `wrangler deploy` from this folder (examples/worker), where wrangler.jsonc
|
|
33
31
|
* lives. Point your MCP client at `<PUBLIC_URL>/mcp`.
|
|
@@ -35,23 +33,21 @@
|
|
|
35
33
|
import { DynamicWorkerExecutor } from "@cloudflare/codemode";
|
|
36
34
|
import {
|
|
37
35
|
api,
|
|
38
|
-
bearerToken,
|
|
39
36
|
createConnecta,
|
|
40
37
|
remoteMcp,
|
|
41
38
|
} from "@zackbart/connecta";
|
|
42
|
-
import {
|
|
39
|
+
import { cloudflareAccessAuth } from "@zackbart/connecta/auth/cloudflare-access";
|
|
40
|
+
// Rollback for a deployment migrating from Clerk:
|
|
41
|
+
// import { clerkAuth } from "@zackbart/connecta/auth/clerk";
|
|
43
42
|
import { cloudflareKvStorage } from "./cloudflare-kv.js";
|
|
44
43
|
// Activity history, off by default because it needs a D1 database.
|
|
45
44
|
// import { d1ActivityStore } from "./d1-activity.js";
|
|
46
45
|
|
|
47
46
|
interface Env {
|
|
48
47
|
CONNECTA_KV: KVNamespace;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
EXEC_TOKEN: string;
|
|
53
|
-
CLERK_PUBLISHABLE_KEY: string;
|
|
54
|
-
CLERK_SECRET_KEY: string;
|
|
48
|
+
// Keep these during a Clerk migration until Access has been verified:
|
|
49
|
+
// CLERK_PUBLISHABLE_KEY: string;
|
|
50
|
+
// CLERK_SECRET_KEY: string;
|
|
55
51
|
/**
|
|
56
52
|
* Base64 32-byte AES key encrypting operator-managed credentials in KV.
|
|
57
53
|
* Unset means no vault: /credentials stays read-only and connecta says so at
|
|
@@ -75,22 +71,19 @@ function build(env: Env) {
|
|
|
75
71
|
storage: cloudflareKvStorage(env.CONNECTA_KV),
|
|
76
72
|
executor: new DynamicWorkerExecutor({ loader: env.LOADER }),
|
|
77
73
|
auth: [
|
|
78
|
-
//
|
|
79
|
-
//
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
//
|
|
87
|
-
//
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
publicUrl: env.PUBLIC_URL,
|
|
92
|
-
// allowedDomains: ["acme.com"],
|
|
93
|
-
}),
|
|
74
|
+
// Access owns admission policy. A human identity may use MCP and the
|
|
75
|
+
// operator pages; a service token may use MCP but cannot mutate operator
|
|
76
|
+
// state. Neither path asks connecta to parse a JWT.
|
|
77
|
+
cloudflareAccessAuth(),
|
|
78
|
+
// Leave the previous Clerk provider below this entry during migration.
|
|
79
|
+
// It is a rollback path until Worker-level Access is detached; Access
|
|
80
|
+
// itself decides whether a request reaches this array.
|
|
81
|
+
// clerkAuth({
|
|
82
|
+
// publishableKey: env.CLERK_PUBLISHABLE_KEY,
|
|
83
|
+
// secretKey: env.CLERK_SECRET_KEY,
|
|
84
|
+
// publicUrl: env.PUBLIC_URL,
|
|
85
|
+
// allowedDomains: ["acme.com"],
|
|
86
|
+
// }),
|
|
94
87
|
],
|
|
95
88
|
// Connectors that declare a `credential` slot become editable at
|
|
96
89
|
// /credentials, encrypted with this key before anything reaches KV. A
|
|
@@ -105,8 +98,9 @@ function build(env: Env) {
|
|
|
105
98
|
// `echo`, or use a provider connector like `notion()`, which declares its
|
|
106
99
|
// own) and the page appears on the next load.
|
|
107
100
|
credentials: { encryptionKey: env.CREDENTIAL_ENCRYPTION_KEY },
|
|
108
|
-
// Eligible
|
|
109
|
-
// at /tokens.
|
|
101
|
+
// Eligible human operators can create named, revocable MCP Bearer tokens
|
|
102
|
+
// at /tokens. Under Worker-level Access those tokens are a rollback tool,
|
|
103
|
+
// not standalone edge credentials: Access still runs before connecta.
|
|
110
104
|
accessTokens: {},
|
|
111
105
|
// Payload-free activity at /activity, off until a database exists to hold
|
|
112
106
|
// it. Uncomment the `d1_databases` binding in wrangler.jsonc, apply the
|
|
@@ -6,12 +6,20 @@
|
|
|
6
6
|
"compatibility_flags": ["nodejs_compat"],
|
|
7
7
|
"observability": { "enabled": true },
|
|
8
8
|
|
|
9
|
-
// Plain vars. Secrets (
|
|
10
|
-
// CREDENTIAL_ENCRYPTION_KEY, DOWNSTREAM_TOKEN) are set with
|
|
9
|
+
// Plain vars. Secrets (CREDENTIAL_ENCRYPTION_KEY, DOWNSTREAM_TOKEN) are set with
|
|
11
10
|
// `wrangler secret put <NAME>`, not here.
|
|
12
11
|
"vars": {
|
|
13
|
-
"PUBLIC_URL": "https://connecta.example.workers.dev"
|
|
14
|
-
|
|
12
|
+
"PUBLIC_URL": "https://connecta.example.workers.dev"
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
// Local-only Access identity. Remove this block to exercise the
|
|
16
|
+
// unauthenticated path in `wrangler dev`; production identity comes from the
|
|
17
|
+
// Worker-level Access application, not from this file.
|
|
18
|
+
"access": {
|
|
19
|
+
"dev": {
|
|
20
|
+
"aud": "connecta-local",
|
|
21
|
+
"identity": { "email": "operator@example.com" }
|
|
22
|
+
}
|
|
15
23
|
},
|
|
16
24
|
|
|
17
25
|
// Create with `wrangler kv namespace create CONNECTA_KV` and paste the id.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zackbart/connecta",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.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.",
|
|
@@ -63,6 +63,10 @@
|
|
|
63
63
|
"types": "./dist/auth/clerk.d.ts",
|
|
64
64
|
"import": "./dist/auth/clerk.js"
|
|
65
65
|
},
|
|
66
|
+
"./auth/cloudflare-access": {
|
|
67
|
+
"types": "./dist/auth/cloudflare-access.d.ts",
|
|
68
|
+
"import": "./dist/auth/cloudflare-access.js"
|
|
69
|
+
},
|
|
66
70
|
"./providers/cloudflare": {
|
|
67
71
|
"types": "./dist/providers/cloudflare.d.ts",
|
|
68
72
|
"import": "./dist/providers/cloudflare.js"
|