Deployment
August 1, 2026 · View on GitHub
This guide covers supported 1.0 deployment shapes. Start from loopback, add an intentional authentication mode, and validate the real Apache Doris route before exposing the Server to a Host.
Choose a transport
| Shape | Use when | Process model | Authentication boundary |
|---|---|---|---|
| stdio | One local Host launches one Server | child process | local OS/process boundary plus Doris credentials |
| Streamable HTTP, loopback | Local tools share a service | one or more workers, subject to auth mode | token/JWT/OAuth optional but recommended |
| Streamable HTTP behind TLS proxy | Controlled remote access | proxy + Server workers | authenticated HTTP, trusted proxy policy, TLS |
The retired standalone SSE transport is not supported. New HTTP integrations
use POST /mcp and MCP 2026-07-28.
stdio deployment
Example Host command:
{
"command": "doris-mcp-server",
"args": ["--transport", "stdio"],
"env": {
"DORIS_HOST": "127.0.0.1",
"DORIS_PORT": "9030",
"DORIS_USER": "mcp_reader",
"DORIS_PASSWORD": "<secret>",
"DORIS_DATABASE": "information_schema"
}
}
Operational rules:
- stdout is reserved for MCP frames;
- logs must use stderr or configured files;
- the Host owns process restart and environment injection;
- do not share the process with unrelated users when credentials are in the environment;
- stdio initialization establishes a working Doris route before accepting ordinary work.
Streamable HTTP deployment
Local command:
export TRANSPORT=http
export SERVER_HOST=127.0.0.1
export SERVER_PORT=3000
export DORIS_HOST=127.0.0.1
export DORIS_PORT=9030
export DORIS_USER=mcp_reader
export DORIS_PASSWORD='<secret>'
doris-mcp-server --transport http --host 127.0.0.1 --port 3000
Endpoints:
POST /mcp— modern MCP requests;GET /live— process/protocol liveness;GET /ready— bounded Doris-backed readiness;GET /health— compatibility health view;/mcp/legacy— default-off protocol migration adapter.
Enable /mcp/legacy only for validated handshake-era clients such as Dify
1.16.1 (2025-06-18) or SDK v2 clients using 2025-11-25:
export ENABLE_LEGACY_HTTP_ADAPTER=true
Configure those Hosts with the exact /mcp/legacy URL. Keep modern
2026-07-28 Hosts on /mcp; the Server never silently downgrades that
endpoint.
Keep the Server on loopback until authentication, Host/Origin policy, proxy behavior, TLS termination, timeouts, and secret injection are tested together.
Authentication and worker count
Stateless MCP requests do not require sticky sessions. Authentication and provider modes can impose tighter constraints:
| Mode | Worker guidance |
|---|---|
| static token | multiple workers are possible with shared token/state configuration |
| JWT | multiple workers are possible with consistent keys/policy |
| external OAuth/OIDC | multiple workers require consistent validation and mapping configuration |
| Doris-backed OAuth | exactly one worker in 1.0; tokens and user pools are process-local |
| custom provider rate limiting | quotas are per process unless the provider supplies external state |
Independently launched replicas behind a load balancer must share the same
high-entropy MCP_STATE_HANDLE_SECRET so pagination/state handles remain valid
across instances. They must also share compatible authorization policy and
visible catalogs. Do not share Doris OAuth traffic across replicas in 1.0.
Docker
Build locally:
docker build -t doris-mcp-server:1.0.0 .
Run with an environment file stored outside the image:
docker run --rm \
--env-file /secure/path/doris-mcp.env \
--publish 127.0.0.1:3000:3000 \
doris-mcp-server:1.0.0
Or review docker-compose.yml and .env.example before using Compose. The
checked-in examples contain placeholders and security assertions; they are not
production credentials.
Container requirements:
- pin the image/release rather than deploying mutable
latest; - mount secret files read-only with owner-restricted permissions;
- keep
/liveand/readyas separate probes; - set memory/CPU limits compatible with query concurrency and result ceilings;
- allow only required FE MySQL, FE HTTP, BE HTTP, OAuth, and provider egress;
- avoid publishing the port on all interfaces until the proxy/auth boundary is complete.
Reverse proxy and TLS
When traffic leaves the machine:
- terminate TLS with a controlled proxy or in the platform ingress;
- preserve required MCP headers and request body without method/name rewrite;
- configure exact public Host/Origin behavior;
- configure trusted proxy CIDRs before honoring forwarded headers;
- reject oversized requests before they reach the process, while keeping limits compatible with MCP Schema/instance ceilings;
- disable buffering/timeouts that would truncate valid Streamable HTTP responses;
- never log bearer or admin authorization headers.
Binding 0.0.0.0 only selects a network interface. It does not authorize a
public hostname, proxy, or Origin.
Apache Doris routing
Single FE:
export DORIS_HOST=fe.example
export DORIS_PORT=9030
export DORIS_FE_HTTP_HOST=fe.example
export DORIS_FE_HTTP_PORT=8030
Multiple FE candidates:
export DORIS_HOSTS='fe-1.example:9030,fe-2.example:9030'
export DORIS_FE_HTTP_HOSTS='fe-1.example:8030,fe-2.example:8030'
Explicit BE HTTP allowlist:
export DORIS_BE_HOSTS='be-1.example:8040,be-2.example:8040'
The route manager validates candidates and preserves route identity. Do not allow MCP callers to supply arbitrary FE/BE hostnames. Network policy should restrict egress to the configured cluster and reviewed providers.
Exposure mode
Default:
export MCP_TOOL_EXPOSURE_MODE=hierarchical
Host compatibility fallback:
export MCP_TOOL_EXPOSURE_MODE=flat
Changing the mode requires process restart and Host reconnect. It is a startup contract, not a per-request switch.
Optional providers
- ADBC: enable the default-off advanced provider and configure Arrow Flight
SQL ports; ordinary queries still use MySQL, and ADBC calls require explicit
end-user intent plus
explicit_adbc=true. - Ossie: set
OSSIE_ENABLED=true, mount reviewed models and private Doris bindings, and grant explicit semantic scopes. - MetricFlow: configure an absolute reviewed sidecar command and project; validate Doris-dialect compilation and real Doris read-only/negative-write behavior before enabling it.
- Native lineage: configure the canonical queryable store/provider and verify required columns and delivery health.
- Custom tools: install the package and list its exact provider name in
MCP_TOOL_PROVIDERS.
An optional provider that is absent should make relevant children unavailable, not prevent unrelated domains from working. An explicitly allowlisted but invalid custom provider fails startup.
Rollout procedure
- Pin the package/image and capture configuration hashes without secrets.
- Validate startup configuration offline/in a staging process.
- Check
/liveand/readyindependently. - Run
server/discoverandtools/listfrom the target Host. - Discover all authorized domains and record
callablestates/reason codes. - Execute a read-only
SELECT 1through the formal Query child. - Execute negative tests: write SQL rejection, unauthorized child, invalid cursor, permission-denied table, result/timeout ceiling.
- Validate FE failover and readiness if multiple FE routes are configured.
- Compare the generated tool registry and release artifacts with the deployed package version.
- Enable production traffic gradually and monitor typed failures/truncation.
Upgrade and rollback
- Read Migrating to 1.0 before replacing a pre-1.0 Server.
- Restart Hosts so cached pre-1.0 schemas disappear.
- Treat exposure-mode changes as an API change requiring reconnect.
- Roll back package/image and configuration together.
- A rollback does not make 1.0 state handles or manifests valid on an older process; Hosts must rediscover.
- Do not use the legacy HTTP adapter as a permanent mixed-version deployment.