Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions docs/MCP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# MCP Server

Plexus exposes two MCP (Model Context Protocol) server endpoints:

1. **MCP Gateway** at `/mcp/:name` — proxies requests to configured upstream MCP servers.
2. **Plexus Management MCP** at `/mcp/plexus` — an admin-only MCP server for managing Plexus itself.

Both endpoints have independent controls. The Plexus Management MCP at `/mcp/plexus` can be disabled via the toggle on the MCP Servers page. When disabled, `/mcp/plexus` responds with HTTP 418; gateway servers (`/mcp/:name`) are unaffected.

## Authentication

### MCP Gateway (`/mcp/:name`)

The MCP Gateway requires an inference API key passed as a Bearer token or in the `x-api-key` header. Requests are authenticated against the same key store used by the Plexus inference API.

- Missing key → 401
- Invalid key → 401
- Valid key with route access → proxied to the upstream MCP server

### Plexus Management MCP (`/mcp/plexus`)

The management MCP requires the admin key in the `x-admin-key` header. Inference API keys and Bearer tokens are **not** accepted.

- Missing `x-admin-key` → 401
- Incorrect `x-admin-key` → 401
- Inference API key or Bearer token alone → 401
- Valid admin key → request processed

## MCP Gateway Commands

The gateway proxies all MCP protocol messages (JSON-RPC over HTTP POST, GET, DELETE) to the configured upstream server. It does not interpret or modify tool calls. Logs are recorded in the MCP usage storage and viewable in the MCP Logs page.

### Configuring Upstream Servers

Upstream MCP servers are configured on the MCP page. Each server requires:

- **Name** — slug-safe identifier used in the URL path
- **Upstream URL** — the upstream MCP server endpoint
- **Headers** — optional headers forwarded to the upstream server
- **Timeout** — request timeout in milliseconds

Server names must match `[a-z0-9][a-z0-9-_]{1,62}`. The name `plexus` is reserved for the management MCP server and cannot be used as a gateway server name.

## Plexus Management MCP Tools

The management MCP server at `/mcp/plexus` provides domain-oriented tools for inspecting and managing Plexus configuration. Each tool uses an `operation` argument to select the action, keeping the tool surface compact.

### Input Shape

```json
{
"operation": "list | get | ...",
"id": "optional-resource-id",
"category": "optional-settings-category",
"query": {},
"body": {},
"destructive": "acknowledged"
}
```

### Destructive Operations

Destructive or high-impact operations (delete, restore, restart, rotate, etc.) require `"destructive": "acknowledged"`. If omitted, the tool call is rejected with a `confirmation_required` error.

### Secret Redaction

All normal responses redact sensitive fields (API keys, secrets, tokens, cookies, sessions, passwords). Secrets are replaced with `[REDACTED]`.

### Available Tools

| Tool | Operations | Description |
|------|-----------|-------------|
| `plexus_config` | `get`, `export`, `status` | Inspect full Plexus configuration or summary status. |
| `plexus_provider` | `list`, `get`, `put`, `create`, `update`, `delete`, `fetch_models` | Inspect and manage providers and routing configuration. |
| `plexus_model_alias` | `list`, `get`, `put`, `create`, `update`, `delete`, `delete_all` | Inspect and manage model aliases, targets, and target groups. |
| `plexus_key` | `list`, `get`, `put`, `create`, `update`, `delete` | Inspect and manage inference keys (secrets redacted). |
| `plexus_quota` | `list`, `get`, `put`, `create`, `update`, `delete` | Inspect and manage user quota definitions. |
| `plexus_quota_checker` | `types`, `list`, `get` | Inspect upstream quota checker configuration. |
| `plexus_usage` | `list`, `summary`, `delete`, `delete_all` | Review request logs and usage summaries; delete individual or bulk usage logs. |
| `plexus_debug` | `state`, `update`, `logs`, `get_log`, `delete_log`, `delete_all_logs` | Inspect and manage debug tracing and stored debug logs. |
| `plexus_mcp_gateway` | `servers_list`, `list`, `get`, `put`, `create`, `update`, `delete` | Inspect and manage upstream MCP gateway server configuration. |
| `plexus_settings` | `get` | Get settings by category (failover, cooldown, timeout, stall, exploration, etc.) |
| `plexus_system_logs` | `recent`, `level`, `set_level`, `reset_level` | Inspect recent in-memory Plexus system logs from the bounded ring buffer and control the runtime logging level. |
| `plexus_operations` | `backup`, `restore`, `restart`, `list_cooldowns`, `clear_cooldowns`, `reset_logs` | High-impact operational actions, backups/restores, cooldown inspection, and log resets. |

### Prompt Resource

The management MCP server registers a `plexus_management_guide` prompt that MCP clients can request. It describes Plexus, the tool design, destructive acknowledgement, secret redaction, and recommended workflows.

## Enabling / Disabling

The Plexus Management MCP can be toggled from the **MCP Servers** page. The "Plexus Management MCP" row at the top of the server list provides the toggle. When disabled, only `/mcp/plexus` responds with:

```
HTTP 418 I'm a teapot
{
"error": {
"message": "Plexus Management MCP is disabled. Enable it on the MCP Servers page.",
"type": "mcp_disabled"
}
}
```

The default state is **enabled**.
2 changes: 2 additions & 0 deletions docs/openapi/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,8 @@ paths:
$ref: paths/v0_management_events.yaml
/v0/system/logs/stream:
$ref: paths/v0_system_logs_stream.yaml
/v0/system/logs/recent:
$ref: paths/v0_system_logs_recent.yaml
/mcp/{name}:
$ref: paths/mcp_{name}.yaml
/.well-known/oauth-authorization-server:
Expand Down
25 changes: 25 additions & 0 deletions docs/openapi/paths/v0_management_aliases_{slug}.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,31 @@ parameters:
schema:
type: string
description: Alias slug (e.g. "gpt-4", "claude-3-opus").
get:
tags:
- Management — Config
summary: Get a model alias by slug (admin only)
description: |
Returns a single model alias configuration by slug.

**Admin only** — limited principals receive 403.
security:
- AdminKey: []
responses:
'200':
description: Alias configuration.
content:
application/json:
schema:
allOf:
- type: object
properties:
slug:
type: string
- $ref: ../components/schemas/AliasConfig.yaml
'404':
description: Alias not found.
operationId: getV0ManagementAliasesByslug
put:
tags:
- Management — Config
Expand Down
7 changes: 4 additions & 3 deletions docs/openapi/paths/v0_management_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ get:
Returns the full Plexus configuration object as JSON. This is the
same structure used by the database.

## JSON vs YAML
## JSON endpoints

- **This endpoint** — Returns the in-memory configuration as JSON
- **`GET /v0/management/config/export`** — Returns the raw YAML as stored on disk
- **`GET /v0/management/config/export`** — Returns an export-friendly JSON object

Both contain the same data; the JSON form is easier for programmatic access.
Both contain nearly the same data; the export form omits derived runtime-only
fields and is suitable for backups or round-tripping through restore/import flows.

## What's included

Expand Down
23 changes: 10 additions & 13 deletions docs/openapi/paths/v0_management_config_export.yaml
Original file line number Diff line number Diff line change
@@ -1,32 +1,29 @@
get:
tags:
- Management — Config
summary: Export the configuration as YAML (admin only)
summary: Export the configuration as JSON (admin only)
description: |
Exports the full configuration as YAML — the same format used in
the database.
Exports the persisted configuration graph as JSON.

## JSON vs YAML
## JSON endpoints

- **`GET /v0/management/config`** — Returns configuration as JSON
- **This endpoint** — Returns configuration as YAML (same as on disk)
- **This endpoint** — Returns an export-friendly JSON object

Both contain the same data; the YAML form is suitable for saving
back to the config file.
This endpoint is useful for programmatic export/backup flows. It does not
return YAML and Plexus no longer relies on an on-disk YAML source of truth.

**Admin only** — limited principals receive 403.
security:
- AdminKey: []
responses:
'200':
description: YAML export.
description: JSON export.
content:
application/x-yaml:
application/json:
schema:
type: string
text/yaml:
schema:
type: string
type: object
additionalProperties: true
'401':
description: Authentication required or invalid credentials.
operationId: getV0ManagementConfigExport
68 changes: 68 additions & 0 deletions docs/openapi/paths/v0_management_keys_{name}.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,35 @@ parameters:
schema:
type: string
description: API key name (e.g. "sk-prod", "sk-dev").
get:
tags:
- Management — Config
summary: Get an API key by name (admin only)
description: |
Returns a single API key record by name.

The stored secret is returned decrypted by the HTTP management API.
Clients that need redaction should apply it themselves or use the MCP
management surface instead.

**Admin only** — limited principals receive 403.
security:
- AdminKey: []
responses:
'200':
description: API key configuration.
content:
application/json:
schema:
allOf:
- type: object
properties:
name:
type: string
- $ref: ../components/schemas/KeyConfig.yaml
'404':
description: API key not found.
operationId: getV0ManagementKeysByname
put:
tags:
- Management — Config
Expand Down Expand Up @@ -72,6 +101,45 @@ put:
'401':
description: Authentication required or invalid credentials.
operationId: putV0ManagementKeysByname
patch:
tags:
- Management — Config
summary: Merge updates into an API key (admin only)
description: |
Merges the request body into the existing API key configuration, then
validates the result against `KeyConfig`.

PATCH performs a shallow merge; fields omitted from the request keep their
existing values.

**Admin only** — limited principals receive 403.
security:
- AdminKey: []
requestBody:
required: true
content:
application/json:
schema:
type: object
additionalProperties: true
responses:
'200':
description: Saved.
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
const: true
name:
type: string
'400':
description: Validation failed.
'404':
description: API key not found.
operationId: patchV0ManagementKeysByname
delete:
tags:
- Management — Config
Expand Down
73 changes: 65 additions & 8 deletions docs/openapi/paths/v0_management_mcp-servers_{serverName}.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,31 @@ parameters:
description: >
Server name (lowercase alphanumeric, max 64 chars). Must match pattern
`^[a-z0-9][a-z0-9-_]{1,62}$`.
get:
tags:
- Management — Config
summary: Get an MCP server entry by name (admin only)
description: |
Returns a single configured MCP gateway server entry.

**Admin only** — limited principals receive 403.
security:
- AdminKey: []
responses:
'200':
description: MCP server configuration.
content:
application/json:
schema:
allOf:
- type: object
properties:
name:
type: string
- $ref: ../components/schemas/McpServerConfig.yaml
'404':
description: MCP server not found.
operationId: getV0ManagementMcpserversByserverName
put:
tags:
- Management — Config
Expand All @@ -21,14 +46,8 @@ put:
- Max 64 characters
- Can contain lowercase letters, numbers, and hyphens/underscores

## Proxy auth fields

These fields affect how the MCP proxy authenticates to the upstream:
- `auth_type` — Authentication type (none, bearer, basic, header)
- `auth_header_value` — Static value for custom auth headers

The proxy strips incoming `Authorization` / `x-api-key` headers and
uses the configured static auth instead.
The request body contains the upstream URL, enabled flag, and optional
static headers forwarded to the upstream MCP server.

**Admin only** — limited principals receive 403.
security:
Expand All @@ -55,6 +74,44 @@ put:
'400':
description: Invalid server name or body.
operationId: putV0ManagementMcpserversByserverName
patch:
tags:
- Management — Config
summary: Merge updates into an MCP server entry (admin only)
description: |
Merges the request body into the existing MCP server configuration, then
validates the result against `McpServerConfig`.

PATCH performs a shallow merge; omitted fields keep their current values.

**Admin only** — limited principals receive 403.
security:
- AdminKey: []
requestBody:
required: true
content:
application/json:
schema:
type: object
additionalProperties: true
responses:
'200':
description: Saved.
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
const: true
name:
type: string
'400':
description: Invalid server name or body.
'404':
description: MCP server not found.
operationId: patchV0ManagementMcpserversByserverName
delete:
tags:
- Management — Config
Expand Down
Loading