Skip to main content
The server supports HTTP transport for web and agent integration, in addition to the default stdio transport.

Enabling HTTP Mode

Set the MCP_TRANSPORT environment variable:

Configuration

Authentication Modes

The server supports three authentication modes for HTTP transport:

Required Mode (default, most secure)

Full /auth flow with per-user DB credentials:
  • Users must authenticate via POST /auth with their IBM i credentials
  • Each user gets their own database connection with their permissions
  • Tokens expire based on MCP_TOKEN_EXPIRY
This is the default and most secure option, ideal for multi-user environments.

Token Mode (simpler integration)

Pre-shared static token using environment DB credentials:
  • All requests use the same Bearer token
  • Database connection uses DB2I_* environment variables
  • No per-user authentication
Generate a secure token:
Security Note: Always use HTTPS with token mode to protect the token in transit.

None Mode (trusted networks only)

No authentication required:
  • /mcp endpoints are accessible without any authentication
  • Database connection uses DB2I_* environment variables
  • /auth endpoint returns 404
Warning: Only use this mode on trusted networks (localhost, internal VPNs) or for development/testing. The process will not listen on a non-loopback address in this mode unless MCP_ALLOW_UNAUTHENTICATED_HTTP=true. Requests whose Host header is not loopback and not listed in MCP_ALLOWED_HOSTS are rejected with 403. Set MCP_ALLOWED_HOSTS to the name clients use when the server is published beyond localhost. In required mode, the host field on POST /auth must be DB2I_HOSTNAME or a name in MCP_AUTH_ALLOWED_DB_HOSTS. Other hosts are rejected before a connection is opened.

Authentication Flow (Required Mode)

HTTP mode uses token-based authentication. You must first obtain a token by posting credentials, then use that token for subsequent MCP requests.

Step 1: Get a Token

Post credentials to /auth:
Response:

Step 2: Use the Token

Include the token in the Authorization header for MCP requests:

Auth Request Fields

Multiple Systems

With DB2I_PROFILES set, a login in required mode picks a system:
The host, port, database, driver, and driver options come from the test profile. The username and password come from the request, and the server tests them on that system before it returns a token. The token is bound to that system:
  • Tools on that token have no system argument, and every call runs on test.
  • Business SQL tools fixed to another system with system: are not listed.
  • To use another system, log in again with its name.
host, port, and database are refused while DB2I_PROFILES is set, because the profile supplies them. When MCP_AUTH_ALLOWED_DB_HOSTS is unset, /auth may connect only to the profile hosts. When it is set, a profile whose host is not in the list cannot be used. In token and none modes there is no login, so every caller can reach every profile, and each call picks one with the system argument. Each caller runs as the profile’s configured user.

Remote Clients (OAuth)

Remote MCP clients, such as claude.ai custom connectors, cannot send a static header or call POST /auth. They follow the MCP authorization spec instead. With MCP_OAUTH_ENABLED=true, the server acts as its own OAuth 2.1 authorization server:
  1. The client calls /mcp, gets 401 with WWW-Authenticate: Bearer resource_metadata="...", and reads the protected resource and authorization server metadata.
  2. It registers itself at /oauth/register (dynamic client registration).
  3. The user’s browser opens /oauth/authorize: a sign-in page for an IBM i user profile and password, with a system picker when DB2I_PROFILES lists more than one.
  4. The server checks the credentials with a test connection, like /auth, and redirects back with a one-time code.
  5. The client exchanges the code, with its PKCE verifier, at /oauth/token for an access token and a refresh token.
The access token is the same kind of token /auth returns. It is bound to the user’s credentials and the chosen system, so every query runs with that user’s own IBM i authority, under the schema allowlist of that profile.
The server must be reachable over HTTPS at MCP_PUBLIC_URL, through a reverse proxy or a tunnel that keeps the Host header. MCP_PUBLIC_URL must be an origin only: serve the server at the root of its hostname, not under a path. To add it in Claude, open Settings > Connectors > Add custom connector and enter https://mcp.example.com/mcp. Choose Sign in now and Register automatically, and leave the request headers empty. When you connect, the sign-in page opens:

Sign-in page: the Db2 for i MCP Server logo and name, a system picker with prod selected, user profile and password fields, and a Sign in button

The page names the client and the site the user returns to. After sign-in, Claude holds a token bound to that user profile and system. Other clients sign in the same way. Each connection is bound to the system picked on the sign-in page, so add one entry per system you want to use.
  • Cursor. In ~/.cursor/mcp.json (or a project’s .cursor/mcp.json), add the URL only, with no command, environment or password:
    Cursor opens the sign-in page in the browser and returns through cursor://anysphere.cursor-mcp/oauth/callback, which is allowed by default.
  • Claude Code. claude mcp add --transport http --scope user db2i https://mcp.example.com/mcp, then sign in from /mcp. Claude Code uses a loopback callback, which is always accepted.
Pointing every client at one server, instead of starting a stdio server per client, keeps one set of connection pools to the IBM i. By default, tokens live in memory, so clients sign in again after the server restarts. To avoid that, set MCP_OAUTH_STATE_FILE.

Staying signed in across restarts

Set MCP_OAUTH_STATE_FILE to a file path, and set MCP_OAUTH_SECRET. The server then writes refresh grants to that file and reads them back when it starts, so a restart or a new Docker image does not sign anyone out:
  • Access tokens still end with the process. The client gets a 401, uses its refresh token, and carries on without showing the sign-in page.
  • Each grant holds the user’s IBM i password, because a refresh opens a new connection. Entries are encrypted with AES-256-GCM under a key derived from MCP_OAUTH_SECRET. The file never holds a refresh token, only its hash.
  • On start, each grant is rebuilt from the current profiles. A grant for a removed system, or a host that is no longer allowed, is dropped.
  • A new MCP_OAUTH_SECRET makes the file unreadable: the server logs a warning, and users sign in again.
  • The file is written with mode 0600, in a directory with mode 0700. If a write fails, the server logs an error and keeps working, but that grant does not survive a restart.
In Docker, keep the file on a volume. The image creates /data/oauth for it:
Anyone who can read both the file and MCP_OAUTH_SECRET can read the stored passwords. Keep them apart where you can, for example the secret in a Docker secret and the file on a volume only the container mounts, and leave them out of backups that other people can read.

Limiting who can reach the server

OAuth decides who may query, but the sign-in page and token endpoint still face the internet. Put an IP allowlist in front of them as well. Claude connectors call from Anthropic’s published outbound range, 160.79.104.0/21. The sign-in page opens in the user’s own browser, so the networks your users sign in from must be allowed too. With an ngrok tunnel, a traffic policy on the endpoint does this before requests reach the server:
A reverse proxy can do the same, for example nginx allow and deny rules. Notes:
  • Redirect URIs. Registration is refused for a redirect URI outside MCP_OAUTH_REDIRECT_URIS, which defaults to the claude.ai and claude.com connector callbacks and Cursor’s cursor://anysphere.cursor-mcp/oauth/callback. Setting it replaces the defaults, so list those you still need. Loopback redirects (http://localhost:<port>/...) are always accepted, for desktop clients. Without this list, anyone could register a client that sends codes to their own site and ask a user to sign in.
  • Registrations are stateless. A client ID is the client’s metadata signed with MCP_OAUTH_SECRET. Nothing is stored, and a registration keeps working after a restart as long as the secret stays the same. Without the secret, a random one is used and clients must register again after a restart.
  • Codes live in memory, refresh tokens too unless MCP_OAUTH_STATE_FILE is set. Without the file, a restart signs every user out. Refresh tokens rotate on every use, and each refresh repeats the test connection, so a disabled user profile or a changed password ends the grant. If the IBM i cannot be reached, the refresh answers 503 and the grant stays. Revoking an access or refresh token ends both.
  • Rate limit. Sign-in attempts share the /auth limit: 5 per minute per client IP by default (AUTH_RATE_LIMIT_MAX_ATTEMPTS, AUTH_RATE_LIMIT_WINDOW_MS). All /oauth/* endpoints together allow 120 requests per minute per IP by default (OAUTH_RATE_LIMIT_MAX_REQUESTS, OAUTH_RATE_LIMIT_WINDOW_MS). Behind a proxy, set MCP_TRUST_PROXY so the limits use the client address from X-Forwarded-For. Without it, all users share the proxy’s budget. A successful sign-in does not count toward the limit.
  • Scopes are not used. A token can call every tool that MCP_TOOLS_ENABLED and MCP_TOOLS_DISABLED leave registered.

API Endpoints

*Authentication depends on MCP_AUTH_MODE:
  • required: Bearer token from /auth or from the OAuth flow
  • token: Static Bearer token from MCP_AUTH_TOKEN
  • none: No authentication required
API Documentation: Import /openapi.json into Postman, Insomnia, or other API clients for interactive exploration.

Protocol versions

HTTP serves two protocol eras from the same /mcp endpoint:
  • 2026-07-28 (current). No initialize handshake and no Mcp-Session-Id. Each request carries a _meta envelope (io.modelcontextprotocol/protocolVersion, client info, capabilities) plus MCP-Protocol-Version, Mcp-Method, and (for named calls) Mcp-Name. server/discover replaces initialize.
  • 2025-era (through 2025-11-25). Stateless by default: each initialize / tools/call is its own request. GET and DELETE /mcp answer 405.
Database connection pools are keyed by the auth token (or one shared pool in token / none mode), so dropping protocol sessions does not mix users’ IBM i credentials.

Session Modes

Stateless (default)

Each HTTP request builds a fresh MCP server on the caller’s existing database pool. This is the mode 2026-07-28 clients use, and it also serves 2025-era clients without Mcp-Session-Id.

Stateful (deprecated)

Set MCP_SESSION_MODE=stateful only when a 2025-era client requires Mcp-Session-Id, GET /mcp, or DELETE /mcp. The process logs a deprecation warning. 2026-07-28 requests on the same endpoint stay stateless. Database pools are still keyed by the auth token, not by that session id.

TLS Configuration

For production deployments, enable TLS or run behind a reverse proxy with TLS termination.

Built-in TLS

Run behind nginx, Caddy, or a cloud load balancer that handles TLS termination. The server can bind to localhost:

Security Considerations

  • Use required mode in production: Provides per-user authentication and database permissions
  • Use HTTPS in production: Enable TLS or run behind a reverse proxy
  • Token expiry: In required mode, tokens expire after 1 hour by default (configurable via MCP_TOKEN_EXPIRY)
  • Rate limiting: The /auth endpoint and the OAuth sign-in page share built-in rate limiting to prevent brute force attacks
  • OAuth: Keep MCP_OAUTH_REDIRECT_URIS to the clients you use, and set MCP_OAUTH_SECRET
  • Token mode requires HTTPS: When using token mode, always enable TLS to protect the static token
  • None mode for trusted networks only: Only use none mode on localhost or secure internal networks
  • Session limits: Maximum concurrent sessions configurable via MCP_MAX_SESSIONS

Auth Mode Security Comparison

Example: Complete Workflow