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
访问服务器

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

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选