Skip to main content
Glama
gayatrimuthina-beep

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.