Skip to main content
Glama
IBM

IBM i MCP Server

Official
by IBM
ibmi-auth.mdx22.5 kB
--- title: "IBM i Authentication" description: "Complete guide to IBM i HTTP authentication with token-based access, RSA encryption, and per-user connection pooling." --- IBM i HTTP authentication enables secure, token-based access to the MCP server with per-user connection pooling. Clients authenticate with IBM i credentials to obtain Bearer tokens for subsequent API requests. <Info> **When to use IBM i authentication:** - **Multi-user environments**: Each user gets their own connection pool with their credentials - **Production deployments**: Token-based auth with automatic expiry and session management - **Enhanced security**: Credentials encrypted during transmission using RSA/AES - **Audit trails**: Per-user tracking of database operations **When to use simpler auth:** - **Development**: Use shared `DB2i_USER`/`DB2i_PASS` credentials (no token auth needed) - **Single-user scenarios**: JWT or OAuth may be sufficient </Info> --- ## How It Works ### Authentication Flow ```mermaid sequenceDiagram participant Client participant Server participant IBM i Client->>Server: 1. GET /api/v1/auth/public-key Server-->>Client: RSA Public Key Client->>Client: 2. Generate AES session key Client->>Client: 3. Encrypt credentials with session key Client->>Client: 4. Encrypt session key with RSA public key Client->>Server: 5. POST /api/v1/auth (encrypted payload) Server->>Server: 6. Decrypt session key with private key Server->>Server: 7. Decrypt credentials with session key Server->>IBM i: 8. Authenticate with decrypted credentials IBM i-->>Server: Authentication Success Server->>Server: 9. Create access token & connection pool Server-->>Client: Bearer Token Client->>Server: 10. API requests with Bearer token Server-->>Client: Authenticated responses ``` **Key Features:** - **End-to-end encryption**: Credentials never transmitted in plain text - **Per-user pools**: Each token gets its own dedicated DB2 connection pool - **Token lifecycle**: Automatic expiry and cleanup of stale sessions - **Key rotation**: Support for multiple keypairs for zero-downtime rotation --- ## Configuration ### Environment Variables | Variable | Description | Default | Required | |----------|-------------|---------|----------| | `MCP_AUTH_MODE` | Must be set to `ibmi` | `none` | ✅ Yes | | `IBMI_HTTP_AUTH_ENABLED` | Enable auth endpoints | `false` | ✅ Yes | | `IBMI_AUTH_KEY_ID` | Identifier for RSA keypair | (none) | ✅ Yes | | `IBMI_AUTH_PRIVATE_KEY_PATH` | Path to RSA private key | (none) | ✅ Yes | | `IBMI_AUTH_PUBLIC_KEY_PATH` | Path to RSA public key | (none) | ✅ Yes | | `IBMI_AUTH_ALLOW_HTTP` | Allow HTTP (dev only) | `false` | No | | `IBMI_AUTH_TOKEN_EXPIRY_SECONDS` | Token lifetime | `3600` (1hr) | No | | `IBMI_AUTH_CLEANUP_INTERVAL_SECONDS` | Cleanup interval | `300` (5min) | No | | `IBMI_AUTH_MAX_CONCURRENT_SESSIONS` | Max sessions | `100` | No | <Info> **Complete Reference**: See the [IBM i Authentication Settings](/configuration#ibm-i-authentication-settings) section in the Configuration Reference for all available environment variables and their defaults. </Info> ### Db2i Credentials: Important Notes <Warning> **Common Pitfall**: When using IBM i HTTP authentication, you may encounter validation errors about `DB2i_USER` and `DB2i_PASS` even though the Bearer token provides authentication. **Solution**: Either **omit these variables entirely** from your `.env` file, or set them to placeholder values like `TOKEN_AUTH`. **Why this happens**: The validation schema requires these fields to be either undefined or have non-empty values. Empty strings (`DB2i_USER=""`) fail validation. When using token authentication, the Bearer token supplies user credentials, so `DB2i_USER` and `DB2i_PASS` are not used. </Warning> <Tabs> <Tab title="Option 1: Omit Variables (Recommended)"> ```bash # .env for IBM i HTTP Authentication # Authentication Mode MCP_AUTH_MODE=ibmi IBMI_HTTP_AUTH_ENABLED=true # Encryption Keys IBMI_AUTH_KEY_ID=production IBMI_AUTH_PRIVATE_KEY_PATH=secrets/private.pem IBMI_AUTH_PUBLIC_KEY_PATH=secrets/public.pem # IBM i Connection (host only, no credentials) DB2i_HOST=ibmi-prod.company.com DB2i_PORT=8076 DB2i_IGNORE_UNAUTHORIZED=false # DO NOT INCLUDE DB2i_USER or DB2i_PASS # Token authentication provides user credentials ``` **This is the cleanest approach**: Variables are completely absent from the configuration. </Tab> <Tab title="Option 2: Placeholder Values"> ```bash # .env for IBM i HTTP Authentication # Authentication Mode MCP_AUTH_MODE=ibmi IBMI_HTTP_AUTH_ENABLED=true # Encryption Keys IBMI_AUTH_KEY_ID=production IBMI_AUTH_PRIVATE_KEY_PATH=secrets/private.pem IBMI_AUTH_PUBLIC_KEY_PATH=secrets/public.pem # IBM i Connection DB2i_HOST=ibmi-prod.company.com DB2i_PORT=8076 DB2i_IGNORE_UNAUTHORIZED=false # Placeholders (not used during token auth) DB2i_USER=TOKEN_AUTH DB2i_PASS=TOKEN_AUTH ``` **Why this works**: Validation passes because values are non-empty, but they're never used since token auth provides real credentials. </Tab> </Tabs> <Note> **Reference**: See [GitHub Issue #77](https://github.com/IBM/ibmi-mcp-server/issues/77) for the original discussion of this validation behavior. </Note> --- ## Setup: RSA Encryption Keys IBM i authentication requires RSA keypairs to protect credentials during transmission. The authentication flow uses RSA and AES encryption to securely exchange IBM i credentials between clients and the server. <Steps> <Step title="Create Secrets Directory"> Create a dedicated directory for storing encryption keys: ```bash mkdir -p secrets ``` <Tip> Store the `secrets/` directory outside of version control. Add it to your `.gitignore` file. </Tip> </Step> <Step title="Generate RSA Private Key"> Generate a 2048-bit RSA private key: ```bash openssl genpkey -algorithm RSA \ -out secrets/private.pem \ -pkeyopt rsa_keygen_bits:2048 ``` **What this does:** - Creates a new RSA private key with 2048-bit encryption strength - Saves it to `secrets/private.pem` - This key will be used by the server to decrypt credentials sent by clients </Step> <Step title="Extract Public Key"> Extract the corresponding public key from the private key: ```bash openssl rsa -pubout \ -in secrets/private.pem \ -out secrets/public.pem ``` **What this does:** - Derives the public key from your private key - Saves it to `secrets/public.pem` - Clients use this public key to encrypt credentials before sending them to the server </Step> <Step title="Set Secure File Permissions"> Restrict access to your private key: ```bash # Make private key readable only by owner chmod 600 secrets/private.pem # Public key can be more permissive chmod 644 secrets/public.pem ``` <Warning> **Critical Security Step**: The private key (`private.pem`) must be protected. Anyone with access to this file can decrypt client credentials. </Warning> </Step> <Step title="Configure Environment Variables"> Add the keypair paths to your `.env` file: ```bash # IBM i Authentication Keys IBMI_AUTH_KEY_ID=production IBMI_AUTH_PRIVATE_KEY_PATH=secrets/private.pem IBMI_AUTH_PUBLIC_KEY_PATH=secrets/public.pem ``` **Key Configuration:** - `IBMI_AUTH_KEY_ID`: Identifier for this keypair (used for key rotation) - `IBMI_AUTH_PRIVATE_KEY_PATH`: Path to your private key file - `IBMI_AUTH_PUBLIC_KEY_PATH`: Path to your public key file </Step> </Steps> **How the Encryption Works:** 1. **Client requests public key** from server (`/api/v1/auth/public-key`) 2. **Client generates** a random AES-256-GCM session key 3. **Client encrypts** IBM i credentials with the session key 4. **Client encrypts** the session key with the server's RSA public key 5. **Server decrypts** the session key using its RSA private key 6. **Server decrypts** the credentials using the session key 7. **Server authenticates** against IBM i and issues an access token <Note> **Key Rotation**: To rotate keys, generate a new keypair with a different `IBMI_AUTH_KEY_ID`. The server can support multiple keypairs simultaneously, allowing gradual migration without service interruption. </Note> --- ## Start the Server After configuring IBM i authentication and generating your RSA keys, start the MCP server with authentication enabled. **Complete Configuration Example:** ```bash # .env file with IBM i HTTP Authentication MCP_AUTH_MODE=ibmi IBMI_HTTP_AUTH_ENABLED=true # Encryption Keys IBMI_AUTH_KEY_ID=production IBMI_AUTH_PRIVATE_KEY_PATH=secrets/private.pem IBMI_AUTH_PUBLIC_KEY_PATH=secrets/public.pem # IBM i Connection (host only - no DB2i_USER/DB2i_PASS needed) DB2i_HOST=ibmi-prod.company.com DB2i_PORT=8076 DB2i_IGNORE_UNAUTHORIZED=false # Server Settings MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 MCP_LOG_LEVEL=info # Security (production) IBMI_AUTH_ALLOW_HTTP=false IBMI_AUTH_TOKEN_EXPIRY_SECONDS=3600 ``` **Start the Server:** <Tabs> <Tab title="NPM Package"> ```bash # Set configuration file path export MCP_SERVER_CONFIG=.env # Start the server npx -y @ibm/ibmi-mcp-server@latest --transport http --tools ./tools ``` You should see: ``` ✓ IBM i HTTP authentication enabled ✓ Public key loaded from secrets/public.pem ✓ Private key loaded from secrets/private.pem ✓ Server ready! Transport: http Host: 127.0.0.1:3010 Endpoint: http://127.0.0.1:3010/mcp Auth: IBM i HTTP (key_id: production) ``` </Tab> <Tab title="Build from Source"> ```bash # From the repository root export MCP_SERVER_CONFIG=.env cd server npm run start:http -- --tools ../tools ``` You should see: ``` ✓ IBM i HTTP authentication enabled ✓ Public key loaded from secrets/public.pem ✓ Private key loaded from secrets/private.pem ✓ Server ready! Transport: http Host: 127.0.0.1:3010 Endpoint: http://127.0.0.1:3010/mcp Auth: IBM i HTTP (key_id: production) ``` </Tab> </Tabs> <Success> ✓ **Verify authentication is working:** Test the public key endpoint: ```bash curl http://localhost:3010/api/v1/auth/public-key ``` Should return: ```json { "keyId": "production", "publicKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhki..." } ``` If you see the public key, authentication is properly configured! </Success> <Warning> **Production HTTPS**: In production, ensure `IBMI_AUTH_ALLOW_HTTP=false` and use HTTPS. The server will reject HTTP authentication requests for security. </Warning> --- ## Usage Examples ### Getting an Access Token The repository includes a helper script to obtain authentication tokens: [`get-access-token.js`](https://github.com/IBM/ibmi-mcp-server/blob/main/get-access-token.js) <Note> **Script Location**: The `get-access-token.js` script is included in the root of the [GitHub repository](https://github.com/IBM/ibmi-mcp-server/blob/main/get-access-token.js). Clone the repository or download this file to use the token helper. **What it does**: This script authenticates with your IBM i credentials and generates a Bearer token, then outputs a command to set the `IBMI_MCP_ACCESS_TOKEN` environment variable. </Note> ```bash # Clone the repository if you haven't already git clone https://github.com/IBM/ibmi-mcp-server.git cd ibmi-mcp-server # ONE-LINER: Generate token and set IBMI_MCP_ACCESS_TOKEN automatically eval $(node get-access-token.js --quiet) # Verify the token was set echo $IBMI_MCP_ACCESS_TOKEN # Alternative: View token details with verbose output node get-access-token.js --verbose # Alternative: Specify credentials explicitly node get-access-token.js \ --user myuser \ --password mypass \ --host my-ibmi-host \ --quiet ``` <Tip> **Quick Setup**: The one-liner `eval $(node get-access-token.js --quiet)` does everything: 1. Reads your IBM i credentials from `.env` 2. Encrypts and sends them to the MCP server 3. Receives the Bearer token 4. Automatically sets `export IBMI_MCP_ACCESS_TOKEN=your-token` 5. Token is now available in your shell session Use this token with any MCP client by including the header: `Authorization: Bearer $IBMI_MCP_ACCESS_TOKEN` </Tip> **Example Output:** ```bash $ eval $(node get-access-token.js --quiet) $ echo $IBMI_MCP_ACCESS_TOKEN eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiTVlVU0VSIiwiaG9zdCI6... # Token is now set and ready to use with MCP clients ``` **Common Options:** | Option | Short | Description | Default | |--------|-------|-------------|---------| | `--user` | `-u` | IBM i username | `DB2i_USER` from .env | | `--password` | `-p` | IBM i password | `DB2i_PASS` from .env | | `--host` | `-h` | IBM i host address | `DB2i_HOST` from .env | | `--server` | | MCP server address | `localhost` | | `--port` | | MCP server port | `3010` | | `--https` | | Use HTTPS instead of HTTP | HTTP | | `--verbose` | `-v` | Enable verbose output with metadata | (quiet mode) | | `--quiet` | `-q` | Output only export command for shell eval | (normal mode) | <Accordion title="Advanced Options"> For advanced use cases, the script supports additional configuration: | Option | Description | |--------|-------------| | `--duration` | Token duration in seconds | | `--pool-start` | Initial connection pool size | | `--pool-max` | Maximum connection pool size | | `--public-key-path` | Path to PEM-encoded server public key (skips HTTP fetch) | | `--key-id` | Key identifier when using `--public-key-path` | **Example with advanced options:** ```bash node get-access-token.js \ --server prod-mcp.company.com \ --port 443 \ --https \ --duration 7200 \ --quiet ``` </Accordion> The script automatically: - Loads IBM i credentials from `.env` with CLI fallback - Fetches the server's public key (or uses local file with `--public-key-path`) - Encrypts credentials client-side using RSA/AES - Requests an access token from the MCP server - Outputs the token (or export command in quiet mode) **View Source**: See the full implementation at [`get-access-token.js`](https://github.com/IBM/ibmi-mcp-server/blob/main/get-access-token.js) ### Using the Token with MCP Clients Once you have a token, configure your MCP client: <Tabs> <Tab title="Python (Agno)"> ```python import asyncio import os from agno.agent import Agent from agno.tools.mcp import MCPTools, StreamableHTTPClientParams # Get access token from environment token = os.environ.get('IBMI_MCP_ACCESS_TOKEN') if not token: raise ValueError("IBMI_MCP_ACCESS_TOKEN not set") url = "http://localhost:3010/mcp" server_params = StreamableHTTPClientParams( url=url, headers={"Authorization": f"Bearer {token}"} ) async def main(): async with MCPTools( url=url, server_params=server_params, transport="streamable-http" ) as tools: agent = Agent( model="openai:gpt-4o", tools=[tools], name="ibmi-agent", show_tool_calls=True ) await agent.aprint_response("What is the system status?") if __name__ == "__main__": asyncio.run(main()) ``` </Tab> <Tab title="Python (MCP SDK)"> ```python import asyncio import os from mcp import ClientSession from mcp.client.streamable_http import streamablehttp_client async def main(): token = os.environ.get('IBMI_MCP_ACCESS_TOKEN') if not token: raise ValueError("IBMI_MCP_ACCESS_TOKEN not set") headers = {"Authorization": f"Bearer {token}"} async with streamablehttp_client( "http://localhost:3010/mcp", headers=headers ) as (read_stream, write_stream, _): async with ClientSession(read_stream, write_stream) as session: await session.initialize() # List tools tools = await session.list_tools() print(f"Tools: {[t.name for t in tools.tools]}") # Execute a tool result = await session.call_tool("system_status", {}) print(result) if __name__ == "__main__": asyncio.run(main()) ``` </Tab> <Tab title="Claude Desktop"> ```json { "mcpServers": { "ibmi-mcp": { "url": "http://localhost:3010/mcp", "type": "http", "headers": { "Authorization": "Bearer YOUR_ACCESS_TOKEN_HERE" } } } } ``` </Tab> <Tab title="VSCode"> ```json { "servers": { "ibmiMcp": { "type": "http", "url": "http://localhost:3010/mcp", "headers": { "Authorization": "Bearer YOUR_ACCESS_TOKEN_HERE" } } } } ``` </Tab> </Tabs> --- ## Security Best Practices <AccordionGroup> <Accordion title="Production Deployment" icon="shield-check"> - **Always use HTTPS**: Set `IBMI_AUTH_ALLOW_HTTP=false` - **Rotate keys regularly**: Generate new keypairs every 90-180 days - **Use strong key sizes**: 2048-bit minimum, 4096-bit recommended for high-security environments - **Monitor key access**: Enable file auditing on the `secrets/` directory - **Backup keys securely**: Store encrypted backups in a secrets management system </Accordion> <Accordion title="File Permissions" icon="lock"> - **Private key**: `chmod 600 secrets/private.pem` (owner read/write only) - **Public key**: `chmod 644 secrets/public.pem` (world-readable is safe) - **Secrets directory**: `chmod 700 secrets/` (owner access only) - **Owner**: Ensure files are owned by the service account running the MCP server </Accordion> <Accordion title="Version Control" icon="code-branch"> - **Never commit keys**: Add `secrets/` to `.gitignore` - **Never commit `.env`**: Environment files often contain paths to secrets - **Use environment-specific keys**: Different keypairs for dev/staging/production - **Document setup process**: Include key generation in deployment documentation </Accordion> <Accordion title="Secrets Management" icon="vault"> For production environments, consider using a secrets management system: - **AWS Secrets Manager**: Store keys in encrypted AWS vault - **HashiCorp Vault**: Centralized secrets management with audit logs - **Azure Key Vault**: Microsoft's cloud-based secrets storage - **Kubernetes Secrets**: For containerized deployments Update `IBMI_AUTH_PRIVATE_KEY_PATH` to reference the mounted secret location. </Accordion> <Accordion title="Network Security" icon="network-wired"> - **HTTPS Only**: Never allow `IBMI_AUTH_ALLOW_HTTP=true` in production - **Firewall Rules**: Restrict access to auth endpoints - **Rate Limiting**: Configure rate limits on authentication endpoints - **IP Whitelisting**: Restrict auth access to known client IPs when possible </Accordion> </AccordionGroup> --- ## Troubleshooting <AccordionGroup> <Accordion title="Validation Error: DB2i_USER and DB2i_PASS Required"> **Symptom**: Server fails to start with error requiring `DB2i_USER` and `DB2i_PASS` even though you're using token authentication. **Solution**: Either completely omit these variables from your `.env` file, or set them to placeholder values like `TOKEN_AUTH`. Do not use empty strings (`DB2i_USER=""`). See the [Configuration](#configuration) section above for detailed examples. **Why**: Validation requires these fields to be either undefined or have non-empty values. When using token auth, credentials come from the Bearer token, not environment variables. </Accordion> <Accordion title="401 Unauthorized When Using Token"> **Possible causes:** - Token has expired (check `IBMI_AUTH_TOKEN_EXPIRY_SECONDS`) - Token was obtained from a different server instance - Authorization header missing or malformed **Check:** ```bash # Verify header format curl -H "Authorization: Bearer YOUR_TOKEN" http://localhost:3010/mcp # Get a fresh token node get-access-token.js --verbose ``` </Accordion> <Accordion title="Encryption Key Errors"> **Symptom**: Server fails to start or auth requests fail with encryption errors. **Solutions:** - Verify file paths in `.env` are correct - Check file permissions: `ls -la secrets/` - Ensure private key is valid: `openssl rsa -in secrets/private.pem -check` - Regenerate keypair if corrupted </Accordion> <Accordion title="Connection Pool Exhaustion"> **Symptom**: "Max concurrent sessions reached" errors. **Solutions:** - Increase `IBMI_AUTH_MAX_CONCURRENT_SESSIONS` - Reduce `IBMI_AUTH_TOKEN_EXPIRY_SECONDS` to clean up idle sessions faster - Monitor active sessions and adjust cleanup interval </Accordion> </AccordionGroup> --- ## Authentication Endpoints When enabled (`IBMI_HTTP_AUTH_ENABLED=true`), the server provides these endpoints: | Endpoint | Method | Description | |----------|--------|-------------| | `/api/v1/auth/public-key` | GET | Retrieve server's RSA public key for client-side encryption | | `/api/v1/auth` | POST | Authenticate with encrypted IBM i credentials and receive Bearer token | | `/healthz` | GET | Health check endpoint (no authentication required) | For detailed API specifications, see the [API Reference](/api/auth-endpoints). --- ## Next Steps <CardGroup cols={2}> <Card title="Configuration Reference" icon="gear" href="/configuration"> Explore all configuration options for the MCP server </Card> <Card title="Client Integrations" icon="plug" href="/clients/overview"> Connect Claude Desktop, VSCode, Cursor, and other MCP clients </Card> <Card title="SQL Tools" icon="database" href="/sql-tools/overview"> Create custom SQL operations for authenticated users </Card> <Card title="Production Deployment" icon="server" href="/deployment/production"> Deploy with Docker, HTTPS, and secrets management </Card> </CardGroup>

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/IBM/ibmi-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server