# How to Configure MCP PostgreSQL Ops Server for Production: Streamable-HTTP Mode with Bearer Token Authentication

> Configure MCP PostgreSQL Ops server for production using streamable-http mode with bearer token authentication. Secure your production deployment with a secret key and Authorization header.

- Repository: [JungJungIn/mcp-postgresql-ops](https://github.com/call518/mcp-postgresql-ops)
- Tags: how-to-guide
- Published: 2026-02-26

---

**To deploy the MCP PostgreSQL Ops server in production, launch it with `--type streamable-http` and `--auth-enable`, providing a strong `--secret-key` so that every request must include an `Authorization: Bearer <token>` header or the server will reject the connection.**

The `call518/mcp-postgresql-ops` repository provides a Model Context Protocol (MCP) server for PostgreSQL operations that supports both local stdio and remote HTTP transports. For production environments requiring network accessibility, you must configure **streamable-http mode with Bearer token authentication** to secure the exposed HTTP endpoint against unauthorized access, as enforced by the startup validation logic in [`src/mcp_postgresql_ops/mcp_main.py`](https://github.com/call518/mcp-postgresql-ops/blob/main/src/mcp_postgresql_ops/mcp_main.py).

## Selecting the Streamable-HTTP Transport Mode

The transport protocol is determined by the `--type` CLI argument or the `FASTMCP_TYPE` environment variable. When set to `streamable-http`, the server binds to a configurable host and port and exposes the MCP endpoint at `/mcp` instead of using standard input/output.

According to the argument definitions in [`src/mcp_postgresql_ops/mcp_main.py`](https://github.com/call518/mcp-postgresql-ops/blob/main/src/mcp_postgresql_ops/mcp_main.py) (lines 3621-3626), the server parses these settings and passes them to the underlying `mcp.run()` method. You must specify both a host and port when using this mode, or the server will default to local-only behavior.

### Configuration via Environment Variables

For containerized deployments, set these variables in your environment or `.env` file:

```bash
FASTMCP_TYPE=streamable-http
FASTMCP_HOST=0.0.0.0
FASTMCP_PORT=8000
REMOTE_AUTH_ENABLE=true
REMOTE_SECRET_KEY=your-production-secret-min-32-chars

```

### Configuration via CLI Arguments

For ad-hoc testing or systemd services, pass the flags directly:

```bash
python -m mcp_postgresql_ops \
    --type streamable-http \
    --host 0.0.0.0 \
    --port 8000 \
    --auth-enable \
    --secret-key your-production-secret-min-32-chars

```

## Enabling Mandatory Bearer Token Authentication

The authentication system is controlled by the mutually exclusive flags `--auth-enable` and `--auth-disable`, or the `REMOTE_AUTH_ENABLE` environment variable (lines 3641-3648 in [`src/mcp_postgresql_ops/mcp_main.py`](https://github.com/call518/mcp-postgresql-ops/blob/main/src/mcp_postgresql_ops/mcp_main.py)). When enabled, the server builds a static token authenticator via the `_build_static_token_auth` method and attaches it to the global `mcp` instance before starting the HTTP server.

This ensures that every incoming request to `/mcp` must present a valid `Authorization: Bearer <secret>` header. Without this header, the server returns a 401 Unauthorized response before reaching any PostgreSQL operation handlers.

### Secret Key Configuration

The secret key is provided via the `--secret-key` argument or `REMOTE_SECRET_KEY` environment variable (lines 3576-3580). This single secret serves as the Bearer token that all clients must present. The implementation in [`src/mcp_postgresql_ops/mcp_main.py`](https://github.com/call518/mcp-postgresql-ops/blob/main/src/mcp_postgresql_ops/mcp_main.py) stores this value and configures the authentication provider at lines 3712-3716.

### Startup Validation

Before binding to the network interface, the code performs a strict validation check at lines 3699-3708. If authentication is enabled but the secret key is empty or null, the server immediately aborts startup with a critical error. This prevents accidental deployment of an unauthenticated production endpoint.

## Production Deployment Best Practices

As documented in the [`README.md`](https://github.com/call518/mcp-postgresql-ops/blob/main/README.md) security section (lines 53-70 and 84-92), production deployments require additional layers of protection beyond the Bearer token:

- **TLS Termination**: The server listens on plain HTTP. Deploy behind Nginx, Traefik, or another reverse proxy to handle HTTPS encryption and certificate management.
- **Network Segmentation**: Restrict access using firewall rules or VPC security groups so only authorized clients can reach port 8000.
- **Secret Rotation**: Periodically update `REMOTE_SECRET_KEY` and distribute the new token to clients through a secure secrets management system.
- **Container Security**: Run the server as a non-root user and mount the PostgreSQL credentials as read-only secrets.

## Client Request Format

Once configured, clients must include the Bearer token in every request to the `/mcp` endpoint:

```bash
curl -X POST \
  -H "Authorization: Bearer your-production-secret-min-32-chars" \
  -H "Content-Type: application/json" \
  http://your-server:8000/mcp/your-tool \
  -d '{"arg1":"value"}'

```

The server validates this header against the secret established during startup in [`src/mcp_postgresql_ops/mcp_main.py`](https://github.com/call518/mcp-postgresql-ops/blob/main/src/mcp_postgresql_ops/mcp_main.py) (lines 3729-3735) before executing any PostgreSQL operations.

## Summary

- Use `FASTMCP_TYPE=streamable-http` (or `--type streamable-http`) to switch from stdio to HTTP transport mode.
- Enable mandatory authentication with `REMOTE_AUTH_ENABLE=true` (or `--auth-enable`) and provide a strong `REMOTE_SECRET_KEY`.
- The server validates that a secret key exists when auth is enabled, aborting startup if missing (lines 3699-3708).
- Authentication is enforced via `_build_static_token_auth` which requires an `Authorization: Bearer <token>` header on every request.
- Always deploy behind a TLS-terminating reverse proxy and rotate secrets periodically for production security.

## Frequently Asked Questions

### What happens if I enable authentication but forget to set the secret key?

The server executes a validation check in [`src/mcp_postgresql_ops/mcp_main.py`](https://github.com/call518/mcp-postgresql-ops/blob/main/src/mcp_postgresql_ops/mcp_main.py) (lines 3699-3708) that inspects the `REMOTE_SECRET_KEY` value when `REMOTE_AUTH_ENABLE` is true. If the key is empty, the process exits immediately with an error message before binding to any port, preventing an insecure startup.

### Can I use environment variables instead of CLI flags?

Yes, the codebase treats environment variables and CLI flags equivalently. You can define `FASTMCP_TYPE`, `FASTMCP_HOST`, `FASTMCP_PORT`, `REMOTE_AUTH_ENABLE`, and `REMOTE_SECRET_KEY` in your environment or an `.env` file, as illustrated in the repository's `.env.example` file, without passing any command-line arguments.

### Does the server support HTTPS natively?

No, the implementation in [`src/mcp_postgresql_ops/mcp_main.py`](https://github.com/call518/mcp-postgresql-ops/blob/main/src/mcp_postgresql_ops/mcp_main.py) starts a plain HTTP server via `mcp.run(transport="streamable-http", ...)`. For production, you must place the server behind a TLS-terminating reverse proxy such as Nginx or Caddy to encrypt traffic in transit while the MCP server handles Bearer token authentication at the application layer.

### Where is the Bearer token authentication logic implemented?

The authentication provider is constructed by the `_build_static_token_auth` function in [`src/mcp_postgresql_ops/mcp_main.py`](https://github.com/call518/mcp-postgresql-ops/blob/main/src/mcp_postgresql_ops/mcp_main.py) (lines 3712-3716) and attached to the global `mcp` instance. When the server starts at lines 3729-3735 with `transport="streamable-http"`, this authenticator intercepts every request to verify the `Authorization` header against the configured `REMOTE_SECRET_KEY`.