ADR-263 (@ruvnet/ruview 0.2.0), O1-O9: - claim-check fails closed on empty input (CLI exit 2, empty_text tool error) - MCP stdio server dispatches tools/call asynchronously (promise-based spawn); ping answers while a 3s fake verify runs — pinned by new e2e test - optionalDependencies dropped: cold npx installs exactly 1 package (MEASURED: was 4 pkgs/620kB/71 files via npm i in a clean prefix) - bounded rolling output tails replace spawnSync 1MiB maxBuffer - node_monitor port passed via sys.argv, never spliced into python -c source - serverInfo.version read from package.json; resources/prompts stubs - skills single-sourced: prepack sync script generates .claude/skills/ copies - which() = memoized dep-free PATH scan - tools underscore-canonical (ruview_claim_check, ...) + dotted aliases - guardrail precision: word-boundary map/f1/auc/iou, code-span + F1/O2 label scrubbing, quantitative-claims-only; packaging reproducer hints - 30/30 tests (was 17), incl. concurrency e2e + fail-open regression pins ADR-264 (@ruvnet/rvagent 0.2.0), O1-O9: - exports fixed: types-first, phantom dist/index.cjs require target removed - tarball map-free: 127,704B unpacked / 46 files / 0 maps (MEASURED, npm pack --dry-run; was 188kB incl. 44 maps referencing unshipped src) - Streamable HTTP actually wired behind RVAGENT_HTTP_PORT: one transport + one MCP server per session (mcp-session-id routing), 1MiB body cap (413), port-aware localhost origin gate; dual-transport description now true - tools renamed underscore-canonical with dotted router-only aliases - single Zod validation gate; advertised inputSchema generated from the same Zod source (zod-to-json-schema) - train_count: parent log fds closed (was leaking 2/job); job records persisted to <jobsDir>/<id>.json (job_status survives restarts); bounded log-tail reads - detectCogBinary probes its candidates instead of dead-coding them - version from package.json; @types/express dropped; @types/jest -> 29 - README rewritten to match reality (no phantom subcommands/policy layer) - 99/99 jest tests (incl. new session/body-cap suite + previously-broken manifest suite); stdio handshake + HTTP session flow smoke-tested live ADR-265 D1-D4: - .github/workflows/npm-packages.yml: 3-package x Node 20/22 gate — tests, version-literal grep (D3), pack-content/size gate, tarball-install smoke test (catches the ADR-264 F1 class), README claim-check (D4) - .github/workflows/ruview-npm-release.yml: publish from CI only with npm publish --provenance - @ruv/ruview-cli bin renamed ruview-cli (ruview bin belongs to @ruvnet/ruview); version single-sourced - ci.yml NODE_VERSION 18 -> 20 ADR statuses updated to Accepted/implemented; harness manifest re-pinned; ADR-263/264/265 + both package READMEs pass claim-check. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WrGfTGKv1oWZ6iwXZACULz
4.7 KiB
@ruvnet/rvagent — SENSE-BRIDGE MCP Server
SENSE-BRIDGE is a dual-transport Model Context Protocol (MCP) server that bridges the RuView WiFi-DensePose sensing stack to AI agents (Claude Code, Cursor, ruflo swarms, and any MCP-compatible client).
Install once; AI agents can then call ruview_presence_now, ruview_vitals_get_heart_rate, ruview_bfld_last_scan, and more — without writing HTTP or WebSocket client code.
Quickstart
# 1. Add to Claude Code (stdio transport — the default)
claude mcp add rvagent -- npx -y @ruvnet/rvagent
# 2. Or run directly
RUVIEW_SENSING_SERVER_URL=http://cognitum-v0:3000 npx @ruvnet/rvagent
# 3. Streamable HTTP (remote agents, ruflo swarms) — explicit opt-in
RUVIEW_SENSING_SERVER_URL=http://cognitum-v0:3000 \
RVAGENT_HTTP_TOKEN=your-secret \
RVAGENT_HTTP_PORT=3001 npx @ruvnet/rvagent
# POST JSON-RPC to http://127.0.0.1:3001/mcp (initialize first; then send the
# returned mcp-session-id header on every request)
Requirements: Node.js >= 20. The wifi-densepose-sensing-server Rust binary must be reachable at RUVIEW_SENSING_SERVER_URL (default http://localhost:3000).
Tools
Canonical tool names are underscore-form (ADR-264 — host tool-name validators
commonly enforce ^[a-zA-Z0-9_-]{1,64}$). The pre-0.1.1 dotted names
(ruview.presence.now, …) are still accepted at call time as deprecated
aliases; tools/list advertises the underscore form only.
| Tool | Description | ADR |
|---|---|---|
ruview_csi_latest |
Latest 56×20 CSI window from the sensing-server | ADR-101/102 |
ruview_pose_infer |
Single-shot 17-keypoint pose inference via cog binary | ADR-101 |
ruview_count_infer |
Single-shot person-count inference via cog binary | ADR-103 |
ruview_registry_list |
Cognitum edge module registry (category/search filters) | ADR-102 |
ruview_train_count |
Kick off a count-cog training run (background job) | ADR-103 |
ruview_job_status |
Poll a training job (persists across server restarts) | ADR-103 |
ruview_presence_now |
Current occupancy: present, n_persons, confidence |
ADR-124 §4.1 |
ruview_vitals_get_breathing |
Breathing rate bpm (null if unavailable) | ADR-124 §4.1 |
ruview_vitals_get_heart_rate |
Heart rate bpm (null if unavailable) | ADR-124 §4.1 |
ruview_vitals_get_all |
Full EdgeVitalsMessage surface |
ADR-124 §4.1 |
ruview_bfld_last_scan |
Latest BFLD scan: identity_risk_score, privacy_class, n_frames |
ADR-118/124 |
ruview_bfld_subscribe |
Subscribe to ruview/<node_id>/bfld/* events for duration_s seconds |
ADR-122/124 |
| (roadmap, ADR-124 §4.1/4.1a) | pose.latest, primitives.*, node.*, vector.*, and the policy.* governance layer are catalogued in src/schemas/ but not yet implemented |
ADR-124 |
Transport security (ADR-124 §6, hardened per ADR-264):
- stdio (default): process-level isolation — no auth needed for local Claude Code / Cursor.
- Streamable HTTP (
/mcp, opt-in viaRVAGENT_HTTP_PORT): one transport + one MCP server per session (routed bymcp-session-id), Origin validation (localhost on any port allowed; anything else → 403), optional bearer token (RVAGENT_HTTP_TOKEN→ 401 on mismatch), 1 MiB request-body cap (413), binds127.0.0.1by default per MCP spec.
Schema validation: each tool declares one Zod schema; the CallTool gate parses exactly once and the advertised JSON Schema is generated from the same Zod source. Invalid arguments return McpError(InvalidParams) rather than a wrapped string.
ADR cross-reference
| ADR | Decision |
|---|---|
| ADR-124 | SENSE-BRIDGE: dual-transport MCP server + ruvector npm + ruflo integration |
| ADR-264 | npm deep review — exports fix, map-free tarball, naming, session-per-transport |
| ADR-118 | BFLD pipeline — source of bfld_last_scan wire format |
| ADR-122 | MQTT topic routing ruview/<node_id>/bfld/* |
| ADR-115 | EdgeVitalsMessage WebSocket surface (ws.py:74-88 parity) |
| ADR-055 | Sensing-server REST API (/api/v1/*) |
Development
cd tools/ruview-mcp
npm install
npm run build # tsc
npm test # jest — 99 tests across 7 suites
Source: tools/ruview-mcp/src/. Tests: tools/ruview-mcp/tests/.
Tracking issue: #787.