AdventedHUD
by av151318
README.md
# AdventedHUD
**Agent-Driven Personal Planner — MCP Service (v1.4.1)**
AdventedHUD is an MCP service that turns an LLM agent into a **personal planner**. It provides agents with atomic context (your roles, goals, mission, and a FranklinCovey decision matrix) and routes classified items to Obsidian as the source of truth, with optional projection to Google Calendar and Google Tasks.
Exposes HTTP routes and JSON-RPC MCP on port **8200** by default.
---
## Table of Contents
- [Architecture](#architecture)
- [Quick Start](#quick-start)
- [Environment Reference](#environment-reference)
- [Auth](#auth)
- [MCP Tool Surface](#mcp-tool-surface)
- [HTTP Route Parity](#http-route-parity)
- [Onboarding Ritual](#onboarding-ritual-v141)
- [Agent Harness Compatibility](#agent-harness-compatibility)
- [AdventedOS Context](#adventedos-context)
- [Project Structure](#project-structure)
- [Docs](#docs)
- [Tests](#tests)
- [License](#license)
---
## Architecture
AdventedHUD was built to slot into a **three-layer** architecture, with **AdventedOS** as the reference deployment. The diagram below shows the full flow and where each component lives.
```
+------------------------------------------------------------------+
| Agent / LLM |
| (Claude, GPT, or any MCP-capable model that can call |
| tools sequentially based on mcp_meta instructions) |
+---------------------------+--------------------------------------+
| JSON-RPC MCP (hud.brief, hud.ingest,
| hud.project, hud.onboarding, hud.mcp)
v
+------------------------------------------------------------------+
| Open WebUI (OWUI) -- Optional UI |
| Tool server layer. Discovers tools from HUD's /openapi.json |
| Manages conversation state, user auth to the proxy. |
+---------------------------+--------------------------------------+
| HTTP (routed through proxy)
v
+------------------------------------------------------------------+
| AdventedOS Proxy (port 52415) |
| Tailnet entry -- handles: |
| * MCP tool discovery (proxies /openapi.json from HUD) |
| * Route orchestration (HUD, model inference, etc.) |
| Does not inject X-HUD-Admin-Key -- clients send the header. |
| Not required to run HUD -- any reverse proxy or direct |
| HTTP access works. |
+---------------------------+--------------------------------------+
| HTTP / JSON-RPC (X-HUD-Admin-Key
| or X-HUD-Agent-Key)
v
+------------------------------------------------------------------+
| AdventedHUD (port 8200) |
| |
| +----------+ +----------+ +----------+ +---------------+ |
| | Brief | | Ingest | | Project | | Onboarding | |
| | (context)| | (create) | |(approve/ | | (soul + | |
| | | | | | reject/ | | atomic) | |
| | | | | | retract/ | | | |
| | | | | | update) | | | |
| +----+-----+ +----+-----+ +----+-----+ +-------+------+ |
| | | | | |
| +-------------+-------------+-----------------+ |
| | | |
| v v |
| +------------------------------+ |
| | Ingest/Project Pipeline | |
| | (classification gate, | |
| | projection dispatch) | |
| +---------------+--------------+ |
+-------------------------------+----------------------------------+
|
+------------------+------------------+
v v v
+--------------------+ +--------------+ +--------------+
| Obsidian | | Google | | Google |
| Vault | | Calendar | | Tasks |
| (source of | | (projected) | | (projected) |
| truth) | | | | |
+--------------------+ +--------------+ +--------------+
```
### Flow Summary
1. **Agent classifies** user input using context from `hud.brief` (roles, goals, decision matrix)
2. **Agent calls** `hud.ingest` with classified item (role_ref, goal_ref, priority_class, semantic_type, google_target)
3. **HUD persists** to Obsidian first -- that's the source of truth
4. **On approval**, HUD projects to Google Calendar/Tasks via OAuth
5. The **AdventedOS proxy** sits between OWUI and HUD when deployed in reference mode -- Tailnet entry on :52415. It does not inject HUD keys; clients send `X-HUD-Admin-Key` or `X-HUD-Agent-Key`. In that stack HUD binds `127.0.0.1:8001` only
---
## Quick Start
### Requirements
- Docker (recommended) **or** Python 3.10+
- A Google Cloud project with Calendar and Tasks APIs enabled (for projection -- optional)
- An Obsidian vault (optional -- HUD creates one)
### Install & Run (Docker)
```bash
# Clone the repo
git clone https://github.com/av151318/AdventedHUD.git
cd AdventedHUD
# Build the image
docker build -t adventedhud .
# Run with defaults (port 8200)
docker run -d -p 8200:8200 \
-e HUD_ADMIN_API_KEY=your-secret-key \
--name adventedhud \
adventedhud
```
```bash
# Verify it's alive
curl -sS http://127.0.0.1:8200/health
```
To pass additional environment variables, append `-e VAR=value` flags to the `docker run` command. For persistent data, mount a volume:
```bash
docker run -d -p 8200:8200 \
-e HUD_ADMIN_API_KEY=your-secret-key \
-e HUD_ALLOW_WRITES=true \
-v /path/to/data:/app/data \
--name adventedhud \
adventedhud
```
### Install & Run (native)
```bash
# Clone the repo
git clone https://github.com/av151318/AdventedHUD.git
cd AdventedHUD
pip install -r requirements.txt
export HUD_ADMIN_API_KEY=your-secret-key
python -m hud.main
```
### Wire Up an Agent
HUD's primary interface is JSON-RPC MCP. An agent calls five methods:
```bash
curl -sS -X POST http://127.0.0.1:8200/hud/mcp \
-H 'Content-Type: application/json' \
-H "X-HUD-Admin-Key: $HUD_ADMIN_API_KEY" \
-d '{"jsonrpc":"2.0","method":"hud.brief"}'
```
To expose HUD's tools to **Open WebUI** or another OpenAPI-compatible tool server, point it at:
```
http://your-host:8200/openapi.json
```
> **For AdventedOS reference deployment**: the proxy at port 52415 is the Tailnet entry and can proxy `/openapi.json`. It does **not** inject `X-HUD-Admin-Key` -- clients must send `X-HUD-Admin-Key` or `X-HUD-Agent-Key`. HUD listens on `127.0.0.1:8001` only. See [AdventedOS Context](#adventedos-context).
### Google OAuth Setup (for Calendar/Tasks Projection)
1. Create a Google Cloud Platform project
2. Enable **Google Calendar API** and **Google Tasks API**
3. Create OAuth 2.0 credentials (Desktop application type)
4. Download as `gOAuth1.json` and place in your `data/` directory, or use env vars:
```bash
export GOOGLE_OAUTH_CREDENTIAL_ID=your-client-id
export GOOGLE_OAUTH_CREDENTIAL_SECRET=your-client-secret
```
5. For token encryption, set:
```bash
export GOOGLE_TOKEN_ENCRYPTION_KEY=your-secure-random-key
```
**Default projection mode is `dry_run`** -- no data touches Google until you explicitly set it to `live` and approve items.
---
## Environment Reference
| Variable | Default | Purpose |
|----------|---------|---------|
| `HUD_PORT` | `8200` | Listen port |
| `HUD_HOST` | `127.0.0.1` | Bind address |
| `HUD_DB_PATH` | `data/hud.db` | SQLite store |
| `HUD_ADMIN_API_KEY` | _(required)_ | `X-HUD-Admin-Key` header value |
| `HUD_DATA_DIR` | `data/` (relative to repo root) | Root for OAuth credentials, Obsidian vault, DB |
| `HUD_SOUL_MD_PATH` | `data/obsidian/AdventedHUD/soul.md` | Onboarding soul file |
| `HUD_SOUL_MD_TEMPLATE_PATH` | _(optional)_ | Worksheet template for onboarding read |
| `HUD_REQUIRE_POST_ONBOARDING_PUSH` | `1` | Set `0` to skip push-policy gate in dev |
| `HUD_RESOLVE_JWT_SUBJECT` | `0` | Set `1` to prefer JWT `sub` as user id |
| `HUD_ALLOW_WRITES` | `false` | Enable file/DB writes (startup safety) |
| `HUD_ALLOW_GOOGLE_WRITES` | `false` | Enable Google Calendar/Tasks projection |
| `HUD_LOG_LEVEL` | `INFO` | Log verbosity |
| `GOOGLE_OAUTH_CREDENTIAL_ID` | _(env hint)_ | OAuth client ID |
| `GOOGLE_OAUTH_CREDENTIAL_FILE` | _(env hint)_ | Path to OAuth JSON file |
| `GOOGLE_OAUTH_CREDENTIAL_PATH` | _(env hint)_ | Dir to search for gOAuth*.json |
| `GOOGLE_OAUTH_CREDENTIALS` | _(env hint)_ | Inline OAuth JSON string |
| `GOOGLE_TOKEN_ENCRYPTION_KEY` | _(default placeholder)_ | Key for encrypting stored OAuth tokens |
| `GOOGLE_TOKEN_FILE` | _(env hint)_ | Path to token JSON file |
### Credential Resolution Order
HUD resolves Google OAuth credentials in this priority:
1. **Inline payload** -- `oauth_credentials` field passed in the request
2. **Environment hints** -- `GOOGLE_OAUTH_CREDENTIAL_ID`, `GOOGLE_OAUTH_CREDENTIAL_FILE`, etc.
3. **File discovery** -- scans `data/` for `gOAuth1.json`, `gOAuth2.json`, and `gOAuth*.json` files
Tokens are resolved similarly: inline -> env var -> file scan for `*.token.json` in `data/`.
---
## Auth
HUD accepts two additive identities. Send a header on every authenticated request.
| Header | Identity | Notes |
|--------|----------|-------|
| `X-HUD-Admin-Key` | Full admin | Must match `HUD_ADMIN_API_KEY`. Invalid or missing admin key still returns **401** `authentication_error` (`invalid_hud_admin_key` / `missing_hud_admin_key`). |
| `X-HUD-Agent-Key` | Scoped agent | SHA-256 hashed lookup in `hud_agent_keys`. Grants JSON (`allowed_tools`, `allowed_role_refs`, `allowed_google_targets`, `calendar_id`, `tasklist_id`) is stored at provision. |
If both headers are present, **admin wins**.
Disallowed agent tool, role, or Google target returns **403** `authorization_error` / `hud_agent_forbidden` (not a silent coerce).
`POST /hud/agents/keys` is **admin-only** provision. The plaintext key is returned once; HUD stores only the hash. Agents cannot mint keys.
`hud.brief` is filtered to the agent's grants. Admin briefs are unfiltered.
Google Calendar/Tasks writes are HUD-mediated. Agents are forced to `calendar_id=primary` and `tasklist_id=@default`. HUD never returns OAuth tokens.
---
## MCP Tool Surface
HUD exposes a five-tool JSON-RPC surface through a single endpoint (`/hud/mcp`), plus decomposed first-class HTTP paths for direct access.
### Core Tools
| Method | Purpose | Agent Use |
|--------|---------|-----------|
| `hud.brief` (default) | Returns roles, goals, decision matrix (Q1-Q4) for classification. Agent principals get a grant-filtered brief; admin is unfiltered | First call every turn -- get context before classifying |
| `hud.brief` (scoped) | Returns human-readable briefing for a time period or goal | When user asks "what's on my plate?" |
| `hud.ingest` | Persists a classified item to Obsidian (with optional projection) | After classification -- create a todo/event/note |
| `hud.project` | Reviews item fate: `approve`, `reject`, `retract`, `update`, or `project` | For item review, approval decisions, and correcting/removing projected items |
| `hud.onboarding` | Reads/writes soul.md and atomic roles/goals | Initial setup, profile edits |
### Decomposed Onboarding Paths
For agents that prefer typed OpenAPI operations over JSON-RPC:
| Operation | HTTP Path | Method | Description |
|-----------|-----------|--------|-------------|
| `hud.onboarding.read` | `/hud/onboarding/read` | GET | Read soul.md + atomic template + validation status |
| `hud.onboarding.write_soul` | `/hud/onboarding/write_soul` | POST | Write soul.md markdown (step 1/3) |
| `hud.onboarding.set_atomic` | `/hud/onboarding/set_atomic` | POST | Persist atomic roles/goals (step 2/3) |
| `hud.onboarding.set_push` | `/hud/onboarding/set_push` | POST | Set external push policy (step 3/3) |
### OpenAPI Discovery
HUD serves a full OpenAPI 3.1 spec at `/openapi.json` for tool server auto-discovery. Compatible with OWUI, custom tool servers, and any OpenAPI client.
---
## HTTP Route Parity
All MCP methods have direct HTTP path equivalents:
| Route | Method | Maps To |
|-------|--------|---------|
| `/health` | GET | Service health check |
| `/hud/brief` | POST | `hud.brief` |
| `/hud/ingest` | POST | `hud.ingest` |
| `/hud/project` | POST | `hud.project` |
| `/hud/mcp` | POST | All tools (JSON-RPC) |
| `/hud/agents/keys` | POST | Admin-only agent key provision |
| `/hud/onboarding/soul` | GET, POST | Legacy combined onboarding |
| `/hud/onboarding/read` | GET | `hud.onboarding.read` |
| `/hud/onboarding/write_soul` | POST | `hud.onboarding.write_soul` |
| `/hud/onboarding/set_atomic` | POST | `hud.onboarding.set_atomic` |
| `/hud/onboarding/set_push` | POST | `hud.onboarding.set_push` |
| `/hud/sync_status` | POST | Sync status check |
| `/hud/status` | POST | Sync status (compat alias) |
| `/openapi.json` | GET | OpenAPI 3.1 discovery spec |
---
## Onboarding Ritual (v1.4.1)
HUD uses a multi-step onboarding to build the user's personal context (roles, goals, mission) and push policy preferences.
1. **`hud.brief` (no scope)** -- Returns classification context with `onboarding_state: incomplete`
2. **`hud.onboarding.read`** -- Returns the current soul.md template markdown and the exact `atomic_template` shape
3. **Write soul.md** -- `hud.onboarding.write_soul` with filled markdown (Roles Matrix + Goals Matrix tables)
4. **Set atomic** -- `hud.onboarding.set_atomic` with structured `roles`, `goals_by_role`, `primary_role_ref`, `primary_goal_ref`
5. **Set push policy** -- `hud.onboarding.set_push` with user's `external_push_without_approval` preference
6. **Verify** -- `hud.brief` (no scope) confirms `onboarding_state: fully_onboarded`
The onboarding uses **meta-prompting** -- tool responses include `mcp_meta.mode` that tells the agent what to do next (`efficiency`, `strict_ritual`) and reduces tool-calling overhead.
---
## Agent Harness Compatibility
> **Important note on tool calling patterns**
AdventedHUD was designed and tested against **Open WebUI's sequential tool-calling model**, where the agent calls one tool at a time and the system enforces a strict turn-by-turn flow.
The `mcp_meta` instruction system -- which tells agents "call this next" -- is optimized for this sequential pattern. Key behaviors to expect:
| Agent Harness | Compatibility | Notes |
|---------------|---------------|-------|
| **Open WebUI** | Full | Reference platform. Sequential calls, mcp_meta instructions, onboarding ritual -- all tested |
| **Claude Code / Claude Desktop** | Varies | MCP JSON-RPC works. Parallel tool calling may skip mcp_meta sequencing. Onboarding ritual instructions may behave differently |
| **Custom agent harness** | Varies | Direct HTTP to HUD works. If your harness calls tools in parallel or ignores mcp_meta, you may need to orchestrate the onboarding ritual steps yourself |
| **OpenAI Compatible** | Partial | The OpenAPI spec at `/openapi.json` works for tool discovery. Sequential constraint behavior depends on your client |
**Key callout**: The onboarding ritual relies on `mcp_meta.next_action` to guide the agent through the 6-step sequence. If your agent harness does not read and follow `mcp_meta` instructions between tool calls, you will need to orchestrate the onboarding steps externally.
---
## AdventedOS Context
AdventedHUD was built as part of **AdventedOS** -- a personal server infrastructure that bundles:
- **AdventedOS Proxy** -- Tailnet HTTP gateway on port **52415**. Routes requests between OWUI, HUD, model inference, and other services. Proxies HUD `/openapi.json` for tool discovery. It does **not** inject `X-HUD-Admin-Key`; clients must send `X-HUD-Admin-Key` or `X-HUD-Agent-Key`.
- **Open WebUI (OWUI)** -- Chat interface for interacting with LLMs. Discovers HUD's tools via the OpenAPI spec and manages conversation state.
### Running HUD in the AdventedOS Stack
In the reference deployment, the proxy lives at the monorepo root next to `AdventedHUD/`:
```
AdventedOS/
+-- AdventedHUD/ # this repo
+-- proxy/ # AdventedOS proxy (separate service)
+-- data/ # Shared data (OAuth credentials, Obsidian vault, DB)
+-- docker-compose.yml # OWUI container config
```
In that stack:
- HUD binds **`127.0.0.1:8001` only** (not Tailnet-reachable)
- The proxy on **:52415** is the Tailnet entry and routes `/hud/*` to HUD
- Clients still send `X-HUD-Admin-Key` or `X-HUD-Agent-Key` themselves
**You do not need AdventedOS to run AdventedHUD.** The service is fully standalone -- point any HTTP client or MCP-capable agent directly at the listen port (`HUD_PORT`, default 8200).
---
## Project Structure
```
AdventedHUD/
+-- main.py # Entry point
+-- hud/
| +-- main.py # Server bootstrap (aiohttp)
| +-- server.py # Route definitions + OpenAPI spec
| +-- mcp.py # JSON-RPC dispatch for all tools
| +-- adapters.py # Google OAuth, Calendar, Tasks projection
| +-- brief_context.py # Decision matrix + context builder
| +-- contracts.py # Shared models, error payloads, constants
| +-- gates.py # Admin/agent auth, grants, onboarding gating
| +-- handlers.py # /health, /sync_status
| +-- ingest_project.py # Ingest + approve/reject/retract/update pipeline
| +-- meta.py # Meta-prompting / efficiency modes
| +-- onboarding.py # Soul read/write with validation
| +-- onboarding_db.py # DB-level onboarding state management
| +-- store.py # SQLite store
| +-- sync.py # Sync utilities
| +-- workers.py # Background workers
+-- tests/
| +-- test_phase1_smoke.py
| +-- test_brief_v141.py
| +-- test_meta.py
| +-- test_onboarding_db.py
| +-- test_store.py
| +-- test_soul_template_gates.py
| +-- test_google_projection_lifecycle.py
+-- docs/
| +-- hud_foundation_spec.md # Foundation specification (authoritative)
| +-- hud_skill.md # Agent MCP contract (for LLM agents)
| +-- soul-template.md # Soul worksheet template
+-- requirements.txt # aiohttp only
+-- README.md # you are here
```
---
## Docs
| Document | Purpose |
|----------|---------|
| [`docs/hud_foundation_spec.md`](docs/hud_foundation_spec.md) | Foundation specification. Describes intent, philosophy, atomic data model, decision matrix, projection rules, and onboarding gating. Authoritative design document. |
| [`docs/hud_skill.md`](docs/hud_skill.md) | Agent MCP contract. The exact instructions an LLM agent follows to interact with HUD. Includes onboarding ritual sequence, classification rules, and meta-prompting behavior. |
| [`docs/soul-template.md`](docs/soul-template.md) | User-facing soul worksheet template. The markdown file users fill with their mission, roles, goals, values, and priorities. |
---
## Tests
```bash
# From the repo root
pip install pytest
pytest tests -q
# All tests use monkeypatch + tmp_path -- no external dependencies, no live services
```
Test coverage:
- `test_phase1_smoke.py` -- End-to-end routing and basic MCP dispatch
- `test_brief_v141.py` -- Brief context with decision matrix
- `test_meta.py` -- Meta-prompting mode transitions
- `test_onboarding_db.py` -- DB-level onboarding state management
- `test_store.py` -- SQLite store operations
- `test_soul_template_gates.py` -- Soul template validation gating
- `test_google_projection_lifecycle.py` -- Google projection: deferred on ingest, dispatched on approve, auto-approve for Pattern B
---
## License
Apache 2.0
---
*Built as part of the AdventedOS personal infrastructure ecosystem.*
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues