Running on nanoHUB

nanohub-mcp is designed to work with nanoHUB’s tool infrastructure. The start_mcp CLI command handles proxy configuration automatically.

CLI Usage

start_mcp --app start_mcp.py

With a conda environment:

start_mcp --app start_mcp.py --python-env AIIDA

All options:

usage: start_mcp [-h] --app APP [--host HOST] [--port PORT]
                 [--python-env PYTHON_ENV] [--debug]

Start an MCP server on nanoHUB or locally

optional arguments:
  -h, --help            show this help message and exit
  --app APP, -a APP     Path to Python file defining 'server = MCPServer(...)'
  --host HOST           Host to bind to (default: 0.0.0.0)
  --port PORT, -p PORT  Port to listen on (default: 8000)
  --python-env PYTHON_ENV
                        Conda environment name (e.g., AIIDA, ALIGNN)
  --debug               Enable debug mode with verbose logging

How It Works

When start_mcp runs on nanoHUB, it:

  1. Detects the nanoHUB environment via SESSION and SESSIONDIR environment variables

  2. Reads the session resources file to build the proxy URL

  3. Searches for an available wrwroxy reverse proxy using the use command

  4. Starts the MCP server and proxy

With wrwroxy available:

  • MCP server listens on port 8001

  • wrwroxy listens on port 8000 and forwards to 8001

  • wrwroxy strips the weber path prefix, so the MCP server sees clean paths

Without wrwroxy:

  • MCP server listens directly on port 8000

  • The path_prefix is set to the weber path so the server strips it internally

  • SSE transport works directly without a reverse proxy

Proxy URL Format

The nanoHUB weber proxy URL follows this pattern:

https://proxy.nanohub.org/weber/{session}/{cookie}/{port}/

Where:

  • {session} — nanoHUB session ID

  • {cookie} — file transfer cookie

  • {port} — file transfer port (mod 1000)

The proxy URL and SSE endpoint are printed at startup:

Proxy URL : https://proxy.nanohub.org/weber/2806628/QFknvaEtyl5V31wR/13/
MCP Server ready! Access it at: https://proxy.nanohub.org/weber/2806628/QFknvaEtyl5V31wR/13/
SSE endpoint: https://proxy.nanohub.org/weber/2806628/QFknvaEtyl5V31wR/13/sse

Testing Through the Proxy

Replace the placeholder values with your actual session details:

PROXY_URL="https://proxy.nanohub.org/weber/{session}/{cookie}/{port}"
COOKIE="weber-auth-nanohub-org={session}%3A{auth_token}"

Server info:

curl -b "$COOKIE" "$PROXY_URL/"

Initialize:

curl -b "$COOKIE" -X POST "$PROXY_URL/" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}'

List tools:

curl -b "$COOKIE" -X POST "$PROXY_URL/" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'

Call a tool:

curl -b "$COOKIE" -X POST "$PROXY_URL/" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"add","arguments":{"a":2,"b":3}}}'

Direct tool call:

curl -b "$COOKIE" -X POST "$PROXY_URL/tools/add" \
  -H "Content-Type: application/json" \
  -d '{"a": 7, "b": 3}'

Using the nanoHUB API

Use the nanoHUB API when calling tools from outside a nanoHUB session. All endpoints require a Bearer token.

Base URL:

https://nanohub.org

Recommended: Streamable HTTP (auto-session)

API_BASE="https://nanohub.org"
TOOL="mcpdemo"
TOKEN="your_token"

# Get connection info (creates or reuses a session)
curl -H "Authorization: Bearer $TOKEN" \
  "$API_BASE/api/mcp/$TOOL/mcp"

# Initialize
curl -H "Authorization: Bearer $TOKEN" -X POST "$API_BASE/api/mcp/$TOOL/mcp" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"example-client","version":"0.1.0"}}}'

# List tools
curl -H "Authorization: Bearer $TOKEN" -X POST "$API_BASE/api/mcp/$TOOL/mcp" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'

# Call a tool
curl -H "Authorization: Bearer $TOKEN" -X POST "$API_BASE/api/mcp/$TOOL/mcp" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"add","arguments":{"a":2,"b":3}}}'

Direct JSON-RPC (session-aware)

Use these endpoints if you want to pin or reuse a session id:

POST /api/mcp/{tool}           # creates a session if not provided
POST /api/mcp/{tool}/{session} # uses an existing session

Direct tool calls (REST/OpenAPI style)

# Call a tool directly
curl -H "Authorization: Bearer $TOKEN" -X POST "$API_BASE/api/mcp/$TOOL/tools/add" \
  -H "Content-Type: application/json" \
  -d '{"a": 7, "b": 3}'

# Fetch OpenAPI schema for the tool
curl -H "Authorization: Bearer $TOKEN" \
  "$API_BASE/api/mcp/$TOOL/openapi.json"

SSE connection info

If you need SSE transport, the API will return the proxy endpoint and cookie you must use:

curl -H "Authorization: Bearer $TOKEN" \
  "$API_BASE/api/mcp/$TOOL/sse"

The response includes sse_endpoint, post_endpoint, and cookie_header. Connect to sse_endpoint with the cookie header and POST JSON-RPC to post_endpoint.

Revision selection

Most endpoints accept an optional revision query parameter (default, dev, test, or a specific version). Example:

curl -H "Authorization: Bearer $TOKEN" \
  "$API_BASE/api/mcp/$TOOL/mcp?revision=dev"

Reference client

See App/nanohub_mcp_client.py for a complete stdio-to-nanoHUB MCP bridge. It uses:

NANOHUB_TOKEN=...   # API token (required)
NANOHUB_API=...     # Base URL (default: https://nanohub.org)
NANOHUB_TOOLS=...   # Comma-separated tool list (default: mcpdemo)

Local Development

When running outside of nanoHUB (no SESSION environment variable), start_mcp runs the server directly without any proxy:

start_mcp --app start_mcp.py --port 9000

This is equivalent to calling server.run(port=9000) directly in your script.