function topologyFigure(host) { ensureStyles(); var rows = [ { id: 'files', label: 'client: files', s1: 'server: files', s2: 'local . stdio . tools', s3: 'reports: "primary"', y: 32 }, { id: 'notes', label: 'client: notes', s1: 'server: notes', s2: 'local . stdio . tools', s3: 'reports: "primary"', y: 104 }, { id: 'metrics', label: 'client: metrics', s1: 'server: metrics', s2: 'remote . http . resources', s3: 'reports: "metrics-svc"', y: 176 } ]; var parts = []; var i; for (i = 0; i < rows.length; i++) { var r = rows[i]; var cy = r.y + 27; parts.push(''); parts.push('' + r.label + ''); parts.push(''); parts.push(''); parts.push('' + r.s1 + ''); parts.push('' + r.s2 + ''); parts.push('' + r.s3 + ''); } var shell = document.createElement('div'); shell.className = 'mf-shell'; shell.innerHTML = [ '
Hosts, Clients, and Servers one client per server, one registry behind the host
', '
', '', '', '', 'host process', parts.join(''), 'registry keys are host-assigned ids, never serverInfo.name', 'search -> files (first to declare the name keeps it)', 'notes/search -> notes (the collision gets a server-id prefix)', '', '', '
', '
The host embeds one client per server. Files and notes are local stdio subprocesses that both self-report the name "primary", so the host keys its registry on the connection id it assigned, files and notes, never on that self-reported name. Metrics is a remote Streamable HTTP server with no tools capability, so its tools are never listed. Both files and notes declare a tool named search; the aggregator keeps the first as the canonical name and exposes the second as notes/search.
' ].join(''); host.appendChild(shell); } // register as: mcpa-06-topology