Skip to content

design: add MCP client proxy design doc - #2

Closed
R-Lawton wants to merge 4 commits into
mainfrom
design/mcp-client-proxy
Closed

design: add MCP client proxy design doc#2
R-Lawton wants to merge 4 commits into
mainfrom
design/mcp-client-proxy

Conversation

@R-Lawton

@R-Lawton R-Lawton commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Defines the proxy architecture for MCP Inspector-like functionality in the console plugin
  • Proxy lives in the developer-portal-controller (shared backend for both console plugin and RHDH)
  • Covers gateway discovery, auth passthrough, session management, and multi-gateway support

Key decisions

  • Custom proxy needed because MCP servers don't enable CORS and ConsolePlugin spec.proxy is static (can't handle dynamic multi-gateway)
  • Proxy discovers gateways from MCPGatewayExtension CRs and routes MCP requests to the correct gateway
  • Auth tokens are passed through to the gateway — proxy never stores or validates them
  • Session management is stateless in the proxy — frontend holds the Mcp-Session-Id
  • Dev preview scope: tools (list, call), prompts (list, get)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Documentation
    • Added design documentation for an MCP client proxy.
    • Defined gateway discovery, endpoint resolution and readiness reporting.
    • Documented supported MCP request forwarding, authentication pass-through and session handling.
    • Included security considerations and potential future enhancements.

Defines the proxy architecture for MCP Inspector-like functionality
in the console plugin. The proxy lives in the developer-portal-controller
and handles gateway discovery, auth passthrough, session management,
and multi-gateway support.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

Signed-off-by: R-Lawton <rlawton@redhat.com>
@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@R-Lawton, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 3 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4dce9b0c-bc58-4575-a0d5-8d213342cbce

📥 Commits

Reviewing files that changed from the base of the PR and between dfecbd6 and 24f030d.

📒 Files selected for processing (1)
  • docs/design/mcp-client-proxy.md
📝 Walkthrough

Walkthrough

Adds a design document for an MCP client proxy that discovers MCPGatewayExtension resources, resolves gateway endpoints, exposes listing and forwarding APIs, and passes authentication and session headers through to gateways.

Changes

MCP client proxy

Layer / File(s) Summary
Proxy API and protocol design
docs/design/mcp-client-proxy.md
Defines cluster-wide gateway discovery, endpoint resolution, GET /gateways, MCP request forwarding, authentication and session passthrough, security considerations, and future extensions.

Estimated code review effort: 1 (Trivial) | ~5 minutes

Poem

A rabbit sketched gateways in lines neat and bright,
Mapping each endpoint by day and by night.
Tokens pass onward, sessions hop too,
MCP calls find the gateways they’re due.
Thump, thump—the proxy design is in view!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Clear and specific: it names the new MCP client proxy design document, which matches the main change.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch design/mcp-client-proxy

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

R-Lawton added 2 commits July 17, 2026 12:01
Add accurate JSON-RPC request and response examples for all MCP
operations (initialize, notifications/initialized, tools/list,
tools/call, prompts/list, prompts/get) matching the MCP Gateway's
actual protocol version (2025-03-26) and response formats.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

Signed-off-by: R-Lawton <rlawton@redhat.com>
Replace verbose MCP request/response examples with a link to the
MCP specification. Simplify goals section. Remove redundant MCP
operations table.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

Signed-off-by: R-Lawton <rlawton@redhat.com>
@R-Lawton
R-Lawton marked this pull request as ready for review July 17, 2026 14:52

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/design/mcp-client-proxy.md`:
- Around line 123-125: The MCP client/session handling flow should automatically
re-initialize when a session-bearing request receives a 404. Update the
frontend/client logic to clear the in-memory Mcp-Session-Id, send a fresh
InitializeRequest without that header, replace the stored ID with the new
session ID, and retry within a bounded limit while preserving the existing error
response when retries are exhausted.
- Line 100: Update the MCP specification link in the proxy documentation to use
the canonical URL https://modelcontextprotocol.io/specification/2025-03-26/,
while leaving the MCP Gateway docs link unchanged.
- Around line 32-39: The endpoint derivation documentation must use the
controller-managed internal host rather than constructing a host from the
Gateway name and class. Document that the proxy selects http:// or https://
based on the referenced listener protocol, while preserving spec.privateHost as
a verbatim endpoint override.
- Around line 72-102: Update the MCP protocol and proxy-flow documentation to
clarify that the implementation supports a gateway-specific JSON-only subset,
including its handling of notifications/initialized and responses.
Alternatively, document and require forwarding the frontend Accept header,
upstream status, Content-Type, and SSE response payloads, including 202 no-body
responses for notifications. Ensure the stated operations and response contract
match the implemented behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: fe6a51be-bbbe-42da-ba5d-dc2d47ed1668

📥 Commits

Reviewing files that changed from the base of the PR and between 20ad410 and dfecbd6.

📒 Files selected for processing (1)
  • docs/design/mcp-client-proxy.md

Comment on lines +32 to +39
The proxy watches MCPGatewayExtension CRs across the cluster using the k8s API. For each CR, it resolves the gateway endpoint:

1. Read `spec.targetRef` on the MCPGatewayExtension — this points to a Gateway resource with a `name`, `namespace`, and `sectionName` (listener)
2. Read the referenced Gateway resource to get the `gatewayClassName` and the listener's port
3. If `spec.privateHost` is set on the MCPGatewayExtension, use that as the endpoint
4. Otherwise, derive the endpoint: `<gateway-name>-<gatewayClassName>.<gateway-namespace>.svc.cluster.local:<port>`

The proxy maintains a map of MCPGatewayExtension (namespace + name) → gateway endpoint. When CRs are created, updated, or deleted, the map is updated. No console restarts are needed.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n 'privateHost|gatewayClassName|cluster\.local|listener.*protocol' .

Repository: Kuadrant/mcp-gateway-console-plugin

Length of output: 579


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== docs/design/mcp-client-proxy.md (lines 1-140) ==\n'
cat -n docs/design/mcp-client-proxy.md | sed -n '1,140p'

printf '\n== search for gateway Service/endpoint references ==\n'
rg -n 'gatewayClassName|privateHost|svc\.cluster\.local|listener.*protocol|HTTPS|HTTP|Streamable|MCPGatewayExtension' docs . --glob '!**/node_modules/**'

Repository: Kuadrant/mcp-gateway-console-plugin

Length of output: 12582


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== docs/design/mcp-client-proxy.md (lines 1-220) ==\n'
cat -n docs/design/mcp-client-proxy.md | sed -n '1,220p'

printf '\n== related docs and references ==\n'
rg -n 'MCPGatewayExtension|privateHost|gatewayClassName|Streamable HTTP|SSE|session|404' docs . --glob '!**/node_modules/**' --glob '!**/.git/**'

Repository: Kuadrant/mcp-gateway-console-plugin

Length of output: 20175


🌐 Web query:

MCPGatewayExtension privateHost gatewayClassName service name scheme listener protocol kuadrant docs

💡 Result:

In the Kuadrant MCP Gateway documentation, the MCPGatewayExtension resource is used to enable MCP protocol support on a Kubernetes Gateway [1][2]. Key configuration details for your inquiry include: MCPGatewayExtension privateHost The privateHost field in the MCPGatewayExtension specification is used to override the internal host address utilized for hair-pinning requests back through the gateway [1][3]. By default, this value is computed as -istio-..svc.cluster.local:, where the port is derived from the targeted Gateway listener [1][4][3]. If the targeted listener uses the HTTPS protocol, the default address is prefixed with https://; otherwise, it defaults to http:// [1][5][3]. You can set this field explicitly to use a different host, port, or scheme (e.g., https://my-gw:443), and the provided value is honored verbatim [1][6][3]. gatewayClassName and Service Mapping The MCPGatewayExtension targets a specific Gateway resource via the targetRef field [1][7]. The controller reads the Gateway's gatewayClassName and configuration to manage the broker/router deployment [6][4]. While gatewayClassName is a property of the Gateway itself rather than the MCPGatewayExtension, it dictates the underlying Gateway API provider (such as Istio or OpenShift) that the MCP Gateway must interact with [6][3]. The controller also automatically manages a service (typically named mcp-gateway) in the same namespace as the MCPGatewayExtension, which acts as the broker for MCP traffic [4][2]. Listener Protocol and Scheme The MCPGatewayExtension requires a sectionName that identifies a specific listener on the target Gateway [1][6][7]. The controller inspects this listener to determine the port and protocol (HTTP/HTTPS) [1][6]. For successful operation, the listener's protocol influences both the public address configuration and the internal hair-pinning scheme [8][4][5]. If your environment requires specific handling for HTTPS listeners—such as using an HTTP listener on a different port for internal hair-pinning—you can explicitly configure the privateHost field to point to that specific address [5][3].

Citations:


Document the actual internal endpoint shape and scheme. <gateway-name>-<gatewayClassName>... is not the published default here; use the controller-managed internal host instead, and derive http:// vs https:// from the listener protocol. Keep spec.privateHost as a verbatim override.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/design/mcp-client-proxy.md` around lines 32 - 39, The endpoint
derivation documentation must use the controller-managed internal host rather
than constructing a host from the Gateway name and class. Document that the
proxy selects http:// or https:// based on the referenced listener protocol,
while preserving spec.privateHost as a verbatim endpoint override.

Comment on lines +72 to +102
1. The frontend sends a POST with:
- Body: a JSON-RPC payload (e.g., `{"jsonrpc":"2.0","method":"tools/list","id":1}`)
- `Authorization` header: the user's auth token (if provided)
- `Mcp-Session-Id` header: the MCP session ID (if an active session exists)
- `Content-Type: application/json`

2. The proxy:
- Parses the namespace and name from the URL
- Looks up the gateway endpoint from its map
- Creates a new HTTP POST request to `<gateway-endpoint>/mcp`
- Copies the body from the frontend request
- Copies the `Authorization` header as-is
- Copies the `Mcp-Session-Id` header if present
- Sets `Content-Type: application/json`
- Sends this request to the gateway

3. The gateway processes the request through its full stack:
- AuthPolicy validates the `Authorization` token (if configured)
- ext_proc router parses the JSON-RPC method, manages sessions, routes tool calls to the correct upstream MCP server
- Broker handles initialize, tools/list, prompts/list, prompts/get

4. The proxy:
- Reads the gateway's response
- Copies the `Mcp-Session-Id` response header back to the frontend
- Returns the JSON response body to the frontend

### MCP protocol

The proxy forwards standard MCP Streamable HTTP requests. For the full protocol specification, see the [MCP specification](https://spec.modelcontextprotocol.io/specification/2025-03-26/) and the [MCP Gateway docs](https://docs.kuadrant.io).

The operations in scope are: `initialize`, `notifications/initialized`, `tools/list`, `tools/call`, `prompts/list`, and `prompts/get`. All are JSON-RPC over POST, all return JSON responses.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
curl -fsSL https://modelcontextprotocol.io/specification/2025-03-26/basic/transports |
  rg -n 'Accept|202 Accepted|text/event-stream|Mcp-Session-Id'

Repository: Kuadrant/mcp-gateway-console-plugin

Length of output: 50392


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== docs/design/mcp-client-proxy.md (around lines 72-102) =="
sed -n '72,102p' docs/design/mcp-client-proxy.md | cat -n

echo
echo "== spec excerpts for Streamable HTTP =="
tmp=$(mktemp)
curl -fsSL https://modelcontextprotocol.io/specification/2025-03-26/basic/transports > "$tmp"

# Pull only the headings and the lines around the relevant transport requirements.
rg -n -C 2 'Accept: application/json, text/event-stream|202 Accepted|text/event-stream|notifications/initialized|Streamable HTTP|Listening for Messages from the Server|Sending Messages to the Server' "$tmp" | head -n 200
rm -f "$tmp"

Repository: Kuadrant/mcp-gateway-console-plugin

Length of output: 50392


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== docs/design/mcp-client-proxy.md lines 72-102 =="
sed -n '72,102p' docs/design/mcp-client-proxy.md | cat -n

echo
echo "== file size =="
wc -l docs/design/mcp-client-proxy.md

Repository: Kuadrant/mcp-gateway-console-plugin

Length of output: 2141


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from urllib.request import urlopen
import re

url = "https://modelcontextprotocol.io/specification/2025-03-26/basic/transports"
html = urlopen(url, timeout=20).read().decode("utf-8", "replace")

# crude text extraction: strip scripts/styles and tags
html = re.sub(r'(?is)<script.*?</script>', ' ', html)
html = re.sub(r'(?is)<style.*?</style>', ' ', html)
text = re.sub(r'(?s)<[^>]+>', '\n', html)
text = re.sub(r'\n{3,}', '\n\n', text)

needles = [
    "Accept: application/json, text/event-stream",
    "202 Accepted",
    "text/event-stream",
    "notifications/initialized",
    "Listening for Messages from the Server",
    "Sending Messages to the Server",
    "Streamable HTTP",
]
for needle in needles:
    print(f"\n== {needle} ==")
    for m in re.finditer(re.escape(needle), text):
        start = max(0, m.start() - 300)
        end = min(len(text), m.end() + 500)
        snippet = text[start:end].replace("\n", " ")
        print(snippet)
        break
PY

Repository: Kuadrant/mcp-gateway-console-plugin

Length of output: 2767


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== mentions in docs/design/mcp-client-proxy.md =="
rg -n -i 'sse|event-stream|202 accepted|Accept:|Streamable HTTP|JSON response|notification|notifications/initialized|Mcp-Session-Id' docs/design/mcp-client-proxy.md

echo
echo "== nearby context around any hits =="
for n in $(rg -n -i 'sse|event-stream|202 accepted|Accept:|Streamable HTTP|JSON response|notification|notifications/initialized|Mcp-Session-Id' docs/design/mcp-client-proxy.md | cut -d: -f1 | head -n 10); do
  start=$((n>8 ? n-8 : 1))
  end=$((n+8))
  echo "--- lines $start-$end ---"
  sed -n "${start},${end}p" docs/design/mcp-client-proxy.md
done

Repository: Kuadrant/mcp-gateway-console-plugin

Length of output: 11219


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== mentions in docs/design/mcp-client-proxy.md =="
rg -n -i 'sse|event-stream|202 accepted|Accept:|Streamable HTTP|JSON response|notification|notifications/initialized|Mcp-Session-Id' docs/design/mcp-client-proxy.md

echo
echo "== broader repo mentions of Streamable HTTP / SSE =="
rg -n -i 'Streamable HTTP|text/event-stream|202 Accepted|notifications/initialized|Accept: application/json, text/event-stream' docs

Repository: Kuadrant/mcp-gateway-console-plugin

Length of output: 2898


🏁 Script executed:

#!/bin/bash
set -euo pipefail

for log in /tmp/coderabbit-shell-logs/shell-output-0ldTsA /tmp/coderabbit-shell-logs/shell-output-65FbWO /tmp/coderabbit-shell-logs/shell-output-B3Q9Zo /tmp/coderabbit-shell-logs/shell-output-eYvaLz /tmp/coderabbit-shell-logs/shell-output-orUmAm /tmp/coderabbit-shell-logs/shell-output-ochVIm; do
  [ -f "$log" ] || continue
  echo "== $log =="
  rg -n -C 2 'Accept: application/json, text/event-stream|202 Accepted|text/event-stream|notifications/initialized|Streamable HTTP|request-bearing POST|notification-only POST' "$log" | head -n 80 || true
  echo
done

Repository: Kuadrant/mcp-gateway-console-plugin

Length of output: 50392


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from urllib.request import urlopen
import ssl, re

url = "https://modelcontextprotocol.io/specification/2025-03-26/basic/transports"
ctx = ssl._create_unverified_context()
html = urlopen(url, context=ctx, timeout=20).read().decode("utf-8", "replace")

# Strip scripts/styles and tags to text
html = re.sub(r'(?is)<script.*?</script>', ' ', html)
html = re.sub(r'(?is)<style.*?</style>', ' ', html)
text = re.sub(r'(?s)<[^>]+>', '\n', html)
text = re.sub(r'\n{3,}', '\n\n', text)

needles = [
    "Accept: application/json, text/event-stream",
    "202 Accepted",
    "text/event-stream",
    "notifications/initialized",
    "Streamable HTTP",
]
for needle in needles:
    print(f"\n== {needle} ==")
    m = re.search(re.escape(needle), text)
    if not m:
        print("NOT FOUND")
        continue
    start = max(0, m.start() - 250)
    end = min(len(text), m.end() + 500)
    print(text[start:end].replace("\n", " "))
PY

Repository: Kuadrant/mcp-gateway-console-plugin

Length of output: 1889


Document the Streamable HTTP response contract. The proxy is described as “standard MCP Streamable HTTP”, but notifications/initialized is notification-only and the protocol allows 202 Accepted/no body plus Accept: application/json, text/event-stream and SSE responses for request-bearing POSTs. Either call out this as a gateway-specific JSON-only subset, or forward Accept, upstream status, Content-Type, and SSE payloads.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/design/mcp-client-proxy.md` around lines 72 - 102, Update the MCP
protocol and proxy-flow documentation to clarify that the implementation
supports a gateway-specific JSON-only subset, including its handling of
notifications/initialized and responses. Alternatively, document and require
forwarding the frontend Accept header, upstream status, Content-Type, and SSE
response payloads, including 202 no-body responses for notifications. Ensure the
stated operations and response contract match the implemented behavior.

Comment thread docs/design/mcp-client-proxy.md Outdated
Comment on lines +123 to +125
Each user gets their own session with each gateway. User A connecting to gateway-team-a has a different session than user B connecting to the same gateway, or user A connecting to gateway-team-b. The proxy doesn't track any of this — it just copies the `Mcp-Session-Id` header from responses and onto subsequent requests. It never decodes, validates, or stores the value.

If the gateway returns a 404 (session expired or invalid), the proxy passes it back to the frontend. The user must manually reconnect — the proxy does not automatically re-initialize sessions.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
curl -fsSL https://modelcontextprotocol.io/specification/2025-03-26/basic/transports |
  rg -n '404 Not Found|new.*InitializeRequest|new session'

Repository: Kuadrant/mcp-gateway-console-plugin

Length of output: 50392


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== docs/design/mcp-client-proxy.md (around lines 110-135) ==\n'
sed -n '110,135p' docs/design/mcp-client-proxy.md

printf '\n== spec excerpts for 2025-03-26 transports ==\n'
python3 - <<'PY'
import re, urllib.request
url = 'https://modelcontextprotocol.io/specification/2025-03-26/basic/transports'
html = urllib.request.urlopen(url, timeout=30).read().decode('utf-8', 'replace')
for pat in [
    r'404[^<\n]{0,200}',
    r'new session[^<\n]{0,200}',
    r'InitializeRequest[^<\n]{0,200}',
    r'expired[^<\n]{0,200}',
    r'invalid[^<\n]{0,200}',
]:
    print(f'\n-- {pat} --')
    seen = set()
    for m in re.finditer(pat, html, flags=re.I):
        snippet = re.sub(r'\s+', ' ', html[max(0, m.start()-120):m.end()+180])
        if snippet in seen:
            continue
        seen.add(snippet)
        print(snippet[:400])
        if len(seen) >= 5:
            break
PY

Repository: Kuadrant/mcp-gateway-console-plugin

Length of output: 4719


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
import re, ssl, urllib.request

url = 'https://modelcontextprotocol.io/specification/2025-03-26/basic/transports'
ctx = ssl._create_unverified_context()
html = urllib.request.urlopen(url, context=ctx, timeout=30).read().decode('utf-8', 'replace')

patterns = [
    r'404[^<\n]{0,300}',
    r'new session[^<\n]{0,300}',
    r'InitializeRequest[^<\n]{0,300}',
    r're-initialize[^<\n]{0,300}',
    r'reinitiali[sz]e[^<\n]{0,300}',
    r'session expired[^<\n]{0,300}',
    r'invalid[^<\n]{0,300}',
    r'Mcp-Session-Id[^<\n]{0,300}',
]
for pat in patterns:
    print(f'\n-- {pat} --')
    count = 0
    for m in re.finditer(pat, html, flags=re.I):
        snippet = re.sub(r'\s+', ' ', html[max(0, m.start()-180):m.end()+260])
        print(snippet[:700])
        count += 1
        if count >= 3:
            break
PY

Repository: Kuadrant/mcp-gateway-console-plugin

Length of output: 7265


🏁 Script executed:

#!/bin/bash
set -euo pipefail

curl -kfsSL 'https://modelcontextprotocol.io/specification/2025-03-26/basic/transports' |
  tr '\r' '\n' |
  rg -n -C 4 -i 'Mcp-Session-Id|404|re-?initiali[sz]e|session expired|invalid session|InitializeRequest|new session'

Repository: Kuadrant/mcp-gateway-console-plugin

Length of output: 50392


Re-initialise automatically on 404. MCP requires a fresh InitializeRequest without Mcp-Session-Id after a 404 on a session-bearing request, so manual reconnect is non-compliant. The frontend/client should own the automatic session reset and swap the in-memory ID with bounded retry behaviour.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/design/mcp-client-proxy.md` around lines 123 - 125, The MCP
client/session handling flow should automatically re-initialize when a
session-bearing request receives a 404. Update the frontend/client logic to
clear the in-memory Mcp-Session-Id, send a fresh InitializeRequest without that
header, replace the stored ID with the new session ID, and retry within a
bounded limit while preserving the existing error response when retries are
exhausted.

Add note about HTTP/HTTPS scheme handling in gateway discovery.
Fix MCP spec URL to canonical modelcontextprotocol.io domain.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

Signed-off-by: R-Lawton <rlawton@redhat.com>
@R-Lawton

Copy link
Copy Markdown
Contributor Author

Moved to Kuadrant/kuadrant-console-plugin#674

@R-Lawton R-Lawton closed this Jul 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant