Tentative target: this page records the proposed ContextForge 2.0 end state and delivery phases. It is not a description of the current Rust implementation. See Architecture and MCP Routing Semantics for current behavior.
This is a product-wide view because the ContextForge external dataplane
boundary depends on work owned by the ContextForge control plane and built-in
dataplane in the Python IBM/mcp-context-forge repository. It does not move
control-plane or built-in-dataplane responsibilities into this repository. See
Project terminology for the canonical component
names.
- ContextForge supports MCP
2026-07-28and2025-11-25over Streamable HTTP on both the client-facing and backend-facing sides of the ContextForge external dataplane. - Same-version client/backend paths are supported directly. Cross-version
2026-07-28→2025-11-25and2025-11-25→2026-07-28adaptation is best effort. - All external-dataplane request/response handling is stateless for both versions. The target request path does not depend on an MCP session, session affinity, or a retained backend transport.
initializeremains supported for compatibility, but it is a stateless request: the external dataplane generates its response from effective configuration and does not use it to establish state required by later requests.- Legacy SSE transport is not part of the external-dataplane target.
- Fan-out and other one-to-many MCP work is limited to the control plane. The built-in and external dataplanes generate discovery, capability, and list responses from control-plane-authored effective configuration.
- Effective configuration flows one way from the control plane to the built-in and external dataplanes through externally shared state. A process-local cache may speed reads but is never the source of truth.
- MCP subscriptions and notifications remain Phase 4 work.
IBM/mcp-context-forge issue #6327
tracks the first targeted-operation slice for tools/call. The issue calls the
incoming/client-facing side “upstream” and the selected backend-facing side
“downstream”; this wiki uses the explicit names below.
| Incoming client | Selected backend | Target behavior |
|---|---|---|
2026-07-28 |
2026-07-28 |
Supported directly as one stateless request. |
2026-07-28 |
2025-11-25 |
Best-effort protocol adaptation within one stateless request. |
2025-11-25 |
2026-07-28 |
Best-effort protocol adaptation within one stateless request. |
2025-11-25 |
2025-11-25 |
Supported directly as one stateless request. |
For every row, the external dataplane authenticates and authorizes the request, reads
the principal-bound effective configuration, validates that the requested
object is visible and permitted, resolves exactly one backend, adapts the
protocol when necessary, and closes the request-scoped backend connection after
the response. A client may call initialize, but later operations neither
require nor reuse state created by it.
“Best effort” never permits hidden session state. If a semantic difference or backend requirement cannot be handled within the current request, the external dataplane returns an explicit error instead of creating affinity or retaining a backend transport for a later request.
For the initial tools/call slice, issue #6327 assumes that the selected
backend needs neither application authentication nor mTLS and that its server
certificate chains to the system CA. Those are issue-scope assumptions, not a
change to the external dataplane's broader transport-security model.
The front door separates management traffic from MCP traffic and chooses the built-in or external dataplane by deployment route and session model, not only by protocol version. The built-in dataplane can handle either supported version in stateful or stateless mode. The external dataplane can handle either supported version only in stateless mode. PostgreSQL remains the durable management store; the shared runtime store carries compiled configuration to both dataplanes.
flowchart TB
subgraph Clients[Traffic]
direction LR
AdminClient([Admin or User])
CompatClient([MCP 2025-11-25 Client])
ModernClient([MCP 2026-07-28 Client])
end
FrontDoor[Load Balancer and Router]
subgraph ContextForge[ContextForge 2.0]
direction LR
subgraph PythonRepo[IBM mcp-context-forge Python Repository]
direction TB
Control[ContextForge Control Plane]
Builtin[ContextForge Built-In Dataplane]
end
External[ContextForge External Dataplane - Rust]
end
Postgres[(PostgreSQL Management State)]
RuntimeStore[(Shared Effective Configuration)]
Upstreams[MCP 2026-07-28 and 2025-11-25 Servers]
AdminClient -->|Management API| FrontDoor
CompatClient -->|Streamable HTTP MCP 2025-11-25| FrontDoor
ModernClient -->|Streamable HTTP MCP 2026-07-28| FrontDoor
FrontDoor -->|Management routes| Control
FrontDoor -->|Stateful or built-in MCP routes| Builtin
FrontDoor -->|Stateless external MCP routes| External
Control -->|Persist administrative state| Postgres
Control -->|Publish effective configuration| RuntimeStore
RuntimeStore -->|Read shared configuration| Builtin
RuntimeStore -->|Read-only configuration| External
Control -->|Discover catalogs and poll liveness| Upstreams
Builtin -->|Stateful or stateless MCP calls| Upstreams
External -->|Stateless targeted MCP calls| Upstreams
Redis is the current external-dataplane configuration store and the preferred shared implementation. The built-in dataplane may consume the same compiled configuration from Redis or PostgreSQL. When multiple built-in-dataplane instances are deployed, stateful MCP behavior requires an explicit shared-state or affinity design; stateless behavior must not rely on process memory.
| Component | Target responsibility |
|---|---|
| Front door | Route management APIs to the ContextForge control plane. Route MCP to the built-in dataplane when the built-in route or stateful behavior is required, and to the external dataplane when the configured stateless external route is selected. Protocol version alone does not identify the component. |
| ContextForge control plane | Manage the virtual-server lifecycle and upstream assignments; connect to heterogeneous upstreams; retrieve and page through capabilities, tools, resources, prompts, completions, and other catalogs; normalize and persist them; let administrators select exposed objects and rules; compile effective runtime configuration; poll upstream liveness and changes. |
| PostgreSQL | Persist administrative source data such as virtual servers, upstream definitions, normalized catalogs, selections, and policies. It is not on the external-dataplane request path. |
| Configuration synchronization | Publish effective configuration one way from the control plane to externally shared state. The built-in and external dataplanes should consume the same shape where practical. |
| ContextForge built-in dataplane | Handle 2026-07-28 and 2025-11-25 MCP requests in Python, including stateful and stateless behavior. It is the MCP request path shipped in the same repository as the control plane, not the control plane itself. |
| ContextForge external dataplane | Handle 2026-07-28 and 2025-11-25 Streamable HTTP requests statelessly in Rust. Read effective configuration, serve aggregate and initialize responses locally, and route a targeted method to exactly one selected backend. Cross-version adaptation is best effort. It does not own IAM, UI, management APIs, or durable metrics storage. |
| Backend MCP servers | May use 2026-07-28 or 2025-11-25, independently of the incoming client version. Connections and any required negotiation are request-scoped and leave no reusable session; the architecture does not require backend session affinity. |
The control plane owns two distinct forms of state:
| State | Contents | Owner and consumers |
|---|---|---|
| Administrative source state | Virtual servers, upstream registrations, raw and normalized catalogs, exposure selections, policies, and liveness. | Written by the control plane to PostgreSQL; used by management workflows and reconciliation. |
| Effective runtime configuration | Effective server identity and capabilities, visible tools/resources/prompts/completions, downstream paging material, backend resolution, required scopes/roles, and applicable runtime policy for a tenant or isolation domain, user, team, or other principal. | Compiled and published by the control plane; read by the built-in and external dataplanes. |
The control plane must exhaust upstream pagination while reconciling catalogs. The compiled snapshot must contain enough information for either the built-in or external dataplane to produce downstream paging without contacting every upstream. Publication must be atomic or revisioned so neither the built-in nor external dataplane combines partial catalog and policy state.
The effective-configuration model requires identity isolation as well as catalog precomputation. A cached snapshot is data, not an authorization grant. Every downstream request must independently establish and enforce its trusted authorization context.
- The external dataplane derives the authorization key only from verified JWT claims and the validated server route. MCP params and client metadata must not supply or override a principal, team, tenant, virtual server, backend, or cache key.
- Snapshot and cache partitions include the applicable trust or tenant
boundary, authenticated
sub, effective team or other principal, virtual server, and configuration revision. Entries must never be reused across authorization contexts. - The control plane maps verified identity attributes to an effective principal and compiles its visible objects and RBAC policy. The built-in and external dataplanes enforce required token scopes or roles and the compiled policy on every discovery, list, and targeted operation.
- Missing, unmapped, ambiguous, expired, or unauthorized snapshots and objects are denied by default. A targeted denial makes no upstream call, and errors must not disclose another principal's catalog or backend mapping.
- The exact tenant/team claim mapping and token-scope-to-RBAC rules are a
cross-repository contract that the control plane, publisher, schemas,
external dataplane, and integration tests must define together. The current
coarse
sub-only implementation is not the Phase 3 target.
| Work | Target owner and behavior |
|---|---|
| Virtual-server creation and upstream assignment | Control plane persists management state and connects to assigned upstreams. |
| Upstream discovery, initialization where required, catalog pagination, capability aggregation, filtering, and liveness polling | Control plane only; this is the intentional fan-out boundary. |
server/discover, initialize, and effective capabilities |
After per-request authorization, the built-in or external dataplane generates the response from principal-bound effective configuration. The built-in dataplane may support a stateful flow; the external dataplane treats initialize as stateless compatibility and creates no state required by later requests. |
tools/list, resources/list, prompts/list, resource-template listing, and similar aggregate methods |
After method-scope and compiled-RBAC enforcement, the built-in or external dataplane generates the visible response from principal-bound effective configuration with no live upstream fan-out. |
tools/call, resources/read, prompts/get, completion, and similar targeted methods |
The built-in or external dataplane resolves the effective entry under the trusted authorization key, applies default-deny scope and object policy, and calls exactly one selected backend only when authorized. The external dataplane adapts protocol versions when necessary and leaves no reusable session; the built-in dataplane may use its stateful or stateless execution model. |
| Plugins for trusted aggregate responses | Prefer policy compiled by the control plane; avoid mandatory per-request plugin calls for a response already produced from trusted effective configuration. |
| Plugins for targeted calls | May run on the external-dataplane request path when request or response inspection is required. Exact hook allocation remains an implementation decision. |
| Subscriptions, server notifications, and downstream list-change notifications | Deferred to Phase 4 because their state and delivery model do not fit the request/response simplification. |
| Phase | Scope |
|---|---|
| 1. Separate control-plane and built-in-dataplane responsibilities | Establish a clear boundary between the ContextForge control plane and built-in dataplane inside the Python repository. The control plane writes effective configuration per user, team, or other principal to shared state; the built-in dataplane reads it and handles MCP requests. |
| 2. Route targeted calls through the external dataplane | Make the built-in and external dataplanes follow the same configuration-driven contract. Send selected targeted operations such as tools/call, resources/read, prompts/get, and completion to the external dataplane. For each operation, support both same-version 2026-07-28/2025-11-25 paths and attempt both cross-version paths on a best-effort basis, always without reusable session state. The tools/call slice is tracked by #6327. |
| 3. Route all stateless request/response MCP methods through the external dataplane | Serve discovery, stateless initialize, capabilities, aggregate lists, and targeted calls for both supported protocol versions from the external dataplane. Aggregate responses come from effective configuration; targeted calls reach exactly one backend. The built-in dataplane continues to support both stateful and stateless behavior. |
| 4. Implement subscriptions and notifications | Add the state, routing, and delivery model for upstream subscriptions, resource notifications, and list-change notifications after the request/response architecture is complete. |
The examples below use tools, but the same ownership applies to resources,
prompts, completions, and other aggregate or targeted request/response methods.
“Supported MCP client” and “supported MCP server” mean either 2026-07-28 or
2025-11-25; when the two sides differ, adaptation is best effort.
sequenceDiagram
autonumber
actor User
participant UI as Admin UI or API
participant CP as ContextForge Control Plane
participant DB as Control Plane DB
participant MCP1 as MCP 2026-07-28 Server
participant MCP2 as MCP 2025-11-25 Server
participant Store as Shared Config Store (Redis)
participant DP as ContextForge External Dataplane
User->>UI: Create virtual server
UI->>CP: Submit virtual server
CP->>DB: Store virtual server
User->>UI: Assign MCP Server 1 and MCP Server 2
UI->>CP: Update backend associations
CP->>DB: Store backend associations
par Inspect 2026-07-28 backend
CP->>MCP1: Discover capabilities and retrieve catalogs
MCP1-->>CP: Capabilities and catalog
and Inspect 2025-11-25 backend
CP->>MCP2: Initialize or discover and retrieve catalogs
MCP2-->>CP: Capabilities and catalog
end
CP->>DB: Reconcile normalized catalog
User->>UI: View available catalog entries
UI->>CP: Request reconciled catalog
CP->>DB: Read catalog
DB-->>CP: inc, sum, dec, diff
CP-->>UI: Display available catalog entries
User->>UI: Allow inc and sum
UI->>CP: Update virtual server policy
CP->>DB: Store selected tools and policy
CP->>CP: Compile snapshot by tenant, principal and vhost
CP->>Store: Atomically publish revision N
Store-->>DP: Configuration revision available
DP->>Store: Load revision N
DP->>DP: Replace local cache atomically
Note over CP,MCP2: Control Plane handles upstream protocol and pagination
Note over CP,DP: Effective configuration flows one way from CP to DP
Note over CP,DP: Snapshot carries compiled scopes, RBAC and visible objects
sequenceDiagram
autonumber
participant Client as Supported MCP Client
participant Ingress
participant DP as ContextForge External Dataplane
participant Cache as Local Cache
participant Store as Shared Config Store (Redis)
Client->>Ingress: initialize or server/discover
Ingress->>DP: Forward supported MCP request
DP->>DP: Verify JWT, metadata and server route
DP->>DP: Derive authorization key from trusted context
DP->>Cache: Get snapshot by authorization key
alt Snapshot available
Cache-->>DP: Snapshot revision N
else Snapshot missing or expired
Cache-->>DP: Cache miss
DP->>Store: Read by authorization key
Store-->>DP: Snapshot revision N or not found
opt Authorized snapshot returned
DP->>Cache: Store under authorization key
end
end
DP->>DP: Enforce discovery scope and compiled RBAC
alt Snapshot mapped and authorized
DP-->>Client: Version-appropriate identity and visible capabilities
else Missing, unmapped or denied
DP-->>Client: Authorization error without catalog details
end
Client->>Ingress: tools/list as independent request
Ingress->>DP: Forward supported MCP request
DP->>DP: Reverify and derive authorization key
DP->>DP: Enforce tools/list scope and compiled RBAC
alt Snapshot mapped and authorized
DP->>Cache: Read visible tools by authorization key
Cache-->>DP: inc and sum
DP-->>Client: tools/list result
else Missing, unmapped or denied
DP-->>Client: Authorization error without catalog details
end
Note over DP,Store: The shared store distributes compiled state
Note over DP: No live upstream call for discovery or aggregate lists
Note over Client,DP: initialize does not create required session state
Note over Client,DP: Client-supplied identity or routing metadata is untrusted
sequenceDiagram
autonumber
participant Client as Supported MCP Client
participant Ingress
participant DP as ContextForge External Dataplane
participant Cache as Local Cache
participant CPEX as Policy and CPEX
participant MCP as Selected Supported MCP Server
Client->>Ingress: tools/call name inc
Ingress->>DP: Forward supported MCP request
DP->>DP: Verify JWT, metadata and server route
DP->>DP: Derive authorization key from trusted context
DP->>Cache: Resolve inc under authorization key
Cache-->>DP: Backend mapping, protocol version and policy or missing
DP->>DP: Enforce tools/call scope and compiled RBAC
alt Tool mapped and authorized
DP->>CPEX: Run pre-call policy
CPEX-->>DP: Allow or modify request
DP->>DP: Adapt client protocol to backend protocol
opt Backend negotiation is required
DP->>MCP: Request-scoped initialize
MCP-->>DP: Initialize result
end
DP->>MCP: tools/call name inc
MCP-->>DP: Tool result
DP->>MCP: Close request-scoped connection
DP->>CPEX: Run post-call policy
CPEX-->>DP: Allow or modify result
DP-->>Client: Return version-appropriate tool result
else Missing, unmapped or denied
DP-->>Client: Authorization error with no upstream call
end
Note over DP,MCP: Exactly one backend is called
Note over DP,MCP: Client and backend versions are independently 2026-07-28 or 2025-11-25
Note over DP,MCP: No durable backend MCP session is required
Note over DP: Control Plane, DB and Redis are not on this result path
Note over Client,DP: Client-supplied identity or backend selection is untrusted
sequenceDiagram
autonumber
participant MCP as Supported MCP Server
participant CP as Control Plane Reconciler
participant DB as Control Plane DB
participant Store as Shared Config Store (Redis)
participant DP as ContextForge External Dataplane
participant Client as Supported MCP Client
CP->>MCP: Poll liveness and refresh discovery and lists
MCP-->>CP: Updated catalog
CP->>DB: Reconcile catalog changes
CP->>CP: Recompile affected snapshots
CP->>Store: Atomically publish revision N plus 1
Store-->>DP: Configuration revision available
DP->>Store: Load revision N plus 1
DP->>DP: Replace local cache atomically
Client->>DP: tools/list
DP-->>Client: Updated list from local snapshot
Note over DP,Client: Phase 4 owns MCP list-change notifications