diff --git a/Dockerfile b/Dockerfile index 2e91ac1..52cf757 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,7 +5,10 @@ WORKDIR /app # Environment variables ENV UV_COMPILE_BYTECODE=1 \ PYTHONUNBUFFERED=1 \ - PYTHONDONTWRITEBYTECODE=1 + PYTHONDONTWRITEBYTECODE=1 \ + # MCP server defaults for HTTP transports + MCP_HOST=0.0.0.0 \ + MCP_PORT=8000 # Install uv COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ @@ -31,5 +34,5 @@ ENTRYPOINT ["uv", "run", "src/server.py"] # Default arguments (can be overridden) # For stdio (default MCP transport): no args needed -# For HTTP: --transport streamable-http --host 0.0.0.0 --port 8000 +# For HTTP: --transport streamable-http CMD ["--transport", "stdio"] \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 5f6c5ed..32a05a1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,7 +15,7 @@ services: # Usage: docker-compose up mcp-trino-http mcp-trino-http: build: . - command: ["--transport", "streamable-http", "--host", "0.0.0.0", "--port", "8000"] + command: ["--transport", "streamable-http"] ports: - "8000:8000" environment: @@ -24,6 +24,8 @@ services: - TRINO_USER=trino - TRINO_CATALOG=tpch - TRINO_SCHEMA=tiny + - MCP_HOST=0.0.0.0 + - MCP_PORT=8000 depends_on: trino: condition: service_healthy @@ -35,7 +37,7 @@ services: # Usage: docker-compose --profile sse up mcp-trino-sse mcp-trino-sse: build: . - command: ["--transport", "sse", "--host", "0.0.0.0", "--port", "8000"] + command: ["--transport", "sse"] ports: - "8001:8000" environment: @@ -44,6 +46,8 @@ services: - TRINO_USER=trino - TRINO_CATALOG=tpch - TRINO_SCHEMA=tiny + - MCP_HOST=0.0.0.0 + - MCP_PORT=8000 depends_on: trino: condition: service_healthy diff --git a/pyproject.toml b/pyproject.toml index d6b718d..3e9bda3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "mcp-trino-python" -version = "0.7.0" +version = "0.7.1" description = "A Model Context Protocol (MCP) connector for Trino, enabling seamless integration between MCP-compliant services and Trino query engine" readme = "README.md" license = { text = "Apache-2.0" } diff --git a/src/server.py b/src/server.py index 02c2884..6ca1112 100644 --- a/src/server.py +++ b/src/server.py @@ -4,6 +4,8 @@ functionality through resources and tools, with special support for Iceberg tables. """ +import os + from mcp.server.fastmcp import FastMCP from mcp.server.fastmcp.prompts import base from pydantic import Field @@ -16,11 +18,16 @@ client = TrinoClient(config) -# Initialize the MCP server with context +# Initialize the MCP server with recommended settings for all transports mcp = FastMCP( name="Trino Explorer", instructions="This Model Context Protocol (MCP) server provides access to Trino Query Engine.", - dependencies=["trino", "python-dotenv", "loguru"], + # HTTP transport settings (used by streamable-http and sse) + host=os.getenv("MCP_HOST", "127.0.0.1"), + port=int(os.getenv("MCP_PORT", "8000")), + # Recommended for production HTTP deployments + stateless_http=True, + json_response=True, ) @@ -561,17 +568,21 @@ def maintain_iceberg(table: str, catalog: str, schema_name: str) -> list[base.Me # Run with SSE transport python server.py --transport sse --host 127.0.0.1 --port 8001 + +Environment variables: + MCP_HOST Default host for HTTP transports (default: 127.0.0.1) + MCP_PORT Default port for HTTP transports (default: 8000) """, ) parser.add_argument( "--host", - default="127.0.0.1", + default=None, help="Host to bind to (default: 127.0.0.1, use 0.0.0.0 for all interfaces)", ) parser.add_argument( "--port", type=int, - default=8000, + default=None, help="Port to listen on (default: 8000)", ) parser.add_argument( @@ -582,22 +593,25 @@ def maintain_iceberg(table: str, catalog: str, schema_name: str) -> list[base.Me ) args = parser.parse_args() + # Update settings if CLI args provided (override env vars) + if args.host: + mcp.settings.host = args.host + if args.port: + mcp.settings.port = args.port + logger.info(f"Starting Trino MCP server with {args.transport} transport") if args.transport == "stdio": logger.info("Using stdio transport for local MCP communication") mcp.run(transport="stdio") elif args.transport == "streamable-http": - logger.info(f"Starting Streamable HTTP server on http://{args.host}:{args.port}/mcp") - mcp.run(transport="streamable-http", host=args.host, port=args.port) + logger.info(f"Starting Streamable HTTP server on http://{mcp.settings.host}:{mcp.settings.port}/mcp") + mcp.run(transport="streamable-http") elif args.transport == "sse": - logger.info(f"Starting SSE server on http://{args.host}:{args.port}/sse") - mcp.run(transport="sse", host=args.host, port=args.port) + logger.info(f"Starting SSE server on http://{mcp.settings.host}:{mcp.settings.port}/sse") + mcp.run(transport="sse") def main(): """Entry point for the MCP Trino server.""" - import sys - - sys.argv = sys.argv[:1] # Reset args for mcp.run mcp.run(transport="stdio")