@shipfox/api-integration-core 7.0.1 → 7.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +11 -14
- package/CHANGELOG.md +21 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/presentation/routes/agent-tools-gateway/dispatch.d.ts.map +1 -1
- package/dist/presentation/routes/agent-tools-gateway/dispatch.js +22 -3
- package/dist/presentation/routes/agent-tools-gateway/dispatch.js.map +1 -1
- package/dist/presentation/routes/agent-tools-gateway/index.d.ts.map +1 -1
- package/dist/presentation/routes/agent-tools-gateway/index.js +20 -2
- package/dist/presentation/routes/agent-tools-gateway/index.js.map +1 -1
- package/dist/presentation/routes/agent-tools-gateway/mcp-server.d.ts.map +1 -1
- package/dist/presentation/routes/agent-tools-gateway/mcp-server.js +11 -2
- package/dist/presentation/routes/agent-tools-gateway/mcp-server.js.map +1 -1
- package/dist/temporal/workflows/index.bundle.js +17164 -3306
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +14 -31
- package/src/index.ts +2 -0
- package/src/presentation/routes/agent-tools-gateway/dispatch.ts +14 -2
- package/src/presentation/routes/agent-tools-gateway/index.ts +16 -2
- package/src/presentation/routes/agent-tools-gateway/mcp-server.ts +5 -1
- package/tsconfig.build.tsbuildinfo +1 -1
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,20 +1,17 @@
|
|
|
1
1
|
$ shipfox-swc && shipfox-temporal-bundle dist/temporal/workflows/index.js
|
|
2
|
-
Successfully compiled: 50 files with swc (
|
|
3
|
-
2026-07-
|
|
4
|
-
|
|
5
|
-
modules
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
../../../../node_modules/.pnpm/long@5.3.2/node_modules/long/index.js 43.2 KiB [built] [code generated]
|
|
10
|
-
../../../../node_modules/.pnpm/ms@3.0.0-canary.1/node_modules/ms/dist/index.mjs 3.26 KiB [built] [code generated]
|
|
11
|
-
modules by path ./dist/temporal/workflows/ 1020 bytes
|
|
12
|
-
./dist/temporal/workflows/index-autogenerated-entrypoint.cjs 535 bytes [built] [code generated]
|
|
2
|
+
Successfully compiled: 50 files with swc (523.83ms)
|
|
3
|
+
2026-07-22T13:12:11.575Z [INFO] asset workflow-bundle-646aca428e9943f8cf17.js 3.17 MiB [emitted] [immutable] (name: main)
|
|
4
|
+
orphan modules 33.5 KiB [orphan] 21 modules
|
|
5
|
+
runtime modules 1.13 KiB 5 modules
|
|
6
|
+
modules by path ../../../../node_modules/.pnpm/ 970 KiB 196 modules
|
|
7
|
+
modules by path ./dist/temporal/workflows/ 1.39 KiB
|
|
8
|
+
./dist/temporal/workflows/index-autogenerated-entrypoint.cjs 941 bytes [built] [code generated]
|
|
13
9
|
./dist/temporal/workflows/index.js 82 bytes [built] [code generated]
|
|
14
10
|
./dist/temporal/workflows/prune-webhook-deliveries-cron.js 405 bytes [built] [code generated]
|
|
15
11
|
optional modules 30 bytes [optional]
|
|
16
12
|
__temporal_custom_payload_converter (ignored) 15 bytes [optional] [built] [code generated]
|
|
17
13
|
__temporal_custom_failure_converter (ignored) 15 bytes [optional] [built] [code generated]
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
14
|
+
../../../shared/node/temporal/dist/workflow-error-interceptor.js 1.21 KiB [built] [code generated]
|
|
15
|
+
webpack 5.107.2 compiled successfully in 9255 ms
|
|
16
|
+
2026-07-22T13:12:11.593Z [INFO] Workflow bundle created { size: '3.17MB' }
|
|
17
|
+
/home/runner/work/shipfox/shipfox/libs/api/integration/core/dist/temporal/workflows/index.js: 3323154 bytes
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# @shipfox/api-integration-core
|
|
2
2
|
|
|
3
|
+
## 7.1.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- ac42c96: Adds boundary-owned reporting for unexpected API runtime failures while preserving expected client and provider outcomes.
|
|
8
|
+
- Updated dependencies [ac42c96]
|
|
9
|
+
- Updated dependencies [6ce08c0]
|
|
10
|
+
- @shipfox/node-error-monitoring@0.2.0
|
|
11
|
+
- @shipfox/node-fastify@0.3.0
|
|
12
|
+
- @shipfox/node-module@0.5.0
|
|
13
|
+
- @shipfox/node-temporal@0.4.0
|
|
14
|
+
- @shipfox/api-integration-github@7.1.0
|
|
15
|
+
- @shipfox/node-opentelemetry@0.6.0
|
|
16
|
+
- @shipfox/api-auth-context@7.1.0
|
|
17
|
+
- @shipfox/api-integration-gitea@7.1.0
|
|
18
|
+
- @shipfox/api-integration-jira@7.1.0
|
|
19
|
+
- @shipfox/api-integration-linear@7.1.0
|
|
20
|
+
- @shipfox/api-integration-sentry@7.1.0
|
|
21
|
+
- @shipfox/api-integration-slack@7.1.0
|
|
22
|
+
- @shipfox/api-integration-webhook@7.1.0
|
|
23
|
+
|
|
3
24
|
## 7.0.1
|
|
4
25
|
|
|
5
26
|
### Patch Changes
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,uBAAuB,EAE7B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,yCAAyC,CAAC;AACnF,OAAO,KAAK,EAAC,2BAA2B,EAAC,MAAM,0CAA0C,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { dirname, resolve } from 'node:path';
|
|
2
2
|
import { fileURLToPath } from 'node:url';
|
|
3
3
|
import { integrationsEventSchemas } from '@shipfox/api-integration-core-dto';
|
|
4
|
+
import { reportError } from '@shipfox/node-error-monitoring';
|
|
4
5
|
import { logger } from '@shipfox/node-opentelemetry';
|
|
5
6
|
import { WebhookProcessorNotConfiguredError } from '#core/errors.js';
|
|
6
7
|
import { createIntegrationProviderRegistry } from '#core/providers/registry.js';
|
|
@@ -58,6 +59,9 @@ export async function createIntegrationsContext(options = {}) {
|
|
|
58
59
|
logger().error({
|
|
59
60
|
err: error
|
|
60
61
|
}, 'Integration startup task failed, continuing boot');
|
|
62
|
+
reportError(error, {
|
|
63
|
+
boundary: 'integration.startup'
|
|
64
|
+
});
|
|
61
65
|
}
|
|
62
66
|
}
|
|
63
67
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import {dirname, resolve} from 'node:path';\nimport {fileURLToPath} from 'node:url';\nimport {\n integrationsEventSchemas,\n type StoredWebhookRequest,\n type WebhookProcessingResult,\n type WebhookRequestProcessor,\n type WebhookRouteId,\n} from '@shipfox/api-integration-core-dto';\nimport type {WorkflowsModuleClient} from '@shipfox/api-workflows-dto/inter-module';\nimport type {WorkspacesInterModuleClient} from '@shipfox/api-workspaces-dto/inter-module';\nimport type {ModuleService, ShipfoxModule} from '@shipfox/node-module';\nimport {logger} from '@shipfox/node-opentelemetry';\nimport type {IntegrationProvider} from '#core/entities/provider.js';\nimport {WebhookProcessorNotConfiguredError} from '#core/errors.js';\nimport {\n createIntegrationProviderRegistry,\n type IntegrationProviderRegistry,\n} from '#core/providers/registry.js';\nimport {\n createSourceControlIntegrationService,\n type IntegrationSourceControlService,\n} from '#core/source-control-service.js';\nimport {getIntegrationConnectionById} from '#db/connections.js';\nimport {db} from '#db/db.js';\nimport {migrationsPath} from '#db/migrations.js';\nimport {integrationsOutbox} from '#db/schema/outbox.js';\nimport {createIntegrationsInterModulePresentation} from '#presentation/inter-module.js';\nimport {createIntegrationRoutes} from '#presentation/routes/index.js';\nimport {loadEnabledProviderModules} from '#providers/modules.js';\nimport type {\n IntegrationModuleParts,\n IntegrationProviderSecrets,\n WebhookProcessorRegistration,\n} from '#providers/types.js';\nimport {createIntegrationsMaintenanceActivities} from '#temporal/activities/index.js';\nimport {INTEGRATIONS_MAINTENANCE_TASK_QUEUE} from '#temporal/constants.js';\n\nconst packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');\nconst maintenanceWorkflowsPath = resolve(packageRoot, 'dist/temporal/workflows/index.js');\n\nexport type {\n StoredWebhookRequest,\n WebhookProcessingResult,\n WebhookRequestProcessor,\n WebhookRouteId,\n} from '@shipfox/api-integration-core-dto';\nexport {\n buildProviderRepositoryId,\n MAX_REPOSITORY_FILE_BYTES,\n parseProviderRepositoryId,\n} from '@shipfox/api-integration-core-dto';\nexport type {\n AgentToolCatalogs,\n AgentToolSelectionCatalogs,\n LoadWorkspaceConnectionSnapshot,\n WorkspaceConnectionSnapshot,\n WorkspaceConnectionSnapshotEntry,\n} from '#core/agent-tool-selection.js';\nexport {\n buildAgentToolCatalogs,\n buildAgentToolSelectionCatalogs,\n createWorkspaceConnectionSnapshotLoader,\n} from '#core/agent-tool-selection.js';\nexport type {\n IntegrationConnection,\n IntegrationConnectionLifecycleStatus,\n} from '#core/entities/connection.js';\nexport type {\n IntegrationCapability,\n IntegrationProvider,\n IntegrationProviderAdapters,\n IntegrationProviderKind,\n RegisteredIntegrationProvider,\n} from '#core/entities/provider.js';\nexport type {IntegrationProviderErrorReason} from '#core/errors.js';\nexport {\n ConnectionSlugConflictError,\n IntegrationCapabilityUnavailableError,\n IntegrationCheckoutUnsupportedError,\n IntegrationConnectionInactiveError,\n IntegrationConnectionNotFoundError,\n IntegrationConnectionWorkspaceMismatchError,\n IntegrationProviderError,\n IntegrationProviderUnavailableError,\n WebhookProcessorNotConfiguredError,\n} from '#core/errors.js';\nexport type {\n AgentToolCallInput,\n AgentToolCatalogEntry,\n AgentToolCatalogMethod,\n AgentToolJsonSchema,\n AgentToolSensitivity,\n AgentToolSession,\n AgentToolsProvider,\n OpenAgentToolsSessionInput,\n} from '#core/providers/agent-tools.js';\nexport {redactCheckoutSpec} from '#core/providers/redact-checkout-spec.js';\nexport type {IntegrationProviderRegistry} from '#core/providers/registry.js';\nexport type {\n CheckoutCredentials,\n CheckoutPermissions,\n CheckoutSpec,\n CreateCheckoutSpecInput,\n FetchFileInput,\n FileEntry,\n FilePage,\n FileSnapshot,\n ListFilesInput,\n ListRepositoriesInput,\n RepositoryPage,\n RepositorySnapshot,\n RepositoryVisibility,\n ResolveRepositoryInput,\n SourceControlProvider,\n} from '#core/providers/source-control.js';\nexport type {IntegrationSourceControlService} from '#core/source-control-service.js';\nexport {createSourceControlIntegrationService} from '#core/source-control-service.js';\nexport type {GetIntegrationConnectionByIdFn} from '#db/connections.js';\nexport {getIntegrationConnectionById} from '#db/connections.js';\nexport type {\n ClaimWebhookDeliveryFn,\n PublishIntegrationEventReceivedFn,\n PublishIntegrationEventReceivedParams,\n PublishIntegrationEventReceivedResult,\n PublishSourcePushFn,\n PublishSourcePushParams,\n RecordDeliveryOnlyFn,\n RecordDeliveryOnlyParams,\n} from '#db/webhook-deliveries.js';\nexport {claimWebhookDelivery, pruneWebhookDeliveries} from '#db/webhook-deliveries.js';\nexport {integrationRouteErrorHandler} from '#presentation/routes/errors.js';\n\nexport interface CreateIntegrationsModuleOptions {\n providers?: IntegrationProvider[] | undefined;\n /**\n * Pre-built module parts, bypassing config-gated provider loading. Test-only seam\n * for exercising a provider's database, workers, or startup tasks directly. Takes\n * precedence over `providers`.\n */\n parts?: IntegrationModuleParts[] | undefined;\n secrets?: IntegrationProviderSecrets | undefined;\n workspaces?: WorkspacesInterModuleClient | undefined;\n agentTools?:\n | {\n workflows: WorkflowsModuleClient;\n }\n | undefined;\n webhookDeliverySource?: WebhookDeliverySource | undefined;\n}\n\n/**\n * Hosted runtimes implement this port to receive stored webhook requests. The\n * integration module starts its returned service after migrations complete.\n */\nexport interface WebhookDeliverySource {\n createService(processor: WebhookRequestProcessor): ModuleService;\n}\n\nexport interface IntegrationsContext {\n module: ShipfoxModule;\n registry: IntegrationProviderRegistry;\n capabilities: {\n sourceControl: IntegrationSourceControlService;\n };\n sourceControl: IntegrationSourceControlService;\n webhookProcessor: WebhookRequestProcessor;\n /**\n * Runs every enabled provider's one-shot boot-time tasks, after modules are initialized\n * (migrations done). Failures are isolated and logged, never rethrown, so a provider task\n * can never gate API boot. No-op when no enabled provider contributes a task.\n */\n runStartupTasks: () => Promise<void>;\n}\n\nexport async function createIntegrationsModule(\n options: CreateIntegrationsModuleOptions = {},\n): Promise<ShipfoxModule> {\n return (await createIntegrationsContext(options)).module;\n}\n\nexport async function createIntegrationsContext(\n options: CreateIntegrationsModuleOptions = {},\n): Promise<IntegrationsContext> {\n const workspaces = options.workspaces;\n const parts: IntegrationModuleParts[] =\n options.parts ??\n (options.providers\n ? options.providers.map((provider) => ({\n provider,\n webhookProcessors: provider.webhookProcessors,\n }))\n : await loadEnabledProviderModules({\n secrets: options.secrets,\n ...(workspaces\n ? {\n requireActiveWorkspaceMembership: (input: {\n workspaceId: string;\n userId: string;\n memberships: ReadonlyArray<\n import('@shipfox/api-auth-context').UserContextMembership\n >;\n }) =>\n workspaces.requireActiveMembership({\n ...input,\n memberships: [...input.memberships],\n }),\n }\n : {}),\n }));\n\n const registry = createIntegrationProviderRegistry(parts.map((part) => part.provider));\n const sourceControl = createSourceControlIntegrationService({\n registry,\n getIntegrationConnectionById,\n });\n const webhookProcessor = createComposedWebhookProcessor(\n parts.flatMap((part) => part.webhookProcessors ?? []),\n );\n\n async function runStartupTasks(): Promise<void> {\n for (const task of parts.flatMap((part) => part.startupTasks ?? [])) {\n // A provider convenience must never gate API boot.\n try {\n await task();\n } catch (error) {\n logger().error({err: error}, 'Integration startup task failed, continuing boot');\n }\n }\n }\n\n const module: ShipfoxModule = {\n name: 'integrations',\n interModulePresentations: [\n createIntegrationsInterModulePresentation({registry, sourceControl}),\n ],\n startupTasks: runStartupTasks,\n database: [\n {db, migrationsPath},\n ...parts.flatMap((part) => (part.database ? [part.database] : [])),\n ],\n routes: createIntegrationRoutes(registry, sourceControl, {\n agentTools: options.agentTools\n ? {\n workflows: options.agentTools.workflows,\n getIntegrationConnectionById,\n }\n : undefined,\n }),\n e2eRoutes: parts.flatMap((part) => part.e2eRoutes ?? []),\n publishers: [\n {name: 'integrations', table: integrationsOutbox, db, eventSchemas: integrationsEventSchemas},\n ],\n workers: [\n {\n taskQueue: INTEGRATIONS_MAINTENANCE_TASK_QUEUE,\n workflowsPath: maintenanceWorkflowsPath,\n activities: createIntegrationsMaintenanceActivities,\n workflows: [\n {\n name: 'pruneWebhookDeliveriesCron',\n id: 'integrations-prune-webhook-deliveries',\n cronSchedule: '0 3 * * *',\n },\n ],\n },\n ...parts.flatMap((part) => part.workers ?? []),\n ],\n ...(options.webhookDeliverySource\n ? {services: [options.webhookDeliverySource.createService(webhookProcessor)]}\n : {}),\n };\n\n return {\n module,\n registry,\n capabilities: {sourceControl},\n sourceControl,\n webhookProcessor,\n runStartupTasks,\n };\n}\n\nfunction createComposedWebhookProcessor(\n registrations: WebhookProcessorRegistration[],\n): WebhookRequestProcessor {\n const processors = new Map<WebhookRouteId, WebhookRequestProcessor>();\n for (const registration of registrations) {\n for (const routeId of registration.routeIds) {\n if (processors.has(routeId)) {\n throw new Error(`Webhook processor is registered more than once for ${routeId}`);\n }\n processors.set(routeId, registration.processor);\n }\n }\n\n return {\n async process(request: StoredWebhookRequest): Promise<WebhookProcessingResult> {\n const processor = processors.get(request.route_id);\n if (!processor) {\n throw new WebhookProcessorNotConfiguredError(request.route_id);\n }\n return await processor.process(request);\n },\n };\n}\n"],"names":["dirname","resolve","fileURLToPath","integrationsEventSchemas","logger","WebhookProcessorNotConfiguredError","createIntegrationProviderRegistry","createSourceControlIntegrationService","getIntegrationConnectionById","db","migrationsPath","integrationsOutbox","createIntegrationsInterModulePresentation","createIntegrationRoutes","loadEnabledProviderModules","createIntegrationsMaintenanceActivities","INTEGRATIONS_MAINTENANCE_TASK_QUEUE","packageRoot","url","maintenanceWorkflowsPath","buildProviderRepositoryId","MAX_REPOSITORY_FILE_BYTES","parseProviderRepositoryId","buildAgentToolCatalogs","buildAgentToolSelectionCatalogs","createWorkspaceConnectionSnapshotLoader","ConnectionSlugConflictError","IntegrationCapabilityUnavailableError","IntegrationCheckoutUnsupportedError","IntegrationConnectionInactiveError","IntegrationConnectionNotFoundError","IntegrationConnectionWorkspaceMismatchError","IntegrationProviderError","IntegrationProviderUnavailableError","redactCheckoutSpec","claimWebhookDelivery","pruneWebhookDeliveries","integrationRouteErrorHandler","createIntegrationsModule","options","createIntegrationsContext","module","workspaces","parts","providers","map","provider","webhookProcessors","secrets","requireActiveWorkspaceMembership","input","requireActiveMembership","memberships","registry","part","sourceControl","webhookProcessor","createComposedWebhookProcessor","flatMap","runStartupTasks","task","startupTasks","error","err","name","interModulePresentations","database","routes","agentTools","workflows","undefined","e2eRoutes","publishers","table","eventSchemas","workers","taskQueue","workflowsPath","activities","id","cronSchedule","webhookDeliverySource","services","createService","capabilities","registrations","processors","Map","registration","routeId","routeIds","has","Error","set","processor","process","request","get","route_id"],"mappings":"AAAA,SAAQA,OAAO,EAAEC,OAAO,QAAO,YAAY;AAC3C,SAAQC,aAAa,QAAO,WAAW;AACvC,SACEC,wBAAwB,QAKnB,oCAAoC;AAI3C,SAAQC,MAAM,QAAO,8BAA8B;AAEnD,SAAQC,kCAAkC,QAAO,kBAAkB;AACnE,SACEC,iCAAiC,QAE5B,8BAA8B;AACrC,SACEC,qCAAqC,QAEhC,kCAAkC;AACzC,SAAQC,4BAA4B,QAAO,qBAAqB;AAChE,SAAQC,EAAE,QAAO,YAAY;AAC7B,SAAQC,cAAc,QAAO,oBAAoB;AACjD,SAAQC,kBAAkB,QAAO,uBAAuB;AACxD,SAAQC,yCAAyC,QAAO,gCAAgC;AACxF,SAAQC,uBAAuB,QAAO,gCAAgC;AACtE,SAAQC,0BAA0B,QAAO,wBAAwB;AAMjE,SAAQC,uCAAuC,QAAO,gCAAgC;AACtF,SAAQC,mCAAmC,QAAO,yBAAyB;AAE3E,MAAMC,cAAchB,QAAQD,QAAQE,cAAc,YAAYgB,GAAG,IAAI;AACrE,MAAMC,2BAA2BlB,QAAQgB,aAAa;AAQtD,SACEG,yBAAyB,EACzBC,yBAAyB,EACzBC,yBAAyB,QACpB,oCAAoC;AAQ3C,SACEC,sBAAsB,EACtBC,+BAA+B,EAC/BC,uCAAuC,QAClC,gCAAgC;AAavC,SACEC,2BAA2B,EAC3BC,qCAAqC,EACrCC,mCAAmC,EACnCC,kCAAkC,EAClCC,kCAAkC,EAClCC,2CAA2C,EAC3CC,wBAAwB,EACxBC,mCAAmC,EACnC5B,kCAAkC,QAC7B,kBAAkB;AAWzB,SAAQ6B,kBAAkB,QAAO,0CAA0C;AAoB3E,SAAQ3B,qCAAqC,QAAO,kCAAkC;AAEtF,SAAQC,4BAA4B,QAAO,qBAAqB;AAWhE,SAAQ2B,oBAAoB,EAAEC,sBAAsB,QAAO,4BAA4B;AACvF,SAAQC,4BAA4B,QAAO,iCAAiC;AA4C5E,OAAO,eAAeC,yBACpBC,UAA2C,CAAC,CAAC;IAE7C,OAAO,AAAC,CAAA,MAAMC,0BAA0BD,QAAO,EAAGE,MAAM;AAC1D;AAEA,OAAO,eAAeD,0BACpBD,UAA2C,CAAC,CAAC;IAE7C,MAAMG,aAAaH,QAAQG,UAAU;IACrC,MAAMC,QACJJ,QAAQI,KAAK,IACZJ,CAAAA,QAAQK,SAAS,GACdL,QAAQK,SAAS,CAACC,GAAG,CAAC,CAACC,WAAc,CAAA;YACnCA;YACAC,mBAAmBD,SAASC,iBAAiB;QAC/C,CAAA,KACA,MAAMjC,2BAA2B;QAC/BkC,SAAST,QAAQS,OAAO;QACxB,GAAIN,aACA;YACEO,kCAAkC,CAACC,QAOjCR,WAAWS,uBAAuB,CAAC;oBACjC,GAAGD,KAAK;oBACRE,aAAa;2BAAIF,MAAME,WAAW;qBAAC;gBACrC;QACJ,IACA,CAAC,CAAC;IACR,EAAC;IAEP,MAAMC,WAAW/C,kCAAkCqC,MAAME,GAAG,CAAC,CAACS,OAASA,KAAKR,QAAQ;IACpF,MAAMS,gBAAgBhD,sCAAsC;QAC1D8C;QACA7C;IACF;IACA,MAAMgD,mBAAmBC,+BACvBd,MAAMe,OAAO,CAAC,CAACJ,OAASA,KAAKP,iBAAiB,IAAI,EAAE;IAGtD,eAAeY;QACb,KAAK,MAAMC,QAAQjB,MAAMe,OAAO,CAAC,CAACJ,OAASA,KAAKO,YAAY,IAAI,EAAE,EAAG;YACnE,mDAAmD;YACnD,IAAI;gBACF,MAAMD;YACR,EAAE,OAAOE,OAAO;gBACd1D,SAAS0D,KAAK,CAAC;oBAACC,KAAKD;gBAAK,GAAG;YAC/B;QACF;IACF;IAEA,MAAMrB,SAAwB;QAC5BuB,MAAM;QACNC,0BAA0B;YACxBrD,0CAA0C;gBAACyC;gBAAUE;YAAa;SACnE;QACDM,cAAcF;QACdO,UAAU;YACR;gBAACzD;gBAAIC;YAAc;eAChBiC,MAAMe,OAAO,CAAC,CAACJ,OAAUA,KAAKY,QAAQ,GAAG;oBAACZ,KAAKY,QAAQ;iBAAC,GAAG,EAAE;SACjE;QACDC,QAAQtD,wBAAwBwC,UAAUE,eAAe;YACvDa,YAAY7B,QAAQ6B,UAAU,GAC1B;gBACEC,WAAW9B,QAAQ6B,UAAU,CAACC,SAAS;gBACvC7D;YACF,IACA8D;QACN;QACAC,WAAW5B,MAAMe,OAAO,CAAC,CAACJ,OAASA,KAAKiB,SAAS,IAAI,EAAE;QACvDC,YAAY;YACV;gBAACR,MAAM;gBAAgBS,OAAO9D;gBAAoBF;gBAAIiE,cAAcvE;YAAwB;SAC7F;QACDwE,SAAS;YACP;gBACEC,WAAW5D;gBACX6D,eAAe1D;gBACf2D,YAAY/D;gBACZsD,WAAW;oBACT;wBACEL,MAAM;wBACNe,IAAI;wBACJC,cAAc;oBAChB;iBACD;YACH;eACGrC,MAAMe,OAAO,CAAC,CAACJ,OAASA,KAAKqB,OAAO,IAAI,EAAE;SAC9C;QACD,GAAIpC,QAAQ0C,qBAAqB,GAC7B;YAACC,UAAU;gBAAC3C,QAAQ0C,qBAAqB,CAACE,aAAa,CAAC3B;aAAkB;QAAA,IAC1E,CAAC,CAAC;IACR;IAEA,OAAO;QACLf;QACAY;QACA+B,cAAc;YAAC7B;QAAa;QAC5BA;QACAC;QACAG;IACF;AACF;AAEA,SAASF,+BACP4B,aAA6C;IAE7C,MAAMC,aAAa,IAAIC;IACvB,KAAK,MAAMC,gBAAgBH,cAAe;QACxC,KAAK,MAAMI,WAAWD,aAAaE,QAAQ,CAAE;YAC3C,IAAIJ,WAAWK,GAAG,CAACF,UAAU;gBAC3B,MAAM,IAAIG,MAAM,CAAC,mDAAmD,EAAEH,SAAS;YACjF;YACAH,WAAWO,GAAG,CAACJ,SAASD,aAAaM,SAAS;QAChD;IACF;IAEA,OAAO;QACL,MAAMC,SAAQC,OAA6B;YACzC,MAAMF,YAAYR,WAAWW,GAAG,CAACD,QAAQE,QAAQ;YACjD,IAAI,CAACJ,WAAW;gBACd,MAAM,IAAIzF,mCAAmC2F,QAAQE,QAAQ;YAC/D;YACA,OAAO,MAAMJ,UAAUC,OAAO,CAACC;QACjC;IACF;AACF"}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import {dirname, resolve} from 'node:path';\nimport {fileURLToPath} from 'node:url';\nimport {\n integrationsEventSchemas,\n type StoredWebhookRequest,\n type WebhookProcessingResult,\n type WebhookRequestProcessor,\n type WebhookRouteId,\n} from '@shipfox/api-integration-core-dto';\nimport type {WorkflowsModuleClient} from '@shipfox/api-workflows-dto/inter-module';\nimport type {WorkspacesInterModuleClient} from '@shipfox/api-workspaces-dto/inter-module';\nimport {reportError} from '@shipfox/node-error-monitoring';\nimport type {ModuleService, ShipfoxModule} from '@shipfox/node-module';\nimport {logger} from '@shipfox/node-opentelemetry';\nimport type {IntegrationProvider} from '#core/entities/provider.js';\nimport {WebhookProcessorNotConfiguredError} from '#core/errors.js';\nimport {\n createIntegrationProviderRegistry,\n type IntegrationProviderRegistry,\n} from '#core/providers/registry.js';\nimport {\n createSourceControlIntegrationService,\n type IntegrationSourceControlService,\n} from '#core/source-control-service.js';\nimport {getIntegrationConnectionById} from '#db/connections.js';\nimport {db} from '#db/db.js';\nimport {migrationsPath} from '#db/migrations.js';\nimport {integrationsOutbox} from '#db/schema/outbox.js';\nimport {createIntegrationsInterModulePresentation} from '#presentation/inter-module.js';\nimport {createIntegrationRoutes} from '#presentation/routes/index.js';\nimport {loadEnabledProviderModules} from '#providers/modules.js';\nimport type {\n IntegrationModuleParts,\n IntegrationProviderSecrets,\n WebhookProcessorRegistration,\n} from '#providers/types.js';\nimport {createIntegrationsMaintenanceActivities} from '#temporal/activities/index.js';\nimport {INTEGRATIONS_MAINTENANCE_TASK_QUEUE} from '#temporal/constants.js';\n\nconst packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');\nconst maintenanceWorkflowsPath = resolve(packageRoot, 'dist/temporal/workflows/index.js');\n\nexport type {\n StoredWebhookRequest,\n WebhookProcessingResult,\n WebhookRequestProcessor,\n WebhookRouteId,\n} from '@shipfox/api-integration-core-dto';\nexport {\n buildProviderRepositoryId,\n MAX_REPOSITORY_FILE_BYTES,\n parseProviderRepositoryId,\n} from '@shipfox/api-integration-core-dto';\nexport type {\n AgentToolCatalogs,\n AgentToolSelectionCatalogs,\n LoadWorkspaceConnectionSnapshot,\n WorkspaceConnectionSnapshot,\n WorkspaceConnectionSnapshotEntry,\n} from '#core/agent-tool-selection.js';\nexport {\n buildAgentToolCatalogs,\n buildAgentToolSelectionCatalogs,\n createWorkspaceConnectionSnapshotLoader,\n} from '#core/agent-tool-selection.js';\nexport type {\n IntegrationConnection,\n IntegrationConnectionLifecycleStatus,\n} from '#core/entities/connection.js';\nexport type {\n IntegrationCapability,\n IntegrationProvider,\n IntegrationProviderAdapters,\n IntegrationProviderKind,\n RegisteredIntegrationProvider,\n} from '#core/entities/provider.js';\nexport type {IntegrationProviderErrorReason} from '#core/errors.js';\nexport {\n ConnectionSlugConflictError,\n IntegrationCapabilityUnavailableError,\n IntegrationCheckoutUnsupportedError,\n IntegrationConnectionInactiveError,\n IntegrationConnectionNotFoundError,\n IntegrationConnectionWorkspaceMismatchError,\n IntegrationProviderError,\n IntegrationProviderUnavailableError,\n WebhookProcessorNotConfiguredError,\n} from '#core/errors.js';\nexport type {\n AgentToolCallInput,\n AgentToolCatalogEntry,\n AgentToolCatalogMethod,\n AgentToolJsonSchema,\n AgentToolSensitivity,\n AgentToolSession,\n AgentToolsProvider,\n OpenAgentToolsSessionInput,\n} from '#core/providers/agent-tools.js';\nexport {redactCheckoutSpec} from '#core/providers/redact-checkout-spec.js';\nexport type {IntegrationProviderRegistry} from '#core/providers/registry.js';\nexport type {\n CheckoutCredentials,\n CheckoutPermissions,\n CheckoutSpec,\n CreateCheckoutSpecInput,\n FetchFileInput,\n FileEntry,\n FilePage,\n FileSnapshot,\n ListFilesInput,\n ListRepositoriesInput,\n RepositoryPage,\n RepositorySnapshot,\n RepositoryVisibility,\n ResolveRepositoryInput,\n SourceControlProvider,\n} from '#core/providers/source-control.js';\nexport type {IntegrationSourceControlService} from '#core/source-control-service.js';\nexport {createSourceControlIntegrationService} from '#core/source-control-service.js';\nexport type {GetIntegrationConnectionByIdFn} from '#db/connections.js';\nexport {getIntegrationConnectionById} from '#db/connections.js';\nexport type {\n ClaimWebhookDeliveryFn,\n PublishIntegrationEventReceivedFn,\n PublishIntegrationEventReceivedParams,\n PublishIntegrationEventReceivedResult,\n PublishSourcePushFn,\n PublishSourcePushParams,\n RecordDeliveryOnlyFn,\n RecordDeliveryOnlyParams,\n} from '#db/webhook-deliveries.js';\nexport {claimWebhookDelivery, pruneWebhookDeliveries} from '#db/webhook-deliveries.js';\nexport {integrationRouteErrorHandler} from '#presentation/routes/errors.js';\n\nexport interface CreateIntegrationsModuleOptions {\n providers?: IntegrationProvider[] | undefined;\n /**\n * Pre-built module parts, bypassing config-gated provider loading. Test-only seam\n * for exercising a provider's database, workers, or startup tasks directly. Takes\n * precedence over `providers`.\n */\n parts?: IntegrationModuleParts[] | undefined;\n secrets?: IntegrationProviderSecrets | undefined;\n workspaces?: WorkspacesInterModuleClient | undefined;\n agentTools?:\n | {\n workflows: WorkflowsModuleClient;\n }\n | undefined;\n webhookDeliverySource?: WebhookDeliverySource | undefined;\n}\n\n/**\n * Hosted runtimes implement this port to receive stored webhook requests. The\n * integration module starts its returned service after migrations complete.\n */\nexport interface WebhookDeliverySource {\n createService(processor: WebhookRequestProcessor): ModuleService;\n}\n\nexport interface IntegrationsContext {\n module: ShipfoxModule;\n registry: IntegrationProviderRegistry;\n capabilities: {\n sourceControl: IntegrationSourceControlService;\n };\n sourceControl: IntegrationSourceControlService;\n webhookProcessor: WebhookRequestProcessor;\n /**\n * Runs every enabled provider's one-shot boot-time tasks, after modules are initialized\n * (migrations done). Failures are isolated and logged, never rethrown, so a provider task\n * can never gate API boot. No-op when no enabled provider contributes a task.\n */\n runStartupTasks: () => Promise<void>;\n}\n\nexport async function createIntegrationsModule(\n options: CreateIntegrationsModuleOptions = {},\n): Promise<ShipfoxModule> {\n return (await createIntegrationsContext(options)).module;\n}\n\nexport async function createIntegrationsContext(\n options: CreateIntegrationsModuleOptions = {},\n): Promise<IntegrationsContext> {\n const workspaces = options.workspaces;\n const parts: IntegrationModuleParts[] =\n options.parts ??\n (options.providers\n ? options.providers.map((provider) => ({\n provider,\n webhookProcessors: provider.webhookProcessors,\n }))\n : await loadEnabledProviderModules({\n secrets: options.secrets,\n ...(workspaces\n ? {\n requireActiveWorkspaceMembership: (input: {\n workspaceId: string;\n userId: string;\n memberships: ReadonlyArray<\n import('@shipfox/api-auth-context').UserContextMembership\n >;\n }) =>\n workspaces.requireActiveMembership({\n ...input,\n memberships: [...input.memberships],\n }),\n }\n : {}),\n }));\n\n const registry = createIntegrationProviderRegistry(parts.map((part) => part.provider));\n const sourceControl = createSourceControlIntegrationService({\n registry,\n getIntegrationConnectionById,\n });\n const webhookProcessor = createComposedWebhookProcessor(\n parts.flatMap((part) => part.webhookProcessors ?? []),\n );\n\n async function runStartupTasks(): Promise<void> {\n for (const task of parts.flatMap((part) => part.startupTasks ?? [])) {\n // A provider convenience must never gate API boot.\n try {\n await task();\n } catch (error) {\n logger().error({err: error}, 'Integration startup task failed, continuing boot');\n reportError(error, {boundary: 'integration.startup'});\n }\n }\n }\n\n const module: ShipfoxModule = {\n name: 'integrations',\n interModulePresentations: [\n createIntegrationsInterModulePresentation({registry, sourceControl}),\n ],\n startupTasks: runStartupTasks,\n database: [\n {db, migrationsPath},\n ...parts.flatMap((part) => (part.database ? [part.database] : [])),\n ],\n routes: createIntegrationRoutes(registry, sourceControl, {\n agentTools: options.agentTools\n ? {\n workflows: options.agentTools.workflows,\n getIntegrationConnectionById,\n }\n : undefined,\n }),\n e2eRoutes: parts.flatMap((part) => part.e2eRoutes ?? []),\n publishers: [\n {name: 'integrations', table: integrationsOutbox, db, eventSchemas: integrationsEventSchemas},\n ],\n workers: [\n {\n taskQueue: INTEGRATIONS_MAINTENANCE_TASK_QUEUE,\n workflowsPath: maintenanceWorkflowsPath,\n activities: createIntegrationsMaintenanceActivities,\n workflows: [\n {\n name: 'pruneWebhookDeliveriesCron',\n id: 'integrations-prune-webhook-deliveries',\n cronSchedule: '0 3 * * *',\n },\n ],\n },\n ...parts.flatMap((part) => part.workers ?? []),\n ],\n ...(options.webhookDeliverySource\n ? {services: [options.webhookDeliverySource.createService(webhookProcessor)]}\n : {}),\n };\n\n return {\n module,\n registry,\n capabilities: {sourceControl},\n sourceControl,\n webhookProcessor,\n runStartupTasks,\n };\n}\n\nfunction createComposedWebhookProcessor(\n registrations: WebhookProcessorRegistration[],\n): WebhookRequestProcessor {\n const processors = new Map<WebhookRouteId, WebhookRequestProcessor>();\n for (const registration of registrations) {\n for (const routeId of registration.routeIds) {\n if (processors.has(routeId)) {\n throw new Error(`Webhook processor is registered more than once for ${routeId}`);\n }\n processors.set(routeId, registration.processor);\n }\n }\n\n return {\n async process(request: StoredWebhookRequest): Promise<WebhookProcessingResult> {\n const processor = processors.get(request.route_id);\n if (!processor) {\n throw new WebhookProcessorNotConfiguredError(request.route_id);\n }\n return await processor.process(request);\n },\n };\n}\n"],"names":["dirname","resolve","fileURLToPath","integrationsEventSchemas","reportError","logger","WebhookProcessorNotConfiguredError","createIntegrationProviderRegistry","createSourceControlIntegrationService","getIntegrationConnectionById","db","migrationsPath","integrationsOutbox","createIntegrationsInterModulePresentation","createIntegrationRoutes","loadEnabledProviderModules","createIntegrationsMaintenanceActivities","INTEGRATIONS_MAINTENANCE_TASK_QUEUE","packageRoot","url","maintenanceWorkflowsPath","buildProviderRepositoryId","MAX_REPOSITORY_FILE_BYTES","parseProviderRepositoryId","buildAgentToolCatalogs","buildAgentToolSelectionCatalogs","createWorkspaceConnectionSnapshotLoader","ConnectionSlugConflictError","IntegrationCapabilityUnavailableError","IntegrationCheckoutUnsupportedError","IntegrationConnectionInactiveError","IntegrationConnectionNotFoundError","IntegrationConnectionWorkspaceMismatchError","IntegrationProviderError","IntegrationProviderUnavailableError","redactCheckoutSpec","claimWebhookDelivery","pruneWebhookDeliveries","integrationRouteErrorHandler","createIntegrationsModule","options","createIntegrationsContext","module","workspaces","parts","providers","map","provider","webhookProcessors","secrets","requireActiveWorkspaceMembership","input","requireActiveMembership","memberships","registry","part","sourceControl","webhookProcessor","createComposedWebhookProcessor","flatMap","runStartupTasks","task","startupTasks","error","err","boundary","name","interModulePresentations","database","routes","agentTools","workflows","undefined","e2eRoutes","publishers","table","eventSchemas","workers","taskQueue","workflowsPath","activities","id","cronSchedule","webhookDeliverySource","services","createService","capabilities","registrations","processors","Map","registration","routeId","routeIds","has","Error","set","processor","process","request","get","route_id"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../../../src/presentation/routes/agent-tools-gateway/dispatch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../../../src/presentation/routes/agent-tools-gateway/dispatch.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAC,2BAA2B,EAAC,MAAM,6BAA6B,CAAC;AAC7E,OAAO,KAAK,EAAC,yBAAyB,EAA+B,MAAM,iBAAiB,CAAC;AAE7F,MAAM,WAAW,qCAAqC;IACpD,QAAQ,EAAE,2BAA2B,CAAC;CACvC;AAKD,wBAAgB,+BAA+B,CAC7C,MAAM,EAAE,qCAAqC,GAC5C,yBAAyB,CAE3B"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { reportError } from '@shipfox/node-error-monitoring';
|
|
2
|
+
import { logger } from '@shipfox/node-opentelemetry';
|
|
1
3
|
import { IntegrationProviderError } from '#core/errors.js';
|
|
2
4
|
const timeoutErrorPattern = /timed?\s*out|timeout/i;
|
|
3
5
|
const credentialErrorNamePattern = /Token|Credential|Secret|AccessToken/;
|
|
@@ -23,7 +25,17 @@ async function dispatchIntegrationToolCall(input) {
|
|
|
23
25
|
arguments: input.arguments
|
|
24
26
|
});
|
|
25
27
|
} catch (error) {
|
|
26
|
-
|
|
28
|
+
const result = errorResult(error);
|
|
29
|
+
if (result.code === 'provider-unavailable') {
|
|
30
|
+
logger().error({
|
|
31
|
+
err: error,
|
|
32
|
+
provider: input.authorizedTool.integration.provider
|
|
33
|
+
}, 'Integration agent tool provider was unavailable');
|
|
34
|
+
reportError(error, {
|
|
35
|
+
boundary: 'integration.agent-tool'
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
return toolError(result);
|
|
27
39
|
} finally{
|
|
28
40
|
await closeSession(session);
|
|
29
41
|
}
|
|
@@ -54,8 +66,15 @@ function agentToolCatalogEntry(input) {
|
|
|
54
66
|
async function closeSession(session) {
|
|
55
67
|
try {
|
|
56
68
|
await session?.close?.();
|
|
57
|
-
} catch
|
|
58
|
-
|
|
69
|
+
} catch (error) {
|
|
70
|
+
// Cleanup must not mask the tool result returned to the runner.
|
|
71
|
+
logger().error({
|
|
72
|
+
err: error
|
|
73
|
+
}, 'Failed to close integration agent tool session');
|
|
74
|
+
reportError(error, {
|
|
75
|
+
boundary: 'integration.agent-tool',
|
|
76
|
+
operation: 'close-session'
|
|
77
|
+
});
|
|
59
78
|
}
|
|
60
79
|
}
|
|
61
80
|
function errorResult(error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/presentation/routes/agent-tools-gateway/dispatch.ts"],"sourcesContent":["import type {CallToolResult} from '@modelcontextprotocol/sdk/types.js';\nimport {IntegrationProviderError} from '#core/errors.js';\nimport type {\n AgentToolCatalogEntry,\n AgentToolCatalogMethod,\n AgentToolSession,\n AgentToolsProvider,\n} from '#core/providers/agent-tools.js';\nimport type {IntegrationProviderRegistry} from '#core/providers/registry.js';\nimport type {IntegrationToolDispatcher, IntegrationToolDispatchInput} from './mcp-server.js';\n\nexport interface CreateIntegrationToolDispatcherParams {\n registry: IntegrationProviderRegistry;\n}\n\nconst timeoutErrorPattern = /timed?\\s*out|timeout/i;\nconst credentialErrorNamePattern = /Token|Credential|Secret|AccessToken/;\n\nexport function createIntegrationToolDispatcher(\n params: CreateIntegrationToolDispatcherParams,\n): IntegrationToolDispatcher {\n return (input) => dispatchIntegrationToolCall({...input, registry: params.registry});\n}\n\nasync function dispatchIntegrationToolCall(\n input: IntegrationToolDispatchInput & {registry: IntegrationProviderRegistry},\n): Promise<CallToolResult> {\n let session: AgentToolSession<CallToolResult> | undefined;\n\n try {\n const adapter = input.registry.getAdapter(\n input.authorizedTool.integration.provider,\n 'agent_tools',\n ) as AgentToolsProvider<\n typeof input.authorizedTool.connection,\n unknown,\n typeof input.authorizedTool.integration,\n CallToolResult\n >;\n session = await adapter.openSession({\n connection: input.authorizedTool.connection,\n tools: [agentToolCatalogEntry(input)],\n scope: input.authorizedTool.integration,\n });\n\n return await session.call({\n toolId: input.authorizedTool.tool.id,\n arguments: input.arguments,\n });\n } catch (error) {\n
|
|
1
|
+
{"version":3,"sources":["../../../../src/presentation/routes/agent-tools-gateway/dispatch.ts"],"sourcesContent":["import type {CallToolResult} from '@modelcontextprotocol/sdk/types.js';\nimport {reportError} from '@shipfox/node-error-monitoring';\nimport {logger} from '@shipfox/node-opentelemetry';\nimport {IntegrationProviderError} from '#core/errors.js';\nimport type {\n AgentToolCatalogEntry,\n AgentToolCatalogMethod,\n AgentToolSession,\n AgentToolsProvider,\n} from '#core/providers/agent-tools.js';\nimport type {IntegrationProviderRegistry} from '#core/providers/registry.js';\nimport type {IntegrationToolDispatcher, IntegrationToolDispatchInput} from './mcp-server.js';\n\nexport interface CreateIntegrationToolDispatcherParams {\n registry: IntegrationProviderRegistry;\n}\n\nconst timeoutErrorPattern = /timed?\\s*out|timeout/i;\nconst credentialErrorNamePattern = /Token|Credential|Secret|AccessToken/;\n\nexport function createIntegrationToolDispatcher(\n params: CreateIntegrationToolDispatcherParams,\n): IntegrationToolDispatcher {\n return (input) => dispatchIntegrationToolCall({...input, registry: params.registry});\n}\n\nasync function dispatchIntegrationToolCall(\n input: IntegrationToolDispatchInput & {registry: IntegrationProviderRegistry},\n): Promise<CallToolResult> {\n let session: AgentToolSession<CallToolResult> | undefined;\n\n try {\n const adapter = input.registry.getAdapter(\n input.authorizedTool.integration.provider,\n 'agent_tools',\n ) as AgentToolsProvider<\n typeof input.authorizedTool.connection,\n unknown,\n typeof input.authorizedTool.integration,\n CallToolResult\n >;\n session = await adapter.openSession({\n connection: input.authorizedTool.connection,\n tools: [agentToolCatalogEntry(input)],\n scope: input.authorizedTool.integration,\n });\n\n return await session.call({\n toolId: input.authorizedTool.tool.id,\n arguments: input.arguments,\n });\n } catch (error) {\n const result = errorResult(error);\n if (result.code === 'provider-unavailable') {\n logger().error(\n {err: error, provider: input.authorizedTool.integration.provider},\n 'Integration agent tool provider was unavailable',\n );\n reportError(error, {boundary: 'integration.agent-tool'});\n }\n return toolError(result);\n } finally {\n await closeSession(session);\n }\n}\n\nfunction agentToolCatalogEntry(input: IntegrationToolDispatchInput): AgentToolCatalogEntry {\n const {tool, description, inputSchema, outputSchema} = input.authorizedTool;\n return {\n id: tool.id,\n description,\n sensitivity: tool.sensitivity,\n sensitive: tool.sensitive,\n requiredScope: tool.requiredScope,\n inputSchema,\n ...(outputSchema === undefined ? {} : {outputSchema}),\n ...(tool.methods === undefined\n ? {}\n : {\n methods: tool.methods.map(\n (method): AgentToolCatalogMethod => ({\n id: method.id,\n description: method.description ?? method.token,\n sensitivity: method.sensitivity,\n sensitive: method.sensitive,\n requiredScope: method.requiredScope,\n }),\n ),\n }),\n };\n}\n\nasync function closeSession(session: {close?(): Promise<void>} | undefined): Promise<void> {\n try {\n await session?.close?.();\n } catch (error) {\n // Cleanup must not mask the tool result returned to the runner.\n logger().error({err: error}, 'Failed to close integration agent tool session');\n reportError(error, {boundary: 'integration.agent-tool', operation: 'close-session'});\n }\n}\n\nfunction errorResult(error: unknown): {code: string; message: string} {\n if (error instanceof IntegrationProviderError) {\n return {\n code: error.reason,\n message: `Integration provider error: ${error.reason}`,\n };\n }\n\n if (isTimeoutError(error)) {\n return {\n code: 'provider-timeout',\n message: 'Integration provider timed out',\n };\n }\n\n if (isCredentialError(error)) {\n return {\n code: 'credentials-unavailable',\n message: 'Integration provider credentials are unavailable',\n };\n }\n\n return {\n code: 'provider-unavailable',\n message: 'Integration provider call failed',\n };\n}\n\nfunction isTimeoutError(error: unknown): boolean {\n if (!(error instanceof Error)) return false;\n return (\n error.name === 'AbortError' ||\n timeoutErrorPattern.test(error.name) ||\n timeoutErrorPattern.test(error.message)\n );\n}\n\nfunction isCredentialError(error: unknown): boolean {\n if (!(error instanceof Error)) return false;\n return credentialErrorNamePattern.test(error.name);\n}\n\nfunction toolError(params: {code: string; message: string}): CallToolResult {\n return {\n isError: true,\n content: [{type: 'text', text: params.message}],\n structuredContent: {code: params.code},\n };\n}\n"],"names":["reportError","logger","IntegrationProviderError","timeoutErrorPattern","credentialErrorNamePattern","createIntegrationToolDispatcher","params","input","dispatchIntegrationToolCall","registry","session","adapter","getAdapter","authorizedTool","integration","provider","openSession","connection","tools","agentToolCatalogEntry","scope","call","toolId","tool","id","arguments","error","result","errorResult","code","err","boundary","toolError","closeSession","description","inputSchema","outputSchema","sensitivity","sensitive","requiredScope","undefined","methods","map","method","token","close","operation","reason","message","isTimeoutError","isCredentialError","Error","name","test","isError","content","type","text","structuredContent"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/presentation/routes/agent-tools-gateway/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/presentation/routes/agent-tools-gateway/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAc,KAAK,UAAU,EAAC,MAAM,uBAAuB,CAAC;AAEnE,OAAO,KAAK,EAAC,2BAA2B,EAAC,MAAM,6BAA6B,CAAC;AAC7E,OAAO,KAAK,EAAC,8BAA8B,EAAC,MAAM,oBAAoB,CAAC;AAIvE,OAAO,EACL,KAAK,qBAAqB,EAE3B,MAAM,+BAA+B,CAAC;AAEvC,YAAY,EAAC,qBAAqB,EAAC,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAC,oCAAoC,EAAC,MAAM,+BAA+B,CAAC;AAEnF,MAAM,WAAW,mCAAmC;IAClD,mBAAmB,EAAE,qBAAqB,CAAC;IAC3C,QAAQ,EAAE,2BAA2B,CAAC;IACtC,4BAA4B,EAAE,8BAA8B,CAAC;CAC9D;AAED,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,mCAAmC,GAC1C,UAAU,CAiDZ"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
2
2
|
import { AUTH_LEASED_JOB, requireLeasedJobContext } from '@shipfox/api-auth-context';
|
|
3
|
+
import { reportError } from '@shipfox/node-error-monitoring';
|
|
3
4
|
import { defineRoute } from '@shipfox/node-fastify';
|
|
5
|
+
import { logger } from '@shipfox/node-opentelemetry';
|
|
4
6
|
import { createIntegrationToolCallRecorder } from './audit.js';
|
|
5
7
|
import { createIntegrationToolDispatcher } from './dispatch.js';
|
|
6
8
|
import { buildAgentToolsMcpServer } from './mcp-server.js';
|
|
@@ -33,8 +35,24 @@ export function createAgentToolsGatewayRoutes(params) {
|
|
|
33
35
|
const transport = new StreamableHTTPServerTransport();
|
|
34
36
|
await server.connect(transport);
|
|
35
37
|
reply.raw.on('close', ()=>{
|
|
36
|
-
void transport.close()
|
|
37
|
-
|
|
38
|
+
void transport.close().catch((error)=>{
|
|
39
|
+
logger().error({
|
|
40
|
+
err: error
|
|
41
|
+
}, 'Failed to close integration agent tool transport');
|
|
42
|
+
reportError(error, {
|
|
43
|
+
boundary: 'integration.agent-tool',
|
|
44
|
+
operation: 'close-transport'
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
void server.close().catch((error)=>{
|
|
48
|
+
logger().error({
|
|
49
|
+
err: error
|
|
50
|
+
}, 'Failed to close integration agent tool server');
|
|
51
|
+
reportError(error, {
|
|
52
|
+
boundary: 'integration.agent-tool',
|
|
53
|
+
operation: 'close-server'
|
|
54
|
+
});
|
|
55
|
+
});
|
|
38
56
|
});
|
|
39
57
|
reply.hijack();
|
|
40
58
|
await transport.handleRequest(request.raw, reply.raw, request.body);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/presentation/routes/agent-tools-gateway/index.ts"],"sourcesContent":["import {StreamableHTTPServerTransport} from '@modelcontextprotocol/sdk/server/streamableHttp.js';\nimport type {Transport} from '@modelcontextprotocol/sdk/shared/transport.js';\nimport {AUTH_LEASED_JOB, requireLeasedJobContext} from '@shipfox/api-auth-context';\nimport {defineRoute, type RouteGroup} from '@shipfox/node-fastify';\nimport type {IntegrationProviderRegistry} from '#core/providers/registry.js';\nimport type {GetIntegrationConnectionByIdFn} from '#db/connections.js';\nimport {createIntegrationToolCallRecorder} from './audit.js';\nimport {createIntegrationToolDispatcher} from './dispatch.js';\nimport {buildAgentToolsMcpServer} from './mcp-server.js';\nimport {\n type LeasedAgentStepLoader,\n resolveAuthorizedIntegrationTools,\n} from './resolve-authorized-tools.js';\n\nexport type {LeasedAgentStepLoader} from './resolve-authorized-tools.js';\nexport {createWorkflowsLeasedAgentStepLoader} from './resolve-authorized-tools.js';\n\nexport interface CreateAgentToolsGatewayRoutesParams {\n loadLeasedAgentStep: LeasedAgentStepLoader;\n registry: IntegrationProviderRegistry;\n getIntegrationConnectionById: GetIntegrationConnectionByIdFn;\n}\n\nexport function createAgentToolsGatewayRoutes(\n params: CreateAgentToolsGatewayRoutesParams,\n): RouteGroup {\n const dispatchIntegrationToolCall = createIntegrationToolDispatcher({registry: params.registry});\n\n return {\n prefix: '/runs/jobs/current/integration-tools',\n auth: AUTH_LEASED_JOB,\n routes: [\n defineRoute({\n method: 'POST',\n path: '/mcp',\n description: 'Gateway MCP endpoint for integration-backed agent tools',\n handler: async (request, reply) => {\n const authorizedTools = await resolveAuthorizedIntegrationTools({\n request,\n loadLeasedAgentStep: params.loadLeasedAgentStep,\n registry: params.registry,\n getIntegrationConnectionById: params.getIntegrationConnectionById,\n });\n const server = buildAgentToolsMcpServer({\n authorizedTools,\n dispatch: dispatchIntegrationToolCall,\n recordCall: createIntegrationToolCallRecorder(requireLeasedJobContext(request)),\n });\n const transport = new StreamableHTTPServerTransport();\n\n await server.connect(transport as unknown as Transport);\n reply.raw.on('close', () => {\n void transport.close();\n void server.close();\n });\n\n reply.hijack();\n await transport.handleRequest(request.raw, reply.raw, request.body);\n },\n }),\n ],\n };\n}\n"],"names":["StreamableHTTPServerTransport","AUTH_LEASED_JOB","requireLeasedJobContext","defineRoute","createIntegrationToolCallRecorder","createIntegrationToolDispatcher","buildAgentToolsMcpServer","resolveAuthorizedIntegrationTools","createWorkflowsLeasedAgentStepLoader","createAgentToolsGatewayRoutes","params","dispatchIntegrationToolCall","registry","prefix","auth","routes","method","path","description","handler","request","reply","authorizedTools","loadLeasedAgentStep","getIntegrationConnectionById","server","dispatch","recordCall","transport","connect","raw","on","close","hijack","handleRequest","body"],"mappings":"AAAA,SAAQA,6BAA6B,QAAO,qDAAqD;AAEjG,SAAQC,eAAe,EAAEC,uBAAuB,QAAO,4BAA4B;AACnF,SAAQC,WAAW,QAAwB,wBAAwB;
|
|
1
|
+
{"version":3,"sources":["../../../../src/presentation/routes/agent-tools-gateway/index.ts"],"sourcesContent":["import {StreamableHTTPServerTransport} from '@modelcontextprotocol/sdk/server/streamableHttp.js';\nimport type {Transport} from '@modelcontextprotocol/sdk/shared/transport.js';\nimport {AUTH_LEASED_JOB, requireLeasedJobContext} from '@shipfox/api-auth-context';\nimport {reportError} from '@shipfox/node-error-monitoring';\nimport {defineRoute, type RouteGroup} from '@shipfox/node-fastify';\nimport {logger} from '@shipfox/node-opentelemetry';\nimport type {IntegrationProviderRegistry} from '#core/providers/registry.js';\nimport type {GetIntegrationConnectionByIdFn} from '#db/connections.js';\nimport {createIntegrationToolCallRecorder} from './audit.js';\nimport {createIntegrationToolDispatcher} from './dispatch.js';\nimport {buildAgentToolsMcpServer} from './mcp-server.js';\nimport {\n type LeasedAgentStepLoader,\n resolveAuthorizedIntegrationTools,\n} from './resolve-authorized-tools.js';\n\nexport type {LeasedAgentStepLoader} from './resolve-authorized-tools.js';\nexport {createWorkflowsLeasedAgentStepLoader} from './resolve-authorized-tools.js';\n\nexport interface CreateAgentToolsGatewayRoutesParams {\n loadLeasedAgentStep: LeasedAgentStepLoader;\n registry: IntegrationProviderRegistry;\n getIntegrationConnectionById: GetIntegrationConnectionByIdFn;\n}\n\nexport function createAgentToolsGatewayRoutes(\n params: CreateAgentToolsGatewayRoutesParams,\n): RouteGroup {\n const dispatchIntegrationToolCall = createIntegrationToolDispatcher({registry: params.registry});\n\n return {\n prefix: '/runs/jobs/current/integration-tools',\n auth: AUTH_LEASED_JOB,\n routes: [\n defineRoute({\n method: 'POST',\n path: '/mcp',\n description: 'Gateway MCP endpoint for integration-backed agent tools',\n handler: async (request, reply) => {\n const authorizedTools = await resolveAuthorizedIntegrationTools({\n request,\n loadLeasedAgentStep: params.loadLeasedAgentStep,\n registry: params.registry,\n getIntegrationConnectionById: params.getIntegrationConnectionById,\n });\n const server = buildAgentToolsMcpServer({\n authorizedTools,\n dispatch: dispatchIntegrationToolCall,\n recordCall: createIntegrationToolCallRecorder(requireLeasedJobContext(request)),\n });\n const transport = new StreamableHTTPServerTransport();\n\n await server.connect(transport as unknown as Transport);\n reply.raw.on('close', () => {\n void transport.close().catch((error) => {\n logger().error({err: error}, 'Failed to close integration agent tool transport');\n reportError(error, {\n boundary: 'integration.agent-tool',\n operation: 'close-transport',\n });\n });\n void server.close().catch((error) => {\n logger().error({err: error}, 'Failed to close integration agent tool server');\n reportError(error, {\n boundary: 'integration.agent-tool',\n operation: 'close-server',\n });\n });\n });\n\n reply.hijack();\n await transport.handleRequest(request.raw, reply.raw, request.body);\n },\n }),\n ],\n };\n}\n"],"names":["StreamableHTTPServerTransport","AUTH_LEASED_JOB","requireLeasedJobContext","reportError","defineRoute","logger","createIntegrationToolCallRecorder","createIntegrationToolDispatcher","buildAgentToolsMcpServer","resolveAuthorizedIntegrationTools","createWorkflowsLeasedAgentStepLoader","createAgentToolsGatewayRoutes","params","dispatchIntegrationToolCall","registry","prefix","auth","routes","method","path","description","handler","request","reply","authorizedTools","loadLeasedAgentStep","getIntegrationConnectionById","server","dispatch","recordCall","transport","connect","raw","on","close","catch","error","err","boundary","operation","hijack","handleRequest","body"],"mappings":"AAAA,SAAQA,6BAA6B,QAAO,qDAAqD;AAEjG,SAAQC,eAAe,EAAEC,uBAAuB,QAAO,4BAA4B;AACnF,SAAQC,WAAW,QAAO,iCAAiC;AAC3D,SAAQC,WAAW,QAAwB,wBAAwB;AACnE,SAAQC,MAAM,QAAO,8BAA8B;AAGnD,SAAQC,iCAAiC,QAAO,aAAa;AAC7D,SAAQC,+BAA+B,QAAO,gBAAgB;AAC9D,SAAQC,wBAAwB,QAAO,kBAAkB;AACzD,SAEEC,iCAAiC,QAC5B,gCAAgC;AAGvC,SAAQC,oCAAoC,QAAO,gCAAgC;AAQnF,OAAO,SAASC,8BACdC,MAA2C;IAE3C,MAAMC,8BAA8BN,gCAAgC;QAACO,UAAUF,OAAOE,QAAQ;IAAA;IAE9F,OAAO;QACLC,QAAQ;QACRC,MAAMf;QACNgB,QAAQ;YACNb,YAAY;gBACVc,QAAQ;gBACRC,MAAM;gBACNC,aAAa;gBACbC,SAAS,OAAOC,SAASC;oBACvB,MAAMC,kBAAkB,MAAMf,kCAAkC;wBAC9Da;wBACAG,qBAAqBb,OAAOa,mBAAmB;wBAC/CX,UAAUF,OAAOE,QAAQ;wBACzBY,8BAA8Bd,OAAOc,4BAA4B;oBACnE;oBACA,MAAMC,SAASnB,yBAAyB;wBACtCgB;wBACAI,UAAUf;wBACVgB,YAAYvB,kCAAkCJ,wBAAwBoB;oBACxE;oBACA,MAAMQ,YAAY,IAAI9B;oBAEtB,MAAM2B,OAAOI,OAAO,CAACD;oBACrBP,MAAMS,GAAG,CAACC,EAAE,CAAC,SAAS;wBACpB,KAAKH,UAAUI,KAAK,GAAGC,KAAK,CAAC,CAACC;4BAC5B/B,SAAS+B,KAAK,CAAC;gCAACC,KAAKD;4BAAK,GAAG;4BAC7BjC,YAAYiC,OAAO;gCACjBE,UAAU;gCACVC,WAAW;4BACb;wBACF;wBACA,KAAKZ,OAAOO,KAAK,GAAGC,KAAK,CAAC,CAACC;4BACzB/B,SAAS+B,KAAK,CAAC;gCAACC,KAAKD;4BAAK,GAAG;4BAC7BjC,YAAYiC,OAAO;gCACjBE,UAAU;gCACVC,WAAW;4BACb;wBACF;oBACF;oBAEAhB,MAAMiB,MAAM;oBACZ,MAAMV,UAAUW,aAAa,CAACnB,QAAQU,GAAG,EAAET,MAAMS,GAAG,EAAEV,QAAQoB,IAAI;gBACpE;YACF;SACD;IACH;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../../../../src/presentation/routes/agent-tools-gateway/mcp-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAC,MAAM,2CAA2C,CAAC;AACjE,OAAO,EAEL,KAAK,cAAc,EAEpB,MAAM,oCAAoC,CAAC;
|
|
1
|
+
{"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../../../../src/presentation/routes/agent-tools-gateway/mcp-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAC,MAAM,2CAA2C,CAAC;AACjE,OAAO,EAEL,KAAK,cAAc,EAEpB,MAAM,oCAAoC,CAAC;AAG5C,OAAO,EAAuB,KAAK,2BAA2B,EAAkB,MAAM,YAAY,CAAC;AACnG,OAAO,KAAK,EACV,yBAAyB,EACzB,4BAA4B,EAC7B,MAAM,+BAA+B,CAAC;AAEvC,MAAM,WAAW,4BAA4B;IAC3C,cAAc,EAAE,yBAAyB,CAAC;IAC1C,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AAED,MAAM,MAAM,yBAAyB,GAAG,CACtC,KAAK,EAAE,4BAA4B,KAChC,OAAO,CAAC,cAAc,CAAC,CAAC;AAE7B,MAAM,WAAW,8BAA8B;IAC7C,eAAe,EAAE,4BAA4B,CAAC;IAC9C,QAAQ,EAAE,yBAAyB,CAAC;IACpC,UAAU,CAAC,EAAE,2BAA2B,GAAG,SAAS,CAAC;CACtD;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,8BAA8B,GAAG,MAAM,CAqFvF"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
2
|
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
3
|
+
import { reportError } from '@shipfox/node-error-monitoring';
|
|
4
|
+
import { logger } from '@shipfox/node-opentelemetry';
|
|
3
5
|
import { INVALID_METHOD_LABEL, NO_METHOD_LABEL } from './audit.js';
|
|
4
6
|
export function buildAgentToolsMcpServer(params) {
|
|
5
7
|
const server = new Server({
|
|
@@ -81,8 +83,15 @@ export function buildAgentToolsMcpServer(params) {
|
|
|
81
83
|
function recordToolCall(recordCall, record) {
|
|
82
84
|
try {
|
|
83
85
|
recordCall?.(record);
|
|
84
|
-
} catch
|
|
85
|
-
|
|
86
|
+
} catch (error) {
|
|
87
|
+
// Audit and metrics must not affect MCP responses.
|
|
88
|
+
logger().error({
|
|
89
|
+
err: error
|
|
90
|
+
}, 'Failed to record integration agent tool audit event');
|
|
91
|
+
reportError(error, {
|
|
92
|
+
boundary: 'integration.agent-tool',
|
|
93
|
+
operation: 'audit'
|
|
94
|
+
});
|
|
86
95
|
}
|
|
87
96
|
}
|
|
88
97
|
function validateMethod(authorizedTool, args) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/presentation/routes/agent-tools-gateway/mcp-server.ts"],"sourcesContent":["import {Server} from '@modelcontextprotocol/sdk/server/index.js';\nimport {\n CallToolRequestSchema,\n type CallToolResult,\n ListToolsRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js';\nimport {INVALID_METHOD_LABEL, type IntegrationToolCallRecorder, NO_METHOD_LABEL} from './audit.js';\nimport type {\n AuthorizedIntegrationTool,\n AuthorizedIntegrationToolMap,\n} from './resolve-authorized-tools.js';\n\nexport interface IntegrationToolDispatchInput {\n authorizedTool: AuthorizedIntegrationTool;\n arguments: Record<string, unknown>;\n method?: string | undefined;\n}\n\nexport type IntegrationToolDispatcher = (\n input: IntegrationToolDispatchInput,\n) => Promise<CallToolResult>;\n\nexport interface BuildAgentToolsMcpServerParams {\n authorizedTools: AuthorizedIntegrationToolMap;\n dispatch: IntegrationToolDispatcher;\n recordCall?: IntegrationToolCallRecorder | undefined;\n}\n\nexport function buildAgentToolsMcpServer(params: BuildAgentToolsMcpServerParams): Server {\n const server = new Server(\n {name: 'shipfox-integration-tools', version: '0.0.0'},\n {capabilities: {tools: {}}},\n );\n server.setRequestHandler(ListToolsRequestSchema, () => ({\n tools: [...params.authorizedTools.values()].map((authorizedTool) => ({\n name: authorizedTool.mcpName,\n description: authorizedTool.description,\n inputSchema: authorizedTool.inputSchema as {\n type: 'object';\n properties?: Record<string, object> | undefined;\n required?: string[] | undefined;\n },\n ...(authorizedTool.outputSchema\n ? {\n outputSchema: authorizedTool.outputSchema as {\n type: 'object';\n properties?: Record<string, object> | undefined;\n required?: string[] | undefined;\n },\n }\n : {}),\n })),\n }));\n\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const authorizedTool = params.authorizedTools.get(request.params.name);\n if (!authorizedTool) {\n recordToolCall(params.recordCall, {\n arguments: request.params.arguments ?? {},\n method: NO_METHOD_LABEL,\n outcome: 'invalid-request',\n });\n return toolError(`Unknown integration tool: ${request.params.name}`);\n }\n\n const args = request.params.arguments ?? {};\n if (!isRecord(args)) {\n recordToolCall(params.recordCall, {\n authorizedTool,\n arguments: args,\n method: NO_METHOD_LABEL,\n outcome: 'invalid-request',\n });\n return toolError('Tool arguments must be an object');\n }\n\n const methodValidation = validateMethod(authorizedTool, args);\n if (methodValidation.kind === 'error') {\n recordToolCall(params.recordCall, {\n authorizedTool,\n arguments: args,\n method: INVALID_METHOD_LABEL,\n outcome: 'invalid-request',\n });\n return toolError(methodValidation.message);\n }\n const method = methodValidation.method ?? NO_METHOD_LABEL;\n\n try {\n const result = await params.dispatch({\n authorizedTool,\n arguments: args,\n method: methodValidation.method,\n });\n recordToolCall(params.recordCall, {\n authorizedTool,\n arguments: args,\n method,\n outcome: result.isError === true ? 'tool-error' : 'success',\n });\n return result;\n } catch (error) {\n recordToolCall(params.recordCall, {\n authorizedTool,\n arguments: args,\n method,\n outcome: 'exception',\n });\n throw error;\n }\n });\n\n return server;\n}\n\nfunction recordToolCall(\n recordCall: IntegrationToolCallRecorder | undefined,\n record: Parameters<IntegrationToolCallRecorder>[0],\n): void {\n try {\n recordCall?.(record);\n } catch {\n // Audit and metrics must not affect MCP responses.\n }\n}\n\nfunction validateMethod(\n authorizedTool: AuthorizedIntegrationTool,\n args: Record<string, unknown>,\n): {kind: 'ok'; method?: string | undefined} | {kind: 'error'; message: string} {\n if (!authorizedTool.tool.methods) return {kind: 'ok'};\n\n const method = args.method;\n if (typeof method !== 'string') {\n return {kind: 'error', message: 'Method-family tools require a string method argument'};\n }\n\n const allowedMethods = new Set(authorizedTool.tool.methods.map((candidate) => candidate.id));\n if (!allowedMethods.has(method)) {\n return {kind: 'error', message: `Unauthorized integration tool method: ${method}`};\n }\n\n return {kind: 'ok', method};\n}\n\nfunction toolError(message: string): CallToolResult {\n return {\n isError: true,\n content: [{type: 'text', text: message}],\n };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n"],"names":["Server","CallToolRequestSchema","ListToolsRequestSchema","INVALID_METHOD_LABEL","NO_METHOD_LABEL","buildAgentToolsMcpServer","params","server","name","version","capabilities","tools","setRequestHandler","authorizedTools","values","map","authorizedTool","mcpName","description","inputSchema","outputSchema","request","get","recordToolCall","recordCall","arguments","method","outcome","toolError","args","isRecord","methodValidation","validateMethod","kind","message","result","dispatch","isError","error","record","tool","methods","allowedMethods","Set","candidate","id","has","content","type","text","value","Array","isArray"],"mappings":"AAAA,SAAQA,MAAM,QAAO,4CAA4C;AACjE,SACEC,qBAAqB,EAErBC,sBAAsB,QACjB,qCAAqC;AAC5C,SAAQC,oBAAoB,EAAoCC,eAAe,QAAO,aAAa;AAsBnG,OAAO,SAASC,yBAAyBC,MAAsC;IAC7E,MAAMC,SAAS,
|
|
1
|
+
{"version":3,"sources":["../../../../src/presentation/routes/agent-tools-gateway/mcp-server.ts"],"sourcesContent":["import {Server} from '@modelcontextprotocol/sdk/server/index.js';\nimport {\n CallToolRequestSchema,\n type CallToolResult,\n ListToolsRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js';\nimport {reportError} from '@shipfox/node-error-monitoring';\nimport {logger} from '@shipfox/node-opentelemetry';\nimport {INVALID_METHOD_LABEL, type IntegrationToolCallRecorder, NO_METHOD_LABEL} from './audit.js';\nimport type {\n AuthorizedIntegrationTool,\n AuthorizedIntegrationToolMap,\n} from './resolve-authorized-tools.js';\n\nexport interface IntegrationToolDispatchInput {\n authorizedTool: AuthorizedIntegrationTool;\n arguments: Record<string, unknown>;\n method?: string | undefined;\n}\n\nexport type IntegrationToolDispatcher = (\n input: IntegrationToolDispatchInput,\n) => Promise<CallToolResult>;\n\nexport interface BuildAgentToolsMcpServerParams {\n authorizedTools: AuthorizedIntegrationToolMap;\n dispatch: IntegrationToolDispatcher;\n recordCall?: IntegrationToolCallRecorder | undefined;\n}\n\nexport function buildAgentToolsMcpServer(params: BuildAgentToolsMcpServerParams): Server {\n const server = new Server(\n {name: 'shipfox-integration-tools', version: '0.0.0'},\n {capabilities: {tools: {}}},\n );\n server.setRequestHandler(ListToolsRequestSchema, () => ({\n tools: [...params.authorizedTools.values()].map((authorizedTool) => ({\n name: authorizedTool.mcpName,\n description: authorizedTool.description,\n inputSchema: authorizedTool.inputSchema as {\n type: 'object';\n properties?: Record<string, object> | undefined;\n required?: string[] | undefined;\n },\n ...(authorizedTool.outputSchema\n ? {\n outputSchema: authorizedTool.outputSchema as {\n type: 'object';\n properties?: Record<string, object> | undefined;\n required?: string[] | undefined;\n },\n }\n : {}),\n })),\n }));\n\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const authorizedTool = params.authorizedTools.get(request.params.name);\n if (!authorizedTool) {\n recordToolCall(params.recordCall, {\n arguments: request.params.arguments ?? {},\n method: NO_METHOD_LABEL,\n outcome: 'invalid-request',\n });\n return toolError(`Unknown integration tool: ${request.params.name}`);\n }\n\n const args = request.params.arguments ?? {};\n if (!isRecord(args)) {\n recordToolCall(params.recordCall, {\n authorizedTool,\n arguments: args,\n method: NO_METHOD_LABEL,\n outcome: 'invalid-request',\n });\n return toolError('Tool arguments must be an object');\n }\n\n const methodValidation = validateMethod(authorizedTool, args);\n if (methodValidation.kind === 'error') {\n recordToolCall(params.recordCall, {\n authorizedTool,\n arguments: args,\n method: INVALID_METHOD_LABEL,\n outcome: 'invalid-request',\n });\n return toolError(methodValidation.message);\n }\n const method = methodValidation.method ?? NO_METHOD_LABEL;\n\n try {\n const result = await params.dispatch({\n authorizedTool,\n arguments: args,\n method: methodValidation.method,\n });\n recordToolCall(params.recordCall, {\n authorizedTool,\n arguments: args,\n method,\n outcome: result.isError === true ? 'tool-error' : 'success',\n });\n return result;\n } catch (error) {\n recordToolCall(params.recordCall, {\n authorizedTool,\n arguments: args,\n method,\n outcome: 'exception',\n });\n throw error;\n }\n });\n\n return server;\n}\n\nfunction recordToolCall(\n recordCall: IntegrationToolCallRecorder | undefined,\n record: Parameters<IntegrationToolCallRecorder>[0],\n): void {\n try {\n recordCall?.(record);\n } catch (error) {\n // Audit and metrics must not affect MCP responses.\n logger().error({err: error}, 'Failed to record integration agent tool audit event');\n reportError(error, {boundary: 'integration.agent-tool', operation: 'audit'});\n }\n}\n\nfunction validateMethod(\n authorizedTool: AuthorizedIntegrationTool,\n args: Record<string, unknown>,\n): {kind: 'ok'; method?: string | undefined} | {kind: 'error'; message: string} {\n if (!authorizedTool.tool.methods) return {kind: 'ok'};\n\n const method = args.method;\n if (typeof method !== 'string') {\n return {kind: 'error', message: 'Method-family tools require a string method argument'};\n }\n\n const allowedMethods = new Set(authorizedTool.tool.methods.map((candidate) => candidate.id));\n if (!allowedMethods.has(method)) {\n return {kind: 'error', message: `Unauthorized integration tool method: ${method}`};\n }\n\n return {kind: 'ok', method};\n}\n\nfunction toolError(message: string): CallToolResult {\n return {\n isError: true,\n content: [{type: 'text', text: message}],\n };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n"],"names":["Server","CallToolRequestSchema","ListToolsRequestSchema","reportError","logger","INVALID_METHOD_LABEL","NO_METHOD_LABEL","buildAgentToolsMcpServer","params","server","name","version","capabilities","tools","setRequestHandler","authorizedTools","values","map","authorizedTool","mcpName","description","inputSchema","outputSchema","request","get","recordToolCall","recordCall","arguments","method","outcome","toolError","args","isRecord","methodValidation","validateMethod","kind","message","result","dispatch","isError","error","record","err","boundary","operation","tool","methods","allowedMethods","Set","candidate","id","has","content","type","text","value","Array","isArray"],"mappings":"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"}
|