Add first-class REST/OAuth provider type#21
Merged
Conversation
Introduce a new `rest` provider kind so a REST API can be wrapped as MCP tools declaratively — no Python required. A provider YAML with a `rest:` block declares a base URL, an `auth:` block, and endpoints (entered by hand or imported from an OpenAPI 3.0 spec); each endpoint becomes an MCP tool exposed on both the MCP server (8888) and the OpenAI-compatible REST API (8889). - rest_provider.py: generic httpx handler routed through register_tool, a client_credentials token manager (cache/refresh), an authorization_code + PKCE token store (on-disk cache, interactive browser flow, refresh-token rotation), an auth resolver, and an OpenAPI 3.0 introspector. - server.py: a `rest` branch in register_provider (checked first; each tool maps 1:1 to an endpoint by name). - frontend/app.py: "REST / OAuth API" wizard step (auth-type fields, OpenAPI import + manual endpoints), editor rest-box with an Authorize button, plus /api/introspect-openapi, /api/rest-authorize, and /oauth/callback endpoints; pending auth links surface in the existing banner. - config.py / run_local.sh / docker-compose.yml: REST_AUTH_DIR and OAUTH_REDIRECT_BASE settings and token-cache volume. - requirements.txt: httpx promoted to a runtime dependency. - Tests: tests/test_rest_provider.py plus rest cases in test_server.py and test_frontend.py (387 passing). https://claude.ai/code/session_01L9uGbkXi2RwUmBQHdVaNoZ
The rich editor's REST box now supports editing the auth block (type + conditional fields) and the endpoint list (name, method, path, and path/query/body param routing) directly — previously these were only set through the creation wizard. Adding or removing an endpoint keeps its paired tool in sync (endpoints map 1:1 to tools by name), renaming an endpoint renames its tool, and a "⟳ Sync params to tool schema" action regenerates a tool's input schema from its endpoint's params (preserving existing types/descriptions). Adds a frontend test covering the editor save path (PUT with an added endpoint + renamed tool) so auth and endpoints survive a round-trip. https://claude.ai/code/session_01L9uGbkXi2RwUmBQHdVaNoZ
Adds an end-to-end frontend test that drives the exact backend API sequence the REST wizard performs: introspect an OpenAPI spec with the real parser, assemble the provider as wzNext() does, POST it, read it back, and assert the on-disk YAML (endpoint param classification, auth block, surfaced secret keys). Complements the static verification of the wizard/editor JavaScript (node --check, HTML-handler→definition wiring, and eslint no-undef all clean) by exercising the create → reload path through the HTTP API the JS calls. https://claude.ai/code/session_01L9uGbkXi2RwUmBQHdVaNoZ
- Warm OAuth-backed REST providers at startup (mirrors the mcp-remote warm-up): client_credentials tokens are fetched/cached, and authorization_code providers with no usable token surface their authorize URL via the pending-auth banner immediately instead of only after the first failed tool call. Gated by MCPPROXY_WARM_REMOTE. - Give in-flight authorization_code PKCE state a TTL (MCPPROXY_OAUTH_FLOW_TTL, default 600s) and prune stale entries on begin/complete, so a restart mid-flow or abandoned attempts don't leak state. - Tests for provider discovery (_rest_oauth_providers) and flow pruning; README notes the warm-up behaviour and new env vars. https://claude.ai/code/session_01L9uGbkXi2RwUmBQHdVaNoZ
- Truncate oversized response bodies to a bounded preview with a `truncated` flag (MCPPROXY_REST_MAX_BYTES, default 100KB, 0 disables) so one call can't flood the model's context. - Support api_key auth sent as a query parameter (`in: query` + `name`) in addition to a header; editor exposes a header/query toggle. - Add an editable default-headers section to the REST editor box (serialized to a plain YAML mapping on save). - Tests for all three plus a header/api_key round-trip; README updated. Wizard/editor JS re-verified (node --check, handler wiring, eslint no-undef all clean). 400 tests passing. https://claude.ai/code/session_01L9uGbkXi2RwUmBQHdVaNoZ
The introspector now handles both OpenAPI 3.x and Swagger 2.0 specs: - Swagger 2.0 `in: body` parameters expand their schema's properties into body params; `in: formData` maps to body params; param types are read from `param.type` (2.0) or `param.schema.type` (3.x). - Object schemas merge `allOf` (resolving `#/components/...` and `#/definitions/...` refs) so composed request bodies import correctly. Adds tests for Swagger 2.0 param classification and allOf merging. 402 tests passing; README notes 2.0/3.x support. https://claude.ai/code/session_01L9uGbkXi2RwUmBQHdVaNoZ
There was a problem hiding this comment.
Pull request overview
This PR adds a first-class rest provider type so users can declaratively wrap REST APIs as MCP tools (including OAuth flows), without writing Python code. It introduces a REST provider runtime (rest_provider.py), wires REST provider registration into the MCP server, and extends the UI to create/edit REST providers and run OAuth authorization_code + PKCE.
Changes:
- Added
rest_provider.pywith REST request handling, auth resolvers (none/bearer/api_key/OAuth), token caching, and OpenAPI/Swagger introspection. - Updated server registration to support
rest:providers and added startup warm-up for OAuth-backed REST providers. - Extended the frontend to support a “REST / OAuth API” wizard/editor, OpenAPI introspection endpoint, and OAuth callback/authorize endpoints; added comprehensive tests.
Reviewed changes
Copilot reviewed 10 out of 12 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
server.py |
Registers REST providers and adds REST OAuth warm-up on startup. |
rest_provider.py |
Implements REST tool handler, OAuth token management, and OpenAPI/Swagger parsing. |
frontend/app.py |
Adds REST provider CRUD support in UI, OpenAPI introspection API, and OAuth authorize/callback endpoints plus editor/wizard UI. |
README.md |
Documents REST/OAuth providers, auth modes, example YAML, and config knobs. |
config.py |
Adds REST_AUTH_DIR and OAUTH_REDIRECT_BASE settings. |
docker-compose.yml |
Persists REST OAuth token cache via a new volume and env var. |
run_local.sh |
Adds local default for MCPPROXY_REST_AUTH_DIR. |
requirements.txt |
Adds httpx as a runtime dependency. |
.gitignore |
Ignores .rest-auth/ token cache directory. |
tests/test_rest_provider.py |
Adds unit tests for REST provider behavior, OAuth managers, and OpenAPI parsing. |
tests/test_server.py |
Adds tests for REST branch detection and OAuth REST provider discovery. |
tests/test_frontend.py |
Adds REST provider UI/backend tests including wizard flow and OAuth endpoints. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- /oauth/callback: HTML-escape the `error` query param and exception text before embedding them in the response (reflected-XSS fix). - /api/introspect-openapi: restrict local spec paths to the files directory (no arbitrary file reads like .env) and run the blocking fetch/parse in a worker thread so it can't block the UI event loop. - OAuth token managers: make the asyncio lock loop-safe so a manager cached by the startup warm-up thread can be reused from the MCP server loop without "bound to a different loop" errors. - introspect_openapi: drop the unused `base_url` parameter (and stop the wizard from sending it). Tests for callback escaping, path traversal/containment, and cross-loop token-manager reuse. 407 passing; wizard/editor JS re-verified. https://claude.ai/code/session_01L9uGbkXi2RwUmBQHdVaNoZ
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Introduce a new
restprovider kind so a REST API can be wrapped as MCPtools declaratively — no Python required. A provider YAML with a
rest:block declares a base URL, an
auth:block, and endpoints (entered byhand or imported from an OpenAPI 3.0 spec); each endpoint becomes an MCP
tool exposed on both the MCP server (8888) and the OpenAI-compatible REST
API (8889).
a client_credentials token manager (cache/refresh), an
authorization_code + PKCE token store (on-disk cache, interactive
browser flow, refresh-token rotation), an auth resolver, and an
OpenAPI 3.0 introspector.
restbranch in register_provider (checked first; eachtool maps 1:1 to an endpoint by name).
OpenAPI import + manual endpoints), editor rest-box with an Authorize
button, plus /api/introspect-openapi, /api/rest-authorize, and
/oauth/callback endpoints; pending auth links surface in the existing
banner.
OAUTH_REDIRECT_BASE settings and token-cache volume.
and test_frontend.py (387 passing).
https://claude.ai/code/session_01L9uGbkXi2RwUmBQHdVaNoZ