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
- App/service starts and initializes app graph modules.
- MCP server starts and prepares subscription manager context.
- Pairing/session token is created or resumed.
- Relay transport opens and server creates current transport session ID.
- Client sends
initializetheninitialized. - Server advertises current tools/resources and begins normal request/subscribe handling.
- 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
initializeinitialized/notifications/initializedtools/listtools/callresources/listresources/readresources/subscriberesources/unsubscriberelay/client_connected/relay/client_disconnectedping
Outbound Notifications
notifications/resources/updatednotifications/resources/list_changednotifications/tools/list_changedsession/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/info | SessionInfoModule | Pairing/session metadata and agent name state. |
vagus://sensors/motion | MockMotionModule | Motion context stream. |
vagus://sensors/activity | ActivityRecognitionModule | Physical activity recognition. |
vagus://sensors/activity_recognition | ActivityRecognitionModule | Alias resource for activity data. |
vagus://sensors/location | LocationModule | Location context. |
vagus://sensors/environment | EnvironmentModule | Ambient/device environment context. |
vagus://inference/attention | EnvironmentModule | Attention inference stream. |
vagus://inference/indoor_confidence | EnvironmentModule | Indoor confidence inference. |
vagus://inference/sleep_likelihood | EnvironmentModule | Sleep likelihood inference. |
vagus://inference/notification_timing | EnvironmentModule | Notification timing inference. |
vagus://device/connectivity | ConnectivityModule | Network state and connectivity context. |
vagus://device/screen | ScreenStateModule | Screen and lock state context. |
vagus://device/battery | BatteryModule | Battery level/charging state. |
vagus://device/notifications | NotificationsReadModule | Recent observed notification events. |
vagus://device/clipboard | ClipboardModule | Current clipboard text context. |
vagus://io/type_* | IoSensorsModule | Dynamic per-sensor onboard I/O resources. |
Current Tools
| Tool | Module | Notes |
|---|---|---|
notify | NotifyToolModule | Posts Android notifications. |
clipboard/set | ClipboardModule | Writes text to clipboard. |
haptic/pulse | HapticsModule | Single haptic pulse. |
haptic/pattern | HapticsModule | Pattern-based haptics. |
speak | TtsModule | Text-to-speech output. |
sms/send | ActionToolsModule | Send SMS, subject to policy and permission. |
intent/open_url | ActionToolsModule | Open URL in browser with policy checks. |
calendar/create_event | ActionToolsModule | Create calendar event. |
agent/set_name | SessionInfoModule | Set persistent agent display name. |
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.
- 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.
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, andtraceId.
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
| Symptom | Likely Cause | Action |
|---|---|---|
| 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. |