| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance |
| # with the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, |
| # software distributed under the License is distributed on an |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| # KIND, either express or implied. See the License for the |
| # specific language governing permissions and limitations |
| # under the License. |
| # =================================================================== |
| # Doris MCP Server Environment Configuration Example |
| # =================================================================== |
| # Copy this file to .env and modify the configuration values as needed |
| |
| # =================================================================== |
| # Database Connection Configuration |
| # =================================================================== |
| |
| # Doris FE (Frontend) connection settings |
| DORIS_HOST=localhost |
| # Optional ordered FE MySQL endpoints for one Doris cluster. DORIS_HOST is |
| # prepended when both settings are present. |
| DORIS_HOSTS= |
| DORIS_PORT=9030 |
| DORIS_USER=root |
| DORIS_PASSWORD= |
| DORIS_DATABASE=information_schema |
| |
| # Doris FE HTTP API endpoint (for Profile and other HTTP APIs). |
| # Leave the host empty to reuse DORIS_HOST for backward compatibility. |
| DORIS_FE_HTTP_HOST= |
| # Optional ordered FE HTTP endpoints for the same Doris cluster. |
| DORIS_FE_HTTP_HOSTS= |
| DORIS_FE_HTTP_PORT=8030 |
| |
| # Doris BE (Backend) HTTP allowlist for monitoring metrics. |
| # Format: host1,host2,host3. If empty, BE HTTP metrics are disabled. |
| DORIS_BE_HOSTS= |
| DORIS_BE_WEBSERVER_PORT=8040 |
| |
| # FE/BE HTTP safety limits. Redirects are always disabled and resolved |
| # metadata/link-local addresses are always rejected. |
| DORIS_HTTP_CONNECT_TIMEOUT_SECONDS=3 |
| DORIS_HTTP_READ_TIMEOUT_SECONDS=15 |
| DORIS_HTTP_TOTAL_TIMEOUT_SECONDS=30 |
| DORIS_HTTP_MAX_RESPONSE_BYTES=4194304 |
| |
| # Docker Compose reads sensitive values from ignored host files and mounts |
| # them as container secrets. These variables are host paths, never secret |
| # values. See the Docker deployment section in README.md before starting the |
| # bundled stack. |
| COMPOSE_DORIS_PASSWORD_FILE=./.secrets/doris_password |
| COMPOSE_DORIS_FE_CUSTOM_CONFIG_FILE=./.secrets/doris_fe_custom.conf |
| COMPOSE_MCP_STATIC_TOKEN_FILE=./.secrets/mcp_static_token |
| COMPOSE_REDIS_PASSWORD_FILE=./.secrets/redis_password |
| COMPOSE_GRAFANA_ADMIN_PASSWORD_FILE=./.secrets/grafana_admin_password |
| |
| # Connection pool configuration |
| DORIS_MAX_CONNECTIONS=20 |
| DORIS_CONNECTION_TIMEOUT=30 |
| DORIS_HEALTH_CHECK_INTERVAL=60 |
| DORIS_MAX_CONNECTION_AGE=3600 |
| |
| # Arrow Flight SQL Configuration (Required for ADBC tools) |
| # FE_ARROW_FLIGHT_SQL_PORT= |
| # BE_ARROW_FLIGHT_SQL_PORT= |
| |
| # Explicit allowlist of installed Python entry points from the |
| # doris_mcp_server.tool_providers group. Empty means no custom code is loaded. |
| # Custom providers are supported with local/stdio, static token, and JWT auth; |
| # they are hidden from OAuth modes until they have a reviewed OAuth policy. |
| MCP_TOOL_PROVIDERS= |
| MCP_TOOL_EXPOSURE_MODE=hierarchical |
| |
| # Doris-changing MCP actions are reserved for a separately reviewed release. |
| # The 1.0 server rejects attempts to enable this domain or disable its future |
| # confirmation requirement; no administration tool or handler is registered. |
| MCP_ADMIN_DOMAIN_ENABLED=false |
| MCP_ADMIN_REQUIRE_CONFIRMATION=true |
| |
| # Route-private capability snapshots drive each child availability decision. |
| # A failed refresh may reuse the previous snapshot only during the bounded |
| # stale grace window; unavailable or unknown capabilities remain fail-closed. |
| CAPABILITY_SNAPSHOT_TTL_SECONDS=300 |
| CAPABILITY_PROBE_TIMEOUT_SECONDS=5 |
| CAPABILITY_STALE_GRACE_SECONDS=900 |
| |
| # Read-only Governance runtime bounds and optional native lineage store. |
| GOVERNANCE_MAX_SAMPLE_RATIO=0.25 |
| GOVERNANCE_MAX_AUDIT_WINDOW_DAYS=30 |
| GOVERNANCE_MAX_LINEAGE_EDGES=500 |
| GOVERNANCE_LINEAGE_STORE_TABLE= |
| GOVERNANCE_LINEAGE_RECENT_EVENT_MINUTES=1440 |
| |
| # Read-only Lakehouse catalog, snapshot, partition, and Variant bounds. |
| LAKEHOUSE_MAX_CATALOG_OBJECTS=50 |
| LAKEHOUSE_MAX_CATALOG_DATABASES=20 |
| LAKEHOUSE_MAX_SNAPSHOTS=50 |
| LAKEHOUSE_MAX_PARTITIONS=100 |
| LAKEHOUSE_MAX_VARIANT_SAMPLE_ROWS=20 |
| LAKEHOUSE_MAX_VARIANT_PATHS=200 |
| |
| # Experimental Apache Ossie Core semantic grounding. Models and their |
| # server-private Doris binding manifest are loaded from local UTF-8 YAML or |
| # JSON files at startup. The adapter never compiles or executes model |
| # expressions, and it never guesses a model reference. |
| OSSIE_ENABLED=false |
| OSSIE_MODEL_DIRECTORY= |
| OSSIE_BINDING_MANIFEST= |
| OSSIE_MAX_FILE_BYTES=2097152 |
| OSSIE_MAX_TOTAL_BYTES=8388608 |
| OSSIE_MAX_MODELS=64 |
| OSSIE_MAX_DEPTH=32 |
| OSSIE_MAX_ALIASES=32 |
| OSSIE_MAX_STRING_BYTES=16384 |
| OSSIE_MAX_EXPRESSION_BYTES=4096 |
| OSSIE_CONTEXT_MAX_BYTES=16384 |
| OSSIE_CONTEXT_HARD_MAX_BYTES=65536 |
| # Semantic tools and resources are hidden in OAuth modes unless the matching |
| # channel is explicitly enabled. Calls also require semantic:read plus the |
| # normal exact tool or resource operation scopes. |
| DORIS_OAUTH_SEMANTIC_TOOLS_ENABLED=false |
| DORIS_OAUTH_SEMANTIC_RESOURCES_ENABLED=false |
| |
| # =================================================================== |
| # Security Configuration |
| # =================================================================== |
| |
| # Independent Authentication Switches - NEW DESIGN! |
| # Each authentication method can be enabled/disabled independently |
| # Any enabled method that succeeds will allow access |
| # If all methods are disabled, anonymous HTTP access is limited to loopback |
| # Non-loopback HTTP without authentication is rejected before startup |
| ALLOW_UNAUTHENTICATED_NON_LOOPBACK=false |
| |
| # Legacy configuration - kept for backward compatibility |
| # AUTH_TYPE is now deprecated - use individual switches above |
| # AUTH_TYPE=token |
| |
| # Token Authentication (Default method - simple and effective) |
| ENABLE_TOKEN_AUTH=false |
| |
| # JWT Authentication (For stateless applications) |
| ENABLE_JWT_AUTH=false |
| |
| # OAuth 2.0/OIDC Authentication (For enterprise integration) |
| ENABLE_OAUTH_AUTH=false |
| |
| # =================================================================== |
| # Token Authentication Configuration (Enable with ENABLE_TOKEN_AUTH=true) |
| # =================================================================== |
| |
| # Basic token authentication settings |
| TOKEN_FILE_PATH=tokens.json |
| ENABLE_TOKEN_EXPIRY=true |
| DEFAULT_TOKEN_EXPIRY_HOURS=720 |
| TOKEN_HASH_ALGORITHM=sha256 |
| # Cache successful token-bound Doris route checks so MCP pings and discovery |
| # requests do not reconnect on every request. Set 0 to validate every request. |
| TOKEN_DB_VALIDATION_TTL_SECONDS=30 |
| # No static bearer token is shipped. Generate one outside source control: |
| # python -c 'import secrets; print(secrets.token_urlsafe(32))' |
| # TOKEN_ADMIN=<paste-generated-value-here> |
| # Managed tokens.json writes persist only a self-describing token digest and |
| # return plaintext only at creation time. Legacy plaintext files are migrated |
| # to digest-only version 2.0 on first successful load. |
| # Local worker processes serialize updates through tokens.json.lock and check |
| # shared state before authentication. Revocation digests also disable matching |
| # TOKEN_<ID> environment credentials across every worker. |
| |
| # =================================================================== |
| # Token Management Security Configuration (NEW in v0.6.0) - CRITICAL SECURITY SETTINGS |
| # =================================================================== |
| |
| # HTTP Token Management Endpoints (DISABLED BY DEFAULT FOR SECURITY) |
| # WARNING: These endpoints allow creation, deletion, and management of authentication tokens |
| # Only enable if you need HTTP-based token management and understand the security implications |
| ENABLE_HTTP_TOKEN_MANAGEMENT=false |
| |
| # Admin Authentication Token (REQUIRED if HTTP token management is enabled) |
| # This token is required to access HTTP token management endpoints |
| # SECURITY: Generate a secure random token in production - NEVER use default values |
| TOKEN_MANAGEMENT_ADMIN_TOKEN= |
| |
| # IP Address Restrictions for Token Management (CRITICAL SECURITY CONTROL) |
| # Only these IP addresses/networks can access token management endpoints |
| # DEFAULT: localhost only (most secure) - add other IPs/networks only if necessary |
| # Format: comma-separated list of IPs and CIDR networks |
| # Examples: |
| # - Localhost only: 127.0.0.1,::1 |
| # - Private network: 127.0.0.1,192.168.1.0/24,10.0.0.0/8 |
| # - Specific IPs: 127.0.0.1,192.168.1.10,192.168.1.11 |
| TOKEN_MANAGEMENT_ALLOWED_IPS=127.0.0.1,::1 |
| |
| # Require Admin Authentication (ENABLED BY DEFAULT FOR SECURITY) |
| # When true, all token management operations require valid admin token |
| # When false, only IP restrictions apply (NOT RECOMMENDED for production) |
| REQUIRE_ADMIN_AUTH=true |
| |
| # =================================================================== |
| # JWT Authentication Configuration (Enable with ENABLE_JWT_AUTH=true) |
| # =================================================================== |
| |
| # JWT token settings (when ENABLE_JWT_AUTH=true) |
| JWT_SECRET_KEY=your_jwt_secret_key_here_change_in_production |
| JWT_ALGORITHM=HS256 |
| JWT_EXPIRATION_HOURS=24 |
| JWT_ISSUER=doris-mcp-server |
| JWT_AUDIENCE=doris-mcp-client |
| |
| # JWT token validation settings |
| JWT_VERIFY_SIGNATURE=true |
| JWT_VERIFY_EXPIRATION=true |
| JWT_VERIFY_AUDIENCE=true |
| JWT_VERIFY_ISSUER=true |
| |
| # JWT refresh token settings |
| ENABLE_JWT_REFRESH=true |
| JWT_REFRESH_EXPIRATION_DAYS=30 |
| JWT_REFRESH_SECRET_KEY=your_jwt_refresh_secret_key_here |
| |
| # JWT user claims configuration |
| JWT_USER_ID_CLAIM=user_id |
| JWT_ROLES_CLAIM=roles |
| JWT_PERMISSIONS_CLAIM=permissions |
| JWT_SECURITY_LEVEL_CLAIM=security_level |
| |
| # =================================================================== |
| # OAuth 2.0 / OpenID Connect Configuration (Enable with ENABLE_OAUTH_AUTH=true) |
| # =================================================================== |
| |
| # OAuth provider settings (when ENABLE_OAUTH_AUTH=true) |
| OAUTH_PROVIDER_TYPE=generic |
| OAUTH_CLIENT_ID=your_oauth_client_id |
| OAUTH_CLIENT_SECRET=your_oauth_client_secret |
| OAUTH_REDIRECT_URI=http://localhost:3000/auth/callback |
| |
| # External OAuth trust boundary. The server validates every access token through |
| # RFC 7662 introspection before calling userinfo. OAUTH_ISSUER and |
| # OAUTH_RESOURCE are mandatory. OAUTH_AUDIENCE defaults to OAUTH_RESOURCE. |
| OAUTH_ISSUER=https://your-provider.com |
| OAUTH_RESOURCE=https://your-mcp-server.example.com/mcp |
| OAUTH_AUDIENCE=https://your-mcp-server.example.com/mcp |
| |
| # OAuth endpoints (for generic provider). OAUTH_DISCOVERY_URL may supply the |
| # endpoints, but its returned issuer must exactly match OAUTH_ISSUER. |
| OAUTH_DISCOVERY_URL=https://your-provider.com/.well-known/oauth-authorization-server |
| OAUTH_AUTHORIZATION_URL=https://your-provider.com/auth |
| OAUTH_TOKEN_URL=https://your-provider.com/token |
| OAUTH_INTROSPECTION_URL=https://your-provider.com/introspect |
| OAUTH_USERINFO_URL=https://your-provider.com/userinfo |
| OAUTH_JWKS_URL=https://your-provider.com/.well-known/jwks.json |
| |
| # Optional dedicated RFC 7662 credentials. If omitted, OAUTH_CLIENT_ID and |
| # OAUTH_CLIENT_SECRET are used. |
| # OAUTH_INTROSPECTION_CLIENT_ID=your_introspection_client_id |
| # OAUTH_INTROSPECTION_CLIENT_SECRET=your_introspection_client_secret |
| |
| # OAuth scope and claims. OAUTH_REQUIRED_SCOPE defaults to every value in |
| # OAUTH_SCOPE. Token scopes outside OAUTH_SCOPE are not copied into AuthContext. |
| OAUTH_SCOPE=openid profile email |
| OAUTH_REQUIRED_SCOPE=openid profile email |
| OAUTH_USER_ID_CLAIM=sub |
| OAUTH_USERNAME_CLAIM=preferred_username |
| OAUTH_EMAIL_CLAIM=email |
| OAUTH_ROLES_CLAIM=roles |
| OAUTH_GROUPS_CLAIM=groups |
| |
| # External OAuth authorization mapping. Role names are matched |
| # case-insensitively. Trusted domains require email_verified=true. |
| OAUTH_DEFAULT_ROLES=oauth_user |
| OAUTH_DEFAULT_SECURITY_LEVEL=internal |
| OAUTH_DEFAULT_PERMISSIONS=read_data |
| OAUTH_TRUSTED_DOMAINS= |
| OAUTH_TRUSTED_DOMAIN_SECURITY_LEVEL=confidential |
| # JSON values replace the complete built-in mapping when configured. |
| # OAUTH_ROLE_SECURITY_LEVELS_JSON={"analyst":"internal","executive":"secret"} |
| # OAUTH_ROLE_PERMISSIONS_JSON={"analyst":["read_data","query_database"],"executive":["read_data"]} |
| |
| # OAuth session settings |
| OAUTH_SESSION_SECRET=your_oauth_session_secret_here |
| OAUTH_SESSION_EXPIRY=3600 |
| OAUTH_STATE_EXPIRY=300 |
| |
| # Popular OAuth provider endpoint examples. External OAuth is enabled only when |
| # that authorization server also provides a trusted RFC 7662 introspection |
| # endpoint and the issuer/resource/audience values above are configured. |
| |
| # Google OAuth Configuration |
| # OAUTH_PROVIDER_TYPE=google |
| # OAUTH_CLIENT_ID=your_google_client_id.apps.googleusercontent.com |
| # OAUTH_CLIENT_SECRET=your_google_client_secret |
| # OAUTH_AUTHORIZATION_URL=https://accounts.google.com/o/oauth2/auth |
| # OAUTH_TOKEN_URL=https://oauth2.googleapis.com/token |
| # OAUTH_USERINFO_URL=https://www.googleapis.com/oauth2/v1/userinfo |
| # OAUTH_JWKS_URL=https://www.googleapis.com/oauth2/v3/certs |
| # OAUTH_SCOPE=openid profile email |
| |
| # Microsoft Azure AD Configuration |
| # OAUTH_PROVIDER_TYPE=azure |
| # OAUTH_CLIENT_ID=your_azure_client_id |
| # OAUTH_CLIENT_SECRET=your_azure_client_secret |
| # OAUTH_TENANT_ID=your_tenant_id |
| # OAUTH_AUTHORIZATION_URL=https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize |
| # OAUTH_TOKEN_URL=https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token |
| # OAUTH_USERINFO_URL=https://graph.microsoft.com/v1.0/me |
| # OAUTH_JWKS_URL=https://login.microsoftonline.com/{tenant}/discovery/v2.0/keys |
| # OAUTH_SCOPE=openid profile email |
| |
| # GitHub OAuth Configuration |
| # OAUTH_PROVIDER_TYPE=github |
| # OAUTH_CLIENT_ID=your_github_client_id |
| # OAUTH_CLIENT_SECRET=your_github_client_secret |
| # OAUTH_AUTHORIZATION_URL=https://github.com/login/oauth/authorize |
| # OAUTH_TOKEN_URL=https://github.com/login/oauth/access_token |
| # OAUTH_USERINFO_URL=https://api.github.com/user |
| # OAUTH_SCOPE=user:email |
| |
| # GitLab OAuth Configuration |
| # OAUTH_PROVIDER_TYPE=gitlab |
| # OAUTH_CLIENT_ID=your_gitlab_client_id |
| # OAUTH_CLIENT_SECRET=your_gitlab_client_secret |
| # OAUTH_AUTHORIZATION_URL=https://gitlab.com/oauth/authorize |
| # OAUTH_TOKEN_URL=https://gitlab.com/oauth/token |
| # OAUTH_USERINFO_URL=https://gitlab.com/api/v4/user |
| # OAUTH_SCOPE=read_user |
| |
| # Keycloak OAuth Configuration |
| # OAUTH_PROVIDER_TYPE=keycloak |
| # OAUTH_CLIENT_ID=your_keycloak_client_id |
| # OAUTH_CLIENT_SECRET=your_keycloak_client_secret |
| # OAUTH_REALM=your_realm |
| # OAUTH_SERVER_URL=https://your-keycloak-server.com |
| # OAUTH_AUTHORIZATION_URL=https://your-keycloak-server.com/auth/realms/{realm}/protocol/openid-connect/auth |
| # OAUTH_TOKEN_URL=https://your-keycloak-server.com/auth/realms/{realm}/protocol/openid-connect/token |
| # OAUTH_USERINFO_URL=https://your-keycloak-server.com/auth/realms/{realm}/protocol/openid-connect/userinfo |
| # OAUTH_JWKS_URL=https://your-keycloak-server.com/auth/realms/{realm}/protocol/openid-connect/certs |
| # OAUTH_SCOPE=openid profile email |
| |
| # =================================================================== |
| # Doris-backed OAuth Configuration (Enable with ENABLE_DORIS_OAUTH_AUTH=true) |
| # =================================================================== |
| |
| # Doris-backed OAuth is separate from external OAuth/OIDC. |
| # Do not enable ENABLE_OAUTH_AUTH, OAUTH_ENABLED, or AUTH_TYPE=oauth with this mode. |
| # If both Doris-backed OAuth and external OAuth/OIDC are enabled, startup/config |
| # validation fails fast instead of exposing two OAuth behaviors on one MCP URL. |
| # Default is disabled. |
| ENABLE_DORIS_OAUTH_AUTH=false |
| DORIS_OAUTH_BASE_URL=http://localhost:3000 |
| |
| # Doris-backed OAuth requires HTTP transport and one effective worker. |
| # WORKERS=0 expands to CPU count and will fail when Doris-backed OAuth is enabled. |
| # TRANSPORT=http |
| # WORKERS=1 |
| |
| # Doris OAuth child gate. The allowlist uses exact formal domain.child feature |
| # IDs. Issued scopes use child:call:<domain>:<child> and |
| # child:discover:<domain>:<child>; legacy tool:call scopes are not accepted. |
| # Doris RBAC remains the final data authorization backend. |
| DORIS_OAUTH_CHILD_TOOLS_ENABLED=false |
| DORIS_OAUTH_CHILD_TOOL_ALLOWLIST=doris_catalog.list_databases,doris_query.execute_query,doris_query.explain_query |
| |
| # If SQL should be decided only by Doris RBAC, set ENABLE_SECURITY_CHECK=false; |
| # otherwise the MCP SQL guard can reject some SQL before Doris sees it. |
| |
| # Token/code/client lifetime settings. Current OAuth store is memory-only and |
| # process-local; tokens, auth codes, DCR clients, and client secrets do not |
| # survive process restart. |
| DORIS_OAUTH_ACCESS_TOKEN_EXPIRE_SECONDS=900 |
| DORIS_OAUTH_REFRESH_TOKEN_EXPIRE_SECONDS=86400 |
| DORIS_OAUTH_AUTH_CODE_EXPIRE_SECONDS=300 |
| DORIS_OAUTH_GC_INTERVAL_SECONDS=60 |
| DORIS_OAUTH_IDLE_TIMEOUT_SECONDS= |
| # Compatibility-retained. The current Doris OAuth login page ignores this value |
| # and displays the fixed label "doris". |
| DORIS_OAUTH_LOGIN_PAGE_TITLE="doris" |
| |
| # Dynamic Client Registration: |
| # auto: enabled only for loopback/local development base URLs. |
| # disabled: do not register /oauth/register. |
| # enabled: requires ENABLE_DORIS_OAUTH_PRODUCTION_DCR=true for non-loopback URLs. |
| DORIS_OAUTH_DYNAMIC_CLIENT_REGISTRATION_MODE=auto |
| ENABLE_DORIS_OAUTH_PRODUCTION_DCR=false |
| DORIS_OAUTH_DCR_MAX_CLIENTS=1000 |
| DORIS_OAUTH_DCR_CLIENT_TTL_SECONDS=86400 |
| DORIS_OAUTH_DCR_RATE_LIMIT_PER_IP=30 |
| DORIS_OAUTH_CLIENTS_FILE= |
| DORIS_OAUTH_ALLOWED_REDIRECT_URIS= |
| ENABLE_DORIS_OAUTH_PRODUCTION_WILDCARD_REDIRECTS=false |
| |
| # Rate limits. Keep these enabled for public or shared deployments. |
| DORIS_OAUTH_RATE_LIMIT_WINDOW_SECONDS=300 |
| DORIS_OAUTH_LOGIN_RATE_LIMIT_PER_IP=20 |
| DORIS_OAUTH_LOGIN_RATE_LIMIT_PER_USER=10 |
| DORIS_OAUTH_LOGIN_RATE_LIMIT_PER_CLIENT=30 |
| DORIS_OAUTH_LOGIN_RATE_LIMIT_PER_TXN=5 |
| DORIS_OAUTH_AUTHORIZE_RATE_LIMIT_PER_IP=120 |
| DORIS_OAUTH_TOKEN_RATE_LIMIT_PER_IP=120 |
| DORIS_OAUTH_TOKEN_RATE_LIMIT_PER_CLIENT=240 |
| DORIS_OAUTH_REVOKE_RATE_LIMIT_PER_IP=120 |
| DORIS_OAUTH_REVOKE_RATE_LIMIT_PER_CLIENT=240 |
| DORIS_OAUTH_API_AUTH_TOKEN_RATE_LIMIT_PER_IP=20 |
| DORIS_OAUTH_API_AUTH_TOKEN_RATE_LIMIT_PER_USER=10 |
| DORIS_OAUTH_API_AUTH_REFRESH_RATE_LIMIT_PER_IP=120 |
| DORIS_OAUTH_API_AUTH_REFRESH_RATE_LIMIT_PER_CLIENT=240 |
| |
| # TLS and reverse proxy handling. |
| # Production should use an HTTPS DORIS_OAUTH_BASE_URL. |
| # Non-loopback http:// is rejected unless DORIS_OAUTH_ALLOW_INSECURE_HTTP=true. |
| # Trust proxy headers only from explicitly trusted reverse proxy CIDRs. |
| DORIS_OAUTH_ALLOW_INSECURE_HTTP=false |
| DORIS_OAUTH_TRUST_PROXY_HEADERS=false |
| DORIS_OAUTH_TRUSTED_PROXY_CIDRS= |
| # Example: |
| # DORIS_OAUTH_BASE_URL=https://mcp.example.com |
| # DORIS_OAUTH_TRUST_PROXY_HEADERS=true |
| # DORIS_OAUTH_TRUSTED_PROXY_CIDRS=10.0.0.0/8,192.168.0.0/16 |
| |
| # Legacy token settings (deprecated; no default secret is provided) |
| TOKEN_SECRET= |
| TOKEN_EXPIRY=3600 |
| |
| # SQL security check |
| ENABLE_SECURITY_CHECK=true |
| |
| # Blocked keywords (comma separated) |
| BLOCKED_KEYWORDS=DROP,CREATE,ALTER,TRUNCATE,DELETE,INSERT,UPDATE,GRANT,REVOKE,EXEC,EXECUTE,SHUTDOWN,KILL |
| |
| # Query limits |
| MAX_QUERY_COMPLEXITY=100 |
| # Deployment ceiling; absolute hard cap: 100000 |
| MAX_RESULT_ROWS=10000 |
| # Per-query default when exec_query omits max_rows; must not exceed MAX_RESULT_ROWS |
| DEFAULT_RESULT_ROWS=100 |
| |
| # Data masking |
| ENABLE_MASKING=true |
| |
| # =================================================================== |
| # Performance Configuration |
| # =================================================================== |
| |
| # Query cache |
| ENABLE_QUERY_CACHE=true |
| CACHE_TTL=300 |
| MAX_CACHE_SIZE=1000 |
| |
| # Concurrency control |
| MAX_CONCURRENT_QUERIES=50 |
| # Deployment ceiling; absolute hard cap: 300 seconds |
| QUERY_TIMEOUT=300 |
| # UTF-8 JSON row-data budget; range: 256-16777216 bytes |
| MAX_RESULT_BYTES=1048576 |
| |
| # Response content size limit (characters) |
| MAX_RESPONSE_CONTENT_SIZE=4096 |
| |
| # =================================================================== |
| # ADBC (Arrow Flight SQL) Configuration |
| # =================================================================== |
| # Enable/disable ADBC tools |
| ADBC_ENABLED=true |
| |
| # Default ADBC query parameters |
| # Must not exceed MAX_RESULT_ROWS |
| ADBC_DEFAULT_MAX_ROWS=10000 |
| ADBC_DEFAULT_TIMEOUT=60 |
| # Format: "arrow", "pandas", "dict" |
| ADBC_DEFAULT_RETURN_FORMAT=arrow |
| |
| # ADBC connection timeout |
| ADBC_CONNECTION_TIMEOUT=300 |
| |
| # =================================================================== |
| # Logging Configuration |
| # =================================================================== |
| |
| # Basic logging configuration |
| LOG_LEVEL=INFO |
| LOG_FILE_PATH= |
| |
| # Audit logging |
| ENABLE_AUDIT=true |
| AUDIT_FILE_PATH= |
| |
| # Log file rotation configuration |
| LOG_MAX_FILE_SIZE=10485760 |
| LOG_BACKUP_COUNT=5 |
| |
| # =================================================================== |
| # Log Cleanup Configuration - NEW! |
| # =================================================================== |
| |
| # Enable automatic log cleanup |
| ENABLE_LOG_CLEANUP=true |
| |
| # Maximum age of log files in days (files older than this will be deleted) |
| LOG_MAX_AGE_DAYS=30 |
| |
| # Cleanup check interval in hours |
| LOG_CLEANUP_INTERVAL_HOURS=24 |
| |
| # =================================================================== |
| # Monitoring Configuration |
| # =================================================================== |
| |
| # Metrics collection |
| ENABLE_METRICS=true |
| METRICS_PORT=3001 |
| HEALTH_CHECK_PORT=3002 |
| |
| # Alert configuration |
| ENABLE_ALERTS=false |
| ALERT_WEBHOOK_URL= |
| |
| # =================================================================== |
| # Server Configuration |
| # =================================================================== |
| |
| # Basic server information |
| SERVER_NAME=doris-mcp-server |
| # Product version is defined by the installed package and is not configurable. |
| SERVER_PORT=3000 |
| |
| # Modern MCP is served only at POST /mcp. The isolated 2025-11-25 HTTP |
| # migration adapter is disabled by default and, when enabled, uses |
| # /mcp/legacy. Stdio compatibility is unaffected by this switch. |
| ENABLE_LEGACY_HTTP_ADAPTER=false |
| |
| # Maximum resources, tools, or prompts returned in one list page (1-1000). |
| MCP_LIST_PAGE_SIZE=100 |
| |
| # Explicit cross-call state handles are principal/resource/scope bound, signed, |
| # and expire after the configured lifetime (1-3600 seconds). A launch-local |
| # secret is generated automatically. Independently launched replicas behind a |
| # load balancer must share one generated value of at least 32 bytes. |
| # python -c 'import secrets; print(secrets.token_urlsafe(32))' |
| # MCP_STATE_HANDLE_SECRET=<paste-generated-value-here> |
| MCP_STATE_HANDLE_TTL_SECONDS=300 |
| |
| # Temporary files directory |
| TEMP_FILES_DIR=tmp |
| |
| # =================================================================== |
| # Configuration Examples for Different Environments |
| # =================================================================== |
| |
| # Development Environment Example: |
| # LOG_LEVEL=DEBUG |
| # LOG_MAX_AGE_DAYS=7 |
| # LOG_CLEANUP_INTERVAL_HOURS=6 |
| # ENABLE_SECURITY_CHECK=false |
| |
| # Production Environment Example: |
| # LOG_LEVEL=INFO |
| # LOG_MAX_AGE_DAYS=30 |
| # LOG_CLEANUP_INTERVAL_HOURS=24 |
| # ENABLE_SECURITY_CHECK=true |
| # ENABLE_LOG_CLEANUP=true |
| |
| # Testing Environment Example: |
| # LOG_LEVEL=WARNING |
| # LOG_MAX_AGE_DAYS=3 |
| # LOG_CLEANUP_INTERVAL_HOURS=1 |
| # MAX_RESULT_ROWS=1000 |
| |
| # =================================================================== |
| # Advanced Configuration Notes |
| # =================================================================== |
| |
| # 1. Log Cleanup Feature: |
| # - ENABLE_LOG_CLEANUP: Controls whether to enable automatic cleanup |
| # - LOG_MAX_AGE_DAYS: File retention days, recommended 30 days for production, 7 days for development |
| # - LOG_CLEANUP_INTERVAL_HOURS: Check frequency, recommended 24 hours |
| |
| # 2. Security Best Practices: |
| # - NEW: Enable individual authentication methods using ENABLE_TOKEN_AUTH, ENABLE_JWT_AUTH, ENABLE_OAUTH_AUTH |
| # - When all methods are disabled, anonymous HTTP access is limited to loopback |
| # - Authentication methods work independently - any one succeeding allows access |
| # - Token Auth: Configure deployment-specific TOKEN_<ID> values before enabling it |
| # - JWT Auth: Change JWT_SECRET_KEY and JWT_REFRESH_SECRET_KEY in production |
| # - OAuth Auth: Configure OAuth provider settings and secure client secrets |
| # - TOKEN_SECRET is deprecated and intentionally has no default value |
| # - Adjust BLOCKED_KEYWORDS according to business needs |
| # - Enable ENABLE_SECURITY_CHECK and ENABLE_MASKING |
| # - NEW v0.6.0: Token Management Security (CRITICAL): |
| # * ENABLE_HTTP_TOKEN_MANAGEMENT=false by default (SECURE BY DEFAULT) |
| # * Only enable if you need HTTP token management endpoints |
| # * TOKEN_MANAGEMENT_ADMIN_TOKEN: Use secure random token in production |
| # * TOKEN_MANAGEMENT_ALLOWED_IPS: Restrict to localhost (127.0.0.1,::1) only |
| # * REQUIRE_ADMIN_AUTH=true: Always require admin authentication |
| # * Never expose token management endpoints to external networks |
| |
| # 3. Performance Tuning: |
| # - Adjust MAX_CONCURRENT_QUERIES based on hardware resources |
| # - Adjust QUERY_TIMEOUT based on query complexity |
| # - Adjust MAX_CACHE_SIZE based on memory size |
| |
| # 4. Connection Pool Optimization: |
| # - DORIS_MAX_CONNECTIONS recommended to be 2-4 times the number of CPU cores |
| # - DORIS_CONNECTION_TIMEOUT adjust based on network latency |
| # - DORIS_MAX_CONNECTION_AGE recommended 1 hour to avoid long connection issues |
| |
| # 5. ADBC (Arrow Flight SQL) Configuration: |
| # - FE_ARROW_FLIGHT_SQL_PORT and BE_ARROW_FLIGHT_SQL_PORT: Required for ADBC functionality |
| # - ADBC_DEFAULT_MAX_ROWS: Default maximum rows for ADBC queries (recommended: 100000) |
| # - ADBC_DEFAULT_TIMEOUT: Default timeout for ADBC queries in seconds (recommended: 60) |
| # - ADBC_DEFAULT_RETURN_FORMAT: Default return format (arrow/pandas/dict, recommended: arrow) |
| # - ADBC_CONNECTION_TIMEOUT: Connection timeout for ADBC (recommended: 30) |
| # - ADBC_ENABLED: Enable or disable ADBC tools (true/false) |
| # - Prerequisites: Install adbc_driver_manager, adbc_driver_flightsql, pyarrow packages |
| |
| # 6. Authentication Configuration Guide - UPDATED DESIGN! |
| # |
| # Independent Authentication Control (NEW): |
| # - ENABLE_TOKEN_AUTH=false (default): Disable token authentication |
| # - ENABLE_JWT_AUTH=false (default): Disable JWT authentication |
| # - ENABLE_OAUTH_AUTH=false (default): Disable OAuth authentication |
| # - When all methods are disabled, only loopback HTTP may use anonymous access |
| # - When multiple methods are enabled, any one succeeding allows access |
| # - Recommended for local development/testing: all false with a loopback bind |
| # - Non-loopback HTTP requires authentication; do not enable the dangerous override in production |
| # |
| # Token Authentication (ENABLE_TOKEN_AUTH=true) - Recommended for most use cases: |
| # - Simple and secure token-based authentication |
| # - No default credential; at least one active high-entropy token is required |
| # - Support for custom tokens via TOKEN_* environment variables |
| # - Token file configuration via tokens.json |
| # - Built-in token management HTTP endpoints |
| # - No user management complexity - pure API access control |
| # |
| # JWT Authentication (ENABLE_JWT_AUTH=true) - For stateless applications: |
| # - JSON Web Token based authentication |
| # - Configurable token expiration and refresh |
| # - Support for standard JWT claims |
| # - RSA/ECDSA/HS256 algorithm support |
| # - Suitable for microservices and distributed systems |
| # |
| # OAuth 2.0/OIDC (ENABLE_OAUTH_AUTH=true) - For enterprise integration: |
| # - Integration with external identity providers |
| # - Support for popular providers (Google, Microsoft, GitHub, GitLab, Keycloak) |
| # - OpenID Connect compatibility |
| # - Automatic user provisioning from provider |
| # - Secure authorization code flow |
| # |
| # Authentication Method Selection Guide: |
| # - No Auth (all switches false): Development, testing, trusted networks |
| # - Token Auth only: Small teams, simple deployment, direct API access |
| # - JWT Auth only: Stateless apps, microservices, mobile clients |
| # - OAuth Auth only: Enterprise SSO, large teams, external identity providers |
| # - Multiple methods: Flexible access, different client types, migration scenarios |
| |
| # 7. Token Management Security Configuration Guide (NEW in v0.6.0) - CRITICAL! |
| # |
| # ⚠️ SECURITY WARNING: Token management endpoints are POWERFUL and DANGEROUS |
| # They allow creation, revocation, and management of authentication tokens. |
| # Improper configuration can lead to complete system compromise. |
| # |
| # 🔒 SECURE BY DEFAULT: |
| # - ENABLE_HTTP_TOKEN_MANAGEMENT=false (disabled by default) |
| # - REQUIRE_ADMIN_AUTH=true (admin auth required by default) |
| # - TOKEN_MANAGEMENT_ALLOWED_IPS=127.0.0.1,::1 (localhost only by default) |
| # |
| # 🛡️ SECURITY LAYERS (Applied in order): |
| # 1. Configuration Check: HTTP token management must be explicitly enabled |
| # 2. IP Restrictions: Only allowed IP addresses/networks can access endpoints |
| # 3. Admin Authentication: Valid admin token required for all operations |
| # |
| # 📋 CONFIGURATION OPTIONS: |
| # |
| # Disable Token Management (RECOMMENDED for most deployments): |
| # ENABLE_HTTP_TOKEN_MANAGEMENT=false |
| # # All token management endpoints will return 403 Forbidden |
| # |
| # Enable with Maximum Security (Production): |
| # ENABLE_HTTP_TOKEN_MANAGEMENT=true |
| # TOKEN_MANAGEMENT_ADMIN_TOKEN=<secure-random-token-256-bit> |
| # TOKEN_MANAGEMENT_ALLOWED_IPS=127.0.0.1,::1 |
| # REQUIRE_ADMIN_AUTH=true |
| # |
| # Enable for Private Network (Advanced): |
| # ENABLE_HTTP_TOKEN_MANAGEMENT=true |
| # TOKEN_MANAGEMENT_ADMIN_TOKEN=<secure-random-token-256-bit> |
| # TOKEN_MANAGEMENT_ALLOWED_IPS=127.0.0.1,192.168.1.0/24,10.0.0.0/8 |
| # REQUIRE_ADMIN_AUTH=true |
| # |
| # 🔑 ADMIN TOKEN GENERATION: |
| # # Generate secure admin token (Linux/macOS): |
| # openssl rand -hex 32 |
| # |
| # # Generate secure admin token (Python): |
| # python -c "import secrets; print(secrets.token_urlsafe(32))" |
| # |
| # 🌐 IP CONFIGURATION EXAMPLES: |
| # # Localhost only (most secure): |
| # TOKEN_MANAGEMENT_ALLOWED_IPS=127.0.0.1,::1 |
| # |
| # # Private network + localhost: |
| # TOKEN_MANAGEMENT_ALLOWED_IPS=127.0.0.1,::1,192.168.1.0/24,10.0.0.0/8 |
| # |
| # # Specific servers only: |
| # TOKEN_MANAGEMENT_ALLOWED_IPS=127.0.0.1,192.168.1.10,192.168.1.11 |
| # |
| # # Corporate network (be careful): |
| # TOKEN_MANAGEMENT_ALLOWED_IPS=127.0.0.1,172.16.0.0/12,192.168.0.0/16 |
| # |
| # 🚫 NEVER DO THIS (Security Anti-Patterns): |
| # # NEVER allow all IPs: |
| # # TOKEN_MANAGEMENT_ALLOWED_IPS=0.0.0.0/0 # DANGEROUS! |
| # |
| # # NEVER disable admin auth in production: |
| # # REQUIRE_ADMIN_AUTH=false # DANGEROUS! |
| # |
| # # NEVER use short, repeated, or placeholder admin tokens. |
| # |
| # 📊 ENDPOINT SECURITY TESTING: |
| # # Test security (should fail): |
| # curl -X POST http://external-ip:3000/token/create |
| # # Expected: 403 Forbidden (IP not allowed) |
| # |
| # # Test without auth (should fail): |
| # curl -X POST http://127.0.0.1:3000/token/create |
| # # Expected: 401 Unauthorized (missing admin token) |
| # |
| # # Test with valid auth (should succeed if enabled): |
| # curl -H "Authorization: Bearer $TOKEN_MANAGEMENT_ADMIN_TOKEN" http://127.0.0.1:3000/token/stats |
| # # Expected: 200 OK with token statistics |
| # |
| # 🔍 MONITORING & AUDITING: |
| # # All token management access attempts are logged: |
| # tail -f logs/doris_mcp_server_audit.log | grep "token management" |
| # |
| # # Monitor security events: |
| # tail -f logs/doris_mcp_server_info.log | grep -E "(access denied|token management)" |
| # |
| # ✅ SECURITY BEST PRACTICES: |
| # - Keep ENABLE_HTTP_TOKEN_MANAGEMENT=false unless absolutely necessary |
| # - Use file-based token management (tokens.json) instead of HTTP endpoints |
| # - Generate strong admin tokens using cryptographically secure methods |
| # - Restrict access to localhost (127.0.0.1,::1) whenever possible |
| # - Never expose token management endpoints to public internet |
| # - Regularly audit token management access logs |
| # - Use firewall rules as additional protection layer |
| # - Consider VPN access for remote token management needs |