Skip to main content
The Orkestral MCP server is a standalone package (@orkestral/mcp) that exposes your Orkestral workspace over the Model Context Protocol (MCP). You register it in an MCP client like Claude Code, and the client gains tools to read and edit your knowledge base, plus read your issues, sources, and workspace overview. The server talks to the same local database the desktop app uses (~/.orkestral/instances/default/db/orkestral.db, in WAL mode). You do not need the app open: both processes share the SQLite file safely thanks to WAL and a busy timeout. The package also ships a orkestral CLI and an optional local REST API that reuse the same core and tools.

Knowledge base

The KB that this server reads and edits.

Workspaces

Each MCP session targets one workspace.

What it is

The server is a thin transport layer over Orkestral’s shared core. It bundles the app’s schema, repositories, and the single KB tool registry (kb-mcp-tools) via esbuild, so there is one source of truth: only the transport differs between the desktop app’s embedded server and this standalone process.
The package exists separately because the desktop app’s better-sqlite3 is compiled for the Electron ABI. A plain Node process (what claude mcp add -- npx ... runs) cannot load it. So this package keeps its own node_modules with better-sqlite3 built for the Node ABI.

Requirements

  • Node.js 20 or later (engines.node is >=20).
  • An existing Orkestral database at ~/.orkestral/instances/default/db/orkestral.db, created by running the desktop app at least once and creating a workspace.
  • At least one workspace in that database. Use orkestral workspaces (or the list_workspaces tool) to find workspace ids.
  • An MCP client that speaks stdio, such as Claude Code.
The standalone server reuses native modules that must match your local platform and Node ABI. If you install from a clone, run npm install so better-sqlite3 compiles for your Node version before building.

Set it up

1

Build the package (local install)

From a clone of the package:
cd orkestral-mcp
npm install     # compiles better-sqlite3 for the Node ABI
npm run build   # esbuild → dist/index.js (MCP) + dist/cli.js (CLI)
2

Find your workspace id

orkestral workspaces
This lists each workspace as id and name. Copy the id you want the server to target.
3

Register the server in Claude Code

Point Claude Code at the built entry, passing the workspace id:
# local (after build):
claude mcp add orkestral -- node /path/to/orkestral-mcp/dist/index.js --workspace <id>

# via npx (after the package is published to NPM):
claude mcp add orkestral -- npx -y -p @orkestral/mcp orkestral mcp --workspace <id>
Without --workspace, the server resolves the target on its own if there is exactly one workspace in the database.
4

Confirm the tools are available

In your MCP client, list the available tools. You should see list_workspaces, the kb_* tools, and the workspace read tools described below.

Configuration options

You configure the server through command flags or environment variables passed at registration time.
--workspace, -w <id>
string
Target workspace, by id or name (name match is case-insensitive). If omitted, the server uses the only workspace when exactly one exists. With multiple workspaces and no flag, calls fail until you re-register with a workspace.
ORKESTRAL_WORKSPACE
env var
Alternative to --workspace. The server reads this environment variable when no --workspace flag is present.
--status <s>
string
CLI-only filter for orkestral issues. One of backlog, todo, in_progress, in_review, blocked, done, cancelled.
--limit <n>
number
CLI-only result cap for list commands (KB search and issues).
--port <n>
number
default:"3100"
Port for orkestral serve (the local REST API). The server binds to 127.0.0.1 only.
The database path is fixed: the server always opens ~/.orkestral/instances/default/db/orkestral.db. There is no flag to point it elsewhere.

Transport

The MCP server speaks JSON-RPC 2.0, newline-delimited, over stdio. It implements initialize, notifications/initialized, ping, tools/list, and tools/call. The default reported protocol version is 2025-06-18, and it echoes the client’s protocolVersion when one is provided.
stdout is exclusively the protocol channel. All internal logs (including database open messages) go to stderr. Do not write anything else to stdout, or you will corrupt the stream. The server already redirects console.log to stderr to protect the channel.
Tool results come back as a single text content block containing pretty-printed JSON. Tool errors are returned in the result with isError: true rather than as JSON-RPC errors.

Available tools

The server exposes 20 tools. Knowledge base tools come from the shared registry; the rest are standalone discovery and read tools.
ToolPurpose
kb_searchBM25 search across the knowledge base.
kb_get_pageRead one page by id or slug.
kb_get_page_treeThe page tree for the workspace.
kb_get_backlinksPages that link to a given page.
Issues and sources are read-only in the standalone server. Creating an issue triggers agent execution, which is the desktop app’s responsibility, so the server does not expose write tools for it.

CLI

The bundled orkestral CLI hits the same shared database directly. It is handy for quick checks and for launching the server.
CommandDescription
orkestral workspacesList workspaces (id + name).
orkestral kb search <terms...>BM25 search in the KB.
orkestral kb treePage tree.
orkestral kb get <id|slug>Read one page.
orkestral issues [--status <s>]List issues.
orkestral issue <key>Read one issue by number.
orkestral sourcesList repos and folders.
orkestral infoWorkspace overview plus goals.
orkestral mcpRun the MCP stdio server.
orkestral serve [--port 3100]Run the local REST API.
Like the server, the CLI writes results to stdout and logs to stderr, so you can pipe output safely.

REST API

orkestral serve exposes the same core and tools over HTTP on 127.0.0.1 (localhost only). Choose the workspace per request with ?workspace=, the x-orkestral-workspace header, or fall back to the default.
GET    /workspaces
GET    /kb/search?q=&limit=     GET  /kb/tree           GET /kb/page/:idOrSlug
POST   /kb/page                 PATCH /kb/page/:idOrSlug DELETE /kb/page/:idOrSlug
GET    /issues?status=&limit=   GET  /issues/:key
GET    /sources                 GET  /info
GET / and GET /health return a small status object. Unknown routes return 404; tool errors return 400 with an error message.

Capabilities and limits

  • Shared database: reads and writes land in the same SQLite file as the desktop app. Changes are visible across both processes.
  • Self-contained: the published package bundles the app core, with better-sqlite3 and drizzle-orm as runtime dependencies, so npx -y @orkestral/mcp works after publish.
  • One workspace per process: each registered server instance targets a single resolved workspace (except list_workspaces, which works without one).
  • No issue or source writes: those flows belong to the desktop app.
  • No remote access: the REST API binds to localhost only; there is no network listener for the MCP transport (it is stdio).

Troubleshooting

The server could not resolve a single workspace. Re-register with --workspace <id> (or set ORKESTRAL_WORKSPACE). Run orkestral workspaces or call list_workspaces to get the ids. This happens when the database has zero or multiple workspaces and no flag was given.
The reference did not match any workspace id and no name matched (case-insensitive). The error lists the available workspaces as name (id). Copy an exact id from orkestral workspaces.
The native module must match your Node ABI. Run npm install then npm run build from the package with the same Node version you launch the server with. Confirm Node is 20 or later.
The server opens ~/.orkestral/instances/default/db/orkestral.db. Open the desktop app once and create a workspace so the database and schema exist.
Something wrote to stdout outside the JSON-RPC channel. Make sure you launch the server through its dist/index.js entry (or orkestral mcp) and do not pipe extra output into it. Internal logs belong on stderr.
Pass ?workspace=<id> or the x-orkestral-workspace header per request. Without either, the server uses the default resolved at serve startup.
Start the server with node dist/index.js --workspace <id> directly in a terminal to watch the stderr startup line. It reports the resolved workspace (or the reason it could not resolve one) before any client connects.