{{ 'XP.McpPublication.Title' | translate: { Default: 'MCP services' } }}
{{ 'XP.Operations.SuperAdminOnly' | translate: { Default: 'Super Admin' } }}
{{ 'XP.McpPublication.Description' | translate : { Default: 'Publish capabilities in the current tenant or organization as authenticated MCP 2026-07-28 Streamable HTTP services.' } }}
@if (canManageMcp()) { }

{{ 'XP.McpPublication.CreateDialogTitle' | translate: { Default: 'Create MCP service' } }}

{{ 'XP.McpPublication.CreateDialogDescription' | translate : { Default: 'Set the public name, endpoint slug, and instructions for the new MCP service.' } }}

{{ 'XP.McpPublication.Name' | translate: { Default: 'Service name' } }} {{ 'XP.McpPublication.Slug' | translate: { Default: 'Slug' } }} @if (createForm.controls.slug.invalid && createForm.controls.slug.touched) { {{ 'XP.McpPublication.SlugHint' | translate: { Default: 'Use lowercase letters, numbers, and hyphens.' } }} } @else { {{ 'XP.McpPublication.SlugCreateHint' | translate : { Default: 'This becomes the public endpoint path and cannot be changed after the service is created.' } }} } {{ 'XP.McpPublication.Instructions' | translate: { Default: 'Instructions' } }}
@if (loading()) {
} @else if (!publications().length) { } @else {
@if (detailLoading()) {
} @else if (publication(); as selected) {

{{ selected.name }}

{{ 'XP.McpPublication.Status.' + selected.status | translate: { Default: selected.status } }} @if (selected.reviewStatus === 'required') { {{ 'XP.McpPublication.ReviewRequired' | translate: { Default: 'Review required' } }} }
{{ connectionInfo()?.endpoint }} @if (connectionInfo()?.endpoint; as endpoint) { }
@if (canManageMcp()) { }
@switch (activeSection()) { @case ('basic') {
{{ 'XP.McpPublication.Name' | translate: { Default: 'Service name' } }} {{ 'XP.McpPublication.Slug' | translate: { Default: 'Slug' } }} {{ 'XP.McpPublication.SlugImmutableHint' | translate : { Default: 'The slug is part of the public endpoint and cannot be changed after creation.' } }}
{{ 'XP.McpPublication.ApiKey' | translate: { Default: 'API key' } }}

{{ 'XP.McpPublication.ApiKeyDescription' | translate : { Default: 'Clients authenticate with a key created and managed in the Authentication tab.' } }}

{{ 'XP.Xpert.Enabled' | translate: { Default: 'Enabled' } }}
{{ 'XP.McpPublication.OAuth' | translate: { Default: 'OAuth 2.0 / OIDC' } }}

{{ 'XP.McpPublication.OAuthDescription' | translate : { Default: 'Clients use access tokens issued by your identity provider and validated by Xpert.' } }}

{{ 'XP.Xpert.Enabled' | translate: { Default: 'Enabled' } }}
} @case ('capabilities') {

{{ 'XP.McpPublication.OpenCapabilities' | translate: { Default: 'Open capabilities' } }}

{{ 'XP.McpPublication.CapabilityHint' | translate : { Default: 'Capabilities are grouped by their concrete toolset instance. Renaming a public capability does not rename its source.' } }}

{{ capabilityCountLabel() }}
@if (capabilityGroups().length) { @for (group of capabilityGroups(); track group.toolsetId) { {{ group.label }} {{ group.pluginName || ('XP.McpPublication.Toolset' | translate: { Default: 'Toolset' }) }} · {{ group.toolsetId }} @if (isCapabilityGroupLoading(group.toolsetId)) { {{ 'XP.McpPublication.LoadingCapabilities' | translate: { Default: 'Loading capabilities…' } }} } @else if (isCapabilityGroupLoaded(group.toolsetId) || group.capabilities.length) { {{ capabilityGroupCountLabel(group) }} } @if (isCapabilityGroupLoading(group.toolsetId)) {
} @else if (group.capabilities.length) {
@for ( draft of group.capabilities; track draft.catalog.id || draft.catalog.capabilityKey ) {
{{ capabilityTitle(draft) }}
{{ 'XP.McpPublication.CapabilityType.' + draft.catalog.capabilityType | translate : { Default: capabilityTypeLabel(draft.catalog.capabilityType) } }}
@if (capabilityDescription(draft); as description) {

{{ description }}

} {{ draft.catalog.capabilityKey }}
{{ 'XP.McpPublication.PublicName' | translate: { Default: 'Public name' } }} {{ 'XP.Xpert.Enabled' | translate: { Default: 'Enabled' } }}
}
} @else if (isCapabilityGroupLoaded(group.toolsetId)) { }
}
} @else { } } @case ('authentication') {

{{ 'XP.McpPublication.ApiKey' | translate: { Default: 'API Key' } }}

{{ 'XP.McpPublication.SecretOnce' | translate : { Default: 'The secret is shown only immediately after creation or rotation.' } }}

@if (revealedApiKey(); as revealed) {
{{ 'XP.McpPublication.CopySecretNow' | translate: { Default: 'Copy this secret now' } }}
{{ revealed.secret }}
} @if (canManageMcp()) {
{{ 'XP.McpPublication.KeyName' | translate: { Default: 'Key name' } }} {{ 'XP.McpPublication.Scopes' | translate: { Default: 'Scopes' } }} @for (scope of mcpScopeOptions; track scope.value) { {{ 'XP.McpPublication.Scope.' + scope.key | translate: { Default: scope.defaultLabel } }} ({{ scope.value }}) } {{ 'XP.McpPublication.ExpiresAt' | translate: { Default: 'Expires at' } }}
} @if (apiKeys().length) {
@for (key of apiKeys(); track key.id) { }
{{ 'XP.McpPublication.KeyName' | translate: { Default: 'Key name' } }} {{ 'XP.McpPublication.Prefix' | translate: { Default: 'Prefix' } }} {{ 'XP.McpPublication.Scopes' | translate: { Default: 'Scopes' } }} {{ 'XP.McpPublication.LastUsed' | translate: { Default: 'Last used' } }} {{ 'XP.McpPublication.StatusLabel' | translate: { Default: 'Status' } }} {{ 'XP.ModelGateway.Actions' | translate: { Default: 'Actions' } }}
{{ key.name }} {{ key.keyPrefix }}… {{ key.scopes.join(' ') }} {{ key.lastUsedAt ? (key.lastUsedAt | date: 'yyyy-MM-dd HH:mm') : '-' }} {{ 'XP.McpPublication.ApiKeyStatus.' + (isApiKeyActive(key) ? 'active' : 'inactive') | translate: { Default: isApiKeyActive(key) ? 'Active' : 'Inactive' } }} @if (isApiKeyActive(key) && canManageMcp()) {
@if (revealedApiKey(); as revealed) { @if (revealed.apiKey.id === key.id) { } }
}
}

{{ 'XP.McpPublication.OAuthOidc' | translate: { Default: 'OAuth 2.0 / OIDC' } }}

{{ 'XP.McpPublication.OAuthHint' | translate : { Default: 'Xpert validates issuer, audience, scopes, JWKS, and subject mapping as the MCP Resource Server.' } }}

{{ 'XP.McpPublication.OAuthSetupTitle' | translate: { Default: 'Before you configure OAuth' } }}

{{ 'XP.McpPublication.OAuthSetupDescription' | translate : { Default: 'Register this MCP endpoint as an API or resource server in your identity provider. Use the token issuer URL below, set the audience to this service endpoint, and grant the selected scopes to the client application.' } }}

{{ 'XP.McpPublication.Issuer' | translate: { Default: 'Issuer' } }} {{ 'XP.McpPublication.OAuthIssuerHint' | translate : { Default: 'Use the exact iss value from access tokens. Xpert discovers its JWKS from this URL.' } }} {{ 'XP.McpPublication.Audience' | translate: { Default: 'Audience' } }} {{ 'XP.McpPublication.OAuthAudienceHint' | translate : { Default: 'Use the API audience configured in your identity provider; this service endpoint is the recommended value.' } }} {{ 'XP.McpPublication.RequiredScopes' | translate: { Default: 'Required scopes' } }} @for (scope of mcpScopeOptions; track scope.value) { {{ 'XP.McpPublication.Scope.' + scope.key | translate: { Default: scope.defaultLabel } }} ({{ scope.value }}) } {{ 'XP.McpPublication.OAuthScopesHint' | translate : { Default: 'Every selected scope must be present in the access token. Configure the same scopes in your identity provider.' } }} {{ 'XP.McpPublication.SubjectClaim' | translate: { Default: 'Subject claim' } }} {{ 'XP.McpPublication.OAuthSubjectClaimHint' | translate : { Default: 'Claim containing the stable caller identity. Most OIDC providers use sub.' } }} {{ 'XP.McpPublication.EmailClaim' | translate: { Default: 'Email claim' } }} {{ 'XP.McpPublication.ClientIdClaim' | translate: { Default: 'Client ID claim' } }}

{{ 'XP.McpPublication.TokenIntrospection' | translate: { Default: 'Token introspection' } }}

{{ 'XP.McpPublication.TokenIntrospectionHint' | translate : { Default: 'Require RFC 7662 active-token checks on every request for immediate authorization-server revocation.' } }}

{{ 'XP.Xpert.Enabled' | translate: { Default: 'Enabled' } }}
@if (oauthForm.controls.introspectionEnabled.value) {
{{ 'XP.McpPublication.IntrospectionEndpoint' | translate: { Default: 'Introspection endpoint override' } }} {{ 'XP.McpPublication.IntrospectionClientId' | translate: { Default: 'Resource Server client ID' } }} {{ 'XP.McpPublication.IntrospectionClientSecret' | translate: { Default: 'Resource Server client secret' } }}
}
{{ 'XP.Xpert.Enabled' | translate: { Default: 'Enabled' } }}
} @case ('policy') {

{{ 'XP.McpPublication.PermissionPolicy' | translate: { Default: 'Permission policy' } }}

{{ 'XP.McpPublication.PolicyHint' | translate : { Default: 'Policies are enforced after Publication selection and current tenant or organization permission checks.' } }}

@if (selectedCapabilityDrafts().length) {
@for ( draft of selectedCapabilityDrafts(); track draft.catalog.id || draft.catalog.capabilityKey ) {
{{ draft.publicName }}
{{ capabilityTitle(draft) }} · {{ draft.catalog.toolsetId }}
{{ 'XP.McpPublication.InvocationPolicy' | translate: { Default: 'Invocation policy' } }} @for (mode of approvalModes; track mode) { {{ 'XP.McpPublication.Approval.' + mode | translate: { Default: mode } }} }
{{ 'XP.McpPublication.TimeoutMs' | translate: { Default: 'Timeout (ms)' } }} {{ 'XP.McpPublication.RateRequests' | translate: { Default: 'Rate requests' } }} {{ 'XP.McpPublication.RateWindow' | translate: { Default: 'Rate window (seconds)' } }}
}
} @else { }
} @case ('instructions') {
{{ 'XP.McpPublication.Instructions' | translate: { Default: 'Instructions' } }} {{ 'XP.McpPublication.InstructionsHint' | translate : { Default: 'Returned by server/discover as guidance shared by every capability in this service.' } }}
} @case ('audit') {

{{ 'XP.McpPublication.InvocationAudit' | translate: { Default: 'Invocation audit' } }}

{{ 'XP.McpPublication.AuditHint' | translate : { Default: 'Audit records retain identity, capability, outcome, timing, trace, and safe argument summaries—not raw secrets or full payloads.' } }}

@if (auditLoading() && !auditEntries().length) {
} @else if (auditEntries().length) {
@for (entry of auditEntries(); track entry.id) { }
{{ 'XP.McpPublication.Time' | translate: { Default: 'Time' } }} {{ 'XP.McpPublication.Capability' | translate: { Default: 'Capability' } }} {{ 'XP.McpPublication.Subject' | translate: { Default: 'Subject' } }} {{ 'XP.McpPublication.Client' | translate: { Default: 'Client' } }} {{ 'XP.McpPublication.StatusLabel' | translate: { Default: 'Status' } }} {{ 'XP.McpPublication.Duration' | translate: { Default: 'Duration' } }} {{ 'XP.McpPublication.Trace' | translate: { Default: 'Trace' } }}
{{ entry.createdAt ? (entry.createdAt | date: 'yyyy-MM-dd HH:mm:ss') : '-' }} {{ entry.publicName || entry.capabilityKey || '-' }} {{ entry.subjectType }} · {{ entry.subjectId }} {{ entry.clientName || '-' }} {{ 'XP.McpPublication.AuditStatus.' + entry.status | translate: { Default: entry.status } }} @if (entry.errorCode) {
{{ entry.errorCode }}
}
{{ entry.durationMs ?? '-' }}{{ entry.durationMs !== null && entry.durationMs !== undefined ? ' ms' : '' }} {{ entry.traceId || entry.requestId }}
{{ 'XP.McpPublication.AuditPageSummary' | translate : { current: auditPageNumber(), pages: auditPageCount(), total: auditTotal(), Default: 'Page ' + auditPageNumber() + ' of ' + auditPageCount() + ' · ' + auditTotal() + ' total' } }} @if (auditPageCount() > 1) { @let pages = auditPaginationPages();
  • @for (page of pages; track page; let index = $index) { @if (index > 0 && page - pages[index - 1] > 1) {
  • }
  • }
}
} @else { }
} @case ('test') {

{{ 'XP.McpPublication.ReadinessTest' | translate: { Default: 'Readiness test' } }}

{{ 'XP.McpPublication.TestHint' | translate : { Default: 'Checks protocol, capability compatibility, review state, and runtime status.' } }}

@if (testResult(); as result) {
{{ (result.ready ? 'XP.McpPublication.Ready' : 'XP.McpPublication.NotReady') | translate: { Default: result.ready ? 'Ready' : 'Not ready' } }} {{ 'XP.McpPublication.CapabilityCount' | translate : { count: result.enabledCapabilityCount, Default: result.enabledCapabilityCount + ' capabilities' } }} · {{ result.protocolVersion }}
@for (check of result.checks; track check.key) {
{{ 'XP.McpPublication.CheckStatus.' + check.status | translate: { Default: check.status } }} {{ check.message }}
}
}

{{ 'XP.McpPublication.ConnectionConfigurations' | translate: { Default: 'Connection configurations' } }}

{{ 'XP.McpPublication.ConfigSecretHint' | translate : { Default: 'Configurations reference an environment variable. Existing API key secrets are never read back.' } }}

Codex

{{ codexConfiguration() }}

{{ 'XP.McpPublication.JsonClient' | translate: { Default: 'JSON MCP client' } }}

{{ jsonClientConfiguration() }}

{{ 'XP.McpPublication.GenericClient' | translate: { Default: 'Generic MCP client' } }}

{{ genericConfiguration() }}
} }
}
}