Connect Character App to your agent

One URL gives your harness your Worlds, Cast, the Bible, Library, Scenes, Clips, Films and Episodes — the durable state, consent and money rails, and rendering stay here; your agent supplies the creative judgment.

MCP endpoint
https://mcp.character.app/mcp?profile=writer
Transport
Streamable HTTP (POST /mcp)
Sign-in
OAuth 2.1 — scope email only
Discovery
https://mcp.character.app/.well-known/oauth-protected-resource/mcp
First call
get_creative_workspace — read-only orientation for your account

Pick a tool preset

A preset narrows which tools your connection exposes. Choosing one rewrites every snippet below with ?profile=<id>.

Per-harness setup

Codex (Headless via bearer header)

codex mcp add charactr --url https://mcp.character.app/mcp?profile=writer
codex mcp login charactr --scopes email

Or paste into ~/.codex/config.toml:

[mcp_servers.charactr]
url = "https://mcp.character.app/mcp?profile=writer"
tool_timeout_sec = 120
# headless: bearer_token_env_var = "CHARACTR_TOKEN"

Sign-in: codex mcp add charactr --url <url> writes the config and immediately opens a browser, blocking on a localhost callback. Its default OAuth request asks for `openid profile email phone offline_access`; the platform now publishes an ES256 signing key, so `openid` is expected to work, but a consented `openid` exchange has not yet been witnessed — if `codex mcp add` fails at the token exchange, sign in with the scoped `codex mcp login charactr --scopes email` line instead.

A bearer token is a short-lived (~1h) Supabase access token.

Claude Code (No-browser OAuth path)

claude mcp add --transport http -s user charactr https://mcp.character.app/mcp?profile=writer

Or paste into ~/.claude.json under "mcpServers":

{
  "mcpServers": {
    "charactr": {
      "type": "http",
      "url": "https://mcp.character.app/mcp?profile=writer"
    }
  }
}

Sign-in: claude mcp login charactr — opens a browser. On a machine with no browser, claude mcp login charactr --no-browser prints the authorization URL and reads the pasted redirect back.

A typeless { "url" } block is a configuration error in Claude Code — the "type": "http" field is required.

Claude Desktop (Needs one browser sign-in)

Claude app → Settings → Connectors → Add custom connector → name it charactr → URL: https://mcp.character.app/mcp?profile=writer

Sign-in: OAuth consent inside the app — the config file has no remote-URL field.

Same on claude.ai: Settings → Connectors → Add custom connector. A config-file MCP registration only covers local stdio servers here.

Cursor (Headless via bearer header)

{
  "mcpServers": {
    "charactr": {
      "url": "https://mcp.character.app/mcp?profile=writer"
    }
  }
}

One-click install

Goes in ~/.cursor/mcp.json

Sign-in: OAuth on first use — the client registers itself (DCR), no sign-up step.

Headless: add "headers": { "Authorization": "Bearer $CHARACTR_TOKEN" } to the same entry.

Devin CLI (Headless via bearer header)

devin mcp add charactr -s user --transport http --scopes email https://mcp.character.app/mcp?profile=writer
devin mcp login charactr --scopes email

Or paste into ~/.config/devin/mcp_config.json:

{
  "mcpServers": {
    "charactr": {
      "url": "https://mcp.character.app/mcp?profile=writer",
      "transport": "http"
    }
  }
}

Sign-in: devin mcp add writes the config and immediately opens the browser sign-in — its OAuth callback listens on the fixed port 8765, so the browser must run on the same machine.

Windsurf's Devin Local agent (the default for new tabs) reads this same Devin config — no separate Windsurf setup needed there. Headless/CI: "headers": { "Authorization": "Bearer $CHARACTR_TOKEN" } on the same entry, or .devin/mcp_config.local.json for one project.

Gemini CLI (Headless via bearer header)

{
  "mcpServers": {
    "charactr": {
      "httpUrl": "https://mcp.character.app/mcp?profile=writer"
    }
  }
}

Goes in ~/.gemini/settings.json

Sign-in: Browser OAuth on first use — no browserless OAuth flow is documented.

The remote key is "httpUrl", not "url". Headless: "headers": { "Authorization": "Bearer $CHARACTR_TOKEN" } on the same entry. A workspace .gemini/settings.json overrides the user file.

VS Code (Headless via bearer header)

{
  "servers": {
    "charactr": {
      "type": "http",
      "url": "https://mcp.character.app/mcp?profile=writer"
    }
  }
}

One-click install

Goes in User mcp.json — Command Palette → "MCP: Open User Configuration"

Sign-in: Browser OAuth on first connect.

The root key is "servers", not "mcpServers". Also works: code --add-mcp '{"name":"charactr","type":"http","url":"https://mcp.character.app/mcp?profile=writer"}'. Agent Host never forwards ${input:…} variables — use a literal "headers" bearer there.

Windsurf (Headless via bearer header)

{
  "mcpServers": {
    "charactr": {
      "serverUrl": "https://mcp.character.app/mcp?profile=writer"
    }
  }
}

Goes in ~/.codeium/windsurf/mcp_config.json

Sign-in: OAuth on first use.

This file configures the legacy Cascade agent only. New Windsurf tabs run the Devin Local agent, which reads the Devin CLI config — use the Devin CLI entry above for them.

Zed (Needs one browser sign-in)

{
  "context_servers": {
    "charactr": {
      "url": "https://mcp.character.app/mcp?profile=writer"
    }
  }
}

Goes in ~/.config/zed/settings.json under "context_servers"

Sign-in: OAuth on first use.

No verified static-header path for remote servers — plan on one browser sign-in.

ChatGPT (Needs one browser sign-in)

Settings → Connectors → Developer Mode → New app → URL: https://mcp.character.app/mcp?profile=writer → auth: OAuth

Sign-in: OAuth only — there is no bearer-header field, so a browser sign-in is mandatory.

Needs ChatGPT developer mode. Refresh tokens keep the connection alive past access-token expiry.

Any other MCP client (Headless via bearer header)

{
  "mcpServers": {
    "charactr": {
      "type": "http",
      "url": "https://mcp.character.app/mcp?profile=writer"
    }
  }
}

Sign-in: The client runs its own OAuth prompt and consent screen.

Any client that speaks streamable HTTP. If it accepts a static "Authorization: Bearer …" header, a fresh Supabase access token serves headless for about an hour.

Headless, honestly

OAuth 2.1 is the only door — Character App does not issue a long-lived API key yet. Clients that take a static Authorization bearer header can run headless with a fresh Supabase access token, but that token lives about an hour: fine for CI smoke checks, not a durable install. Claude Code has a true no-browser OAuth path (claude mcp login charactr --no-browser); every other harness needs one browser sign-in on the same machine the callback listens on.

Request only the advertised scope email. Codex's default OAuth request asks for openid profile email phone offline_access; the platform now publishes an ES256 signing key, so openid is expected to work, but a consented openid exchange has not yet been witnessed — if codex mcp add fails at the token exchange, sign in with codex mcp login charactr --scopes email. Where a client offers no scope override and no bearer-header option, it cannot connect headless today.