Skip to content
Open
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
37 changes: 37 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Python
__pycache__/
*.pyc
*.pyo
*.pyd
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# Git
.git/
.gitignore

# Docker
.dockerignore
Dockerfile

# Testing
tests/
noxfile.py

# GitHub
.github/
23 changes: 23 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Use the official lightweight Python image.
# https://hub.docker.com/_/python
FROM python:3.11-slim

# Set the working directory in the container.
WORKDIR /app

# Copy the dependency file to the working directory.
COPY pyproject.toml .

# Install any dependencies.
RUN pip install --no-cache-dir -e .

# Copy the rest of the working directory contents into the container.
COPY . .

# Set the port that the container will listen on.
# This is the default port for Cloud Run.
ENV PORT=8080
ENV HOST=0.0.0.0

# Run the application.
CMD ["analytics-mcp"]
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,34 @@ Here are some sample prompts to get you started:
what are the custom dimensions and custom metrics in my property?
```

## Running with Docker 🐳

This project includes a `Dockerfile` that can be used to run the server in a
container.

### Build the image

From the root of the repository, run the following command to build the Docker
image:

```shell
docker build -t analytics-mcp .
```

### Run the container

To run the server in a Docker container, you will need to provide your
Application Default Credentials (ADC) to the container. You can do this by
mounting the directory containing your `gcloud` configuration to the container.

```shell
docker run -p 8080:8080 \
-v ~/.config/gcloud:/root/.config/gcloud \
analytics-mcp
```

The server will be available at `http://localhost:8080`.

## Contributing ✨

Contributions welcome! See the [Contributing Guide](CONTRIBUTING.md).
7 changes: 6 additions & 1 deletion analytics_mcp/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

"""Entry point for the Google Analytics MCP server."""

import os
from analytics_mcp.coordinator import mcp

# The following imports are necessary to register the tools with the `mcp`
Expand All @@ -32,7 +33,11 @@ def run_server() -> None:

Serves as the entrypoint for the 'runmcp' command.
"""
mcp.run()
# For Cloud Run, the server must listen on 0.0.0.0 and a port specified by
# the PORT environment variable.
host = os.environ.get("HOST", "127.0.0.1")
port = int(os.environ.get("PORT", "8000"))
Comment on lines +38 to +39
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of hardcoding the defaults used by mcp here (127,0.0.1 and 8000), could you make overriding the host and port only happen if the environment has the HOST and PORT env vars set?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It turns out that FastMCP already handles host/port overrides via its own env vars FAST_MCP_HOST and FAST_MCP_PORT, respectively. See this comment in server.py.

If you use those in Docker, you won't need this code that overrides the host and port at all.

Comment on lines +38 to +39
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, HOST and PORT are pretty general names that might conflict with existing env vars. WDYT of naming these MCP_HOST and MCP_PORT instead? Then users not using Docker could also override these values just for the MCP server, without conflicts.

mcp.run(transport="streamable-http", host=host, port=port)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this require an upgrade to the mcp[cli] dependency? I don't see the streamable-http option in v1.2.0:

https://github.com/modelcontextprotocol/python-sdk/blob/af940aeea7abf8454c811b22c6b90372127bb3ea/src/mcp/server/fastmcp/server.py#L113

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

host and port don't appear to be valid keyword args for the run() method, even in the main branch:

https://github.com/modelcontextprotocol/python-sdk/blob/47d35f0b3ca2e59ddc26ddc0f2a816ac3dc8df9b/src/mcp/server/fastmcp/server.py#L233

Should the host and port override go in the constructor call instead?



if __name__ == "__main__":
Expand Down