@contractspec/example.integration-hub 3.0.0 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/connection/connection.enum.d.ts +8 -0
- package/dist/connection/connection.enum.js +18 -1
- package/dist/connection/connection.operation.d.ts +48 -0
- package/dist/connection/connection.operation.js +25 -2
- package/dist/connection/connection.presentation.js +25 -2
- package/dist/connection/connection.schema.d.ts +32 -0
- package/dist/connection/connection.schema.js +25 -2
- package/dist/connection/index.js +25 -2
- package/dist/handlers/index.js +47 -1
- package/dist/handlers/integration.handlers.d.ts +35 -0
- package/dist/handlers/integration.handlers.js +47 -1
- package/dist/index.js +80 -7
- package/dist/mcp-example.d.ts +3 -1
- package/dist/mcp-example.js +8 -4
- package/dist/node/connection/connection.enum.js +18 -1
- package/dist/node/connection/connection.operation.js +25 -2
- package/dist/node/connection/connection.presentation.js +25 -2
- package/dist/node/connection/connection.schema.js +25 -2
- package/dist/node/connection/index.js +25 -2
- package/dist/node/handlers/index.js +47 -1
- package/dist/node/handlers/integration.handlers.js +47 -1
- package/dist/node/index.js +80 -7
- package/dist/node/mcp-example.js +8 -4
- package/dist/node/run-mcp.js +8 -4
- package/dist/run-mcp.js +8 -4
- package/package.json +9 -9
package/dist/mcp-example.js
CHANGED
|
@@ -11,6 +11,7 @@ var DEFAULT_STDIO_ARGS = [
|
|
|
11
11
|
];
|
|
12
12
|
async function runIntegrationHubMcpExampleFromEnv() {
|
|
13
13
|
const mode = resolveMode();
|
|
14
|
+
const transport = resolveTransport();
|
|
14
15
|
const config = buildMcpConfigFromEnv();
|
|
15
16
|
const toolset = await createMcpToolsets([config], {
|
|
16
17
|
onNameCollision: "error"
|
|
@@ -21,8 +22,10 @@ async function runIntegrationHubMcpExampleFromEnv() {
|
|
|
21
22
|
mode,
|
|
22
23
|
server: {
|
|
23
24
|
name: config.name,
|
|
24
|
-
transport
|
|
25
|
+
transport
|
|
25
26
|
},
|
|
27
|
+
authMethod: process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_AUTH_METHOD,
|
|
28
|
+
apiVersion: process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_API_VERSION,
|
|
26
29
|
tools: toolNames
|
|
27
30
|
};
|
|
28
31
|
if (mode === "call") {
|
|
@@ -64,9 +67,10 @@ function buildMcpConfigFromEnv() {
|
|
|
64
67
|
}
|
|
65
68
|
const accessToken = process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_ACCESS_TOKEN;
|
|
66
69
|
const accessTokenEnvVar = process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_ACCESS_TOKEN_ENV;
|
|
70
|
+
const mcpTransport = transport === "webhook" || transport === "http" ? "http" : "sse";
|
|
67
71
|
return {
|
|
68
72
|
name,
|
|
69
|
-
transport,
|
|
73
|
+
transport: mcpTransport,
|
|
70
74
|
url: requireEnv("CONTRACTSPEC_INTEGRATION_HUB_MCP_URL"),
|
|
71
75
|
headers: parseStringRecordEnv("CONTRACTSPEC_INTEGRATION_HUB_MCP_HEADERS_JSON"),
|
|
72
76
|
accessToken,
|
|
@@ -83,10 +87,10 @@ function resolveMode() {
|
|
|
83
87
|
}
|
|
84
88
|
function resolveTransport() {
|
|
85
89
|
const rawTransport = process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_TRANSPORT?.toLowerCase() ?? "stdio";
|
|
86
|
-
if (rawTransport === "stdio" || rawTransport === "http" || rawTransport === "sse") {
|
|
90
|
+
if (rawTransport === "stdio" || rawTransport === "http" || rawTransport === "sse" || rawTransport === "webhook") {
|
|
87
91
|
return rawTransport;
|
|
88
92
|
}
|
|
89
|
-
throw new Error(`Unsupported CONTRACTSPEC_INTEGRATION_HUB_MCP_TRANSPORT: ${rawTransport}. Use "stdio", "http", or "
|
|
93
|
+
throw new Error(`Unsupported CONTRACTSPEC_INTEGRATION_HUB_MCP_TRANSPORT: ${rawTransport}. Use "stdio", "http", "sse", or "webhook".`);
|
|
90
94
|
}
|
|
91
95
|
function parseStringArrayEnv(key, fallback) {
|
|
92
96
|
const raw = process.env[key];
|
|
@@ -7,6 +7,23 @@ var ConnectionStatusEnum = defineEnum("ConnectionStatus", [
|
|
|
7
7
|
"ERROR",
|
|
8
8
|
"EXPIRED"
|
|
9
9
|
]);
|
|
10
|
+
var AuthTypeEnum = defineEnum("AuthType", [
|
|
11
|
+
"api_key",
|
|
12
|
+
"oauth2",
|
|
13
|
+
"bearer",
|
|
14
|
+
"header",
|
|
15
|
+
"basic",
|
|
16
|
+
"webhook_signing",
|
|
17
|
+
"service_account"
|
|
18
|
+
]);
|
|
19
|
+
var TransportTypeEnum = defineEnum("TransportType", [
|
|
20
|
+
"rest",
|
|
21
|
+
"mcp",
|
|
22
|
+
"webhook",
|
|
23
|
+
"sdk"
|
|
24
|
+
]);
|
|
10
25
|
export {
|
|
11
|
-
|
|
26
|
+
TransportTypeEnum,
|
|
27
|
+
ConnectionStatusEnum,
|
|
28
|
+
AuthTypeEnum
|
|
12
29
|
};
|
|
@@ -7,6 +7,21 @@ var ConnectionStatusEnum = defineEnum("ConnectionStatus", [
|
|
|
7
7
|
"ERROR",
|
|
8
8
|
"EXPIRED"
|
|
9
9
|
]);
|
|
10
|
+
var AuthTypeEnum = defineEnum("AuthType", [
|
|
11
|
+
"api_key",
|
|
12
|
+
"oauth2",
|
|
13
|
+
"bearer",
|
|
14
|
+
"header",
|
|
15
|
+
"basic",
|
|
16
|
+
"webhook_signing",
|
|
17
|
+
"service_account"
|
|
18
|
+
]);
|
|
19
|
+
var TransportTypeEnum = defineEnum("TransportType", [
|
|
20
|
+
"rest",
|
|
21
|
+
"mcp",
|
|
22
|
+
"webhook",
|
|
23
|
+
"sdk"
|
|
24
|
+
]);
|
|
10
25
|
|
|
11
26
|
// src/connection/connection.schema.ts
|
|
12
27
|
import { defineSchemaModel, ScalarTypeEnum } from "@contractspec/lib.schema";
|
|
@@ -27,7 +42,11 @@ var ConnectionModel = defineSchemaModel({
|
|
|
27
42
|
},
|
|
28
43
|
connectedAt: { type: ScalarTypeEnum.DateTime(), isOptional: true },
|
|
29
44
|
lastHealthCheck: { type: ScalarTypeEnum.DateTime(), isOptional: true },
|
|
30
|
-
healthStatus: { type: ScalarTypeEnum.String_unsecure(), isOptional: true }
|
|
45
|
+
healthStatus: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
46
|
+
transport: { type: TransportTypeEnum, isOptional: true },
|
|
47
|
+
authMethod: { type: AuthTypeEnum, isOptional: true },
|
|
48
|
+
apiVersion: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
49
|
+
ownershipMode: { type: ScalarTypeEnum.String_unsecure(), isOptional: true }
|
|
31
50
|
}
|
|
32
51
|
});
|
|
33
52
|
var CreateConnectionInputModel = defineSchemaModel({
|
|
@@ -39,7 +58,11 @@ var CreateConnectionInputModel = defineSchemaModel({
|
|
|
39
58
|
},
|
|
40
59
|
name: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },
|
|
41
60
|
authType: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },
|
|
42
|
-
credentials: { type: ScalarTypeEnum.JSON(), isOptional: true }
|
|
61
|
+
credentials: { type: ScalarTypeEnum.JSON(), isOptional: true },
|
|
62
|
+
transport: { type: TransportTypeEnum, isOptional: true },
|
|
63
|
+
authMethod: { type: AuthTypeEnum, isOptional: true },
|
|
64
|
+
apiVersion: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
65
|
+
ownershipMode: { type: ScalarTypeEnum.String_unsecure(), isOptional: true }
|
|
43
66
|
}
|
|
44
67
|
});
|
|
45
68
|
|
|
@@ -7,6 +7,21 @@ var ConnectionStatusEnum = defineEnum("ConnectionStatus", [
|
|
|
7
7
|
"ERROR",
|
|
8
8
|
"EXPIRED"
|
|
9
9
|
]);
|
|
10
|
+
var AuthTypeEnum = defineEnum("AuthType", [
|
|
11
|
+
"api_key",
|
|
12
|
+
"oauth2",
|
|
13
|
+
"bearer",
|
|
14
|
+
"header",
|
|
15
|
+
"basic",
|
|
16
|
+
"webhook_signing",
|
|
17
|
+
"service_account"
|
|
18
|
+
]);
|
|
19
|
+
var TransportTypeEnum = defineEnum("TransportType", [
|
|
20
|
+
"rest",
|
|
21
|
+
"mcp",
|
|
22
|
+
"webhook",
|
|
23
|
+
"sdk"
|
|
24
|
+
]);
|
|
10
25
|
|
|
11
26
|
// src/connection/connection.schema.ts
|
|
12
27
|
import { defineSchemaModel, ScalarTypeEnum } from "@contractspec/lib.schema";
|
|
@@ -27,7 +42,11 @@ var ConnectionModel = defineSchemaModel({
|
|
|
27
42
|
},
|
|
28
43
|
connectedAt: { type: ScalarTypeEnum.DateTime(), isOptional: true },
|
|
29
44
|
lastHealthCheck: { type: ScalarTypeEnum.DateTime(), isOptional: true },
|
|
30
|
-
healthStatus: { type: ScalarTypeEnum.String_unsecure(), isOptional: true }
|
|
45
|
+
healthStatus: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
46
|
+
transport: { type: TransportTypeEnum, isOptional: true },
|
|
47
|
+
authMethod: { type: AuthTypeEnum, isOptional: true },
|
|
48
|
+
apiVersion: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
49
|
+
ownershipMode: { type: ScalarTypeEnum.String_unsecure(), isOptional: true }
|
|
31
50
|
}
|
|
32
51
|
});
|
|
33
52
|
var CreateConnectionInputModel = defineSchemaModel({
|
|
@@ -39,7 +58,11 @@ var CreateConnectionInputModel = defineSchemaModel({
|
|
|
39
58
|
},
|
|
40
59
|
name: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },
|
|
41
60
|
authType: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },
|
|
42
|
-
credentials: { type: ScalarTypeEnum.JSON(), isOptional: true }
|
|
61
|
+
credentials: { type: ScalarTypeEnum.JSON(), isOptional: true },
|
|
62
|
+
transport: { type: TransportTypeEnum, isOptional: true },
|
|
63
|
+
authMethod: { type: AuthTypeEnum, isOptional: true },
|
|
64
|
+
apiVersion: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
65
|
+
ownershipMode: { type: ScalarTypeEnum.String_unsecure(), isOptional: true }
|
|
43
66
|
}
|
|
44
67
|
});
|
|
45
68
|
|
|
@@ -7,6 +7,21 @@ var ConnectionStatusEnum = defineEnum("ConnectionStatus", [
|
|
|
7
7
|
"ERROR",
|
|
8
8
|
"EXPIRED"
|
|
9
9
|
]);
|
|
10
|
+
var AuthTypeEnum = defineEnum("AuthType", [
|
|
11
|
+
"api_key",
|
|
12
|
+
"oauth2",
|
|
13
|
+
"bearer",
|
|
14
|
+
"header",
|
|
15
|
+
"basic",
|
|
16
|
+
"webhook_signing",
|
|
17
|
+
"service_account"
|
|
18
|
+
]);
|
|
19
|
+
var TransportTypeEnum = defineEnum("TransportType", [
|
|
20
|
+
"rest",
|
|
21
|
+
"mcp",
|
|
22
|
+
"webhook",
|
|
23
|
+
"sdk"
|
|
24
|
+
]);
|
|
10
25
|
|
|
11
26
|
// src/connection/connection.schema.ts
|
|
12
27
|
import { defineSchemaModel, ScalarTypeEnum } from "@contractspec/lib.schema";
|
|
@@ -27,7 +42,11 @@ var ConnectionModel = defineSchemaModel({
|
|
|
27
42
|
},
|
|
28
43
|
connectedAt: { type: ScalarTypeEnum.DateTime(), isOptional: true },
|
|
29
44
|
lastHealthCheck: { type: ScalarTypeEnum.DateTime(), isOptional: true },
|
|
30
|
-
healthStatus: { type: ScalarTypeEnum.String_unsecure(), isOptional: true }
|
|
45
|
+
healthStatus: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
46
|
+
transport: { type: TransportTypeEnum, isOptional: true },
|
|
47
|
+
authMethod: { type: AuthTypeEnum, isOptional: true },
|
|
48
|
+
apiVersion: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
49
|
+
ownershipMode: { type: ScalarTypeEnum.String_unsecure(), isOptional: true }
|
|
31
50
|
}
|
|
32
51
|
});
|
|
33
52
|
var CreateConnectionInputModel = defineSchemaModel({
|
|
@@ -39,7 +58,11 @@ var CreateConnectionInputModel = defineSchemaModel({
|
|
|
39
58
|
},
|
|
40
59
|
name: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },
|
|
41
60
|
authType: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },
|
|
42
|
-
credentials: { type: ScalarTypeEnum.JSON(), isOptional: true }
|
|
61
|
+
credentials: { type: ScalarTypeEnum.JSON(), isOptional: true },
|
|
62
|
+
transport: { type: TransportTypeEnum, isOptional: true },
|
|
63
|
+
authMethod: { type: AuthTypeEnum, isOptional: true },
|
|
64
|
+
apiVersion: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
65
|
+
ownershipMode: { type: ScalarTypeEnum.String_unsecure(), isOptional: true }
|
|
43
66
|
}
|
|
44
67
|
});
|
|
45
68
|
export {
|
|
@@ -7,6 +7,21 @@ var ConnectionStatusEnum = defineEnum("ConnectionStatus", [
|
|
|
7
7
|
"ERROR",
|
|
8
8
|
"EXPIRED"
|
|
9
9
|
]);
|
|
10
|
+
var AuthTypeEnum = defineEnum("AuthType", [
|
|
11
|
+
"api_key",
|
|
12
|
+
"oauth2",
|
|
13
|
+
"bearer",
|
|
14
|
+
"header",
|
|
15
|
+
"basic",
|
|
16
|
+
"webhook_signing",
|
|
17
|
+
"service_account"
|
|
18
|
+
]);
|
|
19
|
+
var TransportTypeEnum = defineEnum("TransportType", [
|
|
20
|
+
"rest",
|
|
21
|
+
"mcp",
|
|
22
|
+
"webhook",
|
|
23
|
+
"sdk"
|
|
24
|
+
]);
|
|
10
25
|
|
|
11
26
|
// src/connection/connection.schema.ts
|
|
12
27
|
import { defineSchemaModel, ScalarTypeEnum } from "@contractspec/lib.schema";
|
|
@@ -27,7 +42,11 @@ var ConnectionModel = defineSchemaModel({
|
|
|
27
42
|
},
|
|
28
43
|
connectedAt: { type: ScalarTypeEnum.DateTime(), isOptional: true },
|
|
29
44
|
lastHealthCheck: { type: ScalarTypeEnum.DateTime(), isOptional: true },
|
|
30
|
-
healthStatus: { type: ScalarTypeEnum.String_unsecure(), isOptional: true }
|
|
45
|
+
healthStatus: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
46
|
+
transport: { type: TransportTypeEnum, isOptional: true },
|
|
47
|
+
authMethod: { type: AuthTypeEnum, isOptional: true },
|
|
48
|
+
apiVersion: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
49
|
+
ownershipMode: { type: ScalarTypeEnum.String_unsecure(), isOptional: true }
|
|
31
50
|
}
|
|
32
51
|
});
|
|
33
52
|
var CreateConnectionInputModel = defineSchemaModel({
|
|
@@ -39,7 +58,11 @@ var CreateConnectionInputModel = defineSchemaModel({
|
|
|
39
58
|
},
|
|
40
59
|
name: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },
|
|
41
60
|
authType: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },
|
|
42
|
-
credentials: { type: ScalarTypeEnum.JSON(), isOptional: true }
|
|
61
|
+
credentials: { type: ScalarTypeEnum.JSON(), isOptional: true },
|
|
62
|
+
transport: { type: TransportTypeEnum, isOptional: true },
|
|
63
|
+
authMethod: { type: AuthTypeEnum, isOptional: true },
|
|
64
|
+
apiVersion: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
65
|
+
ownershipMode: { type: ScalarTypeEnum.String_unsecure(), isOptional: true }
|
|
43
66
|
}
|
|
44
67
|
});
|
|
45
68
|
|
|
@@ -228,6 +228,49 @@ function createIntegrationHandlers(db) {
|
|
|
228
228
|
])).rows;
|
|
229
229
|
return rowToSyncConfig(rows[0]);
|
|
230
230
|
}
|
|
231
|
+
async function validateByokKey(input) {
|
|
232
|
+
const rows = (await db.query(`SELECT * FROM integration_connection WHERE id = ?`, [
|
|
233
|
+
input.connectionId
|
|
234
|
+
])).rows;
|
|
235
|
+
if (!rows[0]) {
|
|
236
|
+
return {
|
|
237
|
+
valid: false,
|
|
238
|
+
provider: "unknown",
|
|
239
|
+
keyPrefix: "",
|
|
240
|
+
error: `Connection ${input.connectionId} not found`
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
const keyPrefix = input.providerKey.slice(0, 8);
|
|
244
|
+
const looksValid = input.providerKey.length >= 16;
|
|
245
|
+
return {
|
|
246
|
+
valid: looksValid,
|
|
247
|
+
provider: rows[0].name,
|
|
248
|
+
keyPrefix: `${keyPrefix}...`,
|
|
249
|
+
expiresAt: looksValid ? new Date(Date.now() + 90 * 24 * 60 * 60 * 1000).toISOString() : undefined,
|
|
250
|
+
error: looksValid ? undefined : "Key must be at least 16 characters"
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
async function refreshOAuth2Token(input) {
|
|
254
|
+
const now = new Date().toISOString();
|
|
255
|
+
await db.execute(`UPDATE integration_connection SET updatedAt = ? WHERE id = ?`, [now, input.connectionId]);
|
|
256
|
+
return {
|
|
257
|
+
refreshed: true,
|
|
258
|
+
expiresAt: new Date(Date.now() + 3600 * 1000).toISOString(),
|
|
259
|
+
tokenType: "Bearer",
|
|
260
|
+
scopes: ["read", "write", "sync"]
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
async function getTransportOptions(input) {
|
|
264
|
+
return {
|
|
265
|
+
integrationId: input.integrationId,
|
|
266
|
+
transports: [
|
|
267
|
+
{ transport: "rest", supported: true, defaultVersion: "v2" },
|
|
268
|
+
{ transport: "mcp", supported: true, defaultVersion: "v1" },
|
|
269
|
+
{ transport: "webhook", supported: true },
|
|
270
|
+
{ transport: "sdk", supported: false }
|
|
271
|
+
]
|
|
272
|
+
};
|
|
273
|
+
}
|
|
231
274
|
return {
|
|
232
275
|
listIntegrations,
|
|
233
276
|
createIntegration,
|
|
@@ -238,7 +281,10 @@ function createIntegrationHandlers(db) {
|
|
|
238
281
|
configureSync,
|
|
239
282
|
mapFields,
|
|
240
283
|
getFieldMappings,
|
|
241
|
-
runSync
|
|
284
|
+
runSync,
|
|
285
|
+
validateByokKey,
|
|
286
|
+
refreshOAuth2Token,
|
|
287
|
+
getTransportOptions
|
|
242
288
|
};
|
|
243
289
|
}
|
|
244
290
|
export {
|
|
@@ -228,6 +228,49 @@ function createIntegrationHandlers(db) {
|
|
|
228
228
|
])).rows;
|
|
229
229
|
return rowToSyncConfig(rows[0]);
|
|
230
230
|
}
|
|
231
|
+
async function validateByokKey(input) {
|
|
232
|
+
const rows = (await db.query(`SELECT * FROM integration_connection WHERE id = ?`, [
|
|
233
|
+
input.connectionId
|
|
234
|
+
])).rows;
|
|
235
|
+
if (!rows[0]) {
|
|
236
|
+
return {
|
|
237
|
+
valid: false,
|
|
238
|
+
provider: "unknown",
|
|
239
|
+
keyPrefix: "",
|
|
240
|
+
error: `Connection ${input.connectionId} not found`
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
const keyPrefix = input.providerKey.slice(0, 8);
|
|
244
|
+
const looksValid = input.providerKey.length >= 16;
|
|
245
|
+
return {
|
|
246
|
+
valid: looksValid,
|
|
247
|
+
provider: rows[0].name,
|
|
248
|
+
keyPrefix: `${keyPrefix}...`,
|
|
249
|
+
expiresAt: looksValid ? new Date(Date.now() + 90 * 24 * 60 * 60 * 1000).toISOString() : undefined,
|
|
250
|
+
error: looksValid ? undefined : "Key must be at least 16 characters"
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
async function refreshOAuth2Token(input) {
|
|
254
|
+
const now = new Date().toISOString();
|
|
255
|
+
await db.execute(`UPDATE integration_connection SET updatedAt = ? WHERE id = ?`, [now, input.connectionId]);
|
|
256
|
+
return {
|
|
257
|
+
refreshed: true,
|
|
258
|
+
expiresAt: new Date(Date.now() + 3600 * 1000).toISOString(),
|
|
259
|
+
tokenType: "Bearer",
|
|
260
|
+
scopes: ["read", "write", "sync"]
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
async function getTransportOptions(input) {
|
|
264
|
+
return {
|
|
265
|
+
integrationId: input.integrationId,
|
|
266
|
+
transports: [
|
|
267
|
+
{ transport: "rest", supported: true, defaultVersion: "v2" },
|
|
268
|
+
{ transport: "mcp", supported: true, defaultVersion: "v1" },
|
|
269
|
+
{ transport: "webhook", supported: true },
|
|
270
|
+
{ transport: "sdk", supported: false }
|
|
271
|
+
]
|
|
272
|
+
};
|
|
273
|
+
}
|
|
231
274
|
return {
|
|
232
275
|
listIntegrations,
|
|
233
276
|
createIntegration,
|
|
@@ -238,7 +281,10 @@ function createIntegrationHandlers(db) {
|
|
|
238
281
|
configureSync,
|
|
239
282
|
mapFields,
|
|
240
283
|
getFieldMappings,
|
|
241
|
-
runSync
|
|
284
|
+
runSync,
|
|
285
|
+
validateByokKey,
|
|
286
|
+
refreshOAuth2Token,
|
|
287
|
+
getTransportOptions
|
|
242
288
|
};
|
|
243
289
|
}
|
|
244
290
|
export {
|
package/dist/node/index.js
CHANGED
|
@@ -7,6 +7,21 @@ var ConnectionStatusEnum = defineEnum("ConnectionStatus", [
|
|
|
7
7
|
"ERROR",
|
|
8
8
|
"EXPIRED"
|
|
9
9
|
]);
|
|
10
|
+
var AuthTypeEnum = defineEnum("AuthType", [
|
|
11
|
+
"api_key",
|
|
12
|
+
"oauth2",
|
|
13
|
+
"bearer",
|
|
14
|
+
"header",
|
|
15
|
+
"basic",
|
|
16
|
+
"webhook_signing",
|
|
17
|
+
"service_account"
|
|
18
|
+
]);
|
|
19
|
+
var TransportTypeEnum = defineEnum("TransportType", [
|
|
20
|
+
"rest",
|
|
21
|
+
"mcp",
|
|
22
|
+
"webhook",
|
|
23
|
+
"sdk"
|
|
24
|
+
]);
|
|
10
25
|
|
|
11
26
|
// src/connection/connection.schema.ts
|
|
12
27
|
import { defineSchemaModel, ScalarTypeEnum } from "@contractspec/lib.schema";
|
|
@@ -27,7 +42,11 @@ var ConnectionModel = defineSchemaModel({
|
|
|
27
42
|
},
|
|
28
43
|
connectedAt: { type: ScalarTypeEnum.DateTime(), isOptional: true },
|
|
29
44
|
lastHealthCheck: { type: ScalarTypeEnum.DateTime(), isOptional: true },
|
|
30
|
-
healthStatus: { type: ScalarTypeEnum.String_unsecure(), isOptional: true }
|
|
45
|
+
healthStatus: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
46
|
+
transport: { type: TransportTypeEnum, isOptional: true },
|
|
47
|
+
authMethod: { type: AuthTypeEnum, isOptional: true },
|
|
48
|
+
apiVersion: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
49
|
+
ownershipMode: { type: ScalarTypeEnum.String_unsecure(), isOptional: true }
|
|
31
50
|
}
|
|
32
51
|
});
|
|
33
52
|
var CreateConnectionInputModel = defineSchemaModel({
|
|
@@ -39,7 +58,11 @@ var CreateConnectionInputModel = defineSchemaModel({
|
|
|
39
58
|
},
|
|
40
59
|
name: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },
|
|
41
60
|
authType: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },
|
|
42
|
-
credentials: { type: ScalarTypeEnum.JSON(), isOptional: true }
|
|
61
|
+
credentials: { type: ScalarTypeEnum.JSON(), isOptional: true },
|
|
62
|
+
transport: { type: TransportTypeEnum, isOptional: true },
|
|
63
|
+
authMethod: { type: AuthTypeEnum, isOptional: true },
|
|
64
|
+
apiVersion: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
65
|
+
ownershipMode: { type: ScalarTypeEnum.String_unsecure(), isOptional: true }
|
|
43
66
|
}
|
|
44
67
|
});
|
|
45
68
|
|
|
@@ -326,6 +349,49 @@ function createIntegrationHandlers(db) {
|
|
|
326
349
|
])).rows;
|
|
327
350
|
return rowToSyncConfig(rows[0]);
|
|
328
351
|
}
|
|
352
|
+
async function validateByokKey(input) {
|
|
353
|
+
const rows = (await db.query(`SELECT * FROM integration_connection WHERE id = ?`, [
|
|
354
|
+
input.connectionId
|
|
355
|
+
])).rows;
|
|
356
|
+
if (!rows[0]) {
|
|
357
|
+
return {
|
|
358
|
+
valid: false,
|
|
359
|
+
provider: "unknown",
|
|
360
|
+
keyPrefix: "",
|
|
361
|
+
error: `Connection ${input.connectionId} not found`
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
const keyPrefix = input.providerKey.slice(0, 8);
|
|
365
|
+
const looksValid = input.providerKey.length >= 16;
|
|
366
|
+
return {
|
|
367
|
+
valid: looksValid,
|
|
368
|
+
provider: rows[0].name,
|
|
369
|
+
keyPrefix: `${keyPrefix}...`,
|
|
370
|
+
expiresAt: looksValid ? new Date(Date.now() + 90 * 24 * 60 * 60 * 1000).toISOString() : undefined,
|
|
371
|
+
error: looksValid ? undefined : "Key must be at least 16 characters"
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
async function refreshOAuth2Token(input) {
|
|
375
|
+
const now = new Date().toISOString();
|
|
376
|
+
await db.execute(`UPDATE integration_connection SET updatedAt = ? WHERE id = ?`, [now, input.connectionId]);
|
|
377
|
+
return {
|
|
378
|
+
refreshed: true,
|
|
379
|
+
expiresAt: new Date(Date.now() + 3600 * 1000).toISOString(),
|
|
380
|
+
tokenType: "Bearer",
|
|
381
|
+
scopes: ["read", "write", "sync"]
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
async function getTransportOptions(input) {
|
|
385
|
+
return {
|
|
386
|
+
integrationId: input.integrationId,
|
|
387
|
+
transports: [
|
|
388
|
+
{ transport: "rest", supported: true, defaultVersion: "v2" },
|
|
389
|
+
{ transport: "mcp", supported: true, defaultVersion: "v1" },
|
|
390
|
+
{ transport: "webhook", supported: true },
|
|
391
|
+
{ transport: "sdk", supported: false }
|
|
392
|
+
]
|
|
393
|
+
};
|
|
394
|
+
}
|
|
329
395
|
return {
|
|
330
396
|
listIntegrations,
|
|
331
397
|
createIntegration,
|
|
@@ -336,7 +402,10 @@ function createIntegrationHandlers(db) {
|
|
|
336
402
|
configureSync,
|
|
337
403
|
mapFields,
|
|
338
404
|
getFieldMappings,
|
|
339
|
-
runSync
|
|
405
|
+
runSync,
|
|
406
|
+
validateByokKey,
|
|
407
|
+
refreshOAuth2Token,
|
|
408
|
+
getTransportOptions
|
|
340
409
|
};
|
|
341
410
|
}
|
|
342
411
|
|
|
@@ -1570,6 +1639,7 @@ var DEFAULT_STDIO_ARGS = [
|
|
|
1570
1639
|
];
|
|
1571
1640
|
async function runIntegrationHubMcpExampleFromEnv() {
|
|
1572
1641
|
const mode = resolveMode();
|
|
1642
|
+
const transport = resolveTransport();
|
|
1573
1643
|
const config = buildMcpConfigFromEnv();
|
|
1574
1644
|
const toolset = await createMcpToolsets([config], {
|
|
1575
1645
|
onNameCollision: "error"
|
|
@@ -1580,8 +1650,10 @@ async function runIntegrationHubMcpExampleFromEnv() {
|
|
|
1580
1650
|
mode,
|
|
1581
1651
|
server: {
|
|
1582
1652
|
name: config.name,
|
|
1583
|
-
transport
|
|
1653
|
+
transport
|
|
1584
1654
|
},
|
|
1655
|
+
authMethod: process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_AUTH_METHOD,
|
|
1656
|
+
apiVersion: process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_API_VERSION,
|
|
1585
1657
|
tools: toolNames
|
|
1586
1658
|
};
|
|
1587
1659
|
if (mode === "call") {
|
|
@@ -1623,9 +1695,10 @@ function buildMcpConfigFromEnv() {
|
|
|
1623
1695
|
}
|
|
1624
1696
|
const accessToken = process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_ACCESS_TOKEN;
|
|
1625
1697
|
const accessTokenEnvVar = process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_ACCESS_TOKEN_ENV;
|
|
1698
|
+
const mcpTransport = transport === "webhook" || transport === "http" ? "http" : "sse";
|
|
1626
1699
|
return {
|
|
1627
1700
|
name,
|
|
1628
|
-
transport,
|
|
1701
|
+
transport: mcpTransport,
|
|
1629
1702
|
url: requireEnv("CONTRACTSPEC_INTEGRATION_HUB_MCP_URL"),
|
|
1630
1703
|
headers: parseStringRecordEnv("CONTRACTSPEC_INTEGRATION_HUB_MCP_HEADERS_JSON"),
|
|
1631
1704
|
accessToken,
|
|
@@ -1642,10 +1715,10 @@ function resolveMode() {
|
|
|
1642
1715
|
}
|
|
1643
1716
|
function resolveTransport() {
|
|
1644
1717
|
const rawTransport = process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_TRANSPORT?.toLowerCase() ?? "stdio";
|
|
1645
|
-
if (rawTransport === "stdio" || rawTransport === "http" || rawTransport === "sse") {
|
|
1718
|
+
if (rawTransport === "stdio" || rawTransport === "http" || rawTransport === "sse" || rawTransport === "webhook") {
|
|
1646
1719
|
return rawTransport;
|
|
1647
1720
|
}
|
|
1648
|
-
throw new Error(`Unsupported CONTRACTSPEC_INTEGRATION_HUB_MCP_TRANSPORT: ${rawTransport}. Use "stdio", "http", or "
|
|
1721
|
+
throw new Error(`Unsupported CONTRACTSPEC_INTEGRATION_HUB_MCP_TRANSPORT: ${rawTransport}. Use "stdio", "http", "sse", or "webhook".`);
|
|
1649
1722
|
}
|
|
1650
1723
|
function parseStringArrayEnv(key, fallback) {
|
|
1651
1724
|
const raw = process.env[key];
|
package/dist/node/mcp-example.js
CHANGED
|
@@ -10,6 +10,7 @@ var DEFAULT_STDIO_ARGS = [
|
|
|
10
10
|
];
|
|
11
11
|
async function runIntegrationHubMcpExampleFromEnv() {
|
|
12
12
|
const mode = resolveMode();
|
|
13
|
+
const transport = resolveTransport();
|
|
13
14
|
const config = buildMcpConfigFromEnv();
|
|
14
15
|
const toolset = await createMcpToolsets([config], {
|
|
15
16
|
onNameCollision: "error"
|
|
@@ -20,8 +21,10 @@ async function runIntegrationHubMcpExampleFromEnv() {
|
|
|
20
21
|
mode,
|
|
21
22
|
server: {
|
|
22
23
|
name: config.name,
|
|
23
|
-
transport
|
|
24
|
+
transport
|
|
24
25
|
},
|
|
26
|
+
authMethod: process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_AUTH_METHOD,
|
|
27
|
+
apiVersion: process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_API_VERSION,
|
|
25
28
|
tools: toolNames
|
|
26
29
|
};
|
|
27
30
|
if (mode === "call") {
|
|
@@ -63,9 +66,10 @@ function buildMcpConfigFromEnv() {
|
|
|
63
66
|
}
|
|
64
67
|
const accessToken = process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_ACCESS_TOKEN;
|
|
65
68
|
const accessTokenEnvVar = process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_ACCESS_TOKEN_ENV;
|
|
69
|
+
const mcpTransport = transport === "webhook" || transport === "http" ? "http" : "sse";
|
|
66
70
|
return {
|
|
67
71
|
name,
|
|
68
|
-
transport,
|
|
72
|
+
transport: mcpTransport,
|
|
69
73
|
url: requireEnv("CONTRACTSPEC_INTEGRATION_HUB_MCP_URL"),
|
|
70
74
|
headers: parseStringRecordEnv("CONTRACTSPEC_INTEGRATION_HUB_MCP_HEADERS_JSON"),
|
|
71
75
|
accessToken,
|
|
@@ -82,10 +86,10 @@ function resolveMode() {
|
|
|
82
86
|
}
|
|
83
87
|
function resolveTransport() {
|
|
84
88
|
const rawTransport = process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_TRANSPORT?.toLowerCase() ?? "stdio";
|
|
85
|
-
if (rawTransport === "stdio" || rawTransport === "http" || rawTransport === "sse") {
|
|
89
|
+
if (rawTransport === "stdio" || rawTransport === "http" || rawTransport === "sse" || rawTransport === "webhook") {
|
|
86
90
|
return rawTransport;
|
|
87
91
|
}
|
|
88
|
-
throw new Error(`Unsupported CONTRACTSPEC_INTEGRATION_HUB_MCP_TRANSPORT: ${rawTransport}. Use "stdio", "http", or "
|
|
92
|
+
throw new Error(`Unsupported CONTRACTSPEC_INTEGRATION_HUB_MCP_TRANSPORT: ${rawTransport}. Use "stdio", "http", "sse", or "webhook".`);
|
|
89
93
|
}
|
|
90
94
|
function parseStringArrayEnv(key, fallback) {
|
|
91
95
|
const raw = process.env[key];
|
package/dist/node/run-mcp.js
CHANGED
|
@@ -10,6 +10,7 @@ var DEFAULT_STDIO_ARGS = [
|
|
|
10
10
|
];
|
|
11
11
|
async function runIntegrationHubMcpExampleFromEnv() {
|
|
12
12
|
const mode = resolveMode();
|
|
13
|
+
const transport = resolveTransport();
|
|
13
14
|
const config = buildMcpConfigFromEnv();
|
|
14
15
|
const toolset = await createMcpToolsets([config], {
|
|
15
16
|
onNameCollision: "error"
|
|
@@ -20,8 +21,10 @@ async function runIntegrationHubMcpExampleFromEnv() {
|
|
|
20
21
|
mode,
|
|
21
22
|
server: {
|
|
22
23
|
name: config.name,
|
|
23
|
-
transport
|
|
24
|
+
transport
|
|
24
25
|
},
|
|
26
|
+
authMethod: process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_AUTH_METHOD,
|
|
27
|
+
apiVersion: process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_API_VERSION,
|
|
25
28
|
tools: toolNames
|
|
26
29
|
};
|
|
27
30
|
if (mode === "call") {
|
|
@@ -63,9 +66,10 @@ function buildMcpConfigFromEnv() {
|
|
|
63
66
|
}
|
|
64
67
|
const accessToken = process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_ACCESS_TOKEN;
|
|
65
68
|
const accessTokenEnvVar = process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_ACCESS_TOKEN_ENV;
|
|
69
|
+
const mcpTransport = transport === "webhook" || transport === "http" ? "http" : "sse";
|
|
66
70
|
return {
|
|
67
71
|
name,
|
|
68
|
-
transport,
|
|
72
|
+
transport: mcpTransport,
|
|
69
73
|
url: requireEnv("CONTRACTSPEC_INTEGRATION_HUB_MCP_URL"),
|
|
70
74
|
headers: parseStringRecordEnv("CONTRACTSPEC_INTEGRATION_HUB_MCP_HEADERS_JSON"),
|
|
71
75
|
accessToken,
|
|
@@ -82,10 +86,10 @@ function resolveMode() {
|
|
|
82
86
|
}
|
|
83
87
|
function resolveTransport() {
|
|
84
88
|
const rawTransport = process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_TRANSPORT?.toLowerCase() ?? "stdio";
|
|
85
|
-
if (rawTransport === "stdio" || rawTransport === "http" || rawTransport === "sse") {
|
|
89
|
+
if (rawTransport === "stdio" || rawTransport === "http" || rawTransport === "sse" || rawTransport === "webhook") {
|
|
86
90
|
return rawTransport;
|
|
87
91
|
}
|
|
88
|
-
throw new Error(`Unsupported CONTRACTSPEC_INTEGRATION_HUB_MCP_TRANSPORT: ${rawTransport}. Use "stdio", "http", or "
|
|
92
|
+
throw new Error(`Unsupported CONTRACTSPEC_INTEGRATION_HUB_MCP_TRANSPORT: ${rawTransport}. Use "stdio", "http", "sse", or "webhook".`);
|
|
89
93
|
}
|
|
90
94
|
function parseStringArrayEnv(key, fallback) {
|
|
91
95
|
const raw = process.env[key];
|
package/dist/run-mcp.js
CHANGED
|
@@ -11,6 +11,7 @@ var DEFAULT_STDIO_ARGS = [
|
|
|
11
11
|
];
|
|
12
12
|
async function runIntegrationHubMcpExampleFromEnv() {
|
|
13
13
|
const mode = resolveMode();
|
|
14
|
+
const transport = resolveTransport();
|
|
14
15
|
const config = buildMcpConfigFromEnv();
|
|
15
16
|
const toolset = await createMcpToolsets([config], {
|
|
16
17
|
onNameCollision: "error"
|
|
@@ -21,8 +22,10 @@ async function runIntegrationHubMcpExampleFromEnv() {
|
|
|
21
22
|
mode,
|
|
22
23
|
server: {
|
|
23
24
|
name: config.name,
|
|
24
|
-
transport
|
|
25
|
+
transport
|
|
25
26
|
},
|
|
27
|
+
authMethod: process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_AUTH_METHOD,
|
|
28
|
+
apiVersion: process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_API_VERSION,
|
|
26
29
|
tools: toolNames
|
|
27
30
|
};
|
|
28
31
|
if (mode === "call") {
|
|
@@ -64,9 +67,10 @@ function buildMcpConfigFromEnv() {
|
|
|
64
67
|
}
|
|
65
68
|
const accessToken = process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_ACCESS_TOKEN;
|
|
66
69
|
const accessTokenEnvVar = process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_ACCESS_TOKEN_ENV;
|
|
70
|
+
const mcpTransport = transport === "webhook" || transport === "http" ? "http" : "sse";
|
|
67
71
|
return {
|
|
68
72
|
name,
|
|
69
|
-
transport,
|
|
73
|
+
transport: mcpTransport,
|
|
70
74
|
url: requireEnv("CONTRACTSPEC_INTEGRATION_HUB_MCP_URL"),
|
|
71
75
|
headers: parseStringRecordEnv("CONTRACTSPEC_INTEGRATION_HUB_MCP_HEADERS_JSON"),
|
|
72
76
|
accessToken,
|
|
@@ -83,10 +87,10 @@ function resolveMode() {
|
|
|
83
87
|
}
|
|
84
88
|
function resolveTransport() {
|
|
85
89
|
const rawTransport = process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_TRANSPORT?.toLowerCase() ?? "stdio";
|
|
86
|
-
if (rawTransport === "stdio" || rawTransport === "http" || rawTransport === "sse") {
|
|
90
|
+
if (rawTransport === "stdio" || rawTransport === "http" || rawTransport === "sse" || rawTransport === "webhook") {
|
|
87
91
|
return rawTransport;
|
|
88
92
|
}
|
|
89
|
-
throw new Error(`Unsupported CONTRACTSPEC_INTEGRATION_HUB_MCP_TRANSPORT: ${rawTransport}. Use "stdio", "http", or "
|
|
93
|
+
throw new Error(`Unsupported CONTRACTSPEC_INTEGRATION_HUB_MCP_TRANSPORT: ${rawTransport}. Use "stdio", "http", "sse", or "webhook".`);
|
|
90
94
|
}
|
|
91
95
|
function parseStringArrayEnv(key, fallback) {
|
|
92
96
|
const raw = process.env[key];
|