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
56 changes: 43 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Note: There is also a work-in-progress TypeScript implementation available in a
## Key Features

- **Galaxy Connection**: Connect to any Galaxy instance with a URL and API key
- **OAuth Login (optional)**: Offer browser-based sign-in that exchanges credentials for temporary Galaxy API keys
- **Server Information**: Retrieve comprehensive server details including version, configuration, and capabilities
- **Tools Management**: Search, view details, and execute Galaxy tools
- **Workflow Integration**: Access and import workflows from the Interactive Workflow Composer (IWC)
Expand All @@ -20,36 +21,65 @@ Note: There is also a work-in-progress TypeScript implementation available in a

## Quick Start

The fastest way to get started is using `uvx`:
The `galaxy-mcp` CLI ships with both stdio (local) and HTTP transports. Choose the setup that
matches your client:

```bash
# Run the server directly without installation
# Stdio transport (default) – great for local development tools
uvx galaxy-mcp

# Run with MCP developer tools for interactive exploration
uvx --from galaxy-mcp mcp dev galaxy_mcp.server

# Run as a deployed MCP server
uvx --from galaxy-mcp mcp run galaxy_mcp.server
# HTTP transport with OAuth (for remote/browser clients)
export GALAXY_URL="https://usegalaxy.org.au/" # Target Galaxy instance
export GALAXY_MCP_PUBLIC_URL="https://mcp.example.com" # Public base URL for OAuth redirects
export GALAXY_MCP_SESSION_SECRET="$(openssl rand -hex 32)"
uvx galaxy-mcp --transport streamable-http --host 0.0.0.0 --port 8000
```

You'll need to set up your Galaxy credentials via environment variables:
When running over stdio you can provide long-lived credentials via environment variables:

```bash
export GALAXY_URL=<galaxy_url>
export GALAXY_API_KEY=<galaxy_api_key>
export GALAXY_URL="https://usegalaxy.org/"
export GALAXY_API_KEY="your-api-key"
```

For OAuth flows the server exchanges user credentials for short-lived Galaxy API keys on demand, so
you typically leave `GALAXY_API_KEY` unset.

### Alternative Installation

```bash
# Install from PyPI
pip install galaxy-mcp

# Or from source
# Run (stdio by default)
galaxy-mcp

# Or from source using uv
cd mcp-server-galaxy-py
pip install -r requirements.txt
mcp run main.py
uv sync
uv run galaxy-mcp --transport streamable-http --host 0.0.0.0 --port 8000
```

## Container Usage

The published image defaults to stdio transport (no HTTP listener):

```bash
docker run --rm -it \
-e GALAXY_URL="https://usegalaxy.org/" \
-e GALAXY_API_KEY="your-api-key" \
galaxyproject/galaxy-mcp
```

For OAuth + HTTP:

```bash
docker run --rm -it -p 8000:8000 \
-e GALAXY_URL="https://usegalaxy.org.au/" \
-e GALAXY_MCP_TRANSPORT="streamable-http" \
-e GALAXY_MCP_PUBLIC_URL="https://mcp.example.com" \
-e GALAXY_MCP_SESSION_SECRET="$(openssl rand -hex 32)" \
galaxyproject/galaxy-mcp
```

## Development Guidelines
Expand Down
17 changes: 10 additions & 7 deletions mcp-server-galaxy-py/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,12 @@ RUN groupadd -r app && useradd -r -g app app

WORKDIR /app

# Define default environment variables
ENV GALAXY_INSTANCE="https://usegalaxy.org" \
GALAXY_API_KEY=""
# Define default environment variables (stdio transport by default)
ENV GALAXY_URL="https://usegalaxy.org" \
GALAXY_API_KEY="" \
GALAXY_MCP_TRANSPORT="stdio" \
GALAXY_MCP_HOST="0.0.0.0" \
GALAXY_MCP_PORT="8000"

COPY --from=uv /root/.local /root/.local
COPY --from=uv --chown=app:app /app/.venv /app/.venv
Expand All @@ -63,12 +66,12 @@ USER app
# Expose service port
EXPOSE 8000

# Add healthcheck
# Add healthcheck that verifies the HTTP listener is accepting connections
HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \
CMD mcp-server-galaxy --health-check || exit 1
CMD python -c "import os, socket, sys; addr=('127.0.0.1', int(os.environ.get('GALAXY_MCP_PORT', '8000'))); sock=socket.socket(); sock.settimeout(2); sock.connect(addr); sock.close()"

# Use tini as init to handle signals properly
ENTRYPOINT ["/usr/bin/tini", "--"]

# Update command to use environment variables instead of DB path
CMD ["mcp-server-galaxy", "--galaxy-url", "${GALAXY_INSTANCE}", "--api-key", "${GALAXY_API_KEY}"]
# Start the MCP server (transport/host/port taken from environment variables)
CMD ["galaxy-mcp"]
64 changes: 38 additions & 26 deletions mcp-server-galaxy-py/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ This is the Python implementation of the Galaxy MCP server, providing a Model Co
## Features

- Complete Galaxy API integration through BioBlend
- Optional OAuth login flow for HTTP deployments
- Interactive Workflow Composer (IWC) integration
- FastMCP2 server with remote deployment support
- Type-annotated Python codebase
Expand Down Expand Up @@ -39,54 +40,65 @@ uv sync --all-extras

## Configuration

The server requires Galaxy credentials to connect to an instance. You can provide these via environment variables:
At minimum the server needs to know which Galaxy instance to target:

```bash
export GALAXY_URL=<galaxy_url>
export GALAXY_API_KEY=<galaxy_api_key>
export GALAXY_URL="https://usegalaxy.org.au/"
```

Alternatively, create a `.env` file in the project root with these variables.
How you authenticate depends on your transport:

## Usage
- **Stdio / long-lived sessions** – provide an API key:

```bash
export GALAXY_API_KEY="your-api-key"
```

- **HTTP / OAuth** – configure the public URL that users reach and a signing secret for session
tokens. The server mints short-lived Galaxy API keys on behalf of each user.

### Quick Start with uvx
```bash
export GALAXY_MCP_PUBLIC_URL="https://mcp.example.com"
export GALAXY_MCP_SESSION_SECRET="$(openssl rand -hex 32)"
```

The fastest way to run the Galaxy MCP server is using `uvx`:
Optionally set `GALAXY_MCP_CLIENT_REGISTRY` to control where OAuth client registrations are stored.

You can also steer the transport with `GALAXY_MCP_TRANSPORT` (`stdio`, `streamable-http`, or `sse`).
All variables can be placed in a `.env` file for convenience.

## Usage

### Quick Start with `uvx`

```bash
# Run the server directly without installation
# Local stdio transport (no network listener)
uvx galaxy-mcp

# Run with FastMCP2 dev tools
uvx --from galaxy-mcp fastmcp dev src/galaxy_mcp/server.py

# Run as remote server
uvx --from galaxy-mcp fastmcp run src/galaxy_mcp/server.py --transport sse --port 8000
# Remote/browser clients with HTTP + OAuth
export GALAXY_URL="https://usegalaxy.org.au/"
export GALAXY_MCP_PUBLIC_URL="https://mcp.example.com"
export GALAXY_MCP_SESSION_SECRET="$(openssl rand -hex 32)"
uvx galaxy-mcp --transport streamable-http --host 0.0.0.0 --port 8000
```

### As a standalone MCP server
### Installed CLI

```bash
# Install and run the MCP server
pip install galaxy-mcp
galaxy-mcp

# The server will wait for MCP protocol messages on stdin
galaxy-mcp --transport streamable-http --host 0.0.0.0 --port 8000
```

### With MCP clients
If `--transport` is omitted the server defaults to stdio and reads/writes MCP messages via stdin/stdout.

```bash
# Use with FastMCP2 CLI tools
fastmcp dev src/galaxy_mcp/server.py
fastmcp run src/galaxy_mcp/server.py
### Working from a checkout

# Use with other MCP-compatible clients
your-mcp-client galaxy-mcp
```bash
uv sync
uv run galaxy-mcp --transport streamable-http --host 0.0.0.0 --port 8000
```

See [USAGE_EXAMPLES.md](USAGE_EXAMPLES.md) for detailed usage patterns and common examples.
See [USAGE_EXAMPLES.md](USAGE_EXAMPLES.md) for detailed tool usage patterns.

## Available MCP Tools

Expand Down
14 changes: 11 additions & 3 deletions mcp-server-galaxy-py/USAGE_EXAMPLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,25 @@ This document provides common usage patterns and examples for the Galaxy MCP ser

### 1. Connect to Galaxy

First, you need to establish a connection to your Galaxy instance:
For stdio deployments you can authenticate with a long-lived API key:

```python
# Option 1: Use environment variables (recommended)
# Set GALAXY_URL and GALAXY_API_KEY in your environment or .env file
connect()

# Option 2: Provide credentials directly
# Or provide credentials directly
connect(url="https://your-galaxy-instance.org", api_key="your-api-key")
```

For HTTP deployments that use OAuth the active session is resolved automatically. Calling
`connect()` without arguments simply confirms the session and returns user details:

```python
session_info = connect()
assert session_info["auth"] == "oauth"
print(session_info["user"]["username"])
```

#### Get server information

Once connected, you can retrieve comprehensive information about the Galaxy server:
Expand Down
2 changes: 2 additions & 0 deletions mcp-server-galaxy-py/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ classifiers = [
]
requires-python = ">=3.10"
dependencies = [
"anyio>=4.0.0",
"bioblend>=1.5.0",
"cryptography>=41.0.0",
"fastmcp>=2.3.0",
"requests>=2.32.3",
"python-dotenv>=1.0.0",
Expand Down
37 changes: 33 additions & 4 deletions mcp-server-galaxy-py/src/galaxy_mcp/__main__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,41 @@
"""Command-line entry point for Galaxy MCP server."""

import argparse
import os

from . import server


def run():
"""Run the MCP server."""
# Use FastMCP's simplified run method
server.mcp.run()
def run() -> None:
"""Run the MCP server using stdio or HTTP transport."""
parser = argparse.ArgumentParser(description="Run the Galaxy MCP server.")
parser.add_argument(
"--transport",
choices=["stdio", "streamable-http", "sse"],
help="Transport to use (defaults to environment or stdio).",
)
parser.add_argument("--host", help="HTTP host to bind when using HTTP transports.")
parser.add_argument(
"--port",
type=int,
help="HTTP port to bind when using HTTP transports.",
)
parser.add_argument(
"--path",
help="Optional HTTP path when using streamable transports.",
)
args = parser.parse_args()

selected = (args.transport or os.environ.get("GALAXY_MCP_TRANSPORT") or "stdio").lower()
if selected in {"streamable-http", "sse"}:
server.run_http_server(
host=args.host,
port=args.port,
transport=selected,
path=args.path,
)
else:
server.mcp.run()


if __name__ == "__main__":
Expand Down
Loading