@zackbart/connecta 0.6.0 → 0.7.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.
Files changed (72) hide show
  1. package/CHANGELOG.md +403 -0
  2. package/README.md +163 -308
  3. package/dist/auth/bearer.d.ts +4 -3
  4. package/dist/auth/bearer.d.ts.map +1 -1
  5. package/dist/auth/bearer.js +10 -8
  6. package/dist/auth/bearer.js.map +1 -1
  7. package/dist/auth/clerk.d.ts +8 -7
  8. package/dist/auth/clerk.d.ts.map +1 -1
  9. package/dist/auth/clerk.js +27 -8
  10. package/dist/auth/clerk.js.map +1 -1
  11. package/dist/connector-scope.d.ts +13 -0
  12. package/dist/connector-scope.d.ts.map +1 -0
  13. package/dist/connector-scope.js +35 -0
  14. package/dist/connector-scope.js.map +1 -0
  15. package/dist/connectors/api.d.ts +5 -5
  16. package/dist/connectors/api.d.ts.map +1 -1
  17. package/dist/connectors/remote-mcp.d.ts +3 -3
  18. package/dist/connectors/remote-mcp.d.ts.map +1 -1
  19. package/dist/connectors/remote-mcp.js +309 -10
  20. package/dist/connectors/remote-mcp.js.map +1 -1
  21. package/dist/credential-health.d.ts +20 -9
  22. package/dist/credential-health.d.ts.map +1 -1
  23. package/dist/credential-health.js +127 -63
  24. package/dist/credential-health.js.map +1 -1
  25. package/dist/credentials.d.ts +84 -1
  26. package/dist/credentials.d.ts.map +1 -1
  27. package/dist/credentials.js +109 -2
  28. package/dist/credentials.js.map +1 -1
  29. package/dist/index.d.ts +83 -82
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +101 -31
  32. package/dist/index.js.map +1 -1
  33. package/dist/meta-tools.d.ts +3 -3
  34. package/dist/meta-tools.d.ts.map +1 -1
  35. package/dist/meta-tools.js +16 -7
  36. package/dist/meta-tools.js.map +1 -1
  37. package/dist/registry.d.ts +3 -2
  38. package/dist/registry.d.ts.map +1 -1
  39. package/dist/registry.js +4 -3
  40. package/dist/registry.js.map +1 -1
  41. package/dist/server.d.ts +1 -1
  42. package/dist/server.d.ts.map +1 -1
  43. package/dist/server.js +154 -52
  44. package/dist/server.js.map +1 -1
  45. package/dist/skills.js +2 -2
  46. package/dist/skills.js.map +1 -1
  47. package/dist/toolkits.js +1 -1
  48. package/dist/types.d.ts +51 -26
  49. package/dist/types.d.ts.map +1 -1
  50. package/dist/ui.d.ts +52 -21
  51. package/dist/ui.d.ts.map +1 -1
  52. package/dist/ui.js +665 -196
  53. package/dist/ui.js.map +1 -1
  54. package/dist/version.d.ts +1 -1
  55. package/dist/version.js +1 -1
  56. package/package.json +3 -2
  57. package/src/auth/bearer.ts +10 -8
  58. package/src/auth/clerk.ts +28 -9
  59. package/src/connector-scope.ts +41 -0
  60. package/src/connectors/api.ts +5 -5
  61. package/src/connectors/remote-mcp.ts +348 -25
  62. package/src/credential-health.ts +151 -71
  63. package/src/credentials.ts +166 -3
  64. package/src/index.ts +202 -113
  65. package/src/meta-tools.ts +22 -7
  66. package/src/registry.ts +4 -3
  67. package/src/server.ts +197 -71
  68. package/src/skills.ts +2 -2
  69. package/src/toolkits.ts +1 -1
  70. package/src/types.ts +51 -26
  71. package/src/ui.ts +703 -195
  72. package/src/version.ts +1 -1
package/README.md CHANGED
@@ -2,9 +2,28 @@
2
2
 
3
3
  ![A monochrome clay Connecta hub joining many tools](./assets/connecta-clay-hero.png)
4
4
 
5
- One MCP to rule them all. A single MCP endpoint that aggregates many downstream
6
- connectors remote MCP servers and plain HTTP APIs and presents agents a fixed
7
- set of **nine meta-tools** instead of hundreds of individual tools.
5
+ One MCP endpoint in front of all your connectors. Agents see nine tools instead
6
+ of hundreds, and each client is configured once instead of once per integration.
7
+
8
+ ## The problem
9
+
10
+ An agent connected to N MCP servers pays for all N before it does anything. Every
11
+ server's tool list is injected into the context window at connect time — hundreds
12
+ of definitions and their schemas, nearly all irrelevant to the task actually at
13
+ hand. That budget is spent whether the model calls one of them or none, and it
14
+ comes out of the same window the work needs.
15
+
16
+ The second cost is configuration. Every client — Claude, Cursor, whatever comes
17
+ next — has to be pointed at each server separately, with its own auth for each.
18
+ Adding an integration means touching every client; rotating one token means
19
+ finding every place it was pasted.
20
+
21
+ ## What connecta is
22
+
23
+ One MCP endpoint you deploy — Cloudflare Worker, Node, or Docker — that
24
+ aggregates your downstream connectors behind a fixed set of **nine meta-tools**.
25
+ A connector is either a remote MCP server that connecta proxies, or a plain HTTP
26
+ API with hand-written tool definitions and a fetch handler.
8
27
 
9
28
  ```
10
29
  ┌── remoteMcp("notion") → mcp.notion.com
@@ -13,14 +32,99 @@ Claude / Cursor ── MCP ──▶ connecta ───┼── remoteMcp("lin
13
32
  └── api("internal") → fetch(...)
14
33
  ```
15
34
 
16
- The agent always sees exactly nine tools; it searches when it needs something and
17
- describes only what it will call. Progressive disclosure is the point. Connectors
18
- are declared in TypeScript (config as code adding one is a code change + deploy,
19
- no database of integrations), and the same fetch-based core runs on **Node** and
20
- **Cloudflare Workers**. Optionally, **code mode** adds a tenth tool that runs
21
- model-written orchestration code in a sandbox.
22
-
23
- ## Installation
35
+ Rather than receiving every tool up front, the agent discovers what it needs.
36
+ `search_tools` returns ranked matches for a query and `describe_tools` returns
37
+ schemas compact by default, raw JSON Schema on request for only the
38
+ addresses it is about to call. `call_tool`,
39
+ `batch_call`, and `call_destructive_tool` invoke them by address
40
+ (`<connectorId>.<toolName>`). `list_connectors` reports what exists and whether
41
+ it is reachable, `authorize_connector` starts a downstream OAuth flow,
42
+ `get_result` pages through a result too large to return inline, and `skills`
43
+ hands the model a short guide to choosing among the rest.
44
+
45
+ That is the entire surface. The agent's context holds nine tool definitions
46
+ whether ten tools sit behind them or a thousand — and the client holds one URL
47
+ and one credential, no matter how many services that URL fans out to.
48
+
49
+ An optional tenth meta-tool, `execute_code`, runs model-written async JavaScript
50
+ in a sandbox with no network, filesystem, or environment access — only the
51
+ explicitly read-only tools as callable globals — turning a loop, a join across
52
+ connectors, or a filter over a large response into one round trip instead of a
53
+ dozen. Configure no `executor` and connecta is exactly the nine-tool server.
54
+
55
+ ## Why it's shaped this way
56
+
57
+ **Config as code, one deployment per tenant.** Connectors are declared in
58
+ TypeScript. Adding one is a code change and a deploy — no database of
59
+ integrations, no registration API, no runtime admin. A deployment is a small
60
+ config file you can read in one sitting and review in a pull request, not a
61
+ platform to administer.
62
+
63
+ **Credentials stay server-side.** Downstream tokens live in an AES-GCM encrypted
64
+ vault over the deployment's own storage, with the key held outside it. A
65
+ connector reaches its own credential through `ctx.credential`; the operator
66
+ pages, meta-tools, and code sandbox never expose a secret value. Rotating a token
67
+ at `/credentials` is an operator action rather than a redeploy — though writing
68
+ to the vault is deliberately narrower than everything else, requiring a
69
+ Clerk-authenticated operator on a same-origin request, so a bearer-only
70
+ deployment cannot administer credentials from the browser. Which tools exist
71
+ is still code either way.
72
+
73
+ **Read-only is fail-closed.** Only tools explicitly annotated `readOnlyHint:
74
+ true` are reachable through `call_tool`, `batch_call`, and the sandbox. Missing,
75
+ false, or contradictory annotations do not get the benefit of the doubt: they
76
+ require `call_destructive_tool`, which is itself annotated so the MCP host can
77
+ put the question to a human. Connecta makes the boundary visible; approval is
78
+ the host's job.
79
+
80
+ **Toolkits scope what a team sees.** A deployment belongs to an org; a toolkit
81
+ is a named view over its registry for one group inside that org — support sees
82
+ Zendesk and Notion, exec also sees Gmail. A client selects one with
83
+ `?toolkit=support` on the MCP URL, and a credential can be bound so it opens
84
+ that view and nothing else. Inside a scoped session an out-of-scope address
85
+ fails exactly as a nonexistent one does. Two teams, one deployment. Who gets in
86
+ at all is the prior question: a static bearer token, or Clerk — where
87
+ `allowedDomains: ["acme.com"]` admits anyone whose verified primary email is on
88
+ your domain without enumerating users, and a `gate` hook handles what a domain
89
+ rule cannot express. Both fail closed, and each one configured must pass.
90
+
91
+ **Activity records the fact, not the payload.** The optional activity store logs
92
+ which resolved tool ran, for whom, and how it went — never arguments, results,
93
+ generated code, search text, or raw error messages. The exclusion is structural
94
+ rather than a redaction pass: the event type has nowhere to put a payload, which
95
+ is what keeps an operations log from becoming something worth stealing.
96
+
97
+ **Operator pages that cannot administer the deployment.** Connections at `GET /`
98
+ shows connector health, tool counts, and downstream authorization links;
99
+ `/credentials` rotates stored secrets; and `/activity` shows the optional
100
+ payload-free ledger. They share one data-free shell with no build step and use
101
+ authenticated private APIs for deployment data. They cannot add a connector,
102
+ change policy, or alter what an agent may call. Credentials connecta stores are
103
+ also probed for liveness
104
+ proactively — using each connector's own test or status hook, never a downstream
105
+ tool call — so a dead token surfaces as `auth_required` with the URL to open on
106
+ Connections and in `list_connectors` before an agent's real call trips over it.
107
+
108
+ ## When not to use it
109
+
110
+ Connecta is deliberately small, and declines several tempting shapes.
111
+ It is **not multi-tenant** — one deployment is one tenant, with one registry and
112
+ one credential store, and toolkits are scoped views rather than tenants. There
113
+ is **no policy engine**, no approvals, and no pauses — access decisions are
114
+ fixed ones connecta already knows how to answer (is this tool read-only, may
115
+ this credential open this toolkit), not rules you author. There is **no runtime
116
+ administration** — you cannot add a connector from a browser or an API. It
117
+ aggregates **tools only**, not MCP resources or prompts, and it will not ingest
118
+ a **GraphQL** schema, because generating hundreds of low-quality tool
119
+ definitions is the problem the nine meta-tools exist to solve. OpenAPI is a
120
+ softer no: not built in today, not refused either, and tracked as
121
+ [issue #26](https://github.com/zackbart/connecta/issues/26). If you want a
122
+ hosted multi-tenant integration platform with an approval workflow, this is the
123
+ wrong shape; the
124
+ [non-goals](https://github.com/zackbart/connecta/blob/main/docs/decisions.md#non-goals)
125
+ say so at more length.
126
+
127
+ ## Getting started
24
128
 
25
129
  Node deployments require Node.js 20.9 or newer.
26
130
 
@@ -28,318 +132,69 @@ Node deployments require Node.js 20.9 or newer.
28
132
  npm install @zackbart/connecta
29
133
  ```
30
134
 
31
- Provider and runtime integrations remain consumer-owned. Install only the
32
- optional packages a deployment uses—for example:
33
-
34
- ```sh
35
- npm install @clerk/backend # optional Clerk auth adapter
36
- npm install quickjs-emscripten # optional Node code-mode executor
37
- npm install @cloudflare/codemode # optional Worker code-mode executor
38
- ```
39
-
40
- ## The nine meta-tools
41
-
42
- A tool **address** is `<connectorId>.<toolName>` (e.g. `notion.search`).
43
-
44
- | Tool | Input | Returns |
45
- | --- | --- | --- |
46
- | `list_connectors` | `{ probe? }` | live (`probe: true`, default) or cached health, tool count, recent real-call observations, and the last proactive credential check |
47
- | `skills` | `{ name? }` | lists or fetches the concise `usage` guide for choosing among the meta-tools, plus any operator-authored per-connector guide (`connector:<connectorId>`) |
48
- | `search_tools` | `{ query?, connector?, limit?, offset?, fullDescriptions?, includeSchemas? }` | ranked, paginated matches; optionally includes compact/raw schemas to remove a round trip |
49
- | `describe_tools` | `{ addresses[], format?, fullDescriptions? }` | names, descriptions, input/output schemas, and behavior annotations |
50
- | `call_tool` | `{ address, args?, fields?, resultMode?, timeoutMs?, maxRetries?, diagnostics? }` | invokes only tools explicitly annotated `readOnlyHint: true` |
51
- | `call_destructive_tool` | same as `call_tool` | invokes unannotated, write-capable, or destructive tools through a host-visible approval boundary |
52
- | `authorize_connector` | `{ connector, force? }` | starts (or with `force`, restarts) the downstream OAuth flow; returns the `authorizationUrl` to open |
53
- | `get_result` | `{ id, offset?, maxBytes? }` | a byte-slice page of a truncated result — `{ text, offset, nextOffset?, totalBytes }`; `maxBytes` is a whole number of bytes >= 1 and `offset` a whole number of bytes >= 0, aligned back to a character boundary and echoed as the `offset` served |
54
- | `batch_call` | `{ calls, resultMode?, timeoutMs?, maxRetries? }` | 1–10 parallel calls sharing request-scoped clients, with attempts/timing/errors |
55
- | `execute_code` *(optional)* | `{ code }` | result + logs of bounded async JS orchestration over explicitly read-only tools; registered only when an `executor` is configured |
56
-
57
- ## Package vs. deployments
58
-
59
- This repository owns the reusable package. Each deployment should be a small,
60
- separate Worker project that pins an exact package version and owns only its
61
- connector configuration, auth policy, domain, bindings, migrations, and secrets.
62
- [`examples/worker/`](./examples/worker/) is the starting template.
63
-
64
- ## Quickstart — Cloudflare Worker
65
-
66
- ```ts
67
- import { DynamicWorkerExecutor } from "@cloudflare/codemode";
68
- import { bearerToken, createConnecta, remoteMcp } from "@zackbart/connecta";
69
- import { clerkAuth } from "@zackbart/connecta/auth/clerk";
70
- import { cloudflareKvStorage } from "./cloudflare-kv.js";
71
-
72
- const build = (env: Env) =>
73
- createConnecta({
74
- publicUrl: env.PUBLIC_URL,
75
- storage: cloudflareKvStorage(env.CONNECTA_KV),
76
- // Code mode (optional): needs a `worker_loaders` binding in wrangler.jsonc.
77
- executor: new DynamicWorkerExecutor({ loader: env.LOADER }),
78
- auth: [
79
- bearerToken(env.CONNECTA_TOKEN),
80
- clerkAuth({
81
- publishableKey: env.CLERK_PUBLISHABLE_KEY,
82
- secretKey: env.CLERK_SECRET_KEY,
83
- publicUrl: env.PUBLIC_URL,
84
- // allowedDomains: ["acme.com"], // only your org's verified emails
85
- }),
86
- ],
87
- connectors: [
88
- remoteMcp("notion", {
89
- url: "https://mcp.notion.com/mcp",
90
- auth: { type: "headers", headers: { Authorization: `Bearer ${env.NOTION_TOKEN}` } },
91
- }),
92
- ],
93
- });
94
-
95
- // Lazy per-isolate singleton: keeps only serializable tool/catalog data warm.
96
- let connecta: ReturnType<typeof build> | undefined;
97
-
98
- export default {
99
- fetch(request: Request, env: Env): Promise<Response> {
100
- connecta ??= build(env);
101
- return connecta.fetch(request);
102
- },
103
- };
104
- ```
105
-
106
- Deployable example: [`examples/worker/`](./examples/worker/).
107
- Its Cloudflare KV and D1 implementations are deployment-owned examples over the
108
- generic `KVStorage` and `ActivityStore` contracts; they are not package exports.
109
-
110
- `clerkAuth` is an optional adapter. Install `@clerk/backend` and import it from
111
- `@zackbart/connecta/auth/clerk` only in deployments that use Clerk. Other
112
- identity providers can implement the exported `InboundAuth` interface.
113
-
114
- ## Quickstart — Node
135
+ A minimal server with one hand-written connector:
115
136
 
116
137
  ```ts
117
138
  import { api, bearerToken, createConnecta } from "@zackbart/connecta";
118
139
  import { fileStorage, listen } from "@zackbart/connecta/node";
119
- import { quickJsExecutor } from "@zackbart/connecta/quickjs";
120
140
 
121
141
  const connecta = createConnecta({
122
142
  storage: fileStorage("./.connecta-state.json"), // or memoryStorage()
123
- auth: bearerToken(process.env.CONNECTA_TOKEN!),
124
- executor: quickJsExecutor(), // code mode (optional): QuickJS/WASM sandbox
143
+ auth: bearerToken(process.env.CONNECTA_TOKEN ?? "dev-token"),
125
144
  connectors: [
126
145
  api("time", {
127
- description: "Time — clock utilities",
128
- tools: [{
129
- name: "get_now",
130
- description: "Return the current ISO timestamp.",
131
- inputSchema: { type: "object", properties: {} },
132
- annotations: { readOnlyHint: true },
133
- handler: async () => ({ now: new Date().toISOString() }),
134
- }],
135
- }),
136
- ],
137
- });
138
-
139
- listen(connecta, 8787); // http://localhost:8787/mcp
140
- ```
141
-
142
- Example: [`examples/node/`](./examples/node/). Docker (single-service compose
143
- stack): [`examples/docker/`](./examples/docker/).
144
-
145
- ## Toolkits — one deployment, many teams
146
-
147
- A deployment belongs to an org. Optional **toolkits** give each group of team
148
- members its own scoped view of the same registry — bound to that group's
149
- credential — so different teams no longer need separate deployments:
150
-
151
- ```ts
152
- createConnecta({
153
- connectors: [zendesk, notion, gmail],
154
- auth: [
155
- // Each team's credential is bound to that team's view.
156
- bearerToken(env.SUPPORT_TOKEN, { subjectId: "support", toolkits: ["support"] }),
157
- bearerToken(env.EXEC_TOKEN, { subjectId: "exec", toolkits: ["exec"] }),
158
- // The operator's: every view, plus /ui — declared, not left unbound.
159
- bearerToken(env.OPS_TOKEN, {
160
- subjectId: "ops",
161
- toolkits: ["support", "exec"],
162
- unscoped: true,
146
+ description: "Time — current timestamp",
147
+ tools: [
148
+ {
149
+ name: "get_now",
150
+ description: "Return the current time as an ISO 8601 timestamp.",
151
+ inputSchema: { type: "object", properties: {} },
152
+ annotations: { readOnlyHint: true },
153
+ handler: async () => ({ now: new Date().toISOString() }),
154
+ },
155
+ ],
163
156
  }),
164
157
  ],
165
- toolkits: {
166
- support: { connectors: ["zendesk", "notion"] },
167
- exec: {
168
- connectors: ["zendesk", "notion", "gmail"],
169
- excludeTools: ["gmail.send_message"], // finer grain than a connector id
170
- },
171
- },
172
158
  });
173
- ```
174
-
175
- A client picks one at connect time: `https://…/mcp?toolkit=support`. Inside a
176
- scoped session **every** meta-tool — search, describe, call, batch, skills,
177
- authorize, `get_result`, and `execute_code` host calls — behaves as if
178
- out-of-scope connectors and tools do not exist, and an out-of-scope address
179
- fails identically to a nonexistent one. No `?toolkit=` ⇒ the full registry, as
180
- before; an unknown name is an error, never a silent fallback.
181
-
182
- `toolkits: [...]` on an auth adapter **binds** a credential to its views: the
183
- support token cannot open `?toolkit=exec`, cannot connect unscoped (unless it also
184
- passes `unscoped: true`), and cannot read the deployment-wide operator surfaces.
185
- Refusal is a flat 403 at connect time, identical whether the toolkit is another
186
- team's or does not exist at all — a mapping, not a policy engine. Leave `toolkits`
187
- off and that credential keeps today's self-service selection. Details:
188
- [docs §16](./docs/documentation.md#16-toolkits-scoped-views).
189
-
190
- ## Code mode
191
159
 
192
- With an `executor` configured, the model can write an async function instead of
193
- making one `call_tool` round trip per step — loops, joins across connectors,
194
- filtering big responses down in-sandbox before they hit the context window:
195
-
196
- ```js
197
- async () => {
198
- const pages = await notion.search({ query: "roadmap" });
199
- return pages.results.map((p) => p.title);
200
- }
160
+ listen(connecta, 8787); // MCP at /mcp; Connections at http://localhost:8787/
201
161
  ```
202
162
 
203
- The sandbox has **no** network/filesystem/env only explicitly read-only
204
- connector globals and
205
- `connecta.call`, `connecta.batch`, `connecta.search`, and `connecta.describe`;
206
- credentials stay host-side. A run may make at most 20 host calls, a
207
- `connecta.batch` may contain at most 10 calls, and every host call has a
208
- 15-second deadline. Executors:
209
- `DynamicWorkerExecutor` (`@cloudflare/codemode`,
210
- Workers, Worker Loader binding open beta) or `quickJsExecutor()`
211
- (`@zackbart/connecta/quickjs`, QuickJS-in-WASM, runs anywhere). Omit the `executor` and
212
- connecta is exactly the nine-tool server. Details:
213
- [docs §13](./docs/documentation.md#13-code-mode-execute_code).
214
-
215
- ## Credentials in `/ui`
216
-
217
- API connectors can declare one operator-managed credential or a named set of
218
- credential fields. Connecta renders
219
- Add / Replace / Test / Remove controls inside that connector's `/ui` card,
220
- encrypts the values with AES-GCM, and stores only ciphertext in the deployment's
221
- existing `KVStorage`. Credentials are available only to the connector through
222
- `ctx.credential.get()`, `get(name)`, or `getAll()`; they are never returned by
223
- `/ui`, MCP tools, or code mode.
224
-
225
- ```ts
226
- api("example", {
227
- description: "Example — authenticated API",
228
- credential: {
229
- label: "API token",
230
- description: "Token used for outbound Example API requests.",
231
- },
232
- tools: [{
233
- name: "get_profile",
234
- description: "Get the authenticated Example profile.",
235
- inputSchema: { type: "object", properties: {} },
236
- annotations: { readOnlyHint: true },
237
- handler: async (_args, ctx) => {
238
- const token = await ctx.credential?.get();
239
- if (!token) throw new Error("Example API token is not configured.");
240
- return fetch("https://api.example.com/profile", {
241
- headers: { Authorization: `Bearer ${token}` },
242
- }).then((response) => response.json());
243
- },
244
- }],
245
- })
246
- ```
247
-
248
- Set `credentialEncryptionKey` on `createConnecta` to a base64-encoded 32-byte
249
- key held in the runtime's secret store (`openssl rand -base64 32`) — a connector
250
- that declares a credential without one fails at construction rather than booting
251
- with an unusable vault. Credential mutation routes require the configured Clerk
252
- provider and a same-origin browser request; the static inbound bearer cannot
253
- administer the vault.
254
-
255
- Connecta does not bundle service-specific HTTP API connectors. Package consumers
256
- define them with `api()` (or implement `Connector` directly), keeping endpoint,
257
- credential, and tool choices in the consuming project.
258
-
259
- ## Credential health
260
-
261
- Stored credentials are checked for liveness *before* an agent's call trips over a
262
- dead one. Connecta asks each connector holding a credential it stores — a vault
263
- credential, or a downstream-OAuth grant — whether that credential still works,
264
- using the connector's own `testCredential(s)` or `status()` hook. No downstream
265
- tool is ever called. A check that finds the credential *rejected* flips the
266
- connector to `auth_required` in `list_connectors({ probe: false })` and on
267
- `/ui`, with the URL to open; a later success (or re-authorizing) flips it back
268
- with no restart. A check that merely failed to complete — a timeout, a 502 from
269
- the status endpoint — is reported but never decides the status: it learned
270
- nothing about the credential.
271
-
272
- Checks are triggered two ways and share one rate limit — at most one per
273
- connector per 15 minutes by default, four in flight, 30 s each:
274
-
275
- ```ts
276
- // 1. Opportunistically, on authenticated traffic connecta already serves.
277
- // On by default; nothing to wire. Disable with:
278
- createConnecta({ connectors, credentialHealth: { onRequest: false } });
279
-
280
- // 2. On a schedule you own — the core starts no timers, so this works the same
281
- // on Workers (cron trigger) and Node.
282
- async scheduled(_c, env, ctx) { ctx.waitUntil(build(env).checkCredentials()); }
283
- setInterval(() => void connecta.checkCredentials(), 15 * 60_000).unref();
284
- ```
285
-
286
- Details: [docs §17](./docs/documentation.md#17-credential-health-proactive-liveness-checks).
287
-
288
- ## Payload-free tool activity
289
-
290
- Connecta can record which resolved downstream tools were actually invoked
291
- without storing their arguments, results, generated code, search text, or raw
292
- errors. Supply a vendor-neutral `activity` store:
293
-
294
- ```ts
295
- const events: ToolCallActivityEvent[] = [];
296
-
297
- const connecta = createConnecta({
298
- connectors,
299
- activity: {
300
- record(event) {
301
- events.push(event);
302
- },
303
- async list({ limit }) {
304
- return { events: events.slice(-limit).reverse() };
305
- },
306
- },
307
- });
308
- ```
309
-
310
- One final event is emitted for each resolved connector call made through
311
- `call_tool`, `call_destructive_tool`, `batch_call`, or `execute_code`; retries
312
- remain one event with an `attempts` count. Implementing `list` enables the
313
- authenticated Activity tab in `/ui`; `activityReadGate` can narrow reads
314
- further. Writes are best-effort and never change a tool result. Clerk calls
315
- carry the Clerk user ID; shared bearer calls are honestly labeled as bearer
316
- unless `bearerToken(secret, { subjectId })` assigns that credential a stable
317
- subject. On Workers, pass `ctx` through to `connecta.fetch(request, env, ctx)`
318
- so async writes settle on `waitUntil`.
319
- [`examples/worker/src/d1-activity.ts`](./examples/worker/src/d1-activity.ts) is
320
- a complete D1 implementation with keyset paging and a retention pass.
321
-
322
- ## Operator dashboard
323
-
324
- `GET /ui` is a read-only dashboard with no build step: connector health and the
325
- last credential check, tool
326
- counts and descriptions with a client-side filter, downstream authorization
327
- links, the credential controls above, and an Activity tab when an activity store
328
- is configured. The shell is open because it carries no data; everything it shows
329
- comes from `/ui/data`, behind the same auth gate as `/mcp`. With Clerk
330
- configured it signs operators in through Clerk's hosted portal; a bearer-only
331
- deployment falls back to a pasted token.
332
-
333
- Every deployment-facing label and mark on `/ui` and the OAuth result pages comes
334
- from `ConnectaConfig.branding` — `productName`, `ownerName`, their URLs,
335
- `description`, `pageTitle`, `themeColor`, and `favicon` — each falling back to a
336
- neutral Connecta default. Nothing about the operator is baked into the package.
163
+ Point an MCP client at `http://localhost:8787/mcp` with an
164
+ `Authorization: Bearer` header and it will see the nine meta-tools, with
165
+ `time.get_now` discoverable through `search_tools`.
166
+
167
+ Runnable deployments live in
168
+ [`examples/`](https://github.com/zackbart/connecta/tree/main/examples):
169
+ [`worker/`](https://github.com/zackbart/connecta/tree/main/examples/worker) is a
170
+ deployable Cloudflare Worker with KV and D1 adapters, and the template to copy
171
+ for a real deployment;
172
+ [`node/`](https://github.com/zackbart/connecta/tree/main/examples/node) adds
173
+ toolkits and code mode to the server above;
174
+ [`docker/`](https://github.com/zackbart/connecta/tree/main/examples/docker) is a
175
+ single-service compose stack. Anything beyond the core is installed only by the
176
+ deployments that use it: `@clerk/backend` and `quickjs-emscripten` are optional
177
+ peer dependencies, reached through the `/auth/clerk` and `/quickjs` subpaths,
178
+ and a Worker using code mode brings its own `@cloudflare/codemode`. Connecta
179
+ ships no service-specific connectors:
180
+ endpoint, credential, and tool choices stay in your project, declared with
181
+ `remoteMcp()` and `api()`.
337
182
 
338
183
  ## Learn more
339
184
 
340
- - **[`docs/documentation.md`](./docs/documentation.md)** — how everything works: architecture,
341
- the meta-tools, connectors and their usage guides, inbound auth, downstream
342
- OAuth, storage, running it (Node / Workers / Docker), Clerk setup, testing,
343
- troubleshooting, code mode, the status UI, activity history, and toolkits.
344
- - **[`docs/design.md`](./docs/design.md)** — why it's built this way, and the non-goals.
345
- - **[`CHANGELOG.md`](./CHANGELOG.md)** — what changed in each release.
185
+ - **[Documentation](https://github.com/zackbart/connecta/blob/main/docs/documentation.md)**
186
+ the reference index for architecture, connectors, inbound auth and
187
+ downstream OAuth, storage, Clerk setup, testing, and troubleshooting. Start
188
+ with the [meta-tools reference](https://github.com/zackbart/connecta/blob/main/docs/meta-tools.md#meta-tools-reference),
189
+ the [config options](https://github.com/zackbart/connecta/blob/main/docs/operations.md#running-it),
190
+ [code mode](https://github.com/zackbart/connecta/blob/main/docs/code-mode.md#code-mode-execute_code),
191
+ [toolkits](https://github.com/zackbart/connecta/blob/main/docs/toolkits.md#toolkits-scoped-views),
192
+ [operator pages](https://github.com/zackbart/connecta/blob/main/docs/operator-ui.md#status-ui),
193
+ or [credential health](https://github.com/zackbart/connecta/blob/main/docs/storage-and-credentials.md#credential-health-proactive-liveness-checks).
194
+ - **[Decisions](https://github.com/zackbart/connecta/blob/main/docs/decisions.md)**
195
+ — what connecta refuses to be, which alternatives lost and why, and the
196
+ invariants a change must preserve.
197
+ - **[CHANGELOG](https://github.com/zackbart/connecta/blob/main/CHANGELOG.md)** —
198
+ what changed in each release.
199
+ - **[SECURITY](https://github.com/zackbart/connecta/blob/main/SECURITY.md)** —
200
+ supported versions and how to report a vulnerability.
@@ -9,9 +9,10 @@ export interface BearerTokenOptions extends ToolkitBindingOptions {
9
9
  * against `secret`. Checked BEFORE the Clerk gate in the server; a mismatch
10
10
  * falls through so a co-configured Clerk provider can still admit the request.
11
11
  *
12
- * `toolkits` binds the token to named toolkits (§16): one `bearerToken(...)` per
13
- * team credential, each naming the view that team may open. Omit it and the
14
- * token stays unbound — every declared toolkit plus the full registry.
12
+ * `toolkits` binds the token to named toolkits (docs/toolkits.md): one
13
+ * `bearerToken(...)` per team credential, each naming the view that team may
14
+ * open. Omit it and the token stays unbound — every declared toolkit plus the
15
+ * full registry.
15
16
  */
16
17
  export declare function bearerToken(secret: string, options?: BearerTokenOptions): InboundAuth;
17
18
  //# sourceMappingURL=bearer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bearer.d.ts","sourceRoot":"","sources":["../../src/auth/bearer.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,qBAAqB,EAC3B,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAc,WAAW,EAAE,MAAM,aAAa,CAAC;AAiB3D,MAAM,WAAW,kBAAmB,SAAQ,qBAAqB;IAC/D,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,kBAAuB,GAC/B,WAAW,CAiDb"}
1
+ {"version":3,"file":"bearer.d.ts","sourceRoot":"","sources":["../../src/auth/bearer.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,qBAAqB,EAC3B,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAc,WAAW,EAAE,MAAM,aAAa,CAAC;AAiB3D,MAAM,WAAW,kBAAmB,SAAQ,qBAAqB;IAC/D,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,kBAAuB,GAC/B,WAAW,CAkDb"}
@@ -19,9 +19,10 @@ function timingSafeEqual(a, b) {
19
19
  * against `secret`. Checked BEFORE the Clerk gate in the server; a mismatch
20
20
  * falls through so a co-configured Clerk provider can still admit the request.
21
21
  *
22
- * `toolkits` binds the token to named toolkits (§16): one `bearerToken(...)` per
23
- * team credential, each naming the view that team may open. Omit it and the
24
- * token stays unbound — every declared toolkit plus the full registry.
22
+ * `toolkits` binds the token to named toolkits (docs/toolkits.md): one
23
+ * `bearerToken(...)` per team credential, each naming the view that team may
24
+ * open. Omit it and the token stays unbound — every declared toolkit plus the
25
+ * full registry.
25
26
  */
26
27
  export function bearerToken(secret, options = {}) {
27
28
  const secretBytes = encoder.encode(secret);
@@ -30,11 +31,12 @@ export function bearerToken(secret, options = {}) {
30
31
  : "bearerToken", options);
31
32
  if (toolkitBinding && !options.subjectId) {
32
33
  // A bound token stands for one team, and both surfaces that report on it —
33
- // the 403 refusal log (§16) and activity events (§15) — can only say
34
- // "bearer" without a subjectId. With several bound tokens that makes an
35
- // operator unable to tell which credential was refused, or whose call
36
- // succeeded. console.warn (as the Clerk adapter does) because an adapter is
37
- // constructed before `createConnecta` has a logger to hand it.
34
+ // the 403 refusal log (docs/toolkits.md) and activity events
35
+ // (docs/operator-ui.md) — can only say "bearer" without a subjectId. With
36
+ // several bound tokens that makes an operator unable to tell which
37
+ // credential was refused, or whose call succeeded. console.warn (as the
38
+ // Clerk adapter does) because an adapter is constructed before
39
+ // `createConnecta` has a logger to hand it.
38
40
  console.warn("[connecta] bearerToken is bound to toolkits " +
39
41
  `(${toolkitBinding.toolkits.join(", ") || "unscoped only"}) but has no ` +
40
42
  "subjectId: refusal logs and activity events cannot say which " +
@@ -1 +1 @@
1
- {"version":3,"file":"bearer.js","sourceRoot":"","sources":["../../src/auth/bearer.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,GAEtB,MAAM,gBAAgB,CAAC;AAGxB,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;AAElC,qFAAqF;AACrF,SAAS,eAAe,CAAC,CAAa,EAAE,CAAa;IACnD,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;QAC1B,IAAI,CAAC,GAAG,CAAC,CAAC;QACV,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;QACvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;YAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAC3D,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACpD,OAAO,CAAC,KAAK,CAAC,CAAC;AACjB,CAAC;AAOD;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CACzB,MAAc,EACd,UAA8B,EAAE;IAEhC,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC3C,MAAM,cAAc,GAAG,qBAAqB,CAC1C,OAAO,CAAC,SAAS;QACf,CAAC,CAAC,2BAA2B,OAAO,CAAC,SAAS,IAAI;QAClD,CAAC,CAAC,aAAa,EACjB,OAAO,CACR,CAAC;IACF,IAAI,cAAc,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;QACzC,2EAA2E;QAC3E,qEAAqE;QACrE,wEAAwE;QACxE,sEAAsE;QACtE,4EAA4E;QAC5E,+DAA+D;QAC/D,OAAO,CAAC,IAAI,CACV,8CAA8C;YAC5C,IAAI,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,eAAe,eAAe;YACxE,+DAA+D;YAC/D,4DAA4D,CAC/D,CAAC;IACJ,CAAC;IACD,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7C,SAAS,CAAC,OAAO;YACf,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC;YAC1D,MAAM,KAAK,GAAG,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC9C,IAAI,KAAK,IAAI,eAAe,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,EAAE,CAAC;gBACpE,OAAO;oBACL,EAAE,EAAE,IAAI;oBACR,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBAC/D,CAAC;YACJ,CAAC;YACD,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,QAAQ,EAAE,IAAI,QAAQ,CACpB,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,EACzC;oBACE,MAAM,EAAE,GAAG;oBACX,OAAO,EAAE;wBACP,cAAc,EAAE,kBAAkB;wBAClC,kBAAkB,EAAE,QAAQ;qBAC7B;iBACF,CACF;aACF,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"bearer.js","sourceRoot":"","sources":["../../src/auth/bearer.ts"],"names":[],"mappings":"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"}
@@ -23,9 +23,9 @@ export interface ClerkAuthOptions extends ToolkitBindingOptions {
23
23
  gate?: (userId: string, clerk: ClerkClient) => boolean | Promise<boolean>;
24
24
  /** Advertised scopes in protected-resource metadata. */
25
25
  scopes?: string[];
26
- /** Optional hosted Account Portal sign-in URL for `/ui`. */
26
+ /** Optional hosted Account Portal sign-in URL for operator pages. Absolute https only. */
27
27
  signInUrl?: string;
28
- /** Optional hosted Account Portal sign-up URL for `/ui`. */
28
+ /** Optional hosted Account Portal sign-up URL for operator pages. Absolute https only. */
29
29
  signUpUrl?: string;
30
30
  }
31
31
  /**
@@ -34,11 +34,12 @@ export interface ClerkAuthOptions extends ToolkitBindingOptions {
34
34
  * `allowedDomains` and `gate` decide WHO is admitted (both must pass);
35
35
  * `toolkits` decides WHICH view the admitted user gets.
36
36
  *
37
- * `toolkits` binds every user this provider admits to those toolkits (§16). For
38
- * a per-team split, configure one `clerkAuth(...)` per team — the same keys, a
39
- * `gate` naming that team's users, and that team's `toolkits`. The server tries
40
- * providers in order and the first that admits the user supplies the binding, so
41
- * a user one gate rejects falls through to the next.
37
+ * `toolkits` binds every user this provider admits to those toolkits
38
+ * (docs/toolkits.md). For a per-team split, configure one `clerkAuth(...)` per
39
+ * team — the same keys, a `gate` naming that team's users, and that team's
40
+ * `toolkits`. The server tries providers in order and the first that admits the
41
+ * user supplies the binding, so a user one gate rejects falls through to the
42
+ * next.
42
43
  */
43
44
  export declare function clerkAuth(opts: ClerkAuthOptions): InboundAuth;
44
45
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"clerk.d.ts","sourceRoot":"","sources":["../../src/auth/clerk.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAEL,KAAK,qBAAqB,EAC3B,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAc,WAAW,EAAE,MAAM,aAAa,CAAC;AAE3D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAExD,MAAM,WAAW,gBAAiB,SAAQ,qBAAqB;IAC7D,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;OAUG;IACH,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,8EAA8E;IAC9E,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1E,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA0ID;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,gBAAgB,GAAG,WAAW,CA0O7D"}
1
+ {"version":3,"file":"clerk.d.ts","sourceRoot":"","sources":["../../src/auth/clerk.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAEL,KAAK,qBAAqB,EAC3B,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAc,WAAW,EAAE,MAAM,aAAa,CAAC;AAE3D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAExD,MAAM,WAAW,gBAAiB,SAAQ,qBAAqB;IAC7D,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;OAUG;IACH,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,8EAA8E;IAC9E,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1E,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,0FAA0F;IAC1F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0FAA0F;IAC1F,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA+ID;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,gBAAgB,GAAG,WAAW,CAuP7D"}