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
12 changes: 0 additions & 12 deletions crates/contextforge-data-plane-apis/src/user_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,6 @@ use std::collections::HashMap;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema, Default)]
pub enum Transport {
#[default]
#[serde(rename = "STREAMABLEHTTP")]
StreamableHttp,
#[serde(rename = "SSE")]
Sse,
#[serde(rename = "STDIO")]
Stdio,
}

#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema, Default)]
pub enum IntegrationType {
#[serde(rename = "REST")]
Expand All @@ -27,7 +16,6 @@ pub enum IntegrationType {
pub struct BackendMCPGateway {
pub name: String,
pub url: url::Url,
pub transport: Transport,
/// Header names copied from the downstream request onto the upstream connection.
pub passthrough_headers: Vec<String>,
/// Static headers injected onto the upstream connection (override passthrough).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,6 @@ mod tests {
"79fabb70-2188-4de8-95ed-dc1e976e14d4": {
"name": "compliance_reference",
"url": "http://upstream:9000/mcp",
"transport": "STREAMABLEHTTP",
"passthrough_headers": [],
"allowed_tool_names": ["get_stats", "echo"],
"tool_name_aliases": {
Expand Down Expand Up @@ -214,7 +213,6 @@ mod tests {
"compliance-reference": {
"name": "compliance_reference",
"url": "http://upstream:9000/mcp",
"transport": "STREAMABLEHTTP",
"passthrough_headers": [],
"allowed_tool_names": ["get_stats"],
"allowed_resource_names": [],
Expand All @@ -223,7 +221,6 @@ mod tests {
"other": {
"name": "other",
"url": "http://other:9000/mcp",
"transport": "STREAMABLEHTTP",
"passthrough_headers": [],
"allowed_tool_names": [],
"allowed_resource_names": [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,6 @@ mod tests {
backend_id: {
"name": "backend",
"url": "http://upstream:9000/mcp",
"transport": "STREAMABLEHTTP",
"passthrough_headers": [],
"allowed_tool_names": [],
"allowed_resource_names": [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -275,8 +275,6 @@ fn is_protected_header(name: &http::HeaderName) -> bool {

#[cfg(test)]
mod tests {
use contextforge_data_plane_apis::user_store::Transport;

use super::*;

#[test]
Expand All @@ -297,7 +295,6 @@ mod tests {
BackendMCPGateway {
name: "b".into(),
url: "https://upstream.example/mcp".parse().unwrap(),
transport: Transport::default(),
passthrough_headers: passthrough.iter().map(|s| (*s).to_owned()).collect(),
add_headers: add.iter().map(|(k, v)| ((*k).to_owned(), (*v).to_owned())).collect(),
remove_headers: remove.iter().map(|s| (*s).to_owned()).collect(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::{collections::HashMap, sync::Arc};

use contextforge_data_plane_apis::{
User,
user_store::{BackendMCPGateway, Transport, UserConfig, VirtualHost},
user_store::{BackendMCPGateway, UserConfig, VirtualHost},
};
use contextforge_data_plane_lib::{Config, Gateway, Result, UserConfigStore, UserConfigStoreType};
use rmcp::{
Expand All @@ -24,7 +24,6 @@ fn paginating_backend(port: u16) -> BackendMCPGateway {
BackendMCPGateway {
name: format!("backend-{port}"),
url: format!("http://127.0.0.1:{port}/mcp").parse().expect("valid url"),
transport: Transport::default(),
passthrough_headers: Vec::new(),
add_headers: HashMap::new(),
remove_headers: Vec::new(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::{collections::HashMap, net::SocketAddr, sync::Arc};

use contextforge_data_plane_apis::{
User,
user_store::{BackendMCPGateway, Transport, UserConfig, VirtualHost},
user_store::{BackendMCPGateway, UserConfig, VirtualHost},
};
use contextforge_data_plane_lib::{
Config, Gateway, Result, UpstreamConnectionMode, UserConfigStore, UserConfigStoreType,
Expand Down Expand Up @@ -215,7 +215,6 @@ fn create_backends(ports: &[u16], with_tls: bool) -> HashMap<String, BackendMCPG
BackendMCPGateway {
name: format!("backend-{port}"),
url,
transport: Transport::default(),
passthrough_headers: Vec::new(),
add_headers: HashMap::default(),
remove_headers: Vec::new(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::{

use contextforge_data_plane_apis::{
User,
user_store::{BackendMCPGateway, Transport, UserConfig, VirtualHost},
user_store::{BackendMCPGateway, UserConfig, VirtualHost},
};
use contextforge_data_plane_cpex::CpexRuntimeRegistry;
use contextforge_data_plane_lib::{Config, Gateway, UpstreamConnectionMode, UserConfigStore, UserConfigStoreType};
Expand Down Expand Up @@ -268,7 +268,6 @@ async fn start_gateway_with_runtime(
BackendMCPGateway {
url: format!("http://127.0.0.1:{backend_port}/mcp").parse().expect("backend URL"),
name: String::new(),
transport: Transport::default(),
passthrough_headers: Vec::new(),
add_headers: HashMap::default(),
remove_headers: Vec::new(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use std::{
use contextforge_data_plane_apis::{
User,
runtime_plugin_config::{RUNTIME_PLUGIN_CONFIG_KEY, RUNTIME_PLUGIN_CONFIG_VERSION},
user_store::{BackendMCPGateway, Transport, UserConfig, VirtualHost},
user_store::{BackendMCPGateway, UserConfig, VirtualHost},
};
use http::{HeaderMap, HeaderValue};
use jsonwebtoken::{Algorithm, EncodingKey, Header, encode};
Expand Down Expand Up @@ -375,7 +375,6 @@ async fn write_redis_config(redis_port: u16, backend: &RunningBackend) {
BackendMCPGateway {
name: "backend".to_owned(),
url: backend.url.parse().expect("backend URL parses"),
transport: Transport::StreamableHttp,
passthrough_headers: Vec::new(),
add_headers: HashMap::new(),
remove_headers: Vec::new(),
Expand Down
7 changes: 3 additions & 4 deletions docs/book/src/backend-connections-and-transports.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ architecture roles.
| Upstream backend | Shared `reqwest::Client` plus RMCP `StreamableHttpClientTransport`. | `common.rs`, `gateway/mcp_service/initialization.rs`, and `gateway/backend_transports.rs`. | Open MCP client sessions to configured backend MCP servers. |
| Config store | Redis plain, TLS, or mTLS connection manager. | `common.rs` and `user_config_store/`. | Load `UserConfig` and plugin runtime config from control-plane authored storage. |

The current MCP dataplane only uses streamable HTTP for backend MCP traffic.
`BackendMCPGateway.transport` already has `STREAMABLEHTTP`, `SSE`, and `STDIO`,
but upstream routing does not branch on that field yet.
The MCP dataplane always uses Streamable HTTP for backend MCP traffic.
`BackendMCPGateway` has no transport selector, and upstream routing always
builds `StreamableHttpClientTransport`.

## Downstream Listeners

Expand Down Expand Up @@ -126,7 +126,6 @@ but it is not the final shape for every backend-specific decision.
| Downstream TLS certificate | Process config. | Process config. It belongs to the gateway listener. |
| Upstream trust bundle and mTLS identity | Process config. | Runtime config per backend or referenced secret material. |
| Backend auth headers | Delegated to `passthrough_headers` / `add_headers` / `remove_headers` in `BackendMCPGateway`. | — |
| Backend transport type | Model field exists, not routed yet. | Runtime config per backend. |
| Header pass-through policy | Implemented via `passthrough_headers`, `add_headers`, `remove_headers` on `BackendMCPGateway`. Headers are session-scoped (snapshotted at initialize); request-scoped propagation is future work. | — |

The boundary to preserve is simple: listener code should not know Redis schema,
Expand Down
2 changes: 0 additions & 2 deletions docs/book/src/running-the-gateway.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,6 @@ curl --silent --show-error --request POST \
"gateway-one": {
"name": "gateway-one",
"url": "http://127.0.0.1:5555/mcp",
"transport": "STREAMABLEHTTP",
"passthrough_headers": [],
"allowed_tool_names": [],
"allowed_resource_names": [],
Expand All @@ -132,7 +131,6 @@ curl --silent --show-error --request POST \
"gateway-two": {
"name": "gateway-two",
"url": "http://127.0.0.1:5556/mcp",
"transport": "STREAMABLEHTTP",
"passthrough_headers": [],
"allowed_tool_names": [],
"allowed_resource_names": [],
Expand Down
11 changes: 2 additions & 9 deletions docs/book/src/runtime-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,20 +35,14 @@ VirtualHost
BackendMCPGateway
name: String
url: Url
transport: Transport
passthrough_headers: Vec<String>
allowed_tool_names: Vec<String>
allowed_resource_names: Vec<String>
allowed_prompt_names: Vec<String>
```

`Transport` currently declares:

```text
STREAMABLEHTTP
SSE
STDIO
```
Backend MCP transport is intentionally absent from `UserConfig`. The dataplane
always builds an upstream Streamable HTTP client.

The Rust types above are easier to picture as JSON. For a complete, working
`UserConfig` document, see the seed request body in
Expand All @@ -65,7 +59,6 @@ but the distinction should stay explicit:
| `VirtualHost.backends` map key | Required. Selects backend session state and becomes the public prefix when a multi-backend identifier has no explicit alias. |
| `BackendMCPGateway.url` | Required. Used to build the upstream `StreamableHttpClientTransport`. |
| `BackendMCPGateway.name` | Present in the model. Current routing uses the backend map key, not this field, as the namespace. |
| `transport` | Present in the model. Current upstream code always builds a streamable HTTP client transport. |
| `passthrough_headers` | Applied during `initialize`: named downstream request headers are copied onto the upstream connection header map. Body-framing (`Content-Length`, `Content-Type`), hop-by-hop, non-standard hop-by-hop (`Proxy-Connection`), and RMCP-reserved headers are silently skipped. Propagation is session-scoped — headers are snapshotted from the initialize request; see note below. |
| `add_headers` | Static `{name: value}` headers injected onto the upstream connection after passthrough (override passthrough values). Body-framing, hop-by-hop, non-standard hop-by-hop (`Proxy-Connection`), and RMCP-reserved headers are silently skipped. |
| `remove_headers` | Header names stripped from the upstream connection after add (applied last). Body-framing, hop-by-hop, non-standard hop-by-hop (`Proxy-Connection`), and RMCP-reserved headers are silently skipped. |
Expand Down
12 changes: 0 additions & 12 deletions schemas/user_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,6 @@
"type": "string",
"format": "uri"
},
"transport": {
"$ref": "#/$defs/Transport"
},
"passthrough_headers": {
"description": "Header names copied from the downstream request onto the upstream connection.",
"type": "array",
Expand Down Expand Up @@ -93,20 +90,11 @@
"required": [
"name",
"url",
"transport",
"passthrough_headers",
"allowed_tool_names",
"allowed_resource_names",
"allowed_prompt_names"
]
},
"Transport": {
"type": "string",
"enum": [
"STREAMABLEHTTP",
"SSE",
"STDIO"
]
}
}
}
Loading