Overview

The VAGUS Android app embeds an MCP server and exposes device capabilities as MCP resources and tools. It runs as a foreground service, connects to the relay over WebSocket, enforces user/governance policy, and streams capability updates to the connected agent.

Current product behavior is single-agent in UX, but core session/subscription handling already tracks session IDs and is structured for future multi-agent expansion.

Related docs: Node Client for CLI/MCP invocation patterns and Self-Hosted Relay for deployment and transport operations.

Architecture

Layer Primary Types Responsibility
UI + Service MainActivity, VagusForegroundService Operator controls, pairing UX, policy toggles, status/log visibility.
MCP Server McpServer, McpCodec, registries JSON-RPC/MCP routing, method dispatch, resource/tool advertisement, notifications.
Governance GovernanceEngine, ActionPolicyStore Permission gates, policy checks, rate/time windows, denial handling, audit events.
Capability Modules modules/* Implement concrete resources/tools backed by Android APIs.
Subscriptions SubscriptionManager, replay buffer/snapshot Track active subscriptions, manage module lifecycles, replay reconnect gaps.
Audit Logs AccessLogStore, Room DB Persist structured log entries, query/filter/export, retention pruning.

Runtime Lifecycle

  1. App/service starts and initializes app graph modules.
  2. MCP server starts and prepares subscription manager context.
  3. Pairing/session token is created or resumed.
  4. Relay transport opens and server creates current transport session ID.
  5. Client sends initialize then initialized.
  6. Server advertises current tools/resources and begins normal request/subscribe handling.
  7. On disconnect, subscriptions are cleaned up per session and reconnect logic applies.

Pairing and Transport

Pairing

  • 6-digit pairing code is generated and reserved through relay APIs.
  • Session token is persisted and used to build relay connect URL.
  • Session completion and agent display name are persisted.

Transport and Reconnect

  • WebSocket transport uses heartbeat ping notifications.
  • Reconnect uses exponential backoff with generation guards.
  • A reconnect marker notification (session/reconnect) is sent after successful reconnects.
  • Replay window is used to re-push recent subscription updates after reconnect.

MCP Surface (Server Methods and Notifications)

Handled Methods

  • initialize
  • initialized / notifications/initialized
  • tools/list
  • tools/call
  • resources/list
  • resources/read
  • resources/subscribe
  • resources/unsubscribe
  • relay/client_connected / relay/client_disconnected
  • ping

Outbound Notifications

  • notifications/resources/updated
  • notifications/resources/list_changed
  • notifications/tools/list_changed
  • session/reconnect

Trace IDs

Outbound responses and notifications include trace_id when available. Request-derived trace IDs are propagated across read/call/subscribe handling and appear in both protocol messages and audit logs.

Current Resources

Resource Module Notes
vagus://session/infoSessionInfoModulePairing/session metadata and agent name state.
vagus://sensors/motionMockMotionModuleMotion context stream.
vagus://sensors/activityActivityRecognitionModulePhysical activity recognition.
vagus://sensors/activity_recognitionActivityRecognitionModuleAlias resource for activity data.
vagus://sensors/locationLocationModuleLocation context.
vagus://sensors/environmentEnvironmentModuleAmbient/device environment context.
vagus://inference/attentionEnvironmentModuleAttention inference stream.
vagus://inference/indoor_confidenceEnvironmentModuleIndoor confidence inference.
vagus://inference/sleep_likelihoodEnvironmentModuleSleep likelihood inference.
vagus://inference/notification_timingEnvironmentModuleNotification timing inference.
vagus://device/connectivityConnectivityModuleNetwork state and connectivity context.
vagus://device/screenScreenStateModuleScreen and lock state context.
vagus://device/batteryBatteryModuleBattery level/charging state.
vagus://device/notificationsNotificationsReadModuleRecent observed notification events.
vagus://device/clipboardClipboardModuleCurrent clipboard text context.
vagus://io/type_*IoSensorsModuleDynamic per-sensor onboard I/O resources.

Current Tools

Tool Module Notes
notifyNotifyToolModulePosts Android notifications. Required: title, body; max lengths 200/1000. Gated by perm_notify and Android notification permission on API 33+.
clipboard/setClipboardModuleWrites text to clipboard. Required: content (max 10000 chars). Gated by perm_clipboard.
haptic/pulseHapticsModuleSingle haptic pulse. Optional: durationMs (10-5000; defaults to 120). Gated by perm_haptics and Android VIBRATE permission.
haptic/patternHapticsModulePattern-based vibration. Optional: pattern (non-negative integer array). Gated by perm_haptics and Android VIBRATE permission.
speakTtsModuleText-to-speech output. Required: text (max 5000). Optional: language, rate (0.25-2.0), pitch (0.5-2.0), voice/voice_id, interrupt. Gated by perm_tts.
sms/sendActionToolsModuleSend SMS. Required: to, body (max 2000). Gated by perm_sms_send + Android SEND_SMS; additionally constrained by SMS policy (allowlist/body length/rate/time/consent).
intent/open_urlActionToolsModuleOpen URL in browser. Required: url with http/https; policy may enforce HTTPS-only. Gated by perm_open_url and Open URL policy (rate/time/consent).
calendar/create_eventActionToolsModuleCreate calendar event. Required: title; optional startTimeMs, endTimeMs, location, description, allDay. Gated by perm_calendar_create + Android calendar permissions and calendar policy (future start/duration/rate/time/consent).
io/set_subscription_resolutionActionToolsModuleSet cadence for all vagus://io/type_* subscriptions using resolutionMs (allowed: 1500, 10000, 30000, 60000, 90000, 120000, 300000). Gated by perm_agent_set_io_resolution (default off).
infer/set_subscription_resolutionActionToolsModuleSet cadence for infer subscriptions using resolutionMs (allowed: 1500, 10000, 30000, 60000, 90000, 120000, 300000). Gated by perm_agent_set_infer_resolution (default off).
agent/set_nameSessionInfoModuleSet persistent agent display name. Required: name (max 64); empty string clears the saved name. Gated by perm_session.

Governance and Policy

Every resource read/subscribe and tool call passes through governance checks before execution.

Controls

  • Android permission gate (where applicable).
  • Per-capability and per-sensor user toggles.
  • Agent control for I/O cadence is gated by perm_agent_set_io_resolution (default off).
  • Agent control for infer cadence is gated by perm_agent_set_infer_resolution (default off).
  • Policy windows (active hours), rate limits, and input constraints.
  • Optional ask/deny one-time approval for selected tools.

I/O Master

perm_io is the master override for onboard sensor resources and is combined with per-sensor toggles (perm_io_sensor_*).

Subscriptions and Replay

  • Subscriptions are tracked by (sessionId, resourceId).
  • Module lifecycles are managed automatically based on active subscription counts/dependencies.
  • Reconnect gap handling uses event ring buffer + snapshot replay.
  • Agent page includes active subscription management UI with per-row cancel and cancel all.

Subscriptions vs Read-Only

Not all resources support streaming subscriptions. Use this as the server-side source of truth for resources/subscribe behavior.

Resource Read Subscribe Notes
vagus://session/infoYesYesSnapshot + stream of session/app status updates.
vagus://sensors/motionYesYesHigh-frequency stream for motion context.
vagus://sensors/locationYesYesEvent-driven location updates from platform location callbacks.
vagus://device/clipboardYesNoRead-only snapshot resource. Subscribe is rejected.
vagus://device/screenYesYesEvent-driven subscription (screen on/off/user present).
vagus://device/notificationsYesYesEvent-driven subscription (posted/removed notification events).
vagus://device/batteryYesYesLow-frequency poll (~5 minutes).
vagus://device/connectivityYesYesEvent-driven subscription (network callback).
vagus://sensors/activity, vagus://sensors/activity_recognitionYesYesCadence controlled by Infer subscription resolution setting.
vagus://sensors/environment, vagus://inference/*YesYesCadence controlled by Infer subscription resolution setting.
vagus://io/type_*YesYesCadence controlled by I/O subscription resolution setting.

Subscription capability may still be denied at runtime by governance toggles, Android permissions, or policy.

Onboard I/O Sensors

The I/O page discovers hardware sensors at runtime and exposes each sensor as a dedicated MCP resource.

  • Sensors grouped by UI tabs: Motion & Pose, Environment, Location & Heading, Other, Uncalibrated.
  • Per-sensor toggle state and live readout are shown in app UI.
  • Uncalibrated/raw feeds are treated as advanced and disabled by default.
  • Vendor-specific sensor types are supported through dynamic resource IDs.

Observability and Logs

Structured Log Model

  • Severity: INFO, WARN, ERROR, SECURITY.
  • Category: Resource, Subscription, Tool, Policy, System.
  • Context fields include agentName, sessionId, and traceId.

Storage and Retention

  • Room-backed persistent log store.
  • Batched background-safe DB writes via queued flush pipeline.
  • Retention pruning: max rows and max age.

Query and Export

  • Internal query API supports time range, category/severity filters, search, and pagination.
  • Status page includes filter pills, search box, paging, and time-range chips.
  • Export current filtered view as JSON or CSV from app UI.

Query/export API is currently app-internal and is not exposed as MCP tool/resource yet.

Security and Privacy

  • Least-privilege posture through explicit Android permission and feature toggle gates.
  • High-risk tools (SMS, URL opening, calendar writes) are policy constrained and auditable.
  • Denials and policy violations are logged as structured policy events.
  • Session cleanup unsubscribes active streams on disconnect/session close.

Troubleshooting

Common Issues

SymptomLikely CauseAction
Method denied Governance toggle/policy/permission block Inspect Event Log policy/system filters, then review capability policy settings.
No resource updates No active subscription or disconnected transport Check active subscriptions card and transport status.
Missing capability in tools/resources list Disabled toggle or missing Android permission Enable toggle and grant runtime permission.
Reconnect loops Relay/network instability Review system lifecycle logs and relay URL configuration.