#!/usr/bin/env sh set -eu SCRIPT_DIR="$(CDPATH= cd "$(dirname "$0")" && pwd -P)" ENV_FILE="${ALPACA_MCP_ENV_FILE:-${SCRIPT_DIR}/.env}" env_has_credentials() { python3 - "${ENV_FILE}" <<'PY' import os import sys env_file = sys.argv[1] values = dict(os.environ) if os.path.exists(env_file): with open(env_file, "r", encoding="utf-8-sig") as handle: for raw_line in handle: line = raw_line.strip() if not line or line.startswith("#"): continue if line.startswith("export "): line = line[7:].strip() if "=" not in line: continue key, value = line.split("=", 1) values[key.strip()] = value.strip().strip("'\"") api_key = values.get("ALPACA_API_KEY", "") secret_key = values.get("ALPACA_SECRET_KEY", "") placeholders = {"your_alpaca_api_key", "your_alpaca_secret_key"} has_real_values = api_key and secret_key and api_key not in placeholders and secret_key not in placeholders sys.exit(0 if has_real_values else 1) PY } run_account_check() { python3 - "${ENV_FILE}" <<'PY' import json import os import sys import urllib.error import urllib.request env_file = sys.argv[1] def load_env(path): values = {} if not os.path.exists(path): return values with open(path, "r", encoding="utf-8-sig") as handle: for raw_line in handle: line = raw_line.strip() if not line or line.startswith("#"): continue if line.startswith("export "): line = line[7:].strip() if "=" not in line: continue key, value = line.split("=", 1) key = key.strip() value = value.strip().strip("'\"") values[key] = value return values values = {**os.environ, **load_env(env_file)} api_key = values.get("ALPACA_API_KEY", "") secret_key = values.get("ALPACA_SECRET_KEY", "") paper = values.get("ALPACA_PAPER_TRADE", "true").strip().lower() != "false" placeholders = {"your_alpaca_api_key", "your_alpaca_secret_key"} if not api_key or not secret_key or api_key in placeholders or secret_key in placeholders: print("error: ALPACA_API_KEY and ALPACA_SECRET_KEY must both be set") sys.exit(2) base_url = "https://paper-api.alpaca.markets" if paper else "https://api.alpaca.markets" request = urllib.request.Request( f"{base_url}/v2/account", headers={ "APCA-API-KEY-ID": api_key, "APCA-API-SECRET-KEY": secret_key, "Accept": "application/json", }, ) try: with urllib.request.urlopen(request, timeout=15) as response: data = json.loads(response.read().decode("utf-8")) except urllib.error.HTTPError as error: body = error.read().decode("utf-8", "replace").strip() print(f"error: Alpaca account check failed with HTTP {error.code} against {base_url}") if error.code in (401, 403): print("hint: verify the key and secret are from the same Alpaca environment and match ALPACA_PAPER_TRADE") if body: print(f"details: {body[:300]}") sys.exit(1) except Exception as error: print(f"error: Alpaca account check could not reach {base_url}: {error}") sys.exit(1) status = data.get("status", "unknown") currency = data.get("currency", "unknown") trading_blocked = data.get("trading_blocked", "unknown") print(f"ok: Alpaca account authenticated against {base_url}") print(f"ok: account status={status} currency={currency} trading_blocked={trading_blocked}") PY } if [ "${1:-}" = "--doctor" ]; then if [ -f "${ENV_FILE}" ]; then echo "ok: env file found (${ENV_FILE})" else echo "warn: env file not found (${ENV_FILE}); copy scripts/mcp/.env.example to scripts/mcp/.env" fi if env_has_credentials; then echo "ok: Alpaca credential variables are set" else echo "warn: ALPACA_API_KEY and/or ALPACA_SECRET_KEY are not set" fi echo "hint: run sh scripts/mcp/alpaca-mcp-server.sh --check-account to validate the key pair with Alpaca" if command -v uvx >/dev/null 2>&1; then echo "ok: uvx available ($(command -v uvx))" exit 0 fi if command -v uv >/dev/null 2>&1; then echo "ok: uv available ($(command -v uv))" exit 0 fi if command -v pipx >/dev/null 2>&1; then echo "ok: pipx fallback available ($(command -v pipx))" exit 0 fi echo "error: install uv or pipx before starting the Alpaca MCP server" >&2 exit 127 fi if [ "${1:-}" = "--check-account" ]; then run_account_check exit $? fi if command -v uvx >/dev/null 2>&1; then if [ -f "${ENV_FILE}" ]; then exec uvx alpaca-mcp-server --env-file "${ENV_FILE}" "$@" fi exec uvx alpaca-mcp-server "$@" fi if command -v uv >/dev/null 2>&1; then if [ -f "${ENV_FILE}" ]; then exec uv tool run alpaca-mcp-server --env-file "${ENV_FILE}" "$@" fi exec uv tool run alpaca-mcp-server "$@" fi if command -v pipx >/dev/null 2>&1; then if [ -f "${ENV_FILE}" ]; then exec pipx run alpaca-mcp-server --env-file "${ENV_FILE}" "$@" fi exec pipx run alpaca-mcp-server "$@" fi echo "error: install uv or pipx before starting the Alpaca MCP server" >&2 exit 127