{
  "markdown": "# radiochron-mcp\n\n**[radiochron.com](https://radiochron.com)** · the chronicle of your radio.\n\nA local-first [Model Context Protocol](https://modelcontextprotocol.io) server\n**and command line** for Wi-Fi incident diagnosis and Bluetooth Low Energy\nobservation. It combines native radio collection with the\n[`radiochron`](https://github.com/sergii-ziborov/radiochron) Rust core, then\nreturns typed conclusions instead of forcing an assistant to interpret raw\noperating-system output.\n\nThe two front ends are not two implementations. `radiochron analyze` and the\n`wifi_analyze` tool run the same handler with the same bounds and the same error\ntext, so a conclusion never depends on how you asked for it.\n\nThe preferred MCP revision is `2025-11-25`; clients that request\n`2025-06-18` receive the compatible legacy tool shape. Every tool has input and\noutput schemas, structured content, safety annotations, explicit execution\nsemantics, cancellation where work is long-running, and actionable separation\nbetween JSON-RPC protocol errors and tool execution errors.\n\nRadioChron repositories remain independent:\n\n- [`radiochron`](https://github.com/sergii-ziborov/radiochron) is the Rust/IoT core.\n- [`radiochron-js`](https://github.com/sergii-ziborov/radiochron-js) is the Node/npm library; it does not ship MCP.\n- [`radiochron-mcp`](https://github.com/sergii-ziborov/radiochron-mcp) is this pure-Rust MCP server and command line.\n- [`radiochron-agent`](https://github.com/sergii-ziborov/radiochron-agent) is the unattended durable collector/exporter and does not depend on MCP.\n- [`radiochron-electron`](https://github.com/sergii-ziborov/radiochron-electron) is the standalone desktop app and does not depend on MCP.\n\n## Install\n\nThe npm package carries verified native binaries for Windows x64, Linux\nx64/ARM64, Intel Mac, and Apple Silicon:\n\n```sh\nclaude mcp add radiochron -- npx -y radiochron-mcp\n```\n\nOr install the Rust binary from source:\n\n```sh\ncargo install --git https://github.com/sergii-ziborov/radiochron-mcp\n```\n\nBuilding on Debian/Ubuntu requires `libdbus-1-dev` and `pkg-config` for the\nBlueZ adapter. Prebuilt npm users do not need a Rust toolchain.\n\nRegister an installed binary with any stdio MCP client:\n\n```json\n{\n  \"mcpServers\": {\n    \"radiochron\": {\n      \"command\": \"radiochron\"\n    }\n  }\n}\n```\n\n`RADIOCHRON_CHRONICLE_PATH` optionally overrides the local chronicle path:\n`%LOCALAPPDATA%\\RadioChron` on Windows, `~/Library/Application\nSupport/RadioChron` on macOS, or the XDG state directory on Linux.\n\n## Command line\n\nThe same binary is a CLI. Nothing extra to install — `npx radiochron status`\nworks from the npm package, and `cargo install` puts `radiochron` on `PATH`.\n\n```sh\nradiochron status                  # association state of every adapter\nradiochron scan                    # look again, then list what is there\nradiochron analyze                 # findings about the environment\nradiochron report                  # the full Markdown diagnostic report\nradiochron incident --ble          # one composite answer for \"the Wi-Fi is broken\"\nradiochron connectivity --dns example.com --tcp example.com:443\nradiochron ble scan --duration 4000\nradiochron chronicle recent --max 20\nradiochron --help                  # every command and flag\n```\n\nAdd `--json` to any command for the raw tool result, which is what a script\nwants:\n\n```sh\nradiochron networks --json | jq '.networks[] | select(.rssi_dbm > -60) | .ssid'\n```\n\n`radiochron tool <name> [--args '<json>']` reaches any tool the catalogue\npublishes, including ones with no friendly spelling:\n\n```sh\nradiochron tool ble_evaluate --args '{\"now_ms\":1717000000000}'\n```\n\nUnknown flags are refused rather than ignored, so a mistyped `--durations`\nfails loudly instead of silently running with a default.\n\n**Running with no arguments still serves MCP over stdio**, exactly as before, so\nevery existing client configuration keeps working. A terminal on stdin means a\nperson typed the name, and prints help instead; a pipe means a client, and\nspeaks the protocol. `radiochron mcp` forces the server explicitly.\n\nTwo commands are CLI-only, because they have no session to live in:\n`chronicle record` runs the recorder in the foreground until you stop it, and\n`chronicle path` prints where the journal is kept.\n\n## MCP versus Node (`radiochron-js`)\n\nThey share one Rust core and one incident classifier. They are not stacked.\n\n| Surface | Package | Speaks MCP? | Best for |\n|---|---|---|---|\n| MCP + CLI | `radiochron-mcp` | Yes (stdio) | Assistants, `radiochron doctor`, operator shell |\n| Node/npm | `radiochron` | No | Apps, Electron, services, CI probes |\n\nDesktop imports `radiochron` (npm) only. It must never spawn the MCP server for\ndiagnosis — that would duplicate collectors and let cause logic drift.\n\n### Same verdict, two entry points\n\n```sh\n# MCP / CLI — orchestrates collectors, then core::incident::classify\nradiochron doctor --json\n```\n\n```js\n// Node — same classifier, in-process native bridge\nimport { getRadioChronCoreClient } from 'radiochron';\n\nconst rc = getRadioChronCoreClient();\nconst report = await rc.diagnose({ includeBle: false });\nconsole.log(report.assessment, report.causes);\n```\n\n```js\n// Optional: portable transfer matching MCP incident exports\nimport { createIncidentBundle, readIncidentBundle } from 'radiochron';\n\nconst bytes = createIncidentBundle({\n  report,\n  producer: {\n    surface: 'node',\n    surface_version: '0.7.0',\n    core_version: '0.6.0'\n  }\n});\n// write bytes to a .rchron file, or round-trip:\nconst again = readIncidentBundle(bytes);\n```\n\nAn assistant that needs radio evidence should call MCP tools. An application\nthat already runs Node should call `radiochron` directly and skip the MCP\nprocess entirely.\n\n## Start with one tool\n\nUse `diagnose_incident` first (CLI alias: `radiochron doctor`). The tool\norchestrates collectors and asks the shared core classifier for one incident\nverdict. The response keeps independent sections for:\n\n- current Wi-Fi interfaces and association;\n- RF/environment analysis;\n- radio → authentication → DHCP → gateway → DNS → TCP → Internet stages;\n- Windows WLAN event history when available;\n- recent change-only chronicle entries;\n- an optional native BLE advertisement scan, normalized identities, retained\n  histories, and evidence-based findings.\n\nOne unavailable collector does not discard the rest of the incident. Each\nsection has `ok`, `data`, or an actionable `error`, and the top-level\n`problems` list is compact enough for an assistant to explain directly.\nTargets are never contacted unless the caller supplies them.\n\n## Tool surface\n\nSeventeen tools are portable. Windows exposes an eighteenth,\n`wifi_history`, backed by WLAN AutoConfig.\n\n| Tool | Purpose |\n|---|---|\n| `diagnose_incident` | Orchestrate Wi-Fi, connectivity, history, chronicle, and optional native BLE evidence in one compact response |\n| `wifi_status` | Current state of every WLAN interface |\n| `wifi_networks` | Nearby BSS records with real dBm, security, width, and load; summary or full detail |\n| `wifi_analyze` | Signal, contention, roaming, security, and scan-quality findings |\n| `wifi_history` (Windows) | Reconnect loops, key-exchange failures, and credential-mismatch evidence |\n| `wifi_sample` | Cancelable RSSI/rate/roaming sampling with progress |\n| `wifi_scan` | Native Wi-Fi refresh with per-interface completion/failure |\n| `connectivity_diagnose` | Separate radio, authentication, IP assignment, gateway, DNS, TCP, portal, TLS, quality, and Internet stages |\n| `chronicle_start` | Start the local rotating change-only JSONL recorder |\n| `chronicle_stop` | Stop and flush the recorder |\n| `chronicle_status` | Recorder state, path, counters, and latest error |\n| `chronicle_recent` | Recent entries from active and rotated files |\n| `ble_scan` | Scan native adapters without connecting, normalize advertisements, update histories, and return risk evidence |\n| `ble_identify` | Identify a caller-supplied advertisement and hash its payload |\n| `ble_tracker_reset` | Clear process-local BLE history and apply detector policy |\n| `ble_observe` | Add an externally collected timed observation |\n| `ble_histories` | First/last seen, recurrence, sensors, movement sessions, and RSSI summaries |\n| `ble_evaluate` | Time-based disappearance findings for expected identities |\n\n`ble_scan` uses WinRT on Windows, BlueZ on Linux, and CoreBluetooth on macOS.\nIt listens only for devices observed during the requested scan window, does\nnot perform GATT connections, and feeds the same privacy-minimized RadioChron\ntracker used by explicit `ble_observe` calls. iBeacon and Eddystone UID data\ncan provide stronger protocol identity; generic private addresses remain\nephemeral.\n\nOn macOS 11+, the host application or terminal launching the MCP process must\nhave Bluetooth permission. An app bundle needs\n`NSBluetoothAlwaysUsageDescription`; a terminal-launched server requires\nBluetooth access for that terminal in System Settings. Linux requires a\nrunning BlueZ service and access to the system D-Bus.\n\n## MCP behavior\n\n- Newline-delimited UTF-8 JSON-RPC 2.0 over stdio; stdout contains MCP frames only.\n- Negotiates both `2025-11-25` and `2025-06-18`, preferring the current revision.\n- Current tool definitions declare `execution.taskSupport: \"forbidden\"` because\n  this local stdio server uses normal cancelable requests rather than durable\n  experimental tasks.\n- Unknown methods and malformed call envelopes use JSON-RPC errors.\n- Tool input/radio/platform failures use `isError: true` so a model can correct\n  arguments or explain the platform problem.\n- Structured results are also serialized into text content for older clients.\n- Source files are architecture-gated at 300 lines; real stdio conformance\n  tests cover current and legacy lifecycle/catalog/error behavior.\n\nThe tools and resource request paths use the Tokio-free `mcport` runtime and\nits `blazingly-json` value/codec surface. RadioChron keeps only its strict\ninitialize/notification lifecycle locally. Native BLE collection uses the\nseparate `radiochron-native-ble` crate, which talks directly to WinRT, BlueZ\nD-Bus, and CoreBluetooth without `btleplug`, Tokio, or `futures`. The portable\n`radiochron` core remains independent of host Bluetooth APIs.\n\n## Safety and privacy\n\nSSIDs, BSSIDs, Bluetooth addresses, advertisement payloads, and event logs can\nbe sensitive. The server has no telemetry and sends nothing off the machine.\nThe chronicle writes only its rotating local JSONL file. Saved Wi-Fi passwords\nare never read.\n\nRSSI is signal evidence, not physical distance or direction. Private Bluetooth\naddresses can rotate, so clone/recurrence claims require protocol identity or\ncaller-provided identity. Native BLE scanning never connects to peripherals.\n\nThe MCP surface intentionally excludes plaintext Wi-Fi keys, adapter MAC\nchanges, adapter restarts, computer rename, active LAN sweeps, arbitrary shell\nexecution, and external AI review.\n\n## Release\n\nReleases are assembled from one green cross-platform CI run. The npm archive\nmust contain revision-matched binaries and provenance sidecars for all five\ntargets. An immutable version tag publishes the npm package through the\nprotected repository secret, then publishes the matching `server.json` to the\nofficial MCP Registry through GitHub OIDC. The npm credential is the masked,\ntag-gated `NPM_TOKEN` GitHub Actions secret; the MCP Registry uses no\nlong-lived token.\n\n## License\n\nLicensed under the [MIT License](LICENSE-MIT). The underlying `radiochron` Rust\ncore remains separately dual-licensed under MIT or Apache-2.0.\n",
  "bytes": 11606,
  "sha": "3a1dccfefafb3a733ddfee2fe861ed7d4b2770185234700a051ceafc72528f3f",
  "repo_slug": "sergii-ziborov/radiochron-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_sergii_ziborov_radiochron_196d58eb/readme"
}