Pulse

Pulse

Connects live Wear OS heart-rate data and conversation transcripts to AI agents through MCP, enabling agents to observe sessions, derive stress and speech signals, and deliver coaching responses.

Category
访问服务器

README

Pulse

A consent-aware nervous system for AI agents.

Pulse connects live Wear OS heart-rate data and Android conversation transcripts to AI agents through the Model Context Protocol (MCP). Agents can observe a session, derive evidence-backed speech and stress signals, review synchronized reports, and deliver coaching responses through the wearer's phone.

[!WARNING] Pulse is an experimental prototype, not a medical device. Its stress signal is a deterministic heart-rate heuristic and must not be used for diagnosis, treatment, safety-critical decisions, or emergency response.

Why Pulse?

Most AI agents only know what a user types. Pulse gives an agent a real-time, session-scoped view of what is happening around the wearer:

  • Live physiological context from Wear OS Health Services, including freshness and sensor availability.
  • Conversation context from streaming transcription, with pace, turn length, and silence metrics.
  • Deterministic stress signals derived from heart-rate changes rather than opaque model inference.
  • Durable event delivery across watch, phone, and backend disconnects, with acknowledgements and duplicate suppression.
  • MCP-native access through typed resources, tools, prompts, and an interactive session-report widget.
  • On-demand coaching requested from the watch and delivered after conversational silence.
  • Hardware-free development through canonical fixtures and simulated device actions.

How It Works

flowchart LR
    W[Wear OS watch<br/>heart rate + requests] -->|Wear Data Layer| P[Android phone<br/>queue + transcription]
    P -->|WebSocket events| B[Pulse backend<br/>validation + SQLite]
    B --> S[Session intelligence<br/>stress + speech metrics + reports]
    S --> M[NitroStack MCP server]
    M --> A[AI agent / MCP host]
    A -->|coaching action| B
    B -->|TTS command| P
    P -->|spoken advice| E[Wearer]

The phone owns the session clock and durably queues events. The backend validates strict versioned contracts, stores events transactionally, indexes final transcripts with SQLite FTS5, and derives repeatable session metrics. The MCP server exposes that state without coupling the device pipeline to a specific agent host.

Quick Start

The default configuration uses fixture events, simulated vitals, and simulated device actions. No watch, phone, cloud API key, or native build toolchain is needed.

Prerequisites

  • Node.js 20 or 22 LTS
  • npm 9 or newer
  • NitroStudio for interactive MCP testing

1. Install

git clone https://github.com/tejasai2007/pulse.git
cd pulse
npm ci
npm --prefix src/widgets ci

Create the local environment file:

cp .env.example .env

On Windows PowerShell, use Copy-Item .env.example .env instead.

The sample binds the backend to 0.0.0.0 so physical devices can reach it. For simulator-only use, set BACKEND_HOST=127.0.0.1 in .env before starting the backend.

2. Start Pulse

Run the backend and NitroStack development environment in separate terminals:

npm run dev:backend
npm run dev

The backend is reachable locally at http://127.0.0.1:8787. Check its runtime health:

curl http://127.0.0.1:8787/health

Without OPENAI_API_KEY, the health response reports the copilot provider as degraded and uses deterministic fallback advice; the local fixture path remains available.

3. Send Fixture Events

In a third terminal:

npm run mock:events

Each event prints a JSON acknowledgement. The fixture creates session-fixture-001 with one simulated heart-rate sample and one final transcript segment. Event IDs are stable and deduplicated, so rerunning the command is safe.

npm run dev keeps TypeScript and the widgets rebuilt, but it does not launch the MCP entry point. Open the project in NitroStudio and launch dist/index.js. For a stdio MCP host, run npm run build, set its working directory to the cloned repository, and configure the host command as node --env-file=.env dist/index.js.

Then try:

  • phase_zero_probe with message: "hello" to verify MCP connectivity.
  • session://latest/transcript to read the fixture transcript.
  • search_sessions with status: "calibrating" to find the fixture session.
  • generate_session_report with sessionId: "session-fixture-001" to render the report widget in a compatible host.

MCP Surface

Resources

Resource Purpose
session://latest/transcript Most recently ingested final transcript segment
session://current/transcript Ordered transcript for the current session
session://{sessionId}/transcript Stored transcript for a selected session
session://current/vitals Consent-checked latest BPM, freshness, and rolling window
session://current/stress Consent-checked deterministic stress state and supporting metrics
session://current/speech-metrics Speech pace, longest turn, and current silence
session://current/context Consent-checked wearer-provided goals and boundaries
session://{sessionId}/report Synchronized session summary and evidence timeline

Tools

Tool Purpose
get_current_session_metrics Read live vitals, stress, and speech metrics together
get_current_transcript Read a bounded selection of current transcript segments
search_sessions Search transcript text, dates, and lifecycle status
generate_session_report Build an evidence-only report for a stored session
haptic_nudge Request a predefined haptic intervention
whisper_coach Queue TTS coaching after conversational silence
get_pending_copilot_request Claim an advice request initiated from the watch
copilot_advice Deliver grounded advice for a claimed request
phase_zero_probe Verify connectivity between an MCP host and Pulse

Pulse also provides the review_session and handle_copilot_request prompts. Canonical schemas and delivery semantics are documented in docs/contracts-v1.md.

Conversation Copilot

Conversation Copilot supports two execution modes:

  • COPILOT_MODE=automatic asks an OpenAI-compatible Responses API for one concise suggestion. Set OPENAI_API_KEY only on the backend. Requests use store: false, and deterministic metric-based advice is used if no key is configured or the provider fails. The current system prompt is specifically tailored to presenting Pulse on stage, not general conversations.
  • COPILOT_MODE=mcp leaves reasoning to an MCP host. The host claims the watch request, reads the consented session evidence, and responds through copilot_advice. The current Android flow does not create session context or grant read:context, so context-dependent MCP mode requires those events to be supplied separately.

Set COPILOT_ENABLED=false to disable watch-requested advice. Backend-queued TTS pauses transcription, waits for 1.5 seconds of conversational silence, plays through the selected phone audio route, and then resumes capture. Local probe and heart-rate alerts speak immediately.

Android and Wear OS

Additional Prerequisites

  • Android Studio with Android SDK 35
  • JDK 17
  • Android phone running API 31 or newer
  • Wear OS device running API 30 or newer with Health Services and Google Play services
  • A paired phone and watch; Bluetooth earbuds are optional
  • A Deepgram API key for live cloud transcription

Open android in Android Studio and add machine-specific values to the ignored android/local.properties file:

BACKEND_URL=http://10.0.2.2:8787
VITALS_SOURCE=simulated
AUDIO_INPUT=phone
TRANSCRIPTION_MODE=fixture
# DEEPGRAM_API_KEY=restricted-development-key

10.0.2.2 reaches the host machine from an Android emulator. A physical phone must use a backend URL reachable on its network, such as http://192.168.1.10:8787. Debug builds allow local cleartext traffic; release builds require HTTPS/WSS.

From the android directory, build and install both apps:

.\gradlew.bat :phone:installDebug :watch:installDebug

On macOS or Linux, use sh ./gradlew (the tracked wrapper is not executable).

For the real device path:

  1. Set VITALS_SOURCE=watch in android/local.properties.
  2. Add a restricted development DEEPGRAM_API_KEY to enable Deepgram streaming. It is compiled into every APK variant, so never use a production credential or distribute that APK.
  3. Point BACKEND_URL at the reachable Pulse backend.
  4. Grant microphone permission on the phone and health/body-sensor permissions on the watch.
  5. Start a session from either device and verify watch, backend, and audio-route status on the phone.

The watch captures heart rate through a foreground Health Services exercise session. It sends urgent Data Layer items to the phone and retains unacknowledged samples across temporary disconnects. The phone persists its backend replay queue and reconnects with bounded backoff.

[!NOTE] The Android app currently ignores TRANSCRIPTION_MODE: when microphone permission and foreground startup allow capture, a non-empty DEEPGRAM_API_KEY enables Deepgram streaming. On-device transcription is not implemented, and fixture transcripts come from npm run mock:events, not from Android. DEVICE_ACTIONS is a backend setting; Android's generated value is unused. Real backend-triggered watch haptic delivery is also incomplete.

[!CAUTION] The phone currently triggers a local watch vibration and spoken warning after heart rate remains above 85 BPM for 10 seconds outside exercise mode. This prototype alert does not check MCP consent scopes or DEVICE_ACTIONS and is not medically validated. Do not use the real-vitals path with people until this behavior has been reviewed or disabled.

Hardware validation steps and the latest recorded results are in docs/phase-zero-results.md.

Session Report Widget

The report tool is connected to an MCP Ext App built with Next.js and React. To develop it separately:

npm --prefix src/widgets ci
npm --prefix src/widgets run dev

The development server runs at http://localhost:3001. Build it with:

npm --prefix src/widgets run build

Configuration

Copy .env.example to .env for development defaults. The default BACKEND_HOST=0.0.0.0 exposes the unauthenticated backend to the local network; use 127.0.0.1 when device access is not required.

Variable Default Description
NODE_ENV development Runtime environment
LOG_LEVEL info debug, info, warn, or error
NITROSTACK_APP_MODE universal NitroStack process mode used by the local development path
BACKEND_HOST 0.0.0.0 Backend bind address
BACKEND_PORT 8787 Backend HTTP/WebSocket port
BACKEND_URL http://127.0.0.1:8787 in .env.example Backend URL used by the MCP server and fixture sender
DATABASE_PATH data/pulse.sqlite SQLite database path
VITALS_SOURCE simulated watch or simulated
AUDIO_INPUT phone earbuds or phone route label
TRANSCRIPTION_MODE fixture Backend runtime label; Android currently ignores it
DEVICE_ACTIONS simulated real or simulated intervention delivery
COPILOT_ENABLED true Enable watch-requested advice
COPILOT_MODE automatic automatic or mcp reasoning path
OPENAI_API_KEY unset Backend-only key for automatic copilot advice
OPENAI_MODEL gpt-4.1-mini OpenAI-compatible model name
OPENAI_BASE_URL https://api.openai.com/v1 OpenAI-compatible API base URL
DEEPGRAM_API_KEY unset Deepgram key for live Android transcription
STORE_RAW_AUDIO false Must remain false; any other enabled value is rejected

Do not commit .env or android/local.properties.

Privacy and Safety

Pulse processes health-adjacent and conversational data. Understand the current boundary before using real data:

  • Starting an Android session attempts microphone capture when permission and foreground-service startup allow it. If the APK contains a non-empty DEEPGRAM_API_KEY, captured audio is streamed to Deepgram regardless of TRANSCRIPTION_MODE. Pulse does not intentionally persist or expose raw audio through MCP.
  • Final transcripts, heart-rate samples, consent events, and derived metrics are stored in local SQLite without application-level encryption. The phone also keeps pending and rejected event payloads in unencrypted SharedPreferences.
  • Automatic copilot mode may send up to 20 recent transcript segments, speech metrics, and consented vital/stress summaries to the configured OpenAI-compatible provider. It does not currently send wearer-provided session context.
  • Current vitals, stress, context, and backend intervention paths enforce their defined consent scopes. Consent enforcement is not uniform across every transcript and historical HTTP/MCP read, and the phone's local high-heart-rate alert bypasses those scopes.
  • Backend HTTP and WebSocket endpoints do not currently implement transport authentication. Bind only to trusted development networks.
  • Data retention and session deletion controls are not yet implemented.
  • Logs redact common secret, authorization, transcript, text, and audio fields, but logs should still be treated as sensitive.

Use synthetic data for development. Never include real transcripts, health data, credentials, or identifying logs in issues or pull requests.

Project Structure

pulse/
|-- src/
|   |-- backend/          # HTTP/WS ingestion, SQLite, metrics, reports
|   |-- contracts/        # Canonical Zod schemas and fixtures
|   |-- observability/    # Structured redacting logger
|   |-- widgets/          # Next.js MCP Ext App
|   `-- *.ts              # MCP resources, tools, prompts, and registration
|-- android/
|   |-- contracts/        # Shared Kotlin transport contracts
|   |-- phone/            # Session, audio, queue, and backend bridge
|   `-- watch/            # Wear UI, Health Services, and Data Layer
|-- fixtures/events/      # Canonical JSON contract fixtures
|-- docs/                 # Contracts and validation records
`-- data/                 # Local SQLite state, ignored by Git

Development

Command Purpose
npm run dev Rebuild TypeScript on change and run the widget development server
npm run dev:backend Build and run the backend with .env
npm run mock:events Send the canonical fixture sequence
npm run typecheck Type-check TypeScript without emitting files
npm run build Build the MCP server and backend
npm test Build and run contract, backend, metric, report, and server tests
npm start Start the built MCP server
npm run start:backend Start the previously built backend

Validate all Android modules from the android directory:

.\gradlew.bat --no-daemon "-Pkotlin.incremental=false" :contracts:testDebugUnitTest :phone:testDebugUnitTest :phone:assembleDebug :watch:assembleDebug

There is currently no configured lint command or CI workflow.

Current Limitations

  • Pulse is a prototype and has no production deployment configuration.
  • HTTP/WebSocket ingress authentication and uniform read authorization are unfinished.
  • Real backend-to-watch haptic command delivery is incomplete.
  • Android ignores TRANSCRIPTION_MODE; on-device transcription is not implemented.
  • Android ignores its generated DEVICE_ACTIONS value; intervention simulation is controlled by the backend.
  • The local high-heart-rate alert bypasses consent and device-action settings.
  • Session retention, deletion, and cross-session trend controls are not implemented.
  • The device-health widget source is present but is not registered in the active MCP module.
  • Physical sensor quality, private earbud routing, and vibration behavior require manual device testing.

Contributing

Issues and focused pull requests are welcome. Before opening a PR:

  1. Run npm run typecheck and npm test.
  2. Run npm --prefix src/widgets test for widget changes.
  3. Run the Android validation command for Kotlin or contract changes.
  4. Describe any hardware used and separate automated evidence from manual device observations.
  5. Keep fixtures deterministic and update both TypeScript and Kotlin consumers when changing a boundary contract.

For security reports, do not disclose sensitive data in a public issue. Submit a sanitized report and request a private contact channel.

License

This repository does not currently include a license. Its source is available for inspection, but it is not yet distributed under an open-source license.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选