Skip to main content
Glama
inslot2525-ctrl

ring-partner-mcp

README.md
# ring-partner-mcp

An [MCP](https://modelcontextprotocol.io) server for the **Ring Partner API** (the API behind the
[Ring Appstore](https://developer.ring.com)). It lets AI agents read the Ring devices a user has shared with your app:

> *"Did anyone ring the doorbell while I was out?"*
> *"Is the back door sensor online?"*
> *"Show me the porch from the last 10 minutes."*

## Why

Ring ships an MCP server for its **documentation**, which is great for writing integration code. Nothing exposes a user's
actual **devices and events** to agents. This server does, read-only, over stdio for desktop agents (Claude, Kiro,
Cursor, VS Code) or Streamable HTTP (MCP spec 2025-11-25) for remote agents such as an Alexa+ integration.

## Tools

All tools are read-only (`readOnlyHint: true`).

| Tool | What it does | Ring endpoints |
|---|---|---|
| `ring_list_devices` | Devices with kind (`camera`, `contact_sensor`, …), online state and end-to-end encryption | `/v1/devices`, `/status`, `/capabilities`, `/configurations` |
| `ring_get_device` | Full status, capabilities and configuration for one device | same, per device |
| `ring_get_event_history` | Doorbell presses, motion (with `motion.human` etc. filters), live views, newest first, paginated | `/v1/history/devices/{id}/events` |
| `ring_get_snapshot` | Latest recorded JPEG in the last N minutes, returned as MCP image content | `/media/image/download` (303 → pre-signed URL) |

Things it handles so agents don't have to:

- **Device kind from capabilities.** Ring returns unsupported capabilities as `null`, and the device list doesn't say what a device is.
- **End-to-end encrypted cameras** (TAKE/E2EE) are reported and never asked for media, since it would be unreadable.
- **Pre-signed media URLs** are fetched without forwarding your bearer token.
- **Common errors** come back in plain language: `MEDIA_NOT_FOUND` (nothing recorded in that window), `TIME_RANGE_NOT_AUTHORIZED` (window starts before the token's access), and expired tokens.
- **History pagination** follows `links.next` up to your limit.

## Setup

Requires Node 20+.

```bash
git clone https://github.com/inslot2525-ctrl/ring-partner-mcp
cd ring-partner-mcp
npm install && npm run build
```

Credentials, either:

- `RING_ACCESS_TOKEN`: a token from the [Ring Developer Playground](https://developer.amazon.com/ring/console/playground) (valid 30 minutes), or
- `RING_REFRESH_TOKEN` + `RING_CLIENT_ID` + `RING_CLIENT_SECRET`: from Ring account linking, auto-renewed.

### Claude Code

```bash
claude mcp add ring -e RING_ACCESS_TOKEN=<token> -- node /path/to/ring-partner-mcp/dist/index.js
```

### Claude Desktop, Kiro, Cursor, VS Code (stdio)

```json
{
  "mcpServers": {
    "ring": {
      "command": "node",
      "args": ["/path/to/ring-partner-mcp/dist/index.js"],
      "env": { "RING_ACCESS_TOKEN": "<token>" }
    }
  }
}
```

### Streamable HTTP

```bash
RING_ACCESS_TOKEN=<token> node dist/index.js --http --port 3333
# → http://127.0.0.1:3333/mcp
```

The server holds a Ring token, so it binds to localhost by default and refuses any other host unless
`MCP_HTTP_TOKEN` is set. Clients must then send `Authorization: Bearer <MCP_HTTP_TOKEN>`. For a public deployment,
put it behind HTTPS.

## Privacy

- Read-only: no tool changes device settings.
- The server instructions tell agents not to try to identify people in snapshots (Ring's Appstore policies prohibit facial recognition).
- Event history only covers events after the user granted your app consent, as Ring enforces server-side.

## Notes from testing against the Playground

- The Playground device streams live video but doesn't **record** live-view sessions, so snapshot and clip downloads return `416 MEDIA_NOT_FOUND`. Real devices with a Ring subscription record normally.
- Snapshot windows that start before the token was issued return `403 TIME_RANGE_NOT_AUTHORIZED`.

## Development

```bash
npm test         # MCP client ↔ server tests against a fake Ring API modeled on real Playground responses
npm run typecheck
npm run dev      # run from source with tsx
```

## License

MIT. Not affiliated with or endorsed by Ring or Amazon.