# WriteForYou MCP — connect guide

This file is the machine-readable setup guide (no JavaScript).
Human UI: https://writer.swapp1990.org/connect
Discovery: https://writer.swapp1990.org/.well-known/mcp/server.json

## Server

| Field | Value |
|-------|--------|
| URL | `https://writer.swapp1990.org/mcp/v2/` |
| Transport | Streamable HTTP (remote MCP) |
| Trailing slash | **Required** (`/mcp/v2/` not `/mcp/v2`) |
| OAuth scopes | `openid` `profile` `email` |
| Server name | `writeforyou` (recommended in client configs) |

## Auth (pick one)

There is **no** free anonymous MCP access. Every successful tool call is
authenticated as a WriteForYou user.

### A) OAuth (browser sign-in) — primary path

**This is the normal flow.** You sign in once in a browser; the **MCP client**
stores tokens. You do **not** generate a PAT on the website for this path.

1. Add the MCP server URL (recipes below).
2. When the client prompts, complete the **web login** (Google or email/password
   through the Logto hosted sign-in). This is a real account sign-in, not a pasted API key.
3. The client stores OAuth access/refresh tokens. Subsequent calls are silent
   until reauthorization is required.

If the client shows the server as **disabled / not connected / auth required**
after add, OAuth did not finish. Use option B only as a fallback.

### B) Long-lived bearer token (mint → configure → use) — fallback

**Not the default.** Use only when OAuth cannot complete (Codex bearer-first,
headless agents, CI, or OAuth stuck on “disabled / not connected”).

You (or a human operator) mint a revocable PAT on the website while signed in;
then the client is configured with that secret. This is **not** automatic
client-side token generation from a website session cookie.

**Mint (human, while logged in on the website):**

1. Sign in at https://writer.swapp1990.org (same account that owns the stories).
2. Open https://writer.swapp1990.org/connect
3. Use **Generate** under long-lived tokens. The full token is shown **once**.
4. Store it only as env var `WRITEFORYOU_MCP_TOKEN` (or a password manager).
5. Revoke it on the same page if it leaks or when the eval ends.

Minting **requires** a signed-in browser session on WriteForYou. Agents cannot
mint a token by calling MCP while unauthenticated. Do **not** paste browser
localStorage session tokens into chat. Do **not** use admin or service tokens.

**Configure (agent or human):**

Send `Authorization: Bearer <token>` (or the client's "bearer token env var"
setting pointing at `WRITEFORYOU_MCP_TOKEN`). Client-specific recipes below.

**Use:**

Call any tool (e.g. `get_credits`, `list_stories`). Unauthenticated calls return
HTTP 401 — that is expected until OAuth completes or a bearer is configured.

## Client recipes

### ChatGPT

For a personal connection, enable Developer mode in ChatGPT under Settings →
Security and login. In Plugins, use the plus button to create a plugin from this
MCP URL: `https://writer.swapp1990.org/mcp/v2/`. Complete the WriteForYou
sign-in when prompted, review the discovered tools, and install the personal
plugin. In a Work chat, ask it to call `list_stories` to confirm the connection.
Availability depends on your account and workspace settings.

Asking ChatGPT to install WriteForYou by name requires a public Plugins
Directory listing. A custom MCP connection does not create that listing.
For that route, the publisher must submit the remote MCP server for review and
publish the approved listing. Use the personal connection above while no listing is available.

Official instructions: https://developers.openai.com/plugins/quickstart and
https://developers.openai.com/plugins/deploy/submission

### Claude Code

**OAuth:**

```bash
claude mcp add --transport http writeforyou https://writer.swapp1990.org/mcp/v2/
# all projects on this machine:
claude mcp add --scope user --transport http writeforyou https://writer.swapp1990.org/mcp/v2/
```

Then approve OAuth in the browser when prompted.

**Bearer (after minting `WRITEFORYOU_MCP_TOKEN`):**

```bash
claude mcp add --transport http writeforyou https://writer.swapp1990.org/mcp/v2/ \
  --header "Authorization: Bearer ${WRITEFORYOU_MCP_TOKEN}"
```

### Grok (xAI)

**OAuth (interactive):**

```bash
grok mcp add --transport http writeforyou https://writer.swapp1990.org/mcp/v2/
```

Then in the Grok TUI: `/mcps` → select `writeforyou` → press `i` to authorize
→ press `r` to refresh. Tokens land in `~/.grok/mcp_credentials.json`.

**Bearer (after minting `WRITEFORYOU_MCP_TOKEN`):**

```bash
# PowerShell (Windows) — set a user env var once (paste the minted token)
[Environment]::SetEnvironmentVariable("WRITEFORYOU_MCP_TOKEN", "<paste-token-here>", "User")

# restart the shell / Grok so the env var is visible, then:
grok mcp add --transport http writeforyou https://writer.swapp1990.org/mcp/v2/ --header "Authorization: Bearer ${WRITEFORYOU_MCP_TOKEN}"
grok mcp doctor writeforyou
```

`~/.grok/config.toml` should look like:

```toml
[mcp_servers.writeforyou]
url = "https://writer.swapp1990.org/mcp/v2/"
enabled = true

[mcp_servers.writeforyou.headers]
Authorization = "Bearer ${WRITEFORYOU_MCP_TOKEN}"
```

### Codex

Codex is bearer-first (mint token first):

```powershell
[Environment]::SetEnvironmentVariable("WRITEFORYOU_MCP_TOKEN", "<paste-token-here>", "User")
codex mcp remove writeforyou
codex mcp add writeforyou --url https://writer.swapp1990.org/mcp/v2/ --bearer-token-env-var WRITEFORYOU_MCP_TOKEN
```

### Cursor

One-click from https://writer.swapp1990.org/connect or `.cursor/mcp.json`:

```json
{
  "mcpServers": {
    "writeforyou": {
      "url": "https://writer.swapp1990.org/mcp/v2/",
      "transport": "http"
    }
  }
}
```

Complete OAuth when Cursor prompts, or configure a bearer header if your Cursor
build supports static headers.

### OpenCode

**OAuth:**

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "writeforyou": {
      "type": "remote",
      "url": "https://writer.swapp1990.org/mcp/v2/",
      "enabled": true
    }
  }
}
```

```bash
opencode mcp auth writeforyou
opencode mcp list
```

**Bearer (after minting `WRITEFORYOU_MCP_TOKEN`):**

```bash
opencode mcp add writeforyou --url https://writer.swapp1990.org/mcp/v2/ \
  --header "Authorization=Bearer ${WRITEFORYOU_MCP_TOKEN}"
```

(Exact `mcp add` flags may vary by OpenCode version; equivalent: remote URL +
Authorization bearer header using the minted token.)

### Claude Desktop

Add to `claude_desktop_config.json` (macOS:
`~/Library/Application Support/Claude/claude_desktop_config.json`, Windows:
`%APPDATA%\Claude\claude_desktop_config.json`):

```json
{
  "mcpServers": {
    "writeforyou": {
      "type": "http",
      "url": "https://writer.swapp1990.org/mcp/v2/"
    }
  }
}
```

Restart Claude Desktop, then complete OAuth when prompted.

## Agent checklist (curl, no browser UI)

```bash
# 1. Discover server
curl -s https://writer.swapp1990.org/.well-known/mcp/server.json

# 2. Read this guide
curl -s https://writer.swapp1990.org/.well-known/mcp/connect.md
# same content also at:
curl -s https://writer.swapp1990.org/connect.md

# 3. OAuth metadata (for clients implementing OAuth)
curl -s https://writer.swapp1990.org/.well-known/oauth-protected-resource

# 4. Smoke initialize with a minted bearer token (expect SSE initialize result)
curl -s -X POST https://writer.swapp1990.org/mcp/v2/ \
  -H "Authorization: Bearer $WRITEFORYOU_MCP_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"smoke","version":"1.0"}}}'
```

Unauthenticated POSTs return HTTP 401 with a `WWW-Authenticate` header pointing
at protected-resource metadata — that is expected, not a server outage.

## After connect

- Always surface `story_url` / `article_url` fields from tool responses to the user.
- Prefer free probes first: `list_stories`, `get_credits`, `list_models`.
- Full tool catalog and flows: https://writer.swapp1990.org/connect