# Connect an AI agent to Roundr

> Roundr is a beginner-friendly golf log. Track hole-by-hole rounds, then let Cursor or Claude analyze your progress over MCP.

Roundr exposes one MCP server. There are no API keys, no REST endpoints and no client registration step. If you are an agent reading this, the short version is: add the URL below, tell your human a browser window will open, and call `whoami` once it closes.

## Endpoint

- **MCP URL:** `https://roundrgolf.app/mcp`
- **Transport:** Streamable HTTP, stateless. `POST` for JSON-RPC, `GET` for the optional event stream.
- **Auth:** OAuth 2.1 with PKCE, issued by Clerk. Bearer token in the `Authorization` header.
- **Discovery:** `https://roundrgolf.app/.well-known/oauth-protected-resource/mcp` (RFC 9728 protected-resource metadata) and `https://roundrgolf.app/.well-known/oauth-authorization-server` (authorization-server metadata).
- **Client identity:** Client ID Metadata Documents (CIMD). Any compatible client connects without being pre-registered. Dynamic Client Registration is intentionally off.

An unauthenticated request returns `401` with a `WWW-Authenticate` header pointing at the resource metadata, plus a JSON body that links back to this page.

## Connect

Claude Code:

```bash
claude mcp add --transport http roundr https://roundrgolf.app/mcp
```

Cursor, Claude Desktop, or any client that takes a JSON config:

```json
{
  "mcpServers": {
    "roundr": {
      "url": "https://roundrgolf.app/mcp"
    }
  }
}
```

In Claude Desktop use Settings, Connectors, Add custom connector, and leave Client ID and Client Secret empty.

## What happens next

1. The client fetches the discovery documents above and starts an OAuth flow.
2. A browser opens on a Clerk-hosted page. The person signs in, or creates a Roundr account right there if they do not have one. No prior sign-up is needed.
3. They approve access. The client receives a token scoped to that one account.
4. Call `whoami`. It returns the signed-in user id and how many rounds exist. An empty log is still a successful connection.

Each connection only sees that person's rounds. They can revoke it from their Clerk account at any time.

## Tools

| Tool | Access | Purpose |
| --- | --- | --- |
| `whoami` | read | Confirm the connection: who is signed in, how many rounds exist. |
| `list_courses` | read | Courses with ids, slugs, pars and tees. Filter by city or type. Needed before log_round. |
| `get_course_scorecard` | read | Hole-by-hole par, stroke index and yardage per tee for one course. |
| `list_rounds` | read | Rounds, newest first, with per-round stats. Filter by course, type, date range, limit. |
| `get_round` | read | Hole-by-hole detail and computed stats for one round, including tee club. |
| `get_stats` | read | Aggregate stats over a filter, including fairway % by tee club. Call twice with two date windows to compare periods. |
| `get_trends` | read | Chronological per-round series for progress analysis. |
| `get_hole_stats` | read | Per-hole averages on one course: where strokes are lost. |
| `get_handicap` | read | Golf Canada / WHS handicap index from acceptable 9- and 18-hole scores, with which differentials count and known gaps versus Golf Canada. |
| `log_round` | write | Create a round from hole-by-hole data, including optional teeClub. Needs a courseId from list_courses. |
| `update_round` | write | Replace an existing round after a bad log. Same fields as log_round (including optional teeClub) plus roundId from get_round. |
| `delete_round` | write | Permanently delete one of your rounds (duplicate or logged by mistake). |

Prompt: `analyze_progress`. Guided review of recent rounds: trends, weaknesses, what to practice.

### Typical flows

- **First look:** `whoami`, then `list_rounds` with a small limit, then `get_stats` for the last 30 days.
- **Progress review:** `get_trends`, then `get_stats` twice with an earlier and a later window, then `get_hole_stats` for the course played most. Keep pitch and putt separate from full-length courses.
- **Log a round:** `list_courses` to get a `courseId` and tee name, then `log_round` with one entry per hole. `gir` is inferred from strokes and putts when omitted. Optional `teeClub` per hole is `Driver`, `3W`, `5W`, `Hybrid`, `4i` to `9i`, `PW`, `GW`, `SW`, `LW`, or `Putter`. Set `playedWithOthers` to false for a solo round; it is logged but excluded from the handicap.
- **Correct a round:** `get_round` for the id from `list_rounds`, change the wrong hole or metadata (including `teeClub`), then `update_round` with the full payload (`log_round` fields plus `roundId`). This replaces the whole round; send every hole, not just the one you are fixing. `delete_round` removes a duplicate or a round logged by mistake.

## Limits and conventions

- Dates are `YYYY-MM-DD`. Course types are `pitch_putt`, `executive` and `championship`.
- `list_rounds` caps at 500 rounds per call.
- The handicap index follows Golf Canada / WHS as closely as logged data allows (Adjusted Gross Score / net double bogey, last 20 differentials, 9-hole expected-score approximation, soft/hard cap). It needs at least three acceptable 9- or 18-hole scores played with others on rated tees. It is not a certified Golf Canada index: PCC is usually 0, the 9-hole expected-score table is unpublished, and scores that exist only on Golf Canada are missing.
- Course data is public. Round data is private to the account.

## Links

- Site: https://roundrgolf.app
- Courses (public, no account): https://roundrgolf.app/courses
- This page as Markdown: https://roundrgolf.app/docs/mcp.md
- Index for agents: https://roundrgolf.app/llms.txt
