@zackbart/connecta 0.15.1 → 0.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +40 -20
- package/CHANGELOG.md +653 -0
- package/README.md +25 -5
- package/bin/connecta.mjs +44 -3
- package/dist/access-tokens.d.ts +0 -1
- package/dist/access-tokens.js +0 -1
- package/dist/activity.d.ts +50 -2
- package/dist/activity.js +34 -1
- package/dist/apps-shell.d.ts +0 -1
- package/dist/apps-shell.js +0 -1
- package/dist/auth/bearer.d.ts +0 -1
- package/dist/auth/bearer.js +0 -1
- package/dist/auth/clerk.d.ts +0 -1
- package/dist/auth/clerk.js +45 -9
- package/dist/auth/downstream-oauth.d.ts +0 -1
- package/dist/auth/downstream-oauth.js +0 -1
- package/dist/call-admission.d.ts +0 -1
- package/dist/call-admission.js +0 -1
- package/dist/catalog-drift.d.ts +99 -0
- package/dist/catalog-drift.js +251 -0
- package/dist/catalog-fingerprint.d.ts +0 -1
- package/dist/catalog-fingerprint.js +0 -1
- package/dist/catalog-limits.d.ts +0 -1
- package/dist/catalog-limits.js +0 -1
- package/dist/catalog-service.d.ts +0 -1
- package/dist/catalog-service.js +41 -5
- package/dist/catalog.d.ts +11 -1
- package/dist/catalog.js +20 -1
- package/dist/concurrency.d.ts +0 -1
- package/dist/concurrency.js +0 -1
- package/dist/connector-scope.d.ts +0 -1
- package/dist/connector-scope.js +0 -1
- package/dist/connectors/api.d.ts +29 -21
- package/dist/connectors/api.js +45 -19
- package/dist/connectors/guarded-fetch.d.ts +106 -0
- package/dist/connectors/guarded-fetch.js +289 -0
- package/dist/connectors/remote-mcp.d.ts +0 -1
- package/dist/connectors/remote-mcp.js +0 -1
- package/dist/credentials.d.ts +0 -1
- package/dist/credentials.js +0 -1
- package/dist/errors.d.ts +30 -3
- package/dist/errors.js +1 -1
- package/dist/execute.d.ts +0 -1
- package/dist/execute.js +0 -1
- package/dist/executor-admission.d.ts +11 -1
- package/dist/executor-admission.js +28 -1
- package/dist/executor-result.d.ts +0 -1
- package/dist/executor-result.js +0 -1
- package/dist/executors/quickjs-child.d.ts +0 -1
- package/dist/executors/quickjs-child.js +0 -1
- package/dist/executors/quickjs-protocol.d.ts +0 -1
- package/dist/executors/quickjs-protocol.js +0 -1
- package/dist/executors/quickjs-runtime.d.ts +0 -1
- package/dist/executors/quickjs-runtime.js +0 -1
- package/dist/executors/quickjs.d.ts +0 -1
- package/dist/executors/quickjs.js +2 -1
- package/dist/favicon.d.ts +0 -1
- package/dist/favicon.js +0 -1
- package/dist/index.d.ts +2 -3
- package/dist/index.js +24 -7
- package/dist/invocation.d.ts +0 -1
- package/dist/invocation.js +0 -1
- package/dist/json-schema.d.ts +0 -1
- package/dist/json-schema.js +0 -1
- package/dist/mcp-result.d.ts +0 -1
- package/dist/mcp-result.js +0 -1
- package/dist/meta-tools.d.ts +0 -1
- package/dist/meta-tools.js +0 -1
- package/dist/node.d.ts +0 -1
- package/dist/node.js +0 -1
- package/dist/operator-ui/generated.d.ts +2 -3
- package/dist/operator-ui/generated.js +3 -4
- package/dist/operator-ui/model.d.ts +10 -1
- package/dist/operator-ui/model.js +0 -1
- package/dist/operator-ui/view.d.ts +167 -0
- package/dist/operator-ui/view.js +270 -0
- package/dist/providers/cloudflare.d.ts +0 -1
- package/dist/providers/cloudflare.js +261 -299
- package/dist/providers/linear.d.ts +26 -5
- package/dist/providers/linear.js +32 -61
- package/dist/providers/mixpanel.d.ts +35 -4
- package/dist/providers/mixpanel.js +53 -79
- package/dist/providers/notion.d.ts +0 -1
- package/dist/providers/notion.js +87 -42
- package/dist/providers/stripe.d.ts +13 -1
- package/dist/providers/stripe.js +31 -60
- package/dist/registry.d.ts +34 -2
- package/dist/registry.js +85 -5
- package/dist/retired-toolkits.d.ts +0 -1
- package/dist/retired-toolkits.js +0 -1
- package/dist/routes/access-tokens.d.ts +0 -1
- package/dist/routes/access-tokens.js +0 -1
- package/dist/routes/activity.d.ts +0 -1
- package/dist/routes/activity.js +0 -1
- package/dist/routes/credentials.d.ts +0 -1
- package/dist/routes/credentials.js +0 -1
- package/dist/routes/mcp.d.ts +0 -1
- package/dist/routes/mcp.js +0 -1
- package/dist/routes/oauth.d.ts +0 -1
- package/dist/routes/oauth.js +0 -1
- package/dist/routes/shared.d.ts +2 -1
- package/dist/routes/shared.js +0 -1
- package/dist/routes/ui.d.ts +0 -1
- package/dist/routes/ui.js +0 -1
- package/dist/server.d.ts +0 -1
- package/dist/server.js +11 -1
- package/dist/skills.d.ts +0 -1
- package/dist/skills.js +0 -1
- package/dist/storage/file.d.ts +0 -1
- package/dist/storage/file.js +0 -1
- package/dist/storage/memory.d.ts +0 -1
- package/dist/storage/memory.js +0 -1
- package/dist/timeout.d.ts +0 -1
- package/dist/timeout.js +0 -1
- package/dist/tool-safety.d.ts +0 -1
- package/dist/tool-safety.js +0 -1
- package/dist/types.d.ts +45 -1
- package/dist/types.js +0 -1
- package/dist/ui.d.ts +0 -1
- package/dist/ui.js +13 -137
- package/dist/validate.d.ts +13 -15
- package/dist/validate.js +24 -11
- package/dist/version.d.ts +1 -2
- package/dist/version.js +1 -2
- package/documentation/architecture.md +186 -5
- package/documentation/auth.md +11 -0
- package/documentation/call-admission.md +142 -6
- package/documentation/cloudflare.md +92 -10
- package/documentation/code-first-exploration.md +2 -2
- package/documentation/code-mode.md +14 -14
- package/documentation/connector-guides.md +172 -5
- package/documentation/connectors.md +89 -0
- package/documentation/linear.md +20 -2
- package/documentation/mcp-ui-design.md +2 -2
- package/documentation/meta-tools.md +7 -1
- package/documentation/mixpanel.md +42 -9
- package/documentation/notion.md +23 -2
- package/documentation/operations.md +325 -5
- package/documentation/operator-ui.md +120 -5
- package/documentation/provider-audit.md +160 -0
- package/documentation/provider-conventions.md +667 -0
- package/documentation/request-admission.md +167 -5
- package/documentation/rich-output-design.md +1 -2
- package/documentation/stripe.md +15 -0
- package/documentation/upgrading.md +454 -0
- package/ethos.md +14 -9
- package/examples/worker/README.md +102 -12
- package/examples/worker/src/index.ts +46 -1
- package/examples/worker/wrangler.jsonc +14 -1
- package/package.json +10 -6
- package/templates/node/.dockerignore +10 -0
- package/templates/node/.env.example +40 -3
- package/templates/node/AGENTS.md +16 -1
- package/templates/node/Dockerfile +49 -0
- package/templates/node/README.md +117 -2
- package/templates/node/docker-compose.yml +39 -0
- package/templates/node/package.json +1 -1
- package/templates/node/src/file-activity.ts +182 -0
- package/templates/node/src/index.ts +80 -4
- package/assets/connecta-clay-hero.png +0 -0
- package/dist/access-tokens.d.ts.map +0 -1
- package/dist/access-tokens.js.map +0 -1
- package/dist/activity.d.ts.map +0 -1
- package/dist/activity.js.map +0 -1
- package/dist/apps-shell.d.ts.map +0 -1
- package/dist/apps-shell.js.map +0 -1
- package/dist/auth/bearer.d.ts.map +0 -1
- package/dist/auth/bearer.js.map +0 -1
- package/dist/auth/clerk.d.ts.map +0 -1
- package/dist/auth/clerk.js.map +0 -1
- package/dist/auth/downstream-oauth.d.ts.map +0 -1
- package/dist/auth/downstream-oauth.js.map +0 -1
- package/dist/call-admission.d.ts.map +0 -1
- package/dist/call-admission.js.map +0 -1
- package/dist/catalog-fingerprint.d.ts.map +0 -1
- package/dist/catalog-fingerprint.js.map +0 -1
- package/dist/catalog-limits.d.ts.map +0 -1
- package/dist/catalog-limits.js.map +0 -1
- package/dist/catalog-service.d.ts.map +0 -1
- package/dist/catalog-service.js.map +0 -1
- package/dist/catalog.d.ts.map +0 -1
- package/dist/catalog.js.map +0 -1
- package/dist/concurrency.d.ts.map +0 -1
- package/dist/concurrency.js.map +0 -1
- package/dist/connector-scope.d.ts.map +0 -1
- package/dist/connector-scope.js.map +0 -1
- package/dist/connectors/api.d.ts.map +0 -1
- package/dist/connectors/api.js.map +0 -1
- package/dist/connectors/remote-mcp.d.ts.map +0 -1
- package/dist/connectors/remote-mcp.js.map +0 -1
- package/dist/credentials.d.ts.map +0 -1
- package/dist/credentials.js.map +0 -1
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js.map +0 -1
- package/dist/execute.d.ts.map +0 -1
- package/dist/execute.js.map +0 -1
- package/dist/executor-admission.d.ts.map +0 -1
- package/dist/executor-admission.js.map +0 -1
- package/dist/executor-result.d.ts.map +0 -1
- package/dist/executor-result.js.map +0 -1
- package/dist/executors/quickjs-child.d.ts.map +0 -1
- package/dist/executors/quickjs-child.js.map +0 -1
- package/dist/executors/quickjs-protocol.d.ts.map +0 -1
- package/dist/executors/quickjs-protocol.js.map +0 -1
- package/dist/executors/quickjs-runtime.d.ts.map +0 -1
- package/dist/executors/quickjs-runtime.js.map +0 -1
- package/dist/executors/quickjs.d.ts.map +0 -1
- package/dist/executors/quickjs.js.map +0 -1
- package/dist/favicon.d.ts.map +0 -1
- package/dist/favicon.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/invocation.d.ts.map +0 -1
- package/dist/invocation.js.map +0 -1
- package/dist/json-schema.d.ts.map +0 -1
- package/dist/json-schema.js.map +0 -1
- package/dist/mcp-result.d.ts.map +0 -1
- package/dist/mcp-result.js.map +0 -1
- package/dist/meta-tools.d.ts.map +0 -1
- package/dist/meta-tools.js.map +0 -1
- package/dist/node.d.ts.map +0 -1
- package/dist/node.js.map +0 -1
- package/dist/operator-ui/generated.d.ts.map +0 -1
- package/dist/operator-ui/generated.js.map +0 -1
- package/dist/operator-ui/model.d.ts.map +0 -1
- package/dist/operator-ui/model.js.map +0 -1
- package/dist/providers/cloudflare.d.ts.map +0 -1
- package/dist/providers/cloudflare.js.map +0 -1
- package/dist/providers/linear.d.ts.map +0 -1
- package/dist/providers/linear.js.map +0 -1
- package/dist/providers/mixpanel.d.ts.map +0 -1
- package/dist/providers/mixpanel.js.map +0 -1
- package/dist/providers/notion.d.ts.map +0 -1
- package/dist/providers/notion.js.map +0 -1
- package/dist/providers/stripe.d.ts.map +0 -1
- package/dist/providers/stripe.js.map +0 -1
- package/dist/registry.d.ts.map +0 -1
- package/dist/registry.js.map +0 -1
- package/dist/retired-toolkits.d.ts.map +0 -1
- package/dist/retired-toolkits.js.map +0 -1
- package/dist/routes/access-tokens.d.ts.map +0 -1
- package/dist/routes/access-tokens.js.map +0 -1
- package/dist/routes/activity.d.ts.map +0 -1
- package/dist/routes/activity.js.map +0 -1
- package/dist/routes/credentials.d.ts.map +0 -1
- package/dist/routes/credentials.js.map +0 -1
- package/dist/routes/mcp.d.ts.map +0 -1
- package/dist/routes/mcp.js.map +0 -1
- package/dist/routes/oauth.d.ts.map +0 -1
- package/dist/routes/oauth.js.map +0 -1
- package/dist/routes/shared.d.ts.map +0 -1
- package/dist/routes/shared.js.map +0 -1
- package/dist/routes/ui.d.ts.map +0 -1
- package/dist/routes/ui.js.map +0 -1
- package/dist/server.d.ts.map +0 -1
- package/dist/server.js.map +0 -1
- package/dist/skills.d.ts.map +0 -1
- package/dist/skills.js.map +0 -1
- package/dist/storage/file.d.ts.map +0 -1
- package/dist/storage/file.js.map +0 -1
- package/dist/storage/memory.d.ts.map +0 -1
- package/dist/storage/memory.js.map +0 -1
- package/dist/timeout.d.ts.map +0 -1
- package/dist/timeout.js.map +0 -1
- package/dist/tool-safety.d.ts.map +0 -1
- package/dist/tool-safety.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/ui.d.ts.map +0 -1
- package/dist/ui.js.map +0 -1
- package/dist/validate.d.ts.map +0 -1
- package/dist/validate.js.map +0 -1
- package/dist/version.d.ts.map +0 -1
- package/dist/version.js.map +0 -1
- package/examples/node/README.md +0 -52
- package/examples/node/src/index.ts +0 -71
- package/src/access-tokens.ts +0 -289
- package/src/activity.ts +0 -234
- package/src/apps-shell.ts +0 -370
- package/src/auth/bearer.ts +0 -61
- package/src/auth/clerk.ts +0 -553
- package/src/auth/downstream-oauth.ts +0 -575
- package/src/call-admission.ts +0 -521
- package/src/catalog-fingerprint.ts +0 -52
- package/src/catalog-limits.ts +0 -11
- package/src/catalog-service.ts +0 -1153
- package/src/catalog.ts +0 -790
- package/src/concurrency.ts +0 -39
- package/src/connector-scope.ts +0 -66
- package/src/connectors/api.ts +0 -159
- package/src/connectors/remote-mcp.ts +0 -1090
- package/src/credentials.ts +0 -428
- package/src/errors.ts +0 -364
- package/src/execute.ts +0 -1406
- package/src/executor-admission.ts +0 -328
- package/src/executor-result.ts +0 -107
- package/src/executors/quickjs-child.ts +0 -172
- package/src/executors/quickjs-protocol.ts +0 -99
- package/src/executors/quickjs-runtime.ts +0 -470
- package/src/executors/quickjs.ts +0 -776
- package/src/favicon.ts +0 -53
- package/src/index.ts +0 -666
- package/src/invocation.ts +0 -655
- package/src/json-schema.ts +0 -11
- package/src/mcp-result.ts +0 -43
- package/src/meta-tools.ts +0 -1607
- package/src/node.ts +0 -206
- package/src/operator-ui/browser.css +0 -423
- package/src/operator-ui/browser.ts +0 -1281
- package/src/operator-ui/generated.ts +0 -4
- package/src/operator-ui/model.ts +0 -111
- package/src/providers/cloudflare.ts +0 -3999
- package/src/providers/linear.ts +0 -302
- package/src/providers/mixpanel.ts +0 -229
- package/src/providers/notion.ts +0 -1879
- package/src/providers/stripe.ts +0 -307
- package/src/registry.ts +0 -1085
- package/src/retired-toolkits.ts +0 -14
- package/src/routes/access-tokens.ts +0 -115
- package/src/routes/activity.ts +0 -215
- package/src/routes/credentials.ts +0 -254
- package/src/routes/mcp.ts +0 -429
- package/src/routes/oauth.ts +0 -322
- package/src/routes/shared.ts +0 -247
- package/src/routes/ui.ts +0 -152
- package/src/server.ts +0 -195
- package/src/skills.ts +0 -271
- package/src/storage/file.ts +0 -123
- package/src/storage/memory.ts +0 -44
- package/src/timeout.ts +0 -84
- package/src/tool-safety.ts +0 -15
- package/src/types.ts +0 -523
- package/src/ui.ts +0 -744
- package/src/validate.ts +0 -387
- package/src/version.ts +0 -7
package/src/providers/linear.ts
DELETED
|
@@ -1,302 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
remoteMcp,
|
|
3
|
-
type RemoteMcpAuth,
|
|
4
|
-
} from "../connectors/remote-mcp.js";
|
|
5
|
-
import type {
|
|
6
|
-
Connector,
|
|
7
|
-
ConnectorCallAdmissionPolicy,
|
|
8
|
-
ToolDef,
|
|
9
|
-
} from "../types.js";
|
|
10
|
-
|
|
11
|
-
/** Which of Linear's two hosted MCP endpoints this connection is bound to. */
|
|
12
|
-
export type LinearAccess = "read-write" | "read-only";
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Linear publishes two hosted endpoints. `read-only` is not a client-side
|
|
16
|
-
* filter: it advertises the `read` scope alone, so the token minted for it
|
|
17
|
-
* cannot reach Linear's write APIs at all. The deprecated `/sse` transport is
|
|
18
|
-
* deliberately absent — it now answers 404.
|
|
19
|
-
*/
|
|
20
|
-
export const LINEAR_MCP_ENDPOINTS: Readonly<Record<LinearAccess, string>> = {
|
|
21
|
-
"read-write": "https://mcp.linear.app/mcp",
|
|
22
|
-
"read-only": "https://mcp.linear.app/mcp/readonly",
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export interface LinearOptions {
|
|
26
|
-
/**
|
|
27
|
-
* Human-readable display name; defaults to "Linear", or
|
|
28
|
-
* "Linear (read-only)" when `access` is `"read-only"`.
|
|
29
|
-
*/
|
|
30
|
-
title?: string;
|
|
31
|
-
/** Which workspace this is and what decisions it answers. */
|
|
32
|
-
purpose: string;
|
|
33
|
-
/**
|
|
34
|
-
* Endpoint selection. Defaults to `"read-write"`. `"read-only"` binds the
|
|
35
|
-
* connection to Linear's read-only endpoint, whose token is scope-limited
|
|
36
|
-
* downstream — a stronger guarantee than any annotation Connecta applies.
|
|
37
|
-
*/
|
|
38
|
-
access?: LinearAccess;
|
|
39
|
-
/** OAuth by default; static headers support a Linear personal API key. */
|
|
40
|
-
auth?: RemoteMcpAuth;
|
|
41
|
-
/** Workspace-specific conventions appended to the maintained provider guide. */
|
|
42
|
-
instructions?: string;
|
|
43
|
-
/** Connector-specific inline result limit; omit to inherit the deployment. */
|
|
44
|
-
maxResultBytes?: number;
|
|
45
|
-
/**
|
|
46
|
-
* Optional per-runtime call-admission policy. Deliberately not defaulted:
|
|
47
|
-
* Linear documents no MCP-specific limit, and the underlying API limit is
|
|
48
|
-
* per user per hour, varies by credential type, and is raised dynamically
|
|
49
|
-
* for workspace-level OAuth apps. A hardcoded per-runtime ceiling would
|
|
50
|
-
* either throttle a healthy deployment or fail to protect a busy one, so
|
|
51
|
-
* the number stays with the operator who knows the workspace.
|
|
52
|
-
*/
|
|
53
|
-
callAdmission?: ConnectorCallAdmissionPolicy;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Tools whose contract is observational rather than mutating.
|
|
58
|
-
*
|
|
59
|
-
* Linear's hosted catalog is not a fixed set — it varies by workspace plan and
|
|
60
|
-
* enabled features (customer requests, releases, and code review are gated),
|
|
61
|
-
* so this list is a superset of what any one workspace lists. A name here that
|
|
62
|
-
* the workspace never returns costs nothing; a real read missing from it merely
|
|
63
|
-
* fails closed. Only a write mistakenly listed here would be a safety bug,
|
|
64
|
-
* which is why ambiguous helpers stay out.
|
|
65
|
-
*/
|
|
66
|
-
const READ_ONLY_TOOLS = new Set([
|
|
67
|
-
// Issues
|
|
68
|
-
"list_issues",
|
|
69
|
-
"get_issue",
|
|
70
|
-
"list_issue_statuses",
|
|
71
|
-
"get_issue_status",
|
|
72
|
-
"list_issue_labels",
|
|
73
|
-
// Projects
|
|
74
|
-
"list_projects",
|
|
75
|
-
"get_project",
|
|
76
|
-
"list_project_labels",
|
|
77
|
-
// Milestones
|
|
78
|
-
"list_milestones",
|
|
79
|
-
"get_milestone",
|
|
80
|
-
// Initiatives
|
|
81
|
-
"list_initiatives",
|
|
82
|
-
"get_initiative",
|
|
83
|
-
"list_initiative_labels",
|
|
84
|
-
// Cycles
|
|
85
|
-
"list_cycles",
|
|
86
|
-
// Comments
|
|
87
|
-
"list_comments",
|
|
88
|
-
// Documents
|
|
89
|
-
"list_documents",
|
|
90
|
-
"get_document",
|
|
91
|
-
// Teams and users
|
|
92
|
-
"list_teams",
|
|
93
|
-
"get_team",
|
|
94
|
-
"list_users",
|
|
95
|
-
"get_user",
|
|
96
|
-
// Status updates
|
|
97
|
-
"get_status_updates",
|
|
98
|
-
// Releases
|
|
99
|
-
"list_release_pipelines",
|
|
100
|
-
"list_releases",
|
|
101
|
-
"get_release",
|
|
102
|
-
"list_release_notes",
|
|
103
|
-
"get_release_note",
|
|
104
|
-
// Code review
|
|
105
|
-
"list_diffs",
|
|
106
|
-
"get_diff",
|
|
107
|
-
"get_diff_threads",
|
|
108
|
-
// Attachments
|
|
109
|
-
"get_attachment",
|
|
110
|
-
// Agent skills
|
|
111
|
-
"list_agent_skills",
|
|
112
|
-
"get_agent_skill",
|
|
113
|
-
// Documentation search
|
|
114
|
-
"search_documentation",
|
|
115
|
-
// Customer requests (plan-gated)
|
|
116
|
-
"list_customers",
|
|
117
|
-
// Markdown helper. It reads images out of content it is handed and touches
|
|
118
|
-
// no workspace state; the hosted server ships it annotated `readOnlyHint:
|
|
119
|
-
// true, idempotentHint: true`, and a fill-in classification agrees rather
|
|
120
|
-
// than argues.
|
|
121
|
-
"extract_images",
|
|
122
|
-
]);
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* The maintained write catalog. `"destructive"` tools modify or remove state
|
|
126
|
-
* that already exists; `"additive"` ones only bring something new into being.
|
|
127
|
-
* Both leave the read-only path — the distinction only decides whether the
|
|
128
|
-
* connection asserts `destructiveHint`, which shapes the host's approval copy.
|
|
129
|
-
*
|
|
130
|
-
* Linear's `save_*` tools are upserts: passing an existing record's id updates
|
|
131
|
-
* it in place. An upsert can therefore overwrite, so every `save_*` is
|
|
132
|
-
* destructive even though some calls only create. The `create_*_label` tools
|
|
133
|
-
* are the genuine creates.
|
|
134
|
-
*/
|
|
135
|
-
const WRITE_TOOLS: ReadonlyMap<string, "additive" | "destructive"> = new Map([
|
|
136
|
-
// Issues
|
|
137
|
-
["save_issue", "destructive"],
|
|
138
|
-
["create_issue_label", "additive"],
|
|
139
|
-
// Projects
|
|
140
|
-
["save_project", "destructive"],
|
|
141
|
-
// Milestones
|
|
142
|
-
["save_milestone", "destructive"],
|
|
143
|
-
// Initiatives
|
|
144
|
-
["save_initiative", "destructive"],
|
|
145
|
-
["create_initiative_label", "additive"],
|
|
146
|
-
// Comments
|
|
147
|
-
["save_comment", "destructive"],
|
|
148
|
-
["delete_comment", "destructive"],
|
|
149
|
-
// Documents
|
|
150
|
-
["save_document", "destructive"],
|
|
151
|
-
// Status updates
|
|
152
|
-
["save_status_update", "destructive"],
|
|
153
|
-
["delete_status_update", "destructive"],
|
|
154
|
-
// Releases
|
|
155
|
-
["save_release", "destructive"],
|
|
156
|
-
["save_release_note", "destructive"],
|
|
157
|
-
// Code review
|
|
158
|
-
["save_diff_comment", "destructive"],
|
|
159
|
-
["resolve_diff_thread", "destructive"],
|
|
160
|
-
["delete_diff_comment", "destructive"],
|
|
161
|
-
["submit_diff_review", "destructive"],
|
|
162
|
-
["merge_diff", "destructive"],
|
|
163
|
-
// Attachments
|
|
164
|
-
["prepare_attachment_upload", "additive"],
|
|
165
|
-
["create_attachment_from_upload", "additive"],
|
|
166
|
-
["create_attachment", "additive"],
|
|
167
|
-
["delete_attachment", "destructive"],
|
|
168
|
-
// Customer requests (plan-gated)
|
|
169
|
-
["save_customer", "destructive"],
|
|
170
|
-
["delete_customer", "destructive"],
|
|
171
|
-
["save_customer_need", "destructive"],
|
|
172
|
-
["delete_customer_need", "destructive"],
|
|
173
|
-
]);
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* Fill in downstream silence; keep reviewed destructive tools fail-closed.
|
|
177
|
-
*
|
|
178
|
-
* Silence is what a vetted classification is for, and an explicit downstream
|
|
179
|
-
* annotation otherwise wins in both directions. `destructiveHint: true` or
|
|
180
|
-
* `readOnlyHint: false` on an allowlisted read name is the downstream telling
|
|
181
|
-
* us this release's allowlist is stale; `readOnlyHint: true` on a name no
|
|
182
|
-
* release has classified says the same thing from the other side. The single
|
|
183
|
-
* place a vetted verdict still overrides the downstream is a name this release
|
|
184
|
-
* reviewed and filed destructive: there connecta knows what the tool does, and
|
|
185
|
-
* a claim to the contrary is a downstream bug rather than news
|
|
186
|
-
* ([#310](https://github.com/zackbart/connecta/issues/310),
|
|
187
|
-
* [#315](https://github.com/zackbart/connecta/issues/315)).
|
|
188
|
-
*/
|
|
189
|
-
function vettedSafety(definition: ToolDef): ToolDef {
|
|
190
|
-
const downstream = definition.annotations ?? {};
|
|
191
|
-
if (READ_ONLY_TOOLS.has(definition.name)) {
|
|
192
|
-
if (
|
|
193
|
-
downstream.destructiveHint === true ||
|
|
194
|
-
downstream.readOnlyHint === false
|
|
195
|
-
) {
|
|
196
|
-
return definition;
|
|
197
|
-
}
|
|
198
|
-
return {
|
|
199
|
-
...definition,
|
|
200
|
-
annotations: {
|
|
201
|
-
...downstream,
|
|
202
|
-
readOnlyHint: true,
|
|
203
|
-
destructiveHint: downstream.destructiveHint ?? false,
|
|
204
|
-
},
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
if (WRITE_TOOLS.get(definition.name) === "destructive") {
|
|
208
|
-
return {
|
|
209
|
-
...definition,
|
|
210
|
-
annotations: {
|
|
211
|
-
...downstream,
|
|
212
|
-
readOnlyHint: false,
|
|
213
|
-
destructiveHint: true,
|
|
214
|
-
},
|
|
215
|
-
};
|
|
216
|
-
}
|
|
217
|
-
// Maintained additive creates and tools this release has never seen land
|
|
218
|
-
// here alike. Fill-in only: a silent tool is not read-only, so drift still
|
|
219
|
-
// fails closed onto `call_destructive_tool`, and neither population gets a
|
|
220
|
-
// `destructiveHint` it has not earned. A tool that arrives explicitly
|
|
221
|
-
// read-only keeps that annotation — on a name no release has reviewed, the
|
|
222
|
-
// downstream's own word is the only evidence there is, and rewriting it
|
|
223
|
-
// would be an overrule rather than a fill-in.
|
|
224
|
-
return {
|
|
225
|
-
...definition,
|
|
226
|
-
annotations: {
|
|
227
|
-
...downstream,
|
|
228
|
-
readOnlyHint: downstream.readOnlyHint ?? false,
|
|
229
|
-
},
|
|
230
|
-
};
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
function usageGuide(
|
|
234
|
-
purpose: string,
|
|
235
|
-
access: LinearAccess,
|
|
236
|
-
instructions: string | undefined,
|
|
237
|
-
): string {
|
|
238
|
-
const accountInstructions = instructions?.trim();
|
|
239
|
-
// Leads the guide because discovery summarizes a connector by its first
|
|
240
|
-
// content line: whether this connection can write at all is the one thing an
|
|
241
|
-
// agent must know before it opens the guide, and `search_tools` shows the
|
|
242
|
-
// summary without the description.
|
|
243
|
-
const accessNote =
|
|
244
|
-
access === "read-only"
|
|
245
|
-
? "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."
|
|
246
|
-
: "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.";
|
|
247
|
-
return `# Linear usage
|
|
248
|
-
|
|
249
|
-
${accessNote}
|
|
250
|
-
|
|
251
|
-
Workspace purpose: ${purpose}
|
|
252
|
-
|
|
253
|
-
- 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.
|
|
254
|
-
- 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.
|
|
255
|
-
- \`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.
|
|
256
|
-
- Labels are the exception to that naming: \`create_issue_label\` and \`create_initiative_label\` only ever create.
|
|
257
|
-
- 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.
|
|
258
|
-
- 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.
|
|
259
|
-
- 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.
|
|
260
|
-
- 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.
|
|
261
|
-
- 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.
|
|
262
|
-
${
|
|
263
|
-
accountInstructions
|
|
264
|
-
? `\n## Workspace instructions\n\n${accountInstructions}\n`
|
|
265
|
-
: ""
|
|
266
|
-
}`;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
/** A maintained Linear hosted-MCP connection. */
|
|
270
|
-
export function linear(id: string, options: LinearOptions): Connector {
|
|
271
|
-
const purpose = options.purpose.trim();
|
|
272
|
-
if (!purpose) {
|
|
273
|
-
throw new Error("linear() requires a non-empty workspace purpose.");
|
|
274
|
-
}
|
|
275
|
-
const access = options.access ?? "read-write";
|
|
276
|
-
const connector = remoteMcp(id, {
|
|
277
|
-
url: LINEAR_MCP_ENDPOINTS[access],
|
|
278
|
-
// The title is what browse-time discovery renders; a read-only connection
|
|
279
|
-
// says so there rather than only in a description the caller may not see.
|
|
280
|
-
title:
|
|
281
|
-
options.title ?? (access === "read-only" ? "Linear (read-only)" : "Linear"),
|
|
282
|
-
description:
|
|
283
|
-
access === "read-only"
|
|
284
|
-
? `Linear issue tracking and project planning (read-only) — ${purpose}`
|
|
285
|
-
: `Linear issue tracking and project planning — ${purpose}`,
|
|
286
|
-
auth: options.auth ?? { type: "oauth" },
|
|
287
|
-
requireHttps: true,
|
|
288
|
-
usageGuide: usageGuide(purpose, access, options.instructions),
|
|
289
|
-
...(options.callAdmission !== undefined
|
|
290
|
-
? { callAdmission: options.callAdmission }
|
|
291
|
-
: {}),
|
|
292
|
-
...(options.maxResultBytes !== undefined
|
|
293
|
-
? { maxResultBytes: options.maxResultBytes }
|
|
294
|
-
: {}),
|
|
295
|
-
});
|
|
296
|
-
return {
|
|
297
|
-
...connector,
|
|
298
|
-
async listTools(ctx) {
|
|
299
|
-
return (await connector.listTools(ctx)).map(vettedSafety);
|
|
300
|
-
},
|
|
301
|
-
};
|
|
302
|
-
}
|
|
@@ -1,229 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
remoteMcp,
|
|
3
|
-
type RemoteMcpAuth,
|
|
4
|
-
} from "../connectors/remote-mcp.js";
|
|
5
|
-
import type {
|
|
6
|
-
Connector,
|
|
7
|
-
ConnectorCallAdmissionPolicy,
|
|
8
|
-
ToolDef,
|
|
9
|
-
} from "../types.js";
|
|
10
|
-
|
|
11
|
-
export type MixpanelRegion = "us" | "eu" | "in";
|
|
12
|
-
|
|
13
|
-
export const MIXPANEL_MCP_ENDPOINTS: Readonly<
|
|
14
|
-
Record<MixpanelRegion, string>
|
|
15
|
-
> = {
|
|
16
|
-
us: "https://mcp.mixpanel.com/mcp",
|
|
17
|
-
eu: "https://mcp-eu.mixpanel.com/mcp",
|
|
18
|
-
in: "https://mcp-in.mixpanel.com/mcp",
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export interface MixpanelOptions {
|
|
22
|
-
/** Human-readable display name; defaults to "Mixpanel". */
|
|
23
|
-
title?: string;
|
|
24
|
-
/** Who should use this account and for what decisions. */
|
|
25
|
-
purpose: string;
|
|
26
|
-
/** Mixpanel data residency region. Defaults to "us". */
|
|
27
|
-
region?: MixpanelRegion;
|
|
28
|
-
/** OAuth by default; static headers support Mixpanel service accounts. */
|
|
29
|
-
auth?: RemoteMcpAuth;
|
|
30
|
-
/** Account-specific conventions appended to the maintained provider guide. */
|
|
31
|
-
instructions?: string;
|
|
32
|
-
/** Connector-specific inline result limit; omit to inherit the deployment. */
|
|
33
|
-
maxResultBytes?: number;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// Budget-only: a rejection computes its own retry-after from the window, and
|
|
37
|
-
// declaring `retryAfterMs` here would be a queue setting without a queue —
|
|
38
|
-
// which the admission controller refuses at construction.
|
|
39
|
-
const MIXPANEL_ADMISSION: ConnectorCallAdmissionPolicy = {
|
|
40
|
-
rules: [
|
|
41
|
-
{
|
|
42
|
-
budget: {
|
|
43
|
-
kind: "rolling-window",
|
|
44
|
-
maxCalls: 600,
|
|
45
|
-
windowMs: 3_600_000,
|
|
46
|
-
},
|
|
47
|
-
},
|
|
48
|
-
],
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
/** Tools whose official contract is observational rather than mutating. */
|
|
52
|
-
const READ_ONLY_TOOLS = new Set([
|
|
53
|
-
"Run-Query",
|
|
54
|
-
"Get-Query-Schema",
|
|
55
|
-
"Get-Report",
|
|
56
|
-
"Display-Query",
|
|
57
|
-
"List-Dashboards",
|
|
58
|
-
"Get-Dashboard",
|
|
59
|
-
"Get-Business-Context",
|
|
60
|
-
"Get-Projects",
|
|
61
|
-
"List-Organizations",
|
|
62
|
-
"Get-Events",
|
|
63
|
-
"List-Properties",
|
|
64
|
-
"Get-Property-Values",
|
|
65
|
-
"Search-Entities",
|
|
66
|
-
"Get-Issues",
|
|
67
|
-
"Get-Lexicon-URL",
|
|
68
|
-
"Find-Duplicate-Groups",
|
|
69
|
-
"Get-Custom-Property",
|
|
70
|
-
"Get-Cohort",
|
|
71
|
-
"List-Cohorts",
|
|
72
|
-
"Describe-Cohort-Schema",
|
|
73
|
-
"Get-Lookup-Table",
|
|
74
|
-
"Get-Metric",
|
|
75
|
-
"List-Metrics",
|
|
76
|
-
"Get-User-Replays-Data",
|
|
77
|
-
"List-Experiments",
|
|
78
|
-
"Get-Experiment",
|
|
79
|
-
"Get-Experiment-Setup-Guidance",
|
|
80
|
-
"Get-Experiment-Results-Interpretation-Guidance",
|
|
81
|
-
"Explain-Experiment-Health-Check",
|
|
82
|
-
"Run-Experiment-Pre-Launch-Checks",
|
|
83
|
-
"Search-Prior-Experiments",
|
|
84
|
-
"List-Feature-Flags",
|
|
85
|
-
"Get-Feature-Flag",
|
|
86
|
-
"Get-Feature-Flag-Setup-Guidance",
|
|
87
|
-
"Get-Feature-Flag-Lifecycle-Guidance",
|
|
88
|
-
]);
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* The maintained write catalog. `"destructive"` tools modify or remove state
|
|
92
|
-
* that already exists; `"additive"` ones only bring something new into being.
|
|
93
|
-
* Both leave the read-only path — the distinction only decides whether the
|
|
94
|
-
* connection asserts `destructiveHint`, which shapes the host's approval copy.
|
|
95
|
-
*/
|
|
96
|
-
const WRITE_TOOLS: ReadonlyMap<string, "additive" | "destructive"> = new Map([
|
|
97
|
-
["Create-Dashboard", "additive"],
|
|
98
|
-
["Update-Dashboard", "destructive"],
|
|
99
|
-
["Duplicate-Dashboard", "additive"],
|
|
100
|
-
["Delete-Dashboard", "destructive"],
|
|
101
|
-
["Edit-Event", "destructive"],
|
|
102
|
-
["Edit-Property", "destructive"],
|
|
103
|
-
["Bulk-Edit-Events", "destructive"],
|
|
104
|
-
["Bulk-Edit-Properties", "destructive"],
|
|
105
|
-
["Create-Tag", "additive"],
|
|
106
|
-
["Rename-Tag", "destructive"],
|
|
107
|
-
["Delete-Tag", "destructive"],
|
|
108
|
-
["Dismiss-Issues", "destructive"],
|
|
109
|
-
["Update-Business-Context", "destructive"],
|
|
110
|
-
["Dismiss-Duplicate-Group", "destructive"],
|
|
111
|
-
["Merge-Group", "destructive"],
|
|
112
|
-
["Create-Custom-Property", "additive"],
|
|
113
|
-
["Update-Custom-Property", "destructive"],
|
|
114
|
-
["Create-Cohort", "additive"],
|
|
115
|
-
["Update-Cohort", "destructive"],
|
|
116
|
-
["Delete-Cohort", "destructive"],
|
|
117
|
-
["Create-Lookup-Table", "additive"],
|
|
118
|
-
["Update-Lookup-Table", "destructive"],
|
|
119
|
-
["Create-Metric", "additive"],
|
|
120
|
-
["Update-Metric", "destructive"],
|
|
121
|
-
["Create-Experiment", "additive"],
|
|
122
|
-
["Update-Experiment", "destructive"],
|
|
123
|
-
["Create-Feature-Flag", "additive"],
|
|
124
|
-
["Update-Feature-Flag", "destructive"],
|
|
125
|
-
]);
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Fill in downstream silence; keep reviewed destructive tools fail-closed.
|
|
129
|
-
*
|
|
130
|
-
* Silence is what a vetted classification is for, and an explicit downstream
|
|
131
|
-
* annotation otherwise wins in both directions. `destructiveHint: true` or
|
|
132
|
-
* `readOnlyHint: false` on an allowlisted read name is the downstream telling
|
|
133
|
-
* us this release's allowlist is stale; `readOnlyHint: true` on a name no
|
|
134
|
-
* release has classified says the same thing from the other side. The single
|
|
135
|
-
* place a vetted verdict still overrides the downstream is a name this release
|
|
136
|
-
* reviewed and filed destructive: there connecta knows what the tool does, and
|
|
137
|
-
* a claim to the contrary is a downstream bug rather than news
|
|
138
|
-
* ([#310](https://github.com/zackbart/connecta/issues/310),
|
|
139
|
-
* [#315](https://github.com/zackbart/connecta/issues/315)).
|
|
140
|
-
*/
|
|
141
|
-
function vettedSafety(definition: ToolDef): ToolDef {
|
|
142
|
-
const downstream = definition.annotations ?? {};
|
|
143
|
-
if (READ_ONLY_TOOLS.has(definition.name)) {
|
|
144
|
-
if (
|
|
145
|
-
downstream.destructiveHint === true ||
|
|
146
|
-
downstream.readOnlyHint === false
|
|
147
|
-
) {
|
|
148
|
-
return definition;
|
|
149
|
-
}
|
|
150
|
-
return {
|
|
151
|
-
...definition,
|
|
152
|
-
annotations: {
|
|
153
|
-
...downstream,
|
|
154
|
-
readOnlyHint: true,
|
|
155
|
-
destructiveHint: downstream.destructiveHint ?? false,
|
|
156
|
-
},
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
if (WRITE_TOOLS.get(definition.name) === "destructive") {
|
|
160
|
-
return {
|
|
161
|
-
...definition,
|
|
162
|
-
annotations: {
|
|
163
|
-
...downstream,
|
|
164
|
-
readOnlyHint: false,
|
|
165
|
-
destructiveHint: true,
|
|
166
|
-
},
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
// Maintained additive creates and tools this release has never seen land
|
|
170
|
-
// here alike. Fill-in only: a silent tool is not read-only, so drift still
|
|
171
|
-
// fails closed onto `call_destructive_tool`, and neither population gets a
|
|
172
|
-
// `destructiveHint` it has not earned. A tool that arrives explicitly
|
|
173
|
-
// read-only keeps that annotation — on a name no release has reviewed, the
|
|
174
|
-
// downstream's own word is the only evidence there is, and rewriting it
|
|
175
|
-
// would be an overrule rather than a fill-in.
|
|
176
|
-
return {
|
|
177
|
-
...definition,
|
|
178
|
-
annotations: {
|
|
179
|
-
...downstream,
|
|
180
|
-
readOnlyHint: downstream.readOnlyHint ?? false,
|
|
181
|
-
},
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
function usageGuide(purpose: string, instructions: string | undefined): string {
|
|
186
|
-
const accountInstructions = instructions?.trim();
|
|
187
|
-
return `# Mixpanel usage
|
|
188
|
-
|
|
189
|
-
Account purpose: ${purpose}
|
|
190
|
-
|
|
191
|
-
- Start with \`Get-Projects\`, then use \`Get-Business-Context\` for the selected project before interpreting its events or metrics.
|
|
192
|
-
- Discover names with \`Get-Events\`, \`List-Properties\`, and \`Get-Property-Values\`; do not guess event or property spelling.
|
|
193
|
-
- For a new analysis, fetch \`Get-Query-Schema\` before \`Run-Query\`. Reduce query results inside \`execute_code\` before returning them.
|
|
194
|
-
- Use \`Get-Report\` when the request names an existing saved report. Use \`Run-Query\` for a new question.
|
|
195
|
-
- Mixpanel limits MCP traffic to 600 requests per user per hour. Reuse discovery results within a run and avoid speculative fan-out.
|
|
196
|
-
- 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.
|
|
197
|
-
${
|
|
198
|
-
accountInstructions
|
|
199
|
-
? `\n## Account instructions\n\n${accountInstructions}\n`
|
|
200
|
-
: ""
|
|
201
|
-
}`;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
/** A maintained Mixpanel hosted-MCP connection. */
|
|
205
|
-
export function mixpanel(id: string, options: MixpanelOptions): Connector {
|
|
206
|
-
const purpose = options.purpose.trim();
|
|
207
|
-
if (!purpose) {
|
|
208
|
-
throw new Error("mixpanel() requires a non-empty account purpose.");
|
|
209
|
-
}
|
|
210
|
-
const region = options.region ?? "us";
|
|
211
|
-
const connector = remoteMcp(id, {
|
|
212
|
-
url: MIXPANEL_MCP_ENDPOINTS[region],
|
|
213
|
-
title: options.title ?? "Mixpanel",
|
|
214
|
-
description: `Mixpanel product analytics — ${purpose}`,
|
|
215
|
-
auth: options.auth ?? { type: "oauth" },
|
|
216
|
-
requireHttps: true,
|
|
217
|
-
callAdmission: MIXPANEL_ADMISSION,
|
|
218
|
-
usageGuide: usageGuide(purpose, options.instructions),
|
|
219
|
-
...(options.maxResultBytes !== undefined
|
|
220
|
-
? { maxResultBytes: options.maxResultBytes }
|
|
221
|
-
: {}),
|
|
222
|
-
});
|
|
223
|
-
return {
|
|
224
|
-
...connector,
|
|
225
|
-
async listTools(ctx) {
|
|
226
|
-
return (await connector.listTools(ctx)).map(vettedSafety);
|
|
227
|
-
},
|
|
228
|
-
};
|
|
229
|
-
}
|