integrate-sdk 0.8.31-dev.1 → 0.8.35

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/dist/index.js CHANGED
@@ -370,6 +370,81 @@ function methodToToolName(methodName, integrationId) {
370
370
  return `${integrationId}_${snakeCaseMethod}`;
371
371
  }
372
372
 
373
+ // src/triggers/client.ts
374
+ class TriggerClient {
375
+ config;
376
+ constructor(config) {
377
+ this.config = config;
378
+ }
379
+ async create(params) {
380
+ return this.request("POST", "/triggers", params);
381
+ }
382
+ async list(params) {
383
+ let path = "/triggers";
384
+ if (params) {
385
+ const searchParams = new URLSearchParams;
386
+ if (params.status)
387
+ searchParams.set("status", params.status);
388
+ if (params.toolName)
389
+ searchParams.set("toolName", params.toolName);
390
+ if (params.limit !== undefined)
391
+ searchParams.set("limit", params.limit.toString());
392
+ if (params.offset !== undefined)
393
+ searchParams.set("offset", params.offset.toString());
394
+ const query = searchParams.toString();
395
+ if (query)
396
+ path += `?${query}`;
397
+ }
398
+ return this.request("GET", path);
399
+ }
400
+ async get(triggerId) {
401
+ return this.request("GET", `/triggers/${triggerId}`);
402
+ }
403
+ async update(triggerId, params) {
404
+ return this.request("PATCH", `/triggers/${triggerId}`, params);
405
+ }
406
+ async delete(triggerId) {
407
+ await this.request("DELETE", `/triggers/${triggerId}`);
408
+ }
409
+ async pause(triggerId) {
410
+ return this.request("POST", `/triggers/${triggerId}/pause`);
411
+ }
412
+ async resume(triggerId) {
413
+ return this.request("POST", `/triggers/${triggerId}/resume`);
414
+ }
415
+ async run(triggerId) {
416
+ return this.request("POST", `/triggers/${triggerId}/run`);
417
+ }
418
+ async request(method, path, body) {
419
+ const url = this.config.apiBaseUrl ? `${this.config.apiBaseUrl}${this.config.apiRouteBase}${path}` : `${this.config.apiRouteBase}${path}`;
420
+ const options = {
421
+ method,
422
+ headers: {
423
+ "Content-Type": "application/json",
424
+ ...this.config.getHeaders()
425
+ }
426
+ };
427
+ if (body !== undefined) {
428
+ options.body = JSON.stringify(body);
429
+ }
430
+ const response = await fetch(url, options);
431
+ if (!response.ok) {
432
+ let errorMessage = `Request failed: ${response.statusText}`;
433
+ try {
434
+ const errorData = await response.json();
435
+ if (errorData.error) {
436
+ errorMessage = typeof errorData.error === "string" ? errorData.error : errorData.error.message || errorMessage;
437
+ }
438
+ } catch {}
439
+ throw new Error(errorMessage);
440
+ }
441
+ if (method === "DELETE" && response.status === 204) {
442
+ return;
443
+ }
444
+ return response.json();
445
+ }
446
+ }
447
+
373
448
  // src/oauth/pkce.ts
374
449
  var exports_pkce = {};
375
450
  __export(exports_pkce, {
@@ -1565,6 +1640,7 @@ class MCPClientBase {
1565
1640
  databaseDetected = false;
1566
1641
  oauthCallbackPromise;
1567
1642
  server;
1643
+ trigger;
1568
1644
  constructor(config) {
1569
1645
  this.transport = new HttpSessionTransport({
1570
1646
  url: config.serverUrl || MCP_SERVER_URL,
@@ -1607,6 +1683,10 @@ class MCPClientBase {
1607
1683
  this.authState.set(provider, { authenticated: false });
1608
1684
  }
1609
1685
  }
1686
+ const integrationHeaderValue = this.getIntegrationHeaderValue();
1687
+ if (integrationHeaderValue && this.transport.setHeader) {
1688
+ this.transport.setHeader("X-Integrations", integrationHeaderValue);
1689
+ }
1610
1690
  const providers = this.integrations.filter((p) => p.oauth).map((p) => p.oauth.provider);
1611
1691
  const usingDatabaseCallbacks = !!config.getProviderToken;
1612
1692
  if (usingDatabaseCallbacks) {
@@ -1682,6 +1762,13 @@ class MCPClientBase {
1682
1762
  this.todoist = this.createIntegrationProxy("todoist");
1683
1763
  }
1684
1764
  this.server = this.createServerProxy();
1765
+ this.trigger = new TriggerClient({
1766
+ apiRouteBase: this.apiRouteBase,
1767
+ apiBaseUrl: this.apiBaseUrl,
1768
+ getHeaders: () => ({
1769
+ "X-Integrations": this.getIntegrationHeaderValue()
1770
+ })
1771
+ });
1685
1772
  this.initializeIntegrations();
1686
1773
  }
1687
1774
  getDefaultRedirectUri(oauthApiBase, apiBaseUrl) {
@@ -1711,9 +1798,24 @@ class MCPClientBase {
1711
1798
  }
1712
1799
  });
1713
1800
  }
1801
+ getIntegrationHeaderValue() {
1802
+ return this.integrations.map((integration) => integration.id).join(",");
1803
+ }
1714
1804
  createServerProxy() {
1715
1805
  return new Proxy({}, {
1716
1806
  get: (_target, methodName) => {
1807
+ if (methodName === "listConfiguredIntegrations") {
1808
+ return async () => ({
1809
+ integrations: this.integrations.map((integration) => ({
1810
+ id: integration.id,
1811
+ name: integration.name || integration.id,
1812
+ tools: integration.tools,
1813
+ hasOAuth: !!integration.oauth,
1814
+ scopes: integration.oauth?.scopes,
1815
+ provider: integration.oauth?.provider
1816
+ }))
1817
+ });
1818
+ }
1717
1819
  return async (args, options) => {
1718
1820
  const toolName = methodToToolName(methodName, "");
1719
1821
  const finalToolName = toolName.startsWith("_") ? toolName.substring(1) : toolName;
@@ -1819,6 +1921,10 @@ class MCPClientBase {
1819
1921
  const headers = {
1820
1922
  "Content-Type": "application/json"
1821
1923
  };
1924
+ const integrationsHeader = this.getIntegrationHeaderValue();
1925
+ if (integrationsHeader) {
1926
+ headers["X-Integrations"] = integrationsHeader;
1927
+ }
1822
1928
  if (provider) {
1823
1929
  const tokenData = await this.oauthManager.getProviderToken(provider, undefined, options?.context);
1824
1930
  if (tokenData) {
@@ -2433,7 +2539,8 @@ function createNextOAuthHandler(config) {
2433
2539
  try {
2434
2540
  const body = await req.json();
2435
2541
  const authHeader = req.headers.get("authorization");
2436
- const result = await handler.handleToolCall(body, authHeader);
2542
+ const integrationsHeader = req.headers.get("x-integrations");
2543
+ const result = await handler.handleToolCall(body, authHeader, integrationsHeader);
2437
2544
  return Response.json(result);
2438
2545
  } catch (error) {
2439
2546
  console.error("[MCP Tool Call] Error:", error);
@@ -7997,6 +8104,59 @@ var init_ai = __esm(() => {
7997
8104
  init_google();
7998
8105
  });
7999
8106
 
8107
+ // node_modules/nanoid/index.browser.js
8108
+ var nanoid = (size = 21) => crypto.getRandomValues(new Uint8Array(size)).reduce((id, byte) => {
8109
+ byte &= 63;
8110
+ if (byte < 36) {
8111
+ id += byte.toString(36);
8112
+ } else if (byte < 62) {
8113
+ id += (byte - 26).toString(36).toUpperCase();
8114
+ } else if (byte > 62) {
8115
+ id += "-";
8116
+ } else {
8117
+ id += "_";
8118
+ }
8119
+ return id;
8120
+ }, "");
8121
+ var init_index_browser = () => {};
8122
+
8123
+ // src/triggers/utils.ts
8124
+ var exports_utils = {};
8125
+ __export(exports_utils, {
8126
+ validateStatusTransition: () => validateStatusTransition,
8127
+ generateTriggerId: () => generateTriggerId,
8128
+ extractProviderFromToolName: () => extractProviderFromToolName,
8129
+ calculateHasMore: () => calculateHasMore
8130
+ });
8131
+ function generateTriggerId() {
8132
+ return `trig_${nanoid(12)}`;
8133
+ }
8134
+ function extractProviderFromToolName(toolName) {
8135
+ const parts = toolName.split("_");
8136
+ return parts[0] || toolName;
8137
+ }
8138
+ function validateStatusTransition(currentStatus, targetStatus) {
8139
+ if (targetStatus === "paused" && currentStatus !== "active") {
8140
+ return {
8141
+ valid: false,
8142
+ error: `Cannot pause trigger with status '${currentStatus}'. Only 'active' triggers can be paused.`
8143
+ };
8144
+ }
8145
+ if (targetStatus === "active" && currentStatus !== "paused") {
8146
+ return {
8147
+ valid: false,
8148
+ error: `Cannot resume trigger with status '${currentStatus}'. Only 'paused' triggers can be resumed.`
8149
+ };
8150
+ }
8151
+ return { valid: true };
8152
+ }
8153
+ function calculateHasMore(offset, returnedCount, total) {
8154
+ return offset + returnedCount < total;
8155
+ }
8156
+ var init_utils2 = __esm(() => {
8157
+ init_index_browser();
8158
+ });
8159
+
8000
8160
  // src/server.ts
8001
8161
  var exports_server = {};
8002
8162
  __export(exports_server, {
@@ -8196,6 +8356,7 @@ function createMCPServer(config) {
8196
8356
  try {
8197
8357
  const body = await webRequest.json();
8198
8358
  const authHeader = webRequest.headers.get("authorization");
8359
+ const integrationsHeader = webRequest.headers.get("x-integrations");
8199
8360
  const { OAuthHandler: OAuthHandler2 } = await Promise.resolve().then(() => exports_base_handler);
8200
8361
  const oauthHandler = new OAuthHandler2({
8201
8362
  providers,
@@ -8205,7 +8366,7 @@ function createMCPServer(config) {
8205
8366
  removeProviderToken: config.removeProviderToken,
8206
8367
  getSessionContext: config.getSessionContext
8207
8368
  });
8208
- const result = await oauthHandler.handleToolCall(body, authHeader);
8369
+ const result = await oauthHandler.handleToolCall(body, authHeader, integrationsHeader);
8209
8370
  const response2 = Response.json(result);
8210
8371
  if (oauthHandler.hasDatabaseCallbacks()) {
8211
8372
  response2.headers.set("X-Integrate-Use-Database", "true");
@@ -8216,13 +8377,308 @@ function createMCPServer(config) {
8216
8377
  return Response.json({ error: error.message || "Failed to execute tool call" }, { status: error.statusCode || 500 });
8217
8378
  }
8218
8379
  }
8380
+ if (segments.length >= 1 && segments[0] === "triggers") {
8381
+ if (!config.triggers) {
8382
+ return Response.json({ error: "Triggers not configured. Add triggers callbacks to createMCPServer config." }, { status: 501 });
8383
+ }
8384
+ try {
8385
+ const context2 = config.getSessionContext ? await config.getSessionContext(webRequest) : undefined;
8386
+ if (segments.length === 1) {
8387
+ if (method === "GET") {
8388
+ const url = new URL(webRequest.url);
8389
+ const params = {
8390
+ status: url.searchParams.get("status"),
8391
+ toolName: url.searchParams.get("toolName") || undefined,
8392
+ limit: url.searchParams.get("limit") ? parseInt(url.searchParams.get("limit")) : undefined,
8393
+ offset: url.searchParams.get("offset") ? parseInt(url.searchParams.get("offset")) : undefined
8394
+ };
8395
+ const callbackResult = await config.triggers.list(params, context2);
8396
+ const { calculateHasMore: calculateHasMore2 } = await Promise.resolve().then(() => (init_utils2(), exports_utils));
8397
+ const offset = params.offset || 0;
8398
+ const hasMore = calculateHasMore2(offset, callbackResult.triggers.length, callbackResult.total);
8399
+ return Response.json({
8400
+ triggers: callbackResult.triggers,
8401
+ total: callbackResult.total,
8402
+ hasMore
8403
+ });
8404
+ } else if (method === "POST") {
8405
+ const body = await webRequest.json();
8406
+ const { generateTriggerId: generateTriggerId2, extractProviderFromToolName: extractProviderFromToolName2 } = await Promise.resolve().then(() => (init_utils2(), exports_utils));
8407
+ const triggerId = generateTriggerId2();
8408
+ const provider = body.toolName ? extractProviderFromToolName2(body.toolName) : undefined;
8409
+ const trigger = {
8410
+ id: triggerId,
8411
+ ...body,
8412
+ provider,
8413
+ status: body.status || "active",
8414
+ createdAt: new Date().toISOString(),
8415
+ updatedAt: new Date().toISOString(),
8416
+ runCount: 0
8417
+ };
8418
+ const created = await config.triggers.create(trigger, context2);
8419
+ const schedulerUrl = config.schedulerUrl || config.serverUrl || "https://mcp.integrate.dev";
8420
+ const callbackBaseUrl = process.env.INTEGRATE_URL || (typeof window !== "undefined" ? window.location.origin : "http://localhost:3000");
8421
+ try {
8422
+ await fetch(`${schedulerUrl}/scheduler/register`, {
8423
+ method: "POST",
8424
+ headers: {
8425
+ "Content-Type": "application/json",
8426
+ "X-API-KEY": config.apiKey || ""
8427
+ },
8428
+ body: JSON.stringify({
8429
+ triggerId: created.id,
8430
+ schedule: created.schedule,
8431
+ callbackUrl: `${callbackBaseUrl}/api/integrate/triggers/${created.id}/execute`,
8432
+ completeUrl: `${callbackBaseUrl}/api/integrate/triggers/${created.id}/complete`,
8433
+ metadata: {
8434
+ userId: context2?.userId,
8435
+ provider: created.provider
8436
+ }
8437
+ })
8438
+ });
8439
+ } catch (scheduleError) {
8440
+ console.error("[Trigger] Failed to register with scheduler:", scheduleError);
8441
+ }
8442
+ return Response.json(created, { status: 201 });
8443
+ }
8444
+ } else if (segments.length >= 2) {
8445
+ const triggerId = segments[1];
8446
+ if (!triggerId) {
8447
+ return Response.json({ error: "Trigger ID is required" }, { status: 400 });
8448
+ }
8449
+ const subAction = segments.length > 2 ? segments[2] : undefined;
8450
+ if (subAction === "pause" && method === "POST") {
8451
+ const trigger = await config.triggers.get(triggerId, context2);
8452
+ if (!trigger) {
8453
+ return Response.json({ error: "Trigger not found" }, { status: 404 });
8454
+ }
8455
+ const { validateStatusTransition: validateStatusTransition2 } = await Promise.resolve().then(() => (init_utils2(), exports_utils));
8456
+ const validation = validateStatusTransition2(trigger.status, "paused");
8457
+ if (!validation.valid) {
8458
+ return Response.json({ error: validation.error }, { status: 400 });
8459
+ }
8460
+ const updated = await config.triggers.update(triggerId, {
8461
+ status: "paused",
8462
+ updatedAt: new Date().toISOString()
8463
+ }, context2);
8464
+ const schedulerUrl = config.schedulerUrl || config.serverUrl || "https://mcp.integrate.dev";
8465
+ try {
8466
+ await fetch(`${schedulerUrl}/scheduler/pause`, {
8467
+ method: "POST",
8468
+ headers: {
8469
+ "Content-Type": "application/json",
8470
+ "X-API-KEY": config.apiKey || ""
8471
+ },
8472
+ body: JSON.stringify({ triggerId })
8473
+ });
8474
+ } catch (error) {
8475
+ console.error("[Trigger] Failed to pause in scheduler:", error);
8476
+ }
8477
+ return Response.json(updated);
8478
+ } else if (subAction === "resume" && method === "POST") {
8479
+ const trigger = await config.triggers.get(triggerId, context2);
8480
+ if (!trigger) {
8481
+ return Response.json({ error: "Trigger not found" }, { status: 404 });
8482
+ }
8483
+ const { validateStatusTransition: validateStatusTransition2 } = await Promise.resolve().then(() => (init_utils2(), exports_utils));
8484
+ const validation = validateStatusTransition2(trigger.status, "active");
8485
+ if (!validation.valid) {
8486
+ return Response.json({ error: validation.error }, { status: 400 });
8487
+ }
8488
+ const updated = await config.triggers.update(triggerId, {
8489
+ status: "active",
8490
+ updatedAt: new Date().toISOString()
8491
+ }, context2);
8492
+ const schedulerUrl = config.schedulerUrl || config.serverUrl || "https://mcp.integrate.dev";
8493
+ try {
8494
+ await fetch(`${schedulerUrl}/scheduler/resume`, {
8495
+ method: "POST",
8496
+ headers: {
8497
+ "Content-Type": "application/json",
8498
+ "X-API-KEY": config.apiKey || ""
8499
+ },
8500
+ body: JSON.stringify({ triggerId })
8501
+ });
8502
+ } catch (error) {
8503
+ console.error("[Trigger] Failed to resume in scheduler:", error);
8504
+ }
8505
+ return Response.json(updated);
8506
+ } else if (subAction === "run" && method === "POST") {
8507
+ const trigger = await config.triggers.get(triggerId, context2);
8508
+ if (!trigger) {
8509
+ return Response.json({ error: "Trigger not found" }, { status: 404 });
8510
+ }
8511
+ if (!trigger.provider) {
8512
+ return Response.json({ error: "Trigger has no provider configured" }, { status: 400 });
8513
+ }
8514
+ const providerToken = config.getProviderToken ? await config.getProviderToken(trigger.provider, undefined, context2) : undefined;
8515
+ if (!providerToken) {
8516
+ return Response.json({ error: "No OAuth token available for this trigger" }, { status: 401 });
8517
+ }
8518
+ const { OAuthHandler: OAuthHandler2 } = await Promise.resolve().then(() => exports_base_handler);
8519
+ const oauthHandler = new OAuthHandler2({
8520
+ providers,
8521
+ serverUrl: config.serverUrl,
8522
+ apiKey: config.apiKey,
8523
+ setProviderToken: config.setProviderToken,
8524
+ removeProviderToken: config.removeProviderToken,
8525
+ getSessionContext: config.getSessionContext
8526
+ });
8527
+ const startTime = Date.now();
8528
+ try {
8529
+ const result = await oauthHandler.handleToolCall({ name: trigger.toolName, arguments: trigger.toolArguments }, `Bearer ${providerToken.accessToken}`, null);
8530
+ const duration = Date.now() - startTime;
8531
+ const executionResult = {
8532
+ success: true,
8533
+ result,
8534
+ executedAt: new Date().toISOString(),
8535
+ duration
8536
+ };
8537
+ await config.triggers.update(triggerId, {
8538
+ lastRunAt: executionResult.executedAt,
8539
+ runCount: (trigger.runCount || 0) + 1,
8540
+ lastResult: result,
8541
+ lastError: undefined
8542
+ }, context2);
8543
+ return Response.json(executionResult);
8544
+ } catch (error) {
8545
+ const duration = Date.now() - startTime;
8546
+ const executionResult = {
8547
+ success: false,
8548
+ error: error.message || "Tool execution failed",
8549
+ executedAt: new Date().toISOString(),
8550
+ duration
8551
+ };
8552
+ await config.triggers.update(triggerId, {
8553
+ lastRunAt: executionResult.executedAt,
8554
+ runCount: (trigger.runCount || 0) + 1,
8555
+ lastError: error.message,
8556
+ status: "failed"
8557
+ }, context2);
8558
+ return Response.json(executionResult, { status: 500 });
8559
+ }
8560
+ } else if (subAction === "execute" && method === "GET") {
8561
+ const apiKey = webRequest.headers.get("x-api-key");
8562
+ if (!apiKey || apiKey !== config.apiKey) {
8563
+ return Response.json({ error: "Unauthorized" }, { status: 401 });
8564
+ }
8565
+ const trigger = await config.triggers.get(triggerId, context2);
8566
+ if (!trigger) {
8567
+ return Response.json({ error: "Trigger not found" }, { status: 404 });
8568
+ }
8569
+ if (!trigger.provider) {
8570
+ return Response.json({ error: "Trigger has no provider configured" }, { status: 400 });
8571
+ }
8572
+ const providerToken = config.getProviderToken ? await config.getProviderToken(trigger.provider, undefined, context2) : undefined;
8573
+ if (!providerToken) {
8574
+ return Response.json({ error: "No OAuth token available for this trigger" }, { status: 401 });
8575
+ }
8576
+ return Response.json({
8577
+ trigger: {
8578
+ id: trigger.id,
8579
+ toolName: trigger.toolName,
8580
+ toolArguments: trigger.toolArguments,
8581
+ provider: trigger.provider
8582
+ },
8583
+ accessToken: providerToken.accessToken,
8584
+ tokenType: providerToken.tokenType || "Bearer"
8585
+ });
8586
+ } else if (subAction === "complete" && method === "POST") {
8587
+ const apiKey = webRequest.headers.get("x-api-key");
8588
+ if (!apiKey || apiKey !== config.apiKey) {
8589
+ return Response.json({ error: "Unauthorized" }, { status: 401 });
8590
+ }
8591
+ const body = await webRequest.json();
8592
+ const trigger = await config.triggers.get(triggerId, context2);
8593
+ if (!trigger) {
8594
+ return Response.json({ error: "Trigger not found" }, { status: 404 });
8595
+ }
8596
+ const updates = {
8597
+ lastRunAt: body.executedAt,
8598
+ runCount: (trigger.runCount || 0) + 1
8599
+ };
8600
+ if (body.success) {
8601
+ updates.lastResult = body.result;
8602
+ updates.lastError = undefined;
8603
+ if (trigger.schedule.type === "once") {
8604
+ updates.status = "completed";
8605
+ }
8606
+ } else {
8607
+ updates.lastError = body.error;
8608
+ updates.status = "failed";
8609
+ }
8610
+ await config.triggers.update(triggerId, updates, context2);
8611
+ return Response.json({ success: true });
8612
+ } else if (!subAction && method === "GET") {
8613
+ const trigger = await config.triggers.get(triggerId, context2);
8614
+ if (!trigger) {
8615
+ return Response.json({ error: "Trigger not found" }, { status: 404 });
8616
+ }
8617
+ return Response.json(trigger);
8618
+ } else if (!subAction && method === "PATCH") {
8619
+ const body = await webRequest.json();
8620
+ const trigger = await config.triggers.get(triggerId, context2);
8621
+ if (!trigger) {
8622
+ return Response.json({ error: "Trigger not found" }, { status: 404 });
8623
+ }
8624
+ const updates = {
8625
+ ...body,
8626
+ updatedAt: new Date().toISOString()
8627
+ };
8628
+ const updated = await config.triggers.update(triggerId, updates, context2);
8629
+ if (body.schedule) {
8630
+ const schedulerUrl = config.schedulerUrl || config.serverUrl || "https://mcp.integrate.dev";
8631
+ try {
8632
+ await fetch(`${schedulerUrl}/scheduler/update`, {
8633
+ method: "POST",
8634
+ headers: {
8635
+ "Content-Type": "application/json",
8636
+ "X-API-KEY": config.apiKey || ""
8637
+ },
8638
+ body: JSON.stringify({
8639
+ triggerId,
8640
+ schedule: body.schedule
8641
+ })
8642
+ });
8643
+ } catch (error) {
8644
+ console.error("[Trigger] Failed to update scheduler:", error);
8645
+ }
8646
+ }
8647
+ return Response.json(updated);
8648
+ } else if (!subAction && method === "DELETE") {
8649
+ await config.triggers.delete(triggerId, context2);
8650
+ const schedulerUrl = config.schedulerUrl || config.serverUrl || "https://mcp.integrate.dev";
8651
+ try {
8652
+ await fetch(`${schedulerUrl}/scheduler/unregister`, {
8653
+ method: "POST",
8654
+ headers: {
8655
+ "Content-Type": "application/json",
8656
+ "X-API-KEY": config.apiKey || ""
8657
+ },
8658
+ body: JSON.stringify({ triggerId })
8659
+ });
8660
+ } catch (error) {
8661
+ console.error("[Trigger] Failed to unregister from scheduler:", error);
8662
+ }
8663
+ return new Response(null, { status: 204 });
8664
+ }
8665
+ }
8666
+ return Response.json({ error: "Invalid trigger route or method" }, { status: 404 });
8667
+ } catch (error) {
8668
+ console.error("[Trigger] Error:", error);
8669
+ return Response.json({ error: error.message || "Failed to process trigger request" }, { status: error.statusCode || 500 });
8670
+ }
8671
+ }
8219
8672
  if (segments.length > 0) {
8220
- if (segments.length === 2 && segments[0] !== "oauth") {
8673
+ if (segments.length === 2 && segments[0] !== "oauth" && segments[0] !== "triggers") {
8221
8674
  return Response.json({ error: `Invalid route: /${segments.join("/")}` }, { status: 404 });
8222
8675
  }
8223
8676
  if (segments.length === 1 && segments[0] === "mcp") {
8224
8677
  return Response.json({ error: `Method ${method} not allowed for /mcp route. Use POST.` }, { status: 405 });
8225
8678
  }
8679
+ if (segments.length >= 1 && segments[0] === "triggers") {
8680
+ return Response.json({ error: `Invalid trigger route or method` }, { status: 404 });
8681
+ }
8226
8682
  }
8227
8683
  if (method === "GET" && action === "callback") {
8228
8684
  const url = new URL(webRequest.url);
@@ -9104,7 +9560,7 @@ class OAuthHandler {
9104
9560
  const data = await response.json();
9105
9561
  return data;
9106
9562
  }
9107
- async handleToolCall(request, authHeader) {
9563
+ async handleToolCall(request, authHeader, integrationsHeader) {
9108
9564
  const url = this.serverUrl;
9109
9565
  const headers = this.getHeaders({
9110
9566
  "Content-Type": "application/json"
@@ -9112,6 +9568,9 @@ class OAuthHandler {
9112
9568
  if (authHeader && authHeader.startsWith("Bearer ")) {
9113
9569
  headers["Authorization"] = authHeader;
9114
9570
  }
9571
+ if (integrationsHeader) {
9572
+ headers["X-Integrations"] = integrationsHeader;
9573
+ }
9115
9574
  const jsonRpcRequest = {
9116
9575
  jsonrpc: "2.0",
9117
9576
  id: Date.now() + Math.random(),
@@ -9325,6 +9784,7 @@ export {
9325
9784
  clearClientCache,
9326
9785
  calcomIntegration,
9327
9786
  airtableIntegration,
9787
+ TriggerClient,
9328
9788
  ToolCallError,
9329
9789
  TokenExpiredError,
9330
9790
  OAuthWindowManager,