@zackbart/connecta 0.22.1 → 0.22.3
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/AGENTS.md +6 -5
- package/CHANGELOG.md +59 -0
- package/README.md +4 -2
- package/dist/auth/downstream-oauth.d.ts +3 -1
- package/dist/auth/downstream-oauth.js +11 -0
- package/dist/catalog-drift.d.ts +3 -3
- package/dist/providers/cloudflare.d.ts +30 -9
- package/dist/providers/cloudflare.js +75 -9
- package/dist/providers/notion.d.ts +28 -7
- package/dist/providers/notion.js +106 -9
- package/dist/providers/revenuecat.js +10 -0
- package/dist/providers/stripe.js +7 -0
- package/dist/providers/vercel.d.ts +29 -10
- package/dist/providers/vercel.js +118 -11
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/documentation/cloudflare.md +51 -11
- package/documentation/connectors.md +23 -5
- package/documentation/linear.md +9 -0
- package/documentation/mixpanel.md +13 -3
- package/documentation/notion.md +49 -12
- package/documentation/operations.md +12 -7
- package/documentation/provider-conventions.md +61 -47
- package/documentation/revenuecat.md +14 -10
- package/documentation/stripe.md +7 -0
- package/documentation/upgrading.md +5 -5
- package/documentation/vercel.md +70 -23
- package/package.json +2 -1
- package/templates/node/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -122,11 +122,12 @@ dead, and neither is a state to leave the repository in.
|
|
|
122
122
|
- **CHANGELOG.** Each release opens with a narrative paragraph — what this
|
|
123
123
|
release is, what breaks, what a deployment can ignore — then
|
|
124
124
|
`### Added` / `### Changed` / `### Fixed`.
|
|
125
|
-
- **Provider drift.**
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
125
|
+
- **Provider drift.** Run `npm run providers:check` for the credential-free
|
|
126
|
+
public check across every maintained provider. It covers official MCP
|
|
127
|
+
documentation and OpenAPI contracts and never reads a provider credential.
|
|
128
|
+
Remote MCP schemas remain owned by the live `tools/list` response rather than
|
|
129
|
+
a vendored copy. Findings are read by a human and become GitHub issues;
|
|
130
|
+
nothing files itself.
|
|
130
131
|
See
|
|
131
132
|
[`documentation/provider-conventions.md`](./documentation/provider-conventions.md#the-maintainer-run-drift-check).
|
|
132
133
|
- **Releases.** `npm run release:check`, tag `v<version>` matching
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,65 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this package are documented here.
|
|
4
4
|
|
|
5
|
+
## 0.22.3 — 2026-09-03
|
|
6
|
+
|
|
7
|
+
This patch carries OAuth discovery across the browser redirect. It matters for
|
|
8
|
+
downstream MCP servers whose authentication challenge names a protected-resource
|
|
9
|
+
metadata URL outside the RFC 9728 default path, including Cloudflare Access
|
|
10
|
+
Managed OAuth. Existing grants and connectors using the default path require no
|
|
11
|
+
configuration or storage migration.
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- **Non-default OAuth discovery survives callbacks.** The KV OAuth provider now
|
|
16
|
+
persists the SDK's discovery state in the authorization generation, restores
|
|
17
|
+
it in the callback's fresh request scope, and deletes it through discovery,
|
|
18
|
+
all-credential, and generation cleanup. A callback therefore exchanges its
|
|
19
|
+
code against the same validated authorization-server issuer that registered
|
|
20
|
+
the client instead of invalidating that client after rediscovery (#523).
|
|
21
|
+
|
|
22
|
+
## 0.22.2 — 2026-09-01
|
|
23
|
+
|
|
24
|
+
This patch makes the maintained-provider release check credential-free and
|
|
25
|
+
adds explicit official-MCP alternatives beside the existing Cloudflare,
|
|
26
|
+
Notion, and Vercel API connections. Existing declarations still select the
|
|
27
|
+
hand-written API interface by default. Linear, Mixpanel, RevenueCat, and Stripe
|
|
28
|
+
remain MCP-only, and deployments that do not select a new interface need no
|
|
29
|
+
configuration or credential change.
|
|
30
|
+
|
|
31
|
+
### Added
|
|
32
|
+
|
|
33
|
+
- **Selectable API and MCP interfaces.** Cloudflare, Notion, and Vercel accept
|
|
34
|
+
`surface: "mcp"` for their official hosted server while preserving the API
|
|
35
|
+
default. Each MCP wrapper supplies release-reviewed safety classifications,
|
|
36
|
+
keeps unknown tools fail-closed, and leaves provider descriptions and input
|
|
37
|
+
and output schemas untouched.
|
|
38
|
+
- **Credential-free provider validation.** `npm run providers:check` compares
|
|
39
|
+
every maintained provider with official public evidence: touched OpenAPI
|
|
40
|
+
operations for the three hand-written interfaces, and endpoint, OAuth, and
|
|
41
|
+
documented tool inventories for the seven hosted interfaces. It reads no
|
|
42
|
+
provider credential and generates no runtime tool.
|
|
43
|
+
|
|
44
|
+
### Changed
|
|
45
|
+
|
|
46
|
+
- **Public evidence replaces authenticated drift setup.** The lower-level
|
|
47
|
+
`drift:check` command now defaults to the same specification and documentation
|
|
48
|
+
checks; the credential helper and `--hosted` mode are removed. Live
|
|
49
|
+
`tools/list` responses remain authoritative for MCP schemas.
|
|
50
|
+
- **Hosted safety manifests refreshed.** Stripe and RevenueCat classifications
|
|
51
|
+
now cover their current official tool references. Vercel URL fetching is
|
|
52
|
+
approval-gated because an application GET route is not guaranteed to be
|
|
53
|
+
observational.
|
|
54
|
+
|
|
55
|
+
### Fixed
|
|
56
|
+
|
|
57
|
+
- **Reviewed Vercel event drift.** Build-log projection accepts the expanded
|
|
58
|
+
deployment-event variants, including events without a published timestamp,
|
|
59
|
+
and the touched-endpoint digest records the reviewed contract (#520).
|
|
60
|
+
- **Schema ownership stays intact.** Deterministic coverage now proves the
|
|
61
|
+
safety wrapper preserves each provider description, input schema, and output
|
|
62
|
+
schema by reference instead of substituting a vendored definition (#521).
|
|
63
|
+
|
|
5
64
|
## 0.22.1 — 2026-08-31
|
|
6
65
|
|
|
7
66
|
This patch adds a maintained Vercel connection over the public REST API. It is
|
package/README.md
CHANGED
|
@@ -63,8 +63,10 @@ Fifty issues in, one small object out. Your context window notices.
|
|
|
63
63
|
- **Wrap any HTTP API by hand.** A few lines per tool. No OpenAPI conversion —
|
|
64
64
|
generated tool sprawl is the problem, not the fix.
|
|
65
65
|
- **Use maintained connections** for Cloudflare, Linear, Mixpanel, Notion,
|
|
66
|
-
RevenueCat, Stripe, and Vercel
|
|
67
|
-
read/write classifications, imported one at a time.
|
|
66
|
+
RevenueCat, Stripe, and Vercel: known endpoints, auth defaults, and vetted
|
|
67
|
+
read/write classifications, imported one at a time. Cloudflare, Notion, and
|
|
68
|
+
Vercel each let the deployment choose their hand-written API interface or
|
|
69
|
+
official hosted MCP.
|
|
68
70
|
- **Let the agent work in code.** Search, chain, filter, join, and reduce
|
|
69
71
|
inside the sandbox instead of round-tripping every call through the model.
|
|
70
72
|
- **Teach undeclared result shapes by using them.** Successful read-only calls
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { FetchLike, OAuthClientInformationContext, OAuthClientInformationMixed, OAuthClientMetadata, OAuthClientProvider, OAuthTokens } from "@modelcontextprotocol/client";
|
|
1
|
+
import type { FetchLike, OAuthClientInformationContext, OAuthClientInformationMixed, OAuthClientMetadata, OAuthClientProvider, OAuthDiscoveryState, OAuthTokens } from "@modelcontextprotocol/client";
|
|
2
2
|
import type { KVStorage } from "../types.js";
|
|
3
3
|
type OAuthRefreshFlightOutcome = {
|
|
4
4
|
status: "refreshed";
|
|
@@ -134,6 +134,8 @@ export declare class KvOAuthProvider implements OAuthClientProvider {
|
|
|
134
134
|
get clientMetadata(): OAuthClientMetadata;
|
|
135
135
|
clientInformation(ctx?: OAuthClientInformationContext): Promise<OAuthClientInformationMixed | undefined>;
|
|
136
136
|
saveClientInformation(info: OAuthClientInformationMixed, ctx?: OAuthClientInformationContext): Promise<void>;
|
|
137
|
+
discoveryState(): Promise<OAuthDiscoveryState | undefined>;
|
|
138
|
+
saveDiscoveryState(state: OAuthDiscoveryState): Promise<void>;
|
|
137
139
|
tokens(ctx?: OAuthClientInformationContext): Promise<OAuthTokens | undefined>;
|
|
138
140
|
saveTokens(tokens: OAuthTokens, ctx?: OAuthClientInformationContext): Promise<void>;
|
|
139
141
|
/**
|
|
@@ -24,6 +24,7 @@ const OAUTH_VALUE_KEYS = [
|
|
|
24
24
|
"oauth:pending",
|
|
25
25
|
"oauth:verifier",
|
|
26
26
|
"oauth:state",
|
|
27
|
+
"oauth:discovery",
|
|
27
28
|
];
|
|
28
29
|
const MAX_CLEANUP_BACKLOG = 1_000;
|
|
29
30
|
function isRefreshTokenRequest(init) {
|
|
@@ -621,6 +622,12 @@ export class KvOAuthProvider {
|
|
|
621
622
|
async saveClientInformation(info, ctx) {
|
|
622
623
|
await this.writeValue("oauth:client", info, (value) => JSON.stringify(value), ctx?.issuer);
|
|
623
624
|
}
|
|
625
|
+
async discoveryState() {
|
|
626
|
+
return (await this.readValue("oauth:discovery", (raw) => JSON.parse(raw)))?.value;
|
|
627
|
+
}
|
|
628
|
+
async saveDiscoveryState(state) {
|
|
629
|
+
await this.writeValue("oauth:discovery", state, (value) => JSON.stringify(value));
|
|
630
|
+
}
|
|
624
631
|
async tokens(ctx) {
|
|
625
632
|
const refreshGeneration = ctx ? await this.flowGeneration() : undefined;
|
|
626
633
|
const successIdentity = refreshGeneration !== undefined
|
|
@@ -800,6 +807,7 @@ export class KvOAuthProvider {
|
|
|
800
807
|
oauthValueStorageKey("oauth:client", generation),
|
|
801
808
|
oauthValueStorageKey("oauth:tokens", generation),
|
|
802
809
|
oauthValueStorageKey("oauth:verifier", generation),
|
|
810
|
+
oauthValueStorageKey("oauth:discovery", generation),
|
|
803
811
|
]);
|
|
804
812
|
}
|
|
805
813
|
else if (scope === "client") {
|
|
@@ -811,6 +819,9 @@ export class KvOAuthProvider {
|
|
|
811
819
|
else if (scope === "verifier") {
|
|
812
820
|
await this.storage.delete(oauthValueStorageKey("oauth:verifier", generation));
|
|
813
821
|
}
|
|
822
|
+
else if (scope === "discovery") {
|
|
823
|
+
await this.storage.delete(oauthValueStorageKey("oauth:discovery", generation));
|
|
824
|
+
}
|
|
814
825
|
if (endsRefresh) {
|
|
815
826
|
this.failRefreshFlight(new Error("OAuth refresh invalidated credentials before tokens were saved."));
|
|
816
827
|
}
|
package/dist/catalog-drift.d.ts
CHANGED
|
@@ -25,9 +25,9 @@ interface VettedToolRecord {
|
|
|
25
25
|
* Digest of the input and output schemas that release read, or undefined
|
|
26
26
|
* when no release has recorded them. Undefined is not "unchanged": a
|
|
27
27
|
* manifest with no digest cannot report a schema change, and says so by
|
|
28
|
-
* counting none.
|
|
29
|
-
*
|
|
30
|
-
* ([#351](https://github.com/zackbart/connecta/issues/351)).
|
|
28
|
+
* counting none. The credential-free provider check does not create or
|
|
29
|
+
* update schema digests; the live `tools/list` response remains the schema
|
|
30
|
+
* agents receive ([#351](https://github.com/zackbart/connecta/issues/351)).
|
|
31
31
|
*/
|
|
32
32
|
schemaDigest?: string;
|
|
33
33
|
}
|
|
@@ -1,19 +1,30 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { type RemoteMcpAuth } from "../connectors/remote-mcp.js";
|
|
2
|
+
import type { Connector, ConnectorCallAdmissionPolicy, ConnectorCredentialConfig } from "../types.js";
|
|
2
3
|
/** Cloudflare's v4 REST base. Override only for a proxy or a test double. */
|
|
3
4
|
export declare const CLOUDFLARE_API_BASE = "https://api.cloudflare.com/client/v4";
|
|
5
|
+
/** Cloudflare's official whole-API hosted MCP endpoint. */
|
|
6
|
+
export declare const CLOUDFLARE_MCP_ENDPOINT = "https://mcp.cloudflare.com/mcp";
|
|
4
7
|
/** Authentication schemes accepted by Cloudflare's v4 API. */
|
|
5
8
|
export type CloudflareAuthentication = "apiToken" | "globalApiKey";
|
|
6
9
|
/** See documentation/cloudflare.md#dns-record-types. */
|
|
7
10
|
export declare const CLOUDFLARE_DNS_RECORD_TYPES: readonly ["A", "AAAA", "CAA", "CERT", "CNAME", "DNSKEY", "DS", "HTTPS", "LOC", "MX", "NAPTR", "NS", "OPENPGPKEY", "PTR", "SMIMEA", "SRV", "SSHFP", "SVCB", "TLSA", "TXT", "URI"];
|
|
8
11
|
/** Content-valued types only; see documentation/cloudflare.md#dns-record-types. */
|
|
9
12
|
export declare const CLOUDFLARE_CONTENT_DNS_RECORD_TYPES: readonly ["A", "AAAA", "CNAME", "MX", "NS", "OPENPGPKEY", "PTR", "TXT"];
|
|
10
|
-
|
|
11
|
-
/** Human-readable display name; defaults
|
|
13
|
+
interface CloudflareCommonOptions {
|
|
14
|
+
/** Human-readable display name; defaults identify the selected interface. */
|
|
12
15
|
title?: string;
|
|
13
16
|
/** Downstream auth ownership. Defaults to one shared deployment grant. */
|
|
14
17
|
authScope?: "shared" | "personal";
|
|
15
18
|
/** Which account/estate this connection administers, and for whom. */
|
|
16
19
|
purpose: string;
|
|
20
|
+
/** Account-specific conventions appended to the maintained provider guide. */
|
|
21
|
+
instructions?: string;
|
|
22
|
+
/** Connector-specific inline result limit; omit to inherit the deployment. */
|
|
23
|
+
maxResultBytes?: number;
|
|
24
|
+
}
|
|
25
|
+
export interface CloudflareApiOptions extends CloudflareCommonOptions {
|
|
26
|
+
/** Omit for backward compatibility; the hand-written API interface is default. */
|
|
27
|
+
surface?: "api";
|
|
17
28
|
/**
|
|
18
29
|
* Default account id for account-scoped tools. When set, `accountId` becomes
|
|
19
30
|
* an optional argument; when omitted, agents must pass one and can find it
|
|
@@ -32,12 +43,22 @@ export interface CloudflareOptions {
|
|
|
32
43
|
authentication?: CloudflareAuthentication;
|
|
33
44
|
/** Credential presentation override; credentials are always operator-managed. */
|
|
34
45
|
credential?: ConnectorCredentialConfig;
|
|
35
|
-
/** Account-specific conventions appended to the maintained provider guide. */
|
|
36
|
-
instructions?: string;
|
|
37
|
-
/** Connector-specific inline result limit; omit to inherit the deployment. */
|
|
38
|
-
maxResultBytes?: number;
|
|
39
46
|
/** Simultaneous downstream calls. Defaults to 6. */
|
|
40
47
|
maxConcurrency?: number;
|
|
41
48
|
}
|
|
42
|
-
|
|
43
|
-
|
|
49
|
+
export interface CloudflareMcpOptions extends CloudflareCommonOptions {
|
|
50
|
+
surface: "mcp";
|
|
51
|
+
/** OAuth by default, or a scoped API token for a headless deployment. */
|
|
52
|
+
auth?: RemoteMcpAuth;
|
|
53
|
+
/** Optional per-runtime downstream call-admission policy. */
|
|
54
|
+
callAdmission?: ConnectorCallAdmissionPolicy;
|
|
55
|
+
}
|
|
56
|
+
/** Backward-compatible API options; existing consumers may extend this interface. */
|
|
57
|
+
export interface CloudflareOptions extends CloudflareApiOptions {
|
|
58
|
+
}
|
|
59
|
+
/** Select one Cloudflare interface when deployment configuration constructs it. */
|
|
60
|
+
export type CloudflareConnectionOptions = CloudflareOptions | CloudflareMcpOptions;
|
|
61
|
+
export declare const CLOUDFLARE_MCP_VETTED_CATALOG: import("../catalog-drift.js").VettedCatalog;
|
|
62
|
+
/** A maintained Cloudflare connection using the selected provider interface. */
|
|
63
|
+
export declare function cloudflare(id: string, options: CloudflareConnectionOptions): Connector;
|
|
64
|
+
export {};
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
/** See documentation/cloudflare.md#no-sdk-on-purpose. */
|
|
2
|
-
import { api } from "../connectors/api.js";
|
|
2
|
+
import { api, defined } from "../connectors/api.js";
|
|
3
|
+
import { remoteMcp, withCredentialDefaults, } from "../connectors/remote-mcp.js";
|
|
4
|
+
import { vettedCatalog, withVettedCatalog } from "../catalog-drift.js";
|
|
3
5
|
import { guardedFetch, retryAfterMs, } from "../connectors/guarded-fetch.js";
|
|
4
6
|
import { ConnectorCallError } from "../errors.js";
|
|
5
7
|
/** Cloudflare's v4 REST base. Override only for a proxy or a test double. */
|
|
6
8
|
export const CLOUDFLARE_API_BASE = "https://api.cloudflare.com/client/v4";
|
|
9
|
+
/** Cloudflare's official whole-API hosted MCP endpoint. */
|
|
10
|
+
export const CLOUDFLARE_MCP_ENDPOINT = "https://mcp.cloudflare.com/mcp";
|
|
7
11
|
/** See documentation/cloudflare.md#dns-record-types. */
|
|
8
12
|
export const CLOUDFLARE_DNS_RECORD_TYPES = [
|
|
9
13
|
"A",
|
|
@@ -2381,7 +2385,7 @@ function buildTools(scope, authentication) {
|
|
|
2381
2385
|
];
|
|
2382
2386
|
return tools;
|
|
2383
2387
|
}
|
|
2384
|
-
function
|
|
2388
|
+
function apiUsageGuide(purpose, scope, instructions, authentication) {
|
|
2385
2389
|
const accountInstructions = instructions?.trim();
|
|
2386
2390
|
const zoneLine = scope.zoneId
|
|
2387
2391
|
? `This connector defaults to zone \`${scope.zoneId}\`; omit \`zoneId\` unless the request names a different domain.`
|
|
@@ -2411,12 +2415,64 @@ ${accountInstructions
|
|
|
2411
2415
|
? `\n## Account instructions\n\n${accountInstructions}\n`
|
|
2412
2416
|
: ""}`;
|
|
2413
2417
|
}
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2418
|
+
export const CLOUDFLARE_MCP_VETTED_CATALOG = vettedCatalog({
|
|
2419
|
+
reads: new Set(["search"]),
|
|
2420
|
+
// `execute` can send any method to more than 2,500 API endpoints. Its input
|
|
2421
|
+
// schema cannot prove a particular program is observational, so it stays on
|
|
2422
|
+
// the approval path even when that program happens to issue only GETs.
|
|
2423
|
+
writes: new Map([["execute", "destructive"]]),
|
|
2424
|
+
});
|
|
2425
|
+
function mcpUsageGuide(purpose, instructions) {
|
|
2426
|
+
const accountInstructions = instructions?.trim();
|
|
2427
|
+
return `# Cloudflare MCP usage
|
|
2428
|
+
|
|
2429
|
+
Official whole-API MCP interface: ${purpose}
|
|
2430
|
+
|
|
2431
|
+
- The catalog contains \`search\` and \`execute\`. Search runs code against
|
|
2432
|
+
Cloudflare's OpenAPI document. Execute runs code that may call any authorized
|
|
2433
|
+
Cloudflare API endpoint.
|
|
2434
|
+
- Use \`search\` to find the exact method, path, and fields before writing an
|
|
2435
|
+
execute program. Do not guess an endpoint from product naming.
|
|
2436
|
+
- Connecta routes every \`execute\` call through approval because the tool can
|
|
2437
|
+
mix GET, POST, PUT, PATCH, and DELETE requests inside one program. The MCP
|
|
2438
|
+
schema cannot establish that arbitrary code is read-only.
|
|
2439
|
+
- Keep returned values small. Filter and project inside the Cloudflare MCP
|
|
2440
|
+
program, then reduce again inside Connecta's \`execute_code\` when several
|
|
2441
|
+
calls must be joined.
|
|
2442
|
+
- OAuth and API-token permissions remain the provider-side boundary. An
|
|
2443
|
+
\`auth_required\` failure needs authorization or a token with the required
|
|
2444
|
+
Cloudflare permission.
|
|
2445
|
+
${accountInstructions
|
|
2446
|
+
? `\n## Account instructions\n\n${accountInstructions}\n`
|
|
2447
|
+
: ""}`;
|
|
2448
|
+
}
|
|
2449
|
+
function cloudflareMcp(id, purpose, options) {
|
|
2450
|
+
const connector = remoteMcp(id, {
|
|
2451
|
+
url: CLOUDFLARE_MCP_ENDPOINT,
|
|
2452
|
+
...defined({
|
|
2453
|
+
authScope: options.authScope,
|
|
2454
|
+
callAdmission: options.callAdmission,
|
|
2455
|
+
maxResultBytes: options.maxResultBytes,
|
|
2456
|
+
}),
|
|
2457
|
+
title: options.title ?? "Cloudflare (MCP)",
|
|
2458
|
+
description: `Cloudflare's official whole-API MCP interface: ${purpose}`,
|
|
2459
|
+
auth: withCredentialDefaults(options.auth ?? { type: "oauth" }, {
|
|
2460
|
+
credential: {
|
|
2461
|
+
label: "Cloudflare API token",
|
|
2462
|
+
description: "A scoped Cloudflare API token. Connecta sends it as a bearer token to mcp.cloudflare.com and stores it encrypted.",
|
|
2463
|
+
placeholder: "Paste Cloudflare API token",
|
|
2464
|
+
},
|
|
2465
|
+
}),
|
|
2466
|
+
requireHttps: true,
|
|
2467
|
+
usageGuide: {
|
|
2468
|
+
content: mcpUsageGuide(purpose, options.instructions),
|
|
2469
|
+
summary: "Official whole-API MCP. Search the OpenAPI document, then approve each mixed-method execute program.",
|
|
2470
|
+
required: true,
|
|
2471
|
+
},
|
|
2472
|
+
});
|
|
2473
|
+
return withVettedCatalog(connector, CLOUDFLARE_MCP_VETTED_CATALOG);
|
|
2474
|
+
}
|
|
2475
|
+
function cloudflareApi(id, purpose, options) {
|
|
2420
2476
|
const maxConcurrency = options.maxConcurrency ?? 6;
|
|
2421
2477
|
if (!Number.isInteger(maxConcurrency) || maxConcurrency < 1) {
|
|
2422
2478
|
throw new Error("cloudflare() maxConcurrency must be a positive integer.");
|
|
@@ -2437,7 +2493,7 @@ export function cloudflare(id, options) {
|
|
|
2437
2493
|
credential: credentialConfig(authentication, options.credential),
|
|
2438
2494
|
callAdmission: admissionPolicy(maxConcurrency),
|
|
2439
2495
|
usageGuide: {
|
|
2440
|
-
content:
|
|
2496
|
+
content: apiUsageGuide(purpose, scope, options.instructions, authentication),
|
|
2441
2497
|
// Explicit rather than derived: the first content line is the zone
|
|
2442
2498
|
// scoping rule, which varies per deployment and reads as an instruction
|
|
2443
2499
|
// rather than as the routing fact a browsing agent needs.
|
|
@@ -2485,3 +2541,13 @@ export function cloudflare(id, options) {
|
|
|
2485
2541
|
}),
|
|
2486
2542
|
});
|
|
2487
2543
|
}
|
|
2544
|
+
/** A maintained Cloudflare connection using the selected provider interface. */
|
|
2545
|
+
export function cloudflare(id, options) {
|
|
2546
|
+
const purpose = options.purpose.trim();
|
|
2547
|
+
if (!purpose) {
|
|
2548
|
+
throw new Error("cloudflare() requires a non-empty account purpose.");
|
|
2549
|
+
}
|
|
2550
|
+
return options.surface === "mcp"
|
|
2551
|
+
? cloudflareMcp(id, purpose, options)
|
|
2552
|
+
: cloudflareApi(id, purpose, options);
|
|
2553
|
+
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import type { Connector } from "../types.js";
|
|
1
|
+
import type { Connector, ConnectorCallAdmissionPolicy } from "../types.js";
|
|
2
2
|
/** Notion's REST origin. Every tool below speaks to exactly this host. */
|
|
3
3
|
export declare const NOTION_API_BASE_URL = "https://api.notion.com";
|
|
4
|
+
/** Notion's official hosted MCP endpoint. */
|
|
5
|
+
export declare const NOTION_MCP_ENDPOINT = "https://mcp.notion.com/mcp";
|
|
4
6
|
/** See documentation/notion.md#the-pinned-api-version. */
|
|
5
7
|
export declare const NOTION_API_VERSION = "2026-03-11";
|
|
6
|
-
|
|
7
|
-
/** Human-readable display name; defaults
|
|
8
|
+
interface NotionCommonOptions {
|
|
9
|
+
/** Human-readable display name; defaults identify the selected interface. */
|
|
8
10
|
title?: string;
|
|
9
11
|
/** Downstream auth ownership. Defaults to one shared deployment grant. */
|
|
10
12
|
authScope?: "shared" | "personal";
|
|
@@ -12,6 +14,13 @@ export interface NotionOptions {
|
|
|
12
14
|
purpose: string;
|
|
13
15
|
/** Workspace-specific conventions appended to the maintained provider guide. */
|
|
14
16
|
instructions?: string;
|
|
17
|
+
/** Connector-specific inline result limit; omit to inherit the deployment. */
|
|
18
|
+
maxResultBytes?: number;
|
|
19
|
+
}
|
|
20
|
+
/** Connecta's maintained hand-written Notion REST interface. */
|
|
21
|
+
export interface NotionApiOptions extends NotionCommonOptions {
|
|
22
|
+
/** Omit for backward compatibility; the hand-written API interface is default. */
|
|
23
|
+
surface?: "api";
|
|
15
24
|
/** Operator-facing label for the integration token. */
|
|
16
25
|
credentialLabel?: string;
|
|
17
26
|
/**
|
|
@@ -19,8 +28,20 @@ export interface NotionOptions {
|
|
|
19
28
|
* Defaults to 25; Notion's maximum is 100.
|
|
20
29
|
*/
|
|
21
30
|
defaultPageSize?: number;
|
|
22
|
-
/** Connector-specific inline result limit; omit to inherit the deployment. */
|
|
23
|
-
maxResultBytes?: number;
|
|
24
31
|
}
|
|
25
|
-
/**
|
|
26
|
-
export
|
|
32
|
+
/** Notion's official hosted MCP interface, authenticated through OAuth. */
|
|
33
|
+
export interface NotionMcpOptions extends NotionCommonOptions {
|
|
34
|
+
surface: "mcp";
|
|
35
|
+
/** Optional per-runtime downstream call-admission policy. */
|
|
36
|
+
callAdmission?: ConnectorCallAdmissionPolicy;
|
|
37
|
+
}
|
|
38
|
+
/** Backward-compatible API options; existing consumers may extend this interface. */
|
|
39
|
+
export interface NotionOptions extends NotionApiOptions {
|
|
40
|
+
}
|
|
41
|
+
/** Select one Notion interface when deployment configuration constructs it. */
|
|
42
|
+
export type NotionConnectionOptions = NotionOptions | NotionMcpOptions;
|
|
43
|
+
/** Release-reviewed Notion MCP inventory and safety verdicts. */
|
|
44
|
+
export declare const NOTION_MCP_VETTED_CATALOG: import("../catalog-drift.js").VettedCatalog;
|
|
45
|
+
/** A maintained Notion connection using the selected provider interface. */
|
|
46
|
+
export declare function notion(id: string, options: NotionConnectionOptions): Connector;
|
|
47
|
+
export {};
|
package/dist/providers/notion.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import { api } from "../connectors/api.js";
|
|
1
|
+
import { api, defined } from "../connectors/api.js";
|
|
2
|
+
import { remoteMcp } from "../connectors/remote-mcp.js";
|
|
3
|
+
import { vettedCatalog, withVettedCatalog } from "../catalog-drift.js";
|
|
2
4
|
import { guardedFetch, retryAfterMs, } from "../connectors/guarded-fetch.js";
|
|
3
5
|
import { ConnectorCallError } from "../errors.js";
|
|
4
6
|
/** Notion's REST origin. Every tool below speaks to exactly this host. */
|
|
5
7
|
export const NOTION_API_BASE_URL = "https://api.notion.com";
|
|
8
|
+
/** Notion's official hosted MCP endpoint. */
|
|
9
|
+
export const NOTION_MCP_ENDPOINT = "https://mcp.notion.com/mcp";
|
|
6
10
|
/** See documentation/notion.md#the-pinned-api-version. */
|
|
7
11
|
export const NOTION_API_VERSION = "2026-03-11";
|
|
8
12
|
/** Notion's hard cap on `page_size` for every paginated endpoint. */
|
|
@@ -1393,7 +1397,7 @@ function buildTools(defaultPageSize) {
|
|
|
1393
1397
|
// Guide and constructor
|
|
1394
1398
|
// ---------------------------------------------------------------------------
|
|
1395
1399
|
/** See documentation/notion.md#databases-contain-data-sources. */
|
|
1396
|
-
function
|
|
1400
|
+
function apiUsageGuide(purpose, instructions) {
|
|
1397
1401
|
const accountInstructions = instructions?.trim();
|
|
1398
1402
|
return `# Notion usage
|
|
1399
1403
|
|
|
@@ -1490,12 +1494,95 @@ ${accountInstructions
|
|
|
1490
1494
|
? `\n## Workspace instructions\n\n${accountInstructions}\n`
|
|
1491
1495
|
: ""}`;
|
|
1492
1496
|
}
|
|
1493
|
-
/**
|
|
1494
|
-
export
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1497
|
+
/** Release-reviewed Notion MCP inventory and safety verdicts. */
|
|
1498
|
+
export const NOTION_MCP_VETTED_CATALOG = vettedCatalog({
|
|
1499
|
+
reads: new Set([
|
|
1500
|
+
"notion-search",
|
|
1501
|
+
"notion-search-skills",
|
|
1502
|
+
"notion-fetch",
|
|
1503
|
+
"notion-download-attachment",
|
|
1504
|
+
"notion-query-data-sources",
|
|
1505
|
+
"notion-query-meeting-notes",
|
|
1506
|
+
"notion-search-agents",
|
|
1507
|
+
"notion-list-agents",
|
|
1508
|
+
"notion-query-sessions",
|
|
1509
|
+
"notion-search-sessions",
|
|
1510
|
+
"notion-get-session-status",
|
|
1511
|
+
"notion-wait-session",
|
|
1512
|
+
"notion-list-session-events",
|
|
1513
|
+
"notion-read-session-event",
|
|
1514
|
+
"notion-get-comments",
|
|
1515
|
+
"notion-get-teams",
|
|
1516
|
+
"notion-get-users",
|
|
1517
|
+
"notion-get-async-task",
|
|
1518
|
+
]),
|
|
1519
|
+
writes: new Map([
|
|
1520
|
+
["notion-create-file-upload", "additive"],
|
|
1521
|
+
["notion-create-attachment", "additive"],
|
|
1522
|
+
["notion-create-pages", "additive"],
|
|
1523
|
+
["notion-duplicate-page", "additive"],
|
|
1524
|
+
["notion-create-database", "additive"],
|
|
1525
|
+
["notion-create-folder", "additive"],
|
|
1526
|
+
["notion-create-view", "additive"],
|
|
1527
|
+
["notion-spawn-session", "additive"],
|
|
1528
|
+
["notion-send-message-to-session", "additive"],
|
|
1529
|
+
["notion-create-comment", "additive"],
|
|
1530
|
+
["notion-update-page", "destructive"],
|
|
1531
|
+
["notion-convert-page-to-skill", "destructive"],
|
|
1532
|
+
["notion-move-pages", "destructive"],
|
|
1533
|
+
["notion-update-data-source", "destructive"],
|
|
1534
|
+
["notion-update-view", "destructive"],
|
|
1535
|
+
["notion-stop-session", "destructive"],
|
|
1536
|
+
]),
|
|
1537
|
+
});
|
|
1538
|
+
function mcpUsageGuide(purpose, instructions) {
|
|
1539
|
+
const accountInstructions = instructions?.trim();
|
|
1540
|
+
return `# Notion MCP usage
|
|
1541
|
+
|
|
1542
|
+
Official MCP interface: tool names, descriptions, argument schemas, and result
|
|
1543
|
+
schemas come from Notion's live server. Connecta preserves that catalog and
|
|
1544
|
+
only fills in release-reviewed safety annotations when Notion leaves them out.
|
|
1545
|
+
|
|
1546
|
+
Workspace purpose: ${purpose}
|
|
1547
|
+
|
|
1548
|
+
- Discover the live catalog before assuming a tool exists. Notion can gate
|
|
1549
|
+
tools by workspace, account, client, and rollout independently of Connecta.
|
|
1550
|
+
- Start broad discovery with \`notion-search\`, then use \`notion-fetch\` on
|
|
1551
|
+
the exact page, database, data source, or object before changing it.
|
|
1552
|
+
- Use the live input schema as the contract. Notion owns these MCP schemas;
|
|
1553
|
+
the REST schemas in Connecta's API interface do not apply to MCP tools with
|
|
1554
|
+
similar names.
|
|
1555
|
+
- Session and agent tools can launch asynchronous work. Read session state and
|
|
1556
|
+
events before sending another message, waiting, or stopping a session.
|
|
1557
|
+
- File uploads and attachment tools create durable workspace state. Keep
|
|
1558
|
+
downloads inside the requested task and do not expose signed attachment URLs.
|
|
1559
|
+
- An \`auth_required\` failure means this connector's OAuth grant is missing or
|
|
1560
|
+
expired. Run \`authorize_connector\` for this connector id, then retry.
|
|
1561
|
+
${accountInstructions
|
|
1562
|
+
? `\n## Workspace instructions\n\n${accountInstructions}\n`
|
|
1563
|
+
: ""}`;
|
|
1564
|
+
}
|
|
1565
|
+
function notionMcp(id, purpose, options) {
|
|
1566
|
+
const connector = remoteMcp(id, {
|
|
1567
|
+
url: NOTION_MCP_ENDPOINT,
|
|
1568
|
+
...defined({
|
|
1569
|
+
authScope: options.authScope,
|
|
1570
|
+
callAdmission: options.callAdmission,
|
|
1571
|
+
maxResultBytes: options.maxResultBytes,
|
|
1572
|
+
}),
|
|
1573
|
+
title: options.title ?? "Notion (MCP)",
|
|
1574
|
+
description: `Notion's official hosted MCP interface: ${purpose}`,
|
|
1575
|
+
auth: { type: "oauth" },
|
|
1576
|
+
requireHttps: true,
|
|
1577
|
+
usageGuide: {
|
|
1578
|
+
content: mcpUsageGuide(purpose, options.instructions),
|
|
1579
|
+
summary: "Official MCP. Live Notion schemas, object discovery, sessions, agents, attachments, and OAuth ownership.",
|
|
1580
|
+
required: true,
|
|
1581
|
+
},
|
|
1582
|
+
});
|
|
1583
|
+
return withVettedCatalog(connector, NOTION_MCP_VETTED_CATALOG);
|
|
1584
|
+
}
|
|
1585
|
+
function notionApi(id, purpose, options) {
|
|
1499
1586
|
const defaultPageSize = options.defaultPageSize ?? DEFAULT_PAGE_SIZE;
|
|
1500
1587
|
if (!Number.isInteger(defaultPageSize) ||
|
|
1501
1588
|
defaultPageSize < 1 ||
|
|
@@ -1530,7 +1617,7 @@ export function notion(id, options) {
|
|
|
1530
1617
|
},
|
|
1531
1618
|
callAdmission: NOTION_ADMISSION,
|
|
1532
1619
|
usageGuide: {
|
|
1533
|
-
content:
|
|
1620
|
+
content: apiUsageGuide(purpose, options.instructions),
|
|
1534
1621
|
summary: "Database-to-data-source lookup, property write rules, lean-vs-raw results, and Notion's overloaded 403/404.",
|
|
1535
1622
|
required: true,
|
|
1536
1623
|
},
|
|
@@ -1540,3 +1627,13 @@ export function notion(id, options) {
|
|
|
1540
1627
|
: {}),
|
|
1541
1628
|
});
|
|
1542
1629
|
}
|
|
1630
|
+
/** A maintained Notion connection using the selected provider interface. */
|
|
1631
|
+
export function notion(id, options) {
|
|
1632
|
+
const purpose = options.purpose.trim();
|
|
1633
|
+
if (!purpose) {
|
|
1634
|
+
throw new Error("notion() requires a non-empty workspace purpose.");
|
|
1635
|
+
}
|
|
1636
|
+
return options.surface === "mcp"
|
|
1637
|
+
? notionMcp(id, purpose, options)
|
|
1638
|
+
: notionApi(id, purpose, options);
|
|
1639
|
+
}
|
|
@@ -108,9 +108,19 @@ const WRITE_TOOLS = new Map([
|
|
|
108
108
|
["create-audience", "additive"],
|
|
109
109
|
["update-audience", "destructive"],
|
|
110
110
|
// Paywalls
|
|
111
|
+
["attach-offering-to-paywall", "destructive"],
|
|
112
|
+
["detach-offering-from-paywall", "destructive"],
|
|
111
113
|
["duplicate-paywall", "additive"],
|
|
112
114
|
["publish-paywall", "destructive"],
|
|
113
115
|
["unpublish-paywall", "destructive"],
|
|
116
|
+
// Offerings and experiments added to the published reference after #512.
|
|
117
|
+
["duplicate-offering", "additive"],
|
|
118
|
+
["create-experiment", "additive"],
|
|
119
|
+
["pause-experiment", "destructive"],
|
|
120
|
+
["resume-experiment", "destructive"],
|
|
121
|
+
["start-experiment", "destructive"],
|
|
122
|
+
["stop-experiment", "destructive"],
|
|
123
|
+
["update-experiment", "destructive"],
|
|
114
124
|
// Customers and subscriptions
|
|
115
125
|
["assign-customer-offering", "destructive"],
|
|
116
126
|
["grant-customer-entitlement", "destructive"],
|
package/dist/providers/stripe.js
CHANGED
|
@@ -37,7 +37,12 @@ const READ_ONLY_TOOLS = new Set([
|
|
|
37
37
|
"stripe_api_search",
|
|
38
38
|
"stripe_api_details",
|
|
39
39
|
"stripe_api_read",
|
|
40
|
+
"get_stripe_account_info",
|
|
40
41
|
"get_balance_summary",
|
|
42
|
+
"list_metrics",
|
|
43
|
+
"explain_metric",
|
|
44
|
+
"metric_drilldown",
|
|
45
|
+
"show_metric_app",
|
|
41
46
|
"list_available_accounts_or_orgs",
|
|
42
47
|
"manage_stripe_accounts",
|
|
43
48
|
"search_stripe_documentation",
|
|
@@ -45,8 +50,10 @@ const READ_ONLY_TOOLS = new Set([
|
|
|
45
50
|
/** Reviewed writes, including mixed read/create tools: `documentation/stripe.md`. */
|
|
46
51
|
const WRITE_TOOLS = new Map([
|
|
47
52
|
["stripe_api_write", "destructive"],
|
|
53
|
+
["create_refund", "destructive"],
|
|
48
54
|
["stripe_implementation_planner", "additive"],
|
|
49
55
|
["stripe_analytics", "additive"],
|
|
56
|
+
["stripe_report", "additive"],
|
|
50
57
|
["send_stripe_mcp_feedback", "additive"],
|
|
51
58
|
]);
|
|
52
59
|
/** Release-reviewed manifest; see provider conventions P5 and P13. */
|