-
Notifications
You must be signed in to change notification settings - Fork 347
Open
Open
Copy link
Labels
enhancementNew feature or requestNew feature or requesttriageIssues / Features awaiting triageIssues / Features awaiting triage
Milestone
Description
Feature Request: REST Passthrough APIs with Pre/Post Plugins
Summary
Add first-class passthrough support for upstream REST APIs. When a REST API is registered as a tool, the gateway also exposes a corresponding HTTP passthrough endpoint that forwards requests to the upstream, with plugin hooks before and after the call for validation, enrichment, filtering, transformation, and auditing.
Motivation
- Unify how external REST services are consumed: as MCP tools and as plain HTTP.
- Enable consistent cross-cutting concerns (auth, rate limit, PII redaction, deny/allow, response shaping) via the existing plugin framework.
- Reduce duplication between “tool invocation” and “custom reverse proxy” patterns.
- Make REST integrations discoverable and self-documented via OpenAPI.
- Supports JSONPath filtering to apply plugins selectively
Goals
- Register a REST integration once and use it as:
- An MCP tool (
tools/call
), and - A passthrough HTTP endpoint (
/passthrough/...
).
- An MCP tool (
- Allow attaching pre/post plugin chains at the route and/or tool level.
- Support path templating, query/header mapping, and body pass-through.
- Enforce security (allowlist, auth injection, SSRF safeguards), rate limiting, and observability.
Non-Goals (Initial)
- Full API gateway feature parity (e.g., complex routing DSL, websocket upgrades).
- Automatic OpenAPI → tool generation (could be a follow-up).
Proposed Design
1) Model additions
- New tool integration type:
rest
(if not already present) with fields:id
,name
,base_url
,path_template
,method
query_mapping
(dict),header_mapping
(dict),timeout_ms
expose_passthrough
(bool, default true)auth
(enum: none|static_header|bearer_env|bearer_secret|mcp_token|plugin)allowlist
(list of allowed upstream hosts/schemes)plugin_chain_pre
,plugin_chain_post
(optional, override defaults)
2) Router
- New router under
mcpgateway/routers/passthrough.py
:- Base path:
/passthrough/{namespace}/{tool_id}
(configurable base, e.g./api/tools/
) - Methods supported: mirror the tool’s
method
(GET/POST/PUT/PATCH/DELETE) - Path segments beyond
tool_id
appended topath_template
if trailing/**
is declared - Query, headers, and body forwarded according to mapping rules
- Base path:
3) Request processing pipeline
- Pipeline per request:
- Resolve tool by
{namespace}/{tool_id}
and validateexpose_passthrough
- Construct upstream URL from
base_url + path_template
using path/query/header/body mapping - Run pre-plugins (validation, auth enrichment, deny/allow, rate limit, logging)
- Forward to upstream with timeout, stream or buffer response
- Run post-plugins (redaction, shape, cache, transform, audit)
- Return response with appropriate status, headers, and body
- Resolve tool by
4) Plugins
- Use existing plugin framework (e.g., built-ins:
pii_filter
,deny_filter
,regex_filter
,resource_filter
). - Define plugin hooks:
- Pre:
on_passthrough_request(context, request)
(can mutate request or raise) - Post:
on_passthrough_response(context, request, response)
(can mutate response)
- Pre:
- Chain selection order:
- Route-specific: tool-level
plugin_chain_pre/post
if provided - Fallback: default passthrough chains from
plugins/config.yaml
- Route-specific: tool-level
5) Configuration
- New section in config to declare defaults and chains:
# plugins/config.yaml
passthrough:
enabled: true
base_path: "/passthrough"
default_timeout_ms: 20000
default_plugin_chains:
pre: ["deny_filter", "regex_filter", "pii_filter"]
post: ["pii_filter"]
# Example tool definition (illustrative; align to existing tool config format)
tools:
- id: "github.search"
type: rest
name: "GitHub Search"
base_url: "https://api.github.com"
path_template: "/search/repositories"
method: GET
query_mapping:
q: "{{params.query}}"
sort: "{{params.sort|default('stars')}}"
header_mapping:
Accept: "application/vnd.github+json"
Authorization: "Bearer {{env.GITHUB_TOKEN}}"
expose_passthrough: true
plugin_chain_pre: ["deny_filter", "rate_limit"]
plugin_chain_post: ["pii_filter", "response_shape"]
6) Security
- Enforce upstream host allowlist; reject requests to non-allowed hosts/schemes.
- Optionally block private IP ranges to prevent SSRF.
- Require JWT bearer auth for passthrough endpoints by default; scope to
{namespace}:{tool_id}
. - Support header redaction in logs and traces.
7) Observability
- Add spans around the pipeline:
passthrough.request
(attrs: tool.id, method, url, tenant, user)passthrough.upstream
(attrs: status_code, duration_ms, retries)- Record plugin execution as events or child spans.
8) Errors and edge cases
- Upstream errors surface with preserved status code and structured error body when possible.
- Timeouts return 504; connection failures 502; policy violations 403/422.
- Size limits for request/response bodies; configurable.
OpenAPI Exposure (optional, but desirable)
- Generate OpenAPI entries for exposed passthrough routes based on tool metadata.
- Tag routes by namespace; include summaries and example requests.
Acceptance Criteria
- Can declare a REST tool once and:
- Invoke it via
tools/call
(MCP) - Call it via HTTP at
/passthrough/{namespace}/{tool_id}
with identical semantics
- Invoke it via
- Pre- and post-plugin chains execute and can mutate request/response.
- Security guardrails: allowlist + SSRF protections + auth requirement documented and enforced.
- Basic OpenAPI entries appear for exposed routes, or explicitly deferred with a follow-up issue.
- Unit tests cover routing, mappings, plugin invocation, and error paths.
Implementation Plan (phased)
- Phase 1: Data model + config parsing for
rest
tools and passthrough defaults - Phase 2: Router + pipeline skeleton with mock upstream
- Phase 3: Plugin hooks + built-in filters integration
- Phase 4: Security guardrails (allowlist + SSRF) and auth
- Phase 5: Observability spans + metrics
- Phase 6: Docs + examples + tests
Risks / Mitigations
- SSRF: strict allowlist + private range blocking + URL normalization
- Secret leakage: header redaction + post-filtering + audit logs
- Backwards compat: default
expose_passthrough: false
for existing tools if needed; true for newrest
type
Notes
- This complements existing federation/gateway features and stdio/SSE/WebSocket transports.
- Keep scope focused on single-upstream REST calls; multi-hop/mashups can be handled by tools or future compositors.
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or requesttriageIssues / Features awaiting triageIssues / Features awaiting triage