@1mcp/agent 0.35.0-beta.4 → 0.36.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/build/admin/assets/{admin-AboutRuntimeWorkspace-CM2ZafTJ.js → admin-AboutRuntimeWorkspace-DH2QC2nJ.js} +1 -1
- package/build/admin/assets/admin-BackendLogsWorkspace-BKavXT9B.js +1 -0
- package/build/admin/assets/admin-InstructionTemplatesWorkspace-CvG4EPdZ.js +1 -0
- package/build/admin/assets/admin-OAuthServicesWorkspace-BCGj2hP4.js +1 -0
- package/build/admin/assets/admin-PresetAuthoringWorkspace-BboJVBFl.js +1 -0
- package/build/admin/assets/admin-console-D6jyI73o.css +1 -0
- package/build/admin/assets/admin-console-xbgqUjbT.js +3 -0
- package/build/admin/assets/admin-icons-CYGTDZA5.js +1 -0
- package/build/admin/assets/admin-mantine-xwbfu5Gd.js +53 -0
- package/build/admin/index.html +4 -4
- package/build/auth/sdkOAuthClientProvider.d.ts +4 -0
- package/build/auth/sdkOAuthClientProvider.d.ts.map +1 -1
- package/build/auth/sdkOAuthClientProvider.js +29 -0
- package/build/auth/sdkOAuthClientProvider.js.map +1 -1
- package/build/commands/instructions/instructions.d.ts.map +1 -1
- package/build/commands/instructions/instructions.js +56 -1
- package/build/commands/instructions/instructions.js.map +1 -1
- package/build/commands/mcp/add.js +2 -2
- package/build/commands/mcp/add.js.map +1 -1
- package/build/commands/mcp/list.js +1 -1
- package/build/commands/mcp/list.js.map +1 -1
- package/build/commands/mcp/update.js +1 -1
- package/build/commands/mcp/update.js.map +1 -1
- package/build/commands/shared/serveTargetResolver.d.ts.map +1 -1
- package/build/commands/shared/serveTargetResolver.js +17 -22
- package/build/commands/shared/serveTargetResolver.js.map +1 -1
- package/build/config/configContext.d.ts +2 -0
- package/build/config/configContext.d.ts.map +1 -1
- package/build/config/configContext.js +5 -0
- package/build/config/configContext.js.map +1 -1
- package/build/config/configLoader.d.ts +8 -0
- package/build/config/configLoader.d.ts.map +1 -1
- package/build/config/configLoader.js +35 -11
- package/build/config/configLoader.js.map +1 -1
- package/build/config/configManager.d.ts +16 -1
- package/build/config/configManager.d.ts.map +1 -1
- package/build/config/configManager.js +77 -0
- package/build/config/configManager.js.map +1 -1
- package/build/config/configWatcher.d.ts +2 -0
- package/build/config/configWatcher.d.ts.map +1 -1
- package/build/config/configWatcher.js +9 -4
- package/build/config/configWatcher.js.map +1 -1
- package/build/config/configuredServerTargets.d.ts +3 -0
- package/build/config/configuredServerTargets.d.ts.map +1 -0
- package/build/config/configuredServerTargets.js +8 -0
- package/build/config/configuredServerTargets.js.map +1 -0
- package/build/config/envProcessor.d.ts +2 -1
- package/build/config/envProcessor.d.ts.map +1 -1
- package/build/config/envProcessor.js +16 -9
- package/build/config/envProcessor.js.map +1 -1
- package/build/config/mcpConfigManager.d.ts +3 -0
- package/build/config/mcpConfigManager.d.ts.map +1 -1
- package/build/config/mcpConfigManager.js +15 -0
- package/build/config/mcpConfigManager.js.map +1 -1
- package/build/config/runtimeScopeEnv.d.ts +15 -0
- package/build/config/runtimeScopeEnv.d.ts.map +1 -0
- package/build/config/runtimeScopeEnv.js +231 -0
- package/build/config/runtimeScopeEnv.js.map +1 -0
- package/build/config/runtimeTargetFingerprint.d.ts +3 -0
- package/build/config/runtimeTargetFingerprint.d.ts.map +1 -0
- package/build/config/runtimeTargetFingerprint.js +66 -0
- package/build/config/runtimeTargetFingerprint.js.map +1 -0
- package/build/config/types.d.ts +5 -0
- package/build/config/types.d.ts.map +1 -1
- package/build/config/types.js +1 -0
- package/build/config/types.js.map +1 -1
- package/build/constants/api.d.ts +1 -0
- package/build/constants/api.d.ts.map +1 -1
- package/build/constants/api.js +1 -0
- package/build/constants/api.js.map +1 -1
- package/build/constants/mcp.d.ts +1 -1
- package/build/constants/mcp.d.ts.map +1 -1
- package/build/constants/mcp.js +1 -1
- package/build/constants/mcp.js.map +1 -1
- package/build/core/capabilities/capabilityAggregator.d.ts.map +1 -1
- package/build/core/capabilities/capabilityAggregator.js +33 -14
- package/build/core/capabilities/capabilityAggregator.js.map +1 -1
- package/build/core/capabilities/capabilityCatalog.d.ts +1 -1
- package/build/core/capabilities/capabilityCatalog.d.ts.map +1 -1
- package/build/core/capabilities/capabilityCatalog.js +19 -7
- package/build/core/capabilities/capabilityCatalog.js.map +1 -1
- package/build/core/capabilities/capabilityPagination.d.ts.map +1 -1
- package/build/core/capabilities/capabilityPagination.js +7 -4
- package/build/core/capabilities/capabilityPagination.js.map +1 -1
- package/build/core/capabilities/configuredToolSnapshot.d.ts +34 -0
- package/build/core/capabilities/configuredToolSnapshot.d.ts.map +1 -0
- package/build/core/capabilities/configuredToolSnapshot.js +137 -0
- package/build/core/capabilities/configuredToolSnapshot.js.map +1 -0
- package/build/core/capabilities/lazyLoadingOrchestrator.d.ts.map +1 -1
- package/build/core/capabilities/lazyLoadingOrchestrator.js +8 -4
- package/build/core/capabilities/lazyLoadingOrchestrator.js.map +1 -1
- package/build/core/capabilities/metaToolProvider.js +3 -3
- package/build/core/capabilities/metaToolProvider.js.map +1 -1
- package/build/core/client/clientManager.d.ts.map +1 -1
- package/build/core/client/clientManager.js +31 -19
- package/build/core/client/clientManager.js.map +1 -1
- package/build/core/client/connectionHandler.d.ts.map +1 -1
- package/build/core/client/connectionHandler.js +9 -6
- package/build/core/client/connectionHandler.js.map +1 -1
- package/build/core/client/postAuthOAuthRecovery.d.ts +6 -0
- package/build/core/client/postAuthOAuthRecovery.d.ts.map +1 -0
- package/build/core/client/postAuthOAuthRecovery.js +74 -0
- package/build/core/client/postAuthOAuthRecovery.js.map +1 -0
- package/build/core/configChangeHandler.d.ts +5 -0
- package/build/core/configChangeHandler.d.ts.map +1 -1
- package/build/core/configChangeHandler.js +58 -14
- package/build/core/configChangeHandler.js.map +1 -1
- package/build/core/instructions/effectiveServerInstructions.d.ts +17 -0
- package/build/core/instructions/effectiveServerInstructions.d.ts.map +1 -0
- package/build/core/instructions/effectiveServerInstructions.js +12 -0
- package/build/core/instructions/effectiveServerInstructions.js.map +1 -0
- package/build/core/instructions/instructionAggregator.d.ts +51 -2
- package/build/core/instructions/instructionAggregator.d.ts.map +1 -1
- package/build/core/instructions/instructionAggregator.js +191 -30
- package/build/core/instructions/instructionAggregator.js.map +1 -1
- package/build/core/instructions/instructionsDistribution.d.ts +53 -0
- package/build/core/instructions/instructionsDistribution.d.ts.map +1 -1
- package/build/core/instructions/instructionsDistribution.js +25 -0
- package/build/core/instructions/instructionsDistribution.js.map +1 -1
- package/build/core/instructions/templateTypes.d.ts +25 -3
- package/build/core/instructions/templateTypes.d.ts.map +1 -1
- package/build/core/instructions/templateTypes.js +45 -0
- package/build/core/instructions/templateTypes.js.map +1 -1
- package/build/core/loading/mcpLoadingManager.d.ts.map +1 -1
- package/build/core/loading/mcpLoadingManager.js +5 -3
- package/build/core/loading/mcpLoadingManager.js.map +1 -1
- package/build/core/protocol/requestHandlerUtils.d.ts.map +1 -1
- package/build/core/protocol/requestHandlerUtils.js +3 -3
- package/build/core/protocol/requestHandlerUtils.js.map +1 -1
- package/build/core/protocol/toolRequestHandlers.d.ts.map +1 -1
- package/build/core/protocol/toolRequestHandlers.js +18 -5
- package/build/core/protocol/toolRequestHandlers.js.map +1 -1
- package/build/core/server/backendStdioSupervisor.d.ts.map +1 -1
- package/build/core/server/backendStdioSupervisor.js +2 -1
- package/build/core/server/backendStdioSupervisor.js.map +1 -1
- package/build/core/server/clientInstanceFactory.d.ts +2 -1
- package/build/core/server/clientInstanceFactory.d.ts.map +1 -1
- package/build/core/server/clientInstanceFactory.js +9 -2
- package/build/core/server/clientInstanceFactory.js.map +1 -1
- package/build/core/server/clientInstancePool.d.ts +1 -0
- package/build/core/server/clientInstancePool.d.ts.map +1 -1
- package/build/core/server/clientInstancePool.js +92 -55
- package/build/core/server/clientInstancePool.js.map +1 -1
- package/build/core/server/clientInstancePoolTypes.d.ts +2 -0
- package/build/core/server/clientInstancePoolTypes.d.ts.map +1 -1
- package/build/core/server/disabledTools.d.ts +2 -0
- package/build/core/server/disabledTools.d.ts.map +1 -1
- package/build/core/server/disabledTools.js +7 -4
- package/build/core/server/disabledTools.js.map +1 -1
- package/build/core/server/mcpServerLifecycleManager.d.ts +0 -4
- package/build/core/server/mcpServerLifecycleManager.d.ts.map +1 -1
- package/build/core/server/mcpServerLifecycleManager.js +18 -40
- package/build/core/server/mcpServerLifecycleManager.js.map +1 -1
- package/build/core/server/serverManager.d.ts +1 -0
- package/build/core/server/serverManager.d.ts.map +1 -1
- package/build/core/server/serverManager.js +32 -0
- package/build/core/server/serverManager.js.map +1 -1
- package/build/core/server/templateIdentity.d.ts +1 -0
- package/build/core/server/templateIdentity.d.ts.map +1 -1
- package/build/core/server/templateIdentity.js +11 -1
- package/build/core/server/templateIdentity.js.map +1 -1
- package/build/core/server/templateServerManager.d.ts +13 -1
- package/build/core/server/templateServerManager.d.ts.map +1 -1
- package/build/core/server/templateServerManager.js +68 -13
- package/build/core/server/templateServerManager.js.map +1 -1
- package/build/core/server/toolDescriptionOverrides.d.ts +9 -0
- package/build/core/server/toolDescriptionOverrides.d.ts.map +1 -0
- package/build/core/server/toolDescriptionOverrides.js +44 -0
- package/build/core/server/toolDescriptionOverrides.js.map +1 -0
- package/build/core/tools/handlers/serverManagementHandler.d.ts +22 -8
- package/build/core/tools/handlers/serverManagementHandler.d.ts.map +1 -1
- package/build/core/tools/internal/adapters/helpers/configTransformers.d.ts +3 -1
- package/build/core/tools/internal/adapters/helpers/configTransformers.d.ts.map +1 -1
- package/build/core/tools/internal/schemas/discovery.d.ts +1 -1
- package/build/core/tools/internal/schemas/index.d.ts +3 -3
- package/build/core/tools/internal/schemas/management.d.ts +2 -2
- package/build/core/types/transport.d.ts +39 -6
- package/build/core/types/transport.d.ts.map +1 -1
- package/build/core/types/transport.js +61 -2
- package/build/core/types/transport.js.map +1 -1
- package/build/domains/admin/adminConfiguredServerService.d.ts +65 -4
- package/build/domains/admin/adminConfiguredServerService.d.ts.map +1 -1
- package/build/domains/admin/adminConfiguredServerService.js +292 -49
- package/build/domains/admin/adminConfiguredServerService.js.map +1 -1
- package/build/domains/admin/adminDomain.d.ts +19 -0
- package/build/domains/admin/adminDomain.d.ts.map +1 -1
- package/build/domains/admin/adminDomain.js +17 -0
- package/build/domains/admin/adminDomain.js.map +1 -1
- package/build/domains/admin/adminInstructionPreviewRuntime.d.ts +7 -0
- package/build/domains/admin/adminInstructionPreviewRuntime.d.ts.map +1 -0
- package/build/domains/admin/adminInstructionPreviewRuntime.js +154 -0
- package/build/domains/admin/adminInstructionPreviewRuntime.js.map +1 -0
- package/build/domains/admin/adminInstructionTemplateService.d.ts +169 -0
- package/build/domains/admin/adminInstructionTemplateService.d.ts.map +1 -0
- package/build/domains/admin/adminInstructionTemplateService.js +181 -0
- package/build/domains/admin/adminInstructionTemplateService.js.map +1 -0
- package/build/domains/admin/configuredToolInventory.d.ts +64 -0
- package/build/domains/admin/configuredToolInventory.d.ts.map +1 -0
- package/build/domains/admin/configuredToolInventory.js +182 -0
- package/build/domains/admin/configuredToolInventory.js.map +1 -0
- package/build/domains/admin/runtimeConfiguredToolInspectionService.d.ts +21 -0
- package/build/domains/admin/runtimeConfiguredToolInspectionService.d.ts.map +1 -0
- package/build/domains/admin/runtimeConfiguredToolInspectionService.js +255 -0
- package/build/domains/admin/runtimeConfiguredToolInspectionService.js.map +1 -0
- package/build/domains/config-change/configChange.d.ts +1 -1
- package/build/domains/config-change/configChange.d.ts.map +1 -1
- package/build/domains/config-change/configChange.js +153 -13
- package/build/domains/config-change/configChange.js.map +1 -1
- package/build/domains/config-change/types.d.ts +30 -2
- package/build/domains/config-change/types.d.ts.map +1 -1
- package/build/domains/instruction-template/instructionTemplateManager.d.ts +58 -0
- package/build/domains/instruction-template/instructionTemplateManager.d.ts.map +1 -0
- package/build/domains/instruction-template/instructionTemplateManager.js +167 -0
- package/build/domains/instruction-template/instructionTemplateManager.js.map +1 -0
- package/build/domains/runtime-targets/runtimeIdentityVerification.d.ts +1 -0
- package/build/domains/runtime-targets/runtimeIdentityVerification.d.ts.map +1 -1
- package/build/domains/runtime-targets/runtimeIdentityVerification.js +6 -5
- package/build/domains/runtime-targets/runtimeIdentityVerification.js.map +1 -1
- package/build/transport/http/routes/adminRoutes.d.ts +2 -0
- package/build/transport/http/routes/adminRoutes.d.ts.map +1 -1
- package/build/transport/http/routes/adminRoutes.js +345 -9
- package/build/transport/http/routes/adminRoutes.js.map +1 -1
- package/build/transport/http/routes/apiRoutes.d.ts.map +1 -1
- package/build/transport/http/routes/apiRoutes.js +2 -0
- package/build/transport/http/routes/apiRoutes.js.map +1 -1
- package/build/transport/http/routes/inspectRequestContext.d.ts +2 -0
- package/build/transport/http/routes/inspectRequestContext.d.ts.map +1 -1
- package/build/transport/http/routes/inspectRequestContext.js +2 -2
- package/build/transport/http/routes/inspectRequestContext.js.map +1 -1
- package/build/transport/http/routes/inspectRoutes.d.ts +9 -0
- package/build/transport/http/routes/inspectRoutes.d.ts.map +1 -1
- package/build/transport/http/routes/inspectRoutes.js +15 -10
- package/build/transport/http/routes/inspectRoutes.js.map +1 -1
- package/build/transport/http/routes/instructionsRoutes.d.ts +4 -0
- package/build/transport/http/routes/instructionsRoutes.d.ts.map +1 -0
- package/build/transport/http/routes/instructionsRoutes.js +147 -0
- package/build/transport/http/routes/instructionsRoutes.js.map +1 -0
- package/build/transport/http/routes/toolRoutes.d.ts.map +1 -1
- package/build/transport/http/routes/toolRoutes.js +5 -4
- package/build/transport/http/routes/toolRoutes.js.map +1 -1
- package/build/transport/http/server.d.ts.map +1 -1
- package/build/transport/http/server.js +16 -0
- package/build/transport/http/server.js.map +1 -1
- package/build/transport/transportFactory.d.ts.map +1 -1
- package/build/transport/transportFactory.js +34 -12
- package/build/transport/transportFactory.js.map +1 -1
- package/build/utils/validation/discoveredServer.d.ts +15 -0
- package/build/utils/validation/discoveredServer.d.ts.map +1 -0
- package/build/utils/validation/discoveredServer.js +2 -0
- package/build/utils/validation/discoveredServer.js.map +1 -0
- package/build/utils/validation/urlDetection.d.ts +4 -5
- package/build/utils/validation/urlDetection.d.ts.map +1 -1
- package/build/utils/validation/urlDetection.js +94 -25
- package/build/utils/validation/urlDetection.js.map +1 -1
- package/package.json +7 -2
- package/build/admin/assets/admin-BackendLogsWorkspace-CvJs1npx.js +0 -1
- package/build/admin/assets/admin-OAuthServicesWorkspace-BswG57Gm.js +0 -1
- package/build/admin/assets/admin-PresetAuthoringWorkspace-BIIRs_EN.js +0 -1
- package/build/admin/assets/admin-console-Brz9bnhv.css +0 -1
- package/build/admin/assets/admin-console-MT8QZmIC.js +0 -3
- package/build/admin/assets/admin-icons-D-JtMXSq.js +0 -1
- package/build/admin/assets/admin-mantine-DSFdoMaN.js +0 -53
|
@@ -1,18 +1,10 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
2
|
import { mergeGlobalAndServerConfig } from '../../config/mcpConfigMerge.js';
|
|
3
|
+
import { normalizeDisabledToolsForServer } from '../../core/server/disabledTools.js';
|
|
3
4
|
import { GLOBAL_TRANSPORT_CONFIG_KEYS, transportConfigSchema, } from '../../core/types/index.js';
|
|
4
5
|
import { fingerprintConfiguredServerConfigDocument, fingerprintConfiguredServerDefaults, fingerprintConfiguredServerSecretValue, fingerprintConfiguredServerTarget, isConfiguredServerTargetDisabled, } from '../../domains/config-change/configChange.js';
|
|
5
6
|
import { createServerInstallationWorkflow, } from '../../domains/installation/serverInstallationWorkflow.js';
|
|
6
7
|
import { z } from 'zod';
|
|
7
|
-
const ENV_PLACEHOLDER_PATTERN = /\$\{[^}]+\}|\$[A-Za-z_][A-Za-z0-9_]*/u;
|
|
8
|
-
const previewTransportConfigSchema = transportConfigSchema.extend({
|
|
9
|
-
url: z
|
|
10
|
-
.string()
|
|
11
|
-
.refine((value) => ENV_PLACEHOLDER_PATTERN.test(value) || z.string().url().safeParse(value).success, {
|
|
12
|
-
message: 'URL must be a valid URL or environment substitution reference.',
|
|
13
|
-
})
|
|
14
|
-
.optional(),
|
|
15
|
-
});
|
|
16
8
|
const configuredServerCreateSecretSchema = z
|
|
17
9
|
.object({
|
|
18
10
|
fieldPath: z.array(z.string()).min(2),
|
|
@@ -154,7 +146,7 @@ function createWorkflowValidation(workflow, config) {
|
|
|
154
146
|
});
|
|
155
147
|
}
|
|
156
148
|
if (config) {
|
|
157
|
-
const parsed =
|
|
149
|
+
const parsed = transportConfigSchema.safeParse(config);
|
|
158
150
|
if (!parsed.success) {
|
|
159
151
|
for (const issue of parsed.error.issues) {
|
|
160
152
|
errors.push({
|
|
@@ -472,56 +464,102 @@ export class AdminConfiguredServerService {
|
|
|
472
464
|
return this.options.operationService.executeReadOnly({
|
|
473
465
|
context: input.context,
|
|
474
466
|
operationName: 'listConfiguredServers',
|
|
475
|
-
run: async () =>
|
|
467
|
+
run: async () => this.readConfiguredServers(),
|
|
476
468
|
});
|
|
477
469
|
}
|
|
478
470
|
async getConfiguredServerDetail(input) {
|
|
471
|
+
const configuredState = this.readConfiguredServerState(input.targetName, input.targetSource);
|
|
472
|
+
const source = configuredState.source;
|
|
479
473
|
const context = {
|
|
480
474
|
...input.context,
|
|
481
|
-
target: { type: 'configured_server', id: input.targetName },
|
|
475
|
+
target: { type: 'configured_server', id: `${source}:${input.targetName}` },
|
|
482
476
|
};
|
|
483
477
|
return this.options.operationService.executeReadOnly({
|
|
484
478
|
context,
|
|
485
479
|
operationName: 'getConfiguredServerDetail',
|
|
486
480
|
run: async () => {
|
|
487
|
-
const { currentConfig, serverDefaults } =
|
|
488
|
-
const server = createConfiguredServerReadModel(input.targetName, mergeGlobalAndServerConfig(serverDefaults, currentConfig));
|
|
481
|
+
const { currentConfig, serverDefaults } = configuredState;
|
|
482
|
+
const server = createConfiguredServerReadModel(input.targetName, mergeGlobalAndServerConfig(serverDefaults, currentConfig), source, fingerprintConfiguredServerTarget(currentConfig), Object.hasOwn(currentConfig, 'instructionOverride') ? currentConfig.instructionOverride : undefined, Object.hasOwn(currentConfig, 'instructionOverride'));
|
|
489
483
|
return {
|
|
490
484
|
server,
|
|
491
485
|
editContract: createConfiguredServerEditContract(server, currentConfig, serverDefaults),
|
|
486
|
+
...(this.options.readToolInventory
|
|
487
|
+
? {
|
|
488
|
+
toolInventory: await this.options.readToolInventory({
|
|
489
|
+
targetName: input.targetName,
|
|
490
|
+
source,
|
|
491
|
+
config: currentConfig,
|
|
492
|
+
...(input.model ? { model: input.model } : {}),
|
|
493
|
+
}),
|
|
494
|
+
}
|
|
495
|
+
: {}),
|
|
492
496
|
};
|
|
493
497
|
},
|
|
494
498
|
});
|
|
495
499
|
}
|
|
500
|
+
async refreshConfiguredToolInventory(input) {
|
|
501
|
+
const configuredState = this.readConfiguredServerState(input.targetName, input.targetSource);
|
|
502
|
+
const context = {
|
|
503
|
+
...input.context,
|
|
504
|
+
target: { type: 'configured_server', id: `${configuredState.source}:${input.targetName}` },
|
|
505
|
+
};
|
|
506
|
+
return this.options.operationService.executeReadOnly({
|
|
507
|
+
context,
|
|
508
|
+
operationName: 'refreshConfiguredToolInventory',
|
|
509
|
+
run: async () => {
|
|
510
|
+
const refresh = this.options.refreshToolInventory;
|
|
511
|
+
if (!refresh) {
|
|
512
|
+
if (!this.options.readToolInventory) {
|
|
513
|
+
throw new Error('Configured tool inventory is unavailable');
|
|
514
|
+
}
|
|
515
|
+
return this.options.readToolInventory({
|
|
516
|
+
targetName: input.targetName,
|
|
517
|
+
source: configuredState.source,
|
|
518
|
+
config: configuredState.currentConfig,
|
|
519
|
+
...(input.model ? { model: input.model } : {}),
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
return refresh({
|
|
523
|
+
targetName: input.targetName,
|
|
524
|
+
source: configuredState.source,
|
|
525
|
+
config: configuredState.currentConfig,
|
|
526
|
+
...(input.model ? { model: input.model } : {}),
|
|
527
|
+
});
|
|
528
|
+
},
|
|
529
|
+
});
|
|
530
|
+
}
|
|
496
531
|
async previewConfiguredServerEdit(input) {
|
|
532
|
+
const configuredState = this.readConfiguredServerState(input.targetName, input.targetSource);
|
|
533
|
+
const source = configuredState.source;
|
|
497
534
|
const context = {
|
|
498
535
|
...input.context,
|
|
499
|
-
target: { type: 'configured_server', id: input.targetName },
|
|
536
|
+
target: { type: 'configured_server', id: `${source}:${input.targetName}` },
|
|
500
537
|
};
|
|
501
|
-
const { currentConfig, serverDefaults } =
|
|
538
|
+
const { currentConfig, serverDefaults } = configuredState;
|
|
502
539
|
return this.options.operationService.executeDryRun({
|
|
503
540
|
context,
|
|
504
541
|
operationName: 'previewConfiguredServerEdit',
|
|
505
|
-
run: async () => this.previewConfiguredServerEditResult(input, currentConfig, serverDefaults),
|
|
542
|
+
run: async () => this.previewConfiguredServerEditResult(input, currentConfig, serverDefaults, false, source),
|
|
506
543
|
});
|
|
507
544
|
}
|
|
508
545
|
async applyConfiguredServerEdit(input) {
|
|
546
|
+
const source = this.resolveConfiguredServerSource(input.targetName, input.targetSource);
|
|
509
547
|
const context = {
|
|
510
548
|
...input.context,
|
|
511
|
-
target: { type: 'configured_server', id: input.targetName },
|
|
549
|
+
target: { type: 'configured_server', id: `${source}:${input.targetName}` },
|
|
512
550
|
confirmationFacts: sanitizeApplyConfirmationFacts(input.context.confirmationFacts),
|
|
513
551
|
};
|
|
514
552
|
return this.options.operationService.executeMutation({
|
|
515
553
|
context,
|
|
516
554
|
operationName: 'applyConfiguredServerEdit',
|
|
517
555
|
prepare: async () => {
|
|
518
|
-
const { currentConfig, serverDefaults } = this.readConfiguredServerState(input.targetName);
|
|
519
|
-
const preview = await this.previewConfiguredServerEditResult({ ...input, connectivityCheck: 'auto' }, currentConfig, serverDefaults, true);
|
|
556
|
+
const { currentConfig, serverDefaults } = this.readConfiguredServerState(input.targetName, source);
|
|
557
|
+
const preview = await this.previewConfiguredServerEditResult({ ...input, connectivityCheck: 'auto' }, currentConfig, serverDefaults, true, source);
|
|
520
558
|
const normalizedEdit = normalizeEditDraft(input.edit);
|
|
521
|
-
const currentReadModel = createConfiguredServerReadModel(input.targetName, mergeGlobalAndServerConfig(serverDefaults, currentConfig));
|
|
559
|
+
const currentReadModel = createConfiguredServerReadModel(input.targetName, mergeGlobalAndServerConfig(serverDefaults, currentConfig), source);
|
|
522
560
|
const applicableEdit = filterApplicableSecretEdits(normalizedEdit.edit, currentReadModel.secretInputs);
|
|
523
|
-
const proposedConfig = applyEditDraft(currentConfig, applicableEdit, serverDefaults);
|
|
524
|
-
const proposedReadModel = createConfiguredServerReadModel(preview.proposedTargetName, mergeGlobalAndServerConfig(serverDefaults, proposedConfig));
|
|
561
|
+
const proposedConfig = applyEditDraft(currentConfig, applicableEdit, serverDefaults, input.targetName);
|
|
562
|
+
const proposedReadModel = createConfiguredServerReadModel(preview.proposedTargetName, mergeGlobalAndServerConfig(serverDefaults, proposedConfig), source);
|
|
525
563
|
const connectionCritical = preview.diff.some((entry) => entry.riskFlags.includes('connection_critical'));
|
|
526
564
|
const secretChange = preview.diff.some((entry) => entry.riskFlags.includes('secret'));
|
|
527
565
|
if (preview.validation.status !== 'valid') {
|
|
@@ -549,6 +587,9 @@ export class AdminConfiguredServerService {
|
|
|
549
587
|
: []),
|
|
550
588
|
...(secretChange ? [{ code: 'secretChangeConfirmed', expected: true }] : []),
|
|
551
589
|
...(connectionCritical ? [{ code: 'connectionCriticalConfirmed', expected: true }] : []),
|
|
590
|
+
...(preview.toolSelection?.requiresZeroEnabledConfirmation
|
|
591
|
+
? [{ code: 'zeroEnabledToolsConfirmed', expected: true }]
|
|
592
|
+
: []),
|
|
552
593
|
...(preview.connectivityCheck.status === 'failed'
|
|
553
594
|
? [{ code: 'connectivityFailureOverrideConfirmed', expected: true }]
|
|
554
595
|
: []),
|
|
@@ -556,6 +597,7 @@ export class AdminConfiguredServerService {
|
|
|
556
597
|
run: async () => {
|
|
557
598
|
const configChange = await this.options.configChangeService.editConfiguredServerTarget({
|
|
558
599
|
sourceName: input.targetName,
|
|
600
|
+
targetSource: source,
|
|
559
601
|
targetName: preview.proposedTargetName,
|
|
560
602
|
serverConfig: proposedConfig,
|
|
561
603
|
expectedSourceFingerprint: fingerprintConfiguredServerTarget(currentConfig),
|
|
@@ -584,17 +626,22 @@ export class AdminConfiguredServerService {
|
|
|
584
626
|
}
|
|
585
627
|
async setConfiguredServerEnabledState(input, enabled) {
|
|
586
628
|
const operationName = enabled ? 'enableConfiguredServer' : 'disableConfiguredServer';
|
|
629
|
+
const source = input.targetSource ?? 'mcpServers';
|
|
587
630
|
const context = {
|
|
588
631
|
...input.context,
|
|
589
|
-
target: { type: 'configured_server', id: input.targetName },
|
|
632
|
+
target: { type: 'configured_server', id: `${source}:${input.targetName}` },
|
|
590
633
|
};
|
|
591
634
|
if (input.dryRun) {
|
|
592
635
|
return this.options.operationService.executeDryRun({
|
|
593
636
|
context,
|
|
594
637
|
operationName,
|
|
595
638
|
run: async () => {
|
|
639
|
+
if (source !== 'mcpServers') {
|
|
640
|
+
throw new Error('Template Server definitions do not support enable or disable operations');
|
|
641
|
+
}
|
|
596
642
|
const configChange = await this.options.configChangeService.previewConfiguredServerTargetEnabledState({
|
|
597
643
|
targetName: input.targetName,
|
|
644
|
+
targetSource: source,
|
|
598
645
|
enabled,
|
|
599
646
|
backup: 'skip',
|
|
600
647
|
});
|
|
@@ -614,8 +661,12 @@ export class AdminConfiguredServerService {
|
|
|
614
661
|
operationName,
|
|
615
662
|
confirmationRequirements: input.confirmationRequirements,
|
|
616
663
|
run: async () => {
|
|
664
|
+
if (source !== 'mcpServers') {
|
|
665
|
+
throw new Error('Template Server definitions do not support enable or disable operations');
|
|
666
|
+
}
|
|
617
667
|
const configChange = await this.options.configChangeService.setConfiguredServerTargetEnabledState({
|
|
618
668
|
targetName: input.targetName,
|
|
669
|
+
targetSource: source,
|
|
619
670
|
enabled,
|
|
620
671
|
backup: 'required',
|
|
621
672
|
});
|
|
@@ -632,49 +683,84 @@ export class AdminConfiguredServerService {
|
|
|
632
683
|
readConfiguredServers() {
|
|
633
684
|
const parsed = this.options.readConfigDocument();
|
|
634
685
|
if (!parsed) {
|
|
635
|
-
return [];
|
|
686
|
+
return { servers: [], configFingerprint: fingerprintConfiguredServerConfigDocument({}) };
|
|
636
687
|
}
|
|
637
|
-
return
|
|
688
|
+
return {
|
|
689
|
+
configFingerprint: fingerprintConfiguredServerConfigDocument(parsed),
|
|
690
|
+
servers: ['mcpServers', 'mcpTemplates'].flatMap((source) => Object.entries(parsed[source] ?? {}).map(([name, serverConfig]) => createConfiguredServerReadModel(name, mergeGlobalAndServerConfig(parsed.serverDefaults, serverConfig), source, fingerprintConfiguredServerTarget(serverConfig), Object.hasOwn(serverConfig, 'instructionOverride') ? serverConfig.instructionOverride : undefined, Object.hasOwn(serverConfig, 'instructionOverride')))),
|
|
691
|
+
};
|
|
638
692
|
}
|
|
639
|
-
readConfiguredServerState(targetName) {
|
|
693
|
+
readConfiguredServerState(targetName, targetSource) {
|
|
640
694
|
const parsed = this.options.readConfigDocument();
|
|
641
|
-
const
|
|
695
|
+
const source = this.resolveConfiguredServerSource(targetName, targetSource, parsed);
|
|
696
|
+
const currentConfig = parsed?.[source]?.[targetName];
|
|
642
697
|
if (!currentConfig) {
|
|
643
698
|
throw new AdminConfiguredServerNotFoundError(targetName);
|
|
644
699
|
}
|
|
645
|
-
return { currentConfig, serverDefaults: parsed?.serverDefaults };
|
|
700
|
+
return { currentConfig, serverDefaults: parsed?.serverDefaults, source };
|
|
701
|
+
}
|
|
702
|
+
resolveConfiguredServerSource(targetName, targetSource, document = this.options.readConfigDocument()) {
|
|
703
|
+
if (targetSource)
|
|
704
|
+
return targetSource;
|
|
705
|
+
return document?.mcpTemplates?.[targetName] ? 'mcpTemplates' : 'mcpServers';
|
|
646
706
|
}
|
|
647
707
|
readConfiguredServerConfig(targetName) {
|
|
648
708
|
const parsed = this.options.readConfigDocument();
|
|
649
|
-
const currentConfig = parsed?.mcpServers?.[targetName];
|
|
709
|
+
const currentConfig = parsed?.mcpTemplates?.[targetName] ?? parsed?.mcpServers?.[targetName];
|
|
650
710
|
if (!currentConfig) {
|
|
651
711
|
throw new AdminConfiguredServerNotFoundError(targetName);
|
|
652
712
|
}
|
|
653
713
|
return currentConfig;
|
|
654
714
|
}
|
|
655
|
-
async previewConfiguredServerEditResult(input, currentConfig, serverDefaults, requireCriticalConnectivity = false) {
|
|
715
|
+
async previewConfiguredServerEditResult(input, currentConfig, serverDefaults, requireCriticalConnectivity = false, source = 'mcpServers') {
|
|
656
716
|
const normalizedEdit = normalizeEditDraft(input.edit);
|
|
657
|
-
const
|
|
717
|
+
const sourceValidation = validateEditForSource(source, normalizedEdit.edit);
|
|
718
|
+
const currentReadModel = createConfiguredServerReadModel(input.targetName, mergeGlobalAndServerConfig(serverDefaults, currentConfig), source);
|
|
658
719
|
const secretValidation = validateSecretEditCapabilities(normalizedEdit.edit, currentReadModel.secretInputs);
|
|
659
720
|
const transportApplicabilityValidation = validateTransportFieldApplicability(currentConfig, normalizedEdit.edit);
|
|
660
721
|
const overrideValidation = validateTransportOverrideClears(currentConfig, normalizedEdit.edit);
|
|
661
722
|
const applicableEdit = filterApplicableSecretEdits(normalizedEdit.edit, currentReadModel.secretInputs);
|
|
662
723
|
const proposedTargetName = applicableEdit.id?.trim() || input.targetName;
|
|
663
|
-
const proposedConfig = applyEditDraft(currentConfig, applicableEdit, serverDefaults);
|
|
664
|
-
const proposedReadModel = createConfiguredServerReadModel(proposedTargetName, mergeGlobalAndServerConfig(serverDefaults, proposedConfig));
|
|
724
|
+
const proposedConfig = applyEditDraft(currentConfig, applicableEdit, serverDefaults, input.targetName);
|
|
725
|
+
const proposedReadModel = createConfiguredServerReadModel(proposedTargetName, mergeGlobalAndServerConfig(serverDefaults, proposedConfig), source);
|
|
665
726
|
const proposedTransportType = configuredTransportType(proposedConfig);
|
|
666
727
|
const serverValidation = validatePreviewServerConfig(proposedConfig);
|
|
667
|
-
const
|
|
728
|
+
const currentToolInventory = this.options.readToolInventory
|
|
729
|
+
? await this.options.readToolInventory({
|
|
730
|
+
targetName: input.targetName,
|
|
731
|
+
source,
|
|
732
|
+
config: currentConfig,
|
|
733
|
+
...(input.model ? { model: input.model } : {}),
|
|
734
|
+
})
|
|
735
|
+
: undefined;
|
|
736
|
+
const toolEditValidation = validateConfiguredToolEdit(applicableEdit, currentToolInventory);
|
|
737
|
+
const validation = mergeValidation(mergeValidation(mergeValidation(mergeValidation(normalizedEdit.validation, secretValidation), transportApplicabilityValidation), overrideValidation), mergeValidation(mergeValidation(serverValidation, sourceValidation), toolEditValidation));
|
|
668
738
|
const diff = createPreviewDiff(currentReadModel, proposedReadModel, applicableEdit);
|
|
739
|
+
pushDiff(diff, ['disabledTools'], currentConfig.disabledTools ?? [], proposedConfig.disabledTools ?? [], [
|
|
740
|
+
'tool_visibility',
|
|
741
|
+
]);
|
|
742
|
+
pushDiff(diff, ['toolDescriptionOverrides'], currentConfig.toolDescriptionOverrides ?? {}, proposedConfig.toolDescriptionOverrides ?? {}, ['tool_metadata']);
|
|
669
743
|
appendClearedOverrideDiff(diff, currentReadModel, proposedReadModel, applicableEdit);
|
|
670
744
|
const changed = validation.status === 'valid' && diff.length > 0;
|
|
671
745
|
const endpointChangedWithPreservedSecrets = endpointAuthorityChanged(currentConfig, proposedConfig) &&
|
|
672
746
|
hasPreservedSecretInputs(currentReadModel.secretInputs.filter((input) => !proposedTransportType || transportFieldAppliesToType(input.fieldPath[0], proposedTransportType)), applicableEdit);
|
|
747
|
+
const proposedToolInventory = this.options.readToolInventory
|
|
748
|
+
? await this.options.readToolInventory({
|
|
749
|
+
targetName: proposedTargetName,
|
|
750
|
+
source,
|
|
751
|
+
config: proposedConfig,
|
|
752
|
+
...(input.model ? { model: input.model } : {}),
|
|
753
|
+
})
|
|
754
|
+
: undefined;
|
|
755
|
+
const toolSelection = currentToolInventory && proposedToolInventory
|
|
756
|
+
? createConfiguredToolSelectionPreview(currentToolInventory, proposedToolInventory)
|
|
757
|
+
: undefined;
|
|
673
758
|
return {
|
|
674
759
|
targetName: input.targetName,
|
|
675
760
|
proposedTargetName,
|
|
676
761
|
previewFingerprint: previewFingerprint({
|
|
677
762
|
targetName: input.targetName,
|
|
763
|
+
targetSource: source,
|
|
678
764
|
sourceFingerprint: fingerprintConfiguredServerTarget(currentConfig),
|
|
679
765
|
globalConfigFingerprint: fingerprintConfiguredServerDefaults(serverDefaults),
|
|
680
766
|
edit: normalizedEdit.edit,
|
|
@@ -682,10 +768,11 @@ export class AdminConfiguredServerService {
|
|
|
682
768
|
proposed: proposedReadModel,
|
|
683
769
|
diff,
|
|
684
770
|
validation,
|
|
771
|
+
toolSelection,
|
|
685
772
|
}),
|
|
686
773
|
validation,
|
|
687
774
|
diff,
|
|
688
|
-
configChange: previewConfigChange(input.targetName, changed),
|
|
775
|
+
configChange: previewConfigChange(input.targetName, changed, source),
|
|
689
776
|
connectivityCheck: await this.previewConnectivityCheck({
|
|
690
777
|
targetName: proposedTargetName,
|
|
691
778
|
serverConfig: proposedConfig,
|
|
@@ -696,6 +783,7 @@ export class AdminConfiguredServerService {
|
|
|
696
783
|
(requireCriticalConnectivity && diff.some((entry) => entry.riskFlags.includes('connection_critical'))),
|
|
697
784
|
endpointChangedWithPreservedSecrets,
|
|
698
785
|
}),
|
|
786
|
+
...(toolSelection ? { toolSelection } : {}),
|
|
699
787
|
};
|
|
700
788
|
}
|
|
701
789
|
async previewConnectivityCheck(input) {
|
|
@@ -787,6 +875,20 @@ export class AdminConfiguredServerService {
|
|
|
787
875
|
};
|
|
788
876
|
}
|
|
789
877
|
}
|
|
878
|
+
function validateEditForSource(source, edit) {
|
|
879
|
+
if (source !== 'mcpTemplates')
|
|
880
|
+
return { status: 'valid', errors: [] };
|
|
881
|
+
const supportedTemplateMetadata = new Set(['instructionOverride', 'disabledTools', 'toolDescriptionOverrides']);
|
|
882
|
+
const unsupported = Object.keys(edit).filter((key) => !supportedTemplateMetadata.has(key));
|
|
883
|
+
return {
|
|
884
|
+
status: unsupported.length === 0 ? 'valid' : 'invalid',
|
|
885
|
+
errors: unsupported.map((key) => ({
|
|
886
|
+
fieldPath: [key],
|
|
887
|
+
code: 'template_edit_field_unsupported',
|
|
888
|
+
message: 'Template Server edits may only change instruction and tool metadata.',
|
|
889
|
+
})),
|
|
890
|
+
};
|
|
891
|
+
}
|
|
790
892
|
function assertSuccessfulConfigChange(configChange) {
|
|
791
893
|
if (configChange.reload.status === 'failed') {
|
|
792
894
|
throw new Error(`Config reload observation failed: ${configChange.reload.error ?? 'unknown reload failure'}`);
|
|
@@ -831,6 +933,7 @@ function sanitizeApplyConfirmationFacts(facts) {
|
|
|
831
933
|
return undefined;
|
|
832
934
|
const allowed = ['previewConfirmed', 'targetNameConfirmed', 'secretChangeConfirmed', 'connectionCriticalConfirmed'];
|
|
833
935
|
allowed.push('connectivityFailureOverrideConfirmed');
|
|
936
|
+
allowed.push('zeroEnabledToolsConfirmed');
|
|
834
937
|
const sanitized = Object.fromEntries(allowed.filter((key) => key in facts).map((key) => [key, facts[key]]));
|
|
835
938
|
return Object.keys(sanitized).length > 0 ? sanitized : undefined;
|
|
836
939
|
}
|
|
@@ -843,7 +946,17 @@ function mutationOutcome(enabled, changed) {
|
|
|
843
946
|
function normalizeEditDraft(value) {
|
|
844
947
|
const errors = [];
|
|
845
948
|
const edit = {};
|
|
846
|
-
const supportedKeys = new Set([
|
|
949
|
+
const supportedKeys = new Set([
|
|
950
|
+
'id',
|
|
951
|
+
'enabled',
|
|
952
|
+
'tags',
|
|
953
|
+
'transport',
|
|
954
|
+
'secrets',
|
|
955
|
+
'clearTransportOverrides',
|
|
956
|
+
'instructionOverride',
|
|
957
|
+
'disabledTools',
|
|
958
|
+
'toolDescriptionOverrides',
|
|
959
|
+
]);
|
|
847
960
|
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
848
961
|
return {
|
|
849
962
|
edit,
|
|
@@ -905,6 +1018,36 @@ function normalizeEditDraft(value) {
|
|
|
905
1018
|
});
|
|
906
1019
|
}
|
|
907
1020
|
}
|
|
1021
|
+
if (record.disabledTools !== undefined) {
|
|
1022
|
+
if (Array.isArray(record.disabledTools) && record.disabledTools.every((name) => typeof name === 'string')) {
|
|
1023
|
+
edit.disabledTools = Array.from(new Set(record.disabledTools.map((name) => name.trim()).filter((name) => name.length > 0))).sort((left, right) => left.localeCompare(right));
|
|
1024
|
+
}
|
|
1025
|
+
else {
|
|
1026
|
+
errors.push({
|
|
1027
|
+
fieldPath: ['disabledTools'],
|
|
1028
|
+
code: 'invalid_disabled_tools',
|
|
1029
|
+
message: 'Disabled tools must be a list of logical tool names.',
|
|
1030
|
+
});
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
if (record.toolDescriptionOverrides !== undefined) {
|
|
1034
|
+
if (record.toolDescriptionOverrides &&
|
|
1035
|
+
typeof record.toolDescriptionOverrides === 'object' &&
|
|
1036
|
+
!Array.isArray(record.toolDescriptionOverrides) &&
|
|
1037
|
+
Object.entries(record.toolDescriptionOverrides).every(([name, description]) => name.length > 0 && name === name.trim() && typeof description === 'string')) {
|
|
1038
|
+
edit.toolDescriptionOverrides = Object.fromEntries(Object.entries(record.toolDescriptionOverrides)
|
|
1039
|
+
.map(([name, description]) => [name, description.trim()])
|
|
1040
|
+
.filter(([name, description]) => name.length > 0 && description.length > 0)
|
|
1041
|
+
.sort(([left], [right]) => left.localeCompare(right)));
|
|
1042
|
+
}
|
|
1043
|
+
else {
|
|
1044
|
+
errors.push({
|
|
1045
|
+
fieldPath: ['toolDescriptionOverrides'],
|
|
1046
|
+
code: 'invalid_tool_description_overrides',
|
|
1047
|
+
message: 'Tool description overrides must map logical tool names to descriptions.',
|
|
1048
|
+
});
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
908
1051
|
if (record.transport !== undefined) {
|
|
909
1052
|
if (record.transport && typeof record.transport === 'object' && !Array.isArray(record.transport)) {
|
|
910
1053
|
edit.transport = normalizeTransportEditDraft(record.transport, errors);
|
|
@@ -943,6 +1086,23 @@ function normalizeEditDraft(value) {
|
|
|
943
1086
|
});
|
|
944
1087
|
}
|
|
945
1088
|
}
|
|
1089
|
+
if (record.instructionOverride !== undefined) {
|
|
1090
|
+
const parsed = z
|
|
1091
|
+
.discriminatedUnion('action', [
|
|
1092
|
+
z.object({ action: z.literal('set'), value: z.string() }).strict(),
|
|
1093
|
+
z.object({ action: z.literal('remove') }).strict(),
|
|
1094
|
+
])
|
|
1095
|
+
.safeParse(record.instructionOverride);
|
|
1096
|
+
if (parsed.success)
|
|
1097
|
+
edit.instructionOverride = parsed.data;
|
|
1098
|
+
else {
|
|
1099
|
+
errors.push({
|
|
1100
|
+
fieldPath: ['instructionOverride'],
|
|
1101
|
+
code: 'invalid_instruction_override',
|
|
1102
|
+
message: 'Instruction override must set a string value or remove the configured override.',
|
|
1103
|
+
});
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
946
1106
|
return {
|
|
947
1107
|
edit,
|
|
948
1108
|
validation: { status: errors.length === 0 ? 'valid' : 'invalid', errors },
|
|
@@ -971,6 +1131,20 @@ function normalizeTransportEditDraft(record, errors) {
|
|
|
971
1131
|
}
|
|
972
1132
|
return transport;
|
|
973
1133
|
}
|
|
1134
|
+
function validateConfiguredToolEdit(edit, inventory) {
|
|
1135
|
+
if (!inventory)
|
|
1136
|
+
return { status: 'valid', errors: [] };
|
|
1137
|
+
const allowedNames = new Set(inventory.rows.map((row) => row.name));
|
|
1138
|
+
const requestedNames = new Set([...(edit.disabledTools ?? []), ...Object.keys(edit.toolDescriptionOverrides ?? {})]);
|
|
1139
|
+
const errors = Array.from(requestedNames)
|
|
1140
|
+
.filter((name) => !allowedNames.has(name))
|
|
1141
|
+
.map((name) => ({
|
|
1142
|
+
fieldPath: ['tools', name],
|
|
1143
|
+
code: 'unknown_configured_tool',
|
|
1144
|
+
message: 'Tool changes must refer to an observed tool or a retained unresolved entry.',
|
|
1145
|
+
}));
|
|
1146
|
+
return { status: errors.length === 0 ? 'valid' : 'invalid', errors };
|
|
1147
|
+
}
|
|
974
1148
|
function isSecretCapableRawTransportEdit(key, value) {
|
|
975
1149
|
if (key === 'url') {
|
|
976
1150
|
return isSecretCapableUrlEdit(value);
|
|
@@ -1267,7 +1441,7 @@ function potentialSecretInput(fieldPath) {
|
|
|
1267
1441
|
}
|
|
1268
1442
|
return undefined;
|
|
1269
1443
|
}
|
|
1270
|
-
function applyEditDraft(currentConfig, edit, serverDefaults) {
|
|
1444
|
+
function applyEditDraft(currentConfig, edit, serverDefaults, logicalServerName) {
|
|
1271
1445
|
const nextConfig = cloneServerConfig(currentConfig);
|
|
1272
1446
|
for (const key of edit.clearTransportOverrides ?? []) {
|
|
1273
1447
|
delete nextConfig[key];
|
|
@@ -1283,6 +1457,27 @@ function applyEditDraft(currentConfig, edit, serverDefaults) {
|
|
|
1283
1457
|
if (Array.isArray(edit.tags)) {
|
|
1284
1458
|
nextConfig.tags = edit.tags.filter((tag) => typeof tag === 'string');
|
|
1285
1459
|
}
|
|
1460
|
+
if (edit.instructionOverride?.action === 'set') {
|
|
1461
|
+
nextConfig.instructionOverride = edit.instructionOverride.value;
|
|
1462
|
+
}
|
|
1463
|
+
else if (edit.instructionOverride?.action === 'remove') {
|
|
1464
|
+
delete nextConfig.instructionOverride;
|
|
1465
|
+
}
|
|
1466
|
+
if (Array.isArray(edit.disabledTools)) {
|
|
1467
|
+
const disabledTools = logicalServerName
|
|
1468
|
+
? normalizeDisabledToolsForServer(logicalServerName, edit.disabledTools)
|
|
1469
|
+
: edit.disabledTools;
|
|
1470
|
+
if (disabledTools.length === 0)
|
|
1471
|
+
delete nextConfig.disabledTools;
|
|
1472
|
+
else
|
|
1473
|
+
nextConfig.disabledTools = disabledTools;
|
|
1474
|
+
}
|
|
1475
|
+
if (edit.toolDescriptionOverrides) {
|
|
1476
|
+
if (Object.keys(edit.toolDescriptionOverrides).length === 0)
|
|
1477
|
+
delete nextConfig.toolDescriptionOverrides;
|
|
1478
|
+
else
|
|
1479
|
+
nextConfig.toolDescriptionOverrides = { ...edit.toolDescriptionOverrides };
|
|
1480
|
+
}
|
|
1286
1481
|
if (edit.transport && typeof edit.transport === 'object') {
|
|
1287
1482
|
const currentType = configuredTransportType(currentConfig);
|
|
1288
1483
|
const proposedType = configuredTransportType({ ...currentConfig, ...edit.transport });
|
|
@@ -1584,7 +1779,7 @@ function validatePreviewServerConfig(serverConfig) {
|
|
|
1584
1779
|
const type = typeof serverConfig.type === 'string' ? serverConfig.type : undefined;
|
|
1585
1780
|
const url = typeof serverConfig.url === 'string' ? serverConfig.url : undefined;
|
|
1586
1781
|
const command = typeof serverConfig.command === 'string' ? serverConfig.command : undefined;
|
|
1587
|
-
const schemaResult =
|
|
1782
|
+
const schemaResult = transportConfigSchema.safeParse(serverConfig);
|
|
1588
1783
|
if (!schemaResult.success) {
|
|
1589
1784
|
for (const issue of schemaResult.error.issues) {
|
|
1590
1785
|
if ((issue.path[0] === 'type' && typeof serverConfig.type === 'string') ||
|
|
@@ -1666,12 +1861,12 @@ function isValidUrlOrEnvReference(value) {
|
|
|
1666
1861
|
return false;
|
|
1667
1862
|
}
|
|
1668
1863
|
}
|
|
1669
|
-
function previewConfigChange(targetName, changed) {
|
|
1864
|
+
function previewConfigChange(targetName, changed, source = 'mcpServers') {
|
|
1670
1865
|
return {
|
|
1671
1866
|
status: changed ? 'changed' : 'unchanged',
|
|
1672
1867
|
operation: 'set_static',
|
|
1673
1868
|
configPath: '[redacted]',
|
|
1674
|
-
target: { name: targetName, source
|
|
1869
|
+
target: { name: targetName, source },
|
|
1675
1870
|
changed,
|
|
1676
1871
|
backup: { created: false },
|
|
1677
1872
|
retentionCleanup: { attempted: false, deletedPaths: [], warnings: [] },
|
|
@@ -1684,6 +1879,7 @@ function previewFingerprint(input) {
|
|
|
1684
1879
|
.update(stableStringify({
|
|
1685
1880
|
schemaVersion: 2,
|
|
1686
1881
|
targetName: input.targetName,
|
|
1882
|
+
targetSource: input.targetSource,
|
|
1687
1883
|
sourceFingerprint: input.sourceFingerprint,
|
|
1688
1884
|
globalConfigFingerprint: input.globalConfigFingerprint,
|
|
1689
1885
|
edit: redactEditDraftForFingerprint(input.edit),
|
|
@@ -1691,9 +1887,39 @@ function previewFingerprint(input) {
|
|
|
1691
1887
|
proposed: input.proposed,
|
|
1692
1888
|
diff: input.diff,
|
|
1693
1889
|
validation: input.validation,
|
|
1890
|
+
toolSelection: input.toolSelection,
|
|
1694
1891
|
}))
|
|
1695
1892
|
.digest('hex')}`;
|
|
1696
1893
|
}
|
|
1894
|
+
function createConfiguredToolSelectionPreview(current, proposed) {
|
|
1895
|
+
const currentRows = new Map(current.rows.map((row) => [row.name, row]));
|
|
1896
|
+
const proposedRows = new Map(proposed.rows.map((row) => [row.name, row]));
|
|
1897
|
+
const changedTools = Array.from(new Set([...currentRows.keys(), ...proposedRows.keys()]))
|
|
1898
|
+
.filter((name) => {
|
|
1899
|
+
const before = currentRows.get(name);
|
|
1900
|
+
const after = proposedRows.get(name);
|
|
1901
|
+
return (before?.enabled !== after?.enabled ||
|
|
1902
|
+
before?.descriptionOverride !== after?.descriptionOverride ||
|
|
1903
|
+
before?.effectiveDescription !== after?.effectiveDescription);
|
|
1904
|
+
})
|
|
1905
|
+
.sort((left, right) => left.localeCompare(right));
|
|
1906
|
+
return {
|
|
1907
|
+
capabilityGeneration: current.generation,
|
|
1908
|
+
model: proposed.model,
|
|
1909
|
+
changedTools,
|
|
1910
|
+
counts: proposed.counts,
|
|
1911
|
+
approximateTokens: {
|
|
1912
|
+
before: current.approximateTokens.enabled,
|
|
1913
|
+
after: proposed.approximateTokens.enabled,
|
|
1914
|
+
savings: current.approximateTokens.enabled - proposed.approximateTokens.enabled,
|
|
1915
|
+
},
|
|
1916
|
+
targetEnabled: proposed.targetEnabled,
|
|
1917
|
+
effect: proposed.targetEnabled ? 'immediate' : 'deferred_until_target_enabled',
|
|
1918
|
+
requiresZeroEnabledConfirmation: changedTools.length > 0 &&
|
|
1919
|
+
current.rows.some((row) => row.observed && row.enabled) &&
|
|
1920
|
+
!proposed.rows.some((row) => row.observed && row.enabled),
|
|
1921
|
+
};
|
|
1922
|
+
}
|
|
1697
1923
|
function redactEditDraftForFingerprint(edit) {
|
|
1698
1924
|
return {
|
|
1699
1925
|
...edit,
|
|
@@ -1721,6 +1947,9 @@ function createPreviewDiff(current, proposed, edit) {
|
|
|
1721
1947
|
pushDiff(diff, ['id'], current.id, proposed.id, proposed.id === current.id ? [] : ['rename']);
|
|
1722
1948
|
pushDiff(diff, ['enabled'], current.enabled, proposed.enabled, ['connection_critical']);
|
|
1723
1949
|
pushDiff(diff, ['tags'], current.tags, proposed.tags, []);
|
|
1950
|
+
if (edit.instructionOverride) {
|
|
1951
|
+
pushDiff(diff, ['instructionOverride'], current.instructionOverride, proposed.instructionOverride, []);
|
|
1952
|
+
}
|
|
1724
1953
|
const secretEditedTopLevelKeys = new Set((edit.secrets ?? []).map((secret) => secret.fieldPath[0]));
|
|
1725
1954
|
const transportEditedKeys = new Set(Object.keys(edit.transport ?? {}));
|
|
1726
1955
|
const transportKeys = new Set([...Object.keys(current.transport), ...Object.keys(proposed.transport)]);
|
|
@@ -1857,11 +2086,15 @@ function stableStringify(value) {
|
|
|
1857
2086
|
}
|
|
1858
2087
|
return JSON.stringify(value);
|
|
1859
2088
|
}
|
|
1860
|
-
function createConfiguredServerReadModel(name, serverConfig) {
|
|
2089
|
+
function createConfiguredServerReadModel(name, serverConfig, source = 'mcpServers', revision = fingerprintConfiguredServerTarget(serverConfig), instructionOverride = serverConfig.instructionOverride, hasInstructionOverride = Object.hasOwn(serverConfig, 'instructionOverride')) {
|
|
1861
2090
|
const secretInputs = [];
|
|
1862
2091
|
const transport = {};
|
|
1863
2092
|
for (const [key, value] of Object.entries(serverConfig)) {
|
|
1864
|
-
if (key === 'disabled' ||
|
|
2093
|
+
if (key === 'disabled' ||
|
|
2094
|
+
key === 'tags' ||
|
|
2095
|
+
key === 'instructionOverride' ||
|
|
2096
|
+
key === 'disabledTools' ||
|
|
2097
|
+
key === 'toolDescriptionOverrides') {
|
|
1865
2098
|
continue;
|
|
1866
2099
|
}
|
|
1867
2100
|
if (key === 'env') {
|
|
@@ -1889,22 +2122,33 @@ function createConfiguredServerReadModel(name, serverConfig) {
|
|
|
1889
2122
|
const enabled = !isConfiguredServerTargetDisabled(serverConfig.disabled);
|
|
1890
2123
|
return {
|
|
1891
2124
|
id: name,
|
|
1892
|
-
source
|
|
2125
|
+
source,
|
|
1893
2126
|
target: {
|
|
1894
2127
|
type: 'configured_server',
|
|
1895
2128
|
id: name,
|
|
1896
|
-
source
|
|
2129
|
+
source,
|
|
1897
2130
|
},
|
|
2131
|
+
revision,
|
|
1898
2132
|
enabled,
|
|
1899
2133
|
tags: normalizeTags(serverConfig.tags),
|
|
1900
2134
|
transportSummary: createTransportSummary(serverConfig, transport),
|
|
1901
2135
|
mutationAvailability: {
|
|
1902
|
-
available:
|
|
1903
|
-
operations: ['enable', 'disable'],
|
|
2136
|
+
available: source === 'mcpServers',
|
|
2137
|
+
operations: source === 'mcpServers' ? ['enable', 'disable'] : [],
|
|
1904
2138
|
},
|
|
1905
|
-
actionState:
|
|
2139
|
+
actionState: source === 'mcpServers'
|
|
2140
|
+
? createActionState(name, enabled)
|
|
2141
|
+
: {
|
|
2142
|
+
enable: { available: false, label: `Enable ${name}`, disabledReason: 'already_enabled' },
|
|
2143
|
+
disable: { available: false, label: `Disable ${name}`, disabledReason: 'already_disabled' },
|
|
2144
|
+
},
|
|
1906
2145
|
transport,
|
|
1907
2146
|
secretInputs,
|
|
2147
|
+
instructionOverride: !hasInstructionOverride
|
|
2148
|
+
? { state: 'upstream' }
|
|
2149
|
+
: instructionOverride === ''
|
|
2150
|
+
? { state: 'suppress', value: '' }
|
|
2151
|
+
: { state: 'replace', value: instructionOverride },
|
|
1908
2152
|
};
|
|
1909
2153
|
}
|
|
1910
2154
|
const STDIO_TRANSPORT_TYPES = ['stdio'];
|
|
@@ -1919,7 +2163,6 @@ const TRANSPORT_FIELD_DEFINITIONS = [
|
|
|
1919
2163
|
{ key: 'timeout', label: 'Deprecated Timeout', control: 'number' },
|
|
1920
2164
|
{ key: 'connectionTimeout', label: 'Connection Timeout', control: 'number' },
|
|
1921
2165
|
{ key: 'requestTimeout', label: 'Request Timeout', control: 'number' },
|
|
1922
|
-
{ key: 'disabledTools', label: 'Disabled Tools', control: 'string-list', defaultValue: [] },
|
|
1923
2166
|
{ key: 'template', label: 'Template', control: 'record', defaultValue: {} },
|
|
1924
2167
|
{
|
|
1925
2168
|
key: 'url',
|