CVM (ContextVM) exposes NIP-66 relay intelligence as 21 structured MCP tools transported over the Nostr protocol. Instead of parsing raw NIP-66 events yourself, you send a tool call as a Nostr event and receive a clean JSON response. No API keys are required — communication uses Nostr pubkeys. CVM works with Claude Desktop, AI agents, and any MCP-compatible client. The tools mirror the REST API endpoints but use the Nostr protocol for transport. Calls are made withDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/sandwichfarm/nostr-watch/llms.txt
Use this file to discover all available pages before exploring further.
cvmClient.callTool(toolName, params) when using the SDK, or via an MCP client like Claude Desktop.
The CVM server is provided by the rstate service. To connect, you need the server’s CVM relay URLs and its public key. For Claude Desktop setup, see the getting started guide.
Relay query tools
relays/list
Get a paginated list of all relays known to this rstate instance. Input:Results per page. Default
50.Pagination offset. Default
0.Sort field:
url, updated, or observationCount. Default url.Sort direction:
asc or desc. Default asc.Response format:
full (per-monitor attribution), detailed (aggregated, default), or simple (URLs only).{ relays, total, limit, offset }
relays/state
Get the aggregated state for a specific relay URL. Input:The relay’s WebSocket URL.
Response format:
full, detailed (default), or simple.{ relay } — full relay state object, or null if not found.
relays/search
Search relays using one or more filter criteria. All filter fields are optional — only relays matching all provided filters are returned. Input:Network type:
clearnet, tor, i2p, or hybrid.Return only relays that support all listed NIP numbers.
Filter by software:
{ family, version }.Filter by NIP-32 labels:
[{ namespace, value }].Maximum RTT in ms:
{ open, read, write }.Minimum monitor support ratio (0–1).
Results per page. Default
100.Pagination offset. Default
0.Response format. Default
detailed.{ relays, total, limit, offset }
Geospatial tools
relays/nearby
Find relays near a geographic location using Haversine distance. Input:Latitude, -90 to 90.
Longitude, -180 to 180.
Search radius in km. Default
100.Maximum results. Default
50.Response format. Default
detailed.{ relays, center: { lat, lon }, radius } — each relay includes a distance field in km.
relays/bbox
Find relays within a geographic bounding box. Input:Southwest corner:
{ lat, lon }.Northeast corner:
{ lat, lon }.Maximum results. Default
100.Return relay URLs only (legacy). Default
false.{ relays, bbox: { sw, ne }, total }
Label tools
relays/labels
Get labels for a specific relay. Input:The relay’s WebSocket URL.
Filter to a specific label namespace (e.g.
country, isp).{ relayUrl, labels } — labels is a Record<namespace, values[]>.
relays/labels/list
List all available label namespaces and values across all relays. Input:Filter to a specific namespace.
{ namespaces, labels } — namespaces is a sorted string array; labels is Record<namespace, values[]>.
relays/by/label
Get relays that have a specific label value. Input:Label namespace, e.g.
country, isp.Label value, e.g.
US, amazon.Results per page. Default
100.Pagination offset. Default
0.Response format. Default
detailed.{ relays, label: { namespace, value }, total }
Aggregation tools
relays/by/software
Group relays by their software family. Input:Filter to a specific software family name, e.g.
strfry. Omit to get all groups.{ groups: [{ family, count, relays }] }
relays/by/network
Group relays by network type (clearnet, tor, i2p).
Input: None
Output: { groups: [{ network, count, relays }] }
relays/by/nip
Group relays by NIP support, with optional minimum support threshold. Input:Filter to a specific NIP number.
Minimum monitor support ratio (0–1). Default
0.5.{ groups: [{ nip, count, avgSupport, relays }] }
relays/by/country
Group relays by country using ISO 3166-1 alpha-2 codes. Input:Filter to a specific country code, e.g.
US, DE. Omit to get all countries.{ groups: [{ countryCode, countryName, count, relays }] }
Availability tools
relays/online
List relays that are currently online (responded to a check within the configured window). Input:Override the online window. Default is derived from the maximum monitor check frequency.
Additional filters:
{ network, labels }.Results per page. Default
100.Pagination offset. Default
0.{ relays, total, limit, offset }
relays/offline
List relays that are currently offline but have not yet been considered dead. Input:Seconds since last successful open to consider a relay offline.
Seconds since last seen to consider a relay dead. Default: 7 days (604800).
Additional filters:
{ network, labels }.Results per page.
Pagination offset.
{ relays, total, limit, offset }
relays/dead
List relays that have not been seen for a long time and are probably permanently offline. Input:Override the dead threshold. Default: 7 days (604800).
Additional filters:
{ network, labels }.Results per page.
Pagination offset.
{ relays, total, limit, offset }
relays/compare
Compare multiple relays side by side. Input:Array of 2–10 relay WebSocket URLs to compare.
{ relays, comparison: { common: { nips, requirements }, differences: { network, software, latency } } }
Monitor tools
monitors/get
Get information and analytics for a specific monitor. Input:The monitor’s Nostr pubkey in hex format.
{ monitor, analytics } — analytics includes reliability score and coverage data.
monitors/list
List all known monitors with reliability scores. Input:Results per page. Default
100.Pagination offset. Default
0.{ monitors, total, analytics } — sorted by last seen (most recent first).
System tools
health/ping
Check server health, version, and cache statistics. Input: None Output:{ status, version, uptime, relayCount, observationCount, cache, timestamp }
status is ok, degraded, or error based on relay connectivity.
policy/get
Get the current aggregation policy configuration. Input: None Output:{ policy } — includes quorum, labelQuorum, madScale, and weights.
policy/set
Update the aggregation policy. Requires server-side authorization (the caller’s pubkey must be inallowedPubkeys).
Input:
Policy fields to update. Accepted fields:
windowStrategy— aggregation window strategyquorum— minimum monitor agreement fraction (0–1)labelQuorum— minimum label support fraction (0–1)madScale— MAD outlier rejection scale factorweights—{ recency, reliability }weighting object
{ success, policy, message }
Subscription tools
relays/subscribe_state
Subscribe to relay state change notifications. The server sends a notification each time a subscribed relay’s aggregated state changes. Input:Filter notifications to specific relay URLs.
Filter to a specific network type.
Filter to relays that support specific NIPs.
Filter by software family/version.
Filter by NIP-32 labels.
Geographic area filter:
{ center: { lat, lon }, radius }.Change thresholds before triggering a notification:
{ rttDeltaMs, supportDelta }.{ subscriptionId, message }
relays/unsubscribe
Cancel a state change subscription. Input:The subscription ID to cancel.
{ success, message }
Response formats
All relay query tools accept aformat parameter that controls response verbosity:
| Format | Returns | Use when |
|---|---|---|
full | All fields including per-monitor attribution | You need to see which monitors reported which values |
detailed | Aggregated values without per-monitor breakdown (default) | Most use cases |
simple | Relay URLs only | You only need a list of addresses |
Claude Desktop setup
Add the@nostr-watch/relayvm MCP server to your Claude Desktop configuration: