Skip to content

Commit 6a2db7b

Browse files
authored
feat(radar): add BGP IP space timeseries and real-time routes tools (#275)
Add two new BGP tools to address gaps in IPv6 monitoring: - get_bgp_ip_space_timeseries: track announced IPv4/IPv6 address space over time - get_bgp_routes_realtime: get real-time BGP routes from RouteViews/RIPE RIS
1 parent ac8ea3d commit 6a2db7b

File tree

3 files changed

+92
-0
lines changed

3 files changed

+92
-0
lines changed

apps/radar/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ Currently available tools:
2828
| | `get_bgp_top_prefixes` | Gets top IP prefixes by BGP update count |
2929
| | `get_bgp_moas` | Gets Multi-Origin AS (MOAS) prefixes |
3030
| | `get_bgp_pfx2as` | Gets prefix-to-ASN mapping |
31+
| | `get_bgp_ip_space_timeseries` | Retrieves announced IP address space over time (IPv4 /24s and IPv6 /48s) - useful for detecting route withdrawals |
32+
| | `get_bgp_routes_realtime` | Gets real-time BGP routes for a prefix using RouteViews and RIPE RIS collectors |
3133
| **Bots** | `get_bots_data` | Retrieves bot traffic data by name, operator, category (AI crawlers, search engines, etc.) |
3234
| | `list_bots` | Lists known bots with details (AI crawlers, search engines, monitoring bots) |
3335
| | `get_bot_details` | Gets detailed information about a specific bot by slug |
@@ -82,6 +84,10 @@ Currently available tools:
8284
- `Show me recent BGP hijack events.`
8385
- `Which prefixes have the most BGP updates?`
8486
- `What AS announces the prefix 1.1.1.0/24?`
87+
- `Show me IPv6 announced address space for Portugal over the last 30 days.`
88+
- `Compare IPv4 vs IPv6 BGP address space trends for AS13335.`
89+
- `Get real-time BGP routes for prefix 1.1.1.0/24.`
90+
- `Monitor announced IPv6 space changes for a specific country to detect route withdrawals.`
8591

8692
**Security & Attacks**
8793

apps/radar/src/tools/radar.tools.ts

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
BgpInvalidOnlyParam,
2323
BgpInvolvedAsnParam,
2424
BgpInvolvedCountryParam,
25+
BgpIpVersionParam,
2526
BgpLeakAsnParam,
2627
BgpLongestPrefixMatchParam,
2728
BgpMaxConfidenceParam,
@@ -2398,6 +2399,84 @@ export function registerRadarTools(agent: RadarMCP) {
23982399
}
23992400
)
24002401

2402+
agent.server.tool(
2403+
'get_bgp_ip_space_timeseries',
2404+
'Retrieve announced IP address space time series data. Shows the count of announced IPv4 /24s and IPv6 /48s over time. Essential for monitoring BGP route withdrawals, IPv6 address space changes, and detecting significant routing events by ASN or country.',
2405+
{
2406+
dateRange: DateRangeArrayParam.optional(),
2407+
dateStart: DateStartArrayParam.optional(),
2408+
dateEnd: DateEndArrayParam.optional(),
2409+
asn: AsnArrayParam,
2410+
location: LocationArrayParam,
2411+
ipVersion: BgpIpVersionParam,
2412+
},
2413+
async ({ dateRange, dateStart, dateEnd, asn, location, ipVersion }) => {
2414+
try {
2415+
const props = getProps(agent)
2416+
const result = await fetchRadarApi(props.accessToken, '/bgp/ips/timeseries', {
2417+
dateRange,
2418+
dateStart,
2419+
dateEnd,
2420+
asn,
2421+
location,
2422+
ipVersion,
2423+
})
2424+
2425+
return {
2426+
content: [
2427+
{
2428+
type: 'text' as const,
2429+
text: JSON.stringify({ result }),
2430+
},
2431+
],
2432+
}
2433+
} catch (error) {
2434+
return {
2435+
content: [
2436+
{
2437+
type: 'text' as const,
2438+
text: `Error getting BGP IP space timeseries: ${error instanceof Error ? error.message : String(error)}`,
2439+
},
2440+
],
2441+
}
2442+
}
2443+
}
2444+
)
2445+
2446+
agent.server.tool(
2447+
'get_bgp_routes_realtime',
2448+
'Get real-time BGP routes for a specific IP prefix using public route collectors (RouteViews and RIPE RIS). Shows current routing state including AS paths, RPKI validation status, and visibility across peers. Useful for troubleshooting routing issues and verifying route announcements.',
2449+
{
2450+
prefix: BgpPrefixParam,
2451+
},
2452+
async ({ prefix }) => {
2453+
try {
2454+
const props = getProps(agent)
2455+
const result = await fetchRadarApi(props.accessToken, '/bgp/routes/realtime', {
2456+
prefix,
2457+
})
2458+
2459+
return {
2460+
content: [
2461+
{
2462+
type: 'text' as const,
2463+
text: JSON.stringify({ result }),
2464+
},
2465+
],
2466+
}
2467+
} catch (error) {
2468+
return {
2469+
content: [
2470+
{
2471+
type: 'text' as const,
2472+
text: `Error getting real-time BGP routes: ${error instanceof Error ? error.message : String(error)}`,
2473+
},
2474+
],
2475+
}
2476+
}
2477+
}
2478+
)
2479+
24012480
// ============================================================
24022481
// AS Sets and Relationships Tools
24032482
// ============================================================

apps/radar/src/types/radar.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -852,6 +852,13 @@ export const BgpInvalidOnlyParam = z
852852
.optional()
853853
.describe('Only return invalid MOAS prefixes.')
854854

855+
export const BgpIpVersionParam = z
856+
.array(z.enum(['IPv4', 'IPv6']))
857+
.optional()
858+
.describe(
859+
'Filters results by IP version (IPv4 vs. IPv6). Useful for monitoring IPv6 address space specifically.'
860+
)
861+
855862
// ============================================================
856863
// Geolocation Parameters
857864
// ============================================================

0 commit comments

Comments
 (0)