Skip to content

Commit 3f682dd

Browse files
authored
Merge pull request #9 from alaturqua/update_project
feat: add multi-transport support (stdio, streamable-http, sse)
2 parents 80a8322 + 9d2b2a6 commit 3f682dd

File tree

5 files changed

+712
-266
lines changed

5 files changed

+712
-266
lines changed

Dockerfile

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,34 @@ FROM python:3.12-slim
22

33
WORKDIR /app
44

5-
ENV UV_COMPILE_BYTECODE=1
5+
# Environment variables
6+
ENV UV_COMPILE_BYTECODE=1 \
7+
PYTHONUNBUFFERED=1 \
8+
PYTHONDONTWRITEBYTECODE=1
69

10+
# Install uv
711
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
812

9-
WORKDIR /app
10-
11-
COPY pyproject.toml pyproject.toml
12-
COPY uv.lock uv.lock
13+
# Copy dependency files first for better caching
14+
COPY pyproject.toml uv.lock ./
1315

16+
# Install dependencies
1417
RUN --mount=type=cache,target=/root/.cache/uv \
1518
uv sync --frozen --no-dev --no-editable
1619

17-
ADD . /app
20+
# Copy source code
21+
COPY src/ src/
1822

1923
ENV PATH="/app/.venv/bin:$PATH"
2024

25+
# Default port for HTTP transports
2126
EXPOSE 8000
2227

23-
ENTRYPOINT [ "uv", "run", "src/server.py" ]
24-
CMD [ "--host", "0.0.0.0", "--port", "8000" ]
28+
# Default transport is stdio for MCP compatibility
29+
# Override with --transport streamable-http or --transport sse for HTTP modes
30+
ENTRYPOINT ["uv", "run", "src/server.py"]
31+
32+
# Default arguments (can be overridden)
33+
# For stdio (default MCP transport): no args needed
34+
# For HTTP: --transport streamable-http --host 0.0.0.0 --port 8000
35+
CMD ["--transport", "stdio"]

docker-compose.yml

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,77 @@ services:
22
trino:
33
image: trinodb/trino:latest
44
ports:
5-
- 8080:8080
5+
- "8080:8080"
66
networks:
77
- trino-network
8+
healthcheck:
9+
test: ["CMD", "curl", "-f", "http://localhost:8080/v1/info"]
10+
interval: 10s
11+
timeout: 5s
12+
retries: 5
13+
14+
# MCP Server with Streamable HTTP transport (recommended for web/remote access)
15+
# Usage: docker-compose up mcp-trino-http
16+
mcp-trino-http:
17+
build: .
18+
command: ["--transport", "streamable-http", "--host", "0.0.0.0", "--port", "8000"]
19+
ports:
20+
- "8000:8000"
21+
environment:
22+
- TRINO_HOST=trino
23+
- TRINO_PORT=8080
24+
- TRINO_USER=trino
25+
- TRINO_CATALOG=tpch
26+
- TRINO_SCHEMA=tiny
27+
depends_on:
28+
trino:
29+
condition: service_healthy
30+
networks:
31+
- trino-network
32+
restart: unless-stopped
33+
34+
# MCP Server with SSE transport (legacy HTTP transport)
35+
# Usage: docker-compose --profile sse up mcp-trino-sse
36+
mcp-trino-sse:
37+
build: .
38+
command: ["--transport", "sse", "--host", "0.0.0.0", "--port", "8000"]
39+
ports:
40+
- "8001:8000"
41+
environment:
42+
- TRINO_HOST=trino
43+
- TRINO_PORT=8080
44+
- TRINO_USER=trino
45+
- TRINO_CATALOG=tpch
46+
- TRINO_SCHEMA=tiny
47+
depends_on:
48+
trino:
49+
condition: service_healthy
50+
networks:
51+
- trino-network
52+
profiles:
53+
- sse
54+
restart: unless-stopped
55+
56+
# MCP Server with stdio transport (for testing with docker exec)
57+
# Usage: docker-compose --profile stdio run --rm mcp-trino-stdio
58+
mcp-trino-stdio:
59+
build: .
60+
command: ["--transport", "stdio"]
61+
environment:
62+
- TRINO_HOST=trino
63+
- TRINO_PORT=8080
64+
- TRINO_USER=trino
65+
- TRINO_CATALOG=tpch
66+
- TRINO_SCHEMA=tiny
67+
depends_on:
68+
trino:
69+
condition: service_healthy
70+
networks:
71+
- trino-network
72+
profiles:
73+
- stdio
74+
stdin_open: true
75+
tty: true
876

977
networks:
1078
trino-network:

pyproject.toml

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,11 @@
11
[project]
22
name = "mcp-trino-python"
3-
version = "0.6.0"
3+
version = "0.7.0"
44
description = "A Model Context Protocol (MCP) connector for Trino, enabling seamless integration between MCP-compliant services and Trino query engine"
55
readme = "README.md"
66
license = { text = "Apache-2.0" }
77
requires-python = ">=3.12"
8-
keywords = ["trino", "connector", "mcp"]
9-
dependencies = [
10-
"loguru>=0.7.3",
11-
"mcp[cli]>=1.22.0",
12-
"python-dotenv>=1.1.0",
13-
"trino>=0.336.0",
14-
]
15-
8+
keywords = ["trino", "connector", "mcp", "iceberg", "data-catalog"]
169
classifiers = [
1710
"Programming Language :: Python :: 3.12",
1811
"License :: OSI Approved :: Apache Software License",
@@ -21,6 +14,29 @@ classifiers = [
2114
"Intended Audience :: Developers",
2215
"Topic :: Software Development :: Libraries :: Python Modules",
2316
]
17+
dependencies = [
18+
"loguru>=0.7.3",
19+
"mcp[cli]>=1.22.0",
20+
"python-dotenv>=1.2.1",
21+
"trino>=0.336.0",
22+
]
23+
24+
[project.optional-dependencies]
25+
# For running HTTP-based transports (streamable-http, sse)
26+
http = ["uvicorn>=0.32.0", "starlette>=0.41.0"]
27+
28+
[project.scripts]
29+
mcp-trino = "server:main"
30+
31+
[tool.uv]
32+
package = true
33+
34+
[build-system]
35+
requires = ["hatchling"]
36+
build-backend = "hatchling.build"
37+
38+
[tool.hatch.build.targets.wheel]
39+
packages = ["src"]
2440

2541
[tool.black]
2642
target-version = ["py312"]

src/server.py

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -535,21 +535,69 @@ def maintain_iceberg(table: str, catalog: str, schema_name: str) -> list[base.Me
535535

536536
if __name__ == "__main__":
537537
import argparse
538+
import sys
538539

539540
from loguru import logger
540541

541-
logger.info("Starting Trino MCP server...")
542-
543-
parser = argparse.ArgumentParser(description="Run MCP Trino Server")
544-
parser.add_argument("--host", default="127.0.0.1", help="Host to bind to")
545-
parser.add_argument("--port", type=int, default=8000, help="Port to listen on")
542+
# Configure logging
543+
logger.remove()
544+
logger.add(sys.stderr, level="INFO", format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {message}")
545+
546+
parser = argparse.ArgumentParser(
547+
description="MCP Trino Server - Model Context Protocol connector for Trino",
548+
formatter_class=argparse.RawDescriptionHelpFormatter,
549+
epilog="""
550+
Transport modes:
551+
stdio Standard I/O (default) - for local MCP clients like VS Code
552+
streamable-http HTTP with streaming support (recommended for remote/web access)
553+
sse Server-Sent Events (legacy HTTP transport)
554+
555+
Examples:
556+
# Run with stdio (default, for VS Code integration)
557+
python server.py
558+
559+
# Run with Streamable HTTP on port 8000
560+
python server.py --transport streamable-http --host 0.0.0.0 --port 8000
561+
562+
# Run with SSE transport
563+
python server.py --transport sse --host 127.0.0.1 --port 8001
564+
""",
565+
)
566+
parser.add_argument(
567+
"--host",
568+
default="127.0.0.1",
569+
help="Host to bind to (default: 127.0.0.1, use 0.0.0.0 for all interfaces)",
570+
)
571+
parser.add_argument(
572+
"--port",
573+
type=int,
574+
default=8000,
575+
help="Port to listen on (default: 8000)",
576+
)
546577
parser.add_argument(
547578
"--transport",
548579
choices=["stdio", "streamable-http", "sse"],
549580
default="stdio",
550-
help="Transport type to use (default: stdio)",
581+
help="Transport type (default: stdio)",
551582
)
552583
args = parser.parse_args()
553584

554-
# Run the server with the specified transport
555-
mcp.run(transport=args.transport, host=args.host, port=args.port)
585+
logger.info(f"Starting Trino MCP server with {args.transport} transport")
586+
587+
if args.transport == "stdio":
588+
logger.info("Using stdio transport for local MCP communication")
589+
mcp.run(transport="stdio")
590+
elif args.transport == "streamable-http":
591+
logger.info(f"Starting Streamable HTTP server on http://{args.host}:{args.port}/mcp")
592+
mcp.run(transport="streamable-http", host=args.host, port=args.port)
593+
elif args.transport == "sse":
594+
logger.info(f"Starting SSE server on http://{args.host}:{args.port}/sse")
595+
mcp.run(transport="sse", host=args.host, port=args.port)
596+
597+
598+
def main():
599+
"""Entry point for the MCP Trino server."""
600+
import sys
601+
602+
sys.argv = sys.argv[:1] # Reset args for mcp.run
603+
mcp.run(transport="stdio")

0 commit comments

Comments
 (0)