dream-os

dream-os

MCP server for Dream OS, enabling Claude to read, add, update, remove, and move desktop gadgets, capture ideas, and manage a transparent overlay through a set of 8 tools.

Category
Visit Server

README

Dream OS

A transparent, nestable desktop element layer for Windows — that Claude can build on.

Rainmeter-style widgets rendered in web tech, sitting on your desktop under your real windows. The difference: Dream OS ships an MCP server, so Claude can read the desktop, add gadgets, update them live, and capture your ideas — through a proper tool interface instead of you hand-editing config files.

Styled after the Freelancer (2003) HUD, because that game's UI is nested translucent frames — which is exactly what this is.

┌─ Claude ──┐   stdio    ┌─ MCP server ─┐   HTTP    ┌─ Dream OS ─┐
│  tools    │ ────────►  │  8 tools     │ ────────► │  desktop   │
└───────────┘            └──────────────┘  :8787    └────────────┘

What it does

  • Transparent full-desktop overlay with dynamic click-through — clicks pass to whatever is underneath, and the layer only becomes solid while your cursor is over a gadget.
  • Sits under your windows. It's a desktop layer, not an always-on-top nag.
  • Nestable elements. Drop a gadget into a group and it becomes a DOM child, so dragging the parent moves everything inside it with zero extra code.
  • Drag, resize, persist. Layout survives restarts.
  • Claude-drivable. Everything above is reachable over MCP.

The toolbag

Every gadget is one self-registering file in renderer/elementals/:

defineElemental('clock', {
  label: 'Clock',
  size: { w: 210, h: 120 },
  render(node, ctx) { /* return an HTMLElement */ },
});

Shipped elementals:

type what it is
capture zero-friction idea box; Enter files a timestamped line
note free text that persists
clock time + date readout
group pure container — drag it, children follow
text static label / paragraph
markdown rendered markdown (safe subset, everything escaped)
list bulleted or checkable list
meter labelled progress bars with tone colouring
status named lamps: ok / warn / bad / idle
table simple data table with sticky headers
log scrolling line feed
link clickable shortcuts (URL or file path)

A gadget reads everything from node.props, which is exactly what Claude writes over the API — so anything you can build by hand, Claude can build too.

MCP tools

tool purpose
dreamos_state list what's on the desktop
dreamos_elementals list the toolbag and each type's props
dreamos_add add an element (optionally nested)
dreamos_update move / resize / retitle / patch props
dreamos_remove delete an element and its children
dreamos_move re-parent an element
dreamos_capture append to the capture log
dreamos_read_captures read the capture log back

The MCP server has zero dependencies — plain Node, newline-delimited JSON-RPC.

Install

npm install
npm start

Quick launch

Dream OS.bat brings up the overlay and both local voice services in one go, and Stop Dream OS.bat shuts them all down. Running it twice is safe — anything already listening is skipped, so it doubles as a "make sure everything is up" command.

.\launch.ps1            # start whatever isn't already running
.\launch.ps1 -Stop      # shut everything down
.\launch.ps1 -NoVoice   # overlay only, skip the speech services

Cold start is about 20 seconds, most of it Kokoro loading its 325 MB model.

Register the MCP server with Claude Code (.mcp.json in your project, or your user config):

{
  "mcpServers": {
    "dream-os": {
      "command": "node",
      "args": ["C:/path/to/dream-os/mcp/server.js"]
    }
  }
}

Dream OS must be running — the MCP server bridges to its control API and will say so plainly if it can't reach it.

Shortcuts

There's a tray icon too — left-click toggles the layer, right-click for the full menu (show/hide, edit, float on top, capture box, data folder, quit).

key action
Ctrl+Alt+H hide / show the layer
Ctrl+Alt+D toggle edit mode (headers, drag handles, toolbar)
Ctrl+Alt+N jump to the capture box
Ctrl+Alt+T float above everything (toggle)
Ctrl+Alt+Q quit — the escape hatch

Talking to Claude from the desktop

The claude elemental is a message box wired to the Claude desktop app. Type, press Enter: the text goes on the clipboard, Claude is focused, pasted and sent. The reply comes back by tailing Claude's own session transcript at ~/.claude/projects/<project>/<session-id>.jsonl.

It costs no extra tokens — it's the same conversation, just a different surface. Records in that transcript are typed, so filtering thinking / tool_use / tool_result from the visible text is the entire "cleaner". No OCR, no screen scraping.

Tag routing

A line beginning #dream:<id> in Claude's prose updates that element — no tool call at all:

#dream:console
All systems nominal.

A JSON object payload is merged into the element's props; anything else becomes props.text. Guards: the element must already exist, the tag must start a line (so inline mentions are inert), and the element flashes gold when touched so the magic is at least visible.

Icon

build/gen-icon.js generates the icon as a real PNG with zero image dependencies — hand-rolled CRC32 and zlib chunks — so it can be re-themed from the same colour values as the CSS rather than living as a binary blob.

node build/gen-icon.js

Where it sits (Wallpaper Engine, Fences, Rainmeter)

Windows has no arbitrary "layers". There is one z-order for normal windows, plus a wallpaper layer (WorkerW) beneath it where Wallpaper Engine and the Fences background live. Fences popups — and every application — are ordinary top-level windows.

So "above the wallpaper, below everything else" is exactly one call:

SetWindowPos(hwnd, HWND_BOTTOM, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE)

Electron doesn't expose it, so zorder.js reaches it through koffi (prebuilt, no node-gyp). Dream OS parks at the bottom on startup and re-sinks on blur, so interacting with a gadget raises it briefly and it drops back afterwards. Ctrl+Alt+T pins it above everything when you want the HUD in front.

If koffi is unavailable the module degrades to no-ops and the app still runs — it just won't stay underneath.

Theming

One block at the top of renderer/style.css drives everything:

--h:    258;   /* base hue — 210 blue · 288 purple · 160 green · 20 amber */
--lum:   27%;  /* master darkness. lower = darker */

Panels, insets, borders, text and glow all derive from those via hsl().

Control API

Loopback only, port 8787.

GET    /health          GET    /state[?flat=1]      POST /state
GET    /elementals      POST   /elements            GET  /elements/:id
PATCH  /elements/:id    DELETE /elements/:id        POST /elements/:id/move
GET    /captures        POST   /captures

seed-desktop.js is a worked example that builds a whole desktop through it.

Development

renderer/app.js includes a shim: with no Electron preload it stubs the API and, if Dream OS is running, mirrors the live desktop over HTTP. So you can serve renderer/ as a static site and iterate on styling without relaunching the overlay.

python -m http.server 8757 --directory renderer

Notes from the build

A few things worth knowing, found the hard way:

  • Elements are DOM children, not separate OS windows. One window per widget is the obvious Rainmeter-style approach, but then nesting means manually syncing window positions on every drag. As DOM nodes, nesting is free.
  • .dp-body needs min-height: 0. Flex items default to min-height: auto, which lets content push the inset box out past the panel border.
  • Don't use setPointerCapture for dragging. It routes events to the element and silently kills the whole drag if it throws. Window-level capture-phase listeners are robust, and survive a fast drag outrunning the cursor.
  • Atomic save can fail on EFS-encrypted directories. Where %APPDATA% carries the EFS attribute, Windows treats the encryption boundary as a device boundary: Node's fs.renameSync fails with EXDEV within a single folder, and .NET's File.Replace throws access-denied. The store attempts the atomic path and falls back to a direct write plus a .bak.

License

MIT © minidraco711

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured