# StayFocus MCP server

> Connect Claude, ChatGPT or any MCP client to your own StayFocus focus sessions, projects, experiments, notes and brain dump. OAuth 2.1, 15 tools, one endpoint.

- Canonical: https://stayfocus.now/mcp
- Language: en

---

## Summary

StayFocus is a focus-session app: you run one timed deep-work session at a time, park distracting thoughts in a brain dump, run two-week experiments, and keep a streak. The StayFocus MCP server lets an AI assistant read and write **one** authenticated user's own StayFocus data over the Model Context Protocol.

Every tool resolves the user from the authorizing token and scopes each query to that user. No tool can reach another user's data, billing data, or admin data.

## Connection

| Field | Value |
| --- | --- |
| Endpoint | `https://stayfocus.now/mcp` |
| Transport | Streamable HTTP (`POST`, JSON-RPC 2.0) |
| Server name | StayFocus |
| Server version | 1.1.0 |
| Tools | 15 |
| Resources / prompts | None — tools only |
| Authentication | OAuth 2.1 (authorization code + PKCE), or a bearer personal access token |
| Plan required | Active subscription or trial (14-day free trial, no card) |

## Authentication

Two supported paths. Web connectors use OAuth; command-line clients that can set headers may use a bearer token instead.

### Option A — OAuth 2.1 (Claude.ai, ChatGPT, any MCP web connector)

The user pastes only the endpoint URL. The client discovers and completes the flow automatically; no application registration with Anthropic or OpenAI is required.

```http
GET  https://stayfocus.now/.well-known/oauth-protected-resource     # resource metadata
GET  https://stayfocus.now/.well-known/oauth-authorization-server   # authorization server metadata
POST https://stayfocus.now/oauth/register                           # dynamic client registration
GET  https://stayfocus.now/oauth/authorize                          # user approves the grant
POST https://stayfocus.now/oauth/token                              # authorization code + PKCE -> access token
POST https://stayfocus.now/mcp                                      # tool calls, Authorization: Bearer <token>
```

The issued token is bound to the user who approved the grant and carries the single scope `mcp:use`. The user can revoke it at any time in **Settings → Account → AI assistant → Connected assistants**.

### Option B — bearer personal access token (desktop and CLI)

Generate a token in **Settings → Account → AI assistant → Desktop & CLI (advanced)**. It is shown once. Send it on every request:

```http
Authorization: Bearer <token>
```

Verify a token works:

```bash
curl -s -X POST https://stayfocus.now/mcp \
  -H "Authorization: Bearer $STAYFOCUS_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```

Without a valid token the endpoint returns `401`.

## Client configuration

### Claude.ai and Claude Desktop (web connector, OAuth)

1. Open [claude.ai/settings/connectors](https://claude.ai/settings/connectors) → **Add custom connector**.

2. Name it `StayFocus`, paste `https://stayfocus.now/mcp`, confirm. There is no token field — none is needed.

3. Enable **StayFocus** from the search & tools menu in a chat.

4. On first use, approve the StayFocus grant screen. Claude Desktop and mobile sync the connector automatically.

### Claude Code

```bash
# OAuth (recommended) — Claude Code opens the browser to authorize
claude mcp add --transport http stayfocus https://stayfocus.now/mcp

# Or with a personal access token
claude mcp add --transport http stayfocus https://stayfocus.now/mcp \
  --header "Authorization: Bearer YOUR_TOKEN"
```

### Claude Desktop config file

Settings → Developer → Edit Config, then add:

```json
{
    "mcpServers": {
        "stayfocus": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://stayfocus.now/mcp"
            ]
        }
    }
}
```

### ChatGPT

1. **Settings → Apps & Connectors**, enable **Developer mode** (Plus, Pro, Team or Enterprise).

2. **Create**, name it `StayFocus`, paste `https://stayfocus.now/mcp`, choose **OAuth** as the authentication method.

3. Approve the StayFocus permission screen.

### Any other MCP client

Point it at `https://stayfocus.now/mcp` with transport `Streamable HTTP`. Both OAuth and `Authorization: Bearer` are accepted.

## Tools

15 tools — 7 read, 8 write. All parameters are JSON, passed as `arguments` to `tools/call`.

| Tool | Type | Purpose |
| --- | --- | --- |
| `get-focus-sessions` | read | Get the authenticated user's focus session history: total count, total focused minutes, and the most recent sessions |
| `get-active-session` | read | Get the authenticated user's currently running (or paused) focus session, if any |
| `get-projects` | read | List the authenticated user's projects with status, visibility and description |
| `create-project` | write | Create a new project for the authenticated user |
| `get-stats` | read | Get the authenticated user's dashboard stats: streaks, total sessions, focused time and experiments summary |
| `get-experiments` | read | List the authenticated user's tiny experiments (time-bound commitments) and highlight the active one |
| `start-focus-session` | write | Start a focus session on one of the user's projects |
| `end-focus-session` | write | End the user's running focus session |
| `get-notes` | read | Search and read the authenticated user's notes — their decision log, reflections and progress journal from the "Updates" page |
| `create-note` | write | Create a private note in the user's decision log / reflection journal (the "Updates" page) |
| `get-brain-dump-items` | read | List items in the user's brain dump — the capture lane for thoughts and ideas that are not a project, experiment or note yet |
| `capture-brain-dump-item` | write | Capture a quick thought, idea or brain dump into the user's brain dump — for things that are not ready to become a project, experiment or note yet, or that should come back later |
| `schedule-brain-dump-reminder` | write | Schedule (or reschedule) a reminder on an open brain dump item, so it resurfaces in "needs attention" later |
| `archive-brain-dump-item` | write | Archive an brain dump item once the user is done with it — it will no longer show up in "needs attention" |
| `convert-brain-dump-item` | write | Turn a brain dump item into a project, a tiny experiment, or a reflection — when the user has decided what to do with a captured idea |

### `get-focus-sessions`

Get the authenticated user's focus session history: total count, total focused minutes, and the most recent sessions.

**Parameters:** none.

Example call:

```json
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "get-focus-sessions"
    }
}
```

### `get-active-session`

Get the authenticated user's currently running (or paused) focus session, if any.

**Parameters:** none.

Example call:

```json
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "get-active-session"
    }
}
```

### `get-projects`

List the authenticated user's projects with status, visibility and description.

**Parameters:** none.

Example call:

```json
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "get-projects"
    }
}
```

### `create-project`

Create a new project for the authenticated user. Projects are private by default.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | string | yes | The project name. |
| `description` | string | no | Optional short description of the project. |
| `visibility` | string (one of: private, public) | no | Project visibility. Defaults to private. |

Example call:

```json
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "create-project",
        "arguments": {
            "name": "…"
        }
    }
}
```

### `get-stats`

Get the authenticated user's dashboard stats: streaks, total sessions, focused time and experiments summary.

**Parameters:** none.

Example call:

```json
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "get-stats"
    }
}
```

### `get-experiments`

List the authenticated user's tiny experiments (time-bound commitments) and highlight the active one.

**Parameters:** none.

Example call:

```json
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "get-experiments"
    }
}
```

### `start-focus-session`

Start a focus session on one of the user's projects. Idempotent: if a session is already running, it is returned unchanged instead of starting a new one.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `project_uuid` | string | yes | UUID of one of the user's active projects (see get-projects). |
| `intention` | string | yes | What the user will work on during this session. |
| `duration_minutes` | integer | no | Planned session length in minutes (15, 25, 50 or 90). |

Example call:

```json
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "start-focus-session",
        "arguments": {
            "project_uuid": "9f8c1e2a-7b4d-4c31-9a0e-5d6f7a8b9c0d",
            "intention": "…"
        }
    }
}
```

### `end-focus-session`

End the user's running focus session. Safe: does nothing if no session is active.

**Parameters:** none.

Example call:

```json
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "end-focus-session"
    }
}
```

### `get-notes`

Search and read the authenticated user's notes — their decision log, reflections and progress journal from the "Updates" page. Use this to answer questions like "what did I decide about X", "summarize my recent notes on project Y", or "search my notes for...". The user may ask in Arabic (e.g. "ملاحظاتي", "قراراتي", "مذكراتي") — treat that the same as "notes". Filter by free-text search, a project, or tags.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `search` | string | no | Free-text search within note content. Leave empty to list recent notes. |
| `project_uuid` | string | no | Only return notes linked to this project (see get-projects for uuids). |
| `tags` | array of string | no | Only return notes tagged with at least one of these tags. |
| `limit` | integer | no | Maximum number of notes to return (1-50). |

Example call:

```json
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "get-notes"
    }
}
```

### `create-note`

Create a private note in the user's decision log / reflection journal (the "Updates" page). Use this when the user wants to record a decision, write down a reflection, log progress, or asks to "save this as a note" — including Arabic phrasing like "خليه كملاحظة" or "سجل هاد القرار". Optionally link the note to a project (get-projects for the uuid), tag it, and set a mood.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `content` | string | yes | The note content — the decision, reflection or progress update to record. |
| `project_uuid` | string | no | Optional: link this note to one of the user's projects (see get-projects for uuids). |
| `tags` | array of string | no | Optional tags for this note (max 5). |
| `mood_key` | string (one of: motivated, focused, excited, proud, grateful, hopeful, calm, tired, bored, stuck, confused, stressed, anxious, frustrated, overwhelmed, sad, lonely, angry) | no | Optional mood associated with this note. |

Example call:

```json
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "create-note",
        "arguments": {
            "content": "…"
        }
    }
}
```

### `get-brain-dump-items`

List items in the user's brain dump — the capture lane for thoughts and ideas that are not a project, experiment or note yet. By default returns items that need attention: open items plus scheduled reminders that are now due. Use this to answer "what's in my brain dump?" / "شنو عندي فتفريغ الذهن دابا؟" or to check for reminders that just came due. Each item shows its uuid, content, status (open, scheduled, converted, archived) and whether a reminder is due.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `status` | string (one of: needs_attention, open, scheduled, converted, archived, all) | no | Which items to return. "needs_attention" (default) is open items plus due reminders. |
| `limit` | integer | no | Maximum number of items to return (1-50). |

Example call:

```json
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "get-brain-dump-items"
    }
}
```

### `capture-brain-dump-item`

Capture a quick thought, idea or brain dump into the user's brain dump — for things that are not ready to become a project, experiment or note yet, or that should come back later. Use this whenever the user says things like "save this idea", "add this to my brain dump", "remind me about this later", or in Arabic "احفظ هاد الفكرة" / "خزن هاد الشي". Only the content is required — capture is zero-friction by design. The user can later ask to schedule a reminder, convert it to a project/experiment/note, or archive it.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `content` | string | yes | The thought, idea or note to capture. |
| `focus_session_uuid` | string | no | Optional: the uuid of the user's currently active/paused focus session, if this idea came up mid-session (see get-active-session). |

Example call:

```json
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "capture-brain-dump-item",
        "arguments": {
            "content": "…"
        }
    }
}
```

### `schedule-brain-dump-reminder`

Schedule (or reschedule) a reminder on an open brain dump item, so it resurfaces in "needs attention" later. Use this when the user says "remind me about this on Friday at 9am", "ذكرني بها يوم الجمعة" or similar. Get the item's uuid from get-brain-dump-items. Provide either "remind_at" with a concrete ISO 8601 date-time you computed from the user's request (must be in the future), or a "preset" (in_1_hour, tomorrow, next_week).

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `item_uuid` | string | yes | UUID of the brain dump item (see get-brain-dump-items). |
| `remind_at` | string | no | A concrete future date-time, ideally ISO 8601 (e.g. 2026-06-19T09:00:00). Resolve relative phrases like "next Friday at 9am" to a real date yourself before calling this tool. |
| `preset` | string (one of: in_1_hour, tomorrow, next_week) | no | A quick preset instead of remind_at. "tomorrow" and "next_week" mean 9:00 local time. |

Example call:

```json
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "schedule-brain-dump-reminder",
        "arguments": {
            "item_uuid": "9f8c1e2a-7b4d-4c31-9a0e-5d6f7a8b9c0d"
        }
    }
}
```

### `archive-brain-dump-item`

Archive an brain dump item once the user is done with it — it will no longer show up in "needs attention". Use this when the user says they're done with an idea, want to dismiss it, or "no longer need" something from their brain dump. Get the item's uuid from get-brain-dump-items.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `item_uuid` | string | yes | UUID of the brain dump item (see get-brain-dump-items). |

Example call:

```json
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "archive-brain-dump-item",
        "arguments": {
            "item_uuid": "9f8c1e2a-7b4d-4c31-9a0e-5d6f7a8b9c0d"
        }
    }
}
```

### `convert-brain-dump-item`

Turn a brain dump item into a project, a tiny experiment, or a reflection — when the user has decided what to do with a captured idea. Use this for requests like "turn this into a project" / "حولها لمشروع", "make this an experiment", or "save this as a reflection" / "احفظها كتأمل". Get the item's uuid from get-brain-dump-items. For "experiment", you may optionally pass duration_days, success_criteria and visibility.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `item_uuid` | string | yes | UUID of the brain dump item (see get-brain-dump-items). |
| `target` | string (one of: project, experiment, note) | yes | What to convert the brain dump item into. |
| `duration_days` | integer | no | Experiment only: how many days the experiment should run. Defaults to 14. |
| `success_criteria` | string | no | Experiment only: what success looks like for this experiment. |
| `visibility` | string (one of: private, public) | no | Experiment only: visibility of the new experiment. Defaults to private. |

Example call:

```json
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "convert-brain-dump-item",
        "arguments": {
            "item_uuid": "9f8c1e2a-7b4d-4c31-9a0e-5d6f7a8b9c0d",
            "target": "project"
        }
    }
}
```

## Errors

| Response | Meaning |
| --- | --- |
| `401 Unauthorized` | Missing, expired or revoked token. Re-authorize the connector, or generate a new personal access token. |
| `403 Forbidden` | The account has no active subscription or trial. See [Pricing](https://stayfocus.now/pricing.md). |
| `405 Method Not Allowed` | The request used `GET` or `DELETE` on the endpoint. MCP messages are `POST` only. |
| `429 Too Many Requests` | Rate limit exceeded. Back off and retry. |
| JSON-RPC `isError: true` | The tool ran but rejected the input — for example an unknown UUID, or a second `start-focus-session` while one is already running. The message text explains what to change. |

## Limits and rules

- **Plan:** the endpoint requires an active subscription or trial. Authentication succeeds but tool calls are refused without one.
- **One active session:** `start-focus-session` is a no-op when a session is already running; end it first with `end-focus-session`.
- **Scope:** every tool is scoped to the authorizing user. There is no way to read another user's data through this server.
- **Write tools** go through the same domain actions as the web app, so the same rules apply.
- **Relative dates:** the server does not parse "next Friday". Resolve dates to ISO 8601 before calling `schedule-brain-dump-reminder`.

## Related

- [Pricing](https://stayfocus.now/pricing.md) — plans, limits and the free trial.
- [StayFocus overview](https://stayfocus.now/index.md) — what the product does.
- [Sign up](https://stayfocus.now/login) — create an account, then connect from Settings → Account.
