Skip to main content

Availability

Custom Endpoint plugins allow you to register and serve arbitrary HTTP endpoints on the Edge Gateway under the /plugins/{slug}/ URL namespace. This gives plugins full control over request handling, enabling use cases like OAuth identity providers, MCP proxy servers, webhook receivers, and custom protocol-specific APIs.

Overview

Custom Endpoints provide plugins with the ability to:
  • Serve custom HTTP APIs alongside the standard LLM/Tool/Datasource proxy endpoints
  • Handle arbitrary URL paths with pre-split path segments for easy routing
  • Stream responses via Server-Sent Events (SSE) for protocols like MCP Streamable HTTP
  • Authenticate requests using the gateway’s existing token system, with full App context (including metadata)
  • Support any HTTP method (GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD)

Working Example

See examples/plugins/gateway/custom-echo-endpoint/ for a complete, working example that combines CustomEndpointHandler + UIProvider + ConfigProvider. It echoes request metadata and serves content configurable via the Studio admin UI.

URL Pattern

All custom endpoints are mounted under:
Where {slug} is declared in the plugin’s configuration (the slug key in the config map), and {path...} is the sub-path handled by the plugin.

How It Works

Implementing Custom Endpoints

Step 1: Implement CustomEndpointHandler Interface

Step 2: Register Your Endpoints

Declare which paths and HTTP methods your plugin handles:
Registration Options:

Step 3: Handle Requests

Unary (Non-Streaming) Endpoints

For standard request/response:

Streaming (SSE) Endpoints

For Server-Sent Events or MCP Streamable HTTP:
Chunk Protocol: HEADERS → BODY* → DONE

Step 4: Configure the Plugin Slug and Register

The plugin slug (used in the URL path) must be set explicitly in the plugin’s config map. The slug determines the URL namespace: /plugins/{slug}/....

Manifest

Declare custom_endpoint in the manifest’s capabilities:
If the plugin also provides a Studio UI, include "studio_ui" in hooks:

Registration via AI Studio

Register the plugin in AI Studio (Admin > Plugins) with: The slug in the config determines the URL path on the gateway. For example, {"slug": "my-mcp"} makes endpoints available at http://gateway:8081/plugins/my-mcp/.... Important: The slug must be set in the config map. Without it, endpoints will not be registered and you’ll see a warning in the gateway logs:

Building and Deploying

Gateway Loading

Custom endpoint plugins are loaded automatically at gateway startup via the pre-warming system. The gateway:
  1. Queries all active plugins with custom_endpoint hook type
  2. Loads each plugin (starts the binary, initializes via gRPC)
  3. Calls GetEndpointRegistrations() to discover endpoints
  4. Registers routes using the slug from config
After a control plane config sync, routes are refreshed automatically.

EndpointRequest Fields

When a request arrives, the plugin receives a rich EndpointRequest:

Path Segments

The path_segments field pre-splits the relative path for easy pattern matching:

Authentication and App Context

When require_auth: true, the gateway:
From v2.2.1, a custom-endpoint plugin has its own ordered list of auth plugins. When the list is not empty, only these plugins authenticate requests to its endpoints on the Edge Gateway, and App keys are refused. The gateway asks the plugins in order, so put the plugin that authenticates the most requests first. Set the list in the Authentication plugins section of the plugin detail page.
  1. Extracts the token from Authorization: Bearer <token> header or ?token= query param
  2. Validates the token via the gateway’s auth provider
  3. Fetches the full App object linked to the token
  4. Populates EndpointRequest with authenticated=true, app, and scopes
The App object includes:

Access Control via App Metadata

The recommended pattern for per-app access control is to store ACL rules in App metadata, which admins configure per-app:

Route Matching

The gateway matches routes in this order:
  1. Exact match — GET:/plugins/my-oauth/.well-known/openid-configuration
  2. Wildcard catch-all — GET:/plugins/my-oauth/*
Recommended: Register a single /* catch-all and handle routing internally using path_segments. This is the simplest and most flexible approach. A plugin can also register multiple specific paths:

MCP Streamable HTTP Support

Custom endpoints are designed to support MCP (Model Context Protocol) Streamable HTTP out of the box.

MCP Protocol Summary

MCP Streamable HTTP uses a single endpoint with:
  • POST: Client sends JSON-RPC messages; server responds with application/json or text/event-stream
  • GET: Client opens an inbound SSE stream for server-initiated messages
  • DELETE: Client terminates the session
  • Session tracking via Mcp-Session-Id header

MCP Proxy Plugin Pattern

The gateway is a transparent pipe — all MCP protocol logic (JSON-RPC, sessions, resumability) lives in the plugin.

Complete Example: Webhook Receiver

Lifecycle Management

Custom endpoint routes are managed automatically across all plugin lifecycle events:

Error Handling

Configuration

Streaming Timeout

The streaming endpoint timeout is configurable via environment variable: For long-running streaming connections (e.g., MCP proxy, real-time data feeds), increase the timeout:
The upstream server should send periodic data to keep the connection alive within the timeout window.