@sweny-ai/core 0.1.77 → 0.1.78

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 (119) hide show
  1. package/dist/browser.d.ts +11 -5
  2. package/dist/browser.js +11 -11
  3. package/dist/claude.d.ts +16 -0
  4. package/dist/claude.js +98 -9
  5. package/dist/cli/config.d.ts +22 -0
  6. package/dist/cli/config.js +56 -9
  7. package/dist/cli/main.d.ts +1 -1
  8. package/dist/cli/main.js +56 -57
  9. package/dist/cli/marketplace.js +35 -9
  10. package/dist/cli/publish.d.ts +10 -0
  11. package/dist/cli/publish.js +22 -14
  12. package/dist/loader.d.ts +40 -0
  13. package/dist/loader.js +73 -0
  14. package/dist/mcp-catalog.d.ts +47 -0
  15. package/dist/mcp-catalog.js +304 -0
  16. package/dist/mcp.d.ts +6 -9
  17. package/dist/mcp.js +24 -314
  18. package/dist/schema.d.ts +183 -151
  19. package/dist/schema.js +49 -7
  20. package/dist/skills/custom-loader.d.ts +40 -0
  21. package/dist/skills/custom-loader.js +107 -32
  22. package/dist/skills/index.d.ts +13 -1
  23. package/dist/skills/index.js +12 -3
  24. package/dist/studio.js +4 -1
  25. package/dist/templates.d.ts +29 -8
  26. package/dist/templates.js +30 -20
  27. package/dist/types.d.ts +12 -0
  28. package/dist/verify.js +42 -4
  29. package/package.json +8 -4
  30. package/dist/__tests__/cascade.test.d.ts +0 -11
  31. package/dist/__tests__/cascade.test.js +0 -452
  32. package/dist/__tests__/claude.test.d.ts +0 -1
  33. package/dist/__tests__/claude.test.js +0 -427
  34. package/dist/__tests__/custom-loader.test.d.ts +0 -1
  35. package/dist/__tests__/custom-loader.test.js +0 -116
  36. package/dist/__tests__/executor.test.d.ts +0 -1
  37. package/dist/__tests__/executor.test.js +0 -1635
  38. package/dist/__tests__/integration/datadog.integration.test.d.ts +0 -1
  39. package/dist/__tests__/integration/datadog.integration.test.js +0 -23
  40. package/dist/__tests__/integration/e2e-workflow.integration.test.d.ts +0 -1
  41. package/dist/__tests__/integration/e2e-workflow.integration.test.js +0 -75
  42. package/dist/__tests__/integration/github.integration.test.d.ts +0 -1
  43. package/dist/__tests__/integration/github.integration.test.js +0 -37
  44. package/dist/__tests__/integration/harness.d.ts +0 -24
  45. package/dist/__tests__/integration/harness.js +0 -34
  46. package/dist/__tests__/integration/linear.integration.test.d.ts +0 -1
  47. package/dist/__tests__/integration/linear.integration.test.js +0 -15
  48. package/dist/__tests__/integration/sentry.integration.test.d.ts +0 -1
  49. package/dist/__tests__/integration/sentry.integration.test.js +0 -20
  50. package/dist/__tests__/integration/slack.integration.test.d.ts +0 -1
  51. package/dist/__tests__/integration/slack.integration.test.js +0 -22
  52. package/dist/__tests__/integration/sources.integration.test.d.ts +0 -1
  53. package/dist/__tests__/integration/sources.integration.test.js +0 -123
  54. package/dist/__tests__/publish.test.d.ts +0 -1
  55. package/dist/__tests__/publish.test.js +0 -180
  56. package/dist/__tests__/requires.test.d.ts +0 -1
  57. package/dist/__tests__/requires.test.js +0 -82
  58. package/dist/__tests__/retry.test.d.ts +0 -1
  59. package/dist/__tests__/retry.test.js +0 -213
  60. package/dist/__tests__/schema.test.d.ts +0 -1
  61. package/dist/__tests__/schema.test.js +0 -600
  62. package/dist/__tests__/skill-config-integration.test.d.ts +0 -1
  63. package/dist/__tests__/skill-config-integration.test.js +0 -204
  64. package/dist/__tests__/skills-index.test.d.ts +0 -1
  65. package/dist/__tests__/skills-index.test.js +0 -119
  66. package/dist/__tests__/skills.test.d.ts +0 -1
  67. package/dist/__tests__/skills.test.js +0 -565
  68. package/dist/__tests__/spec-conformance.test.d.ts +0 -18
  69. package/dist/__tests__/spec-conformance.test.js +0 -1084
  70. package/dist/__tests__/studio.test.d.ts +0 -1
  71. package/dist/__tests__/studio.test.js +0 -403
  72. package/dist/__tests__/templates.test.d.ts +0 -1
  73. package/dist/__tests__/templates.test.js +0 -49
  74. package/dist/__tests__/testing.test.d.ts +0 -1
  75. package/dist/__tests__/testing.test.js +0 -242
  76. package/dist/__tests__/verify.test.d.ts +0 -1
  77. package/dist/__tests__/verify.test.js +0 -517
  78. package/dist/__tests__/version-consistency.test.d.ts +0 -1
  79. package/dist/__tests__/version-consistency.test.js +0 -312
  80. package/dist/__tests__/workflow-builder.test.d.ts +0 -1
  81. package/dist/__tests__/workflow-builder.test.js +0 -110
  82. package/dist/__tests__/workflow-yaml.test.d.ts +0 -1
  83. package/dist/__tests__/workflow-yaml.test.js +0 -201
  84. package/dist/cli/__tests__/diagram.test.d.ts +0 -1
  85. package/dist/cli/__tests__/diagram.test.js +0 -225
  86. package/dist/cli/__tests__/report-cloud.test.d.ts +0 -1
  87. package/dist/cli/__tests__/report-cloud.test.js +0 -165
  88. package/dist/cli/__tests__/upgrade.test.d.ts +0 -1
  89. package/dist/cli/__tests__/upgrade.test.js +0 -317
  90. package/dist/cli/__tests__/version-check.test.d.ts +0 -1
  91. package/dist/cli/__tests__/version-check.test.js +0 -209
  92. package/dist/cli/config.test.d.ts +0 -1
  93. package/dist/cli/config.test.js +0 -200
  94. package/dist/cli/credentials.test.d.ts +0 -1
  95. package/dist/cli/credentials.test.js +0 -172
  96. package/dist/cli/e2e.test.d.ts +0 -1
  97. package/dist/cli/e2e.test.js +0 -690
  98. package/dist/cli/marketplace.test.d.ts +0 -1
  99. package/dist/cli/marketplace.test.js +0 -355
  100. package/dist/cli/new.test.d.ts +0 -1
  101. package/dist/cli/new.test.js +0 -1043
  102. package/dist/cli/output.test.d.ts +0 -1
  103. package/dist/cli/output.test.js +0 -180
  104. package/dist/cli/publish.test.d.ts +0 -1
  105. package/dist/cli/publish.test.js +0 -610
  106. package/dist/cli/renderer.test.d.ts +0 -1
  107. package/dist/cli/renderer.test.js +0 -302
  108. package/dist/executor.test.d.ts +0 -1
  109. package/dist/executor.test.js +0 -618
  110. package/dist/mcp.test.d.ts +0 -1
  111. package/dist/mcp.test.js +0 -735
  112. package/dist/mermaid.test.d.ts +0 -1
  113. package/dist/mermaid.test.js +0 -256
  114. package/dist/sources.test.d.ts +0 -1
  115. package/dist/sources.test.js +0 -265
  116. package/dist/sources.validation.test.d.ts +0 -12
  117. package/dist/sources.validation.test.js +0 -380
  118. package/dist/workflow-builder.test.d.ts +0 -1
  119. package/dist/workflow-builder.test.js +0 -123
package/dist/mcp.js CHANGED
@@ -1,159 +1,26 @@
1
+ import { MCP_CATALOG } from "./mcp-catalog.js";
1
2
  /**
2
3
  * Build MCP server configs for the skills a workflow references.
3
4
  *
4
- * For each skill ID in `referencedSkills`, look up its MCP wiring (if any)
5
- * and include it only when the required credentials are present in `credentials`.
5
+ * For each entry in MCP_CATALOG whose skill triggers intersect
6
+ * `referencedSkills`, wire its MCP if credentials are present. Skills with
7
+ * no MCP variant (e.g. `notification`, `supabase`) are silently skipped —
8
+ * their in-process tools are wired separately by the executor. Unknown
9
+ * skill IDs pass through; the engine's hard-fail validation handles them.
6
10
  *
7
- * Skills with no MCP variant (e.g. `notification`, `supabase`) are silently
8
- * skipped — their in-process tools are wired separately by the executor.
9
- *
10
- * Unknown skill IDs (not built-in, not in this MCP catalog) are silently
11
- * skipped here; the engine's hard-fail validation handles them upstream.
12
- *
13
- * User-supplied servers always win on key conflict.
11
+ * Inline skill-declared servers and user-supplied servers layer on top.
14
12
  */
15
13
  export function buildSkillMcpServers(opts) {
16
14
  const auto = {};
17
15
  const refs = opts.referencedSkills;
18
16
  const creds = opts.credentials;
19
- // GitHub MCP — wired when workflow uses `github` skill and a token is set.
20
- if (refs.has("github") && creds.GITHUB_TOKEN) {
21
- auto["github"] = {
22
- type: "stdio",
23
- command: "npx",
24
- args: ["-y", "@modelcontextprotocol/server-github@latest"],
25
- env: { GITHUB_PERSONAL_ACCESS_TOKEN: creds.GITHUB_TOKEN },
26
- };
27
- }
28
- // GitLab MCP.
29
- if (refs.has("gitlab") && creds.GITLAB_TOKEN) {
30
- const env = { GITLAB_PERSONAL_ACCESS_TOKEN: creds.GITLAB_TOKEN };
31
- const baseUrl = creds.GITLAB_URL || "https://gitlab.com";
32
- if (baseUrl !== "https://gitlab.com")
33
- env.GITLAB_API_URL = `${baseUrl}/api/v4`;
34
- auto["gitlab"] = {
35
- type: "stdio",
36
- command: "npx",
37
- args: ["-y", "@modelcontextprotocol/server-gitlab@latest"],
38
- env,
39
- };
40
- }
41
- // Linear MCP — official remote HTTP endpoint.
42
- if (refs.has("linear") && creds.LINEAR_API_KEY) {
43
- auto["linear"] = {
44
- type: "http",
45
- url: "https://mcp.linear.app/mcp",
46
- headers: { Authorization: `Bearer ${creds.LINEAR_API_KEY}` },
47
- };
48
- }
49
- // Jira / Confluence — needs all 3 creds.
50
- if (refs.has("jira") && creds.JIRA_URL && creds.JIRA_EMAIL && creds.JIRA_API_TOKEN) {
51
- auto["jira"] = {
52
- type: "stdio",
53
- command: "npx",
54
- args: ["-y", "@sooperset/mcp-atlassian@latest"],
55
- env: {
56
- JIRA_URL: creds.JIRA_URL,
57
- JIRA_EMAIL: creds.JIRA_EMAIL,
58
- JIRA_API_TOKEN: creds.JIRA_API_TOKEN,
59
- },
60
- };
61
- }
62
- // Datadog MCP.
63
- if (refs.has("datadog") && creds.DD_API_KEY && creds.DD_APP_KEY) {
64
- auto["datadog"] = {
65
- type: "http",
66
- url: "https://mcp.datadoghq.com/api/unstable/mcp-server/mcp",
67
- headers: { DD_API_KEY: creds.DD_API_KEY, DD_APPLICATION_KEY: creds.DD_APP_KEY },
68
- };
69
- }
70
- // Sentry MCP — server reads SENTRY_ACCESS_TOKEN, not SENTRY_AUTH_TOKEN.
71
- if (refs.has("sentry") && creds.SENTRY_AUTH_TOKEN) {
72
- const env = { SENTRY_ACCESS_TOKEN: creds.SENTRY_AUTH_TOKEN };
73
- const sentryUrl = creds.SENTRY_URL;
74
- if (sentryUrl && sentryUrl !== "https://sentry.io") {
75
- try {
76
- env.SENTRY_HOST = new URL(sentryUrl).hostname;
77
- }
78
- catch {
79
- // malformed URL — leave SENTRY_HOST unset
80
- }
81
- }
82
- auto["sentry"] = {
83
- type: "stdio",
84
- command: "npx",
85
- args: ["-y", "@sentry/mcp-server@latest"],
86
- env,
87
- };
88
- }
89
- // New Relic MCP — region-aware HTTP endpoint, header is "Api-Key".
90
- if (refs.has("newrelic") && creds.NEW_RELIC_API_KEY) {
91
- const region = creds.NEW_RELIC_REGION;
92
- const url = region === "eu" ? "https://mcp.eu.newrelic.com/mcp/" : "https://mcp.newrelic.com/mcp/";
93
- auto["newrelic"] = {
94
- type: "http",
95
- url,
96
- headers: { "Api-Key": creds.NEW_RELIC_API_KEY },
97
- };
98
- }
99
- // BetterStack MCP — accept any of the legacy/telemetry/uptime tokens.
100
- const bsToken = creds.BETTERSTACK_API_TOKEN || creds.BETTERSTACK_TELEMETRY_TOKEN || creds.BETTERSTACK_UPTIME_TOKEN;
101
- if (refs.has("betterstack") && bsToken) {
102
- auto["betterstack"] = {
103
- type: "http",
104
- url: "https://mcp.betterstack.com",
105
- headers: { Authorization: `Bearer ${bsToken}` },
106
- };
107
- }
108
- // Slack MCP — wired when workflow uses `slack` skill and bot token is set.
109
- if (refs.has("slack") && creds.SLACK_BOT_TOKEN) {
110
- const env = { SLACK_BOT_TOKEN: creds.SLACK_BOT_TOKEN };
111
- if (creds.SLACK_TEAM_ID)
112
- env.SLACK_TEAM_ID = creds.SLACK_TEAM_ID;
113
- auto["slack"] = {
114
- type: "stdio",
115
- command: "npx",
116
- args: ["-y", "@modelcontextprotocol/server-slack@latest"],
117
- env,
118
- };
119
- }
120
- // Notion MCP — accept either NOTION_TOKEN or NOTION_API_KEY.
121
- if (refs.has("notion")) {
122
- const token = creds.NOTION_TOKEN || creds.NOTION_API_KEY;
123
- if (token) {
124
- auto["notion"] = {
125
- type: "stdio",
126
- command: "npx",
127
- args: ["-y", "@notionhq/notion-mcp-server@latest"],
128
- env: { NOTION_TOKEN: token },
129
- };
130
- }
131
- }
132
- // PagerDuty MCP — auth scheme is `Token token=<key>`.
133
- if (refs.has("pagerduty") && creds.PAGERDUTY_API_TOKEN) {
134
- auto["pagerduty"] = {
135
- type: "http",
136
- url: "https://mcp.pagerduty.com/mcp",
137
- headers: { Authorization: `Token token=${creds.PAGERDUTY_API_TOKEN}` },
138
- };
139
- }
140
- // Monday.com MCP.
141
- if (refs.has("monday") && creds.MONDAY_TOKEN) {
142
- auto["monday"] = {
143
- type: "stdio",
144
- command: "npx",
145
- args: ["-y", "@mondaydotcomorg/monday-api-mcp@latest"],
146
- env: { MONDAY_TOKEN: creds.MONDAY_TOKEN },
147
- };
148
- }
149
- // Asana MCP.
150
- if (refs.has("asana") && creds.ASANA_ACCESS_TOKEN) {
151
- auto["asana"] = {
152
- type: "stdio",
153
- command: "npx",
154
- args: ["-y", "asana-mcp@latest"],
155
- env: { ASANA_ACCESS_TOKEN: creds.ASANA_ACCESS_TOKEN },
156
- };
17
+ for (const entry of MCP_CATALOG) {
18
+ const skillIds = entry.triggers.skill ?? [];
19
+ if (!skillIds.some((id) => refs.has(id)))
20
+ continue;
21
+ const wired = entry.wire(creds);
22
+ if (wired)
23
+ auto[entry.id] = wired;
157
24
  }
158
25
  // Skill-declared MCP servers — only include for referenced skills.
159
26
  if (opts.skillMcpServers) {
@@ -178,175 +45,18 @@ export function buildSkillMcpServers(opts) {
178
45
  export function buildAutoMcpServers(config) {
179
46
  const auto = {};
180
47
  const creds = config.credentials;
181
- // ── Category A: Provider-config triggered ──────────────────────
182
- // GitHub MCP — inject when using GitHub source control OR GitHub Issues tracker.
183
- // @modelcontextprotocol/server-github requires GITHUB_PERSONAL_ACCESS_TOKEN.
184
- const githubToken = creds.GITHUB_TOKEN;
185
- if ((config.sourceControlProvider === "github" || config.issueTrackerProvider === "github-issues") && githubToken) {
186
- auto["github"] = {
187
- type: "stdio",
188
- command: "npx",
189
- args: ["-y", "@modelcontextprotocol/server-github@latest"],
190
- env: { GITHUB_PERSONAL_ACCESS_TOKEN: githubToken },
191
- };
192
- }
193
- // GitLab MCP — inject when source control provider is gitlab.
194
- const gitlabToken = creds.GITLAB_TOKEN;
195
- if (config.sourceControlProvider === "gitlab" && gitlabToken) {
196
- const gitlabEnv = { GITLAB_PERSONAL_ACCESS_TOKEN: gitlabToken };
197
- const baseUrl = creds.GITLAB_URL || "https://gitlab.com";
198
- if (baseUrl !== "https://gitlab.com") {
199
- gitlabEnv.GITLAB_API_URL = `${baseUrl}/api/v4`;
200
- }
201
- auto["gitlab"] = {
202
- type: "stdio",
203
- command: "npx",
204
- args: ["-y", "@modelcontextprotocol/server-gitlab@latest"],
205
- env: gitlabEnv,
206
- };
207
- }
208
- // Linear MCP — official HTTP remote MCP endpoint.
209
- const linearApiKey = creds.LINEAR_API_KEY;
210
- if (config.issueTrackerProvider === "linear" && linearApiKey) {
211
- auto["linear"] = {
212
- type: "http",
213
- url: "https://mcp.linear.app/mcp",
214
- headers: { Authorization: `Bearer ${linearApiKey}` },
215
- };
216
- }
217
- // Jira / Confluence (Atlassian) MCP — needs all 3 credentials.
218
- const jiraUrl = creds.JIRA_URL;
219
- const jiraEmail = creds.JIRA_EMAIL;
220
- const jiraApiToken = creds.JIRA_API_TOKEN;
221
- if (config.issueTrackerProvider === "jira" && jiraUrl && jiraEmail && jiraApiToken) {
222
- auto["jira"] = {
223
- type: "stdio",
224
- command: "npx",
225
- args: ["-y", "@sooperset/mcp-atlassian@latest"],
226
- env: {
227
- JIRA_URL: jiraUrl,
228
- JIRA_EMAIL: jiraEmail,
229
- JIRA_API_TOKEN: jiraApiToken,
230
- },
231
- };
232
- }
233
- // ── Observability MCP servers ──────────────────────────────────
234
- // Inject MCP for every configured observability provider whose credentials
235
- // are present. Multiple providers are supported (e.g. "loki,sentry").
236
48
  const obsProviders = new Set(config.observabilityProviders ?? []);
237
- // Datadog MCP — HTTP transport.
238
- const ddApiKey = creds.DD_API_KEY;
239
- const ddAppKey = creds.DD_APP_KEY;
240
- if (obsProviders.has("datadog") && ddApiKey && ddAppKey) {
241
- auto["datadog"] = {
242
- type: "http",
243
- url: "https://mcp.datadoghq.com/api/unstable/mcp-server/mcp",
244
- headers: { DD_API_KEY: ddApiKey, DD_APPLICATION_KEY: ddAppKey },
245
- };
246
- }
247
- // Sentry MCP — @sentry/mcp-server reads SENTRY_ACCESS_TOKEN (not SENTRY_AUTH_TOKEN).
248
- const sentryAuthToken = creds.SENTRY_AUTH_TOKEN;
249
- if (obsProviders.has("sentry") && sentryAuthToken) {
250
- const sentryEnv = { SENTRY_ACCESS_TOKEN: sentryAuthToken };
251
- const sentryUrl = creds.SENTRY_URL;
252
- if (sentryUrl && sentryUrl !== "https://sentry.io") {
253
- try {
254
- sentryEnv.SENTRY_HOST = new URL(sentryUrl).hostname;
255
- }
256
- catch {
257
- // malformed URL — leave SENTRY_HOST unset, server defaults to sentry.io
258
- }
259
- }
260
- auto["sentry"] = {
261
- type: "stdio",
262
- command: "npx",
263
- args: ["-y", "@sentry/mcp-server@latest"],
264
- env: sentryEnv,
265
- };
266
- }
267
- // New Relic MCP — HTTP transport; region-aware endpoint.
268
- const nrApiKey = creds.NEW_RELIC_API_KEY;
269
- if (obsProviders.has("newrelic") && nrApiKey) {
270
- const nrRegion = creds.NEW_RELIC_REGION;
271
- const nrEndpoint = nrRegion === "eu" ? "https://mcp.eu.newrelic.com/mcp/" : "https://mcp.newrelic.com/mcp/";
272
- auto["newrelic"] = {
273
- type: "http",
274
- url: nrEndpoint,
275
- headers: { "Api-Key": nrApiKey },
276
- };
277
- }
278
- // Better Stack MCP — HTTP remote MCP; Bearer token auth.
279
- const bsApiToken = creds.BETTERSTACK_API_TOKEN || creds.BETTERSTACK_TELEMETRY_TOKEN || creds.BETTERSTACK_UPTIME_TOKEN;
280
- if (obsProviders.has("betterstack") && bsApiToken) {
281
- auto["betterstack"] = {
282
- type: "http",
283
- url: "https://mcp.betterstack.com",
284
- headers: { Authorization: `Bearer ${bsApiToken}` },
285
- };
286
- }
287
- // ── Category B: Workspace tools (explicit opt-in) ──────────────
288
49
  const tools = new Set(config.workspaceTools ?? []);
289
- // Slack MCP — requires opt-in AND SLACK_BOT_TOKEN.
290
- if (tools.has("slack")) {
291
- const slackBotToken = creds.SLACK_BOT_TOKEN;
292
- if (slackBotToken) {
293
- const slackEnv = { SLACK_BOT_TOKEN: slackBotToken };
294
- if (creds.SLACK_TEAM_ID)
295
- slackEnv.SLACK_TEAM_ID = creds.SLACK_TEAM_ID;
296
- auto["slack"] = {
297
- type: "stdio",
298
- command: "npx",
299
- args: ["-y", "@modelcontextprotocol/server-slack@latest"],
300
- env: slackEnv,
301
- };
302
- }
303
- }
304
- // Notion MCP — requires opt-in; accepts NOTION_TOKEN or NOTION_API_KEY.
305
- if (tools.has("notion")) {
306
- const notionToken = creds.NOTION_TOKEN || creds.NOTION_API_KEY;
307
- if (notionToken) {
308
- auto["notion"] = {
309
- type: "stdio",
310
- command: "npx",
311
- args: ["-y", "@notionhq/notion-mcp-server@latest"],
312
- env: { NOTION_TOKEN: notionToken },
313
- };
314
- }
315
- }
316
- // PagerDuty MCP — HTTP remote endpoint; auth uses "Token token=<key>".
317
- if (tools.has("pagerduty")) {
318
- const pagerdutyToken = creds.PAGERDUTY_API_TOKEN;
319
- if (pagerdutyToken) {
320
- auto["pagerduty"] = {
321
- type: "http",
322
- url: "https://mcp.pagerduty.com/mcp",
323
- headers: { Authorization: `Token token=${pagerdutyToken}` },
324
- };
325
- }
326
- }
327
- // Monday.com MCP — requires opt-in AND MONDAY_TOKEN.
328
- if (tools.has("monday")) {
329
- const mondayToken = creds.MONDAY_TOKEN;
330
- if (mondayToken) {
331
- auto["monday"] = {
332
- type: "stdio",
333
- command: "npx",
334
- args: ["-y", "@mondaydotcomorg/monday-api-mcp@latest"],
335
- env: { MONDAY_TOKEN: mondayToken },
336
- };
337
- }
338
- }
339
- // Asana MCP — requires opt-in AND ASANA_ACCESS_TOKEN.
340
- if (tools.has("asana")) {
341
- const asanaToken = creds.ASANA_ACCESS_TOKEN;
342
- if (asanaToken) {
343
- auto["asana"] = {
344
- type: "stdio",
345
- command: "npx",
346
- args: ["-y", "asana-mcp@latest"],
347
- env: { ASANA_ACCESS_TOKEN: asanaToken },
348
- };
349
- }
50
+ for (const entry of MCP_CATALOG) {
51
+ const matches = (entry.triggers.sourceControl?.includes(config.sourceControlProvider ?? "") ?? false) ||
52
+ (entry.triggers.issueTracker?.includes(config.issueTrackerProvider ?? "") ?? false) ||
53
+ (entry.triggers.observability?.some((o) => obsProviders.has(o)) ?? false) ||
54
+ (entry.triggers.workspaceTool?.some((t) => tools.has(t)) ?? false);
55
+ if (!matches)
56
+ continue;
57
+ const wired = entry.wire(creds);
58
+ if (wired)
59
+ auto[entry.id] = wired;
350
60
  }
351
61
  // User-supplied servers always win on key conflict.
352
62
  return { ...auto, ...(config.userMcpServers ?? {}) };