# HYBRD MCP setup (instructions for AI agents)

You are reading this because a person asked you to connect them to HYBRD. Read the whole document before acting.

This document is for AI agents. If you are a person, use the human setup page instead of these instructions. Human setup: https://www.hybrd.com/mcp

## What and why

HYBRD MCP makes it easy to manage and execute your fitness goals. It lets an agent create your fitness plan and workouts, and connect your wearables, so you can track and complete your training wherever works best for you: in HYBRD, where you can log lifting and running, or on your Apple Watch, Garmin, and other connected devices.

Use HYBRD MCP to get guidance grounded in your workout history, ask better questions about what to do next, and turn recommendations into structured workouts and programming. As you complete training, HYBRD automatically adapts the weights and paces prescribed in future sessions. HYBRD MCP gives your AI profile, workout, and connected fitness integration read/write access.

**What this is:** setup instructions for a *remote MCP server*. It is not a Codex skill package, a Claude plugin, an npm package, or a local process. There is nothing to download or install. You add one server entry to the MCP client's configuration, the person signs in to HYBRD in their browser, and then you verify the connection with a tool call.

**Source of truth:** the connected server. After sign-in, `tools/list` is authoritative for tool names, arguments, scopes, and limits. Public docs may lag the server.

## Server

| Field | Value |
| --- | --- |
| Name | `hybrd` |
| URL | `https://mcp.hybrd.com/mcp` |
| Transport | Streamable HTTP (`streamable-http`) |
| Authorization | OAuth 2.1 with dynamic client registration and PKCE S256 |
| Authorization server metadata | https://mcp.hybrd.com/.well-known/oauth-authorization-server |
| Registration endpoint | `https://mcp.hybrd.com/register` |
| Authorization endpoint (browser OAuth) | `https://mcp.hybrd.com/authorize` |
| Device authorization endpoint (fallback) | `https://mcp.hybrd.com/device_authorization` |
| Token endpoint | `https://mcp.hybrd.com/token` |
| Revocation endpoint | `https://mcp.hybrd.com/revoke` |
| Device verification page (person opens on their phone) | https://app.hybrd.com/mcp/device |
| API key / env vars / command | None. Remote server; OAuth only. |

Every request, including `tools/list`, requires a signed-in HYBRD account. A 401 before sign-in is expected, not an error.

## Access

HYBRD MCP grants your agent profile, workout, and connected fitness integration read/write access. The person reviews access on the HYBRD consent screen. See `scopes_supported` from the authorization server metadata and the `grantedScopes` returned by `get_account`.

All eight scopes:

- `profile:read`: View profile facts, benchmarks, and remaining onboarding work.
- `profile:write`: Update profile facts, body weight, timezone, and benchmarks.
- `workouts:read`: View scheduled and completed workouts and training plans.
- `workouts:write`: Create, update, complete, and delete scheduled or completed workouts.
- `integrations:read`: View connected and available fitness integrations.
- `integrations:write`: Connect and disconnect fitness integrations. Apple Health cannot be connected through MCP; it requires the iOS app.
- `health:read`: View health data that HYBRD has synced from connected devices.
- `health:write`: Record health data into the HYBRD account.

Omit `scope` to request every scope; otherwise send a space-delimited subset of the names above.

## Procedure

1. **Identify the MCP client** you are running in (ChatGPT, Codex CLI, Claude Code, Claude app, Cursor, VS Code, other) and use the matching section below.
2. **Add the server at user level** (available in every project) unless the person asks for project-level config. Name it `hybrd` and use the URL above.
3. **Start OAuth sign-in.** For a native MCP client, give the person the sign-in URL and wait for the client to finish OAuth. For the device flow, show the verification link and code, then poll the token endpoint immediately while the person approves; do not wait for them to say they are done.
4. **Verify the account.** Call `get_account`. It returns the connected HYBRD email, approved scopes, and subscription status. 
5. **Confirm subscription.** Connecting is free. Most tools need an active HYBRD subscription. `get_stripe_checkout_link` is only for clients outside ChatGPT/Codex. If `get_account` or `get_profile` onboarding shows no active subscription, or a tool fails with `subscription_inactive`, call `get_stripe_checkout_link` and share the link. Inside ChatGPT or Codex, do not call `get_stripe_checkout_link`; tell the person they need an active HYBRD subscription (they can go to app.hybrd.com). Retry `get_account` after the person subscribes. Do not stop at reporting a missing subscription.
6. **Read the profile.** Call `get_profile`. Complete each onboarding TODO by calling that step's `toolName`, then call `get_profile` again until `onboarding.complete` is true. DEVICE is optional and never blocks complete.
7. **Summarize recent training.** Once the connection and subscription are correct, call `list_workouts` and give the person a quick summary of their last workouts - this is for their 'aha' moment: wow, it really is connected to my wearable(s).

## Client-specific setup

Use the matching block to add the server and finish OAuth. Then continue the Procedure from **Verify the account** (subscription, profile, and a last-workouts summary). Do not stop after adding the server entry.

### Codex CLI

```
codex mcp add hybrd --url https://mcp.hybrd.com/mcp
codex mcp login hybrd
codex mcp get hybrd
```

This writes a user-level entry to `~/.codex/config.toml`:

```toml
[mcp_servers.hybrd]
url = "https://mcp.hybrd.com/mcp"
```

`codex mcp login hybrd` prints the HYBRD sign-in URL. After the person approves, `codex mcp get hybrd` should show the enabled remote server and `codex mcp list` should show `hybrd` as authenticated; then call `get_account`. If `get_account` is not available in the current conversation, restart or reconnect Codex before calling it.

### ChatGPT (Codex in the browser)

Settings → MCP servers → Add server. Name `HYBRD`, transport streamable HTTP, URL `https://mcp.hybrd.com/mcp`. Requires a paid ChatGPT plan; on Business/Enterprise/Edu an admin may need to allow custom MCP servers. 

### Claude Code

```
claude mcp add --transport http --scope user hybrd https://mcp.hybrd.com/mcp
```

`--scope user` stores it in `~/.claude.json` for every project (omit it for the current project only). Then run `/mcp` inside Claude Code, choose `hybrd`, and authenticate; the browser opens the HYBRD sign-in. 

### Claude (desktop or web app)

Customize → Connectors → Add custom connector. Paste `https://mcp.hybrd.com/mcp` and complete the HYBRD sign-in. In a managed organization an owner may need to approve the connector first.

### Cursor

Add to `~/.cursor/mcp.json` (user level) or `.cursor/mcp.json` (project level):

```json
{
  "mcpServers": {
    "hybrd": {
      "url": "https://mcp.hybrd.com/mcp"
    }
  }
}
```

Then open Cursor Settings → MCP, click sign in next to `hybrd`.

### VS Code (Copilot agent mode)

```
code --add-mcp '{"name":"hybrd","type":"http","url":"https://mcp.hybrd.com/mcp"}'
```

Or add to the user-profile `mcp.json` (or `.vscode/mcp.json` for one project):

```json
{
  "servers": {
    "hybrd": {
      "type": "http",
      "url": "https://mcp.hybrd.com/mcp"
    }
  }
}
```

Trust and start the server, sign in to HYBRD in the browser.

### Muse

Prefer Muse's hosted connector and browser OAuth when its connector UI accepts a pre-registered `client_id`:

1. Get the exact HTTPS redirect URI or URIs that Muse's connector will send. Do not guess them.
2. **Before asking the person to sign in**, register Muse with `POST https://mcp.hybrd.com/register`: `client_id: "Muse"` (exactly, case-sensitive), `client_name: "Muse"`, `grant_types: ["authorization_code", "refresh_token"]`, `token_endpoint_auth_method: "none"`, `response_types: ["code"]`, and the exact Muse values in `redirect_uris`.
3. Wait for registration to succeed. In Muse's connector or API-access UI and at `/authorize`, use the literal `client_id=Muse`. Do not substitute an opaque ID or UUID, including one generated by the portal. Use `resource=https://mcp.hybrd.com/mcp` when the UI asks for a resource, and use PKCE S256.
4. Only now ask the person to authenticate, complete HYBRD sign-in and consent in the browser, then continue the Procedure from **Verify the account**.

If Muse cannot accept the registered `client_id`, cannot use the exact redirect URI, or cannot complete the browser callback, use the **Device flow** below. If approval succeeds but the token request returns HTTP 502, `refresh_rejected`, or another egress/proxy error, report that Muse's host blocked the exchange and stop. Do not create and approve device codes in a loop.

### Instinct

Instinct has no persistent native MCP client. Follow the [Instinct-specific setup and troubleshooting skill](https://hybrd.com/resources/mcp-instinct/skill.md) exactly instead of the generic add-server and browser-OAuth directions. It covers manual OAuth, resumable polling, session-only token handling, raw MCP JSON-RPC, and Instinct's output limits. Then continue this Procedure from **Verify the account**.

### Any other MCP client

```json
{
  "mcpServers": {
    "hybrd": {
      "url": "https://mcp.hybrd.com/mcp",
      "transport": "streamable-http"
    }
  }
}
```

Field names vary by client; the URL and streamable HTTP transport are what matter. OAuth discovery happens automatically from the server URL.

## Device flow (fallback only)

Browser OAuth above is the default and recommended path. Use the device flow (RFC 8628) **only** when the MCP host cannot complete a browser-OAuth callback, for example a headless box, a container, an SSH session with no browser, or an agent such as **Muse** or **Instinct** that can make HTTP requests but has no native external-MCP connector. Native MCP clients should use browser OAuth instead.

The person finishes the approval on their phone or any other device with a browser. Their HYBRD account and subscription rules are the same as for browser OAuth.

1. **Register a device client once per stored registration.** Reuse it only while its stored `client_id` remains available. `POST https://mcp.hybrd.com/register` with JSON: `grant_types` of `["urn:ietf:params:oauth:grant-type:device_code", "refresh_token"]`, `token_endpoint_auth_method` of `"none"`, no `redirect_uris`, empty `response_types`, and a human-readable `client_name` (for example `"Muse"` or `"Instinct"`). The consent screen shows `client_name` to the person, so set it to the name they know you by. Store the returned `client_id`; you need it for every later request, including revocation.
2. **Request a device code.** `POST https://mcp.hybrd.com/device_authorization` as `application/x-www-form-urlencoded` with `client_id`, `resource=https://mcp.hybrd.com/mcp`, and optionally `scope` (space-delimited; omit to request all scopes). The response has a private `device_code` used only for polling, a user-facing `user_code`, `verification_uri`, `expires_in`, and `interval` (seconds between polls). Calculate the deadline from the returned `expires_in`; do not hard-code five minutes. Never send the private `device_code` to the person.
3. **Open the verification page and fill the code.** Open `verification_uri_complete` when returned. Otherwise open `verification_uri` (https://app.hybrd.com/mcp/device) with your browser or UI controls and paste `user_code` into the verification-code field automatically. Do not make the person type it. Tell them the calculated expiry time, hand control to them to approve access, and start polling immediately.
4. **Send a copyable fallback.** Send a **separate chat message containing only `user_code`**—no label, prose, punctuation, or code fence—so the person can copy it with one action if automatic entry fails. Do not ask them to paste it back into chat.
5. **Poll for the token immediately.** Do not wait for the person to confirm approval. `POST https://mcp.hybrd.com/token` (form-encoded) with `grant_type=urn:ietf:params:oauth:grant-type:device_code`, `device_code`, `client_id`, and `resource=https://mcp.hybrd.com/mcp`, waiting `interval` seconds between attempts. `authorization_pending` means keep waiting; `slow_down` means increase the wait; `expired_token` or `access_denied` means stop and start a new device authorization (step 2). Success returns `access_token`, `refresh_token`, and `expires_in`.
6. **Store tokens securely and never log them.** Keep the access and refresh tokens in the OS keychain or an encrypted secret store scoped to the person. Do not write them to plain-text config, chat transcripts, or logs. Send the access token as `Authorization: Bearer <token>` on every MCP request.
7. **Continue the Procedure** from **Verify the account**.

Every `error_description` from these endpoints contains the exact recovery step. Follow it instead of guessing.

## Token lifecycle

High-level rules that apply to both browser OAuth and the device flow. MCP clients such as Claude Code, Codex, and Cursor handle this for you; you only need this section if you hold tokens yourself.

If you implement OAuth HTTP yourself, also read the [token refresh skill](https://www.hybrd.com/resources/mcp-token-refresh/skill.md).

- **Send `resource=https://mcp.hybrd.com/mcp` on every token request**, including the refresh-token grant, not only on `/authorize` and the first code exchange. `/token` returns HTTP 400 `invalid_request` when `resource` is missing or wrong; HYBRD does not infer it from an earlier grant.
- **Access tokens are short-lived** (about one hour). Read `expires_in` rather than assuming a number.
- **Refresh only when needed.** Refresh when the access token has expired or a call returns 401, not on a timer.
- **Refresh tokens rotate and are single-use.** Each refresh returns a new access token and a new refresh token, and the old refresh token stops working. Always persist the new pair before using it.
- **One refresh at a time.** Serialize refreshes per account. Two concurrent refreshes with the same token cause an `invalid_grant` and force the person to sign in again.
- **Reusing a consumed refresh token revokes the whole token family.** After `invalid_grant`, do not retry the old token in a loop; start a new sign-in.
- **Refresh tokens expire** after 30 days idle and 90 days absolute. After that, run the sign-in (or device flow) again.
- **Revocation requires `client_id`.** `POST https://mcp.hybrd.com/revoke` (form-encoded) with `token` and `client_id` when the person disconnects. Revoking either token in a pair revokes both.

## Troubleshooting

Something failed after setup. The [troubleshooting skill](https://www.hybrd.com/resources/mcp-troubleshooting/skill.md) has the full diagnosis guide; the common cases are also listed here so you do not need a second fetch.

- **401 / unauthorized before the person approved access:** the OAuth sign-in has not completed. Re-run the client's login step and wait for the person to approve.
- **401 / unauthorized after a previously working connection (custom OAuth clients):** the access token expired. Refresh once with the current refresh token and `resource=https://mcp.hybrd.com/mcp` (see the [token refresh skill](https://www.hybrd.com/resources/mcp-token-refresh/skill.md)). Start a new sign-in only if refresh returns `invalid_grant`.
- **`get_account` succeeds but a tool reports missing a scope:** explain what the tool needs and ask the person to reconnect the server and approve the matching scope again (see the scope list under Access).
- **`invalid_grant` on refresh ("unknown, expired, revoked, or already rotated"):** the refresh token was already used or has expired. Do not retry it. Start a new sign-in, or a new device flow from `POST /device_authorization`, and store the new tokens.
- **HTTP 400 `invalid_request` mentioning `resource` on `/token`:** send `resource=https://mcp.hybrd.com/mcp` on `/authorize`, the authorization-code `/token` exchange, the refresh-token `/token` call, and the device-code `/token` poll.
- **Muse reports that `client_id` is not registered:** first register the literal, case-sensitive `client_id: "Muse"`, then authorize with `client_id=Muse`. Do not use an opaque ID or UUID generated by the portal. If Muse replaces the ID, use device flow or report the connector limitation.
- **Muse device approval succeeds but token exchange returns HTTP 502 or `refresh_rejected`:** Muse's egress proxy blocked the token request. Stop and report the host restriction; do not keep issuing device codes.
- **`expired_token` while polling the device flow:** the person did not approve within 5 minutes. Do not retry that `device_code`. Request a new one and show the person the new `user_code`.
- **`slow_down` while polling:** you are polling faster than `interval`. Wait at least that many seconds between polls.
- **No active subscription outside ChatGPT/Codex:** call `get_stripe_checkout_link`, share the link, and retry after checkout. Links expire after 24 hours.
- **No active subscription inside ChatGPT/Codex:** Tell the person they need an active HYBRD subscription (can go to app.hybrd.com) and wait until `get_account` shows one.

## Related

- Human-readable setup page with prompts and deep links: https://www.hybrd.com/mcp
- Tool and scope reference: https://www.hybrd.com/docs/tools
- Token refresh for custom OAuth clients: https://www.hybrd.com/resources/mcp-token-refresh/skill.md
- Troubleshooting: https://www.hybrd.com/resources/mcp-troubleshooting/skill.md
