@zackbart/connecta 0.16.1 → 0.18.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 +180 -0
- package/README.md +4 -0
- package/dist/catalog-service.d.ts +10 -0
- package/dist/catalog-service.js +77 -5
- package/dist/catalog.js +114 -12
- package/dist/errors.d.ts +4 -6
- package/dist/execute.d.ts +7 -0
- package/dist/execute.js +262 -168
- package/dist/invocation.js +3 -1
- package/dist/meta-tools.d.ts +4 -0
- package/dist/meta-tools.js +55 -23
- package/dist/operator-ui/generated.d.ts +1 -1
- package/dist/operator-ui/generated.js +1 -1
- package/dist/operator-ui/model.d.ts +3 -1
- package/dist/providers/mixpanel.d.ts +3 -5
- package/dist/providers/mixpanel.js +73 -5
- package/dist/providers/stripe.d.ts +25 -24
- package/dist/providers/stripe.js +64 -35
- package/dist/registry.d.ts +32 -9
- package/dist/registry.js +217 -33
- package/dist/routes/mcp.js +6 -0
- package/dist/routes/ui.js +1 -1
- package/dist/skills.d.ts +5 -1
- package/dist/skills.js +206 -30
- package/dist/types.d.ts +14 -2
- package/dist/ui.js +4 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/documentation/architecture.md +8 -5
- package/documentation/code-mode.md +68 -68
- package/documentation/connector-guides.md +29 -27
- package/documentation/connectors.md +13 -1
- package/documentation/meta-tools.md +53 -19
- package/documentation/mixpanel.md +20 -0
- package/documentation/notion.md +17 -0
- package/documentation/operations.md +24 -21
- package/documentation/operator-ui.md +12 -2
- package/documentation/provider-audit.md +15 -7
- package/documentation/provider-conventions.md +26 -13
- package/documentation/stripe.md +66 -59
- package/documentation/upgrading.md +46 -4
- package/ethos.md +7 -7
- package/examples/worker/README.md +4 -3
- package/package.json +2 -2
- package/templates/node/README.md +7 -0
- package/templates/node/package.json +5 -2
|
@@ -79,14 +79,78 @@ const WRITE_TOOLS = new Map([
|
|
|
79
79
|
["Create-Feature-Flag", "additive"],
|
|
80
80
|
["Update-Feature-Flag", "destructive"],
|
|
81
81
|
]);
|
|
82
|
+
/** Live US hosted-MCP schemas reviewed read-only on 2026-08-13 (#395). */
|
|
83
|
+
const MIXPANEL_SCHEMA_DIGESTS = {
|
|
84
|
+
"Bulk-Edit-Events": "sha256:94512138df153de95436371f5a313e32b97faffebda3be6c0c69d09d1ff2b340",
|
|
85
|
+
"Bulk-Edit-Properties": "sha256:93481eb896ded45b623c678612e2156439efbaad5b4d660da1f2b087e7409ee3",
|
|
86
|
+
"Create-Cohort": "sha256:ea687f4bc607f8bfb5b1949e060239d6f7d629d3ec80fb0b72eae6cc6156ed03",
|
|
87
|
+
"Create-Custom-Property": "sha256:d22818b812f3fd0e785a5bbbee26cf099eaa911d5b6f383f94cf458a2ed26294",
|
|
88
|
+
"Create-Dashboard": "sha256:bd3b6e5134d27dafb04ccdf04d19e54dd23e6e2dc16989e418006e484268037b",
|
|
89
|
+
"Create-Experiment": "sha256:3307bd7202f5483adbc28a9ef1d562095d6942eb2c3a15308f458072c93e6888",
|
|
90
|
+
"Create-Feature-Flag": "sha256:3460d11d726727349cac62db5c19915ab589b7f1d8387042f0a3783356b252c4",
|
|
91
|
+
"Create-Lookup-Table": "sha256:c2fefa33a4f19fc65f394fecdc7126cab0ae874f7c97018cf003d8462a049e4c",
|
|
92
|
+
"Create-Metric": "sha256:315766d0c197d87bb44aedd16732f6e69fbfc93661d1fcfc177cadc1751f26ce",
|
|
93
|
+
"Create-Tag": "sha256:f99b6faad422aa6142d20d0aa4bdec1074e96a8ec45e35573e86d84b01df1d3b",
|
|
94
|
+
"Delete-Cohort": "sha256:e18c500459edd9c2b6a614a3f6c97b668786be9abf72929a0a50086bdadb1dae",
|
|
95
|
+
"Delete-Dashboard": "sha256:3a04594218b491743240e6970f677ed8ed132237d933efe30e97bdc41eb1ab6f",
|
|
96
|
+
"Delete-Tag": "sha256:5f6cc58ada5d2796f124e15883fe05061d03f9129414f4c8e10a0ec463f17807",
|
|
97
|
+
"Describe-Cohort-Schema": "sha256:775dbb8bb71ad3fa39ba35ca3a2683dfd88120f7af84a968531609c5a12de537",
|
|
98
|
+
"Dismiss-Duplicate-Group": "sha256:4e39c6f9bb83ed54020097f6cf34507a5288de2c1ce333456c84682bb5986bc4",
|
|
99
|
+
"Dismiss-Issues": "sha256:9c1f4901eca53f58d16feee126868d23c6ed1f5fad72344f86ea9965385b8644",
|
|
100
|
+
"Display-Query": "sha256:d0776167b8a20898c1ff580ca9517da8dea6b827c64e10b9fa01ae1a3c2db95f",
|
|
101
|
+
"Duplicate-Dashboard": "sha256:9738db7495d29034df966423df3c9d4b16ac3a8254c8473bf1e85a467fe9cf4e",
|
|
102
|
+
"Edit-Event": "sha256:28c47da0b56f57da0f11eb11435441a39ecd5175600f854442744c66a379ef93",
|
|
103
|
+
"Edit-Property": "sha256:11975587d2a566edc468db7cb24df70167d12068f30c1fe52c84f543cf4e2399",
|
|
104
|
+
"Explain-Experiment-Health-Check": "sha256:a50b1263247012dc78521bf6c1dd18584a7b08d46221a444b1ca49c81d3286e5",
|
|
105
|
+
"Find-Duplicate-Groups": "sha256:8f944cef9a147eab3c51bfcf1b873cef1409e5a6c21565d34e7ed20d23dcebb7",
|
|
106
|
+
"Get-Business-Context": "sha256:309f5ba864c90132061096b4f0ebc1e78544a6486bac3a45bd661d16bcab2b6c",
|
|
107
|
+
"Get-Cohort": "sha256:e18c500459edd9c2b6a614a3f6c97b668786be9abf72929a0a50086bdadb1dae",
|
|
108
|
+
"Get-Custom-Property": "sha256:d1cbce906cee66d422846c8ef1a745bbeac2c058ecad6b1ee8dcdd2120fa86be",
|
|
109
|
+
"Get-Dashboard": "sha256:56659fa3277723b75e24f3b4ca142ac9cd62120fb97e6c9252c221d00cdf8509",
|
|
110
|
+
"Get-Events": "sha256:d206fe30ab47d64bf6090bffdb4d119a80cfc2a35963bbe7fd52d56060090ded",
|
|
111
|
+
"Get-Experiment": "sha256:f9f04a2bb136809c754ea612963e1cdfb57c2c9ecc34a53ac6e1730f8758798f",
|
|
112
|
+
"Get-Experiment-Results-Interpretation-Guidance": "sha256:e517d9759f66f4a7ad15b0b67ffaabfb605e80949afcf41d007dfafd8f3e9574",
|
|
113
|
+
"Get-Experiment-Setup-Guidance": "sha256:e517d9759f66f4a7ad15b0b67ffaabfb605e80949afcf41d007dfafd8f3e9574",
|
|
114
|
+
"Get-Feature-Flag": "sha256:129de58b379ffba272bdbcee2b5759262e586dd415edc2067a69e9844d4d0877",
|
|
115
|
+
"Get-Feature-Flag-Lifecycle-Guidance": "sha256:e517d9759f66f4a7ad15b0b67ffaabfb605e80949afcf41d007dfafd8f3e9574",
|
|
116
|
+
"Get-Feature-Flag-Setup-Guidance": "sha256:e517d9759f66f4a7ad15b0b67ffaabfb605e80949afcf41d007dfafd8f3e9574",
|
|
117
|
+
"Get-Issues": "sha256:cf172ef18f37504a758c825c7bd4bc23fd98c3421655754dccd8e5ee2d700a10",
|
|
118
|
+
"Get-Lexicon-URL": "sha256:c6456d5c4a38ba069a2caa6cdac651be9d86d47bc6efb3316a893c7336d0e2bc",
|
|
119
|
+
"Get-Lookup-Table": "sha256:061602b283461f083bbd74348c264f802cb21c4fe6d961241c7090895a8334ac",
|
|
120
|
+
"Get-Metric": "sha256:eef10dd9ca25a63a63775565cbc4f2261b289dec526aa33df0f318eefbc96c46",
|
|
121
|
+
"Get-Projects": "sha256:d23d07a777441f04b128f08a2c30a6e8a1573d203f8a1ad7788bc1fd57a9cbbf",
|
|
122
|
+
"Get-Property-Values": "sha256:0cd487c9b92a187b21f456de3c785bb631aa30cba702785c9ff158608883a6bb",
|
|
123
|
+
"Get-Query-Schema": "sha256:8fea929d2ad4f8fed6c47116ff0eaa6f964b3ddd4685e482b68a8dac0231af73",
|
|
124
|
+
"Get-Report": "sha256:a99ba2af1ab57c1d5a606dbd7701968aa430ab23f5969f356a4c41f345dba041",
|
|
125
|
+
"Get-User-Replays-Data": "sha256:5df287735478a67489075b0c7c9d8c07097abe67408d06743c7fb9be43c6e024",
|
|
126
|
+
"List-Cohorts": "sha256:fd04778d60a027cfd777b40f36fbb037ba070661e149b2fce35a14865cada2db",
|
|
127
|
+
"List-Dashboards": "sha256:994c1c9fc87a4f1f00a677b856a44bad028252d283bd8e647ae157683fc89ea2",
|
|
128
|
+
"List-Experiments": "sha256:26a3f3e0b4e52135d74335dd769103303071fc48c15b1df40efd2dfa5a353848",
|
|
129
|
+
"List-Feature-Flags": "sha256:75fc1ff14f3d3faedb8e00c6563d151de397d584429764fd0c332f6a84f6993c",
|
|
130
|
+
"List-Metrics": "sha256:341710bebabb82112e80eb521d9d5cdb3bca024699b3aa795874d3549a315042",
|
|
131
|
+
"List-Organizations": "sha256:e4c23f123dde073e00038d92ebd53f45157c83a4d3a2ff686ab1b66c859f4a11",
|
|
132
|
+
"List-Properties": "sha256:52b38861df076119dfefe0128cf9819868336bf60e090f63c80da734877a69fe",
|
|
133
|
+
"Merge-Group": "sha256:a3b215a5be70305c2f02439513bee76ae3947da14e2a9e5b6ff0afb9ad3d4dcd",
|
|
134
|
+
"Rename-Tag": "sha256:a7e20e79ecd6ca7edca104fa1030e059ffae8962bf084d4a384c012ac9bbf087",
|
|
135
|
+
"Run-Experiment-Pre-Launch-Checks": "sha256:f6b5d85f75450b76fda9c7ef441f190fd45fcaeaff4cc3c30a6d1bee76e4c706",
|
|
136
|
+
"Run-Query": "sha256:0eb7d52343f6137275a02c2d7bb02dafdbfd25bd6f9067395eb689492d835466",
|
|
137
|
+
"Search-Entities": "sha256:86cfa1d3bf7f17a70ad07264d7b1d16c83480e40996e8d847911fe8bde13e35e",
|
|
138
|
+
"Search-Prior-Experiments": "sha256:847d1dcefaf6dc5e7ea967476f464a4d678a06b5e7d437dfb11ad4af2e56620f",
|
|
139
|
+
"Update-Business-Context": "sha256:0d21290053b6d532386c3c83d60cd78013a7109492c02ba2e7822716f2cde027",
|
|
140
|
+
"Update-Cohort": "sha256:ebe0d5afcc00e23eef55f079cd1816c851c2c647dff9565b7045f1f1615663f2",
|
|
141
|
+
"Update-Custom-Property": "sha256:781aaaab41c1ab5958062dc393d02b1df2ef2a09a28d3c4f21ae3177f4f53c86",
|
|
142
|
+
"Update-Dashboard": "sha256:2cc179ba75eda476ba7488f01503d947f023a4460aa98c4806ef0ab10c3b3ce8",
|
|
143
|
+
"Update-Experiment": "sha256:52ebf7595e48a40e218ff463ed72942a4818abc3ce93d8da6fafa8d358326437",
|
|
144
|
+
"Update-Feature-Flag": "sha256:9b34b19164168938d08a75d268c9becf8d189c85a1789a45061ae304041faf7c",
|
|
145
|
+
"Update-Lookup-Table": "sha256:ef28f1ec9c9484a7a53b5e2b6659e70f79a8e71e55bda17025aa4ab3c23b6a63",
|
|
146
|
+
"Update-Metric": "sha256:739bb6abdab19282afd4a6644a96183daabe9098a5322c44a77b840608a5ee9d",
|
|
147
|
+
};
|
|
82
148
|
/**
|
|
83
149
|
* The manifest this release reviewed: both lists in one place, which is what
|
|
84
150
|
* makes the classification the connector applies and the drift check that runs
|
|
85
|
-
* beside it the same fact (P13).
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
* them from a live project and prints the block to paste in
|
|
89
|
-
* ([#351](https://github.com/zackbart/connecta/issues/351)).
|
|
151
|
+
* beside it the same fact (P13). The 2026-08-13 read-only audit recorded all
|
|
152
|
+
* 63 live US schemas, so a later change is named by the maintainer-run drift
|
|
153
|
+
* check rather than rediscovered in production (#395).
|
|
90
154
|
*
|
|
91
155
|
* Exported because the maintainer-run check compares against this manifest and
|
|
92
156
|
* *names* what moved, which the runtime check deliberately cannot.
|
|
@@ -94,6 +158,7 @@ const WRITE_TOOLS = new Map([
|
|
|
94
158
|
export const MIXPANEL_VETTED_CATALOG = vettedCatalog({
|
|
95
159
|
reads: READ_ONLY_TOOLS,
|
|
96
160
|
writes: WRITE_TOOLS,
|
|
161
|
+
schemaDigests: MIXPANEL_SCHEMA_DIGESTS,
|
|
97
162
|
});
|
|
98
163
|
const REGION_COPY = {
|
|
99
164
|
us: "US",
|
|
@@ -116,6 +181,9 @@ Account purpose: ${purpose}
|
|
|
116
181
|
- Start with \`Get-Projects\`, then use \`Get-Business-Context\` for the selected project before interpreting its events or metrics.
|
|
117
182
|
- Resolve ids before acting; never guess one. \`Get-Projects\` yields the project id every other call is scoped by, and \`List-Dashboards\`, \`List-Cohorts\`, \`List-Metrics\`, \`List-Experiments\`, and \`List-Feature-Flags\` yield the ids their \`Get-\`, \`Update-\`, and \`Delete-\` counterparts expect.
|
|
118
183
|
- Discover names with \`Get-Events\`, \`List-Properties\`, and \`Get-Property-Values\`; do not guess event or property spelling.
|
|
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
|
+
- \`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
|
+
- \`List-Properties\` accepts \`names\` or \`query\`, never both. Use exact \`names\` for known properties and \`query\` for substring discovery.
|
|
119
187
|
- For a new analysis, fetch \`Get-Query-Schema\` before \`Run-Query\`. Reduce query results inside \`execute_code\` before returning them.
|
|
120
188
|
- Use \`Get-Report\` when the request names an existing saved report. Use \`Run-Query\` for a new question.
|
|
121
189
|
- 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.
|
|
@@ -1,37 +1,37 @@
|
|
|
1
1
|
import { type RemoteMcpAuth } from "../connectors/remote-mcp.js";
|
|
2
2
|
import type { Connector } from "../types.js";
|
|
3
|
-
/**
|
|
4
|
-
* Which Stripe environment this instance speaks to. Required, and deliberately
|
|
5
|
-
* undefaulted: there is no safe guess between an account that moves real money
|
|
6
|
-
* and one that does not.
|
|
7
|
-
*/
|
|
3
|
+
/** Which Stripe environment a static credential reaches. */
|
|
8
4
|
export type StripeMode = "production" | "sandbox";
|
|
9
|
-
/** Stripe publishes one hosted MCP endpoint
|
|
5
|
+
/** Stripe publishes one hosted MCP endpoint for every account and mode. */
|
|
10
6
|
export declare const STRIPE_MCP_ENDPOINT = "https://mcp.stripe.com/";
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Which Stripe environment this connector reaches. Shapes the title,
|
|
14
|
-
* description, guide, and admission budget, and is checked against a
|
|
15
|
-
* recognizable key prefix in `auth` headers.
|
|
16
|
-
*/
|
|
17
|
-
mode: StripeMode;
|
|
18
|
-
/** Human-readable display name; defaults to "Stripe (<mode>)". */
|
|
7
|
+
interface StripeCommonOptions {
|
|
8
|
+
/** Human-readable display name; defaults to "Stripe" for OAuth. */
|
|
19
9
|
title?: string;
|
|
20
|
-
/** Which business
|
|
10
|
+
/** Which business purpose and Stripe context this connector is for. */
|
|
21
11
|
purpose: string;
|
|
22
|
-
/**
|
|
23
|
-
auth?: RemoteMcpAuth;
|
|
24
|
-
/**
|
|
25
|
-
* Connect platform only: act as this connected account (`acct_...`) by
|
|
26
|
-
* sending Stripe's `Stripe-Account` header. Stripe does not support OAuth on
|
|
27
|
-
* connected-account calls, so this requires `headers` auth.
|
|
28
|
-
*/
|
|
29
|
-
connectedAccount?: string;
|
|
30
|
-
/** Account-specific conventions appended to the maintained provider guide. */
|
|
12
|
+
/** Connector-specific conventions appended to the maintained provider guide. */
|
|
31
13
|
instructions?: string;
|
|
32
14
|
/** Connector-specific inline result limit; omit to inherit the deployment. */
|
|
33
15
|
maxResultBytes?: number;
|
|
34
16
|
}
|
|
17
|
+
/** OAuth sessions discover account and mode together from Stripe's live tools. */
|
|
18
|
+
export interface StripeOAuthOptions extends StripeCommonOptions {
|
|
19
|
+
auth?: {
|
|
20
|
+
type: "oauth";
|
|
21
|
+
};
|
|
22
|
+
mode?: never;
|
|
23
|
+
connectedAccount?: never;
|
|
24
|
+
}
|
|
25
|
+
/** Static credentials have one fixed mode, including Stripe Connect calls. */
|
|
26
|
+
export interface StripeHeaderOptions extends StripeCommonOptions {
|
|
27
|
+
auth: Extract<RemoteMcpAuth, {
|
|
28
|
+
type: "headers";
|
|
29
|
+
}>;
|
|
30
|
+
mode: StripeMode;
|
|
31
|
+
/** Act as one Connect account by sending Stripe's `Stripe-Account` header. */
|
|
32
|
+
connectedAccount?: string;
|
|
33
|
+
}
|
|
34
|
+
export type StripeOptions = StripeOAuthOptions | StripeHeaderOptions;
|
|
35
35
|
/**
|
|
36
36
|
* The manifest this release reviewed: both lists in one place, which is what
|
|
37
37
|
* makes the classification the connector applies and the drift check that runs
|
|
@@ -47,3 +47,4 @@ export interface StripeOptions {
|
|
|
47
47
|
export declare const STRIPE_VETTED_CATALOG: import("../catalog-drift.js").VettedCatalog;
|
|
48
48
|
/** A maintained Stripe hosted-MCP connection. */
|
|
49
49
|
export declare function stripe(id: string, options: StripeOptions): Connector;
|
|
50
|
+
export {};
|
package/dist/providers/stripe.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { remoteMcp, } from "../connectors/remote-mcp.js";
|
|
2
2
|
import { vettedCatalog, withVettedCatalog } from "../catalog-drift.js";
|
|
3
|
-
/** Stripe publishes one hosted MCP endpoint
|
|
3
|
+
/** Stripe publishes one hosted MCP endpoint for every account and mode. */
|
|
4
4
|
export const STRIPE_MCP_ENDPOINT = "https://mcp.stripe.com/";
|
|
5
5
|
/**
|
|
6
6
|
* Stripe documents no MCP-specific rate limit, so this transcribes the account
|
|
@@ -89,9 +89,9 @@ const TEST_KEY = /\b(?:sk|rk|pk)_test_/;
|
|
|
89
89
|
* Refuse a deployment whose declared mode and supplied key disagree.
|
|
90
90
|
*
|
|
91
91
|
* This is the one half of production/sandbox routing connecta can actually
|
|
92
|
-
* enforce. Nothing here reads or reports key material: an unrecognizable
|
|
93
|
-
*
|
|
94
|
-
*
|
|
92
|
+
* enforce. Nothing here reads or reports key material: an unrecognizable key
|
|
93
|
+
* shape is left alone rather than guessed at, and a mismatch names only the
|
|
94
|
+
* two modes.
|
|
95
95
|
*/
|
|
96
96
|
function assertModeMatchesKey(id, mode, auth) {
|
|
97
97
|
if (auth.type !== "headers")
|
|
@@ -125,43 +125,64 @@ function resolveAuth(id, options) {
|
|
|
125
125
|
headers: { ...auth.headers, "Stripe-Account": connectedAccount },
|
|
126
126
|
};
|
|
127
127
|
}
|
|
128
|
+
const OAUTH_ADMISSION = STRIPE_ADMISSION.sandbox;
|
|
129
|
+
function oauthUsageGuide(purpose, instructions) {
|
|
130
|
+
const accountInstructions = instructions?.trim();
|
|
131
|
+
return `# Stripe usage
|
|
132
|
+
|
|
133
|
+
Scope: live and sandbox accounts. Connector purpose: ${purpose}
|
|
134
|
+
|
|
135
|
+
This OAuth session may expose both live and sandbox Stripe accounts. Call \`list_available_accounts_or_orgs\`, then carry its exact \`stripe_context\` and \`livemode\` into every account-scoped call. A live-mode write moves real money; a sandbox write changes test data. Never infer the account or mode from connector metadata.
|
|
136
|
+
|
|
137
|
+
- Call \`list_available_accounts_or_orgs\` before every account-scoped read or write. Select the intended result, then carry its \`stripe_context\` and \`livemode\` unchanged. If the account, mode, or supported selector is ambiguous, stop and ask; never guess.
|
|
138
|
+
- Organization accounts are not Stripe Connect connected accounts. A Connect call requires a separate connector with a deployment-configured restricted key plus Stripe's documented \`Stripe-Account\` header; OAuth does not support that path.
|
|
139
|
+
${sharedUsageGuide("100 requests per second in live mode and 25 in sandbox mode")}
|
|
140
|
+
${accountInstructions
|
|
141
|
+
? `\n## Account instructions\n\n${accountInstructions}\n`
|
|
142
|
+
: ""}`;
|
|
143
|
+
}
|
|
128
144
|
const MODE_COPY = {
|
|
129
145
|
production: {
|
|
130
146
|
title: "Stripe (production)",
|
|
131
147
|
blurb: "production — live money and real customers",
|
|
132
|
-
warning: "This is a PRODUCTION
|
|
148
|
+
warning: "This is a PRODUCTION Stripe connection. Every write moves real money against real customers, and a refund cannot be undone. If a request could plausibly be a rehearsal, route it to a sandbox connector instead.",
|
|
133
149
|
},
|
|
134
150
|
sandbox: {
|
|
135
151
|
title: "Stripe (sandbox)",
|
|
136
152
|
blurb: "sandbox — test data, no real money",
|
|
137
|
-
warning: "This is a SANDBOX
|
|
153
|
+
warning: "This is a SANDBOX Stripe connection. Nothing here is real money and none of these objects exist in production, so never answer a question about live revenue, payouts, or a named customer from this connector.",
|
|
138
154
|
},
|
|
139
155
|
};
|
|
140
|
-
function
|
|
156
|
+
function fixedModeUsageGuide(mode, purpose, instructions) {
|
|
141
157
|
const copy = MODE_COPY[mode];
|
|
142
158
|
const accountInstructions = instructions?.trim();
|
|
143
|
-
const rate = mode === "production" ? "100" : "25";
|
|
144
159
|
return `# Stripe usage
|
|
145
160
|
|
|
146
|
-
Mode: ${mode}.
|
|
161
|
+
Mode: ${mode}. Connector purpose: ${purpose}
|
|
147
162
|
|
|
148
163
|
${copy.warning}
|
|
149
164
|
|
|
165
|
+
- Organization accounts are not Stripe Connect connected accounts. A Connect call requires a deployment-configured restricted key plus Stripe's documented \`Stripe-Account\` header; OAuth does not support that path. Do not try to turn an organization-account call into a Connect call inside tool arguments.
|
|
166
|
+
${sharedUsageGuide(`${mode === "production" ? "100" : "25"} requests per second`)}
|
|
167
|
+
${accountInstructions
|
|
168
|
+
? `\n## Account instructions\n\n${accountInstructions}\n`
|
|
169
|
+
: ""}`;
|
|
170
|
+
}
|
|
171
|
+
function sharedUsageGuide(rate) {
|
|
172
|
+
return `
|
|
150
173
|
- Four generic tools reach any Stripe API method. Find the method with \`stripe_api_search\`, read its parameters with \`stripe_api_details\`, then call \`stripe_api_read\` (GET) or \`stripe_api_write\` (POST/PATCH/PUT/DELETE). Never guess a path or a parameter name — \`stripe_api_details\` is cheaper than a rejected write.
|
|
151
|
-
- Prefer a dedicated tool when one covers the task: \`get_stripe_account_info\` for
|
|
174
|
+
- Prefer a dedicated tool when one covers the task: \`get_stripe_account_info\` for account information, \`get_balance_summary\` for balances, \`create_refund\` for refunds, \`stripe_report\` for reports. One call instead of three, and a refund named \`create_refund\` reads far more clearly in the approval a human sees than the same refund buried in \`stripe_api_write\` arguments.
|
|
152
175
|
- \`stripe_api_write\` carries the blast radius of the entire write API — every POST, PATCH, PUT, and DELETE, from a customer edit to a subscription cancellation. State the method and path explicitly; expect approval on every call.
|
|
153
176
|
- Lists are cursor-paginated: \`limit\` defaults to 10 and caps at 100, \`starting_after\` and \`ending_before\` take an object id and are mutually exclusive, and \`has_more\` says whether to continue. Page inside \`execute_code\` and reduce before returning.
|
|
154
177
|
- Resolve ids before acting; never guess one. Stripe ids are typed prefixes — \`cus_\` customer, \`sub_\` subscription, \`ch_\` charge, \`pi_\` payment intent, \`in_\` invoice, \`acct_\` account — and a plausible-looking id belongs to a different object or to nobody. Find the object with \`stripe_api_search\` (or a list endpoint through \`stripe_api_read\`) and carry the \`id\` it returned into the write.
|
|
155
|
-
- This
|
|
178
|
+
- This connection's tool list is not a fixed set. Stripe gates parts of its MCP catalog by account, integration, and beta enrollment, so search this connector for what it actually exposes rather than assuming a documented tool is here.
|
|
156
179
|
- Amounts are integers in the currency's minor unit: \`1099\` is 10.99 USD, and zero-decimal currencies like JPY take \`10\` for 10 JPY. Never send a decimal.
|
|
157
180
|
- Send an \`Idempotency-Key\` on every write you might retry, if the tool accepts it, and reuse the same key for the retry. A retry with a fresh key is a second charge, not a second attempt.
|
|
158
|
-
- Stripe answers a rate limit with \`429\` and a \`Stripe-Rate-Limited-Reason\` header; back off on that rather than retrying immediately.
|
|
181
|
+
- Stripe answers a rate limit with \`429\` and a \`Stripe-Rate-Limited-Reason\` header; back off on that rather than retrying immediately. Stripe documents an account ceiling of ${rate}, and any single endpoint is capped at 25 per second regardless of mode, so paging one list is the real constraint.
|
|
159
182
|
- Use \`search_stripe_documentation\` when the shape of an object or a flow is unclear; it is a read and costs nothing but a call.
|
|
160
183
|
- Treat every create, update, delete, refund, and report run as a write. Connecta routes the maintained write catalog through \`call_destructive_tool\`; newly added tools also fail closed until classified.
|
|
161
184
|
- An \`auth_required\` failure means this connector's Stripe authorization is missing or expired: run \`authorize_connector\` for this connector id, then retry the same call unchanged. A rejected argument or a plan restriction comes back in Stripe's own words instead — read it rather than re-authorizing.
|
|
162
|
-
|
|
163
|
-
? `\n## Account instructions\n\n${accountInstructions}\n`
|
|
164
|
-
: ""}`;
|
|
185
|
+
`;
|
|
165
186
|
}
|
|
166
187
|
/** A maintained Stripe hosted-MCP connection. */
|
|
167
188
|
export function stripe(id, options) {
|
|
@@ -169,32 +190,40 @@ export function stripe(id, options) {
|
|
|
169
190
|
if (!purpose) {
|
|
170
191
|
throw new Error("stripe() requires a non-empty account purpose.");
|
|
171
192
|
}
|
|
172
|
-
const mode = options.mode;
|
|
173
|
-
if (mode !== "production" && mode !== "sandbox") {
|
|
174
|
-
throw new Error(`stripe("${id}") requires mode "production" or "sandbox".`);
|
|
175
|
-
}
|
|
176
193
|
const auth = resolveAuth(id, options);
|
|
177
|
-
|
|
178
|
-
|
|
194
|
+
const mode = "mode" in options ? options.mode : undefined;
|
|
195
|
+
if (auth.type === "oauth" && mode !== undefined) {
|
|
196
|
+
throw new Error(`stripe("${id}") cannot declare a connector-wide mode for OAuth; Stripe returns mode with each account.`);
|
|
197
|
+
}
|
|
198
|
+
if (auth.type === "headers" && mode !== "production" && mode !== "sandbox") {
|
|
199
|
+
throw new Error(`stripe("${id}") with headers auth requires mode "production" or "sandbox".`);
|
|
200
|
+
}
|
|
201
|
+
if (auth.type === "headers") {
|
|
202
|
+
assertModeMatchesKey(id, mode, auth);
|
|
203
|
+
}
|
|
204
|
+
const copy = mode === undefined ? undefined : MODE_COPY[mode];
|
|
179
205
|
const connector = remoteMcp(id, {
|
|
180
206
|
url: STRIPE_MCP_ENDPOINT,
|
|
181
|
-
title: options.title ?? copy
|
|
182
|
-
description:
|
|
207
|
+
title: options.title ?? copy?.title ?? "Stripe",
|
|
208
|
+
description: mode === undefined
|
|
209
|
+
? `Stripe payments (live and sandbox accounts) — ${purpose}`
|
|
210
|
+
: `Stripe payments (${copy?.blurb}) — ${purpose}`,
|
|
183
211
|
auth,
|
|
184
212
|
requireHttps: true,
|
|
185
|
-
callAdmission: STRIPE_ADMISSION[mode],
|
|
213
|
+
callAdmission: mode === undefined ? OAUTH_ADMISSION : STRIPE_ADMISSION[mode],
|
|
186
214
|
usageGuide: {
|
|
187
|
-
content:
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
//
|
|
191
|
-
//
|
|
192
|
-
summary: mode ===
|
|
193
|
-
? "
|
|
194
|
-
:
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
//
|
|
215
|
+
content: mode === undefined
|
|
216
|
+
? oauthUsageGuide(purpose, options.instructions)
|
|
217
|
+
: fixedModeUsageGuide(mode, purpose, options.instructions),
|
|
218
|
+
// Explicit rather than derived: fixed credentials must lead with mode,
|
|
219
|
+
// while OAuth must lead with its account-scoped selector pair.
|
|
220
|
+
summary: mode === undefined
|
|
221
|
+
? "Live and sandbox Stripe accounts. List accounts; carry the returned stripe_context and livemode before acting."
|
|
222
|
+
: mode === "production"
|
|
223
|
+
? "PRODUCTION: real money. This static credential has one fixed live-mode scope."
|
|
224
|
+
: "Sandbox: test data only. This static credential has one fixed sandbox scope.",
|
|
225
|
+
// Not `required`. The four generic tools are the routing decision; a
|
|
226
|
+
// guide forced into every call would pay for the same prose repeatedly.
|
|
198
227
|
},
|
|
199
228
|
...(options.maxResultBytes !== undefined
|
|
200
229
|
? { maxResultBytes: options.maxResultBytes }
|
package/dist/registry.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { CatalogDriftReport, Connector, ConnectorContext, ConnectorStatus, KVStorage, Logger, ToolDef } from "./types.js";
|
|
2
|
+
import { type DeferredWork } from "./connector-scope.js";
|
|
2
3
|
import { type CatalogDriftActivityContext } from "./activity.js";
|
|
3
4
|
import { type CredentialVault } from "./credentials.js";
|
|
4
5
|
import { type CallAdmissionPermit, type ConnectorCallAdmissionSnapshot } from "./call-admission.js";
|
|
@@ -70,6 +71,12 @@ export interface RegistryOptions {
|
|
|
70
71
|
catalogDriftActivity?: Omit<CatalogDriftActivityContext, "logger">;
|
|
71
72
|
}
|
|
72
73
|
export type ConnectorOperationOptions = Pick<ConnectorContext, "signal" | "timeoutMs">;
|
|
74
|
+
/** Agent-only catalog behavior. This never enters a ConnectorContext. */
|
|
75
|
+
export interface CatalogReadOptions {
|
|
76
|
+
defer?: DeferredWork;
|
|
77
|
+
/** Fresh deadline for a deferred refresh; never an inbound signal. */
|
|
78
|
+
refreshTimeoutMs: number;
|
|
79
|
+
}
|
|
73
80
|
/**
|
|
74
81
|
* The registry surface a per-connection MCP server consumes: every meta-tool
|
|
75
82
|
* (`src/meta-tools.ts`) and the `execute_code` sandbox bridge (`src/execute.ts`)
|
|
@@ -88,7 +95,7 @@ export interface RegistryView {
|
|
|
88
95
|
connector: Connector;
|
|
89
96
|
toolName: string;
|
|
90
97
|
} | null;
|
|
91
|
-
getTools(id: string, baseUrl: string, requestScope?: object, callOptions?: ConnectorOperationOptions): Promise<ToolDef[]>;
|
|
98
|
+
getTools(id: string, baseUrl: string, requestScope?: object, callOptions?: ConnectorOperationOptions, readOptions?: CatalogReadOptions): Promise<ToolDef[]>;
|
|
92
99
|
refreshTools(id: string, baseUrl: string, requestScope?: object, callOptions?: ConnectorOperationOptions): Promise<ToolDef[]>;
|
|
93
100
|
peekTools(id: string): ToolDef[] | undefined;
|
|
94
101
|
contextFor(id: string, baseUrl: string, requestScope?: object, callOptions?: ConnectorOperationOptions): ConnectorContext;
|
|
@@ -126,6 +133,10 @@ export declare class Registry implements RegistryView {
|
|
|
126
133
|
private readonly catalogMutations;
|
|
127
134
|
/** Same-request cold loads share one promise without retaining the request. */
|
|
128
135
|
private readonly requestCatalogLoads;
|
|
136
|
+
/** One live refresh per connector across agent and operator requests. */
|
|
137
|
+
private readonly catalogRefreshes;
|
|
138
|
+
/** Last payload-free agent catalog access in this runtime. */
|
|
139
|
+
private readonly catalogAccess;
|
|
129
140
|
/** Deployment-wide observations — every call, whatever view made it. */
|
|
130
141
|
private readonly health;
|
|
131
142
|
/** Last drift counts reported to activity, per connector, in this runtime. */
|
|
@@ -215,21 +226,33 @@ export declare class Registry implements RegistryView {
|
|
|
215
226
|
* the catalog and resurrect the pre-change listing.
|
|
216
227
|
*/
|
|
217
228
|
private enqueueCatalogMutation;
|
|
229
|
+
private refreshToolsWithContext;
|
|
230
|
+
/**
|
|
231
|
+
* Publish one shared refresh promise before starting its connector work.
|
|
232
|
+
* The first caller owns the scope and deadline; every later caller joins the
|
|
233
|
+
* result without gaining access to that context.
|
|
234
|
+
*/
|
|
235
|
+
private startCatalogRefresh;
|
|
218
236
|
/** Force a live listTools refresh and replace both catalog cache layers. */
|
|
219
237
|
refreshTools(id: string, baseUrl: string, requestScope?: object, callOptions?: ConnectorOperationOptions): Promise<ToolDef[]>;
|
|
238
|
+
private observeCatalogAccess;
|
|
239
|
+
/**
|
|
240
|
+
* Start or join one shared refresh. A newly deferred task owns its scope,
|
|
241
|
+
* deadline, and teardown; no inbound signal or request scope crosses into it.
|
|
242
|
+
*/
|
|
243
|
+
private deferCatalogRefresh;
|
|
220
244
|
/** Cached listTools with in-memory + persisted serializable catalog layers. */
|
|
221
245
|
private loadTools;
|
|
222
246
|
/**
|
|
223
|
-
* Coalesce one connector's
|
|
224
|
-
* neither roots the request scope nor lets its connector context
|
|
225
|
-
* another request; settled entries are also removed eagerly.
|
|
247
|
+
* Coalesce one connector's catalog traversal inside one inbound request. The
|
|
248
|
+
* WeakMap neither roots the request scope nor lets its connector context
|
|
249
|
+
* escape into another request; settled entries are also removed eagerly.
|
|
226
250
|
*
|
|
227
|
-
* The
|
|
228
|
-
*
|
|
229
|
-
*
|
|
230
|
-
* the deal being made — one fetch, one deadline.
|
|
251
|
+
* The deployment-wide flight below this layer coalesces the actual live
|
|
252
|
+
* refresh across requests. Its first caller's context and deadline govern;
|
|
253
|
+
* later callers join only its result, never its request scope.
|
|
231
254
|
*/
|
|
232
|
-
getTools(id: string, baseUrl: string, requestScope?: object, callOptions?: ConnectorOperationOptions): Promise<ToolDef[]>;
|
|
255
|
+
getTools(id: string, baseUrl: string, requestScope?: object, callOptions?: ConnectorOperationOptions, readOptions?: CatalogReadOptions): Promise<ToolDef[]>;
|
|
233
256
|
/** Return a cached catalog without performing storage or network I/O. */
|
|
234
257
|
peekTools(id: string): ToolDef[] | undefined;
|
|
235
258
|
recordSuccess(id: string, latencyMs: number): void;
|