Skip to content

[WIP] adding docker build #39

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Use a Python image with uv pre-installed
FROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim AS uv

# Install the project into `/app`
WORKDIR /app

# Enable bytecode compilation
ENV UV_COMPILE_BYTECODE=1

# Copy from the cache instead of linking since it's a mounted volume
ENV UV_LINK_MODE=copy

RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential liblz4-dev libzstd-dev
# Install the project's dependencies using the lockfile and settings
RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=uv.lock,target=uv.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
uv sync --frozen --no-install-project --no-dev --no-editable

# Then, add the rest of the project source code and install it
# Installing separately from its dependencies allows optimal layer caching
ADD . /app
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-dev --no-editable

FROM python:3.13-slim-bookworm

WORKDIR /app
# Copy the virtual environment
COPY --from=uv --chown=app:app /app/.venv /app/.venv
# Copy the uv executable
COPY --from=uv /usr/local/bin/uv /usr/local/bin/
# Copy the project files
COPY --from=uv /app /app

# Place executables in the environment at the front of the path
ENV PATH="/app/.venv/bin:/usr/local/bin:$PATH"

# Add ClickHouse environment variables
ENV CLICKHOUSE_HOST=""
ENV CLICKHOUSE_PORT="8443"
ENV CLICKHOUSE_USER=""
ENV CLICKHOUSE_PASSWORD=""
ENV CLICKHOUSE_SECURE="true"
ENV CLICKHOUSE_VERIFY="true"
ENV CLICKHOUSE_CONNECT_TIMEOUT="30"
ENV CLICKHOUSE_SEND_RECEIVE_TIMEOUT="300"
ENV CLICKHOUSE_DATABASE=""

EXPOSE 28123
# when running the container, add --db-path and a bind mount to the host's db file
ENTRYPOINT ["uv", "run", "mcp-clickhouse-sse", "--directory", "/app"]
44 changes: 44 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,50 @@ You can set these variables in your environment, in a `.env` file, or in the Cla
}
```

## Running with Docker Compose

You can run the MCP server using Docker Compose with SSE mode. Create a `docker-compose.yml` file with the following configuration:

```yaml
version: '3.8'
services:
mcp-clickhouse:
build: .
environment:
- CLICKHOUSE_HOST=your-clickhouse-host
- CLICKHOUSE_PORT=8443
- CLICKHOUSE_USER=your-user
- CLICKHOUSE_PASSWORD=your-password
- CLICKHOUSE_DATABASE=your-database
- CLICKHOUSE_SECURE=true
- CLICKHOUSE_VERIFY=true
ports:
- "28123:28123"
```

Then run:
```bash
docker compose up -d
```

### MCP Configuration for Docker

When running the MCP server in Docker in SSE, you'll need to configure your MCP client to use `host.docker.internal` when running on the same machine. Update your MCP configuration to use the following URI:

```json
{
"mcpServers": {
"mcp-clickhouse": {
"type": "sse",
"uri": "http://host.docker.internal:28123/sse",
"timeout": 60000
}
}
}
```

If you're using Claude Desktop, add this configuration to your `claude_desktop_config.json` file along with the existing configuration.

### Running tests

```bash
Expand Down
18 changes: 18 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
version: '3.8'

services:
mcp-clickhouse:
build:
context: .
dockerfile: Dockerfile
ports:
- "28123:28123"
environment:
- CLICKHOUSE_HOST=sql-clickhouse.clickhouse.com
- CLICKHOUSE_PORT=8443
- CLICKHOUSE_USER=demo
- CLICKHOUSE_PASSWORD=
- CLICKHOUSE_SECURE=true
- CLICKHOUSE_VERIFY=true
- CLICKHOUSE_CONNECT_TIMEOUT=30
- CLICKHOUSE_SEND_RECEIVE_TIMEOUT=30
7 changes: 7 additions & 0 deletions mcp_clickhouse/main.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import asyncio
import argparse

from .mcp_server import mcp


def main():
mcp.run()


def main_sse():
mcp.run(transport="sse")


if __name__ == "__main__":
main()
3 changes: 2 additions & 1 deletion mcp_clickhouse/mcp_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class Table:


MCP_SERVER_NAME = "mcp-clickhouse"
SERVER_PORT = 28123

# Configure logging
logging.basicConfig(
Expand All @@ -66,7 +67,7 @@ class Table:
"pip-system-certs",
]

mcp = FastMCP(MCP_SERVER_NAME, dependencies=deps)
mcp = FastMCP(MCP_SERVER_NAME, dependencies=deps, port=SERVER_PORT)


def result_to_table(query_columns, result) -> List[Table]:
Expand Down
5 changes: 3 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "mcp-clickhouse"
version = "0.1.7"
version = "0.1.8"
description = "An MCP server for ClickHouse."
readme = "README.md"
license = "Apache-2.0"
Expand All @@ -10,13 +10,14 @@ dependencies = [
"mcp[cli]>=1.3.0",
"python-dotenv>=1.0.1",
"uvicorn>=0.34.0",
"uvicorn[standard]>=0.34.0",
"clickhouse-connect>=0.8.16",
"pip-system-certs>=4.0",
]

[project.scripts]
mcp-clickhouse = "mcp_clickhouse.main:main"

mcp-clickhouse-sse = "mcp_clickhouse.main:main_sse"
[project.urls]
Home = "https://github.com/ClickHouse/mcp-clickhouse"

Expand Down
5 changes: 5 additions & 0 deletions server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import uvicorn
from mcp_clickhouse.mcp_server import app

if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=18213)