Summary
The plugin-bundled MCP server config in [.claude-plugin/plugin.json] hardcodes DATABASE_URL=postgresql://localhost:5432/cortex in the mcpServers.cortex.env block. Claude Code merges this over the user's shell environment when launching the MCP server, so users running Postgres on any non-localhost host (remote DB, separate LXC, Docker network hostname, non-default port, or requiring credentials) hit a silent connection failure — regardless of what they set in ~/.claude/settings.json or their shell.
Reproduction
Run Postgres somewhere other than localhost:5432 (e.g., postgresql:5432 on a local network).
Set DATABASE_URL=postgresql://user:pass@postgresql:5432/cortex in ~/.claude/settings.json env block (or shell profile).
Restart Claude Code and call any Cortex MCP tool.
Observe:
RuntimeError: PostgreSQL connection failed. Cortex requires PostgreSQL in CLI mode.
Run: bash setup.sh to configure PostgreSQL.
Or set CORTEX_RUNTIME=cowork to allow SQLite fallback.
The hooks (which run via scripts/launcher.py and inherit the shell env) connect fine, but the MCP server — launched directly by Claude Code from plugin.json — gets the hardcoded localhost value.
Root cause
In .claude-plugin/plugin.json:
"mcpServers": {
"cortex": {
"command": “uvx”,
"args": ["--python", "3.13", "--from", "neuro-cortex-memory[postgresql]", "neuro-cortex-memory”],
"env": {
"DATABASE_URL": "postgresql://localhost:5432/cortex”
}
}
}
Claude Code's MCP server launch merges this env block over the user's shell env, so the hardcoded value always wins.
The generic error message also masks the real problem — mcp_server/infrastructure/memory_store.py::_try_pg catches the OperationalError: connection refused and logs it at WARNING level, but the caller only raises a generic "PostgreSQL connection failed" — so users don't see the actual host/port the server tried.
Proposed fixes
Any of these would work:
Drop the env block entirely. Let the user's shell DATABASE_URL pass through. The plugin already defaults to postgresql://localhost:5432/cortex in memory_config.py if nothing is set.
Use a shell-expansion default. If Claude Code supports ${DATABASE_URL:-postgresql://localhost:5432/cortex} substitution in plugin.json env values, that preserves the sensible default while letting users override.
Surface the real exception. In _try_pg, include the str(exc) (at minimum host/port) in the RuntimeError message so users can diagnose network/credential problems without reading plugin source. The hint could also mention: "If DATABASE_URL is set, verify it points to a reachable Postgres instance.”
Workaround
Edit ~/.claude/plugins/cache/cortex-plugins/cortex//.claude-plugin/plugin.json directly and replace the DATABASE_URL value. Note this gets wiped on plugin updates.
Environment
Cortex 3.5.1
macOS 15.4 (Darwin 25.4.0)
Claude Code VSCode extension
Postgres 17 on separate LXC (postgresql:5432), pgvector installed, cortex database exists and is reachable via direct psycopg.connect() from the same Python env that uvx resolves for the MCP server.
Summary
The plugin-bundled MCP server config in [.claude-plugin/plugin.json] hardcodes DATABASE_URL=postgresql://localhost:5432/cortex in the mcpServers.cortex.env block. Claude Code merges this over the user's shell environment when launching the MCP server, so users running Postgres on any non-localhost host (remote DB, separate LXC, Docker network hostname, non-default port, or requiring credentials) hit a silent connection failure — regardless of what they set in ~/.claude/settings.json or their shell.
Reproduction
Run Postgres somewhere other than localhost:5432 (e.g., postgresql:5432 on a local network).
Set DATABASE_URL=postgresql://user:pass@postgresql:5432/cortex in ~/.claude/settings.json env block (or shell profile).
Restart Claude Code and call any Cortex MCP tool.
Observe:
RuntimeError: PostgreSQL connection failed. Cortex requires PostgreSQL in CLI mode.
Run: bash setup.sh to configure PostgreSQL.
Or set CORTEX_RUNTIME=cowork to allow SQLite fallback.
The hooks (which run via scripts/launcher.py and inherit the shell env) connect fine, but the MCP server — launched directly by Claude Code from plugin.json — gets the hardcoded localhost value.
Root cause
In .claude-plugin/plugin.json:
"mcpServers": {
"cortex": {
"command": “uvx”,
"args": ["--python", "3.13", "--from", "neuro-cortex-memory[postgresql]", "neuro-cortex-memory”],
"env": {
"DATABASE_URL": "postgresql://localhost:5432/cortex”
}
}
}
Claude Code's MCP server launch merges this env block over the user's shell env, so the hardcoded value always wins.
The generic error message also masks the real problem — mcp_server/infrastructure/memory_store.py::_try_pg catches the OperationalError: connection refused and logs it at WARNING level, but the caller only raises a generic "PostgreSQL connection failed" — so users don't see the actual host/port the server tried.
Proposed fixes
Any of these would work:
Drop the env block entirely. Let the user's shell DATABASE_URL pass through. The plugin already defaults to postgresql://localhost:5432/cortex in memory_config.py if nothing is set.
Use a shell-expansion default. If Claude Code supports ${DATABASE_URL:-postgresql://localhost:5432/cortex} substitution in plugin.json env values, that preserves the sensible default while letting users override.
Surface the real exception. In _try_pg, include the str(exc) (at minimum host/port) in the RuntimeError message so users can diagnose network/credential problems without reading plugin source. The hint could also mention: "If DATABASE_URL is set, verify it points to a reachable Postgres instance.”
Workaround
Edit ~/.claude/plugins/cache/cortex-plugins/cortex//.claude-plugin/plugin.json directly and replace the DATABASE_URL value. Note this gets wiped on plugin updates.
Environment
Cortex 3.5.1
macOS 15.4 (Darwin 25.4.0)
Claude Code VSCode extension
Postgres 17 on separate LXC (postgresql:5432), pgvector installed, cortex database exists and is reachable via direct psycopg.connect() from the same Python env that uvx resolves for the MCP server.