hyprland-mcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| HYPRLAND_INSTANCE_SIGNATURE | No | The Hyprland instance signature, needed if running outside the Hyprland session. Defaults to auto-detected from environment. |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| list_windowsA | List all open windows (clients) with their address, class, title, workspace, position, size, and floating/fullscreen state. |
| get_active_windowB | Get the currently focused/active window. |
| focus_windowA | Focus a window by its unique address (from list_windows) or by class/title regex selector (e.g. 'class:^(firefox)$'). |
| close_windowA | Close a window by address or selector. Sends the same signal as clicking the close button (not force-kill). |
| kill_active_windowA | Force-kill the currently focused window (hl.dsp.window.kill(), the 0.55+ equivalent of the old killactive dispatcher). |
| move_window_to_workspaceB | Move a window to a different workspace. |
| move_active_windowC | Move the active window by a pixel delta, or to an absolute position. |
| resize_active_windowA | Resize the active window by a pixel delta, or to an exact size. |
| toggle_floatingA | Toggle floating mode for a window (or the active one if no target given). |
| toggle_fullscreenC | Toggle fullscreen for the active window. |
| pin_windowA | Pin the active window so it stays visible across all workspaces. Only works on FLOATING windows — Hyprland rejects pinning a tiled window with a 'Window does not qualify to be pinned' warning (not an error; the call succeeds but has no effect). Use toggle_floating first if this warns and the window should stay pinned. |
| list_workspacesA | List all workspaces across all monitors, including window counts and last-focused window. |
| get_active_workspaceA | Get the currently active workspace on the focused monitor. |
| switch_workspaceA | Switch the focused monitor to a given workspace. |
| move_workspace_to_monitorB | Move an entire workspace (and all its windows) to a different monitor. |
| rename_workspaceC | Rename a workspace by id. |
| toggle_special_workspaceA | Show or hide a named special workspace (Hyprland's version of a scratchpad) on the current monitor. To put a window INTO a special workspace in the first place, use move_window_to_workspace with workspace set to 'special:' — this tool only toggles its visibility. Confirmed: hl.dsp.workspace.toggle_special('name') (bare string arg, not a table). |
| list_monitorsA | List all connected monitors with resolution, position, scale, refresh rate, and active workspace. |
| focus_monitorA | Move focus to a given monitor. NOTE: unlike window/workspace dispatchers, the 0.55+ Lua path for monitor focus isn't documented anywhere confirmable at authoring time — this guesses hl.dsp.focus() (the same top-level dispatcher used for window focus) also accepts a |
| set_monitor_configA | Apply a monitor config via 'hyprctl keyword monitor', same syntax as hyprland.conf's monitor= line. Useful for resolution/position/scale/enable-disable changes. Unlike 'dispatch', 'keyword' is a config-value setter rather than the dispatch mechanism that changed in 0.55, so this should be unaffected — but if it errors on your version, the Lua equivalent is likely hl.config({ monitor = { ... } }), which isn't reachable through this tool's escape hatches (they're dispatch-only) and would need a small code change. |
| hyprland_dispatchA | Escape hatch: run any Hyprland dispatcher not covered by a dedicated tool. As of Hyprland 0.55, |
| hyprctl_rawA | Escape hatch: run any raw hyprctl subcommand that ISN'T 'dispatch' — e.g. 'reload', 'version', 'splash', 'layers', 'devices', 'systeminfo'. These take plain argv, not Lua expressions (only 'dispatch' changed syntax in 0.55). Pass '-j' yourself as the first arg if you want JSON output. |
| get_config_optionA | Read the current value of a Hyprland config option, e.g. 'general:gaps_in' or 'decoration:rounding'. |
| set_config_optionA | Set a Hyprland config option at runtime via 'hyprctl keyword'. This does NOT persist to hyprland.conf — it's a live, in-memory override until reload. Good for experimenting before writing the value into the actual config file. |
| reload_hyprland_configA | Reload hyprland.conf (equivalent to 'hyprctl reload'). |
| get_hyprland_versionA | Get the running Hyprland version, commit, and build flags. |
| list_keybindsA | List all configured keybindings, including modmask, key, dispatcher, and argument. |
| send_notificationA | Send a desktop notification via notify-send (requires a notification daemon like mako or dunst running). If notify-send is unavailable, falls back to Hyprland's built-in hl.notification.create — but a real-session test confirmed this fallback produces NO VISIBLE notification even though the underlying call succeeds without error (likely a Hyprland 0.55.4 rendering gap, not a bug in this call). Practically: if notify-send isn't installed, treat this tool as non-functional and tell the user to install a real notification daemon rather than assuming the fallback message means something appeared. |
| dismiss_notificationsB | Dismiss all currently visible Hyprland built-in on-screen notifications. UNVERIFIABLE as of this writing: send_notification's fallback was confirmed to produce no visible notification in the first place, so there was nothing on a real session to confirm this actually clears. The underlying call (hl.notification.get() + :dismiss() per handle) runs without erroring, but that's equally consistent with 'it worked' and 'it iterated over nothing'. Given send_notification's fallback is effectively non-functional right now, this tool likely has nothing to do in practice either. |
| take_screenshotA | Capture a screenshot with grim. Captures the whole layout (all monitors) by default, or a single output if 'monitor' is given. Requires grim to be installed. |
| take_region_screenshotA | Interactively capture a screen region: opens slurp so you can click-drag a selection on your actual screen right now, then captures it with grim. This blocks until a region is selected (Escape cancels). Requires grim and slurp. |
| screenshot_active_windowA | Screenshot just the currently focused window, cropped via grim -g using the window's box from hyprctl activewindow. |
| toggle_launcherA | Open Hyprland's first-party app launcher/picker (hyprlauncher), or close it if it's already open. hyprlauncher runs as a self-managing daemon: the first call starts the daemon and shows its window; every call after that just toggles the window, near-instantly, without restarting the daemon. Use this for 'open the launcher' / 'let me search for an app' style requests. |
| prewarm_launcher_daemonA | Start the hyprlauncher daemon in the background WITHOUT opening its window (hyprlauncher -d). Useful once at session start so the first real toggle_launcher call is instant rather than paying daemon-startup cost. Safe to call even if the daemon is already running. |
| tag_windowA | Add, remove, or toggle a static tag on a window. Tags are used for grouping windows and can be matched in window rules (e.g. hl.window_rule({ match = { tag = 'code' }, ... })). Confirmed syntax: hl.dsp.window.tag({ tag = '+code' }) adds, '-code' removes, 'code' (no prefix) toggles. |
| toggle_groupA | Make a group from the active window (like i3wm's 'tabbed' container), or ungroup it if it's already grouped. Confirmed: hl.dsp.group.toggle(). |
| group_cycleA | Cycle to the next or previous window within the active group. Confirmed: hl.dsp.group.next() and hl.dsp.group.prev(). |
| toggle_group_lockA | Lock/unlock the active group so new windows can't (or can) join it automatically. Confirmed path: hl.dsp.group.lock(); exact toggle-vs-explicit-state argument shape isn't documented anywhere I could confirm, so this calls it with no arguments (assumed toggle, matching the pattern of group.toggle()). If it doesn't behave as expected, try hyprland_dispatch with a raw_expression like "hl.dsp.group.lock({ action = 'toggle' })" instead. |
| deny_window_from_groupB | Prevent a window from being added to a group, or from becoming a group itself. NOTE: this is documented as existing ('the window.deny_from_group dispatcher') but its Lua path is a best-effort guess (hl.dsp.window.deny_from_group) by analogy with the other window.* dispatchers — not directly confirmed. Verify before relying on it. |
| move_cursorB | Move the cursor to absolute screen coordinates. Confirmed: hl.dsp.cursor.move({ x, y }). |
| move_cursor_to_cornerB | Move the cursor to one of a window's four corners. Confirmed: hl.dsp.cursor.move_to_corner({ corner, window? }). |
| set_sunset_temperatureA | Set hyprsunset's color temperature in Kelvin (lower = warmer/more orange, e.g. 2500-4000 for a strong blue-light filter; higher, e.g. 6500, is closer to neutral daylight). This override is temporary and will be replaced once hyprsunset's next scheduled profile activates. |
| disable_sunset_filterA | Disable hyprsunset's blue-light filter entirely, returning color temperature to normal (hyprctl hyprsunset identity). Temporary — reverts at the next scheduled profile. |
| set_sunset_gammaA | Set or adjust hyprsunset's gamma (perceived brightness). Absolute percent (e.g. '50' = 50%) or a relative delta with an explicit sign (e.g. '+10', '-10'). Max is 150% by default, raisable via max-gamma in hyprsunset.conf, hard-capped at 200%. Using gamma for brightness degrades color accuracy — prefer real monitor brightness control (DDC/backlight) if available. |
| reset_sunsetA | Reset hyprsunset override(s) back to whatever the current time-based profile specifies. NOTE: a Hyprland forum bug report (hyprsunset v0.3.3) found this specific command returns 'invalid command' while temperature/identity/gamma work fine — if you hit that, there's no clean workaround short of manually calling set_sunset_temperature/set_sunset_gamma/disable_sunset_filter with the values your profile should have at the current time. |
| get_sunset_profileA | Print hyprsunset's currently active time-based profile. NOTE: the same forum bug report affecting reset_sunset also reported this command as broken on hyprsunset v0.3.3 — if it errors, that's a known upstream issue, not a wiring problem here. |
| set_wallpaperA | Set the wallpaper for a monitor (or the fallback for all monitors that don't have one specifically assigned, if monitor is omitted). Loads the image on demand — no separate preload step needed on current hyprpaper versions. |
| list_active_wallpapersA | List the currently active wallpaper path for each monitor. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/keanehatescoding/hyprland-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server