@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 +55 -0
- package/README.md +79 -118
- package/dist/providers/mixpanel.js +4 -1
- package/dist/providers/revenuecat.d.ts +77 -0
- package/dist/providers/revenuecat.js +314 -0
- package/dist/providers/stripe.js +5 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/documentation/connectors.md +1 -0
- package/documentation/operations.md +1 -0
- package/documentation/provider-audit.md +32 -2
- package/documentation/provider-conventions.md +24 -15
- package/documentation/revenuecat.md +279 -0
- package/documentation/stripe.md +10 -0
- package/documentation/upgrading.md +14 -4
- package/package.json +5 -1
- package/templates/node/package.json +1 -1
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
|

|
|
4
4
|
|
|
5
|
-
One
|
|
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
|
-
|
|
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
|
-
|
|
15
|
-
|
|
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
|
-
|
|
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
|
-
|
|
33
|
-
|
|
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
|
-
|
|
27
|
+
```mermaid
|
|
28
|
+
flowchart TB
|
|
29
|
+
Client["Your MCP client<br/>Claude, Cursor, …"]
|
|
44
30
|
|
|
45
|
-
|
|
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
|
-
|
|
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
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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
|
-
|
|
74
|
-
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
|
|
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
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
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
|
-
-
|
|
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;
|