Skip to main content
Glama
rajeshkumar-okta

ProGear MCP Servers

ProGear MCP-Server

Ein MCP-Gateway für die ProGear-Basketballausrüstungs-Demo, das vier Domänen hostet – Inventory, Customer, Sales und Pricing –, die jeweils das echte MCP-Protokoll (Streamable-HTTP-Transport) sprechen und durch Ihre eigene Okta-Organisation abgesichert sind (eigener Custom Authorization Server + Scope-Set pro Domäne).

Dies ist ein bewusst kleineres Geschwisterprojekt von ProGearSalesAI: kein Auth0 FGA, kein LangGraph-Orchestrator, kein Frontend. Das Gateway selbst validiert lediglich das übergebene Bearer-Token – es ist egal, wie der Aufrufer es erhalten hat. packages/local-tester (nur lokal, nicht bereitgestellt) zeigt eine Möglichkeit, wie ein Aufrufer vorgehen könnte: menschlicher PKCE-Login + ein Agent, der den ID-JAG-Austausch durchführt, um dieses Token zu prägen, und damit den Cross-App-Access-Flow der ursprünglichen App nachbildet.

Bereitstellungsform

Ein Prozess, ein Render-Dienst, ein Build-/Startbefehl. packages/gateway mountet alle 4 Domänen unter verschiedenen Pfaden hinter einer einzigen Express-App:

Mount

Scopes

Tools

/inventory/mcp

inventory:read, inventory:write, inventory:alert

list_products, search_inventory, check_stock, get_low_stock_alerts, get_inventory_summary, update_inventory_quantity

/customer/mcp

customer:read, customer:lookup, customer:history

get_customer, search_customers, get_customers_by_tier, get_top_customers, get_customer_summary

/sales/mcp

sales:read, sales:quote, sales:order

list_orders, get_order, get_pipeline, create_quote, create_order, cancel_order

/pricing/mcp

pricing:read, pricing:margin, pricing:discount

get_price, get_category_pricing, calculate_bulk_price, get_discount_structure

Jeder Mount validiert gegen seinen eigenen Okta Custom Authorization Server (unterschiedliche Issuer/Audience pro Domäne), obwohl alle im selben Prozess laufen – ein Token, das für den Inventory-Auth-Server ausgestellt wurde, kann nicht gegen /customer/mcp verwendet werden, und innerhalb eines Mounts prüft jeder Tool-Aufruf seinen erforderlichen Scope gegen die im Token des Aufrufers gewährten Scopes (ein Token ohne inventory:write kann check_stock aufrufen, aber nicht update_inventory_quantity).

packages/mcp-inventory, mcp-customer, mcp-sales, mcp-pricing funktionieren weiterhin auch als eigenständige Server (eigene server.ts + /mcp + /health, Umgebungsvariablen für eine einzelne Domäne), falls Sie sie jemals wieder in separate Bereitstellungen aufteilen möchten – das Gateway importiert lediglich die Tool-Registrierungslogik jedes Servers (./tools-Export) und mountet sie unter seiner eigenen Auth-Konfiguration, anstatt selbst .listen() aufzurufen.

Related MCP server: Meraki MCP Server

Daten

Befüllt aus einem portierten Snapshot des ProGearSalesAI-Demo-Datensatzes: 90 Inventory-SKUs, 90 Pricing-Einträge, 34 Kunden, Tabellen für Stufen-/Mengenrabatte (packages/shared/src/data/initial_data.json). Verkaufsaufträge/-angebote sind nur im Speicher. Der gesamte Zustand wird beim Neustart des Prozesses zurückgesetzt – dies ist ein Tools-Server, kein System of Record.

Projektstruktur

packages/
  shared/            # ported data + store, JWKS auth + scope enforcement, HTTP/MCP transport helper
  mcp-inventory/      mcp-customer/      mcp-sales/      mcp-pricing/   # tool definitions + standalone entrypoint each
  gateway/            # the actual deployment: mounts all 4 at /inventory, /customer, /sales, /pricing
  local-tester/       # local-only: PKCE login + agent ID-JAG exchange, calls the deployed gateway (see its own README)

Lokale Entwicklung

npm install
npm run build            # builds shared + all 4 domains + gateway, in dependency order

npm run dev:gateway       # tsx watch, all 4 mounts on one port (default 3000)

Ohne die relevanten Okta-Umgebungsvariablen für einen Mount gibt dieser Mount bei jeder /mcp-Anfrage 500 zurück, es sei denn, Sie setzen ALLOW_INSECURE=true, was die Token-Validierung überspringt und jedem Mount alle Scopes gewährt – nur für die lokale Entwicklung, niemals in einer bereitgestellten Umgebung setzen.

Okta-Einrichtung

Setzen Sie OKTA_DOMAIN einmal, plus OKTA_<DOMAIN>_AUTH_SERVER_ID + OKTA_<DOMAIN>_AUDIENCE pro Domäne – dies sind exakt dieselben Umgebungsvariablennamen, die bereits im ProGearSalesAI-Backend verwendet werden (OKTA_CUSTOMER_AUTH_SERVER_ID, OKTA_INVENTORY_AUDIENCE usw.), sodass vorhandene Werte unverändert übernommen werden können:

OKTA_DOMAIN=https://your-org.okta.com

OKTA_INVENTORY_AUTH_SERVER_ID=...   OKTA_INVENTORY_AUDIENCE=api://progear-inventory
OKTA_CUSTOMER_AUTH_SERVER_ID=...    OKTA_CUSTOMER_AUDIENCE=api://progear-customer
OKTA_SALES_AUTH_SERVER_ID=...       OKTA_SALES_AUDIENCE=api://progear-sales
OKTA_PRICING_AUTH_SERVER_ID=...     OKTA_PRICING_AUDIENCE=api://progear-pricing

Siehe .env.example für die vollständige Liste, einschließlich der Variablen aus einer ProGearSalesAI-ähnlichen .env, die hier nicht zutreffen (Anthropic-Schlüssel, CORS, der eigene private Schlüssel/die Client-ID des KI-Agenten – dieses Gateway validiert eingehende Tokens, es stellt selbst keine aus). Tokens werden anhand von Signatur + Issuer + Audience gegen den jeweiligen Okta-JWKS-Endpunkt jeder Domäne validiert (createRemoteJWKSet von jose) – auf dieser Seite ist kein gemeinsames Geheimnis erforderlich.

Bereitstellung auf Render

Ein einzelner Dienst, entweder über das Dashboard oder über das enthaltene Blueprint.

Manuell (New → Web Service):

Feld

Wert

Sprache

Node

Root-Verzeichnis

(leer – npm-Workspaces-Monorepo, Build läuft vom Repo-Root)

Build-Befehl

npm install && npm run build

Start-Befehl

node packages/gateway/dist/server.js

Health-Check-Pfad

/health

Blueprint: render.yaml im Repo-Root definiert denselben einzelnen progear-mcp-gateway-Dienst – New → Blueprint, auf dieses Repo zeigen, dann die 9 Okta-Umgebungsvariablen ausfüllen, nach denen gefragt wird (markiert mit sync: false).

Verbinden eines Agents

Jeder Mount stellt MCP über Streamable HTTP unter POST/GET/DELETE <mount>/mcp bereit (zustandslos – keine Sitzungspersistenz über Anfragen hinweg) sowie ein eigenes GET <mount>/health; zusätzlich gibt es ein Top-Level-GET /health, das alle Mounts auflistet.

Holen Sie sich ein Zugriffstoken von Okta für den relevanten Custom Authorization Server + Scopes (z. B. Client-Credentials-Grant für eine Dienst-/Agent-Identität), dann:

Claude Code CLI:

claude mcp add --transport http progear-inventory \
  https://<your-render-url>/inventory/mcp \
  --header "Authorization: Bearer <token>"

Wiederholen Sie dies pro Domäne (/customer/mcp, /sales/mcp, /pricing/mcp) mit einem Token, das auf die Audience dieser Domäne ausgerichtet ist.

Jeder andere MCP-Client / Agent-SDK: Richten Sie ihn auf die /mcp-URL des Mounts mit einem Authorization: Bearer <token>-Header bei jeder Anfrage.

OAuth-Discovery (ohne statisches Token)

Clients, die die MCP-Autorisierungsspezifikation implementieren, können Okta selbst finden, anstatt ein Token ausgehändigt zu bekommen. Jeder Mount veröffentlicht RFC 9728-Metadaten für geschützte Ressourcen im Root des Gateways, pfadbezogen auf den Endpunkt, den sie beschreiben:

GET /.well-known/oauth-protected-resource/inventory/mcp
GET /.well-known/oauth-protected-resource/customer/mcp
GET /.well-known/oauth-protected-resource/sales/mcp
GET /.well-known/oauth-protected-resource/pricing/mcp
{
  "resource": "https://<your-render-url>/inventory/mcp",
  "authorization_servers": ["https://your-org.okta.com/oauth2/<inventory-auth-server-id>"],
  "scopes_supported": ["inventory:read", "inventory:write", "inventory:alert"],
  "bearer_methods_supported": ["header"],
  "resource_name": "ProGear Inventory MCP"
}

Eine 401 von /mcp trägt jetzt ebenfalls den Verweis, sodass ein Client, der den Endpunkt kalt aufruft, erfährt, wo er sich authentifizieren kann:

WWW-Authenticate: Bearer resource_metadata="https://<your-render-url>/.well-known/oauth-protected-resource/inventory/mcp"

(Wenn ein Token präsentiert, aber die Validierung fehlschlug, enthält die Challenge zusätzlich error="invalid_token" und error_description.)

Die URLs in diesen Dokumenten werden aus der eingehenden Anfrage abgeleitet (X-Forwarded-Proto + Host, mit aktiviertem trust proxy – korrekt auf Render). Setzen Sie PUBLIC_BASE_URL=https://<your-render-url> nur, wenn etwas vor dem Gateway den Host-Header umschreibt.

Damit ein Client den Flow abschließen kann, registrieren Sie einen OIDC-Public-Client (Authorization Code + PKCE) in Ihrer Okta-Organisation, fügen Sie die Redirect-URI des Clients hinzu (Claude.ai verwendet https://claude.ai/api/mcp/auth_callback) und gewähren Sie die Scopes der Domäne in der Zugriffsrichtlinie dieses Custom Authorization Servers.

Noch fehlend für vollständig konfigurationsfreies Verbinden: dynamische Client-Registrierung. Der /oauth2/v1/clients-Endpunkt von Okta erfordert ein SSWS-API-Token, daher kann er nicht für anonyme Registrierung beworben werden – Clients, die auf DCR bestehen (VS Code / Copilot heute), benötigen einen Registrierungs-Shim davor. Clients, die eine vorregistrierte client_id akzeptieren, können die obige Discovery unverändert verwenden.

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    Not graded
    maintenance
    Aggregates multiple MCP servers behind a single, secure endpoint with unified tool/resource discovery, OAuth authentication, and resilient request routing. Enables users to manage and interact with multiple MCP backends through one centralized interface with load balancing and circuit breakers.
    2
    -
  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables MCP clients to query and manage basketball-equipment inventory, customers, sales orders, and pricing through four secured domain-specific endpoints using Okta authentication.
    -