Plugins

Plugins here means MCP servers. DeckSpace ships two of them and writes one config file. That file is one CLI’s convention, and DeckSpace never calls a plugin itself.

The word “plugin” does not appear in the app. What exists is MCP: two stdio servers bundled with the source, a single .mcp.json written into your workspace, and a connection test. This page is about what that actually reaches. The short version is that it reaches one agent CLI, and only when you run DeckSpace from a source checkout.

The two servers DeckSpace ships

Both are Node scripts in the repo’s mcp/ directory. Both speak MCP over stdio. Neither is a network service.

ServerScriptToolsWhat it exposes
opxmemoryopxmemory-server.mjs12The workspace’s .opxmemory/ markdown vault.
opxmemory_globalopxmemory-server.mjs12The same server pointed at the cross-workspace vault in the app data directory.
opxboardopxboard-server.mjs12The app’s SQLite board — projects, tasks, agent configs.

The memory tools are list_memories, read_memory, create_memory, append_memory, search_memories, recall, find_backlinks, related_notes, link_notes, get_daily, list_tags, notes_by_tag. The board tools are developer_guide, list_projects, create_project, list_tasks, get_task, create_task, update_task, list_agents, get_agent, create_agent, update_agent, delete_agent.

The board server opens the desktop app’s own database — on macOS ~/Library/Application Support/ai.opxera.deckspace/opxspace.db — in WAL mode, so a CLI agent and the app read and write the same board. You can point it elsewhere with OPXSPACE_DB or a path argument, but the config DeckSpace writes passes neither.

Installing one, and what it reaches

A plugin is one JSON file naming a command to run. Drop it in DeckSpace’s plugins directory — the Plugins room shows you the exact path, and opens it for you — and the filename becomes the plugin’s id, so weather.json installs weather. Only .json files are read.

Open the room, press Connect, and DeckSpace starts the server, completes the MCP handshake and lists what it offers.

Connected means connected to Atlas — not to your panes

This is the part worth reading before you install anything. A connected plugin’s tools go to Atlas, the assistant. The agent CLIs running in your panes do not get them, with one exception: Claude Code, which reads the .mcp.json DeckSpace writes into your workspace.

That is one of the eleven CLIs. Codex, Grok, Aider and the rest receive nothing from a connected plugin, because nothing writes their config formats yet. The room says so next to the connection rather than in a footnote.

Every plugin tool asks first

Plugin tools appear to Atlas namespaced as <server>__<tool>, and every one of them takes a confirmation before it runs — there is no allow-list and no quiet default.

The reasoning is worth knowing, because it looks over-cautious until it does not: a tool’s schema describes what it accepts, never what it does. A tool called notes__read with a single string parameter looks harmless and can do anything its author wrote. DeckSpace cannot inspect third-party code, so it does not pretend to classify it.

A broken plugin tells you why

If a declaration cannot work — the command is missing, the file will not parse — the room shows the actual reason in place of a Connect button, rather than offering a button that fails. The bundled servers have a separate health check that spawns them, handshakes, counts tools and reports the real error.

Which agent CLI actually receives a plugin

DeckSpace writes exactly one file: <workspace>/.mcp.json, containing an mcpServers object with the three keys above. The source calls it “a Claude-Code-style .mcp.json”, and that is precisely the scope of it. DeckSpace writes no other agent configuration — no config.toml, no per-CLI file under a dot-directory, nothing.

Agent CLIKeyMCP config DeckSpace writes for it
Claude Codeclaudegets .mcp.json
Codexcodexgets .mcp.json
Aideraidergets .mcp.json
Antigravityagygets .mcp.json
Gemini (legacy CLI)geminigets .mcp.json
OpenCodeopencodegets .mcp.json
Cursor Agentcursorgets .mcp.json
Droiddroidgets .mcp.json
Copilot CLIcopilotgets .mcp.json
Grok CLIgrokgets .mcp.json
Ampampgets .mcp.json
Qwen Codeqwengets .mcp.json
Any custom CLI you registeryoursgets .mcp.json
What that table is, exactly

It is what DeckSpace writes. It is not a claim about what each CLI can read. Several of these CLIs support MCP through configuration of their own — but DeckSpace does not write it, does not detect it, and does not check it. If you want the memory or board servers in Codex, Cursor, or anything else on the roster, you configure that CLI yourself.

The Memory room has a panel for this. Open Memory, expand Use as agent memory (MCP) at the bottom of the note list, and it prints a ready-made line for the one CLI it targets:

claude mcp add opxmemory -- node <mcp-dir>/opxmemory-server.mjs <workspace>

The panel’s second suggestion is worth knowing about before you copy it. Under “or drop a project .mcp.json” it renders the text invoke memory_install_mcp(root, <mcp-dir>). That is the name of an internal backend command, not a shell command and not a button. The frontend does expose a wrapper for it, and nothing in the app calls that wrapper. You cannot run it from the UI.

When the file gets written — and when it does not

There is one automatic route to .mcp.json: adding a workspace. It fires when you create a workspace in the setup wizard, and when you ask Atlas to add one. That is the whole list.

SituationDoes DeckSpace write .mcp.json?
You add a workspace
Setup wizard, or Atlas adding one for you.
yes, once
A workspace already in your rail
Restored from a previous run.
written on restore
Switching to another workspacewritten on switch
A swarm worktree
Each builder’s own checkout.
written for worktrees
App start with no workspace
The backend is given a directory, but no workspace is created.
written at startup

The write itself is careful, and that part is genuinely good. If no file exists it writes the whole thing. If a valid file exists it merges in only the keys that are absent and leaves every existing entry byte-identical, yours or ours, preserving key order. If the file is invalid JSON, or its mcpServers is not an object, it is left completely untouched and the result is reported as left_untouched with the parse error attached.

Reported to nobody

The call is fire-and-forget. The backend returns a result with status (created, merged, unchanged or left_untouched), the list of keys it added, and the reason it gave up — and the frontend discards all of it. Only a thrown error is handled, and that goes to console.warn.

So if your .mcp.json has a trailing comma, DeckSpace silently declines to touch it and you get no toast, no badge, no log you will ever look at. Adding a workspace looks identical either way. Read the file yourself if you care whether it worked.

The path it writes is only correct from a source checkout

This is the part to read before you trust the file.

DeckSpace resolves its mcp/ directory in three steps, in order:

  1. The directory next to the Rust crate, using the path baked in at compile time — this is the build machine’s path, and it is checked by testing whether opxmemory-server.mjs exists there.
  2. The bundled resource directory inside the installed app, checked the same way.
  3. Failing both, the bare relative path mcp.

Step two cannot succeed. The bundle configuration ships exactly one resource directory, and mcp/ is not it. No build script copies the folder in. The two server scripts also import the MCP SDK by bare name, and the board server needs better-sqlite3; both are npm dependencies of the DeckSpace repo, resolved from its node_modules, which the bundle does not ship either.

Where DeckSpace is running fromResolved mcp dirWhat lands in .mcp.json
A source checkout
Built and run from the repo.
The repo’s mcp/Absolute paths that exist.
The installed app
Downloaded, dragged to Applications.
The literal string mcp"args": ["mcp/opxmemory-server.mjs", "<root>"] — relative, resolved against whatever directory the CLI happens to be in.
A correct-looking file that mounts nothing

The writer never checks that the script it is pointing at exists. It writes the path it was handed. In an installed build that produces a valid, well-formed .mcp.json naming three servers whose command cannot be found — and, because the write is fire-and-forget, it reports success by saying nothing at all.

It gets worse on the second pass. The merge only adds absent keys and never modifies an entry that is already there. Once a bad path is in the file, DeckSpace will report unchanged forever and never correct it. Fix it by hand, or delete the file and add the workspace again.

Check with cat <workspace>/.mcp.json. If the first argument is not an absolute path to a file that exists, the servers are not going to start.

Test connection, and what it does not test

In the same Memory panel there is a Test connection button. It is not a config check — it actually spawns the server, performs the real handshake, and reports either the tool count or the real error text: server script not found: …, or failed to start node (…) — is Node.js installed and on PATH?, or whatever the server printed to stderr before dying. There is a 12-second deadline. It reports success only when at least one tool name came back, so it cannot go green on a server that answered with an empty list.

That is a good test. These are the four things it does not cover.

GapConsequence
It tests two servers, not three
Only memory and board.
opxmemory_global is written into your config and never tested.
It does not read your .mcp.json
It resolves the directory itself.
A green tick says DeckSpace can find a server. It says nothing about the path in the file your CLI will read.
An empty root falls through
The server takes its root from the argument, then an environment variable, then the current directory.
With no workspace selected the button passes an empty string, and the test passes against whatever directory the app process is in — not your vault.
It uses the login-shell PATH to find NodeYour agent CLI uses its own. Node being findable here does not mean it is findable there.
Node is required

Both servers are Node scripts and the config invokes them as node. If Node is not on the PATH of the process that launches your CLI, the servers fail to start. The health check names this failure explicitly rather than reporting a silent zero, which is the one place in this feature where a failure is loud.

There is no code-search MCP server

The Pro tier’s feature list includes the line “Repo-aware autocomplete + code search MCP”. The entitlement table declares a feature named code_mcp, commented “expose the code index over MCP”, gated at the Pro tier. The in-app help for Code Search says agents can use the index over MCP.

None of that is wired to anything:

  • The two occurrences of code_mcp in the source are its type declaration and its tier entry. Nothing ever asks whether you have it.
  • The code-index backend module contains no MCP code of any kind.
  • The repo contains two MCP servers. Neither exposes the code index.
The index is reachable, but not over MCP

Code Search is real — the app builds the index and you can search it from inside DeckSpace. What does not exist is a server that hands that index to an outside agent CLI. Do not plan a workflow around a CLI querying your code index over MCP.

What you can do today

  1. Check the file before trusting it. cat <workspace>/.mcp.json. The first argument of each server must be an absolute path to a script that exists.
  2. Fix a relative path once, by hand. DeckSpace will not rewrite an entry it already sees, so your edit sticks.
  3. Add other servers freely. The merge never modifies or removes an entry it did not write, so a foreign server you add to the same file survives every later workspace add.
  4. Configure non-Claude CLIs yourself. The launch line in the Memory panel gives you the command and arguments; every CLI on the roster other than Claude Code needs you to put those into its own config.
  5. Use Test connection to diagnose Node, not to validate your config. It answers a different question than the one you are asking.
  6. Expect nothing in a swarm worktree. Builders get their own checkouts and no .mcp.json is written into them — see Swarm and worktrees.