Skip to main content
Glama
README.md
# screen-recorder-mcp

> MCP server that gives Claude and AI agents start/stop control over full-screen recordings on macOS — powered by FFmpeg avfoundation.

[![CI](https://github.com/jakubkrzysztofsikora/screen-recording/actions/workflows/ci.yml/badge.svg)](https://github.com/jakubkrzysztofsikora/screen-recording/actions/workflows/ci.yml)

---

## What Is This?

This is a [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server that wraps macOS screen recording via FFmpeg's avfoundation input. It lets Claude, or any MCP-compatible AI agent, start and stop full-desktop screen recordings with a simple tool call — no manual terminal commands needed.

Perfect for recording demos, bug reproductions, or documentation walkthroughs driven entirely by AI.

## Demo

```
You:    "Record my screen to ~/Desktop/demo.mp4 in high quality"
Claude: calls start_recording(output_path: "~/Desktop/demo.mp4", quality: "high")
        "Recording started! Screen index: 1, FPS: 30, Quality: high."

        ... you do the demo ...

You:    "Stop the recording"
Claude: calls stop_recording()
        "Recording stopped. Saved to ~/Desktop/demo.mp4 (34s, 12.8 MB)"
```

## Prerequisites

| Requirement | How to get it |
|-------------|---------------|
| **macOS 12+** | Monterey or later |
| **FFmpeg** | `brew install ffmpeg` |
| **Node.js 18+** | `brew install node` or [nodejs.org](https://nodejs.org) |
| **Screen Recording permission** | System Settings (see [Permissions Setup](#permissions-setup)) |

## Installation

### Claude Desktop

Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "screen-recorder": {
      "command": "npx",
      "args": ["screen-recorder-mcp"]
    }
  }
}
```

Then restart Claude Desktop.

### Claude Code

Add as an MCP server — works immediately without restart:

```bash
claude mcp add screen-recorder -- npx screen-recorder-mcp
```

Then in any Claude Code conversation:

```
You: "List my screen devices"
You: "Start recording my screen"
You: "Stop the recording"
```

To remove:

```bash
claude mcp remove screen-recorder
```

### Global Install

```bash
npm install -g screen-recorder-mcp
```

### Cursor / VS Code / Other MCP Clients

Add to your MCP client's configuration file (e.g., `.cursor/mcp.json`, `.vscode/mcp.json`):

```json
{
  "mcpServers": {
    "screen-recorder": {
      "command": "npx",
      "args": ["screen-recorder-mcp"]
    }
  }
}
```

### Smithery Registry

This server is listed on [Smithery](https://smithery.ai) for one-click installation in compatible MCP clients.

## Permissions Setup

Screen recording on macOS requires explicit user consent:

1. Open **System Settings**
2. Navigate to **Privacy & Security** > **Screen Recording**
3. Enable your terminal application (Terminal, iTerm2, Warp, VS Code, etc.)
4. **Restart** the terminal application after granting permission

> **Note:** If recording fails with a permission error, the tool returns a structured error with these exact instructions.

## Available Tools

| Tool | Description | Key Params |
|------|-------------|------------|
| [`start_recording`](#start_recording) | Start full-screen recording | `output_path`, `screen_index`, `audio_index`, `fps`, `quality`, `preset` |
| [`stop_recording`](#stop_recording) | Stop active recording | (none) |
| [`get_recording_status`](#get_recording_status) | Check if recording is active | (none) |
| [`list_recordings`](#list_recordings) | List all past recordings | `limit` |
| [`list_screen_devices`](#list_screen_devices) | Discover screens & audio devices | (none) |

---

### `start_recording`

Start recording the macOS desktop. Only one recording can be active at a time.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `output_path` | string | auto-generated | Output `.mp4` file path. Relative paths resolve to `~/Movies/screen-recordings/` |
| `screen_index` | number | primary display | avfoundation device index (use `list_screen_devices` to find) |
| `audio_index` | number | none | Audio device index. Omit for no audio, `-1` to explicitly disable |
| `fps` | number | `30` | Frames per second (1-60) |
| `quality` | string | `"medium"` | `"low"` (CRF 35), `"medium"` (CRF 28), `"high"` (CRF 18) |
| `preset` | string | `"ultrafast"` | FFmpeg preset: `ultrafast`, `superfast`, `veryfast`, `faster`, `fast` |

<details>
<summary>Example response</summary>

```json
{
  "success": true,
  "session_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "output_path": "/Users/you/Movies/screen-recordings/recording-2025-03-22-143012.mp4",
  "message": "Recording started. Screen index: 1, FPS: 30, Quality: medium. Use stop_recording to end."
}
```

</details>

### `stop_recording`

Stop the active recording. Sends a graceful `q` signal to FFmpeg and waits for the file to finalize.

<details>
<summary>Example response</summary>

```json
{
  "success": true,
  "session_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "output_path": "/Users/you/Movies/screen-recordings/recording-2025-03-22-143012.mp4",
  "duration_seconds": 47,
  "file_size_bytes": 15234048,
  "file_size_human": "14.5 MB",
  "message": "Recording stopped. File saved to ... (47s, 14.5 MB)"
}
```

</details>

### `get_recording_status`

Check whether a recording is in progress, and get elapsed time.

<details>
<summary>Example response</summary>

```json
{
  "status": "recording",
  "is_recording": true,
  "current_session": { "id": "...", "startedAt": "...", "outputPath": "..." },
  "elapsed_seconds": 23,
  "total_recordings": 5
}
```

</details>

### `list_recordings`

Returns past recordings sorted by most recent first.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `limit` | number | `20` | Max recordings to return |

### `list_screen_devices`

Discover available screens and audio devices. Run this first if you're unsure which `screen_index` or `audio_index` to use.

<details>
<summary>Example response (multi-monitor setup)</summary>

```json
{
  "screen_devices": [
    { "index": 1, "name": "Capture screen 0", "type": "screen" },
    { "index": 2, "name": "Capture screen 1", "type": "screen" }
  ],
  "audio_devices": [
    { "index": 0, "name": "Built-in Microphone", "type": "audio" },
    { "index": 1, "name": "BlackHole 2ch", "type": "audio" }
  ],
  "recommended_screen_index": 1,
  "ffmpeg_version": "6.1.2"
}
```

</details>

## Use Cases

### AI-Driven Demo Recording
Let Claude record polished product demos while you narrate and click through the UI. Ask it to start, pause at key moments, and stop — all through natural conversation.

### Automated Bug Reproduction
Have Claude record your screen while you reproduce a bug, then reference the recording when filing issues. Especially useful in QA workflows where evidence is required.

### Documentation Walkthroughs
Record step-by-step tutorials with Claude managing the recording lifecycle. Combine with voice narration for instant how-to videos.

### CI/CD Visual Testing
Integrate screen recordings into automated test pipelines to capture visual regressions or end-to-end test flows.

### Pair Programming Sessions
Record your coding sessions with Claude Code as a pair programming partner. Review recordings later to document architectural decisions.

## Usage Examples

**Record a demo:**
> "Start recording my screen to ~/Desktop/demo.mp4, high quality"
> *... do the demo ...*
> "Stop the recording and tell me the file size"

**Record with audio:**
> "List my screen devices, then start recording screen 1 with my built-in microphone"

**Multi-monitor:**
> "List screen devices, start recording the second monitor"

**Low-resource recording:**
> "Start a screen recording at 15 fps, low quality, ultrafast preset"

**Check what's recording:**
> "What's the current recording status? How long has it been going?"

**Review past recordings:**
> "List my last 5 recordings with their file sizes"

## Error Handling

All tools return structured errors with resolution hints — they never throw unhandled exceptions to the MCP client:

```json
{
  "success": false,
  "error_type": "ScreenRecordingPermissionError",
  "error": "Screen Recording permission not granted.",
  "resolution": "Open System Settings > Privacy & Security > Screen Recording > enable your terminal app."
}
```

| Error Type | Cause | Resolution |
|------------|-------|------------|
| `FfmpegNotFoundError` | ffmpeg not in PATH | `brew install ffmpeg` |
| `ScreenRecordingPermissionError` | macOS permission denied | Enable in System Settings |
| `RecordingAlreadyActiveError` | Tried to start while recording | Call `stop_recording` first |
| `NoActiveRecordingError` | Tried to stop with nothing active | Check `get_recording_status` |
| `InvalidOutputPathError` | Bad file path or extension | Use a path ending in `.mp4` |

## Troubleshooting

| Problem | Solution |
|---------|----------|
| "ffmpeg not found" | `brew install ffmpeg` |
| "Permission denied" / blank recording | Grant Screen Recording permission in System Settings |
| Recording starts but file is 0 bytes | Wrong avfoundation device index — use `list_screen_devices` |
| No audio in recording | Add `audio_index` param — use `list_screen_devices` to find device |
| High CPU during recording | Use `preset: "ultrafast"` and lower `fps` |

## How It Works

```
Claude (MCP Client)          screen-recorder-mcp           FFmpeg
        |                            |                        |
        |-- start_recording -------->|                        |
        |                            |-- spawn ffmpeg ------->|
        |                            |   -f avfoundation      |
        |                            |   -i "3:none"          |
        |                            |   -vcodec libx264      |
        |<-- session_id, path -------|   recording...         |
        |                            |                        |
        |-- stop_recording --------->|                        |
        |                            |-- stdin: "q\n" ------->|
        |                            |          (graceful)     |
        |                            |<-- exit 0 -------------|
        |<-- duration, size ---------|                        |
```

## Development

```bash
git clone https://github.com/jakubkrzysztofsikora/screen-recording.git
cd screen-recorder-mcp
npm install

npm run dev          # Run server in dev mode (tsx)
npm test             # Run unit tests
npm run test:coverage # Run tests with coverage report
npm run typecheck    # TypeScript strict mode check
npm run build        # Build to dist/
npm run check-deps   # Verify ffmpeg + list devices
npm run inspect      # Open MCP Inspector
```

### Project Structure

```
src/
  index.ts       # MCP server entry point & tool registration
  recorder.ts    # FFmpeg process management (start/stop/status)
  devices.ts     # avfoundation device discovery
  storage.ts     # Recording file registry (in-memory + disk manifest)
  types.ts       # All shared TypeScript types & error classes
tests/
  recorder.test.ts
  devices.test.ts
  storage.test.ts
```

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, coding standards, and PR checklist.

## License

[MIT](LICENSE)

TDQS

A4.4/5.0

Scored across 5 tools

Disambiguation5/5

Each tool maps to a distinct lifecycle concern: starting, stopping, querying active status, listing recorded files, and enumerating capture devices. There is no functional overlap between any pair.

Naming Consistency5/5

All tool names follow a consistent snake_case verb_noun pattern with clear verbs: start, stop, get, list. The naming style is uniform and predictable.

Tool Count5/5

Five tools is well-scoped for a screen recorder: no redundant helpers or missing essentials. Each tool earns its place in the workflow.

Completeness5/5

The domain of screen recording is covered end-to-end: device discovery, start, stop, status, and listing past recordings. There are no obvious dead ends or missing operations for this use case.

Maintenance

ActivityInactive
ResponsivenessNo issues