27 live tests · 23 MCP tools · 6 fixes applied · Generated 2026-02-06 · Branch: fix/mcp-tool-audit-issues
FIXED (was CRITICAL): check_as_relationship no longer crashes — monocle bare JSON array responses are now normalized in _run_command(). Also fixes get_as_peers(0).
FIXED (was CRITICAL): get_rpki_status now correctly returns "INVALID" for mismatched origins. RIPE Stat's invalid_asn and invalid_length statuses are normalized to invalid.
FIXED (was SIGNIFICANT): ping_from_global with 8 locations now works — total probes capped to 50, preventing Globalping API 422 errors.
FIXED (was MODERATE): assess_network_resilience now detects Tier 1 / transit-free networks. AS3356 scores 9.2/10 (was 3.7/10).
FIXED (was MODERATE): get_asn_details now labels upstream ASNs as "Observed Upstream ASNs (from sampled routes)" with a note pointing to get_as_upstreams.
IMPROVED: IPv6 "no routes found" message now explains about more-specific prefixes and suggests get_asn_announcements as next step.
UNCHANGED (still good): All 16 previously passing tools continue to work. No regressions.
File: monocle.py:_run_command()
Monocle returns bare JSON arrays for some commands (e.g., as2rel ASN1 ASN2). Callers use .get("results", []) which crashed with AttributeError. Now normalizes lists to {"results": [...]}.
Tests added: 3 (bare array, empty array, check_relationship with empty array)
File: ripe_stat.py:get_rpki_validation()
RIPE Stat returns "invalid_asn" or "invalid_length" but the MCP server only mapped "invalid". Variants fell through to "UNKNOWN". Now uses startswith("invalid") normalization.
Tests added: 2 (invalid_asn, invalid_length)
File: globalping.py:_parse_locations()
8 locations × 10 limit = 80 probes, exceeding Globalping API limits. Now caps total probes to 50 by scaling per-location limit.
Tests added: 2 (cap triggered, no cap when under limit)
File: resilience.py:_score_transit()
Networks with 0 upstreams but 100+ peers and 100+ downstreams are now classified as transit-free (Tier 1) and score 1.0 instead of 0.0. "Low path diversity" recommendation skipped for transit-free networks.
Tests added: 4 (Tier 1, not Tier 1, backwards compat, skip recommendation)
File: mcp_server.py:get_asn_details()
Renamed "Upstream Providers" to "Observed Upstream ASNs (from sampled routes)" with note: "Use get_as_upstreams for authoritative relationship data."
Tests added: 0 (label change only)
File: mcp_server.py:lookup_prefix()
When no routes found for IPv6, message now explains: "many networks announce more-specific prefixes (e.g., /48s) instead of the aggregate block" and suggests get_asn_announcements.
Tests added: 0 (messaging improvement)
| # | Tool | Result | Detail | Latency | Status |
|---|---|---|---|---|---|
| 1 | search_asn | PASS | Found 26 results for "Google" | 133ms | PASS |
| 2 | lookup_prefix (IPv4) | PASS | 358 routes for 8.8.8.0/24 | 129ms | PASS |
| 3 | lookup_prefix (IPv6) | PASS | 0 routes — improved message with IPv6 guidance | 25ms | IMPROVED |
| 4 | get_asn_announcements | PASS | 5617 prefixes (2461 IPv4, 3156 IPv6) for AS13335 | 107ms | PASS |
| 5 | get_routing_history | PASS | 2 origins for 8.8.8.0/24 (7 days) | 77ms | PASS |
| 6 | get_bgp_path_history | PASS | 750 events for 8.8.8.0/24 (1 day) | 335ms | PASS |
| 7 | get_rpki_status (valid) | PASS | status="valid" for 8.8.8.0/24 + AS15169 | 1594ms | PASS |
| 8 | get_rpki_status (invalid_asn) | PASS | status="invalid" for 1.1.1.0/24 + AS15169 (normalized) | 155ms | FIXED |
| 9 | analyze_as_path | PASS | 271 paths, 1 origin for 1.1.1.0/24 | 112ms | PASS |
| 10 | compare_collectors | PASS | 358 collectors, consistent=True | 1ms | PASS |
| 11 | get_asn_details | PASS | 239 observed upstream ASNs, label updated | 121ms | IMPROVED |
| 12 | check_prefix_anomalies | PASS | Single origin (AS13335), no MOAS | <1ms | PASS |
| 13 | get_as_peers | PASS | 475 peers for AS15169 | 336ms | PASS |
| 14 | get_as_upstreams | PASS | 128 upstreams for AS13335 | 171ms | PASS |
| 15 | get_as_downstreams | PASS | 6258 downstreams for AS3356 | 137ms | PASS |
| 16 | check_as_relationship (no match) | PASS | No relationship found (no crash) | 15ms | FIXED |
| 17 | get_as_connectivity_summary | PASS | 521 neighbors for AS15169 | 325ms | PASS |
| 18 | check_as_relationship (existing) | PASS | AS13335 → AS174: upstream | 14ms | FIXED |
| 19 | ping_from_global (default) | PASS | 2 probes from DE | 2238ms | PASS |
| 20 | ping_from_global (8 locations) | PASS | 48 probes (capped from 80) | 2400ms | FIXED |
| 21 | traceroute_from_global | PASS | 1 probe from DE | 2747ms | PASS |
| 22 | get_ixps_for_asn | PASS | 347 IXPs for AS15169 | <1ms | PASS |
| 23 | get_networks_at_ixp | PASS | 851 networks at AMS-IX | <1ms | PASS |
| 24 | get_ixp_details | PASS | AMS-IX, 851 participants | <1ms | PASS |
| 25 | get_network_contacts | PASS | 0 contacts for AS15169 (private) | <1ms | PASS |
| 26 | assess_network_resilience (Tier 1) | PASS | AS3356 score=9.2/10, tier1=True | 155ms | FIXED |
| 27 | assess_network_resilience (normal) | PASS | AS13335 score=10.0/10, 128 upstreams | 75ms | PASS |
| # | Original Test | Before | After | Change |
|---|---|---|---|---|
| 5 | Bidirectional relationship check (check_as_relationship) | BUG (1/5) | PASS (5/5) | FIXED |
| 15 | ASN Zero / reserved (get_as_peers(0)) | BUG (1/5) | PASS (4/5) | FIXED |
| 17 | Deliberate RPKI mismatch (get_rpki_status) | BUG (1/5) | PASS (5/5) | FIXED |
| 18 | Resilience: Tier 1 scoring (assess_network_resilience) | WARN (3/5) | PASS (5/5) | FIXED |
| 1 | Upstream agreement / label (get_asn_details) | WARN (3/5) | IMPROVED (4/5) | IMPROVED |
| 21 | IPv6 prefix lookup message | FAIL (1/5) | IMPROVED (3/5) | IMPROVED |
| 23 | IPv6 anomaly check message | FAIL (1/5) | IMPROVED (3/5) | IMPROVED |
| 25 | IXP peering decision workflow | WARN (3/5) | PASS (5/5) | FIXED |
| 26 | Global reachability (many locations) | WARN* (4/5) | PASS (5/5) | FIXED |
Tests improved: 9 of 30 original tests are now better
BUG → PASS: 3 tests (Tests 5, 15, 17) — all critical/significant bugs resolved
WARN → PASS: 3 tests (Tests 18, 25, 26) — resilience, peering workflow, ping locations
FAIL/WARN → IMPROVED: 3 tests (Tests 1, 21, 23) — label clarity, IPv6 messaging
Average score: 3.5/5 → 4.2/5 (+0.7)
Broken tools: 2 → 0
No regressions: All 16 previously passing tests remain passing. All 397 original unit tests still pass.
Total unit tests: 408 (was 397, +11 new)
All passing: 408/408
Linter: ruff check — all checks passed
Files changed: 9 (5 source, 4 test)
Lines added: 236
Lines removed: 7
| Test File | New Tests | Total | Fix Covered |
|---|---|---|---|
tests/test_sources/test_monocle.py | +3 | 24 | Fix 1: bare array, empty array, check_relationship |
tests/test_sources/test_ripe_stat.py | +2 | 12 | Fix 2: invalid_asn, invalid_length normalization |
tests/test_sources/test_globalping.py | +2 | 18 | Fix 4: probe cap triggered, no cap when under limit |
tests/test_analysis/test_resilience.py | +4 | 21 | Fix 6: Tier 1, not Tier 1, backwards compat, skip rec |
Raw HTTP errors and API URLs leak to users for malformed CIDR input (Test #11). Missing client-side validation for date ranges (Test #14). Reserved ASN/prefix ranges not recognized (Tests #6, #7). Covering prefix suggestion for /32 lookups (Test #10).
Path events show "(from unknown)" and lack the actual path content, reducing forensic value (Tests #16, #20).
compare_routing_periodsNo built-in diff/comparison mode for routing changes across time windows (Test #28). Operators must manually diff two queries.
No aggregation efficiency analysis (Test #29). No geolocation inference from latency data (Test #30). These are new-feature requests rather than bugs.
check_as_relationship monocle response parsingCommit: dfbeacf — Normalized bare JSON array in _run_command()
get_rpki_status to return INVALID for mismatched originsCommit: e360103 — Added startswith("invalid") normalization in get_rpki_validation()
ping_from_global with many locationsCommit: 7ebfdef — Capped total probes to 50 in _parse_locations()
Commit: c2f6aac — Heuristic: 0 upstreams + 100+ peers + 100+ downstreams = transit-free network
get_asn_detailsCommit: f3086fa — Relabeled to "Observed Upstream ASNs (from sampled routes)"
Commit: 9280e67 — Added IPv6 more-specific prefix guidance and get_asn_announcements suggestion
Branch: fix/mcp-tool-audit-issues (6 commits ahead of master)
Commits:
• dfbeacf fix: normalize bare JSON array response from monocle _run_command
• e360103 fix: normalize RPKI "invalid_asn"/"invalid_length" statuses to "invalid"
• 7ebfdef fix: cap total Globalping probes to 50 to avoid API 422 errors
• c2f6aac fix: detect Tier 1 transit-free networks in resilience scoring
• f3086fa fix: relabel "Upstream Providers" to "Observed Upstream ASNs" in get_asn_details
• 9280e67 fix: improve "no routes found" message for IPv6 prefix lookups