@aifabrix/builder 2.53.0 → 2.54.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/bin/aifabrix.js +2 -2
- package/lib/api/assistants.api.js +8 -5
- package/lib/api/channel-identity.api.js +41 -0
- package/lib/api/evidence-authoring.api.js +5 -1
- package/lib/api/evidence.api.js +2 -0
- package/lib/api/types/evidence.types.js +2 -0
- package/lib/api/work-search.api.js +136 -0
- package/lib/channels/add-channel.js +163 -126
- package/lib/channels/approval-guides/chatgpt.js +14 -18
- package/lib/channels/approval-guides/claude.js +29 -0
- package/lib/channels/approval-guides/index.js +88 -22
- package/lib/channels/approval-guides/mcp-client.js +27 -0
- package/lib/channels/approval-guides/microsoft-copilot.js +52 -3
- package/lib/channels/approval-guides/slack.js +10 -10
- package/lib/channels/approval-guides/teams-bot.js +8 -12
- package/lib/channels/channel-add-continuations.js +91 -0
- package/lib/channels/channel-add-ensure.js +124 -27
- package/lib/channels/channel-add-existing.js +160 -28
- package/lib/channels/channel-add-failure.js +60 -0
- package/lib/channels/channel-add-remaining.js +486 -0
- package/lib/channels/channel-add-tty.js +190 -0
- package/lib/channels/channel-add-wizard-config.js +138 -0
- package/lib/channels/channel-add-wizard.js +250 -0
- package/lib/channels/channel-artifact-generator.js +27 -13
- package/lib/channels/channel-cardinality.js +83 -0
- package/lib/channels/channel-catalog-icon.js +45 -0
- package/lib/channels/channel-cli-instructions.js +75 -0
- package/lib/channels/channel-configuration-map.js +213 -0
- package/lib/channels/channel-credential.js +11 -14
- package/lib/channels/channel-definition-project.js +101 -0
- package/lib/channels/channel-definition-registry.js +154 -0
- package/lib/channels/channel-description.js +59 -2
- package/lib/channels/channel-discovery.js +16 -2
- package/lib/channels/channel-external-system.js +86 -9
- package/lib/channels/channel-install-envelope-actions.js +88 -0
- package/lib/channels/channel-install-envelope-microsoft.js +155 -0
- package/lib/channels/channel-install-envelope.js +356 -0
- package/lib/channels/channel-install-help-md.js +172 -0
- package/lib/channels/channel-install-http-payload.js +62 -0
- package/lib/channels/channel-install-inventory.js +115 -0
- package/lib/channels/channel-install-profiles.js +90 -0
- package/lib/channels/channel-instance-collision.js +118 -0
- package/lib/channels/channel-instance-key.js +100 -0
- package/lib/channels/channel-instance-materialize.js +240 -0
- package/lib/channels/channel-integration-generator.js +16 -9
- package/lib/channels/channel-integration-template.js +101 -22
- package/lib/channels/channel-inventory-fetch.js +79 -0
- package/lib/channels/channel-oauth-preflight.js +104 -0
- package/lib/channels/channel-package-version.js +76 -0
- package/lib/channels/channel-predefined-client.js +154 -0
- package/lib/channels/channel-probe.js +7 -2
- package/lib/channels/channel-runtime-resolver.js +180 -72
- package/lib/channels/channel-status-display.js +86 -16
- package/lib/channels/channel-targets.js +106 -92
- package/lib/channels/chatgpt-callback.js +318 -0
- package/lib/channels/chatgpt-channel-add.js +229 -0
- package/lib/channels/chatgpt-preflight.js +396 -0
- package/lib/channels/chatgpt-runtime-contract.js +17 -0
- package/lib/channels/chatgpt-setup-values.js +124 -0
- package/lib/channels/claude-callback.js +67 -0
- package/lib/channels/claude-channel-add.js +254 -0
- package/lib/channels/claude-runtime-contract.js +40 -0
- package/lib/channels/claude-runtime.js +58 -0
- package/lib/channels/claude-setup-values.js +89 -0
- package/lib/channels/mcp-client/config-merge.js +148 -0
- package/lib/channels/mcp-client/ensure-client.js +231 -0
- package/lib/channels/mcp-client/paths.js +53 -0
- package/lib/channels/mcp-client/profiles.js +122 -0
- package/lib/channels/mcp-client/redirect-uris.js +99 -0
- package/lib/channels/mcp-client/runtime.js +59 -0
- package/lib/channels/mcp-client-channel-add.js +186 -0
- package/lib/channels/microsoft-copilot-channel-add.js +117 -7
- package/lib/channels/microsoft-copilot-entra-identifier-uris.js +187 -0
- package/lib/channels/microsoft-copilot-entra-sso-form.js +106 -18
- package/lib/channels/microsoft-copilot-entra-sso.js +31 -2
- package/lib/channels/microsoft-copilot-package-prior.js +107 -0
- package/lib/channels/microsoft-copilot-package.js +29 -28
- package/lib/channels/microsoft-provisioning/a365.js +80 -0
- package/lib/channels/microsoft-provisioning/auth-config.js +240 -0
- package/lib/channels/microsoft-provisioning/auth.js +179 -0
- package/lib/channels/microsoft-provisioning/cli.js +71 -0
- package/lib/channels/microsoft-provisioning/constants.js +75 -0
- package/lib/channels/microsoft-provisioning/errors.js +117 -0
- package/lib/channels/microsoft-provisioning/index.js +55 -0
- package/lib/channels/microsoft-provisioning/install-atk.js +158 -0
- package/lib/channels/microsoft-provisioning/install-teams.js +115 -0
- package/lib/channels/microsoft-provisioning/login-portal-device.js +236 -0
- package/lib/channels/microsoft-provisioning/login-portal-parse.js +71 -0
- package/lib/channels/microsoft-provisioning/login-portal-teams.js +193 -0
- package/lib/channels/microsoft-provisioning/login-portal.js +230 -0
- package/lib/channels/microsoft-provisioning/persist.js +110 -0
- package/lib/channels/microsoft-provisioning/teams-bot-args.js +119 -0
- package/lib/channels/microsoft-provisioning/teams-bot-controller.js +123 -0
- package/lib/channels/microsoft-provisioning/teams-bot-parse.js +134 -0
- package/lib/channels/microsoft-provisioning/teams-bot-persist.js +113 -0
- package/lib/channels/microsoft-provisioning/teams-bot-provision.js +234 -0
- package/lib/channels/microsoft-provisioning/teams-bot-secrets.js +45 -0
- package/lib/channels/microsoft-provisioning/teams-cli.js +82 -0
- package/lib/channels/runtime-tool-catalog.js +5 -2
- package/lib/channels/slack-channel-add-portal.js +130 -0
- package/lib/channels/slack-channel-add-tty-auth.js +95 -0
- package/lib/channels/slack-channel-add.js +258 -0
- package/lib/channels/slack-provisioning/apps.js +181 -0
- package/lib/channels/slack-provisioning/auth-store.js +110 -0
- package/lib/channels/slack-provisioning/auth-ticket.js +185 -0
- package/lib/channels/slack-provisioning/auth.js +115 -0
- package/lib/channels/slack-provisioning/callbacks.js +41 -0
- package/lib/channels/slack-provisioning/cli.js +226 -0
- package/lib/channels/slack-provisioning/constants.js +37 -0
- package/lib/channels/slack-provisioning/credentials.js +169 -0
- package/lib/channels/slack-provisioning/curl-shim.js +132 -0
- package/lib/channels/slack-provisioning/developer-install.js +118 -0
- package/lib/channels/slack-provisioning/env-file.js +120 -0
- package/lib/channels/slack-provisioning/errors.js +47 -0
- package/lib/channels/slack-provisioning/go-ca-bundle.js +137 -0
- package/lib/channels/slack-provisioning/index.js +250 -0
- package/lib/channels/slack-provisioning/install-cli.js +323 -0
- package/lib/channels/slack-provisioning/manifest.js +89 -0
- package/lib/channels/slack-provisioning/oauth-lock.js +33 -0
- package/lib/channels/slack-provisioning/offer-cli.js +113 -0
- package/lib/channels/slack-provisioning/onboard-members.js +122 -0
- package/lib/channels/slack-provisioning/onboard.js +89 -0
- package/lib/channels/slack-provisioning/persist.js +95 -0
- package/lib/channels/slack-provisioning/remaining-urls.js +158 -0
- package/lib/channels/slack-provisioning/with-curl-on-path.js +48 -0
- package/lib/channels/teams-bot-channel-add.js +94 -0
- package/lib/channels/vendor-dataplane-url.js +249 -0
- package/lib/cli/setup-certification.help.js +2 -0
- package/lib/cli/setup-external-system-help.js +2 -0
- package/lib/cli/setup-external-system.js +1 -1
- package/lib/commands/channel-add-help.js +366 -0
- package/lib/commands/channel-add-setup.js +162 -80
- package/lib/commands/channel-configure.js +118 -0
- package/lib/commands/channel.js +10 -1
- package/lib/commands/governance-upload-external.js +6 -3
- package/lib/commands/lifecycle-command-action.js +2 -5
- package/lib/commands/lifecycle-external.js +93 -21
- package/lib/commands/repair-datasource-test-payload.js +4 -2
- package/lib/commands/repair-datasource-webhooks-sync-bridge.js +23 -2
- package/lib/commands/repair-datasource.js +3 -0
- package/lib/commands/repair-external-run.js +59 -25
- package/lib/commands/repair-openapi-rest-runtime.js +127 -0
- package/lib/commands/repair-orchestration-tag-merge.js +339 -0
- package/lib/commands/repair-rbac-catalog-defaults.js +96 -0
- package/lib/commands/repair-rbac-platform-preset.js +26 -15
- package/lib/commands/repair-rbac-reader-roles.js +8 -21
- package/lib/commands/repair-rbac.js +10 -34
- package/lib/commands/repair-system-permissions.js +24 -22
- package/lib/commands/role-assistant-test-output.js +14 -0
- package/lib/commands/role-assistant.js +59 -21
- package/lib/commands/test-e2e-external.js +148 -21
- package/lib/commands/upload-credential-push-log.js +2 -1
- package/lib/commands/upload-publish-context.js +1 -1
- package/lib/commands/upload-role-assistant-shell.js +124 -0
- package/lib/commands/upload-sidecar-followups.js +6 -3
- package/lib/commands/upload.js +18 -3
- package/lib/core/secrets-docker-env.js +4 -1
- package/lib/core/secrets-env-content.js +17 -3
- package/lib/datasource/capability/capability-manifest.js +0 -3
- package/lib/datasource/capability/copy-test-payload.js +3 -0
- package/lib/external-system/deploy-helpers.js +26 -1
- package/lib/external-system/deploy.js +10 -6
- package/lib/external-system/download-helpers.js +29 -2
- package/lib/external-system/download-role-assistant.js +83 -4
- package/lib/external-system/download.js +40 -30
- package/lib/external-system/sync-deploy-manifest.js +3 -2
- package/lib/external-system/upload-identity.js +42 -0
- package/lib/generator/index.js +19 -15
- package/lib/generator/split.js +13 -2
- package/lib/lifecycle/role-assistant-governance.js +146 -0
- package/lib/lifecycle/scenario-upload.js +181 -30
- package/lib/programmatic/builder-api-cors.js +143 -0
- package/lib/programmatic/builder-api-request.js +6 -0
- package/lib/programmatic/builder-api-route-dispatch.js +56 -42
- package/lib/programmatic/builder-api-server.js +8 -1
- package/lib/programmatic/capability-registry.js +54 -0
- package/lib/programmatic/channel-install-help-resolve.js +359 -0
- package/lib/programmatic/channel-install-session.js +218 -0
- package/lib/programmatic/help-content/channel-onboarding.md +2 -0
- package/lib/programmatic/help-content/cip-overview.md +3 -1
- package/lib/programmatic/http-raw-response.js +62 -0
- package/lib/programmatic/openapi-channel-install-bindings.js +179 -0
- package/lib/programmatic/openapi-channel-install-schemas.js +286 -0
- package/lib/programmatic/openapi-component-schemas.js +18 -1
- package/lib/programmatic/openapi-description-enricher.js +3 -1
- package/lib/programmatic/openapi-descriptions.js +74 -3
- package/lib/programmatic/openapi-envelope-examples.js +117 -0
- package/lib/programmatic/openapi-operation-bindings.js +4 -1
- package/lib/programmatic/openapi-schema-descriptions-channel.js +316 -0
- package/lib/programmatic/openapi-spec.js +12 -8
- package/lib/programmatic/platform-rbac-catalog.js +36 -18
- package/lib/programmatic/route-handler-map.js +51 -1
- package/lib/programmatic/route-handlers-context.js +2 -1
- package/lib/programmatic/run-auth-permissions.js +54 -0
- package/lib/programmatic/run-channel-catalog.js +196 -0
- package/lib/programmatic/run-channel-install-artifacts.js +137 -0
- package/lib/programmatic/run-channel-install-copilot.js +353 -0
- package/lib/programmatic/run-channel-install-options.js +232 -0
- package/lib/programmatic/run-channel-install-teams-bot.js +204 -0
- package/lib/programmatic/run-channel-install.js +346 -0
- package/lib/programmatic/run-channel-package.js +87 -7
- package/lib/programmatic/workspace-context.js +2 -0
- package/lib/role-assistant/evidence-sync.js +4 -2
- package/lib/role-assistant/evidence-validation-issues.js +51 -0
- package/lib/role-assistant/knowledge-sync.js +10 -4
- package/lib/role-assistant/settings.js +49 -2
- package/lib/role-assistant/test-cases-evaluate.js +30 -2
- package/lib/role-assistant/test-cases-evidence.js +175 -0
- package/lib/role-assistant/test-cases-search.js +229 -0
- package/lib/role-assistant/test-cases.js +37 -4
- package/lib/role-assistant/test-runner-search.js +149 -0
- package/lib/role-assistant/test-runner-workhub-helpers.js +40 -2
- package/lib/role-assistant/test-runner-workhub-soft.js +9 -3
- package/lib/role-assistant/test-runner-workhub.js +29 -11
- package/lib/role-assistant/test-runner.js +16 -1
- package/lib/schema/external-datasource.schema.json +119 -16
- package/lib/schema/external-system.schema.json +159 -2
- package/lib/schema/mcp-client-profile.schema.json +103 -0
- package/lib/utils/app-path-resolve.js +4 -0
- package/lib/utils/authentication-env-template.js +44 -6
- package/lib/utils/credential-secrets-env.js +6 -1
- package/lib/utils/env-copy.js +19 -7
- package/lib/utils/external-env-template.js +20 -2
- package/lib/utils/paths.js +18 -1
- package/lib/utils/platform-shell-package.js +69 -0
- package/lib/utils/port-resolver.js +50 -1
- package/lib/utils/rewrite-name-flag.js +20 -0
- package/lib/utils/role-assistant-paths.js +13 -10
- package/lib/utils/schema-resolver.js +11 -1
- package/lib/utils/secrets-helpers.js +12 -21
- package/lib/utils/token-manager.js +10 -5
- package/lib/validation/validate.js +40 -0
- package/package.json +1 -1
- package/templates/README.md +1 -1
- package/templates/applications/builder-api/Dockerfile +1 -1
- package/templates/applications/builder-api/env.template +7 -0
- package/templates/applications/dataplane/application.yaml +6 -5
- package/templates/applications/dataplane/env.template +2 -2
- package/templates/applications/dataplane/rbac.yaml +7 -2
- package/templates/applications/keycloak/Dockerfile +30 -4
- package/templates/applications/keycloak/application.yaml +2 -2
- package/templates/applications/keycloak/cimd-lenient-parse/AbstractClientIdMetadataDocumentExecutor.java +896 -0
- package/templates/applications/keycloak/cimd-lenient-parse/SOURCE.md +19 -0
- package/templates/applications/keycloak/env.template +3 -0
- package/templates/applications/miso-controller/application.yaml +1 -2
- package/templates/applications/miso-controller/env.template +2 -0
- package/templates/channels/README.md +5 -5
- package/templates/channels/chatgpt/TROUBLESHOOTING.md +51 -0
- package/templates/channels/chatgpt/channel.json +59 -0
- package/templates/channels/chatgpt/icon.svg +1 -0
- package/templates/channels/chatgpt/install.template.md.hbs +20 -95
- package/templates/channels/chatgpt/integration/README.md +1 -1
- package/templates/channels/chatgpt/integration/application.json +2 -2
- package/templates/channels/chatgpt/integration/chatgpt-system.json +49 -4
- package/templates/channels/chatgpt/integration/env.template +2 -4
- package/templates/channels/chatgpt/integration/rbac.json +13 -0
- package/templates/channels/claude/TROUBLESHOOTING.md +41 -0
- package/templates/channels/claude/channel.json +59 -0
- package/templates/channels/claude/icon.svg +1 -0
- package/templates/channels/claude/install.template.md.hbs +21 -0
- package/templates/channels/claude/integration/README.md +14 -0
- package/templates/channels/claude/integration/application.json +15 -0
- package/templates/channels/claude/integration/claude-system.json +59 -0
- package/templates/channels/claude/integration/env.template +2 -0
- package/templates/channels/claude/integration/rbac.json +13 -0
- package/templates/channels/claude/manifest.template.json.hbs +40 -0
- package/templates/channels/mcp-client/channel.json +72 -0
- package/templates/channels/mcp-client/icon.svg +1 -0
- package/templates/channels/mcp-client/install.template.md.hbs +24 -0
- package/templates/channels/mcp-client/integration/README.md +13 -0
- package/templates/channels/mcp-client/integration/application.json +15 -0
- package/templates/channels/mcp-client/integration/env.template +2 -0
- package/templates/channels/mcp-client/integration/mcp-client-system.json +72 -0
- package/templates/channels/mcp-client/integration/rbac.json +13 -0
- package/templates/channels/mcp-client/manifest.template.json.hbs +41 -0
- package/templates/channels/mcp-client/profiles/cursor.json +26 -0
- package/templates/channels/mcp-client/profiles/github-copilot.json +29 -0
- package/templates/channels/mcp-client/profiles/vscode.json +29 -0
- package/templates/channels/microsoft-copilot/channel.json +73 -0
- package/templates/channels/microsoft-copilot/declarative-agent.template.json.hbs +8 -4
- package/templates/channels/microsoft-copilot/entra-sso-registration.template.md.hbs +65 -5
- package/templates/channels/microsoft-copilot/icon.svg +1 -0
- package/templates/channels/microsoft-copilot/install.template.md.hbs +9 -9
- package/templates/channels/microsoft-copilot/integration/README.md +1 -1
- package/templates/channels/microsoft-copilot/integration/application.json +2 -2
- package/templates/channels/microsoft-copilot/integration/env.template +3 -6
- package/templates/channels/microsoft-copilot/integration/microsoft-copilot-system.json +63 -4
- package/templates/channels/microsoft-copilot/integration/rbac.json +13 -0
- package/templates/channels/microsoft-copilot/oauth-plugin-vault-required.template.md.hbs +5 -5
- package/templates/channels/slack/channel.json +223 -0
- package/templates/channels/slack/icon.svg +1 -0
- package/templates/channels/slack/install.template.md.hbs +36 -28
- package/templates/channels/slack/integration/README.md +245 -22
- package/templates/channels/slack/integration/application.json +44 -7
- package/templates/channels/slack/integration/env.template +15 -6
- package/templates/channels/slack/integration/openapi/openapi.json +126 -0
- package/templates/channels/slack/integration/rbac.json +84 -0
- package/templates/channels/slack/integration/slack-datasource-commands.json +154 -0
- package/templates/channels/slack/integration/slack-datasource-conversations.json +28 -3
- package/templates/channels/slack/integration/slack-datasource-events.json +154 -0
- package/templates/channels/slack/integration/slack-datasource-interactive.json +154 -0
- package/templates/channels/slack/integration/slack-datasource-messages.json +40 -2
- package/templates/channels/slack/integration/slack-system.json +155 -77
- package/templates/channels/slack/manifest.template.json.hbs +5 -2
- package/templates/channels/teams-bot/channel.json +161 -0
- package/templates/channels/teams-bot/icon.svg +1 -0
- package/templates/channels/teams-bot/install.template.md.hbs +12 -13
- package/templates/channels/teams-bot/integration/README.md +5 -4
- package/templates/channels/teams-bot/integration/application.json +6 -4
- package/templates/channels/teams-bot/integration/env.template +5 -4
- package/templates/channels/teams-bot/integration/openapi/openapi.json +68 -0
- package/templates/channels/teams-bot/integration/rbac.json +21 -0
- package/templates/channels/teams-bot/integration/teams-bot-datasource-activities.json +154 -0
- package/templates/channels/teams-bot/integration/teams-bot-system.json +128 -23
- package/templates/channels/web-embed/channel.json +60 -0
- package/templates/channels/web-embed/install.template.md.hbs +1 -1
- package/templates/channels/web-embed/integration/README.md +2 -2
- package/templates/channels/web-embed/integration/application.json +2 -2
- package/templates/channels/web-embed/integration/env.template +1 -1
- package/templates/channels/web-embed/integration/rbac.json +13 -0
- package/templates/channels/web-embed/integration/web-embed-system.json +50 -4
|
@@ -26,7 +26,7 @@ function extractTenantIdFromIssuer(issuer) {
|
|
|
26
26
|
return null;
|
|
27
27
|
}
|
|
28
28
|
const match = issuer.match(
|
|
29
|
-
/login\.
|
|
29
|
+
/login\.microsoft(?:online)?\.com\/([0-9a-fA-F-]{36})(?:\/|$)/i
|
|
30
30
|
);
|
|
31
31
|
return match ? match[1] : null;
|
|
32
32
|
}
|
|
@@ -136,8 +136,37 @@ function trimNonEmptyString(value) {
|
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
/**
|
|
139
|
-
* Teams Entra SSO
|
|
140
|
-
*
|
|
139
|
+
* Teams Entra SSO auth-config id from vault reference_id.
|
|
140
|
+
* Accepts a bare GUID or opaque base64 `tenantId##authConfigId` (Developer Portal).
|
|
141
|
+
* @param {string|null|undefined} referenceId
|
|
142
|
+
* @returns {string|null}
|
|
143
|
+
*/
|
|
144
|
+
function parseOauthPluginVaultAuthConfigId(referenceId) {
|
|
145
|
+
const raw = trimNonEmptyString(referenceId);
|
|
146
|
+
if (!raw) {
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
if (TEAMS_AUTH_CONFIG_GUID.test(raw)) {
|
|
150
|
+
return raw;
|
|
151
|
+
}
|
|
152
|
+
try {
|
|
153
|
+
const decoded = Buffer.from(raw, 'base64').toString('utf8');
|
|
154
|
+
const parts = decoded.split('##');
|
|
155
|
+
if (
|
|
156
|
+
parts.length === 2 &&
|
|
157
|
+
TEAMS_AUTH_CONFIG_GUID.test(parts[0]) &&
|
|
158
|
+
TEAMS_AUTH_CONFIG_GUID.test(parts[1])
|
|
159
|
+
) {
|
|
160
|
+
return parts[1];
|
|
161
|
+
}
|
|
162
|
+
} catch {
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Teams Application ID URI: api://auth-{authConfigId}/{clientId}.
|
|
141
170
|
* @param {string|null} authConfigId
|
|
142
171
|
* @param {string|null} clientId
|
|
143
172
|
* @returns {string|null}
|
|
@@ -151,6 +180,24 @@ function buildTeamsWebApplicationInfoResource(authConfigId, clientId) {
|
|
|
151
180
|
return `api://auth-${configId}/${appId}`;
|
|
152
181
|
}
|
|
153
182
|
|
|
183
|
+
/**
|
|
184
|
+
* Prefer Trust Application ID URI (audience), else api://{clientId}.
|
|
185
|
+
* @param {string|null} clientId
|
|
186
|
+
* @param {string|null|undefined} audience
|
|
187
|
+
* @returns {string|null}
|
|
188
|
+
*/
|
|
189
|
+
function buildApplicationIdUriResource(clientId, audience) {
|
|
190
|
+
const appId = trimNonEmptyString(clientId);
|
|
191
|
+
const aud = trimNonEmptyString(audience).replace(/\/$/, '');
|
|
192
|
+
if (aud.startsWith('api://')) {
|
|
193
|
+
return aud.endsWith('/invoke') ? aud.slice(0, -'/invoke'.length) : aud;
|
|
194
|
+
}
|
|
195
|
+
if (appId) {
|
|
196
|
+
return `api://${appId}`;
|
|
197
|
+
}
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
|
|
154
201
|
/**
|
|
155
202
|
* @param {Object} resolved
|
|
156
203
|
* @returns {string|null}
|
|
@@ -163,30 +210,69 @@ function resolveWebApplicationClientId(resolved) {
|
|
|
163
210
|
);
|
|
164
211
|
}
|
|
165
212
|
|
|
213
|
+
/**
|
|
214
|
+
* @param {Object} resolved
|
|
215
|
+
* @param {Object} params
|
|
216
|
+
* @returns {string}
|
|
217
|
+
*/
|
|
218
|
+
function resolveWebApplicationAudience(resolved, params) {
|
|
219
|
+
return (
|
|
220
|
+
trimNonEmptyString(params.entraProvider && params.entraProvider.audience) ||
|
|
221
|
+
trimNonEmptyString(resolved.discoveryAuthentication && resolved.discoveryAuthentication.audience)
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* @param {Object} sources
|
|
227
|
+
* @returns {{ id: string|null, resource: string|null }}
|
|
228
|
+
*/
|
|
229
|
+
function pickWebApplicationInfo(sources) {
|
|
230
|
+
const {
|
|
231
|
+
explicitId,
|
|
232
|
+
explicitResource,
|
|
233
|
+
priorId,
|
|
234
|
+
priorResource,
|
|
235
|
+
clientId,
|
|
236
|
+
fromApp,
|
|
237
|
+
fromTeamsAuthConfig
|
|
238
|
+
} = sources;
|
|
239
|
+
const derivedId = fromApp || fromTeamsAuthConfig ? clientId : null;
|
|
240
|
+
return {
|
|
241
|
+
id: explicitId || derivedId || priorId || null,
|
|
242
|
+
resource: explicitResource || fromApp || priorResource || fromTeamsAuthConfig || null
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
|
|
166
246
|
/**
|
|
167
247
|
* Preserve / derive Teams webApplicationInfo for Entra SSO packages.
|
|
168
|
-
* Prefer explicit
|
|
169
|
-
*
|
|
248
|
+
* Prefer explicit → Trust audience / api://{clientId} (matches Azure identifierUris)
|
|
249
|
+
* → prior package → Teams api://auth-{configId}/{clientId} only as last resort.
|
|
170
250
|
* @param {Object} resolved
|
|
171
251
|
* @param {Object} params
|
|
172
252
|
* @returns {void}
|
|
173
253
|
*/
|
|
174
254
|
function applyWebApplicationInfoFields(resolved, params = {}) {
|
|
175
255
|
const prior = params.priorWebApplicationInfo || null;
|
|
176
|
-
const explicitId = trimNonEmptyString(params.webApplicationInfoId);
|
|
177
|
-
const explicitResource = trimNonEmptyString(params.webApplicationInfoResource);
|
|
178
|
-
const priorId = trimNonEmptyString(prior && prior.id);
|
|
179
|
-
const priorResource = trimNonEmptyString(prior && prior.resource);
|
|
180
256
|
const clientId = resolveWebApplicationClientId(resolved);
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
);
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
257
|
+
const audience = resolveWebApplicationAudience(resolved, params);
|
|
258
|
+
const authConfigId = parseOauthPluginVaultAuthConfigId(resolved.oauthPluginVaultReferenceId);
|
|
259
|
+
const fromTeamsAuthConfig = buildTeamsWebApplicationInfoResource(authConfigId, clientId);
|
|
260
|
+
const fromApp = buildApplicationIdUriResource(clientId, audience);
|
|
261
|
+
resolved.entraSsoAuthConfigId = authConfigId;
|
|
262
|
+
resolved.teamsApplicationIdUri = fromTeamsAuthConfig;
|
|
263
|
+
resolved.azureApplicationIdUri = fromApp || (clientId ? `api://${clientId}` : null);
|
|
264
|
+
const picked = pickWebApplicationInfo({
|
|
265
|
+
explicitId: trimNonEmptyString(params.webApplicationInfoId),
|
|
266
|
+
explicitResource: trimNonEmptyString(params.webApplicationInfoResource),
|
|
267
|
+
priorId: trimNonEmptyString(prior && prior.id),
|
|
268
|
+
priorResource: trimNonEmptyString(prior && prior.resource),
|
|
269
|
+
clientId,
|
|
270
|
+
fromApp,
|
|
271
|
+
fromTeamsAuthConfig
|
|
272
|
+
});
|
|
273
|
+
if (picked.id && picked.resource) {
|
|
274
|
+
resolved.webApplicationInfoId = picked.id;
|
|
275
|
+
resolved.webApplicationInfoResource = picked.resource;
|
|
190
276
|
}
|
|
191
277
|
}
|
|
192
278
|
|
|
@@ -245,7 +331,9 @@ module.exports = {
|
|
|
245
331
|
resolveEntraTenantId,
|
|
246
332
|
applyCopilotEntraSsoFormFields,
|
|
247
333
|
applyWebApplicationInfoFields,
|
|
334
|
+
parseOauthPluginVaultAuthConfigId,
|
|
248
335
|
buildTeamsWebApplicationInfoResource,
|
|
336
|
+
buildApplicationIdUriResource,
|
|
249
337
|
renderCopilotChannelTemplate,
|
|
250
338
|
formatOauthPluginVaultReferenceRequiredError
|
|
251
339
|
};
|
|
@@ -25,7 +25,10 @@ function isPresent(value) {
|
|
|
25
25
|
* @returns {boolean}
|
|
26
26
|
*/
|
|
27
27
|
function skipsChannelOauthCredential(channelTarget) {
|
|
28
|
-
return channelTarget === 'microsoft-copilot'
|
|
28
|
+
return channelTarget === 'microsoft-copilot'
|
|
29
|
+
|| channelTarget === 'mcp-client'
|
|
30
|
+
|| channelTarget === 'claude'
|
|
31
|
+
|| channelTarget === 'chatgpt';
|
|
29
32
|
}
|
|
30
33
|
|
|
31
34
|
/**
|
|
@@ -109,6 +112,21 @@ function mapCopilotPackageAuthentication(auth) {
|
|
|
109
112
|
* @param {Object|null} [params.entraProvider]
|
|
110
113
|
* @returns {string[]}
|
|
111
114
|
*/
|
|
115
|
+
/**
|
|
116
|
+
* @param {string|null|undefined} audience
|
|
117
|
+
* @returns {string[]}
|
|
118
|
+
*/
|
|
119
|
+
function scopesFromAudience(audience) {
|
|
120
|
+
const aud = typeof audience === 'string' ? audience.trim().replace(/\/$/, '') : '';
|
|
121
|
+
if (!aud.startsWith('api://')) {
|
|
122
|
+
return [];
|
|
123
|
+
}
|
|
124
|
+
if (aud.endsWith('/invoke')) {
|
|
125
|
+
return [aud];
|
|
126
|
+
}
|
|
127
|
+
return [`${aud}/invoke`];
|
|
128
|
+
}
|
|
129
|
+
|
|
112
130
|
function resolveCopilotEntraScopes(params) {
|
|
113
131
|
const explicit = normalizeScopeList(params.explicitScopes);
|
|
114
132
|
if (explicit.length > 0 && !isOpenIdOnlyOrEmptyScopes(explicit)) {
|
|
@@ -118,6 +136,17 @@ function resolveCopilotEntraScopes(params) {
|
|
|
118
136
|
if (fromProvider.length > 0 && !isOpenIdOnlyOrEmptyScopes(fromProvider)) {
|
|
119
137
|
return fromProvider;
|
|
120
138
|
}
|
|
139
|
+
const fromProviderAudience = scopesFromAudience(params.entraProvider?.audience);
|
|
140
|
+
if (fromProviderAudience.length > 0) {
|
|
141
|
+
return fromProviderAudience;
|
|
142
|
+
}
|
|
143
|
+
const enterpriseAppId =
|
|
144
|
+
typeof params.entraIdentityProvider?.enterpriseAppId === 'string'
|
|
145
|
+
? params.entraIdentityProvider.enterpriseAppId.trim()
|
|
146
|
+
: '';
|
|
147
|
+
if (enterpriseAppId) {
|
|
148
|
+
return scopesFromAudience(`api://${enterpriseAppId}`);
|
|
149
|
+
}
|
|
121
150
|
const auth = params.packageContext?.authentication || null;
|
|
122
151
|
const fromAuth = normalizeScopeList(auth?.scopes || auth?.allowedScopes);
|
|
123
152
|
if (fromAuth.length > 0 && !isOpenIdOnlyOrEmptyScopes(fromAuth)) {
|
|
@@ -125,7 +154,7 @@ function resolveCopilotEntraScopes(params) {
|
|
|
125
154
|
}
|
|
126
155
|
const resource = typeof auth?.resource === 'string' ? auth.resource.trim() : '';
|
|
127
156
|
if (resource.startsWith('api://')) {
|
|
128
|
-
return
|
|
157
|
+
return scopesFromAudience(resource);
|
|
129
158
|
}
|
|
130
159
|
return [];
|
|
131
160
|
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read prior Microsoft Copilot package identity from dist/source (regenerate).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Preserve Entra webApplicationInfo / vault ref; bump Teams version
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const fs = require('../internal/fs-real-sync');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
const {
|
|
14
|
+
parseSemverTriple,
|
|
15
|
+
bumpMinorPackageVersion,
|
|
16
|
+
resolvePackageVersionForWrite
|
|
17
|
+
} = require('./channel-package-version');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {string} sourceDir
|
|
21
|
+
* @returns {string|null}
|
|
22
|
+
*/
|
|
23
|
+
function readPriorPackageVersion(sourceDir) {
|
|
24
|
+
const manifestPath = path.join(sourceDir, 'manifest.json');
|
|
25
|
+
if (!fs.existsSync(manifestPath)) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
try {
|
|
29
|
+
const parsed = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
|
30
|
+
const version = parsed && parsed.version;
|
|
31
|
+
return parseSemverTriple(version) ? String(version).trim() : null;
|
|
32
|
+
} catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Read prior webApplicationInfo from an existing source manifest (preserve on regenerate).
|
|
39
|
+
* @param {string} sourceDir
|
|
40
|
+
* @returns {{ id: string, resource: string }|null}
|
|
41
|
+
*/
|
|
42
|
+
function readPriorWebApplicationInfo(sourceDir) {
|
|
43
|
+
const manifestPath = path.join(sourceDir, 'manifest.json');
|
|
44
|
+
if (!fs.existsSync(manifestPath)) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
const parsed = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
|
49
|
+
const info = parsed && parsed.webApplicationInfo;
|
|
50
|
+
if (
|
|
51
|
+
info &&
|
|
52
|
+
typeof info.id === 'string' &&
|
|
53
|
+
info.id.trim() &&
|
|
54
|
+
typeof info.resource === 'string' &&
|
|
55
|
+
info.resource.trim()
|
|
56
|
+
) {
|
|
57
|
+
return { id: info.id.trim(), resource: info.resource.trim() };
|
|
58
|
+
}
|
|
59
|
+
} catch {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Reuse Teams Entra SSO OAuthPluginVault reference_id from a prior ai-plugin.json.
|
|
67
|
+
* @param {string} sourceDir
|
|
68
|
+
* @returns {string|null}
|
|
69
|
+
*/
|
|
70
|
+
function readPriorOauthPluginVaultReferenceId(sourceDir) {
|
|
71
|
+
const pluginPath = path.join(sourceDir, 'ai-plugin.json');
|
|
72
|
+
if (!fs.existsSync(pluginPath)) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
try {
|
|
76
|
+
const parsed = JSON.parse(fs.readFileSync(pluginPath, 'utf8'));
|
|
77
|
+
const runtimes = Array.isArray(parsed?.runtimes) ? parsed.runtimes : [];
|
|
78
|
+
for (const runtime of runtimes) {
|
|
79
|
+
const ref = runtime?.auth?.reference_id;
|
|
80
|
+
if (typeof ref === 'string' && ref.trim()) {
|
|
81
|
+
return ref.trim();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
} catch {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* @param {string} projectRoot
|
|
92
|
+
* @param {string} [channelTarget]
|
|
93
|
+
* @returns {string}
|
|
94
|
+
*/
|
|
95
|
+
function getCopilotPackageSourceDir(projectRoot, channelTarget = 'microsoft-copilot') {
|
|
96
|
+
return path.join(projectRoot, 'dist', 'channels', channelTarget, 'source');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
module.exports = {
|
|
100
|
+
parseSemverTriple,
|
|
101
|
+
bumpMinorPackageVersion,
|
|
102
|
+
readPriorPackageVersion,
|
|
103
|
+
resolvePackageVersionForWrite,
|
|
104
|
+
readPriorWebApplicationInfo,
|
|
105
|
+
readPriorOauthPluginVaultReferenceId,
|
|
106
|
+
getCopilotPackageSourceDir
|
|
107
|
+
};
|
|
@@ -22,6 +22,12 @@ const {
|
|
|
22
22
|
renderCopilotChannelTemplate,
|
|
23
23
|
applyWebApplicationInfoFields
|
|
24
24
|
} = require('./microsoft-copilot-entra-sso-form');
|
|
25
|
+
const {
|
|
26
|
+
readPriorWebApplicationInfo,
|
|
27
|
+
readPriorPackageVersion,
|
|
28
|
+
readPriorOauthPluginVaultReferenceId,
|
|
29
|
+
resolvePackageVersionForWrite
|
|
30
|
+
} = require('./microsoft-copilot-package-prior');
|
|
25
31
|
|
|
26
32
|
/**
|
|
27
33
|
* @param {string} outputPath
|
|
@@ -330,43 +336,36 @@ function buildCopilotPackagePayload(params, runtimeValues, paths, icons) {
|
|
|
330
336
|
}
|
|
331
337
|
|
|
332
338
|
/**
|
|
333
|
-
*
|
|
334
|
-
* @param {
|
|
335
|
-
* @
|
|
339
|
+
* Apply prior vault / Teams version / webApplicationInfo before render.
|
|
340
|
+
* @param {Object} runtimeValues
|
|
341
|
+
* @param {Object} paths
|
|
342
|
+
* @returns {void}
|
|
336
343
|
*/
|
|
337
|
-
function
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
try {
|
|
343
|
-
const parsed = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
|
344
|
-
const info = parsed && parsed.webApplicationInfo;
|
|
345
|
-
if (
|
|
346
|
-
info &&
|
|
347
|
-
typeof info.id === 'string' &&
|
|
348
|
-
info.id.trim() &&
|
|
349
|
-
typeof info.resource === 'string' &&
|
|
350
|
-
info.resource.trim()
|
|
351
|
-
) {
|
|
352
|
-
return { id: info.id.trim(), resource: info.resource.trim() };
|
|
344
|
+
function applyPriorPackageFields(runtimeValues, paths) {
|
|
345
|
+
if (!runtimeValues.oauthPluginVaultReferenceId) {
|
|
346
|
+
const priorVault = readPriorOauthPluginVaultReferenceId(paths.sourceDir);
|
|
347
|
+
if (priorVault) {
|
|
348
|
+
runtimeValues.oauthPluginVaultReferenceId = priorVault;
|
|
353
349
|
}
|
|
354
|
-
} catch {
|
|
355
|
-
return null;
|
|
356
350
|
}
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
assertCopilotPackageOauthPluginVaultReference(runtimeValues);
|
|
363
|
-
const paths = buildCopilotOutputPaths(params.outputPath, runtimeValues);
|
|
351
|
+
const priorVersion = readPriorPackageVersion(paths.sourceDir);
|
|
352
|
+
const explicitVersion =
|
|
353
|
+
runtimeValues.packageVersionExplicit === true ? runtimeValues.packageVersion : null;
|
|
354
|
+
runtimeValues.packageVersion = resolvePackageVersionForWrite(explicitVersion, priorVersion);
|
|
355
|
+
runtimeValues.priorPackageVersion = priorVersion;
|
|
364
356
|
const prior = readPriorWebApplicationInfo(paths.sourceDir);
|
|
365
357
|
applyWebApplicationInfoFields(runtimeValues, {
|
|
366
358
|
webApplicationInfoId: runtimeValues.webApplicationInfoId,
|
|
367
359
|
webApplicationInfoResource: runtimeValues.webApplicationInfoResource,
|
|
368
360
|
priorWebApplicationInfo: prior
|
|
369
361
|
});
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
function generateMicrosoftCopilotPackage(params) {
|
|
365
|
+
const runtimeValues = applyMicrosoftCopilotDisplayLimits({ ...(params.runtimeValues || {}) });
|
|
366
|
+
const paths = buildCopilotOutputPaths(params.outputPath, runtimeValues);
|
|
367
|
+
applyPriorPackageFields(runtimeValues, paths);
|
|
368
|
+
assertCopilotPackageOauthPluginVaultReference(runtimeValues);
|
|
370
369
|
const icons = resolvePackageIcons(runtimeValues);
|
|
371
370
|
const payload = buildCopilotPackagePayload(params, runtimeValues, paths, icons);
|
|
372
371
|
if (!params.dryRun) {
|
|
@@ -387,6 +386,8 @@ function generateMicrosoftCopilotPackage(params) {
|
|
|
387
386
|
installPath: paths.installPath,
|
|
388
387
|
zipPath: paths.zipPath,
|
|
389
388
|
links: payload.summary.links,
|
|
389
|
+
packageVersion: runtimeValues.packageVersion,
|
|
390
|
+
priorPackageVersion: runtimeValues.priorPackageVersion || null,
|
|
390
391
|
installReady: payload.summary.installReady === true,
|
|
391
392
|
blocker: payload.summary.blocker || null,
|
|
392
393
|
packageReady: payload.summary.packageReady === true,
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent 365 BYO MCP register wrap (preview). Not used by microsoft-copilot DA packaging.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Checkpoint + optional a365 CLI; remaining admin/UI stays honest
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const { AGENT365_CHECKPOINT } = require('./constants');
|
|
10
|
+
const {
|
|
11
|
+
microsoftProvisioningError,
|
|
12
|
+
wrongEnvironmentRegistrationError
|
|
13
|
+
} = require('./errors');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @returns {{ preview: boolean, declarativeAgentsSupported: boolean, republishSupported: boolean, copilotStudioApiAttach: boolean, adminApprovalRequired: boolean, byoMcpRegisterCli: boolean, reason: string }}
|
|
17
|
+
*/
|
|
18
|
+
function evaluateAgent365Checkpoint() {
|
|
19
|
+
return { ...AGENT365_CHECKPOINT };
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Declarative Agent packaging must not consume Agent 365 BYO registrations.
|
|
24
|
+
* @returns {boolean}
|
|
25
|
+
*/
|
|
26
|
+
function agent365AppliesToDeclarativeAgents() {
|
|
27
|
+
return evaluateAgent365Checkpoint().declarativeAgentsSupported === true;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @param {Object} existing
|
|
32
|
+
* @param {Object} requested
|
|
33
|
+
* @returns {void}
|
|
34
|
+
*/
|
|
35
|
+
function assertMatchingRegistration(existing, requested) {
|
|
36
|
+
if (!existing || !existing.registrationId) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (existing.environment && existing.environment !== requested.environment) {
|
|
40
|
+
throw wrongEnvironmentRegistrationError(requested.environment, existing.environment);
|
|
41
|
+
}
|
|
42
|
+
if (existing.mcpServerUrl && existing.mcpServerUrl !== requested.mcpServerUrl) {
|
|
43
|
+
throw microsoftProvisioningError(
|
|
44
|
+
'Existing Agent 365 registration points at a different MCP URL. Republish is not supported.',
|
|
45
|
+
'REPUBLISH_UNSUPPORTED'
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @param {Object} params
|
|
52
|
+
* @param {Object} [deps]
|
|
53
|
+
* @returns {Promise<{ skipped: boolean, reason?: string, registrationId?: string }>}
|
|
54
|
+
*/
|
|
55
|
+
async function registerExternalMcpServer(params, deps = {}) {
|
|
56
|
+
const checkpoint = evaluateAgent365Checkpoint();
|
|
57
|
+
if (params && params.forDeclarativeAgent === true && !checkpoint.declarativeAgentsSupported) {
|
|
58
|
+
return { skipped: true, reason: checkpoint.reason };
|
|
59
|
+
}
|
|
60
|
+
const existing = params && params.existingRegistration;
|
|
61
|
+
if (existing && existing.registrationId) {
|
|
62
|
+
assertMatchingRegistration(existing, params);
|
|
63
|
+
return { skipped: false, registrationId: existing.registrationId, reused: true };
|
|
64
|
+
}
|
|
65
|
+
if (typeof deps.runA365 !== 'function') {
|
|
66
|
+
return { skipped: true, reason: checkpoint.reason };
|
|
67
|
+
}
|
|
68
|
+
const registrationId = await deps.runA365(params);
|
|
69
|
+
if (!registrationId) {
|
|
70
|
+
throw microsoftProvisioningError('Agent 365 register did not return a registration id.', 'A365');
|
|
71
|
+
}
|
|
72
|
+
return { skipped: false, registrationId, reused: false };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
module.exports = {
|
|
76
|
+
evaluateAgent365Checkpoint,
|
|
77
|
+
agent365AppliesToDeclarativeAgents,
|
|
78
|
+
assertMatchingRegistration,
|
|
79
|
+
registerExternalMcpServer
|
|
80
|
+
};
|