MCP servers
neondeck reads MCP server config from runtime-home
mcp.json. Connected tools are registered with Flue as
mcp__<server>__<tool> and appear in new Neon sessions
after the registry refreshes.
Configuration
{
"servers": {
"linear": {
"transport": "http",
"url": "https://mcp.linear.app/mcp",
"auth": { "kind": "oauth" }
},
"local-tools": {
"transport": "stdio",
"command": "node",
"args": ["/absolute/path/to/server.mjs"],
"tools": {
"approvalMode": "writes",
"overrides": {
"dangerous_tool": "deny"
}
}
}
}
}
HTTP servers must use https:// except loopback development
hosts. Raw secrets are rejected. Header auth uses environment-variable references,
and OAuth tokens are stored only in
data/neondeck.db.
{
"servers": {
"internal": {
"transport": "http",
"url": "https://mcp.example.com/mcp",
"auth": {
"kind": "header",
"headers": {
"Authorization": { "env": "INTERNAL_MCP_AUTHORIZATION" }
}
}
}
}
}
Approval policy
MCP servers default to writes mode: tools explicitly annotated
by the MCP server as read-only run immediately, while mutations and unannotated
tools ask first. Use prompt to ask for every tool or approve to allow every tool. A per-tool override wins over the server mode:
{
"tools": {
"approvalMode": "writes",
"overrides": {
"search": "approve",
"delete_project": "deny"
}
}
}
A pending request can be allowed once, allowed for the current chat,
always allowed, or denied. Allow-once grants expire after 15 minutes,
are bound to the exact arguments, and are consumed by one retry. Chat
grants are bound to the requesting Flue conversation and remain valid
for that chat. Always allow writes an exact per-tool override to
mcp.json. Server and tool policy changes invalidate older
pending and reusable grants.
MCP annotations are hints supplied by the server. Neondeck only uses
an explicit readOnlyHint: true without a destructive hint for
the writes shortcut; unannotated tools still ask. Use
prompt for servers whose annotations you do not trust.
OAuth
OAuth servers start in needs-login until a user completes a
state-bound authorization flow. By default the callback uses Neondeck's
loopback origin. A dashboard served through an exact
server.trustedOrigins entry instead uses that configured HTTPS
origin, without trusting proxy-forwarded scheme headers. The callback exchanges
the authorization code through the MCP SDK provider and stores client registration,
PKCE verifier, discovery state, and tokens in SQLite.
neondeck mcp add linear --url https://mcp.linear.app/mcp --oauth
neondeck mcp policy linear --approval-mode writes
neondeck mcp policy linear --tool search=approve --tool delete_project=deny
neondeck mcp login linear
neondeck mcp logout linear --confirm
The dashboard Runtime Overview panel shows configured MCP servers,
OAuth login/logout controls, the server-default approval mode, exact
per-tool overrides, tool counts, connection errors, and pending MCP
approvals. The MCP provider must accept the matching callback URL,
such as
https://example.exe.xyz/api/mcp/oauth/callback for the
exe.dev nginx setup.
CLI and API
neondeck mcp list
neondeck mcp status [id]
neondeck mcp add <id> --url ... | --command ...
neondeck mcp enable <id>
neondeck mcp disable <id>
neondeck mcp tools <id>
neondeck mcp policy <id> --approval-mode prompt|writes|approve
neondeck mcp policy <id> --tool <name>=prompt|approve|deny|inherit
neondeck mcp approvals [--resolve <id> --approve [--scope once|chat|always]|--deny]
neondeck mcp audit
GET /api/mcp/servers
POST /api/mcp/servers
PATCH /api/mcp/servers/:id
DELETE /api/mcp/servers/:id
GET /api/mcp/servers/:id/tools
POST /api/mcp/servers/:id/refresh
POST /api/mcp/servers/:id/login
GET /api/mcp/logins/:id
GET /api/mcp/oauth/callback
POST /api/mcp/servers/:id/logout
GET /api/mcp/approvals
POST /api/mcp/approvals/:id/resolve
GET /api/mcp/audit
Agent boundary
Neon can use safe typed actions for HTTP/OAuth server setup and OAuth
login starts. Stdio servers, header-authenticated servers, and tool
approval policy are user-owned surfaces because they can spawn host
processes or forward environment-backed secrets. Configure those
through the CLI, local API, or direct mcp.json edits.