Skip to main content
Glama
quinho981

gnome-screencast-mcp

by quinho981

gnome-screencast-mcp

Screen recording on GNOME, controlled from the command line or by an AI agent via MCP.

Uses the native GNOME Shell recorder (the org.gnome.Shell.Screencast D-Bus interface, the same one behind the Ctrl+Alt+Shift+R shortcut). Does not depend on ffmpeg, wf-recorder, or any external capture binary.

What it's for

Automate screen recordings without touching the graphical interface: demonstrations, bug evidence, flow documentation, and logging of test sessions. Since every command returns JSON, it works for scripts as much as for an agent that needs to record what it is doing.

The problem it solves: calling GNOME's D-Bus directly does not work for recording. The Shell ends the recording as soon as the D-Bus client that started it leaves the bus, so a standalone gdbus call produces a file with a single frame and a 0:00 duration. The solution here is a helper process that keeps the connection open for the entire recording and closes it cleanly on stop — only then does the WebM come out with the correct duration and index.

Related MCP server: video-capture-mcp

Installation

Nothing to clone or compile. Four steps, from scratch to your first recorded video.

It's not on PyPI yet. For now uv installs directly from this GitHub repository — it works the same, only the command is a little longer. When we publish it to PyPI, gnome-screencast-mcp by itself is enough; the two become interchangeable.

Step 1 — check the requirements

Requirement

Why

How to check

GNOME Shell, active graphical session (Wayland or X11)

GNOME itself does the recording; tested on GNOME Shell 42

gnome-shell --version

PyGObject (python3-gi)

Keeps the D-Bus connection alive during the recording; not installable via pip

python3 -c "import gi" — if you get an error: sudo apt install python3-gi

uv

Installs and runs the package, no manual venv

uv --version — if missing: curl -LsSf https://astral.sh/uv/install.sh | sh

If all three pass without error, move to step 2.

Step 2 — install

uv tool install --from git+https://github.com/quinho981/gnome-screencast-mcp gnome-screencast-mcp

That puts three executables in your PATH:

Executable

Role

gnome-screencast-start

Starts recording from the command line.

gnome-screencast-stop

Stops recording from the command line.

gnome-screencast-mcp

MCP server (stdio transport) — this is what an AI agent calls.

If the terminal warns that the installation directory isn't on your PATH, run the command it suggests (usually uv tool update-shell) and open a new terminal.

Step 3 — test

gnome-screencast-start && sleep 3 && gnome-screencast-stop

You should get a JSON with "status": "recording", a 3-second pause, and another JSON with "status": "stopped" and duration_seconds close to 3. If that's what came out, everything is working — the .webm file is in your videos directory.

Something went wrong? Go straight to Common issues.

Step 4 — choose how to use it

  • From the command line: it's ready — see Command-line usage for the -o, -f, and -a options.

  • Through an AI agent (Claude Code, Cursor, opencode, etc.): you need to register the MCP server in your client — see MCP, which gives the step-by-step for each.

No steps: you just want MCP working in an agent

If the only use is MCP, you don't need to install anything by hand — the client itself downloads the package when it runs. Check the requirements in step 1, skip steps 2 and 3, and go straight to MCP use.

Developing the project

Only for those who will change this repository:

git clone https://github.com/quinho981/gnome-screencast-mcp
cd gnome-screencast-mcp
uv run gnome-screencast-mcp        # servidor MCP a partir do código local
bash bin/start-recording.sh        # scripts de gravação, sem instalar nada
bash bin/stop-recording.sh

Structure

File

Purpose

bin/start-recording.sh

Starts recording. Prints JSON and returns immediately.

bin/stop-recording.sh

Stops and waits for the file to be finalized.

bin/recorder-daemon.py

Helper process that holds the D-Bus connection. Don't call it directly.

gnome_screencast_mcp/server.py

MCP server; converts tool calls into script executions.

gnome_screencast_mcp/cli.py

Executables gnome-screencast-start and -stop from an installation.

.mcp.json

MCP server registration for anyone who opens this project in Claude Code.

The scripts live in bin/ so they remain usable directly from a clone; the wheel build copies them into the package, and the server finds them in both places.

Command line use

# Tela inteira, 30 fps, arquivo com data e hora em ~/Vídeos
gnome-screencast-start

# ... faça o que precisa ser gravado ...

gnome-screencast-stop

In a clone, the equivalents are bash bin/start-recording.sh and bash bin/stop-recording.sh.

start returns the file path as soon as recording starts:

{
  "status": "recording",
  "file": "/home/user/Vídeos/screencast-20260824-152940.webm",
  "mode": "screen",
  "framerate": 30,
  "draw_cursor": true,
  "started_at": "2026-08-24T15:29:40-0300",
  "pid": 183615
}

And stop returns the summary of what was recorded:

{
  "status": "stopped",
  "file": "/home/user/Vídeos/screencast-20260824-152940.webm",
  "size_bytes": 361637,
  "duration_seconds": 4.488
}

start options

Option

Effect

-o, --output FILE

Path to the output .webm. Cannot contain %.

-f, --framerate N

Frames per second (default: 30).

-a, --area X Y L A

Records only the specified rectangular region, in pixels.

-c, --no-cursor

Does not draw the mouse pointer.

Example — top-left corner, 1280×720, 60 fps, no cursor:

gnome-screencast-start -a 0 0 1280 720 -f 60 --no-cursor -o /tmp/demo.webm

stop options

Option

Effect

-t, --timeout N

Seconds to wait until the file is finalized (default: 20).

-q, --quiet

Does not print the result JSON.

Exit codes

Both commands use 0 for success and 1 for a usage or environment error. Additionally:

  • start: 2 there is already a recording in progress · 3 GNOME Shell refused to start

  • stop: 2 there is no recording in progress · 3 the file was not finalized in time

MCP use

Registering the server makes recording a capability of the agent: it calls start_recording and stop_recording as typed tools, without needing shell access.

Exposed tools

Tool

What it does

start_recording(output?, framerate=30, draw_cursor=true, area?)

Starts and returns right away. area is [x, y, width, height].

stop_recording(timeout=20)

Stops and returns path, size, and duration.

recording_status()

idle, recording (with elapsed_seconds), or stale.

recording_status is the cheap way to check before acting — it avoids trying to start a recording that already exists, or stop one that doesn't exist.

The command, in any client

The server is a regular stdio process, and the command is the same everywhere:

comando:    uvx
argumentos: gnome-screencast-mcp

If you ran uv tool install, the command is just gnome-screencast-mcp, with no arguments.

While the package is not on PyPI, use this list of arguments instead of ["gnome-screencast-mcp"] in all the examples below:

["--from", "git+https://github.com/quinho981/gnome-screencast-mcp", "gnome-screencast-mcp"]

Once the package is published, switch back to the short form — the examples are already written with it.

Two things break configurations that look right:

  1. uvx may not be on the client's PATH. Clients launched by a graphical launcher (Cursor, VS Code, Zed, Claude Desktop) usually inherit a minimal PATH, without ~/.local/bin. If the server fails with uvx: command not found, replace uvx with the output of command -v uvx — usually /home/<your-user>/.local/bin/uvx.

  2. Recording needs the session bus. GNOME's D-Bus is reached through DBUS_SESSION_BUS_ADDRESS and XDG_RUNTIME_DIR. A client launched inside your graphical session already inherits them. A client in a container, snap, flatpak, or SSH session does not — in that case, declare the two in the env block of the server:

    "env": {
      "DBUS_SESSION_BUS_ADDRESS": "unix:path=/run/user/1000/bus",
      "XDG_RUNTIME_DIR": "/run/user/1000"
    }

    The correct values for your machine come from echo $DBUS_SESSION_BUS_ADDRESS $XDG_RUNTIME_DIR in a terminal in the graphical session.

Claude Code

claude mcp add screen-recorder --scope user \
  -- uvx --from git+https://github.com/quinho981/gnome-screencast-mcp gnome-screencast-mcp

Once published to PyPI, it simplifies to -- uvx gnome-screencast-mcp.

Restart the session and confirm with /mcp that screen-recorder appears connected.

Inside this repository you don't even need that: the versioned .mcp.json here already registers the server from the local code — just approve it when opening the directory.

Codex CLI

codex mcp add screen-recorder \
  -- uvx --from git+https://github.com/quinho981/gnome-screencast-mcp gnome-screencast-mcp

Once published to PyPI, it simplifies to -- uvx gnome-screencast-mcp.

Or manually, in ~/.codex/config.toml:

[mcp_servers.screen-recorder]
command = "uvx"
args = ["gnome-screencast-mcp"]

opencode

In opencode.json at the root of your project, or in ~/.config/opencode/opencode.json to apply to everything:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "screen-recorder": {
      "type": "local",
      "enabled": true,
      "command": ["gnome-screencast-mcp"]
    }
  }
}

This assumes the uv tool install from step 2 of the install — the command is just the executable name, already resolved by PATH. opencode marks the server as failed (and flips enabled back to false on its own) if the command doesn't come up on the first try, and uvx gnome-screencast-mcp falls into that case until the package is on PyPI: every call would try to resolve it there and fail. If you prefer not to install it permanently, the form that works without installing is the same git+ note from the other clients in the cross-client command section:

"command": ["uvx", "--from", "git+https://github.com/quinho981/gnome-screencast-mcp", "gnome-screencast-mcp"]

opencode is the one case where the command is a single list, rather than a separate command and args.

Cursor

In ~/.cursor/mcp.json (global) or .cursor/mcp.json (project only):

{
  "mcpServers": {
    "screen-recorder": {
      "command": "uvx",
      "args": ["gnome-screencast-mcp"]
    }
  }
}

Cursor is launched by the graphical environment: if it does not connect, the most likely reason is a PATH without uvx. See item 1 of the any-client command section.

Gemini CLI

gemini mcp add screen-recorder \
  uvx --from git+https://github.com/quinho981/gnome-screencast-mcp gnome-screencast-mcp

Once published to PyPI, it simplifies to uvx gnome-screencast-mcp.

Or manually, in ~/.gemini/settings.json (global) or .gemini/settings.json (per project), in the same mcpServers format shown for Cursor.

VS Code (GitHub Copilot)

In .vscode/mcp.json in the project. Note that the key is servers, not mcpServers, and that the type is explicit:

{
  "servers": {
    "screen-recorder": {
      "type": "stdio",
      "command": "uvx",
      "args": ["gnome-screencast-mcp"]
    }
  }
}

Windsurf

In ~/.codeium/windsurf/mcp_config.json, in the same mcpServers format as Cursor.

Zed

In Zed's settings.json, under context_servers:

{
  "context_servers": {
    "screen-recorder": {
      "source": "custom",
      "command": "uvx",
      "args": ["gnome-screencast-mcp"],
      "env": {}
    }
  }
}

Claude Desktop

On Linux, in ~/.config/Claude/claude_desktop_config.json, in the same mcpServers format as Cursor. The app needs to be fully restarted after the edit.

Other clients

If your client is not listed, look in its documentation for where "MCP servers" live and provide the uvx command with the argument gnome-screencast-mcp. In practice, the ecosystem has only two format variations: the separate command + args pair (most) and the command as a single list (opencode).

Without uv

The package is a regular Python project and pip handles it:

pip install --user git+https://github.com/quinho981/gnome-screencast-mcp

(After it has been published to PyPI: pip install --user gnome-screencast-mcp.)

The client command becomes gnome-screencast-mcp, with no arguments. A dedicated virtual environment also works — in that case, point to the executable inside of it; the server removes its own venv from the PATH it passes to the scripts, so they still find the system's PyGObject.

Testing the server without a client

Before wrestling with an agent's configuration, it's worth confirming that the server comes up:

printf '%s\n' \
  '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"t","version":"1"}}}' \
  '{"jsonrpc":"2.0","method":"notifications/initialized"}' \
  '{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \
  | uvx --from git+https://github.com/quinho981/gnome-screencast-mcp gnome-screencast-mcp

(After it has been published to PyPI, uvx gnome-screencast-mcp by itself is enough.)

The initialize response should appear, followed by the three tools. On the first run, uvx also prints an installation line to stderr.

How it works

start-recording.sh
  └─ setsid recorder-daemon.py        (sobrevive ao script que o criou)
       ├─ D-Bus: Screencast(...)      → o GNOME Shell começa a gravar
       ├─ escreve o estado em $XDG_RUNTIME_DIR/screen-recorder/current.json
       └─ fica vivo, segurando a conexão, até receber SIGTERM

stop-recording.sh
  └─ SIGTERM no pid do estado
       └─ daemon: D-Bus StopScreencast pela mesma conexão
            └─ espera o GStreamer fechar o WebM e escreve o resumo final

The state file guarantees that only one recording exists at a time — a limitation of GNOME Shell itself, which supports a single simultaneous screencast session.

If the daemon dies without cleaning up (for example, on a logout), the state file is left orphaned: recording_status reports stale and the next start_recording removes it on its own.

Implementation details

Three pitfalls the package needs to work around:

  • Output capture. The server runs the scripts with output redirected to temporary files, not to pipes. The daemon inherits the output descriptors, so a pipe would only see EOF at the end of the recording — and the start_recording call would block until then.

  • Python environment. Once installed, the server runs inside a virtual environment that sits at the start of the PATH. The scripts would then resolve python3 to that environment, where the system's PyGObject doesn't exist. The server removes the venv from the environment the scripts inherit.

  • Executable bit. The scripts are invoked as bash script.sh and the daemon as python3 daemon.py, never directly: the executable permission doesn't reliably survive packaging into a wheel.

Common problems

PyGObject não encontrado — install with sudo apt install python3-gi. If it only shows up when using the MCP and not on the command line, the venv is leaking into the scripts' PATH.

The agent doesn't list the tools — the server never even started. Run the test from Testing the server without a client; if it passes, the problem is in the client's configuration, almost always uvx outside the PATH (item 1 of The command, in any client).

o GNOME Shell recusou iniciar a gravação — there is normally no accessible GNOME session. The MCP server inherits the environment of whoever started it, and D-Bus needs DBUS_SESSION_BUS_ADDRESS and XDG_RUNTIME_DIR. If the MCP client runs in a confined environment (container, snap, flatpak, service, SSH), declare both variables in the server's env block — see item 2 of The command, in any client.

gravação já em andamento — call stop_recording, or gnome-screencast-stop. To inspect the state manually: cat $XDG_RUNTIME_DIR/screen-recorder/current.json.

Video with duration 0:00 — a sign that the recording was started outside these commands, with a D-Bus client that didn't survive. Use gnome-screencast-start.

Helper process log: $XDG_RUNTIME_DIR/screen-recorder/daemon.log.

License

MIT — see LICENSE.

Publishing a version

uv build          # gera dist/*.whl e dist/*.tar.gz
uv publish        # envia ao PyPI

The version lives in pyproject.toml.

Install Server
A
license - permissive license
A
quality
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • F
    license
    A
    quality
    D
    maintenance
    Enables LLMs to capture screenshots and screen recordings through MCP with chunked session-based transfers for reliable image consumption. Supports multi-monitor selection, timeline capture, and compatibility with both vision and non-vision language models.
    11
    1
  • A
    license
    Not graded
    quality
    B
    maintenance
    Free, open-source screen recording MCP server for AI agents. Enables screen capture, screenshots, and frame extraction locally without cloud dependencies.
    7
    1
    Apache 2.0

View all related MCP servers

Related MCP Connectors

  • MCP server for Clipkit — gives AI agents a video toolbox via the Clipkit schema.

  • OCR, transcription, file extraction, and image generation for AI agents via MCP.

  • MCP connector that lets ChatGPT list, search, and run your Apple Shortcuts via a local Mac agent

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/quinho981/gnome-screencast-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server