diff --git a/src/Web/autopilot-monitor-web/app/admin/tenants/sections/SectionTenantConfigReport.tsx b/src/Web/autopilot-monitor-web/app/admin/tenants/sections/SectionTenantConfigReport.tsx
index d41ad011..5f8eaf04 100644
--- a/src/Web/autopilot-monitor-web/app/admin/tenants/sections/SectionTenantConfigReport.tsx
+++ b/src/Web/autopilot-monitor-web/app/admin/tenants/sections/SectionTenantConfigReport.tsx
@@ -6,6 +6,7 @@ import { api } from '@/lib/api';
import { apiErrorText, fetchJson } from "@/lib/apiClient";
import type {
AgentConfigResponse,
+ McpClientRegistrationListResponse,
TenantConfiguration,
TenantFeatureFlagsResponse,
} from "@/utils/wire-types.generated";
@@ -205,6 +206,31 @@ function ChannelRows({ config }: { config: TenantConfiguration }) {
);
}
+// ── Self-hosted AI clients (separate table, not part of TenantConfiguration) ──
+
+function SelfHostedAiClientRows({ list }: { list: McpClientRegistrationListResponse }) {
+ return (
+ <>
+
+ {list.registrations.length === 0 && }
+ {list.registrations.map((r) => (
+
+ |
+
+ |
+
+ ))}
+ >
+ );
+}
+
// ── Main component ───────────────────────────────────────────────────────────
export function SectionTenantConfigReport() {
@@ -215,6 +241,7 @@ export function SectionTenantConfigReport() {
const [config, setConfig] = useState(null);
const [flags, setFlags] = useState(null);
const [effective, setEffective] = useState(null);
+ const [aiClients, setAiClients] = useState(null);
const [loading, setLoading] = useState(false);
const [loadingTenants, setLoadingTenants] = useState(true);
const [error, setError] = useState(null);
@@ -242,27 +269,31 @@ export function SectionTenantConfigReport() {
fetchTenants();
}, [user?.isGlobalAdmin, getAccessToken]);
- // Fetch the stored config plus the two backend-resolved views of it. The stored config is
- // the report; feature-flags (effective entitlement, header) and the effective agent config
- // (runtime column) are fail-soft — a notice replaces them instead of blocking the page.
+ // Fetch the stored config plus the two backend-resolved views of it and the self-hosted AI
+ // client registrations (own table). The stored config is the report; feature-flags (effective
+ // entitlement, header), the effective agent config (runtime column) and the registrations are
+ // fail-soft — a notice replaces them instead of blocking the page.
const fetchConfig = useCallback(async () => {
if (!selectedTenantId) return;
try {
setLoading(true);
setError(null);
setSideError(null);
- const [configResult, flagsResult, effectiveResult] = await Promise.allSettled([
+ const [configResult, flagsResult, effectiveResult, aiClientsResult] = await Promise.allSettled([
fetchJson(api.config.tenant(selectedTenantId), getAccessToken),
fetchJson(api.config.featureFlags(selectedTenantId), getAccessToken),
fetchJson(api.config.effectiveAgentConfig(selectedTenantId), getAccessToken),
+ fetchJson(api.tenants.mcpClientRegistrations(selectedTenantId), getAccessToken),
]);
if (configResult.status === 'rejected') throw configResult.reason;
setConfig(configResult.value);
setFlags(flagsResult.status === 'fulfilled' ? flagsResult.value : null);
setEffective(effectiveResult.status === 'fulfilled' ? effectiveResult.value : null);
+ setAiClients(aiClientsResult.status === 'fulfilled' ? aiClientsResult.value : null);
const sideFailures = [
flagsResult.status === 'rejected' ? `feature flags: ${apiErrorText(flagsResult.reason)}` : null,
effectiveResult.status === 'rejected' ? `effective agent config: ${apiErrorText(effectiveResult.reason)}` : null,
+ aiClientsResult.status === 'rejected' ? `self-hosted AI clients: ${apiErrorText(aiClientsResult.reason)}` : null,
].filter((s): s is string => s !== null);
setSideError(sideFailures.length ? `Backend-resolved views unavailable — ${sideFailures.join('; ')}` : null);
} catch (err) {
@@ -270,6 +301,7 @@ export function SectionTenantConfigReport() {
setConfig(null);
setFlags(null);
setEffective(null);
+ setAiClients(null);
} finally {
setLoading(false);
}
@@ -433,6 +465,7 @@ export function SectionTenantConfigReport() {
/>
);
})}
+ {section === 'Tenant Status' && aiClients && }
))}
diff --git a/src/Web/autopilot-monitor-web/app/admin/tenants/sections/tenantConfigReportCatalog.ts b/src/Web/autopilot-monitor-web/app/admin/tenants/sections/tenantConfigReportCatalog.ts
index 9c13524f..b99c22d0 100644
--- a/src/Web/autopilot-monitor-web/app/admin/tenants/sections/tenantConfigReportCatalog.ts
+++ b/src/Web/autopilot-monitor-web/app/admin/tenants/sections/tenantConfigReportCatalog.ts
@@ -98,7 +98,7 @@ export const TENANT_FIELDS: Record