@samanhappy/mcphub 1.0.5 → 1.0.6
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/betterAuth.js +2 -2
- package/dist/betterAuth.js.map +1 -1
- package/dist/clients/openapi.js +98 -5
- package/dist/clients/openapi.js.map +1 -1
- package/dist/controllers/hostedInternalController.js +55 -0
- package/dist/controllers/hostedInternalController.js.map +1 -0
- package/dist/controllers/serverController.js +1 -1
- package/dist/controllers/serverController.js.map +1 -1
- package/dist/dao/ServerDao.js +24 -0
- package/dist/dao/ServerDao.js.map +1 -1
- package/dist/dao/ServerDaoDbImpl.js +11 -0
- package/dist/dao/ServerDaoDbImpl.js.map +1 -1
- package/dist/db/repositories/ServerRepository.js +16 -0
- package/dist/db/repositories/ServerRepository.js.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/routes/index.js +5 -1
- package/dist/routes/index.js.map +1 -1
- package/dist/services/betterAuthConfig.js +144 -33
- package/dist/services/betterAuthConfig.js.map +1 -1
- package/dist/services/hostedAuthService.js +314 -0
- package/dist/services/hostedAuthService.js.map +1 -0
- package/dist/services/hostedControlPlaneClient.js +90 -0
- package/dist/services/hostedControlPlaneClient.js.map +1 -0
- package/dist/services/hostedEventSubscriber.js +206 -0
- package/dist/services/hostedEventSubscriber.js.map +1 -0
- package/dist/services/hostedInternalAuth.js +108 -0
- package/dist/services/hostedInternalAuth.js.map +1 -0
- package/dist/services/hostedMode.js +4 -0
- package/dist/services/hostedMode.js.map +1 -0
- package/dist/services/hostedNodeIdentity.js +8 -0
- package/dist/services/hostedNodeIdentity.js.map +1 -0
- package/dist/services/hostedRuntimeCatalogNames.js +7 -0
- package/dist/services/hostedRuntimeCatalogNames.js.map +1 -0
- package/dist/services/hostedRuntimeCatalogService.js +31 -0
- package/dist/services/hostedRuntimeCatalogService.js.map +1 -0
- package/dist/services/mcpService.js +84 -10
- package/dist/services/mcpService.js.map +1 -1
- package/dist/services/requestContextService.js +12 -0
- package/dist/services/requestContextService.js.map +1 -1
- package/dist/services/sseService.js +61 -10
- package/dist/services/sseService.js.map +1 -1
- package/dist/utils/rateLimit.js +4 -0
- package/dist/utils/rateLimit.js.map +1 -1
- package/frontend/dist/assets/{ActivityPage-Ccbl6DLW.js → ActivityPage-CLXufyzU.js} +2 -2
- package/frontend/dist/assets/{ActivityPage-Ccbl6DLW.js.map → ActivityPage-CLXufyzU.js.map} +1 -1
- package/frontend/dist/assets/{Dashboard-CPkAALtS.js → Dashboard-YMaaIlIZ.js} +2 -2
- package/frontend/dist/assets/{Dashboard-CPkAALtS.js.map → Dashboard-YMaaIlIZ.js.map} +1 -1
- package/frontend/dist/assets/{EndpointCopy-BYHUhlpW.js → EndpointCopy-Cpc2WqQz.js} +2 -2
- package/frontend/dist/assets/{EndpointCopy-BYHUhlpW.js.map → EndpointCopy-Cpc2WqQz.js.map} +1 -1
- package/frontend/dist/assets/{GroupsPage-CJI35G25.js → GroupsPage-DqK5U5rY.js} +2 -2
- package/frontend/dist/assets/{GroupsPage-CJI35G25.js.map → GroupsPage-DqK5U5rY.js.map} +1 -1
- package/frontend/dist/assets/{LoginPage-BZ0WR09v.js → LoginPage-ByV35kun.js} +2 -2
- package/frontend/dist/assets/{LoginPage-BZ0WR09v.js.map → LoginPage-ByV35kun.js.map} +1 -1
- package/frontend/dist/assets/{LogsPage-C_U-xXX0.js → LogsPage-BygFVcaV.js} +2 -2
- package/frontend/dist/assets/{LogsPage-C_U-xXX0.js.map → LogsPage-BygFVcaV.js.map} +1 -1
- package/frontend/dist/assets/{MarketPage-dyC4ocP6.js → MarketPage-Cc7QeqSw.js} +2 -2
- package/frontend/dist/assets/{MarketPage-dyC4ocP6.js.map → MarketPage-Cc7QeqSw.js.map} +1 -1
- package/frontend/dist/assets/{PromptsPage-gNHl5xn5.js → PromptsPage-DvLm5TW4.js} +2 -2
- package/frontend/dist/assets/{PromptsPage-gNHl5xn5.js.map → PromptsPage-DvLm5TW4.js.map} +1 -1
- package/frontend/dist/assets/{ResourcesPage-DvgjlTqh.js → ResourcesPage-Dnn1u2fr.js} +2 -2
- package/frontend/dist/assets/{ResourcesPage-DvgjlTqh.js.map → ResourcesPage-Dnn1u2fr.js.map} +1 -1
- package/frontend/dist/assets/ServersPage-RQCARDfE.js +37 -0
- package/frontend/dist/assets/ServersPage-RQCARDfE.js.map +1 -0
- package/frontend/dist/assets/{SettingsPage-D66oC6py.js → SettingsPage-CF40R-50.js} +2 -2
- package/frontend/dist/assets/{SettingsPage-D66oC6py.js.map → SettingsPage-CF40R-50.js.map} +1 -1
- package/frontend/dist/assets/{StatusDot-C7XhRfMO.js → StatusDot-CkF9WMhU.js} +2 -2
- package/frontend/dist/assets/{StatusDot-C7XhRfMO.js.map → StatusDot-CkF9WMhU.js.map} +1 -1
- package/frontend/dist/assets/{ToggleGroup-_MiJO3n_.js → ToggleGroup-vRqJ9DIB.js} +2 -2
- package/frontend/dist/assets/{ToggleGroup-_MiJO3n_.js.map → ToggleGroup-vRqJ9DIB.js.map} +1 -1
- package/frontend/dist/assets/{UsersPage-COmrRpdL.js → UsersPage-DBN5qCeO.js} +2 -2
- package/frontend/dist/assets/{UsersPage-COmrRpdL.js.map → UsersPage-DBN5qCeO.js.map} +1 -1
- package/frontend/dist/assets/{index-D82vzW6B.js → index-C7dQApMG.js} +3 -3
- package/frontend/dist/assets/{index-D82vzW6B.js.map → index-C7dQApMG.js.map} +1 -1
- package/frontend/dist/assets/{resourceService-D-fKBZtF.js → resourceService-BgjWoJFK.js} +2 -2
- package/frontend/dist/assets/{resourceService-D-fKBZtF.js.map → resourceService-BgjWoJFK.js.map} +1 -1
- package/frontend/dist/assets/{useServerData-DgGTUuZ8.js → useServerData-CEGj5OU1.js} +2 -2
- package/frontend/dist/assets/{useServerData-DgGTUuZ8.js.map → useServerData-CEGj5OU1.js.map} +1 -1
- package/frontend/dist/assets/useSettingsData-C2-q9Okf.js +2 -0
- package/frontend/dist/assets/{useSettingsData-B3CTLIUT.js.map → useSettingsData-C2-q9Okf.js.map} +1 -1
- package/frontend/dist/assets/variableDetection-GTKqOf1F.js +16 -0
- package/frontend/dist/assets/variableDetection-GTKqOf1F.js.map +1 -0
- package/frontend/dist/index.html +1 -1
- package/package.json +2 -1
- package/frontend/dist/assets/ServersPage-CKuVFL3O.js +0 -37
- package/frontend/dist/assets/ServersPage-CKuVFL3O.js.map +0 -1
- package/frontend/dist/assets/useSettingsData-B3CTLIUT.js +0 -2
- package/frontend/dist/assets/variableDetection-DsYuiOB_.js +0 -16
- package/frontend/dist/assets/variableDetection-DsYuiOB_.js.map +0 -1
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { createHmac, timingSafeEqual } from 'node:crypto';
|
|
2
|
+
const SIGNATURE_HEADER = 'x-internal-signature';
|
|
3
|
+
const TIMESTAMP_HEADER = 'x-internal-timestamp';
|
|
4
|
+
const REPLAY_WINDOW_MS = 5 * 60 * 1000;
|
|
5
|
+
const REDACTED_SIGNATURE_VALUE = '[REDACTED]';
|
|
6
|
+
const REDACTED_SIGNATURE_FIELDS = new Set(['apiKey', 'apiKeyId']);
|
|
7
|
+
export { SIGNATURE_HEADER, TIMESTAMP_HEADER, REPLAY_WINDOW_MS, REDACTED_SIGNATURE_VALUE };
|
|
8
|
+
function isPlainObject(value) {
|
|
9
|
+
return Object.prototype.toString.call(value) === '[object Object]';
|
|
10
|
+
}
|
|
11
|
+
function normalizeSignatureObject(value) {
|
|
12
|
+
const normalized = {};
|
|
13
|
+
for (const key of Object.keys(value).sort((left, right) => left.localeCompare(right))) {
|
|
14
|
+
if (REDACTED_SIGNATURE_FIELDS.has(key)) {
|
|
15
|
+
// Sensitive credential values must never be read during signature canonicalization.
|
|
16
|
+
normalized[key] = REDACTED_SIGNATURE_VALUE;
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
normalized[key] = normalizeSignatureBody(value[key]);
|
|
20
|
+
}
|
|
21
|
+
return normalized;
|
|
22
|
+
}
|
|
23
|
+
function normalizeSignatureBody(value) {
|
|
24
|
+
if (Buffer.isBuffer(value)) {
|
|
25
|
+
return normalizeSignatureBody(value.toString('utf8'));
|
|
26
|
+
}
|
|
27
|
+
if (typeof value === 'string') {
|
|
28
|
+
if (!value)
|
|
29
|
+
return '';
|
|
30
|
+
try {
|
|
31
|
+
return normalizeSignatureBody(JSON.parse(value));
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return value;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (Array.isArray(value)) {
|
|
38
|
+
return value.map((item) => normalizeSignatureBody(item));
|
|
39
|
+
}
|
|
40
|
+
if (isPlainObject(value)) {
|
|
41
|
+
return normalizeSignatureObject(value);
|
|
42
|
+
}
|
|
43
|
+
return value;
|
|
44
|
+
}
|
|
45
|
+
export function serializeInternalRequestBodyForSignature(body) {
|
|
46
|
+
if (body === undefined || body === null || body === '') {
|
|
47
|
+
return '';
|
|
48
|
+
}
|
|
49
|
+
return JSON.stringify(normalizeSignatureBody(body));
|
|
50
|
+
}
|
|
51
|
+
function getSecret() {
|
|
52
|
+
const secret = process.env.INTERNAL_API_SECRET;
|
|
53
|
+
if (!secret || secret.length < 32) {
|
|
54
|
+
throw new Error('INTERNAL_API_SECRET is not configured or is shorter than 32 chars');
|
|
55
|
+
}
|
|
56
|
+
return secret;
|
|
57
|
+
}
|
|
58
|
+
function payload(timestamp, method, path, body) {
|
|
59
|
+
return `${timestamp}.${method.toUpperCase()}.${path}.${body}`;
|
|
60
|
+
}
|
|
61
|
+
export function signInternalRequest(method, path, body) {
|
|
62
|
+
const timestamp = Date.now().toString();
|
|
63
|
+
const serializedBody = serializeInternalRequestBodyForSignature(body);
|
|
64
|
+
const signature = createHmac('sha256', getSecret())
|
|
65
|
+
.update(payload(timestamp, method, path, serializedBody))
|
|
66
|
+
.digest('hex');
|
|
67
|
+
return { timestamp, signature: `sha256=${signature}` };
|
|
68
|
+
}
|
|
69
|
+
export function verifyInternalSignature(opts) {
|
|
70
|
+
if (!opts.timestamp || !opts.signature) {
|
|
71
|
+
return { ok: false, reason: 'missing_signature_headers' };
|
|
72
|
+
}
|
|
73
|
+
const ts = Number(opts.timestamp);
|
|
74
|
+
if (!Number.isFinite(ts)) {
|
|
75
|
+
return { ok: false, reason: 'bad_timestamp' };
|
|
76
|
+
}
|
|
77
|
+
if (Math.abs(Date.now() - ts) > REPLAY_WINDOW_MS) {
|
|
78
|
+
return { ok: false, reason: 'stale_timestamp' };
|
|
79
|
+
}
|
|
80
|
+
let secret;
|
|
81
|
+
try {
|
|
82
|
+
secret = getSecret();
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return { ok: false, reason: 'secret_not_configured' };
|
|
86
|
+
}
|
|
87
|
+
const expected = 'sha256=' +
|
|
88
|
+
createHmac('sha256', secret)
|
|
89
|
+
.update(payload(opts.timestamp, opts.method, opts.path, serializeInternalRequestBodyForSignature(opts.body)))
|
|
90
|
+
.digest('hex');
|
|
91
|
+
const actualBuffer = Buffer.from(opts.signature);
|
|
92
|
+
const expectedBuffer = Buffer.from(expected);
|
|
93
|
+
if (actualBuffer.length !== expectedBuffer.length ||
|
|
94
|
+
!timingSafeEqual(actualBuffer, expectedBuffer)) {
|
|
95
|
+
return { ok: false, reason: 'bad_signature' };
|
|
96
|
+
}
|
|
97
|
+
return { ok: true };
|
|
98
|
+
}
|
|
99
|
+
export function verifyInternalExpressRequest(req, body) {
|
|
100
|
+
return verifyInternalSignature({
|
|
101
|
+
method: req.method,
|
|
102
|
+
path: req.path,
|
|
103
|
+
body,
|
|
104
|
+
timestamp: req.header(TIMESTAMP_HEADER),
|
|
105
|
+
signature: req.header(SIGNATURE_HEADER),
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=hostedInternalAuth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hostedInternalAuth.js","sourceRoot":"","sources":["../../src/services/hostedInternalAuth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hostedMode.js","sourceRoot":"","sources":["../../src/services/hostedMode.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,mBAAmB;IACjC,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC;AAC3C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hostedNodeIdentity.js","sourceRoot":"","sources":["../../src/services/hostedNodeIdentity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AAOzB,MAAM,UAAU,qBAAqB;IACnC,OAAO;QACL,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,SAAS;QAClD,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC,QAAQ,EAAE;KACjD,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export function stripRuntimeToolName(serverSlug, publicToolName, nameSeparator) {
|
|
2
|
+
const prefix = `${serverSlug}${nameSeparator}`;
|
|
3
|
+
return publicToolName.startsWith(prefix)
|
|
4
|
+
? publicToolName.slice(prefix.length)
|
|
5
|
+
: publicToolName;
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=hostedRuntimeCatalogNames.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hostedRuntimeCatalogNames.js","sourceRoot":"","sources":["../../src/services/hostedRuntimeCatalogNames.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,oBAAoB,CAClC,UAAkB,EAClB,cAAsB,EACtB,aAAqB;IAErB,MAAM,MAAM,GAAG,GAAG,UAAU,GAAG,aAAa,EAAE,CAAC;IAC/C,OAAO,cAAc,CAAC,UAAU,CAAC,MAAM,CAAC;QACtC,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC;QACrC,CAAC,CAAC,cAAc,CAAC;AACrB,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { getNameSeparator } from '../config/index.js';
|
|
2
|
+
import { getServersInfo } from './mcpService.js';
|
|
3
|
+
import { getHostedNodeIdentity } from './hostedNodeIdentity.js';
|
|
4
|
+
import { stripRuntimeToolName } from './hostedRuntimeCatalogNames.js';
|
|
5
|
+
export async function getHostedRuntimeCatalog() {
|
|
6
|
+
const identity = getHostedNodeIdentity();
|
|
7
|
+
const nameSeparator = getNameSeparator();
|
|
8
|
+
const servers = await getServersInfo();
|
|
9
|
+
return {
|
|
10
|
+
clusterId: identity.clusterId ?? 'default',
|
|
11
|
+
nodeId: identity.nodeId,
|
|
12
|
+
nameSeparator,
|
|
13
|
+
servers: servers.map((server) => ({
|
|
14
|
+
slug: server.name,
|
|
15
|
+
status: server.status,
|
|
16
|
+
enabled: server.enabled !== false,
|
|
17
|
+
description: server.config?.description ?? '',
|
|
18
|
+
version: server.version,
|
|
19
|
+
instructions: server.instructions,
|
|
20
|
+
error: server.error,
|
|
21
|
+
tools: server.tools.map((tool) => ({
|
|
22
|
+
name: stripRuntimeToolName(server.name, tool.name, nameSeparator),
|
|
23
|
+
publicName: tool.name,
|
|
24
|
+
description: tool.description ?? '',
|
|
25
|
+
inputSchema: tool.inputSchema ?? {},
|
|
26
|
+
enabled: tool.enabled !== false,
|
|
27
|
+
})),
|
|
28
|
+
})),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=hostedRuntimeCatalogService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hostedRuntimeCatalogService.js","sourceRoot":"","sources":["../../src/services/hostedRuntimeCatalogService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AA4BtE,MAAM,CAAC,KAAK,UAAU,uBAAuB;IAC3C,MAAM,QAAQ,GAAG,qBAAqB,EAAE,CAAC;IACzC,MAAM,aAAa,GAAG,gBAAgB,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,MAAM,cAAc,EAAE,CAAC;IAEvC,OAAO;QACL,SAAS,EAAE,QAAQ,CAAC,SAAS,IAAI,SAAS;QAC1C,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,aAAa;QACb,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YAChC,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,OAAO,EAAE,MAAM,CAAC,OAAO,KAAK,KAAK;YACjC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,IAAI,EAAE;YAC7C,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,YAAY,EAAE,MAAM,CAAC,YAAY;YACjC,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;gBACjC,IAAI,EAAE,oBAAoB,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC;gBACjE,UAAU,EAAE,IAAI,CAAC,IAAI;gBACrB,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,EAAE;gBACnC,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,EAAE;gBACnC,OAAO,EAAE,IAAI,CAAC,OAAO,KAAK,KAAK;aAChC,CAAC,CAAC;SACJ,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC"}
|
|
@@ -22,6 +22,7 @@ import { initializeAllOAuthClients } from './oauthService.js';
|
|
|
22
22
|
import { createOAuthProvider } from './mcpOAuthProvider.js';
|
|
23
23
|
import { initSmartRoutingService, getSmartRoutingTools, handleSearchToolsRequest, handleDescribeToolRequest, isSmartRoutingGroup, } from './smartRoutingService.js';
|
|
24
24
|
import { getActivityLoggingService } from './activityLoggingService.js';
|
|
25
|
+
import { assertHostedToolAllowed, filterHostedTools, reserveHostedToolCall, settleHostedToolCall, } from './hostedAuthService.js';
|
|
25
26
|
import { formatErrorForLogging, sanitizeStringForLogging, summarizeErrorForLogging, } from '../utils/serialization.js';
|
|
26
27
|
const servers = {};
|
|
27
28
|
import { setupClientKeepAlive } from './keepAliveService.js';
|
|
@@ -797,7 +798,26 @@ export const initializeClientsFromSettings = async (isInit, serverName, options)
|
|
|
797
798
|
nextServerInfos.push(serverInfo);
|
|
798
799
|
try {
|
|
799
800
|
// Create OpenAPI client instance
|
|
800
|
-
openApiClient = new OpenAPIClient(expandedConf
|
|
801
|
+
openApiClient = new OpenAPIClient(expandedConf, {
|
|
802
|
+
persistOAuth2Token: async (oauth2) => {
|
|
803
|
+
const openapiConfig = {
|
|
804
|
+
...(expandedConf.openapi || {}),
|
|
805
|
+
security: {
|
|
806
|
+
...(expandedConf.openapi?.security || { type: 'oauth2' }),
|
|
807
|
+
type: 'oauth2',
|
|
808
|
+
oauth2: { ...oauth2 },
|
|
809
|
+
},
|
|
810
|
+
};
|
|
811
|
+
expandedConf.openapi = openapiConfig;
|
|
812
|
+
serverInfo.config = {
|
|
813
|
+
...expandedConf,
|
|
814
|
+
openapi: openapiConfig,
|
|
815
|
+
};
|
|
816
|
+
await getServerDao().update(name, {
|
|
817
|
+
openapi: openapiConfig,
|
|
818
|
+
});
|
|
819
|
+
},
|
|
820
|
+
});
|
|
801
821
|
console.log(`Initializing OpenAPI server: ${name}...`);
|
|
802
822
|
// Perform async initialization
|
|
803
823
|
await openApiClient.initialize();
|
|
@@ -847,8 +867,9 @@ export const initializeClientsFromSettings = async (isInit, serverName, options)
|
|
|
847
867
|
});
|
|
848
868
|
// Get request options from server configuration, with fallbacks
|
|
849
869
|
const serverRequestOptions = expandedConf.options || {};
|
|
870
|
+
const defaultRequestTimeout = Number(process.env.DEFAULT_REQUEST_TIMEOUT) || 60000;
|
|
850
871
|
const requestOptions = {
|
|
851
|
-
timeout: serverRequestOptions.timeout ||
|
|
872
|
+
timeout: serverRequestOptions.timeout || defaultRequestTimeout,
|
|
852
873
|
resetTimeoutOnProgress: serverRequestOptions.resetTimeoutOnProgress ?? true,
|
|
853
874
|
maxTotalTimeout: serverRequestOptions.maxTotalTimeout,
|
|
854
875
|
};
|
|
@@ -1020,11 +1041,12 @@ export const registerAllTools = async (isInit, serverName, options) => {
|
|
|
1020
1041
|
// Get all server information
|
|
1021
1042
|
export const getServersInfo = async (page, limit, user) => {
|
|
1022
1043
|
const dataService = getDataService();
|
|
1023
|
-
|
|
1024
|
-
// If pagination is used with a non-admin user, filtering is already done at DAO level
|
|
1044
|
+
const isNonAdminUser = Boolean(user && !user.isAdmin);
|
|
1025
1045
|
const isPaginated = limit !== undefined && page !== undefined;
|
|
1026
1046
|
const allServers = isPaginated
|
|
1027
|
-
? (
|
|
1047
|
+
? (isNonAdminUser
|
|
1048
|
+
? await getServerDao().findVisibleToUserPaginated(user.username, page, limit)
|
|
1049
|
+
: await getServerDao().findAllPaginated(page, limit)).data
|
|
1028
1050
|
: await getServerDao().findAll();
|
|
1029
1051
|
// Ensure that servers recently added via DAO but not yet initialized in serverInfos
|
|
1030
1052
|
// are still visible in the servers list. This avoids a race condition where
|
|
@@ -1059,15 +1081,16 @@ export const getServersInfo = async (page, limit, user) => {
|
|
|
1059
1081
|
});
|
|
1060
1082
|
}
|
|
1061
1083
|
}
|
|
1062
|
-
// Apply user filtering only when NOT using pagination
|
|
1063
|
-
//
|
|
1084
|
+
// Apply user filtering only when NOT using pagination.
|
|
1085
|
+
// Paginated non-admin requests are filtered at DAO level; paginated admin requests
|
|
1086
|
+
// should remain unfiltered as well.
|
|
1064
1087
|
const shouldApplyUserFilter = !isPaginated;
|
|
1065
1088
|
const filterServerInfos = shouldApplyUserFilter && dataService.filterData
|
|
1066
1089
|
? dataService.filterData(filteredServerInfos, user)
|
|
1067
1090
|
: filteredServerInfos;
|
|
1068
1091
|
const infos = filterServerInfos
|
|
1069
1092
|
.filter((info) => requestedServerNames.has(info.name)) // Only include requested servers
|
|
1070
|
-
.map(({ name, status, tools, prompts, resources, createTime, error, oauth }) => {
|
|
1093
|
+
.map(({ name, version, instructions, owner, visibility, status, tools, prompts, resources, createTime, error, oauth, }) => {
|
|
1071
1094
|
const serverConfig = allServers.find((server) => server.name === name);
|
|
1072
1095
|
const enabled = serverConfig ? serverConfig.enabled !== false : true;
|
|
1073
1096
|
const resolvedType = inferServerType(serverConfig);
|
|
@@ -1090,6 +1113,10 @@ export const getServersInfo = async (page, limit, user) => {
|
|
|
1090
1113
|
});
|
|
1091
1114
|
return {
|
|
1092
1115
|
name,
|
|
1116
|
+
version,
|
|
1117
|
+
instructions,
|
|
1118
|
+
owner,
|
|
1119
|
+
visibility,
|
|
1093
1120
|
status,
|
|
1094
1121
|
error,
|
|
1095
1122
|
tools: toolsWithEnabled,
|
|
@@ -1364,6 +1391,22 @@ export const handleCallToolRequest = async (request, extra) => {
|
|
|
1364
1391
|
const keyId = bearerKeyContext.keyId || extra?.keyId || undefined;
|
|
1365
1392
|
const keyName = bearerKeyContext.keyName || extra?.keyName || undefined;
|
|
1366
1393
|
const sourceIp = requestContextService.getRequestContext()?.remoteAddress || undefined;
|
|
1394
|
+
let hostedReservation = null;
|
|
1395
|
+
const reserveHostedIfNeeded = async (serverName, toolName) => {
|
|
1396
|
+
const hostedAuth = requestContextService.getHostedAuthContext();
|
|
1397
|
+
assertHostedToolAllowed(hostedAuth, serverName, toolName);
|
|
1398
|
+
hostedReservation = await reserveHostedToolCall(hostedAuth, serverName, toolName);
|
|
1399
|
+
};
|
|
1400
|
+
const settleHostedIfNeeded = async (input) => {
|
|
1401
|
+
const reservation = hostedReservation;
|
|
1402
|
+
hostedReservation = null;
|
|
1403
|
+
await settleHostedToolCall(reservation, {
|
|
1404
|
+
success: input.success,
|
|
1405
|
+
latencyMs: Date.now() - startTime,
|
|
1406
|
+
requestContent: input.requestContent,
|
|
1407
|
+
responseContent: input.responseContent,
|
|
1408
|
+
});
|
|
1409
|
+
};
|
|
1367
1410
|
try {
|
|
1368
1411
|
// Special handling for smart routing tools
|
|
1369
1412
|
if (request.params.name === 'search_tools') {
|
|
@@ -1441,7 +1484,13 @@ export const handleCallToolRequest = async (request, extra) => {
|
|
|
1441
1484
|
}
|
|
1442
1485
|
}
|
|
1443
1486
|
}
|
|
1487
|
+
await reserveHostedIfNeeded(targetServerInfo.name, cleanToolName);
|
|
1444
1488
|
const result = await openApiClient.callTool(cleanToolName, finalArgs, passthroughHeaders);
|
|
1489
|
+
await settleHostedIfNeeded({
|
|
1490
|
+
success: true,
|
|
1491
|
+
requestContent: finalArgs,
|
|
1492
|
+
responseContent: result,
|
|
1493
|
+
});
|
|
1445
1494
|
console.log('OpenAPI tool invocation result', {
|
|
1446
1495
|
serverName: targetServerInfo.name,
|
|
1447
1496
|
toolName: cleanToolName,
|
|
@@ -1487,10 +1536,16 @@ export const handleCallToolRequest = async (request, extra) => {
|
|
|
1487
1536
|
const cleanToolName = toolName.startsWith(prefix)
|
|
1488
1537
|
? toolName.substring(prefix.length)
|
|
1489
1538
|
: toolName;
|
|
1539
|
+
await reserveHostedIfNeeded(targetServerInfo.name, cleanToolName);
|
|
1490
1540
|
const result = await callToolWithReconnect(targetServerInfo, {
|
|
1491
1541
|
name: cleanToolName,
|
|
1492
1542
|
arguments: finalArgs,
|
|
1493
1543
|
}, targetServerInfo.options || {});
|
|
1544
|
+
await settleHostedIfNeeded({
|
|
1545
|
+
success: !result.isError,
|
|
1546
|
+
requestContent: finalArgs,
|
|
1547
|
+
responseContent: result,
|
|
1548
|
+
});
|
|
1494
1549
|
console.log('Tool invocation result', {
|
|
1495
1550
|
serverName: targetServerInfo.name,
|
|
1496
1551
|
toolName: cleanToolName,
|
|
@@ -1557,7 +1612,14 @@ export const handleCallToolRequest = async (request, extra) => {
|
|
|
1557
1612
|
}
|
|
1558
1613
|
}
|
|
1559
1614
|
}
|
|
1560
|
-
const
|
|
1615
|
+
const finalArgs = request.params.arguments || {};
|
|
1616
|
+
await reserveHostedIfNeeded(serverInfo.name, cleanToolName);
|
|
1617
|
+
const result = await openApiClient.callTool(cleanToolName, finalArgs, passthroughHeaders);
|
|
1618
|
+
await settleHostedIfNeeded({
|
|
1619
|
+
success: true,
|
|
1620
|
+
requestContent: finalArgs,
|
|
1621
|
+
responseContent: result,
|
|
1622
|
+
});
|
|
1561
1623
|
console.log('OpenAPI tool invocation result', {
|
|
1562
1624
|
serverName: serverInfo.name,
|
|
1563
1625
|
toolName: cleanToolName,
|
|
@@ -1596,7 +1658,13 @@ export const handleCallToolRequest = async (request, extra) => {
|
|
|
1596
1658
|
const cleanToolName = request.params.name.startsWith(prefix)
|
|
1597
1659
|
? request.params.name.substring(prefix.length)
|
|
1598
1660
|
: request.params.name;
|
|
1661
|
+
await reserveHostedIfNeeded(serverInfo.name, cleanToolName);
|
|
1599
1662
|
const result = await callToolWithReconnect(serverInfo, { ...request.params, name: cleanToolName }, serverInfo.options || {});
|
|
1663
|
+
await settleHostedIfNeeded({
|
|
1664
|
+
success: !result.isError,
|
|
1665
|
+
requestContent: request.params.arguments,
|
|
1666
|
+
responseContent: result,
|
|
1667
|
+
});
|
|
1600
1668
|
console.log('Tool call result', {
|
|
1601
1669
|
serverName: serverInfo.name,
|
|
1602
1670
|
toolName: cleanToolName,
|
|
@@ -1623,6 +1691,11 @@ export const handleCallToolRequest = async (request, extra) => {
|
|
|
1623
1691
|
console.error('Error handling CallToolRequest', summarizeErrorForLogging(error));
|
|
1624
1692
|
// Log error activity
|
|
1625
1693
|
const duration = Date.now() - startTime;
|
|
1694
|
+
await settleHostedIfNeeded({
|
|
1695
|
+
success: false,
|
|
1696
|
+
requestContent: getActivityInputFromToolRequest(request),
|
|
1697
|
+
responseContent: { error: formatErrorForLogging(error) },
|
|
1698
|
+
});
|
|
1626
1699
|
const activityToolName = getActivityToolNameFromRequest(request);
|
|
1627
1700
|
const serverInfo = (typeof extra?.server === 'string' ? getServerByName(extra.server) : undefined) ||
|
|
1628
1701
|
getServerByTool(activityToolName);
|
|
@@ -1931,7 +2004,8 @@ async function filterToolsByGroup(group, serverName, tools, serverConfig) {
|
|
|
1931
2004
|
tools = tools.filter((tool) => allowedToolNames.includes(tool.name));
|
|
1932
2005
|
}
|
|
1933
2006
|
}
|
|
1934
|
-
|
|
2007
|
+
const hostedAuth = RequestContextService.getInstance().getHostedAuthContext();
|
|
2008
|
+
return filterHostedTools(hostedAuth, serverName, tools, getNameSeparator());
|
|
1935
2009
|
}
|
|
1936
2010
|
const normalizePromptNameForGroup = (serverName, promptName) => {
|
|
1937
2011
|
const prefix = `${serverName}${getNameSeparator()}`;
|