Skip to main content
Glama

authenticate

Authenticate with the Relay Control Plane to enable access to shared Obsidian vaults, real-time sync, and collaborative note management.

Instructions

Authenticate with the Relay Control Plane.

Uses RELAY_EMAIL and RELAY_PASSWORD env vars. Returns a status message. The token is managed internally — subsequent tool calls use it automatically.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • The main authenticate tool handler decorated with @mcp.tool(). Calls _ensure_token() to get or refresh the JWT token and returns a success message with token length.
    @mcp.tool()
    def authenticate() -> str:
        """Authenticate with the Relay Control Plane.
    
        Uses RELAY_EMAIL and RELAY_PASSWORD env vars.
        Returns a status message. The token is managed internally —
        subsequent tool calls use it automatically.
        """
        token = _ensure_token()
        return f"Authenticated successfully. Token length: {len(token)}"
  • Core authentication logic that manages JWT tokens. Handles token refresh if available, otherwise performs full login using RELAY_EMAIL and RELAY_PASSWORD environment variables. Stores token, refresh_token, and expiry globally.
    def _ensure_token() -> str:
        """Return a valid JWT token, refreshing if needed."""
        global _token, _token_expires, _refresh_token
    
        if _token and time.time() < _token_expires - 60:
            return _token
    
        # Try refresh first
        if _refresh_token:
            try:
                with _get_client() as client:
                    r = client.post(
                        f"{_get_base_url()}/v1/auth/refresh",
                        json={"refresh_token": _refresh_token},
                    )
                    if r.status_code == 200:
                        data = r.json()
                        _token = data["access_token"]
                        _refresh_token = data.get("refresh_token", _refresh_token)
                        _token_expires = time.time() + data.get("expires_in", 3600)
                        return _token
            except Exception:
                pass
    
        # Full login
        email = os.environ.get("RELAY_EMAIL", "")
        password = os.environ.get("RELAY_PASSWORD", "")
        if not email or not password:
            raise ValueError("RELAY_EMAIL and RELAY_PASSWORD must be set")
    
        with _get_client() as client:
            r = client.post(
                f"{_get_base_url()}/v1/auth/login",
                json={"email": email, "password": password},
            )
            r.raise_for_status()
            data = r.json()
    
        _token = data["access_token"]
        _refresh_token = data.get("refresh_token")
        _token_expires = time.time() + data.get("expires_in", 3600)
        return _token
  • relay_mcp.py:108-108 (registration)
    The @mcp.tool() decorator that registers the authenticate function as an available MCP tool.
    @mcp.tool()
  • Helper function that retrieves the Relay Control Plane base URL from the RELAY_CP_URL environment variable.
    def _get_base_url() -> str:
        url = os.environ.get("RELAY_CP_URL", "")
        if not url:
            raise ValueError("RELAY_CP_URL environment variable not set")
        return url.rstrip("/")
  • Helper function that creates an httpx client with keep-alive disabled to prevent hanging on stale connections from the Caddy server.
    def _get_client() -> httpx.Client:
        # Disable keep-alive: Caddy sends GOAWAY on idle connections,
        # httpx tries to reuse the stale socket and hangs.
        limits = httpx.Limits(max_keepalive_connections=0)
        return httpx.Client(timeout=30.0, limits=limits)

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/entire-vc/evc-team-relay-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server