@zackbart/connecta 0.28.0 → 0.29.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 +961 -5
- package/README.md +62 -39
- package/bin/connecta.mjs +110 -139
- package/bin/meta-tool-names.d.mts +2 -0
- package/bin/meta-tool-names.mjs +9 -0
- package/bin/version.mjs +3 -0
- package/dist/access-tokens.js +53 -63
- package/dist/activity-request.js +8 -0
- package/dist/activity.d.ts +76 -42
- package/dist/activity.js +110 -42
- package/dist/auth/clerk-sdk/client.d.ts +65 -0
- package/dist/auth/clerk-sdk/client.js +5 -0
- package/dist/auth/clerk-sdk/generated.js +1845 -0
- package/dist/auth/clerk-transport.js +19 -0
- package/dist/auth/clerk.d.ts +17 -7
- package/dist/auth/clerk.js +189 -107
- package/dist/auth/cloudflare-access.js +25 -26
- package/dist/auth/downstream-client-metadata.d.ts +29 -0
- package/dist/auth/downstream-client-metadata.js +133 -0
- package/dist/auth/downstream-oauth.js +1632 -1509
- package/dist/auth/downstream-revocation.js +106 -0
- package/dist/auth/oauth-token-response.js +231 -0
- package/dist/auth/oauth-v2-migration.js +116 -0
- package/dist/auth/static-oauth.js +526 -0
- package/dist/auth-elicitation.js +283 -0
- package/dist/branding.d.ts +8 -16
- package/dist/branding.js +26 -59
- package/dist/byte-read-response.js +39 -0
- package/dist/call-admission.js +12 -16
- package/dist/catalog-cache.js +739 -0
- package/dist/catalog-drift.d.ts +50 -15
- package/dist/catalog-drift.js +365 -128
- package/dist/catalog-fingerprint.js +2 -4
- package/dist/catalog-freshness.js +13 -0
- package/dist/catalog-limits.js +2 -2
- package/dist/catalog-service.js +368 -224
- package/dist/catalog.js +43 -84
- package/dist/concurrency.js +3 -4
- package/dist/config-defaults.d.ts +39 -0
- package/dist/config-defaults.js +46 -0
- package/dist/config-schema.d.ts +181 -0
- package/dist/config-schema.js +435 -0
- package/dist/config-value-sources.js +102 -0
- package/dist/config.d.ts +631 -0
- package/dist/config.js +503 -0
- package/dist/connector-access.d.ts +1 -0
- package/dist/connector-access.js +13 -15
- package/dist/connector-caller.d.ts +8 -0
- package/dist/connector-caller.js +15 -6
- package/dist/connector-scope.js +1 -1
- package/dist/connectors/api-connector.d.ts +220 -0
- package/dist/connectors/api-connector.js +214 -0
- package/dist/connectors/api.d.ts +8 -71
- package/dist/connectors/api.js +13 -99
- package/dist/connectors/guarded-fetch.d.ts +144 -0
- package/dist/connectors/guarded-fetch.js +108 -25
- package/dist/connectors/negotiation-cache.js +46 -0
- package/dist/connectors/option-shapes.js +27 -0
- package/dist/connectors/remote-mcp.d.ts +30 -4
- package/dist/connectors/remote-mcp.js +1780 -351
- package/dist/connectors/resource-uri.js +335 -0
- package/dist/credential-contract.d.ts +10 -0
- package/dist/credential-rules.js +1 -3
- package/dist/credential-url.js +108 -0
- package/dist/credentials.d.ts +6 -1
- package/dist/credentials.js +27 -18
- package/dist/d1.d.ts +130 -0
- package/dist/d1.js +290 -0
- package/dist/describe-config.d.ts +165 -0
- package/dist/describe-config.js +315 -0
- package/dist/described.js +106 -0
- package/dist/downstream-input-context.js +119 -0
- package/dist/downstream-input.js +323 -0
- package/dist/errors.d.ts +97 -20
- package/dist/errors.js +158 -80
- package/dist/execute.js +453 -305
- package/dist/executor-admission.d.ts +1 -0
- package/dist/executor-admission.js +11 -15
- package/dist/executor-contract.d.ts +20 -0
- package/dist/executor-contract.js +48 -0
- package/dist/executor-result.js +24 -9
- package/dist/executors/quickjs-child.js +3 -4
- package/dist/executors/quickjs-runtime.js +147 -59
- package/dist/executors/quickjs.js +29 -35
- package/dist/favicon.js +1 -2
- package/dist/fix-prompt.js +1 -3
- package/dist/guest-runtime.js +188 -0
- package/dist/guest-types.d.ts +176 -0
- package/dist/guest-types.js +1 -0
- package/dist/html-security.js +24 -0
- package/dist/identity.js +1 -3
- package/dist/inbound-credential.js +52 -0
- package/dist/index.d.ts +25 -257
- package/dist/index.js +65 -478
- package/dist/invocation-auth.js +69 -0
- package/dist/invocation.js +230 -73
- package/dist/json-schema.d.ts +1 -1
- package/dist/mcp-client-context.js +35 -0
- package/dist/mcp-result.js +11 -7
- package/dist/meta-output.js +76 -0
- package/dist/meta-tool-names.d.ts +2 -0
- package/dist/meta-tool-names.js +3 -0
- package/dist/meta-tools.js +285 -209
- package/dist/module-contracts.d.ts +8 -23
- package/dist/node.d.ts +0 -2
- package/dist/node.js +2 -2
- package/dist/oauth-callback-outcome.js +1 -3
- package/dist/oauth-handoff.js +117 -0
- package/dist/oauth-partition.js +17 -0
- package/dist/oauth-sealing.js +20 -0
- package/dist/operator-record.d.ts +137 -0
- package/dist/operator-record.js +420 -0
- package/dist/operator-ui/assets.js +31 -0
- package/dist/operator-ui/contract.d.ts +72 -0
- package/dist/operator-ui/contract.js +1 -0
- package/dist/operator-ui/fix-prompts.d.ts +18 -0
- package/dist/operator-ui/generated.js +5 -4
- package/dist/operator-ui/model.d.ts +12 -87
- package/dist/operator-ui/model.js +2 -9
- package/dist/operator-ui/setup-commands.js +1 -3
- package/dist/operator-ui/view.d.ts +323 -0
- package/dist/operator-ui/view.js +62 -189
- package/dist/page-styles.js +2 -3
- package/dist/program-source.js +14 -2
- package/dist/{exempt-writes.js → program-writes.js} +55 -18
- package/dist/provider.d.ts +142 -0
- package/dist/provider.js +187 -0
- package/dist/providers/_shared/google/result-size.js +57 -0
- package/dist/providers/_shared/google/service-account.d.ts +58 -0
- package/dist/providers/_shared/google/service-account.js +500 -0
- package/dist/providers/_shared/google/workspace.d.ts +276 -0
- package/dist/providers/_shared/google/workspace.js +518 -0
- package/dist/providers/basecamp/index.d.ts +43 -0
- package/dist/providers/basecamp/index.js +997 -0
- package/dist/providers/basecamp/skill.generated.js +9 -0
- package/dist/providers/breeze/index.d.ts +34 -0
- package/dist/providers/breeze/index.js +1446 -0
- package/dist/providers/breeze/skill.generated.js +9 -0
- package/dist/providers/ccb/index.d.ts +103 -0
- package/dist/providers/ccb/index.js +1725 -0
- package/dist/providers/ccb/skill.generated.js +9 -0
- package/dist/providers/{cloudflare.d.ts → cloudflare/index.d.ts} +8 -7
- package/dist/providers/{cloudflare.js → cloudflare/index.js} +171 -738
- package/dist/providers/cloudflare/skill.generated.js +10 -0
- package/dist/providers/docs/index.d.ts +54 -0
- package/dist/providers/docs/index.js +1237 -0
- package/dist/providers/docs/skill.generated.js +9 -0
- package/dist/providers/drive/index.d.ts +53 -0
- package/dist/providers/drive/index.js +1523 -0
- package/dist/providers/drive/skill.generated.js +9 -0
- package/dist/providers/forms/index.d.ts +54 -0
- package/dist/providers/forms/index.js +1217 -0
- package/dist/providers/forms/skill.generated.js +11 -0
- package/dist/providers/github/auth.d.ts +32 -0
- package/dist/providers/github/auth.js +361 -0
- package/dist/providers/github/hosted.js +218 -0
- package/dist/providers/github/index.d.ts +13 -0
- package/dist/providers/github/index.js +140 -0
- package/dist/providers/github/key.js +100 -0
- package/dist/providers/github/rest.js +321 -0
- package/dist/providers/github/scope.d.ts +29 -0
- package/dist/providers/github/scope.js +124 -0
- package/dist/providers/github/skill.generated.js +8 -0
- package/dist/providers/gmail/index.d.ts +51 -0
- package/dist/providers/gmail/index.js +1436 -0
- package/dist/providers/gmail/skill.generated.js +9 -0
- package/dist/providers/{linear.d.ts → linear/index.d.ts} +11 -14
- package/dist/providers/linear/index.js +352 -0
- package/dist/providers/linear/skill.generated.js +8 -0
- package/dist/providers/{mixpanel.d.ts → mixpanel/index.d.ts} +5 -10
- package/dist/providers/mixpanel/index.js +416 -0
- package/dist/providers/mixpanel/skill.generated.js +9 -0
- package/dist/providers/{notion.d.ts → notion/index.d.ts} +8 -8
- package/dist/providers/{notion.js → notion/index.js} +226 -239
- package/dist/providers/notion/skill.generated.js +10 -0
- package/dist/providers/overflow/index.d.ts +60 -0
- package/dist/providers/overflow/index.js +1535 -0
- package/dist/providers/overflow/skill.generated.js +8 -0
- package/dist/providers/planning-center/index.d.ts +59 -0
- package/dist/providers/planning-center/index.js +2199 -0
- package/dist/providers/planning-center/skill.generated.js +10 -0
- package/dist/providers/{revenuecat.d.ts → revenuecat/index.d.ts} +5 -10
- package/dist/providers/revenuecat/index.js +557 -0
- package/dist/providers/revenuecat/skill.generated.js +11 -0
- package/dist/providers/sheets/index.d.ts +54 -0
- package/dist/providers/sheets/index.js +1237 -0
- package/dist/providers/sheets/skill.generated.js +10 -0
- package/dist/providers/slides/index.d.ts +53 -0
- package/dist/providers/slides/index.js +2645 -0
- package/dist/providers/slides/skill.generated.js +9 -0
- package/dist/providers/{stripe.d.ts → stripe/index.d.ts} +5 -12
- package/dist/providers/stripe/index.js +266 -0
- package/dist/providers/stripe/skill.generated.js +11 -0
- package/dist/providers/tithely/index.d.ts +49 -0
- package/dist/providers/tithely/index.js +1003 -0
- package/dist/providers/tithely/skill.generated.js +8 -0
- package/dist/providers/{vercel.d.ts → vercel/index.d.ts} +8 -8
- package/dist/providers/vercel/index.js +1038 -0
- package/dist/providers/vercel/mcp-ownership.js +212 -0
- package/dist/providers/vercel/skill.generated.js +11 -0
- package/dist/registry.d.ts +108 -171
- package/dist/registry.js +513 -925
- package/dist/request-state.js +21 -0
- package/dist/resource-read.js +100 -0
- package/dist/result-shapes.js +17 -49
- package/dist/retired-toolkits.js +1 -1
- package/dist/routes/access-tokens.js +3 -6
- package/dist/routes/activity-context.js +21 -0
- package/dist/routes/activity-disclosure.js +40 -0
- package/dist/routes/activity.js +59 -21
- package/dist/routes/actor-labels.js +3 -50
- package/dist/routes/connect.js +221 -0
- package/dist/routes/credentials.js +15 -27
- package/dist/routes/mcp.js +356 -130
- package/dist/routes/oauth-client-metadata.js +15 -0
- package/dist/routes/oauth-management.js +45 -107
- package/dist/routes/oauth.js +136 -57
- package/dist/routes/operator.js +3 -3
- package/dist/routes/shared.d.ts +25 -64
- package/dist/routes/shared.js +160 -80
- package/dist/routes/skills.js +30 -0
- package/dist/routes/ui-config.js +225 -0
- package/dist/routes/ui-data.js +40 -35
- package/dist/routes/ui.js +66 -56
- package/dist/runtime/admission.js +4 -2
- package/dist/runtime/call-admission.js +3 -1
- package/dist/runtime/connector-scope.js +1 -4
- package/dist/runtime/run.js +10 -39
- package/dist/runtime/services.js +12 -117
- package/dist/runtime/shared-read.js +1 -3
- package/dist/runtime/storage.js +8 -1
- package/dist/sent-secrets.d.ts +52 -0
- package/dist/sent-secrets.js +474 -0
- package/dist/server.js +28 -71
- package/dist/skills.js +406 -174
- package/dist/sqlite.d.ts +48 -0
- package/dist/sqlite.js +166 -0
- package/dist/storage/keys.js +428 -0
- package/dist/storage/memory.js +7 -0
- package/dist/storage/sql.d.ts +66 -0
- package/dist/storage/sql.js +534 -0
- package/dist/timeout.js +4 -2
- package/dist/tool-name.js +17 -0
- package/dist/tool-safety.d.ts +9 -35
- package/dist/tool-safety.js +20 -40
- package/dist/types.d.ts +320 -54
- package/dist/types.js +0 -1
- package/dist/ui.d.ts +7 -19
- package/dist/ui.js +76 -90
- package/dist/url-safety.js +3 -6
- package/dist/usage-guide.js +137 -0
- package/dist/validate.d.ts +7 -0
- package/dist/validate.js +309 -47
- package/dist/version.d.ts +1 -7
- package/dist/version.js +3 -7
- package/dist/worker.d.ts +11 -0
- package/dist/worker.js +434 -0
- package/documentation/architecture.md +665 -230
- package/documentation/auth.md +962 -458
- package/documentation/code-mode.md +501 -312
- package/documentation/meta-tools.md +449 -200
- package/documentation/operator-tests.md +93 -0
- package/documentation/provider-migration-0.29.md +60 -0
- package/examples/worker/AGENTS.md +34 -12
- package/examples/worker/README.md +286 -255
- package/examples/worker/kv-to-d1.wrangler.jsonc +26 -0
- package/examples/worker/scripts/copy-kv-to-d1.mjs +162 -0
- package/examples/worker/src/connecta.config.ts +151 -0
- package/examples/worker/src/index.ts +14 -197
- package/examples/worker/wrangler.jsonc +15 -35
- package/package.json +125 -35
- package/templates/node/.dockerignore +1 -2
- package/templates/node/.env.example +20 -21
- package/templates/node/AGENTS.md +21 -17
- package/templates/node/Dockerfile +3 -5
- package/templates/node/README.md +133 -58
- package/templates/node/docker-compose.yml +11 -12
- package/templates/node/package.json +4 -2
- package/templates/node/src/connecta.config.ts +119 -0
- package/templates/node/src/index.ts +9 -154
- package/templates/node/src/provision-token.ts +17 -0
- package/AGENTS.md +0 -170
- package/dist/artifacts/connector.d.ts +0 -58
- package/dist/artifacts/connector.js +0 -730
- package/dist/artifacts/document.js +0 -86
- package/dist/artifacts/guide.js +0 -140
- package/dist/artifacts/html-scan.js +0 -329
- package/dist/artifacts/json.js +0 -78
- package/dist/artifacts/kv-store.d.ts +0 -20
- package/dist/artifacts/kv-store.js +0 -140
- package/dist/artifacts/markdown.js +0 -478
- package/dist/artifacts/module.d.ts +0 -37
- package/dist/artifacts/module.js +0 -66
- package/dist/artifacts/operations.d.ts +0 -197
- package/dist/artifacts/operations.js +0 -1002
- package/dist/artifacts/refresh.d.ts +0 -55
- package/dist/artifacts/refresh.js +0 -236
- package/dist/artifacts/routes.js +0 -206
- package/dist/artifacts/types.d.ts +0 -214
- package/dist/artifacts/types.js +0 -22
- package/dist/artifacts/validate.d.ts +0 -62
- package/dist/artifacts/validate.js +0 -651
- package/dist/artifacts.d.ts +0 -6
- package/dist/artifacts.js +0 -9
- package/dist/auth/bearer.d.ts +0 -11
- package/dist/auth/bearer.js +0 -50
- package/dist/providers/linear.js +0 -217
- package/dist/providers/mixpanel.js +0 -247
- package/dist/providers/revenuecat.js +0 -317
- package/dist/providers/stripe.js +0 -253
- package/dist/providers/vercel.js +0 -1253
- package/dist/storage/file.d.ts +0 -15
- package/dist/storage/file.js +0 -455
- package/ethos.md +0 -93
- package/examples/worker/src/cloudflare-kv.ts +0 -43
- package/examples/worker/src/d1-activity-row.ts +0 -155
- package/examples/worker/src/d1-activity.ts +0 -147
- package/examples/worker/src/d1-storage.ts +0 -138
- package/examples/worker/src/r2-artifact-blobs.ts +0 -29
- package/templates/node/src/file-activity.ts +0 -182
package/dist/auth/bearer.js
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { assertNoRetiredToolkitOptions } from "../retired-toolkits.js";
|
|
2
|
-
const encoder = new TextEncoder();
|
|
3
|
-
/** Constant-time byte comparison. Differing lengths still iterate to reduce leak. */
|
|
4
|
-
function timingSafeEqual(a, b) {
|
|
5
|
-
if (a.length !== b.length) {
|
|
6
|
-
let r = 1;
|
|
7
|
-
const n = Math.max(a.length, b.length);
|
|
8
|
-
for (let i = 0; i < n; i++)
|
|
9
|
-
r |= (a[i] ?? 0) ^ (b[i] ?? 0);
|
|
10
|
-
return false;
|
|
11
|
-
}
|
|
12
|
-
let r = 0;
|
|
13
|
-
for (let i = 0; i < a.length; i++)
|
|
14
|
-
r |= (a[i] ?? 0) ^ (b[i] ?? 0);
|
|
15
|
-
return r === 0;
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Static bearer-token inbound auth. Constant-time compares the Bearer token
|
|
19
|
-
* against `secret`. Checked before interactive providers in the server; a
|
|
20
|
-
* mismatch falls through so another configured provider can admit the request.
|
|
21
|
-
*/
|
|
22
|
-
export function bearerToken(secret, options = {}) {
|
|
23
|
-
assertNoRetiredToolkitOptions("bearerToken", options);
|
|
24
|
-
const secretBytes = encoder.encode(secret);
|
|
25
|
-
return {
|
|
26
|
-
kind: "bearer",
|
|
27
|
-
authorize(request) {
|
|
28
|
-
const header = request.headers.get("authorization") ?? "";
|
|
29
|
-
const match = /^Bearer\s+(.+)$/i.exec(header);
|
|
30
|
-
if (match && timingSafeEqual(encoder.encode(match[1]), secretBytes)) {
|
|
31
|
-
return {
|
|
32
|
-
ok: true,
|
|
33
|
-
...(options.subjectId ? { subjectId: options.subjectId } : {}),
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
return {
|
|
37
|
-
ok: false,
|
|
38
|
-
response: new Response(JSON.stringify({ error: "unauthorized" }), {
|
|
39
|
-
status: 401,
|
|
40
|
-
headers: {
|
|
41
|
-
"Content-Type": "application/json",
|
|
42
|
-
// A configured secret has no OAuth metadata or issuer to
|
|
43
|
-
// advertise; interactive adapters own resource discovery.
|
|
44
|
-
"WWW-Authenticate": "Bearer",
|
|
45
|
-
},
|
|
46
|
-
}),
|
|
47
|
-
};
|
|
48
|
-
},
|
|
49
|
-
};
|
|
50
|
-
}
|
package/dist/providers/linear.js
DELETED
|
@@ -1,217 +0,0 @@
|
|
|
1
|
-
import { remoteMcp, withCredentialDefaults, } from "../connectors/remote-mcp.js";
|
|
2
|
-
import { vettedCatalog, withVettedCatalog } from "../catalog-drift.js";
|
|
3
|
-
import { defined } from "../connectors/api.js";
|
|
4
|
-
/**
|
|
5
|
-
* Linear publishes two hosted endpoints. `read-only` is not a client-side
|
|
6
|
-
* filter: it advertises the `read` scope alone, so the token minted for it
|
|
7
|
-
* cannot reach Linear's write APIs at all. The deprecated `/sse` transport is
|
|
8
|
-
* deliberately absent — it now answers 404.
|
|
9
|
-
*/
|
|
10
|
-
export const LINEAR_MCP_ENDPOINTS = {
|
|
11
|
-
"read-write": "https://mcp.linear.app/mcp",
|
|
12
|
-
"read-only": "https://mcp.linear.app/mcp/readonly",
|
|
13
|
-
};
|
|
14
|
-
/**
|
|
15
|
-
* Reviewed reads, listed by name (P5). The list is a superset: Linear's hosted
|
|
16
|
-
* `tools/list` varies by plan and enabled features, so a name this workspace
|
|
17
|
-
* never returns costs nothing while an unlisted new one fails closed.
|
|
18
|
-
*/
|
|
19
|
-
const READ_ONLY_TOOLS = new Set([
|
|
20
|
-
// Issues
|
|
21
|
-
"list_issues",
|
|
22
|
-
"get_issue",
|
|
23
|
-
"list_issue_statuses",
|
|
24
|
-
"get_issue_status",
|
|
25
|
-
"list_issue_labels",
|
|
26
|
-
// Projects
|
|
27
|
-
"list_projects",
|
|
28
|
-
"get_project",
|
|
29
|
-
"list_project_labels",
|
|
30
|
-
// Milestones
|
|
31
|
-
"list_milestones",
|
|
32
|
-
"get_milestone",
|
|
33
|
-
// Initiatives
|
|
34
|
-
"list_initiatives",
|
|
35
|
-
"get_initiative",
|
|
36
|
-
"list_initiative_labels",
|
|
37
|
-
// Cycles
|
|
38
|
-
"list_cycles",
|
|
39
|
-
// Comments
|
|
40
|
-
"list_comments",
|
|
41
|
-
// Documents
|
|
42
|
-
"list_documents",
|
|
43
|
-
"get_document",
|
|
44
|
-
// Teams and users
|
|
45
|
-
"list_teams",
|
|
46
|
-
"get_team",
|
|
47
|
-
"list_users",
|
|
48
|
-
"get_user",
|
|
49
|
-
"get_workspace",
|
|
50
|
-
// Templates
|
|
51
|
-
"list_templates",
|
|
52
|
-
"get_template",
|
|
53
|
-
// Status updates
|
|
54
|
-
"get_status_updates",
|
|
55
|
-
// Releases
|
|
56
|
-
"list_release_pipelines",
|
|
57
|
-
"list_releases",
|
|
58
|
-
"get_release",
|
|
59
|
-
"list_release_notes",
|
|
60
|
-
"get_release_note",
|
|
61
|
-
// Code review
|
|
62
|
-
"list_diffs",
|
|
63
|
-
"get_diff",
|
|
64
|
-
"get_diff_threads",
|
|
65
|
-
// Attachments
|
|
66
|
-
"get_attachment",
|
|
67
|
-
// Agent skills
|
|
68
|
-
"list_agent_skills",
|
|
69
|
-
"get_agent_skill",
|
|
70
|
-
// Documentation search
|
|
71
|
-
"search_documentation",
|
|
72
|
-
// Customer requests (plan-gated)
|
|
73
|
-
"list_customers",
|
|
74
|
-
// Markdown helper. It reads images out of content it is handed and touches
|
|
75
|
-
// no workspace state; the hosted server ships it annotated `readOnlyHint:
|
|
76
|
-
// true, idempotentHint: true`, and a fill-in classification agrees rather
|
|
77
|
-
// than argues.
|
|
78
|
-
"extract_images",
|
|
79
|
-
]);
|
|
80
|
-
/**
|
|
81
|
-
* Reviewed writes with their destructive verdict. Every `save_*` is destructive
|
|
82
|
-
* because Linear's `save_*` tools are upserts: omitting a record id creates,
|
|
83
|
-
* supplying one overwrites in place, and the schema cannot tell them apart. The
|
|
84
|
-
* genuine creates — the `create_*_label` and attachment tools — stay additive,
|
|
85
|
-
* since `readOnlyHint: false` already routes them through the approval path.
|
|
86
|
-
*/
|
|
87
|
-
const WRITE_TOOLS = new Map([
|
|
88
|
-
// Issues
|
|
89
|
-
["save_issue", "destructive"],
|
|
90
|
-
["create_issue_label", "additive"],
|
|
91
|
-
// Projects
|
|
92
|
-
["save_project", "destructive"],
|
|
93
|
-
// Milestones
|
|
94
|
-
["save_milestone", "destructive"],
|
|
95
|
-
// Initiatives
|
|
96
|
-
["save_initiative", "destructive"],
|
|
97
|
-
["create_initiative_label", "additive"],
|
|
98
|
-
// Comments
|
|
99
|
-
["save_comment", "destructive"],
|
|
100
|
-
["delete_comment", "destructive"],
|
|
101
|
-
// Documents
|
|
102
|
-
["save_document", "destructive"],
|
|
103
|
-
// Status updates
|
|
104
|
-
["save_status_update", "destructive"],
|
|
105
|
-
["delete_status_update", "destructive"],
|
|
106
|
-
// Releases
|
|
107
|
-
["save_release", "destructive"],
|
|
108
|
-
["save_release_note", "destructive"],
|
|
109
|
-
// Code review
|
|
110
|
-
["save_diff_comment", "destructive"],
|
|
111
|
-
["resolve_diff_thread", "destructive"],
|
|
112
|
-
["delete_diff_comment", "destructive"],
|
|
113
|
-
["submit_diff_review", "destructive"],
|
|
114
|
-
["merge_diff", "destructive"],
|
|
115
|
-
// Attachments
|
|
116
|
-
["prepare_attachment_upload", "additive"],
|
|
117
|
-
["create_attachment_from_upload", "additive"],
|
|
118
|
-
["create_attachment", "additive"],
|
|
119
|
-
["delete_attachment", "destructive"],
|
|
120
|
-
// Explicit issue access. Both halves change an existing issue's audience.
|
|
121
|
-
["share_issue", "destructive"],
|
|
122
|
-
["unshare_issue", "destructive"],
|
|
123
|
-
// Customer requests (plan-gated)
|
|
124
|
-
["save_customer", "destructive"],
|
|
125
|
-
["delete_customer", "destructive"],
|
|
126
|
-
["save_customer_need", "destructive"],
|
|
127
|
-
["delete_customer_need", "destructive"],
|
|
128
|
-
]);
|
|
129
|
-
/**
|
|
130
|
-
* One release-reviewed manifest, used both to classify a live tool and as the
|
|
131
|
-
* baseline the drift check compares against, so the annotation a caller gets
|
|
132
|
-
* and the verdict a check reads can never disagree. Drift must surface as an
|
|
133
|
-
* unclassified tool on the approval path (P5), never a quiet re-guess.
|
|
134
|
-
*/
|
|
135
|
-
export const LINEAR_VETTED_CATALOG = vettedCatalog({
|
|
136
|
-
reads: READ_ONLY_TOOLS,
|
|
137
|
-
writes: WRITE_TOOLS,
|
|
138
|
-
});
|
|
139
|
-
function usageGuide(purpose, access, instructions) {
|
|
140
|
-
const accountInstructions = instructions?.trim();
|
|
141
|
-
// Leads the guide because discovery summarizes a connector by its first
|
|
142
|
-
// content line: whether this connection can write at all is the one thing an
|
|
143
|
-
// agent must know before it opens the guide, and `search_tools` shows the
|
|
144
|
-
// summary without the description.
|
|
145
|
-
const accessNote = access === "read-only"
|
|
146
|
-
? "Read-only connection: bound to Linear's read-only endpoint, whose token is scope-limited downstream, so every write fails at Linear regardless of arguments. Route writes to a connector configured for read-write access."
|
|
147
|
-
: "Read-write connection: treat every `save_`, `create_`, `delete_`, `resolve_`, `submit_`, and `merge_` operation as a write. Connecta routes the maintained write catalog through `call_destructive_tool`; newly added tools also fail closed until a release classifies them.";
|
|
148
|
-
return `# Linear usage
|
|
149
|
-
|
|
150
|
-
${accessNote}
|
|
151
|
-
|
|
152
|
-
Workspace purpose: ${purpose}
|
|
153
|
-
|
|
154
|
-
- Resolve identity before acting. \`list_teams\`, \`list_users\`, \`list_projects\`, \`list_issue_statuses\`, and \`list_issue_labels\` return the ids that create and update arguments expect; do not guess a team, status, label, or assignee id.
|
|
155
|
-
- Issues carry a human identifier like \`ENG-123\` — team key, dash, number — alongside a UUID. Use the identifier the request gave you and resolve it with \`get_issue\` or \`list_issues\` when a tool wants an id; never fabricate an identifier or renumber one.
|
|
156
|
-
- \`save_*\` tools are upserts: omit the record id to create, supply it to update in place. Read the record first when you mean to update, and send only the fields you intend to change — an upsert overwrites what you restate.
|
|
157
|
-
- Labels are the exception to that naming: \`create_issue_label\` and \`create_initiative_label\` only ever create.
|
|
158
|
-
- Projects, milestones, and initiatives nest: initiatives contain projects, projects contain milestones and issues, and cycles are per-team time boxes. Scope a search by team or project rather than listing the workspace and filtering afterwards.
|
|
159
|
-
- List tools paginate with a cursor. Thread the returned cursor for the next page instead of raising the page size, and reduce pages inside \`execute_code\` before returning them.
|
|
160
|
-
- This workspace's catalog is not the whole product. Customer requests, releases, and code review are plan- and feature-gated, so search the catalog for what this connector actually exposes rather than assuming a tool exists.
|
|
161
|
-
- Linear meters the underlying API per user per hour, shared with everything else that credential does. Reuse discovery results within a run and avoid speculative fan-out.
|
|
162
|
-
- An \`auth_required\` failure means this connector's Linear authorization is missing or expired: run \`authorize_connector\` for this connector id, then retry the same call unchanged.
|
|
163
|
-
${accountInstructions
|
|
164
|
-
? `\n## Workspace instructions\n\n${accountInstructions}\n`
|
|
165
|
-
: ""}`;
|
|
166
|
-
}
|
|
167
|
-
/** A maintained Linear hosted-MCP connection. */
|
|
168
|
-
export function linear(id, options) {
|
|
169
|
-
const purpose = options.purpose.trim();
|
|
170
|
-
if (!purpose) {
|
|
171
|
-
throw new Error("linear() requires a non-empty workspace purpose.");
|
|
172
|
-
}
|
|
173
|
-
const access = options.access;
|
|
174
|
-
if (access !== "read-write" && access !== "read-only") {
|
|
175
|
-
throw new Error(`linear("${id}") requires access "read-write" or "read-only".`);
|
|
176
|
-
}
|
|
177
|
-
const connector = remoteMcp(id, {
|
|
178
|
-
url: LINEAR_MCP_ENDPOINTS[access],
|
|
179
|
-
...(options.authScope ? { authScope: options.authScope } : {}),
|
|
180
|
-
// The title is what browse-time discovery renders; a read-only connection
|
|
181
|
-
// says so there rather than only in a description the caller may not see.
|
|
182
|
-
title: options.title ?? (access === "read-only" ? "Linear (read-only)" : "Linear"),
|
|
183
|
-
description: access === "read-only"
|
|
184
|
-
? `Linear issue tracking and project planning (read-only) — ${purpose}`
|
|
185
|
-
: `Linear issue tracking and project planning — ${purpose}`,
|
|
186
|
-
// Linear's MCP endpoint takes an API key the same way it takes an OAuth
|
|
187
|
-
// token — `Authorization: Bearer <yourtoken>` — so only the slot copy is
|
|
188
|
-
// provider-specific and the bearer framing default stands. The bare-header
|
|
189
|
-
// convention belongs to Linear's GraphQL API, not to this endpoint.
|
|
190
|
-
auth: withCredentialDefaults(options.auth ?? { type: "oauth" }, {
|
|
191
|
-
credential: {
|
|
192
|
-
label: "Personal API key",
|
|
193
|
-
description: "A Linear personal API key. It carries the issuing user's full workspace access and is stored encrypted; the read-only endpoint still limits what it can reach.",
|
|
194
|
-
placeholder: "lin_api_…",
|
|
195
|
-
},
|
|
196
|
-
}),
|
|
197
|
-
requireHttps: true,
|
|
198
|
-
usageGuide: {
|
|
199
|
-
content: usageGuide(purpose, access, options.instructions),
|
|
200
|
-
// Explicit rather than derived. The derived summary would truncate the
|
|
201
|
-
// access note mid-sentence at 120 characters, and the one thing a
|
|
202
|
-
// browsing agent must not get wrong is whether this connection can write
|
|
203
|
-
// at all ([#342](https://github.com/zackbart/connecta/issues/342)).
|
|
204
|
-
summary: access === "read-only"
|
|
205
|
-
? "Read-only: every write fails at Linear. Id resolution, upsert semantics, and cursor paging."
|
|
206
|
-
: "Read-write. Id resolution, `save_*` upsert semantics, plan-gated areas, and cursor paging.",
|
|
207
|
-
// Not `required`. Linear's own schemas describe each call correctly; the
|
|
208
|
-
// guide adds cross-tool sequence advice that is worth reading before a
|
|
209
|
-
// write, not worth loading before every read.
|
|
210
|
-
},
|
|
211
|
-
...defined({
|
|
212
|
-
callAdmission: options.callAdmission,
|
|
213
|
-
maxResultBytes: options.maxResultBytes,
|
|
214
|
-
}),
|
|
215
|
-
});
|
|
216
|
-
return withVettedCatalog(connector, LINEAR_VETTED_CATALOG);
|
|
217
|
-
}
|
|
@@ -1,247 +0,0 @@
|
|
|
1
|
-
import { remoteMcp, withCredentialDefaults, } from "../connectors/remote-mcp.js";
|
|
2
|
-
import { vettedCatalog, withVettedCatalog } from "../catalog-drift.js";
|
|
3
|
-
import { defined } from "../connectors/api.js";
|
|
4
|
-
export const MIXPANEL_MCP_ENDPOINTS = {
|
|
5
|
-
us: "https://mcp.mixpanel.com/mcp",
|
|
6
|
-
eu: "https://mcp-eu.mixpanel.com/mcp",
|
|
7
|
-
in: "https://mcp-in.mixpanel.com/mcp",
|
|
8
|
-
};
|
|
9
|
-
/** Tools whose official contract is observational rather than mutating. */
|
|
10
|
-
const READ_ONLY_TOOLS = new Set([
|
|
11
|
-
"Run-Query",
|
|
12
|
-
"Get-Query-Schema",
|
|
13
|
-
"Get-Report",
|
|
14
|
-
"Display-Query",
|
|
15
|
-
"List-Dashboards",
|
|
16
|
-
"Get-Dashboard",
|
|
17
|
-
"Get-Business-Context",
|
|
18
|
-
"Get-Projects",
|
|
19
|
-
"List-Organizations",
|
|
20
|
-
"Get-Events",
|
|
21
|
-
"List-Properties",
|
|
22
|
-
"Get-Property-Values",
|
|
23
|
-
"Search-Entities",
|
|
24
|
-
"Get-Issues",
|
|
25
|
-
"Get-Lexicon-URL",
|
|
26
|
-
"Find-Duplicate-Groups",
|
|
27
|
-
"Get-Custom-Property",
|
|
28
|
-
"Get-Cohort",
|
|
29
|
-
"List-Cohorts",
|
|
30
|
-
"Describe-Cohort-Schema",
|
|
31
|
-
"Get-Lookup-Table",
|
|
32
|
-
"Get-Metric",
|
|
33
|
-
"List-Metrics",
|
|
34
|
-
"Get-User-Replays-Data",
|
|
35
|
-
"List-Experiments",
|
|
36
|
-
"Get-Experiment",
|
|
37
|
-
"Get-Experiment-Setup-Guidance",
|
|
38
|
-
"Get-Experiment-Results-Interpretation-Guidance",
|
|
39
|
-
"Explain-Experiment-Health-Check",
|
|
40
|
-
"Run-Experiment-Pre-Launch-Checks",
|
|
41
|
-
"Search-Prior-Experiments",
|
|
42
|
-
"List-Feature-Flags",
|
|
43
|
-
"Get-Feature-Flag",
|
|
44
|
-
"Get-Feature-Flag-Setup-Guidance",
|
|
45
|
-
"Get-Feature-Flag-Lifecycle-Guidance",
|
|
46
|
-
]);
|
|
47
|
-
/**
|
|
48
|
-
* Reviewed writes, each with its destructive verdict (P5). Additive writes stay
|
|
49
|
-
* `additive` because `readOnlyHint: false` already routes them through the
|
|
50
|
-
* approval path, and claiming destruction only inflates the copy a host shows a
|
|
51
|
-
* human. Anything unlisted is not read-only, so a new name fails closed.
|
|
52
|
-
*/
|
|
53
|
-
const WRITE_TOOLS = new Map([
|
|
54
|
-
["Create-Dashboard", "additive"],
|
|
55
|
-
["Update-Dashboard", "destructive"],
|
|
56
|
-
["Duplicate-Dashboard", "additive"],
|
|
57
|
-
["Delete-Dashboard", "destructive"],
|
|
58
|
-
["Edit-Event", "destructive"],
|
|
59
|
-
["Edit-Property", "destructive"],
|
|
60
|
-
["Bulk-Edit-Events", "destructive"],
|
|
61
|
-
["Bulk-Edit-Properties", "destructive"],
|
|
62
|
-
["Create-Tag", "additive"],
|
|
63
|
-
["Rename-Tag", "destructive"],
|
|
64
|
-
["Delete-Tag", "destructive"],
|
|
65
|
-
["Dismiss-Issues", "destructive"],
|
|
66
|
-
["Update-Business-Context", "destructive"],
|
|
67
|
-
["Dismiss-Duplicate-Group", "destructive"],
|
|
68
|
-
["Merge-Group", "destructive"],
|
|
69
|
-
["Create-Custom-Property", "additive"],
|
|
70
|
-
["Update-Custom-Property", "destructive"],
|
|
71
|
-
["Create-Cohort", "additive"],
|
|
72
|
-
["Update-Cohort", "destructive"],
|
|
73
|
-
["Delete-Cohort", "destructive"],
|
|
74
|
-
["Create-Lookup-Table", "additive"],
|
|
75
|
-
["Update-Lookup-Table", "destructive"],
|
|
76
|
-
["Create-Metric", "additive"],
|
|
77
|
-
["Update-Metric", "destructive"],
|
|
78
|
-
["Create-Experiment", "additive"],
|
|
79
|
-
["Update-Experiment", "destructive"],
|
|
80
|
-
["Create-Feature-Flag", "additive"],
|
|
81
|
-
["Update-Feature-Flag", "destructive"],
|
|
82
|
-
// Applies generated names and descriptions to existing Lexicon events.
|
|
83
|
-
["Fill-Event-Metadata", "destructive"],
|
|
84
|
-
]);
|
|
85
|
-
/** Live US hosted-MCP schemas reviewed read-only on 2026-08-30 (#395, #512). */
|
|
86
|
-
const MIXPANEL_SCHEMA_DIGESTS = {
|
|
87
|
-
"Bulk-Edit-Events": "sha256:94512138df153de95436371f5a313e32b97faffebda3be6c0c69d09d1ff2b340",
|
|
88
|
-
"Bulk-Edit-Properties": "sha256:93481eb896ded45b623c678612e2156439efbaad5b4d660da1f2b087e7409ee3",
|
|
89
|
-
"Create-Cohort": "sha256:ea687f4bc607f8bfb5b1949e060239d6f7d629d3ec80fb0b72eae6cc6156ed03",
|
|
90
|
-
"Create-Custom-Property": "sha256:d22818b812f3fd0e785a5bbbee26cf099eaa911d5b6f383f94cf458a2ed26294",
|
|
91
|
-
"Create-Dashboard": "sha256:bd3b6e5134d27dafb04ccdf04d19e54dd23e6e2dc16989e418006e484268037b",
|
|
92
|
-
"Create-Experiment": "sha256:1cfc2edeb2ac2d329a531d2095671a0653ab5b94b9e233b34268ff29a48c5ac5",
|
|
93
|
-
"Create-Feature-Flag": "sha256:3460d11d726727349cac62db5c19915ab589b7f1d8387042f0a3783356b252c4",
|
|
94
|
-
"Create-Lookup-Table": "sha256:c2fefa33a4f19fc65f394fecdc7126cab0ae874f7c97018cf003d8462a049e4c",
|
|
95
|
-
"Create-Metric": "sha256:315766d0c197d87bb44aedd16732f6e69fbfc93661d1fcfc177cadc1751f26ce",
|
|
96
|
-
"Create-Tag": "sha256:f99b6faad422aa6142d20d0aa4bdec1074e96a8ec45e35573e86d84b01df1d3b",
|
|
97
|
-
"Delete-Cohort": "sha256:e18c500459edd9c2b6a614a3f6c97b668786be9abf72929a0a50086bdadb1dae",
|
|
98
|
-
"Delete-Dashboard": "sha256:3a04594218b491743240e6970f677ed8ed132237d933efe30e97bdc41eb1ab6f",
|
|
99
|
-
"Delete-Tag": "sha256:5f6cc58ada5d2796f124e15883fe05061d03f9129414f4c8e10a0ec463f17807",
|
|
100
|
-
"Describe-Cohort-Schema": "sha256:775dbb8bb71ad3fa39ba35ca3a2683dfd88120f7af84a968531609c5a12de537",
|
|
101
|
-
"Dismiss-Duplicate-Group": "sha256:4e39c6f9bb83ed54020097f6cf34507a5288de2c1ce333456c84682bb5986bc4",
|
|
102
|
-
"Dismiss-Issues": "sha256:9c1f4901eca53f58d16feee126868d23c6ed1f5fad72344f86ea9965385b8644",
|
|
103
|
-
"Display-Query": "sha256:d0776167b8a20898c1ff580ca9517da8dea6b827c64e10b9fa01ae1a3c2db95f",
|
|
104
|
-
"Duplicate-Dashboard": "sha256:9738db7495d29034df966423df3c9d4b16ac3a8254c8473bf1e85a467fe9cf4e",
|
|
105
|
-
"Edit-Event": "sha256:28c47da0b56f57da0f11eb11435441a39ecd5175600f854442744c66a379ef93",
|
|
106
|
-
"Edit-Property": "sha256:11975587d2a566edc468db7cb24df70167d12068f30c1fe52c84f543cf4e2399",
|
|
107
|
-
"Explain-Experiment-Health-Check": "sha256:a50b1263247012dc78521bf6c1dd18584a7b08d46221a444b1ca49c81d3286e5",
|
|
108
|
-
"Fill-Event-Metadata": "sha256:53accc988f216bdd5d7a259d731f6df82549e4e6146b191f1815a0d1a72a1abe",
|
|
109
|
-
"Find-Duplicate-Groups": "sha256:8f944cef9a147eab3c51bfcf1b873cef1409e5a6c21565d34e7ed20d23dcebb7",
|
|
110
|
-
"Get-Business-Context": "sha256:309f5ba864c90132061096b4f0ebc1e78544a6486bac3a45bd661d16bcab2b6c",
|
|
111
|
-
"Get-Cohort": "sha256:e18c500459edd9c2b6a614a3f6c97b668786be9abf72929a0a50086bdadb1dae",
|
|
112
|
-
"Get-Custom-Property": "sha256:d1cbce906cee66d422846c8ef1a745bbeac2c058ecad6b1ee8dcdd2120fa86be",
|
|
113
|
-
"Get-Dashboard": "sha256:56659fa3277723b75e24f3b4ca142ac9cd62120fb97e6c9252c221d00cdf8509",
|
|
114
|
-
"Get-Events": "sha256:d206fe30ab47d64bf6090bffdb4d119a80cfc2a35963bbe7fd52d56060090ded",
|
|
115
|
-
"Get-Experiment": "sha256:ab685aa985aa2ec36d9cbeb1b3c1ef298b020e552e8fdce12e75abbeb4706f2b",
|
|
116
|
-
"Get-Experiment-Results-Interpretation-Guidance": "sha256:e517d9759f66f4a7ad15b0b67ffaabfb605e80949afcf41d007dfafd8f3e9574",
|
|
117
|
-
"Get-Experiment-Setup-Guidance": "sha256:e517d9759f66f4a7ad15b0b67ffaabfb605e80949afcf41d007dfafd8f3e9574",
|
|
118
|
-
"Get-Feature-Flag": "sha256:129de58b379ffba272bdbcee2b5759262e586dd415edc2067a69e9844d4d0877",
|
|
119
|
-
"Get-Feature-Flag-Lifecycle-Guidance": "sha256:e517d9759f66f4a7ad15b0b67ffaabfb605e80949afcf41d007dfafd8f3e9574",
|
|
120
|
-
"Get-Feature-Flag-Setup-Guidance": "sha256:e517d9759f66f4a7ad15b0b67ffaabfb605e80949afcf41d007dfafd8f3e9574",
|
|
121
|
-
"Get-Issues": "sha256:cf172ef18f37504a758c825c7bd4bc23fd98c3421655754dccd8e5ee2d700a10",
|
|
122
|
-
"Get-Lexicon-URL": "sha256:c6456d5c4a38ba069a2caa6cdac651be9d86d47bc6efb3316a893c7336d0e2bc",
|
|
123
|
-
"Get-Lookup-Table": "sha256:061602b283461f083bbd74348c264f802cb21c4fe6d961241c7090895a8334ac",
|
|
124
|
-
"Get-Metric": "sha256:eef10dd9ca25a63a63775565cbc4f2261b289dec526aa33df0f318eefbc96c46",
|
|
125
|
-
"Get-Projects": "sha256:d23d07a777441f04b128f08a2c30a6e8a1573d203f8a1ad7788bc1fd57a9cbbf",
|
|
126
|
-
"Get-Property-Values": "sha256:0cd487c9b92a187b21f456de3c785bb631aa30cba702785c9ff158608883a6bb",
|
|
127
|
-
"Get-Query-Schema": "sha256:8fea929d2ad4f8fed6c47116ff0eaa6f964b3ddd4685e482b68a8dac0231af73",
|
|
128
|
-
"Get-Report": "sha256:a99ba2af1ab57c1d5a606dbd7701968aa430ab23f5969f356a4c41f345dba041",
|
|
129
|
-
"Get-User-Replays-Data": "sha256:5df287735478a67489075b0c7c9d8c07097abe67408d06743c7fb9be43c6e024",
|
|
130
|
-
"List-Cohorts": "sha256:fd04778d60a027cfd777b40f36fbb037ba070661e149b2fce35a14865cada2db",
|
|
131
|
-
"List-Dashboards": "sha256:994c1c9fc87a4f1f00a677b856a44bad028252d283bd8e647ae157683fc89ea2",
|
|
132
|
-
"List-Experiments": "sha256:26a3f3e0b4e52135d74335dd769103303071fc48c15b1df40efd2dfa5a353848",
|
|
133
|
-
"List-Feature-Flags": "sha256:75fc1ff14f3d3faedb8e00c6563d151de397d584429764fd0c332f6a84f6993c",
|
|
134
|
-
"List-Metrics": "sha256:341710bebabb82112e80eb521d9d5cdb3bca024699b3aa795874d3549a315042",
|
|
135
|
-
"List-Organizations": "sha256:e4c23f123dde073e00038d92ebd53f45157c83a4d3a2ff686ab1b66c859f4a11",
|
|
136
|
-
"List-Properties": "sha256:52b38861df076119dfefe0128cf9819868336bf60e090f63c80da734877a69fe",
|
|
137
|
-
"Merge-Group": "sha256:a3b215a5be70305c2f02439513bee76ae3947da14e2a9e5b6ff0afb9ad3d4dcd",
|
|
138
|
-
"Rename-Tag": "sha256:a7e20e79ecd6ca7edca104fa1030e059ffae8962bf084d4a384c012ac9bbf087",
|
|
139
|
-
"Run-Experiment-Pre-Launch-Checks": "sha256:f6b5d85f75450b76fda9c7ef441f190fd45fcaeaff4cc3c30a6d1bee76e4c706",
|
|
140
|
-
"Run-Query": "sha256:0eb7d52343f6137275a02c2d7bb02dafdbfd25bd6f9067395eb689492d835466",
|
|
141
|
-
"Search-Entities": "sha256:86cfa1d3bf7f17a70ad07264d7b1d16c83480e40996e8d847911fe8bde13e35e",
|
|
142
|
-
"Search-Prior-Experiments": "sha256:847d1dcefaf6dc5e7ea967476f464a4d678a06b5e7d437dfb11ad4af2e56620f",
|
|
143
|
-
"Update-Business-Context": "sha256:0d21290053b6d532386c3c83d60cd78013a7109492c02ba2e7822716f2cde027",
|
|
144
|
-
"Update-Cohort": "sha256:ebe0d5afcc00e23eef55f079cd1816c851c2c647dff9565b7045f1f1615663f2",
|
|
145
|
-
"Update-Custom-Property": "sha256:781aaaab41c1ab5958062dc393d02b1df2ef2a09a28d3c4f21ae3177f4f53c86",
|
|
146
|
-
"Update-Dashboard": "sha256:2cc179ba75eda476ba7488f01503d947f023a4460aa98c4806ef0ab10c3b3ce8",
|
|
147
|
-
"Update-Experiment": "sha256:3ea3902555c146f45127fc563b36ffb7ff04b7594765dac9ae98cc09dc432808",
|
|
148
|
-
"Update-Feature-Flag": "sha256:9b34b19164168938d08a75d268c9becf8d189c85a1789a45061ae304041faf7c",
|
|
149
|
-
"Update-Lookup-Table": "sha256:ef28f1ec9c9484a7a53b5e2b6659e70f79a8e71e55bda17025aa4ab3c23b6a63",
|
|
150
|
-
"Update-Metric": "sha256:739bb6abdab19282afd4a6644a96183daabe9098a5322c44a77b840608a5ee9d",
|
|
151
|
-
};
|
|
152
|
-
/**
|
|
153
|
-
* One release-reviewed manifest, used both to classify a live tool and as the
|
|
154
|
-
* baseline the drift check compares against, so the annotation a caller gets
|
|
155
|
-
* and the verdict a check reads can never disagree. Drift must surface as an
|
|
156
|
-
* unclassified tool on the approval path (P5), never a quiet re-guess.
|
|
157
|
-
*/
|
|
158
|
-
export const MIXPANEL_VETTED_CATALOG = vettedCatalog({
|
|
159
|
-
reads: READ_ONLY_TOOLS,
|
|
160
|
-
writes: WRITE_TOOLS,
|
|
161
|
-
schemaDigests: MIXPANEL_SCHEMA_DIGESTS,
|
|
162
|
-
});
|
|
163
|
-
const REGION_COPY = {
|
|
164
|
-
us: "US",
|
|
165
|
-
eu: "EU",
|
|
166
|
-
in: "India",
|
|
167
|
-
};
|
|
168
|
-
function usageGuide(purpose, region, instructions) {
|
|
169
|
-
const accountInstructions = instructions?.trim();
|
|
170
|
-
// Leads the guide because discovery summarizes a connector by its first
|
|
171
|
-
// content line. A project lives in exactly one residency, so a question
|
|
172
|
-
// pointed at the wrong region does not return fewer rows — it returns
|
|
173
|
-
// nothing, and reads as the project having no data.
|
|
174
|
-
const regionNote = `${REGION_COPY[region]}-residency connection: bound to Mixpanel's ${region} endpoint. A project created in another residency is not reachable from here at all, so an empty result may mean wrong connector rather than no data.`;
|
|
175
|
-
return `# Mixpanel usage
|
|
176
|
-
|
|
177
|
-
${regionNote}
|
|
178
|
-
|
|
179
|
-
Account purpose: ${purpose}
|
|
180
|
-
|
|
181
|
-
- Start with \`Get-Projects\`, then use \`Get-Business-Context\` for the selected project before interpreting its events or metrics.
|
|
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.
|
|
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.
|
|
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.
|
|
191
|
-
- Use \`Get-Report\` when the request names an existing saved report. Use \`Run-Query\` for a new question.
|
|
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.
|
|
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.
|
|
194
|
-
- An \`auth_required\` failure means this connector's Mixpanel 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 Mixpanel's own words instead — read it rather than re-authorizing.
|
|
195
|
-
- Treat every create, update, edit, merge, dismiss, duplicate, or delete operation as a write. Connecta routes the maintained write catalog through \`call_destructive_tool\`; newly added tools also fail closed until classified.
|
|
196
|
-
${accountInstructions
|
|
197
|
-
? `\n## Account instructions\n\n${accountInstructions}\n`
|
|
198
|
-
: ""}`;
|
|
199
|
-
}
|
|
200
|
-
/** A maintained Mixpanel hosted-MCP connection. */
|
|
201
|
-
export function mixpanel(id, options) {
|
|
202
|
-
const purpose = options.purpose.trim();
|
|
203
|
-
if (!purpose) {
|
|
204
|
-
throw new Error("mixpanel() requires a non-empty account purpose.");
|
|
205
|
-
}
|
|
206
|
-
const region = options.region ?? "us";
|
|
207
|
-
if (!(region in MIXPANEL_MCP_ENDPOINTS)) {
|
|
208
|
-
throw new Error(`mixpanel("${id}") region must be "us", "eu", or "in".`);
|
|
209
|
-
}
|
|
210
|
-
const connector = remoteMcp(id, {
|
|
211
|
-
url: MIXPANEL_MCP_ENDPOINTS[region],
|
|
212
|
-
...(options.authScope ? { authScope: options.authScope } : {}),
|
|
213
|
-
// The region rides the title because browse-time discovery renders the
|
|
214
|
-
// title and the guide summary and nothing else, and residency is the fact
|
|
215
|
-
// an agent must not get wrong between two Mixpanel connections.
|
|
216
|
-
title: options.title ?? `Mixpanel (${region})`,
|
|
217
|
-
description: `Mixpanel product analytics (${REGION_COPY[region]} residency) — ${purpose}`,
|
|
218
|
-
// Mixpanel's beta service-account scheme is deliberately not ordinary HTTP
|
|
219
|
-
// Basic: the endpoint wants `Bearer Basic <base64(user:secret)>`. The
|
|
220
|
-
// operator therefore pastes the pair, not an encoded blob, and Connecta
|
|
221
|
-
// does the framing — the same shaping the maintainer drift check applies.
|
|
222
|
-
auth: withCredentialDefaults(options.auth ?? { type: "oauth" }, {
|
|
223
|
-
credential: {
|
|
224
|
-
label: "Service account",
|
|
225
|
-
description: "A Mixpanel service account as `username:secret`. Connecta encodes and frames it the way the hosted endpoint requires; it is stored encrypted and never displayed.",
|
|
226
|
-
placeholder: "username:secret",
|
|
227
|
-
},
|
|
228
|
-
scheme: "Bearer Basic",
|
|
229
|
-
}),
|
|
230
|
-
requireHttps: true,
|
|
231
|
-
usageGuide: {
|
|
232
|
-
content: usageGuide(purpose, region, options.instructions),
|
|
233
|
-
// Explicit rather than derived: the derived summary would truncate the
|
|
234
|
-
// residency note mid-sentence at 120 characters
|
|
235
|
-
// ([#342](https://github.com/zackbart/connecta/issues/342)).
|
|
236
|
-
summary: `${REGION_COPY[region]} residency. Project scoping, id resolution, query-schema-first analysis, plan-gated catalog.`,
|
|
237
|
-
// Not `required`. Mixpanel's own schemas describe each call; the guide
|
|
238
|
-
// carries the project-then-context sequence, which is worth reading
|
|
239
|
-
// before an analysis rather than before every call.
|
|
240
|
-
},
|
|
241
|
-
...defined({
|
|
242
|
-
callAdmission: options.callAdmission,
|
|
243
|
-
maxResultBytes: options.maxResultBytes,
|
|
244
|
-
}),
|
|
245
|
-
});
|
|
246
|
-
return withVettedCatalog(connector, MIXPANEL_VETTED_CATALOG);
|
|
247
|
-
}
|