Deployment

This page covers the two main deployment topics for the MCP server: configuring HTTPS (required in production) and setting the correct public URL when the server runs behind a reverse proxy. Both topics must be addressed before clients can connect reliably in a non-local environment.

For a full list of the configuration keys referenced on this page, see Configuration reference.

Initial setup

A brand-new binary has no database schema, admin user, or access-control lists, so sign-in and the MCP OAuth flow fail until the database is initialized. Run the binary once with the --initialize flag from the directory that contains it:

./planet9 --initialize

On Windows the binary is planet9.exe, so run planet9.exe --initialize. The command sets up the schema, seeds the default admin user, and exits. Start the server normally afterward. Skipping this step is a common cause of "MCP won’t connect" on new machines. See Troubleshooting: a fresh instance rejects sign-in or returns no tools.

HTTPS and local development

OAuth 2.1 requires HTTPS in production. The MCP server enforces this at startup and refuses to run with a plain HTTP public URL outside of development mode.

Production HTTPS

For production deployments, configure SSL in the Neptune DXP - Open Edition configuration:

{
  "enableSSL": true,
  "sslPort": 8443,
  "sslKey": "/path/to/key.pem",
  "sslCert": "/path/to/cert.pem"
}

After SSL is enabled, the MCP server uses https:// in all metadata documents and OAuth challenges.

Local development

For local development, you can run the MCP server over plain HTTP. The behavior depends on the hostname:

  • http://localhost and http://127.0.0.1 always work, regardless of NODE_ENV.

  • For other hostnames — for example, http://mcp-dev.internal — set NODE_ENV=development and start the process with MCP_DANGEROUSLY_ALLOW_INSECURE_ISSUER_URL=1.

    Never set MCP_DANGEROUSLY_ALLOW_INSECURE_ISSUER_URL=1 in a production environment. The flag disables the protection that prevents OAuth metadata from advertising insecure URLs.

The same scheme rule applies to mcpPublicUrl: it must match the protocol the server actually runs (http:// for local HTTP, https:// only when SSL is enabled or a TLS-terminating proxy is in front). A mismatch does not raise an error — the client’s authorization flow simply never completes. As of this release the mismatch is also logged as a warn at startup, and the runtime symptom is documented at Troubleshooting: the connection silently fails on localhost.

Client behavior with plain HTTP varies:

  • Claude Code generally accepts HTTP for local servers.

  • Claude Desktop may require HTTPS. Configure SSL in Neptune DXP - Open Edition if needed.

Reverse proxy deployments

When Neptune DXP - Open Edition sits behind a reverse proxy, for example, nginx, an AWS Application Load Balancer, Cloudflare, or a Kubernetes ingress controller, the URL that clients use is not the URL that the server binds to. Without explicit configuration, the MCP server builds its OAuth metadata from the bind URL and advertises endpoints that clients cannot reach.

Configure the public URL

To make the MCP server advertise the correct public URL, set the mcpPublicUrl configuration key (or the equivalent environment variable PLANET9_MCP_PUBLIC_URL) to the URL clients will use:

{
  "port": 8080,
  "ip": "127.0.0.1",
  "mcpPublicUrl": "https://mcp.planet9.com"
}

Supply scheme and host only. Do not include a path or a trailing slash. The value is used for:

  • The authorization-server issuer URL and resource server URL.

  • The advertised .well-known metadata documents.

  • The WWW-Authenticate challenge issued when the client is unauthenticated.

Leave mcpPublicUrl empty in single-host or local-development setups. The bind URL is then used as a fallback.

Alternatively, set the same value from the Cockpit: go to System SettingsAIMCP, and enter the Public URL. This writes the same mcpPublicUrl value and does not require the --overwrite step described below, which only applies to edits made directly to the configuration file.

Applying configuration changes

Neptune DXP - Open Edition hydrates its runtime configuration from a database table on each worker startup, then writes the result back to the configuration file. Editing mcpPublicUrl in the configuration file and restarting the server does not persist the change on its own — the database value wins.

To push a configuration-file edit through to the database, start the server once with the --overwrite flag:

# binary installation
planet9 --overwrite

# from source or in development
npm run start:dev -- --overwrite

The process clears the settings row, re-synchronizes from the configuration file, and exits. Start the server normally afterward. The same applies to any configuration key that is loaded from this table — mcpPublicUrl is one common example.

Changing mcpPublicUrl after clients have authenticated invalidates every existing session. Tokens are bound to the original public URL. The server refuses tokens whose audience does not match the new value. Connected clients must repeat the authorization flow. Schedule URL changes during a maintenance window if you have many active clients.