Boomerang Wellbeing Planner
README.md
# Boomerang Wellbeing Planner — MCP Server
A Node.js [MCP (Model Context Protocol)](https://modelcontextprotocol.io) server that generates
**personalised 12-week wellbeing planners for Australian near-retirees**. It exposes a single MCP
tool over **Streamable HTTP** (so it is reachable over a network URL from clients like ServiceNow),
calls the Anthropic API to generate the plan content, and serves an interactive "journey path"
visualisation of each plan.
## What it does
1. An MCP client calls the `generate_wellbeing_plan` tool with a free-text wellbeing concern.
2. The server asks Claude (default model: `claude-sonnet-5`) for a 12-week, milestone-based plan,
grounded in ABS statistics about loneliness and community participation among older Australians.
The response is schema-constrained, parsed, and validated. The plan never contains medical or
clinical advice — sensitive topics are framed as "worth discussing with a GP or counsellor".
3. The plan is stored (in-memory + a simple JSON file, no database) and rendered as a warm, calm
HTML journey: one node per week on a connected path, colour-coded by responsible agent
(wellbeing = rose, connection = blue), with a circular progress ring showing the overall
wellbeing score.
4. The tool returns both the raw JSON plan and a `view_url` to that page.
Everything runs on **one server / one port**: `POST /mcp` (MCP endpoint) and `GET /plans/:plan_id`
(viewer).
## Setting the ANTHROPIC_API_KEY secret in Replit
1. Open the Repl and click **Tools → Secrets** (padlock icon).
2. Add a secret with key `ANTHROPIC_API_KEY` and your key from
[console.anthropic.com](https://console.anthropic.com/) as the value.
3. Click **Run**. Replit installs dependencies on boot and starts the server on `$PORT`.
Optional secrets: `ANTHROPIC_MODEL` (defaults to `claude-sonnet-5`) and `BASE_URL`
(auto-detected on Replit). For local development, copy `.env.example` to `.env`.
## MCP tool schema
**Tool:** `generate_wellbeing_plan`
Input:
| Field | Type | Required | Description |
| ----------------- | ------ | -------- | -------------------------------------------------- |
| `user_query` | string | yes | The user's free-text wellbeing concern |
| `emotional_state` | string | no | e.g. `"lonely"`, `"anxious"`, `"low motivation"` |
| `age_bracket` | string | no | e.g. `"65-70"` |
Output (returned as JSON text content):
```json
{
"plan": {
"plan_id": "<uuid>",
"generated_at": "<iso datetime>",
"overall_wellbeing_score": 62,
"weeks": [
{
"week_offset": 0,
"theme": "Gentle first steps",
"milestones": [
{
"title": "Take a 20-minute morning walk twice this week",
"target_date": "Week 1",
"owner": "retiree",
"agent_responsible": "wellbeing",
"confidence": 0.85
}
]
}
]
},
"view_url": "https://<repl-domain>/plans/<plan_id>"
}
```
`weeks` covers offsets 0–11, with a check-in week every 3 weeks. `owner` is `"retiree"` or
`"agent"`; `agent_responsible` is `"wellbeing"` or `"connection"`; `confidence` is `0.00–1.00`.
## Testing it manually
### With curl
The MCP Streamable HTTP transport takes JSON-RPC over POST. Call the tool directly:
```bash
curl -s -X POST "http://localhost:3000/mcp" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "generate_wellbeing_plan",
"arguments": {
"user_query": "I retire in 6 months and I am worried I will feel lonely and aimless",
"emotional_state": "anxious",
"age_bracket": "65-70"
}
}
}'
```
(Replace `http://localhost:3000` with your Repl URL.) List the available tools with
`"method": "tools/list", "params": {}`. The response includes the plan JSON and the `view_url` —
open it in a browser to see the interactive journey.
### With MCP Inspector
```bash
npx @modelcontextprotocol/inspector
```
Choose transport **Streamable HTTP**, enter `https://<your-repl>/mcp`, connect, and run
`generate_wellbeing_plan` from the Tools tab.
## REST endpoint: render a plan as a PNG
`POST /render-plan-image` takes a plan JSON (the same `weeks[]` schema shown above) and renders
it server-side to a PNG using node-canvas — no headless browser involved.
Response: `{ "image_base64": "<png bytes as base64>", "content_type": "image/png" }`.
Returns `400` with a clear message if `weeks` is missing. The canvas is 900px wide with a
1400px minimum height, growing taller if the plan's milestones need the room.
```bash
curl -s -X POST "http://localhost:3000/render-plan-image" \
-H "Content-Type: application/json" \
-d @plan.json | node -e "
let d=''; process.stdin.on('data',c=>d+=c).on('end',()=>{
require('fs').writeFileSync('plan.png', Buffer.from(JSON.parse(d).image_base64,'base64'));
console.log('wrote plan.png');
})"
```
> Dependency note: the `canvas` package is an *optional* dependency (its prebuilt binary
> installs cleanly on Replit/Linux). On platforms where it can't build, the server falls back
> to the API-compatible `@napi-rs/canvas` automatically.
## Local development
```bash
npm install
cp .env.example .env # add your ANTHROPIC_API_KEY
npm start # http://localhost:3000
```
## Project layout
```
server.js Express app: /mcp (Streamable HTTP, stateless) + /plans/:id viewer
src/generatePlan.js Anthropic API call, schema-constrained output, validation
src/renderPlan.js Self-contained HTML journey-path renderer
src/planStore.js In-memory store persisted to data/plans.json
.replit / replit.nix Replit run + environment config
```
> **Note:** This project provides general lifestyle planning only — never medical or
> psychological advice.
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues