@openhands/extensions 0.18.0 → 0.20.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.
Files changed (62) hide show
  1. package/.agents/skills/custom-codereview-guide.md +7 -0
  2. package/.github/dependabot.yml +24 -0
  3. package/.github/scripts/check_issue_readiness.py +272 -0
  4. package/.github/scripts/check_pr_description.py +226 -0
  5. package/.github/scripts/post-readiness-comment.mjs +184 -0
  6. package/.github/scripts/refresh_linked_pr_checks.py +171 -0
  7. package/.github/workflows/issue-readiness-check.yml +142 -0
  8. package/.github/workflows/pr-description-check.yml +37 -0
  9. package/.pr/custom-automation-event-trigger.png +0 -0
  10. package/.pr/custom-automation-plugin-fields.png +0 -0
  11. package/.pr/custom-automation-prompt-review.png +0 -0
  12. package/.pr/custom-automation-prompt-scheduled.png +0 -0
  13. package/.pr/custom-automation-upload-fields.png +0 -0
  14. package/.release-please-manifest.json +1 -1
  15. package/AGENTS.md +17 -1
  16. package/README.md +10 -2
  17. package/automations/README.md +52 -36
  18. package/automations/bundle-index.js +1 -1
  19. package/automations/catalog/custom-automation/manifest.json +229 -0
  20. package/automations/catalog/github-agents-md-maintainer/manifest.json +5 -0
  21. package/automations/catalog/github-issue-to-pr/manifest.json +6 -1
  22. package/automations/catalog/github-pr-reviewer/manifest.json +6 -1
  23. package/automations/catalog/github-repo-monitor/manifest.json +5 -0
  24. package/automations/catalog/jira-issue-to-bitbucket-pr/manifest.json +23 -0
  25. package/automations/catalog/jira-issue-to-gitlab-mr/manifest.json +23 -0
  26. package/automations/catalog/linear-issue-to-bitbucket-pr/manifest.json +23 -0
  27. package/automations/catalog/linear-issue-to-github-pr/manifest.json +23 -0
  28. package/automations/catalog/linear-issue-to-gitlab-mr/manifest.json +23 -0
  29. package/automations/catalog/news-digest/manifest.json +5 -0
  30. package/automations/catalog/qa-changes/manifest.json +72 -0
  31. package/automations/catalog/slack-github-linear-daily-organization.json +27 -0
  32. package/automations/catalog-index.js +25 -11
  33. package/automations/catalog.schema.json +106 -7
  34. package/automations/index.d.ts +68 -2
  35. package/automations/interface.json +2 -1
  36. package/integrations/catalog/datadog.json +2 -2
  37. package/integrations/catalog/gitlab.json +63 -0
  38. package/integrations/catalog/notion.json +1 -1
  39. package/integrations/catalog-index.js +71 -69
  40. package/integrations/index.d.ts +1 -1
  41. package/marketplaces/openhands-extensions.json +21 -6
  42. package/package.json +1 -1
  43. package/plugins/pr-review/scripts/prompt.py +2 -0
  44. package/pyproject.toml +1 -1
  45. package/python/openhands_extensions/_version.py +1 -1
  46. package/skills/github-pr-reviewer/SKILL.md +2 -1
  47. package/skills/github-pr-reviewer/scripts/main.py +45 -4
  48. package/skills/github-pr-reviewer/tests/test_main.py +74 -0
  49. package/skills/index.js +11 -2
  50. package/skills/openhands-sdk/SKILL.md +1 -0
  51. package/skills/ticket-to-code-change/.plugin/plugin.json +21 -0
  52. package/skills/ticket-to-code-change/README.md +5 -0
  53. package/skills/ticket-to-code-change/SKILL.md +50 -0
  54. package/skills/ticket-to-code-change/commands/ticket-to-code-change-setup.md +8 -0
  55. package/tests/fixtures/automations/custom-automation.json +398 -0
  56. package/tests/fixtures/automations/github-pr-reviewer.json +9 -9
  57. package/tests/test_automation_setup.py +362 -92
  58. package/tests/test_catalogs.py +2 -2
  59. package/tests/test_check_issue_readiness.py +135 -0
  60. package/tests/test_check_pr_description.py +228 -0
  61. package/tests/test_pr_review_prompt.py +10 -0
  62. package/tests/test_refresh_linked_pr_checks.py +130 -0
@@ -46,9 +46,34 @@
46
46
  "type": "string",
47
47
  "minLength": 1
48
48
  },
49
+ "impact": {
50
+ "description": "The value statement the host renders from an installed automation's run history. Declare it only when its basis honestly backs the phrase: for completed-runs, one completed run must always perform exactly one of the stated units of work, manually dispatched runs included, so a poller that can complete having produced nothing must phrase the run itself, never the downstream outcome.",
51
+ "type": "object",
52
+ "additionalProperties": false,
53
+ "required": ["basis", "one", "other"],
54
+ "properties": {
55
+ "basis": {
56
+ "description": "What the statement counts. The only basis today is the automation's lifetime COMPLETED-run count; a host that meets a basis it does not know renders nothing.",
57
+ "const": "completed-runs"
58
+ },
59
+ "one": { "$ref": "#/$defs/impactCopy" },
60
+ "other": {
61
+ "$comment": "The plural phrase must show the number; the singular may spell it out instead.",
62
+ "allOf": [{ "$ref": "#/$defs/impactCopy" }],
63
+ "pattern": "\\{\\{count\\}\\}"
64
+ }
65
+ }
66
+ },
49
67
  "setup": { "$ref": "#/$defs/setup" }
50
68
  },
51
69
  "$defs": {
70
+ "impactCopy": {
71
+ "description": "One value-statement phrase. Markup-free, and the only placeholder it may open is {{count}}, which the host substitutes with the formatted run count.",
72
+ "allOf": [
73
+ { "$ref": "#/$defs/copy" },
74
+ { "not": { "pattern": "\\{\\{(?!count\\}\\})" } }
75
+ ]
76
+ },
52
77
  "setup": {
53
78
  "description": "The extension-owned configuration experience for this automation: what the deployment must support, what must be connected first, what the user is asked, how a draft is validated, what request is sent, and which analytics stages are emitted. It never describes what the automation does at runtime - that is the preset, owned by OpenHands/automation. It is data, not code - there is no key that accepts JavaScript, no markup in copy, no free-form URL, and no secret value.",
54
79
  "type": "object",
@@ -83,6 +108,10 @@
83
108
  "message": {
84
109
  "description": "Setup context handed to the agent conversation that finishes setup. Required for assisted mode. Optional for direct mode, where it seeds the fallback conversation the host offers when the deployment cannot run the direct path. The command that opens it comes from the skill, so it is not repeated here. Capped so this never becomes a channel for runtime instructions.",
85
110
  "allOf": [{ "$ref": "#/$defs/templateCopy" }, { "maxLength": 2000 }]
111
+ },
112
+ "actions": {
113
+ "description": "direct only, and the alternative to prompt or bundle. User-selectable creation paths for one setup card; the key maps to a known automation service endpoint.",
114
+ "$ref": "#/$defs/actions"
86
115
  }
87
116
  },
88
117
  "allOf": [
@@ -93,8 +122,9 @@
93
122
  },
94
123
  "then": {
95
124
  "oneOf": [
96
- { "required": ["prompt"], "not": { "required": ["bundle"] } },
97
- { "required": ["bundle"], "not": { "required": ["prompt"] } }
125
+ { "required": ["prompt"], "not": { "anyOf": [{ "required": ["bundle"] }, { "required": ["actions"] }] } },
126
+ { "required": ["bundle"], "not": { "anyOf": [{ "required": ["prompt"] }, { "required": ["actions"] }] } },
127
+ { "required": ["actions"], "not": { "anyOf": [{ "required": ["prompt"] }, { "required": ["bundle"] }] } }
98
128
  ]
99
129
  }
100
130
  },
@@ -108,7 +138,8 @@
108
138
  "allOf": [
109
139
  { "not": { "required": ["prompt"] } },
110
140
  { "not": { "required": ["bundle"] } },
111
- { "not": { "required": ["filter"] } }
141
+ { "not": { "required": ["filter"] } },
142
+ { "not": { "required": ["actions"] } }
112
143
  ]
113
144
  }
114
145
  },
@@ -132,6 +163,63 @@
132
163
  }
133
164
  ]
134
165
  },
166
+ "actionFeatures": {
167
+ "description": "Deployment capabilities needed only for this selectable action variant.",
168
+ "type": "array",
169
+ "minItems": 1,
170
+ "uniqueItems": true,
171
+ "items": { "type": "string", "minLength": 1 }
172
+ },
173
+ "promptAction": {
174
+ "type": "object",
175
+ "additionalProperties": false,
176
+ "required": ["label", "help", "features", "args", "prompt"],
177
+ "properties": {
178
+ "label": { "$ref": "#/$defs/copy" },
179
+ "help": { "$ref": "#/$defs/copy" },
180
+ "features": { "$ref": "#/$defs/actionFeatures" },
181
+ "args": { "$ref": "#/$defs/formFields" },
182
+ "prompt": { "$ref": "#/$defs/templateValue" }
183
+ }
184
+ },
185
+ "pluginAction": {
186
+ "type": "object",
187
+ "additionalProperties": false,
188
+ "required": ["label", "help", "features", "args", "prompt", "plugins"],
189
+ "properties": {
190
+ "label": { "$ref": "#/$defs/copy" },
191
+ "help": { "$ref": "#/$defs/copy" },
192
+ "features": { "$ref": "#/$defs/actionFeatures" },
193
+ "args": { "$ref": "#/$defs/formFields" },
194
+ "prompt": { "$ref": "#/$defs/templateValue" },
195
+ "plugins": { "$ref": "#/$defs/templateValue" }
196
+ }
197
+ },
198
+ "uploadAction": {
199
+ "type": "object",
200
+ "additionalProperties": false,
201
+ "required": ["label", "help", "features", "args", "tarballPath", "entrypoint"],
202
+ "properties": {
203
+ "label": { "$ref": "#/$defs/copy" },
204
+ "help": { "$ref": "#/$defs/copy" },
205
+ "features": { "$ref": "#/$defs/actionFeatures" },
206
+ "args": { "$ref": "#/$defs/formFields" },
207
+ "tarballPath": { "$ref": "#/$defs/templateValue" },
208
+ "entrypoint": { "$ref": "#/$defs/templateValue" },
209
+ "setupScript": { "$ref": "#/$defs/templateValue" }
210
+ }
211
+ },
212
+ "actions": {
213
+ "description": "Selectable direct-setup creation paths: prompt -> /v1/preset/prompt, plugin -> /v1/preset/plugin, upload -> /v1/uploads then /v1.",
214
+ "type": "object",
215
+ "additionalProperties": false,
216
+ "minProperties": 1,
217
+ "properties": {
218
+ "prompt": { "$ref": "#/$defs/promptAction" },
219
+ "plugin": { "$ref": "#/$defs/pluginAction" },
220
+ "upload": { "$ref": "#/$defs/uploadAction" }
221
+ }
222
+ },
135
223
  "bundle": {
136
224
  "description": "What the host packs into a .tar.gz and uploads before creating the automation. It names files inside this repository and the command that runs them - never a host, a URL, or code to evaluate.",
137
225
  "type": "object",
@@ -278,7 +366,7 @@
278
366
  "properties": {
279
367
  "note": { "$ref": "#/$defs/copy" },
280
368
  "triggers": {
281
- "description": "Inputs that decide when the automation runs, keyed by trigger kind. The key set is the trigger kinds the deployment must support, so it is not restated anywhere else.",
369
+ "description": "Inputs that decide when the automation runs, keyed by trigger kind. Multiple keys are selectable variants; a deployment can offer any variant whose trigger kind it supports.",
282
370
  "type": "object",
283
371
  "additionalProperties": false,
284
372
  "minProperties": 1,
@@ -306,20 +394,29 @@
306
394
  "required": ["type", "label", "help", "required"],
307
395
  "properties": {
308
396
  "type": {
309
- "description": "Semantic field types. The host renders a cron field without knowing what cron means to an automation, and resolves the deployment's schedule limits and timezone list for the cron and timezone types, so an entry never restates them.",
397
+ "description": "Semantic field types. The host renders cron, timezone, llm-profile, event-source, and event-type fields from deployment capabilities or user settings rather than entry-owned option lists.",
310
398
  "enum": [
311
399
  "text",
312
400
  "textarea",
313
401
  "select",
402
+ "number",
314
403
  "cron",
315
404
  "timezone",
316
- "repo-picker"
405
+ "repo-picker",
406
+ "llm-profile",
407
+ "event-source",
408
+ "event-type",
409
+ "plugin-sources",
410
+ "tarball-upload"
317
411
  ]
318
412
  },
319
413
  "label": { "$ref": "#/$defs/copy" },
320
414
  "help": { "$ref": "#/$defs/copy" },
321
415
  "placeholder": { "$ref": "#/$defs/copy" },
322
- "default": { "type": "string" },
416
+ "default": {
417
+ "description": "Initial value for fields whose defaults are entry-owned. Semantic fields may ignore it.",
418
+ "type": ["string", "number", "boolean", "null"]
419
+ },
323
420
  "required": { "type": "boolean" },
324
421
  "provider": { "enum": ["github", "gitlab", "bitbucket"] },
325
422
  "multiple": {
@@ -346,6 +443,8 @@
346
443
  "properties": {
347
444
  "minLength": { "type": "integer", "minimum": 0 },
348
445
  "maxLength": { "type": "integer", "minimum": 1 },
446
+ "min": { "type": "integer", "minimum": 0 },
447
+ "max": { "type": "integer", "minimum": 1 },
349
448
  "format": {
350
449
  "description": "A host-implemented check, named from a closed set. Setup blocks cannot supply their own regex, so one cannot hand the host a pathological pattern. safeExpressionLiteral marks a value that is interpolated into a filter expression string literal, so quotes and backslashes must be rejected before they can break the expression.",
351
450
  "enum": ["safeExpressionLiteral"]
@@ -30,10 +30,26 @@ export interface RecommendedAutomation {
30
30
  */
31
31
  skill?: string;
32
32
  exampleImplementation: string;
33
+ /**
34
+ * The value statement the host renders from an installed automation's run
35
+ * history. Declared only when its basis honestly backs the phrase: for
36
+ * `completed-runs`, one completed run must always perform exactly one of
37
+ * the stated units of work, manually dispatched runs included, so a poller
38
+ * that can complete having produced nothing phrases the run itself, never
39
+ * the downstream outcome. `{{count}}` is the host-substituted run count; a
40
+ * host that meets a basis it does not know renders nothing.
41
+ */
42
+ impact?: AutomationImpact;
33
43
  /** Present when this automation ships an extension-owned setup experience. */
34
44
  setup?: AutomationSetup;
35
45
  }
36
46
 
47
+ export interface AutomationImpact {
48
+ basis: "completed-runs";
49
+ one: string;
50
+ other: string;
51
+ }
52
+
37
53
  /**
38
54
  * The extension-owned configuration experience for one automation.
39
55
  *
@@ -54,9 +70,15 @@ export type AutomationFieldType =
54
70
  | "text"
55
71
  | "textarea"
56
72
  | "select"
73
+ | "number"
57
74
  | "cron"
58
75
  | "timezone"
59
- | "repo-picker";
76
+ | "repo-picker"
77
+ | "llm-profile"
78
+ | "event-source"
79
+ | "event-type"
80
+ | "plugin-sources"
81
+ | "tarball-upload";
60
82
  export type AutomationGitProvider = "github" | "gitlab" | "bitbucket";
61
83
  export type AutomationTriggerKind = "cron" | "event";
62
84
 
@@ -68,6 +90,8 @@ export interface AutomationFieldOption {
68
90
  export interface AutomationFieldConstraints {
69
91
  minLength?: number;
70
92
  maxLength?: number;
93
+ min?: number;
94
+ max?: number;
71
95
  /** Host-implemented check, named from a closed set. Entries supply no regex. */
72
96
  format?: "safeExpressionLiteral";
73
97
  }
@@ -77,7 +101,7 @@ export interface AutomationFormField {
77
101
  label: string;
78
102
  help: string;
79
103
  placeholder?: string;
80
- default?: string;
104
+ default?: string | number | boolean | null;
81
105
  required: boolean;
82
106
  provider?: AutomationGitProvider;
83
107
  /**
@@ -144,6 +168,46 @@ export interface AutomationBundle {
144
168
  config: Record<string, AutomationBundleConfigValue>;
145
169
  }
146
170
 
171
+
172
+ export interface AutomationPromptAction {
173
+ label: string;
174
+ help: string;
175
+ features: string[];
176
+ args: AutomationFormFields;
177
+ /** Prompt sent to /v1/preset/prompt. */
178
+ prompt: string;
179
+ }
180
+
181
+ export interface AutomationPluginAction {
182
+ label: string;
183
+ help: string;
184
+ features: string[];
185
+ args: AutomationFormFields;
186
+ /** Prompt sent to /v1/preset/plugin. */
187
+ prompt: string;
188
+ /** PluginSource list sent to /v1/preset/plugin, usually {{form.plugins}}. */
189
+ plugins: string;
190
+ }
191
+
192
+ export interface AutomationUploadAction {
193
+ label: string;
194
+ help: string;
195
+ features: string[];
196
+ args: AutomationFormFields;
197
+ /** tarball_path produced by uploading the selected tarball file. */
198
+ tarballPath: string;
199
+ /** Entrypoint command sent to /v1. */
200
+ entrypoint: string;
201
+ /** Optional setup_script_path sent to /v1. */
202
+ setupScript?: string;
203
+ }
204
+
205
+ export interface AutomationSetupActions {
206
+ prompt?: AutomationPromptAction;
207
+ plugin?: AutomationPluginAction;
208
+ upload?: AutomationUploadAction;
209
+ }
210
+
147
211
  export interface AutomationSetup {
148
212
  version: "1.0";
149
213
  mode: AutomationSetupMode;
@@ -152,6 +216,8 @@ export interface AutomationSetup {
152
216
  prompt?: string;
153
217
  /** direct only, and the alternative to `prompt`. Exactly one is present. */
154
218
  bundle?: AutomationBundle;
219
+ /** direct only, and the alternative to `prompt` or `bundle`. */
220
+ actions?: AutomationSetupActions;
155
221
  /** direct only, event trigger only. Which delivered events belong to it. */
156
222
  filter?: string;
157
223
  /**
@@ -153,7 +153,8 @@
153
153
  "github-agents-md-maintainer",
154
154
  "news-digest",
155
155
  "github-issue-to-pr",
156
- "slack-channel-monitor"
156
+ "slack-channel-monitor",
157
+ "custom-automation"
157
158
  ],
158
159
  "responderIntegrationIds": ["github", "slack"]
159
160
  }
@@ -43,7 +43,7 @@
43
43
  "urlEditable": true,
44
44
  "headerFields": [
45
45
  {
46
- "key": "DD_API_KEY",
46
+ "key": "DD-API-KEY",
47
47
  "label": "Datadog API key",
48
48
  "type": "password",
49
49
  "required": true,
@@ -51,7 +51,7 @@
51
51
  "helperText": "Created in Datadog under Organization Settings → API Keys. Used to authenticate to the Datadog MCP server. See the [setup docs](https://docs.datadoghq.com/mcp_server/setup/?tab=other#authentication)."
52
52
  },
53
53
  {
54
- "key": "DD_APPLICATION_KEY",
54
+ "key": "DD-APPLICATION-KEY",
55
55
  "label": "Datadog Application key",
56
56
  "type": "password",
57
57
  "required": true,
@@ -0,0 +1,63 @@
1
+ {
2
+ "id": "gitlab",
3
+ "name": "GitLab",
4
+ "description": "Access projects, issues, merge requests, and CI/CD workflows through GitLab's official MCP server or API.",
5
+ "categories": [
6
+ "Engineering",
7
+ "Source control"
8
+ ],
9
+ "appUrl": "https://gitlab.com",
10
+ "docsUrl": "https://docs.gitlab.com/user/model_context_protocol/mcp_server/",
11
+ "notes": "Supports GitLab.com through either the official MCP server (beta) with OAuth or the API with a personal access token. For the OAuth MCP connection to work on GitLab.com, MCP server access must be enabled for a top-level group you belong to (set GitLab Duo availability to Always on or On by default for the top-level group, turn on beta and experimental features, and allow access to the MCP server); otherwise GitLab rejects the connection with a 404 after OAuth, which the client reports as 'Session terminated'. For GitLab Self-Managed, edit the MCP URL to your instance's server and the OAuth flow discovers the host-specific endpoints.",
12
+ "popularityRank": 60,
13
+ "connectionOptions": [
14
+ {
15
+ "id": "api",
16
+ "provider": "http",
17
+ "auth": {
18
+ "strategy": "api_key",
19
+ "apiKeyHeaderName": "PRIVATE-TOKEN",
20
+ "credentialLabel": "Personal access token",
21
+ "credentialPlaceholder": "glpat-...",
22
+ "credentialHelp": "Create a token in [GitLab access token settings](https://gitlab.com/-/user_settings/personal_access_tokens) with the api scope.",
23
+ "credentialSecretName": "GITLAB_TOKEN",
24
+ "saveCredentialAsSecretByDefault": true
25
+ },
26
+ "http": {
27
+ "apiBaseUrl": "https://gitlab.com/api/v4",
28
+ "openApiUrl": "https://gitlab.com/gitlab-org/gitlab/-/raw/master/doc/api/openapi/openapi_v2.yaml"
29
+ }
30
+ },
31
+ {
32
+ "id": "oauth",
33
+ "provider": "mcp",
34
+ "auth": {
35
+ "strategy": "oauth2",
36
+ "oauth": {
37
+ "scopes": [
38
+ "mcp"
39
+ ],
40
+ "pkce": true,
41
+ "clientAuthentication": "none"
42
+ }
43
+ },
44
+ "transport": {
45
+ "kind": "shttp",
46
+ "url": "https://gitlab.com/api/v4/mcp",
47
+ "urlEditable": true
48
+ }
49
+ }
50
+ ],
51
+ "iconBg": "var(--oh-surface)",
52
+ "logoUrl": "https://cdn.simpleicons.org/gitlab/FC6D26",
53
+ "keywords": [
54
+ "git",
55
+ "merge request",
56
+ "repo",
57
+ "issues",
58
+ "code",
59
+ "mr",
60
+ "devops"
61
+ ],
62
+ "installHint": "The GitLab MCP server supports OAuth 2.0. Before installing, make sure an admin has enabled 'MCP client access' for the top-level GitLab group you belong to. If this prerequisite isn't met, GitLab returns 404 after OAuth and the connection fails with 'Session terminated'. For GitLab Self-Managed, edit the URL to https://<your-instance>/api/v4/mcp and make sure MCP server access is enabled for the instance."
63
+ }
@@ -52,7 +52,7 @@
52
52
  ],
53
53
  "envFields": [
54
54
  {
55
- "key": "NOTION_API_KEY",
55
+ "key": "NOTION_TOKEN",
56
56
  "label": "Internal integration token",
57
57
  "type": "password",
58
58
  "placeholder": "ntn_...",
@@ -9,75 +9,76 @@ import entry3 from "./catalog/atlassian.json" with { type: "json" };
9
9
  import entry4 from "./catalog/linear.json" with { type: "json" };
10
10
  import entry5 from "./catalog/notion.json" with { type: "json" };
11
11
  import entry6 from "./catalog/vanta.json" with { type: "json" };
12
- import entry7 from "./catalog/ordinal.json" with { type: "json" };
13
- import entry8 from "./catalog/elevenlabs.json" with { type: "json" };
14
- import entry9 from "./catalog/bitbucket.json" with { type: "json" };
15
- import entry10 from "./catalog/xero.json" with { type: "json" };
16
- import entry11 from "./catalog/quickbooks.json" with { type: "json" };
17
- import entry12 from "./catalog/sonarqube.json" with { type: "json" };
18
- import entry13 from "./catalog/okta.json" with { type: "json" };
19
- import entry14 from "./catalog/netlify.json" with { type: "json" };
20
- import entry15 from "./catalog/vercel.json" with { type: "json" };
21
- import entry16 from "./catalog/supabase.json" with { type: "json" };
22
- import entry17 from "./catalog/posthog.json" with { type: "json" };
23
- import entry18 from "./catalog/sentry.json" with { type: "json" };
24
- import entry19 from "./catalog/datadog.json" with { type: "json" };
25
- import entry20 from "./catalog/canva.json" with { type: "json" };
26
- import entry21 from "./catalog/miro.json" with { type: "json" };
27
- import entry22 from "./catalog/webflow.json" with { type: "json" };
28
- import entry23 from "./catalog/zoom.json" with { type: "json" };
29
- import entry24 from "./catalog/discord.json" with { type: "json" };
30
- import entry25 from "./catalog/stripe.json" with { type: "json" };
31
- import entry26 from "./catalog/intercom.json" with { type: "json" };
32
- import entry27 from "./catalog/hubspot.json" with { type: "json" };
33
- import entry28 from "./catalog/salesforce.json" with { type: "json" };
34
- import entry29 from "./catalog/sharepoint.json" with { type: "json" };
35
- import entry30 from "./catalog/onedrive.json" with { type: "json" };
36
- import entry31 from "./catalog/microsoft-teams.json" with { type: "json" };
37
- import entry32 from "./catalog/microsoft-outlook.json" with { type: "json" };
38
- import entry33 from "./catalog/box.json" with { type: "json" };
39
- import entry34 from "./catalog/airtable.json" with { type: "json" };
40
- import entry35 from "./catalog/monday.json" with { type: "json" };
41
- import entry36 from "./catalog/trello.json" with { type: "json" };
42
- import entry37 from "./catalog/asana.json" with { type: "json" };
43
- import entry38 from "./catalog/confluence.json" with { type: "json" };
44
- import entry39 from "./catalog/jira.json" with { type: "json" };
45
- import entry40 from "./catalog/google-calendar.json" with { type: "json" };
46
- import entry41 from "./catalog/gmail.json" with { type: "json" };
47
- import entry42 from "./catalog/google-sheets.json" with { type: "json" };
48
- import entry43 from "./catalog/google-drive.json" with { type: "json" };
49
- import entry44 from "./catalog/figma.json" with { type: "json" };
50
- import entry45 from "./catalog/google-docs.json" with { type: "json" };
51
- import entry46 from "./catalog/apify.json" with { type: "json" };
52
- import entry47 from "./catalog/atlassian-rovo.json" with { type: "json" };
53
- import entry48 from "./catalog/brave-search.json" with { type: "json" };
54
- import entry49 from "./catalog/browser-mcp.json" with { type: "json" };
55
- import entry50 from "./catalog/clickhouse.json" with { type: "json" };
56
- import entry51 from "./catalog/cloudflare-bindings.json" with { type: "json" };
57
- import entry52 from "./catalog/cloudflare-browser-rendering.json" with { type: "json" };
58
- import entry53 from "./catalog/cloudflare-builds.json" with { type: "json" };
59
- import entry54 from "./catalog/cloudflare-docs.json" with { type: "json" };
60
- import entry55 from "./catalog/cloudflare-observability.json" with { type: "json" };
61
- import entry56 from "./catalog/deepwiki.json" with { type: "json" };
62
- import entry57 from "./catalog/everything.json" with { type: "json" };
63
- import entry58 from "./catalog/exa.json" with { type: "json" };
64
- import entry59 from "./catalog/fetch.json" with { type: "json" };
65
- import entry60 from "./catalog/filesystem.json" with { type: "json" };
66
- import entry61 from "./catalog/firecrawl.json" with { type: "json" };
67
- import entry62 from "./catalog/git.json" with { type: "json" };
68
- import entry63 from "./catalog/huggingface.json" with { type: "json" };
69
- import entry64 from "./catalog/kagi.json" with { type: "json" };
70
- import entry65 from "./catalog/memory.json" with { type: "json" };
71
- import entry66 from "./catalog/mongodb.json" with { type: "json" };
72
- import entry67 from "./catalog/neon.json" with { type: "json" };
73
- import entry68 from "./catalog/obsidian.json" with { type: "json" };
74
- import entry69 from "./catalog/paypal.json" with { type: "json" };
75
- import entry70 from "./catalog/playwright.json" with { type: "json" };
76
- import entry71 from "./catalog/redis.json" with { type: "json" };
77
- import entry72 from "./catalog/resend.json" with { type: "json" };
78
- import entry73 from "./catalog/sequential-thinking.json" with { type: "json" };
79
- import entry74 from "./catalog/superhuman-mail.json" with { type: "json" };
80
- import entry75 from "./catalog/time.json" with { type: "json" };
12
+ import entry7 from "./catalog/gitlab.json" with { type: "json" };
13
+ import entry8 from "./catalog/ordinal.json" with { type: "json" };
14
+ import entry9 from "./catalog/elevenlabs.json" with { type: "json" };
15
+ import entry10 from "./catalog/bitbucket.json" with { type: "json" };
16
+ import entry11 from "./catalog/xero.json" with { type: "json" };
17
+ import entry12 from "./catalog/quickbooks.json" with { type: "json" };
18
+ import entry13 from "./catalog/sonarqube.json" with { type: "json" };
19
+ import entry14 from "./catalog/okta.json" with { type: "json" };
20
+ import entry15 from "./catalog/netlify.json" with { type: "json" };
21
+ import entry16 from "./catalog/vercel.json" with { type: "json" };
22
+ import entry17 from "./catalog/supabase.json" with { type: "json" };
23
+ import entry18 from "./catalog/posthog.json" with { type: "json" };
24
+ import entry19 from "./catalog/sentry.json" with { type: "json" };
25
+ import entry20 from "./catalog/datadog.json" with { type: "json" };
26
+ import entry21 from "./catalog/canva.json" with { type: "json" };
27
+ import entry22 from "./catalog/miro.json" with { type: "json" };
28
+ import entry23 from "./catalog/webflow.json" with { type: "json" };
29
+ import entry24 from "./catalog/zoom.json" with { type: "json" };
30
+ import entry25 from "./catalog/discord.json" with { type: "json" };
31
+ import entry26 from "./catalog/stripe.json" with { type: "json" };
32
+ import entry27 from "./catalog/intercom.json" with { type: "json" };
33
+ import entry28 from "./catalog/hubspot.json" with { type: "json" };
34
+ import entry29 from "./catalog/salesforce.json" with { type: "json" };
35
+ import entry30 from "./catalog/sharepoint.json" with { type: "json" };
36
+ import entry31 from "./catalog/onedrive.json" with { type: "json" };
37
+ import entry32 from "./catalog/microsoft-teams.json" with { type: "json" };
38
+ import entry33 from "./catalog/microsoft-outlook.json" with { type: "json" };
39
+ import entry34 from "./catalog/box.json" with { type: "json" };
40
+ import entry35 from "./catalog/airtable.json" with { type: "json" };
41
+ import entry36 from "./catalog/monday.json" with { type: "json" };
42
+ import entry37 from "./catalog/trello.json" with { type: "json" };
43
+ import entry38 from "./catalog/asana.json" with { type: "json" };
44
+ import entry39 from "./catalog/confluence.json" with { type: "json" };
45
+ import entry40 from "./catalog/jira.json" with { type: "json" };
46
+ import entry41 from "./catalog/google-calendar.json" with { type: "json" };
47
+ import entry42 from "./catalog/gmail.json" with { type: "json" };
48
+ import entry43 from "./catalog/google-sheets.json" with { type: "json" };
49
+ import entry44 from "./catalog/google-drive.json" with { type: "json" };
50
+ import entry45 from "./catalog/figma.json" with { type: "json" };
51
+ import entry46 from "./catalog/google-docs.json" with { type: "json" };
52
+ import entry47 from "./catalog/apify.json" with { type: "json" };
53
+ import entry48 from "./catalog/atlassian-rovo.json" with { type: "json" };
54
+ import entry49 from "./catalog/brave-search.json" with { type: "json" };
55
+ import entry50 from "./catalog/browser-mcp.json" with { type: "json" };
56
+ import entry51 from "./catalog/clickhouse.json" with { type: "json" };
57
+ import entry52 from "./catalog/cloudflare-bindings.json" with { type: "json" };
58
+ import entry53 from "./catalog/cloudflare-browser-rendering.json" with { type: "json" };
59
+ import entry54 from "./catalog/cloudflare-builds.json" with { type: "json" };
60
+ import entry55 from "./catalog/cloudflare-docs.json" with { type: "json" };
61
+ import entry56 from "./catalog/cloudflare-observability.json" with { type: "json" };
62
+ import entry57 from "./catalog/deepwiki.json" with { type: "json" };
63
+ import entry58 from "./catalog/everything.json" with { type: "json" };
64
+ import entry59 from "./catalog/exa.json" with { type: "json" };
65
+ import entry60 from "./catalog/fetch.json" with { type: "json" };
66
+ import entry61 from "./catalog/filesystem.json" with { type: "json" };
67
+ import entry62 from "./catalog/firecrawl.json" with { type: "json" };
68
+ import entry63 from "./catalog/git.json" with { type: "json" };
69
+ import entry64 from "./catalog/huggingface.json" with { type: "json" };
70
+ import entry65 from "./catalog/kagi.json" with { type: "json" };
71
+ import entry66 from "./catalog/memory.json" with { type: "json" };
72
+ import entry67 from "./catalog/mongodb.json" with { type: "json" };
73
+ import entry68 from "./catalog/neon.json" with { type: "json" };
74
+ import entry69 from "./catalog/obsidian.json" with { type: "json" };
75
+ import entry70 from "./catalog/paypal.json" with { type: "json" };
76
+ import entry71 from "./catalog/playwright.json" with { type: "json" };
77
+ import entry72 from "./catalog/redis.json" with { type: "json" };
78
+ import entry73 from "./catalog/resend.json" with { type: "json" };
79
+ import entry74 from "./catalog/sequential-thinking.json" with { type: "json" };
80
+ import entry75 from "./catalog/superhuman-mail.json" with { type: "json" };
81
+ import entry76 from "./catalog/time.json" with { type: "json" };
81
82
 
82
83
  export const INTEGRATION_CATALOG_ENTRIES = [
83
84
  entry0,
@@ -156,4 +157,5 @@ export const INTEGRATION_CATALOG_ENTRIES = [
156
157
  entry73,
157
158
  entry74,
158
159
  entry75,
160
+ entry76,
159
161
  ];
@@ -17,7 +17,7 @@ export type IntegrationTransport =
17
17
  apiKeyOptional?: boolean;
18
18
  /**
19
19
  * Named request headers the user must supply (e.g. Datadog's
20
- * `DD_API_KEY` / `DD_APPLICATION_KEY`). Values are sent verbatim as
20
+ * `DD-API-KEY` / `DD-APPLICATION-KEY`). Values are sent verbatim as
21
21
  * headers on every MCP request. The direct analog of stdio's
22
22
  * `envFields`: each entry renders one input in the install modal,
23
23
  * `type: "password"` entries are secret-saved by default, and