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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,8 @@ repos/
# OAuth token cache for mcp-remote bridges (contains live access/refresh tokens)
.mcp-auth/

# OAuth token cache for REST providers' authorization_code flow (live tokens)
.rest-auth/

# Legacy Playwright MCP output directory (replaced by ./files in docker-compose)
.playwright-mcp/
101 changes: 101 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ Click **+ New Provider** and choose a provider type:
| **Python code** | Write `async def` functions; the UI lists the ones it finds as you type. Each becomes a tool entry. |
| **Package** | Enter any command that launches a stdio MCP server (`npx`, `uvx`, `python -m`, or an installed binary). When you click **Next**, mcpproxy auto-introspects the command and pre-populates the tool list; if introspection fails you can still proceed and add tools by hand. |
| **Repository** | Provide a git URL and a list of build commands. mcpproxy clones the repo, runs the build commands, then introspects the resulting stdio MCP server. The URL and build commands are persisted in YAML so the repo can be re-cloned and re-built automatically on every container restart. |
| **REST / OAuth API** | Point at a REST API: a base URL plus an OpenAPI spec (imported into tools automatically) or hand-entered endpoints, with optional OAuth. Each endpoint becomes an MCP tool. See [REST / OAuth providers](#rest--oauth-providers). |

After the provider step, the wizard shows a **Secrets** step: any `secrets.env` entries
in the provider are listed, and you can fill in their values to save them directly to `.env`.
Expand Down Expand Up @@ -143,6 +144,106 @@ ready when needed.
> **After editing and saving** a provider's command or setup steps, click **Restart MCP Server**
> (the yellow bar that appears after saving) to apply the changes.

## REST / OAuth providers

A **REST provider** wraps an HTTP/REST API directly — no Python and no separate MCP
server needed. A provider YAML with a `rest:` block declares a base URL, an `auth:`
block, and a set of endpoints; each endpoint becomes an MCP tool. mcpproxy builds the
HTTP request (path/query/body), attaches authentication, and returns the JSON response.

Create one through the **+ New Provider → REST / OAuth API** wizard. You can **import an
OpenAPI spec** (URL or file — OpenAPI 3.x or Swagger 2.0) to generate the endpoints and tools automatically, or
enter endpoints by hand. OpenAPI specs are expanded into concrete endpoints when the
provider is created, so startup stays fast and offline.

After creation, the editor lets you **edit everything inline** — the base URL, the auth
block, default headers (sent on every request), and the endpoint list (method, path, and
which params go in the path / query / body). Adding or removing an endpoint keeps its
paired tool in sync (endpoints map 1:1 to tools by name), and **⟳ Sync params to tool
schema** regenerates a tool's input schema from its endpoint's params.

Large responses are **truncated** to a bounded preview (with a `truncated` flag) so a
single call can't flood the model's context — tune or disable via `MCPPROXY_REST_MAX_BYTES`.

### Authentication

The `auth.type` field selects how requests are authenticated. Secrets are referenced by
**environment-variable name** (the `*_env` fields) and filled in via the Secrets UI / `.env` —
never written into the YAML.

| `auth.type` | Fields | Behaviour |
|---|---|---|
| `none` | — | No authentication. |
| `bearer` | `token_env` | Sends `Authorization: Bearer <env>`. |
| `api_key` | `value_env`, plus either `header` (default `X-Api-Key`) or `in: query` + `name` | Sends the secret in a custom header, or as a query parameter when `in: query`. |
| `client_credentials` | `token_url`, `client_id_env`, `client_secret_env`, `scopes` | OAuth2 client-credentials. Token is fetched, cached, and auto-refreshed on expiry/401. |
| `authorization_code` | `authorize_url`, `token_url`, `client_id_env`, `client_secret_env` (optional for PKCE), `scopes` | Interactive OAuth2 + PKCE. Click **🔐 Authorize** in the editor to complete the browser flow; tokens are cached and refreshed automatically. |

For `authorization_code`, register the redirect URI **`<MCPPROXY_OAUTH_REDIRECT_BASE>/oauth/callback`**
(default `http://localhost:8889/oauth/callback`) with your OAuth provider. Tokens are cached
under `MCPPROXY_REST_AUTH_DIR` (default `/app/.rest-auth`, gitignored).

### Example

```yaml
rest:
base_url: https://api.example.com/v1
headers:
Accept: application/json
auth:
type: client_credentials
token_url: https://auth.example.com/oauth/token
client_id_env: EXAMPLE_CLIENT_ID
client_secret_env: EXAMPLE_CLIENT_SECRET
scopes: [read, write]
endpoints:
- name: get_user
method: GET
path: /users/{user_id}
path_params: [user_id]
query_params: [include]
body_params: []
- name: create_item
method: POST
path: /items
path_params: []
query_params: []
body_params: [title, body]

requirements: [httpx]

tools:
- name: get_user
description: Fetch a user by id.
input_schema:
type: object
properties:
user_id: {type: string}
include: {type: string}
required: [user_id]
- name: create_item
description: Create an item.
input_schema:
type: object
properties:
title: {type: string}
body: {type: string}
required: [title]
```

Each tool's `name` maps 1:1 to an endpoint's `name`. REST providers depend on `httpx`
(installed by default).

At startup, OAuth-backed REST providers are **warmed**: `client_credentials` tokens are
fetched and cached, and `authorization_code` providers that have no usable token surface
their **🔐 Authorize** link in the banner immediately, rather than only after the first
failed tool call. (Disable with `MCPPROXY_WARM_REMOTE=0`.)

Config knobs: `MCPPROXY_REST_AUTH_DIR`, `MCPPROXY_OAUTH_REDIRECT_BASE`,
`MCPPROXY_REST_TIMEOUT` (per-request HTTP timeout), `MCPPROXY_REST_MAX_BYTES` (max
response size before truncation; 0 disables), and `MCPPROXY_OAUTH_FLOW_TTL` (seconds an
in-flight authorization attempt stays valid; default 600).

## Secrets

Each tool provider YAML declares its required environment variables under `secrets.env`:
Expand Down
14 changes: 14 additions & 0 deletions config.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,20 @@
# Override with MCPPROXY_REPOS_DIR.
REPOS_DIR = Path(os.environ.get("MCPPROXY_REPOS_DIR", "/app/repos"))

# Directory where REST providers cache OAuth tokens (authorization_code flow).
# One JSON file per provider (e.g. /app/.rest-auth/<provider>.json) holding the
# access/refresh tokens and expiry. Gitignored. Override with
# MCPPROXY_REST_AUTH_DIR (run_local.sh points it at ./.rest-auth for local runs).
REST_AUTH_DIR = Path(os.environ.get("MCPPROXY_REST_AUTH_DIR", "/app/.rest-auth"))

# Public base URL the OAuth provider redirects back to after the user authorizes
# a REST provider's authorization_code flow. The callback route is served by the
# UI app at "<base>/oauth/callback", so this must match a redirect URI registered
# with the OAuth provider. Override with MCPPROXY_OAUTH_REDIRECT_BASE.
OAUTH_REDIRECT_BASE = os.environ.get(
"MCPPROXY_OAUTH_REDIRECT_BASE", "http://localhost:8889"
).rstrip("/")

UI_HOST = os.environ.get("MCP_UI_HOST", "0.0.0.0")
UI_PORT = int(os.environ.get("MCP_UI_PORT", "8889"))

Expand Down
4 changes: 4 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ services:
# Where mcp-remote caches OAuth tokens (access + refresh). Persisted via
# the mcpproxy-mcp-auth volume so you authorize once and refresh silently.
MCP_REMOTE_CONFIG_DIR: "/app/.mcp-auth"
# Where REST providers cache OAuth tokens for the authorization_code flow.
MCPPROXY_REST_AUTH_DIR: "/app/.rest-auth"
volumes:
- mcpproxy-tools:/app/tools
- mcpproxy-files:/app/files
Expand All @@ -59,6 +61,7 @@ services:
- mcpproxy-npm:/root/.npm
- mcpproxy-uv-tools:/root/.local/share/uv
- mcpproxy-mcp-auth:/app/.mcp-auth
- mcpproxy-rest-auth:/app/.rest-auth
- ./.env:/app/.env

volumes:
Expand All @@ -69,3 +72,4 @@ volumes:
mcpproxy-npm:
mcpproxy-uv-tools:
mcpproxy-mcp-auth:
mcpproxy-rest-auth:
Loading
Loading