{% extends "base.html" %} {% block title %}Network · Harbormaster{% endblock %} {% block page_title %}Network{% endblock %} {% block content %}

Inter-project network

Live MCP-call events. Edges thicken with call frequency.

{# v21.0.0a6: network tabs. The networkTabs() factory owns active/setTab and (for graph/chat/timeline) re-dispatches the legacy hm:network:view event consumed by networkPanel(); the stats tab toggles a sibling `data-network-stats` block. #}
{% with tabs_id="network" %}{% include "_partials/_tabs.html" %}{% endwith %}

Network stats

{# v21.0.9: when total_calls === 0, hide the 5-cell grid (whose "by tool / by source / top projects" cells render as empty unlabelled boxes) and show a clear empty-state instead. The window selector above still works so the operator can widen the range from here. #}

No MCP calls in the .

Try a wider window using the selector above, or ask a project something via your MCP client to populate stats.

total calls
error rate
by tool
by source
{# v13.0.0a4: each source row is a button that dispatches the hm:network:filter event so the events panel below can apply the filter without re-rendering the whole stats panel. #}
top projects
{# v13.0.0a4: server-side filter controls. Tool + source dropdowns are derived from the stats panel above (auto-refresh every 30s); the date inputs accept HTML5 datetime-local strings (operator's local TZ, converted to unix ms before being sent to the API). Filter state is mirrored to the URL so an operator can share / bookmark a filtered view. #}
{# v11.0.0a4: stateBadge unification — replaces two inline color- only spans with the shared icon+label badge component. #}

No MCP traffic yet.

Ask a project something via your MCP client and the call will appear here in real-time — including caller, target, timing, and result.

Event density —
{# v21.0.9: nested empty-state for "events exist, but none in the selected window". Previously an empty-but-non-zero events array still rendered the SVG with all-zero bars — operators read this as "broken dashboard". Now the SVG is gated on timelineEventsTotal>0 and a clear empty-state with a CTA to switch the window takes over when the in-window count is 0. #}

No events in the .

Switch to a wider window to see older traffic.

Run an MCP tool against a project to populate the timeline.

events · peak bucket:

{# v16.0.0a3: network page tour wizard (carry-over #8). Three-step walkthrough on first /network visit, gated by localStorage `hm-network-tour-completed`. Anchors via `data-tour-step="network-*"` markup attrs (carry-over #6) — resilient to template refactors. #} {% endblock %} {# v19.0.0a3: network inspector — compact 1h stats summary. The full stats panel (5-column grid, by-tool / by-source / top-projects breakdowns + filter controls) stays in the main column where it has room to breathe. The inspector mirrors the headline numbers (total_calls / error_rate / by_tool top entries) over the last 1h so the operator gets a glance at network health regardless of which view (graph / chat / timeline) is selected in main. #} {% block inspector %}
{# v21.0.9: when the 1h window is genuinely empty (total_calls === 0) the previous version rendered three sections of zeros — operators read this as "broken dashboard" (literal report 2026-05-12). Now a single clear empty-state replaces the grid until traffic arrives, and the per-section breakdowns return automatically when the stats endpoint sees non-zero data. #}

No MCP calls in the last hour.

Inspector pins a 1h rolling window. Widen the main stats panel below (last 24h / 7d / all time) to see longer-range traffic, or run an MCP tool against a project to populate the feed.

{% endblock %}