Aller au contenu principal

MCP Gateway API

Complete API reference for the STOA Gateway MCP endpoints.

Configure your environment

The examples below use environment variables. Set them for your STOA instance:

export STOA_API_URL="https://api.gostoa.dev"       # Replace with your domain
export STOA_AUTH_URL="https://auth.gostoa.dev" # Keycloak OIDC provider
export STOA_GATEWAY_URL="https://mcp.gostoa.dev" # MCP Gateway endpoint

Self-hosted? Replace gostoa.dev with your domain.

Overview

The STOA Gateway implements the Model Context Protocol (MCP) specification version 2025-03-26, with backward compatibility for 2024-11-05.

Two access patterns:

PatternTransportUse Case
RESTHTTP POSTScripts, simple integrations, one-shot calls
MCP ProtocolSSE (JSON-RPC)AI agents, streaming, session-based

Authentication

All endpoints (except discovery) require a JWT Bearer token from Keycloak:

# Get token
TOKEN=$(curl -s -X POST "${STOA_AUTH_URL}/realms/stoa/protocol/openid-connect/token" \
-d "client_id=my-app" \
-d "client_secret=${CLIENT_SECRET}" \
-d "grant_type=client_credentials" | jq -r '.access_token')

# Use token
curl -H "Authorization: Bearer ${TOKEN}" "${STOA_GATEWAY_URL}/mcp/v1/tools"

Public endpoints (no auth required): initialize, ping, and OAuth discovery.


REST Endpoints

Simple HTTP endpoints for tool operations.

List Tools

POST /mcp/v1/tools
Authorization: Bearer <token>
Content-Type: application/json

Response:

{
"tools": [
{
"name": "get-weather",
"description": "Returns current weather for a given city",
"inputSchema": {
"type": "object",
"properties": {
"q": { "type": "string", "description": "City name" }
},
"required": ["q"]
},
"annotations": {
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": true
}
}
]
}

Invoke Tool

POST /mcp/v1/tools/invoke
Authorization: Bearer <token>
Content-Type: application/json

{
"name": "get-weather",
"arguments": { "q": "Paris" }
}

Response:

{
"content": [
{
"type": "text",
"text": "{\"location\":{\"name\":\"Paris\"},\"current\":{\"temp_c\":12.0}}"
}
],
"isError": false
}

MCP Protocol Endpoints (JSON-RPC over SSE)

Full MCP specification compliance via Server-Sent Events transport.

Initialize Session

Handshake with protocol version negotiation:

POST /mcp/sse
Authorization: Bearer <token>
Content-Type: application/json

{
"jsonrpc": "2.0",
"method": "initialize",
"params": {
"protocolVersion": "2025-03-26",
"capabilities": {
"tools": {}
},
"clientInfo": {
"name": "my-agent",
"version": "1.0.0"
}
},
"id": 1
}

Response:

{
"jsonrpc": "2.0",
"result": {
"protocolVersion": "2025-03-26",
"capabilities": {
"tools": { "listChanged": true },
"tokenOptimization": {
"supported": true,
"levels": ["none", "moderate", "aggressive"]
},
"elicitation": {}
},
"serverInfo": {
"name": "stoa-gateway",
"version": "0.1.0"
}
},
"id": 1
}

List Tools (JSON-RPC)

POST /mcp/sse
Content-Type: application/json

{
"jsonrpc": "2.0",
"method": "tools/list",
"id": 2
}

Call Tool (JSON-RPC)

POST /mcp/sse
Content-Type: application/json

{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "get-weather",
"arguments": { "q": "London" }
},
"id": 3
}

Batch Requests (MCP 2025-03-26)

Send multiple JSON-RPC requests in a single call:

POST /mcp/sse
Content-Type: application/json

[
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": { "name": "get-weather", "arguments": { "q": "Paris" } },
"id": 1
},
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": { "name": "get-weather", "arguments": { "q": "London" } },
"id": 2
}
]

All requests are processed concurrently. Response is an array of JSON-RPC results.

Ping

POST /mcp/sse
Content-Type: application/json

{ "jsonrpc": "2.0", "method": "ping", "id": 99 }

Close Session

DELETE /mcp/sse?sessionId=<session-id>

SSE Stream (Legacy)

GET /mcp/sse?sessionId=<session-id>

Opens a persistent SSE connection for streaming responses.

Supported JSON-RPC Methods

MethodAuth RequiredDescription
initializeNoHandshake + version negotiation
pingNoKeepalive
notifications/initializedNoClient acknowledgment (no response)
tools/listYesList available tools
tools/callYesExecute a tool
resources/listYesList resources (returns [])

Discovery Endpoints

MCP Server Discovery

GET /mcp

Returns server metadata: name, version, protocol version, available endpoints.

MCP Capabilities

GET /mcp/capabilities

Returns detailed capability information including supported features.

MCP Health

GET /mcp/health

Returns MCP-specific health: tool count, active sessions, status.


OAuth 2.1 Discovery

STOA implements OAuth 2.1 discovery per RFC 9728, enabling AI agents to authenticate automatically.

Protected Resource Metadata (RFC 9728)

GET /.well-known/oauth-protected-resource
{
"resource": "https://mcp.<YOUR_DOMAIN>",
"authorization_servers": ["https://auth.<YOUR_DOMAIN>/realms/stoa"],
"scopes_supported": ["stoa:read", "stoa:write", "stoa:execute"]
}

Authorization Server Metadata (RFC 8414)

GET /.well-known/oauth-authorization-server

OpenID Connect Discovery

GET /.well-known/openid-configuration

Token Proxy

POST /oauth/token

Transparent proxy to Keycloak token endpoint. Allows AI agents to obtain tokens without knowing the Keycloak URL.

Dynamic Client Registration

POST /oauth/register

Proxy to Keycloak DCR endpoint for automated client registration.


Execution Pipeline

Every tool invocation goes through this pipeline:

  1. JWT Auth — Bearer token validated against Keycloak JWKS
  2. Rate Limit — Per-consumer quota check (if configured)
  3. OPA Policy — Role-based access control with scopes
  4. Tool Execution — HTTP call to backend endpoint
  5. Kafka Metering — Event emitted for analytics (optional, feature-gated)

RBAC Scope Mapping

RoleScopes
cpi-adminadmin, read, write, execute, deploy, audit
tenant-adminread, write, execute
devopsread, write, deploy
viewerread

Token Optimization

Reduce LLM token usage with the X-Token-Optimization header:

curl -X POST "${STOA_GATEWAY_URL}/mcp/tools/call" \
-H "Authorization: Bearer ${TOKEN}" \
-H "X-Token-Optimization: aggressive" \
-H "Content-Type: application/json" \
-d '{"name": "get-weather", "arguments": {"q": "Paris"}}'
LevelEffect
noneFull response (default)
moderateRemove redundant fields
aggressiveMinimal response, optimized for LLM context

Session Management

SSE sessions have a configurable TTL (default: 30 minutes). Sessions are automatically cleaned up by a background task.

Session Stats (Admin)

GET /admin/sessions/stats
Authorization: Bearer <admin-token>
{
"active_sessions": 12,
"zombie_sessions": 0,
"total_created": 1543
}

Error Responses

StatusErrorCause
401UnauthorizedMissing/expired JWT token
403ForbiddenOPA policy denied the action
404Tool not foundTool name doesn't exist in registry
429Rate limitedConsumer quota exceeded
500Tool execution failedBackend endpoint returned error
502Backend unreachableBackend endpoint is down

JSON-RPC errors follow the MCP specification:

{
"jsonrpc": "2.0",
"error": {
"code": -32602,
"message": "Tool not found: unknown-tool"
},
"id": 3
}

Examples

Python Client

import os
import requests

STOA_AUTH_URL = os.environ['STOA_AUTH_URL']
STOA_GATEWAY_URL = os.environ['STOA_GATEWAY_URL']

# Authenticate
auth = requests.post(
f'{STOA_AUTH_URL}/realms/stoa/protocol/openid-connect/token',
data={
'client_id': 'my-app',
'client_secret': os.environ['STOA_CLIENT_SECRET'],
'grant_type': 'client_credentials'
}
)
token = auth.json()['access_token']

# Invoke tool
response = requests.post(
f'{STOA_GATEWAY_URL}/mcp/tools/call',
headers={'Authorization': f'Bearer {token}'},
json={'name': 'get-weather', 'arguments': {'q': 'Paris'}}
)

result = response.json()
print(result['content'][0]['text'])

JavaScript Client

const STOA_GATEWAY_URL = process.env.STOA_GATEWAY_URL;

const response = await fetch(`${STOA_GATEWAY_URL}/mcp/tools/call`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'get-weather',
arguments: { q: 'Paris' }
})
});

const result = await response.json();
console.log(result.content[0].text);