@zackbart/connecta 0.18.0 → 0.18.1

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 CHANGED
@@ -2,6 +2,61 @@
2
2
 
3
3
  All notable changes to this package are documented here.
4
4
 
5
+ ## 0.18.1 — 2026-08-18
6
+
7
+ This patch is the response to one long investigation run against a live
8
+ deployment: a Mixpanel-and-Stripe user-journey reconstruction that rated the
9
+ connectors trustworthy and the ceremony too high. Nothing breaks and no
10
+ constructor changes. The two maintained guides now say the things that
11
+ investigation had to discover the hard way — which questions Insights cannot
12
+ answer, when Mixpanel's `false` is an absent property, which Stripe reads must
13
+ be projected inside the sandbox and why that is a privacy boundary as much as
14
+ a size one, and which fields Stripe search will not filter on. Beside them, a
15
+ new maintained RevenueCat connection lands, with the fact that decides its
16
+ deployment shape stated up front: a RevenueCat secret key reaches exactly one
17
+ project, so several projects are several connectors. A deployment that
18
+ constructs none of the three connections can ignore this release entirely.
19
+
20
+ ### Added
21
+
22
+ - **`revenuecat()` — a maintained RevenueCat hosted-MCP connection** at
23
+ `@zackbart/connecta/providers/revenuecat`. OAuth by default (account-scoped:
24
+ the guide requires `list-projects` first and carries `project_id` into every
25
+ project-scoped call, stopping on ambiguity); an API v2 secret key as the
26
+ headless alternative, which binds the connector to one project — the guide's
27
+ first line names it, and a second project is a second connector with its own
28
+ key. All 95 documented tools are classified from RevenueCat's tools reference
29
+ (50 read-only, 15 additive, 29 destructive); `render-paywall-screenshot`
30
+ carries no access column there and fails closed. Borderline verdicts are
31
+ argued beside the rows they decide: `create-webhook-integration`,
32
+ `grant-customer-entitlement`, and `assign-customer-offering` are destructive
33
+ on consequence, not on verb. RevenueCat publishes six per-domain rate limits
34
+ and one admission rule cannot honestly cover 95 tools, so `callAdmission`
35
+ stays with the operator and the guide states the numbers. The maintainer-run
36
+ drift check accepts `revenuecat` behind `CONNECTA_DRIFT_REVENUECAT_KEY`; no
37
+ schema digests are recorded until a maintainer runs `--record` against a live
38
+ project (#433).
39
+
40
+ ### Changed
41
+
42
+ - **The Mixpanel guide says what Insights cannot answer.** One analysis is one
43
+ `execute_code` program with one `Get-Query-Schema` fetch; per-user event
44
+ timelines and sequence questions are out of reach through `Run-Query`
45
+ (`Get-User-Replays-Data` covers one user only where session replay is on);
46
+ `false` on a boolean property may be an absent one and must be confirmed with
47
+ `List-Properties` before it becomes a signal; breakdown responses are
48
+ flattened one row per combination inside the program with `$overall`
49
+ dropped. Convention P7 gains the rendering-rule clause this rests on (#430).
50
+
51
+ - **The Stripe guide names the reads that must be projected and the fields
52
+ search cannot filter.** Any `stripe_api_read` list or `stripe_api_search`
53
+ that returns full objects belongs inside `execute_code`, projected before
54
+ `return` — the reduction keeps customer PII out of the transcript, not only
55
+ bytes. Charges search takes a documented field set with no `payment_intent`;
56
+ follow the PaymentIntent's `latest_charge` instead. The account → search →
57
+ details → read sequence is one program, and decline outcomes are `outcome`,
58
+ `failure_code`, `failure_message` on the charge (#431).
59
+
5
60
  ## 0.18.0 — 2026-08-13
6
61
 
7
62
  This minor release spends fewer tokens before the first call and answers
package/README.md CHANGED
@@ -2,133 +2,94 @@
2
2
 
3
3
  ![A monochrome clay Connecta hub joining many tools](https://raw.githubusercontent.com/zackbart/connecta/main/assets/connecta-clay-hero.png)
4
4
 
5
- One place for AI agents to connect to the tools you choose.
5
+ One MCP endpoint. The integrations you chose. Your agent reaches them by
6
+ writing code instead of loading a thousand tool definitions.
6
7
 
7
- Connecta gives an agent a single MCP endpoint instead of making it connect to
8
- every service separately. You decide which integrations are available and
9
- Connecta holds their credentials, and the agent mostly works by writing
10
- ordinary JavaScript that Connecta runs in a sandbox next to them — with a few
11
- explicit tools for the jobs a program is the wrong shape for, destructive calls
12
- among them.
8
+ ## The mental model
13
9
 
14
- ```mermaid
15
- flowchart LR
16
- Agent["AI agent"]
17
- Integrations["The integrations you chose"]
18
-
19
- subgraph Connecta["Connecta: one MCP endpoint; credentials stay here"]
20
- Sandbox["execute_code<br/>server-side sandbox"]
21
- Explicit["Explicit tools<br/>destructive calls, search, auth"]
22
- end
23
-
24
- Agent -->|"writes a program"| Sandbox
25
- Agent -->|"one deliberate call"| Explicit
26
- Sandbox --> Integrations
27
- Explicit --> Integrations
28
- ```
10
+ You ask your agent a question that touches a service — Linear, Stripe, an
11
+ internal API, anything you have connected. Here is what happens:
29
12
 
30
- ## Why Connecta
13
+ 1. The agent talks to one endpoint, yours, and sees seven tools. Always seven,
14
+ no matter how many services sit behind it.
15
+ 2. It writes a short JavaScript program. Connecta runs it in a sandbox next to
16
+ your integrations. The program can search for tools, call them, chain the
17
+ calls, and shape the result.
18
+ 3. Only the answer comes back into the agent's context — not raw pages of
19
+ API output.
20
+ 4. If the agent wants to change something — create, update, delete — it
21
+ cannot do that from a program. It makes one explicit call, and your MCP
22
+ client can put that call in front of you first.
31
23
 
32
- - **One connection.** Configure clients once, even as integrations change.
33
- - **Seven tools, not seven hundred.** A program can search the catalog, chain
34
- calls, and trim the results before the agent ever sees them — so nothing has
35
- to be loaded up front.
36
- - **Safer access.** Credentials stay server-side — the program never sees them
37
- — and consequential actions remain explicit and individual.
38
- - **Named client access.** A Clerk operator can issue and revoke one-time,
39
- hashed Bearer tokens for MCP clients that support header authentication.
40
- - **Your deployment.** Connecta runs on Node, Docker, or Cloudflare Workers,
41
- with configuration you can review and version.
24
+ Credentials never leave the server. The program never sees them, and neither
25
+ does the agent.
42
26
 
43
- ## Start here
27
+ ```mermaid
28
+ flowchart TB
29
+ Client["Your MCP client<br/>Claude, Cursor, …"]
44
30
 
45
- Create the prescribed Node deployment:
31
+ subgraph Connecta["Connecta one endpoint, seven tools, your credentials"]
32
+ Sandbox["execute_code<br/>the agent's program runs here<br/>read-only tools only"]
33
+ Explicit["call_destructive_tool<br/>one visible call per write<br/>your client can ask you first"]
34
+ end
46
35
 
47
- ```sh
48
- npx @zackbart/connecta init my-connecta
49
- cd my-connecta
50
- npm install
51
- CONNECTA_TOKEN=dev-token npm start
52
- ```
36
+ Integrations["The integrations you chose<br/>Linear · Stripe · Notion · your HTTP API · any MCP server"]
53
37
 
54
- Point an MCP client at `http://localhost:8787/mcp` with
55
- `Authorization: Bearer dev-token`. The generated project is deliberately small:
56
-
57
- ```text
58
- my-connecta/
59
- ├── src/index.ts # connectors, auth, storage, public URL
60
- ├── src/file-activity.ts # deployment-owned activity store, wired on request
61
- ├── package.json # exact Connecta and QuickJS versions
62
- ├── tsconfig.json
63
- ├── Dockerfile # the same source, containerized
64
- ├── docker-compose.yml # one service, state on a named volume
65
- ├── .dockerignore
66
- ├── .env.example
67
- ├── .gitignore
68
- ├── AGENTS.md
69
- ├── CLAUDE.md -> AGENTS.md
70
- └── README.md
38
+ Client -->|"one connection"| Sandbox
39
+ Client --> Explicit
40
+ Sandbox -->|"reads"| Integrations
41
+ Explicit -->|"writes"| Integrations
71
42
  ```
72
43
 
73
- The same project runs as a long-lived container without changing a line of it:
74
-
75
- ```sh
76
- cp .env.example .env # set CONNECTA_TOKEN
77
- docker compose up -d --build
44
+ This is the kind of thing the agent writes, not you:
45
+
46
+ ```js
47
+ async () => {
48
+ const { nodes } = await tracker.list_issues({ state: "started" });
49
+ const byOwner = {};
50
+ for (const issue of nodes) {
51
+ (byOwner[issue.assignee?.name ?? "unassigned"] ??= []).push(issue.identifier);
52
+ }
53
+ return byOwner;
54
+ }
78
55
  ```
79
56
 
80
- For an agent setting this up, the contract is:
81
-
82
- 1. Edit `src/index.ts`; do not copy Connecta internals into the deployment.
83
- 2. Keep the required `executor: quickJsExecutor()` configuration; without an
84
- executor the deployment refuses to boot.
85
- 3. Keep secrets in environment variables or a secret store, never source.
86
- 4. Add connectors explicitly: import a maintained prebuilt provider
87
- constructor when one exists, otherwise write a deliberate `remoteMcp()` or
88
- `api()` connector. There is no registry to browse and nothing registers
89
- itself.
90
- 5. Run `npm run typecheck`, start the server, and run
91
- `CONNECTA_TOKEN=... npm run doctor`. Doctor checks health, the executor, and
92
- the exact seven-tool model-facing surface, then executes a harmless sandbox
93
- program. The bearer stays in the environment rather than command history.
94
-
95
- The operator surface is the same in both shapes and off until you say so:
96
- Clerk sign-in, the credential vault, access-token issuance, and payload-free
97
- activity ship as commented configuration, each one a variable and an
98
- uncommented block away. The generated `README.md` walks through all four, and
99
- the [Worker example](./examples/worker/) does the same for KV and D1.
100
-
101
- Already have a deployment on an older version? `init` deliberately refuses to
102
- merge into it, so bringing one current is its own procedure:
103
- [Upgrading an existing deployment](./documentation/upgrading.md) is the
104
- runbook, written for the agent working inside that project.
105
-
106
- The template refuses to merge into an existing directory, so initialization
107
- cannot overwrite another project. Its generated programs have no filesystem,
108
- environment, arbitrary network, imports, or timers; only explicitly read-only
109
- connector tools are reachable. Unannotated or write-capable calls stay
110
- individual and cross `call_destructive_tool`, where the MCP host can ask the
111
- operator for approval.
112
-
113
- The Node template also pins its one approved dependency install script:
114
- esbuild, which `tsx` needs to run the deployment source. A dependency update
115
- that adds or changes an install script fails the package smoke until reviewed.
116
-
117
- There are two deployment shapes and no others:
118
-
119
- - [Node, local or Docker](./templates/node/) — what `init` copies
120
- - [Cloudflare Worker deployment](./examples/worker/)
121
- - [Subsystem documentation](./documentation/)
122
-
123
- Every deployment configures a sandbox: QuickJS on Node or a Dynamic Worker on
124
- Cloudflare. Construction fails with an actionable error when the executor is
125
- missing, so the model-facing interface is always the same seven tools.
126
-
127
- ## Project status
128
-
129
- Connecta is built for its author's deployments first and is still evolving.
130
- Breaking changes are expected before 1.0.
131
-
132
- Read the [ethos](./ethos.md) for the product's principles, the
133
- [changelog](./CHANGELOG.md) for releases, and [security policy](./SECURITY.md)
134
- for vulnerability reporting.
57
+ Fifty issues in, one small object out. Your context window notices.
58
+
59
+ ## What you can do with it
60
+
61
+ - **Put every MCP server you use behind one connection.** Add or remove
62
+ services in a config file; your client never changes.
63
+ - **Wrap any HTTP API by hand.** A few lines per tool. No OpenAPI conversion —
64
+ generated tool sprawl is the problem, not the fix.
65
+ - **Use maintained connections** for Cloudflare, Linear, Mixpanel, Notion,
66
+ RevenueCat, and Stripe — known endpoints, auth defaults, and vetted read/write
67
+ classifications, imported one at a time.
68
+ - **Let the agent work in code.** Search, chain, filter, join, and reduce
69
+ inside the sandbox instead of round-tripping every call through the model.
70
+ - **Keep writes deliberate.** Only tools marked read-only run in a program.
71
+ Everything else is a separate, visible call your client can gate.
72
+ - **Run it where you like.** Node, a Docker container, or a Cloudflare Worker,
73
+ from the same small deployment file.
74
+
75
+ There is also an operator surface, off until you turn it on: sign-in, an
76
+ encrypted credential vault with rotation, revocable per-client tokens, and a
77
+ payload-free activity log.
78
+
79
+ Connecta is not a platform, a marketplace, a policy engine, or a multi-tenant
80
+ service. Those are decisions, and the [ethos](./ethos.md) records each one
81
+ and why.
82
+
83
+ ## Getting started
84
+
85
+ Setup is written for an agent. Point yours at [`AGENTS.md`](./AGENTS.md) and
86
+ ask it to set up a Connecta deployment; the
87
+ [documentation](./documentation/) covers every subsystem if you want to go
88
+ deeper, and [upgrading](./documentation/upgrading.md) an existing deployment
89
+ is its own runbook.
90
+
91
+ ## Status
92
+
93
+ Built for its author's deployments first and published openly. Breaking
94
+ changes are expected before 1.0. See the [changelog](./CHANGELOG.md) and
95
+ [security policy](./SECURITY.md).
@@ -184,7 +184,10 @@ Account purpose: ${purpose}
184
184
  - \`Get-Business-Context\` requires either \`project_id\` or \`organization_id\`. Its schema marks both optional, but the hosted tool rejects a call with neither.
185
185
  - \`Get-Property-Values\` requires \`properties\` or the deprecated \`property\` alias. Event property values also require \`event\`; prefer \`properties\` and never send both property forms with conflicting values.
186
186
  - \`List-Properties\` accepts \`names\` or \`query\`, never both. Use exact \`names\` for known properties and \`query\` for substring discovery.
187
- - For a new analysis, fetch \`Get-Query-Schema\` before \`Run-Query\`. Reduce query results inside \`execute_code\` before returning them.
187
+ - One analysis is one \`execute_code\` program: fetch \`Get-Query-Schema\` once, run every \`Run-Query\` of the analysis in that program, and return the reduced table. The schema is tens of kilobytes and the same for every report type, so re-fetching it per query buys nothing. Never return raw \`Run-Query\` output.
188
+ - Insights, funnels, and retention answer aggregate questions. A per-user ordered event timeline, or a sequence question such as "event A with no later event B", is not answerable with \`Run-Query\` in a reasonable number of calls, and this hosted catalog has no per-\`distinct_id\` event timeline — \`Get-User-Replays-Data\` covers one user's replays with their events only where session replay is enabled and present. If the deployment exposes a Mixpanel export or activity-feed connector, use that; if it does not, tell the user the question is out of reach here rather than approximating it with hourly buckets and hundreds of empty rows.
189
+ - \`false\` on a boolean property may be an absent property: Mixpanel renders a missing value as \`false\` in boolean breakdowns, and server-imported events often lack client-side properties entirely. Confirm the property is present with \`List-Properties\` or \`Get-Property-Values\` before treating \`false\` as a signal, and say when a conclusion rests on that ambiguity.
190
+ - Breakdown responses nest \`$overall\` and per-segment series objects. Flatten to one row per complete breakdown combination inside \`execute_code\` before returning, and drop \`$overall\` unless the question asks for the total.
188
191
  - Use \`Get-Report\` when the request names an existing saved report. Use \`Run-Query\` for a new question.
189
192
  - This account's tool list is not a fixed set. Mixpanel gates parts of its MCP catalog by plan and beta enrollment — experiments, feature flags, session replay, and issue triage are the usual absentees — so search this connector for what it actually exposes rather than assuming a documented tool is here.
190
193
  - Mixpanel meters MCP traffic per user per hour, shared with everything else that credential does. Reuse discovery results within a run and avoid speculative fan-out.
@@ -0,0 +1,77 @@
1
+ import { type RemoteMcpAuth } from "../connectors/remote-mcp.js";
2
+ import type { Connector, ConnectorCallAdmissionPolicy } from "../types.js";
3
+ /** RevenueCat publishes one hosted MCP endpoint, streamable HTTP. */
4
+ export declare const REVENUECAT_MCP_ENDPOINT = "https://mcp.revenuecat.ai/mcp";
5
+ export interface RevenueCatOptions {
6
+ /**
7
+ * Human-readable display name; defaults to "RevenueCat" for OAuth and
8
+ * "RevenueCat (single project)" for a static API v2 secret key. The scope
9
+ * shape rides the title because it is the one routing fact connecta can
10
+ * know at construction: an `sk_` key reaches exactly one project, an OAuth
11
+ * session reaches every project the account can. *Which* project a key
12
+ * reaches is not knowable here (P10 — no credential test), so the guide's
13
+ * first line carries the operator's stated purpose instead.
14
+ */
15
+ title?: string;
16
+ /**
17
+ * Which project this connector is for and what decisions it answers. With
18
+ * headers auth this is the only place the project a key reaches is named,
19
+ * so it goes in the guide's first line and its summary.
20
+ */
21
+ purpose: string;
22
+ /**
23
+ * OAuth by default; static headers support a RevenueCat API v2 secret key
24
+ * as `Authorization: Bearer sk_…`.
25
+ */
26
+ auth?: RemoteMcpAuth;
27
+ /** Project-specific conventions appended to the maintained provider guide. */
28
+ instructions?: string;
29
+ /** Connector-specific inline result limit; omit to inherit the deployment. */
30
+ maxResultBytes?: number;
31
+ /**
32
+ * Optional per-runtime call-admission policy. Deliberately not defaulted,
33
+ * even though RevenueCat does publish numbers.
34
+ *
35
+ * API v2 meters per *domain*, and the domains disagree by a factor of
36
+ * nineteen: Customer Information 480/min, Virtual Currencies 480/min,
37
+ * Subscription Transactions Refunds 480/min, Audiences 60/min, Project
38
+ * Configuration 60/min, Charts & Metrics 25/min
39
+ * (https://www.revenuecat.com/docs/api-v2#tag/Rate-Limit, read 2026-08-18).
40
+ * A `ConnectorCallAdmissionPolicy` carries exactly one rule, so a
41
+ * connector-wide budget has to pick one of those six numbers for all ninety-
42
+ * five tools. Transcribing 25 would throttle a customer read loop to a
43
+ * nineteenth of its documented allowance; transcribing 480 would leave a
44
+ * chart sweep unprotected. Neither is the provider's limit, and both would
45
+ * look like RevenueCat being flaky.
46
+ *
47
+ * The metering scope says the same thing again: the limit applies per API
48
+ * key for app-level keys and per *developer* for developer-level keys, so
49
+ * an OAuth session shares one budget with everything else that developer
50
+ * does — which a per-runtime counter cannot approximate in either
51
+ * direction. So the number stays with the operator who knows the account,
52
+ * exactly as P12 prescribes; `documentation/revenuecat.md` shows how to
53
+ * supply one.
54
+ */
55
+ callAdmission?: ConnectorCallAdmissionPolicy;
56
+ }
57
+ /**
58
+ * The manifest this release reviewed: both lists in one place, which is what
59
+ * makes the classification the connector applies and the drift check that runs
60
+ * beside it the same fact (P13). Ninety-four of the ninety-five tools
61
+ * RevenueCat's reference lists on 2026-08-18 are classified; the ninety-fifth,
62
+ * `render-paywall-screenshot`, has no access column to classify from and fails
63
+ * closed.
64
+ *
65
+ * No schema digests. No release has read RevenueCat's live schemas and written
66
+ * them down — that needs a live project and a maintainer's own `sk_` key — and
67
+ * an invented digest would report a change that never happened.
68
+ * `npm run drift:check -- --record` reads them from a live catalog and prints
69
+ * the block to paste in
70
+ * ([#351](https://github.com/zackbart/connecta/issues/351)).
71
+ *
72
+ * Exported because the maintainer-run check compares against this manifest and
73
+ * *names* what moved, which the runtime check deliberately cannot.
74
+ */
75
+ export declare const REVENUECAT_VETTED_CATALOG: import("../catalog-drift.js").VettedCatalog;
76
+ /** A maintained RevenueCat hosted-MCP connection. */
77
+ export declare function revenuecat(id: string, options: RevenueCatOptions): Connector;