Skip to content

fixes #118 session id difference between curl to mcp server directly …#119

Merged
stevehu merged 9 commits into
masterfrom
issue118
Jun 13, 2026
Merged

fixes #118 session id difference between curl to mcp server directly …#119
stevehu merged 9 commits into
masterfrom
issue118

Conversation

@stevehu

@stevehu stevehu commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

…vs light-gateway mcp rotuer

Copilot AI 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.

Pull request overview

This PR implements gateway-managed MCP sessions in light-pingora so the gateway can issue its own frontend mcp-session-id, map it to backend MCP session IDs per target, and properly tear down backend sessions—addressing the session-id mismatch between calling an MCP server directly vs via the light-gateway MCP router (fixes #118).

Changes:

  • Added an in-memory frontend session store with a 30-minute idle timeout, validation on non-initialize methods, and DELETE /mcp session teardown.
  • Implemented backend MCP session initialization (initialize + notifications/initialized), per-frontend/per-target backend session reuse, and backend session termination on purge/delete.
  • Updated MCP router design docs and expanded tests to cover session requirements, backend session mapping/reuse, and teardown.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
frameworks/light-pingora/src/mcp.rs Adds frontend session issuance/validation, backend MCP session mapping & lazy initialization, DELETE teardown, idle expiry purge, and expanded test coverage.
docs/src/design/mcp-router.md Updates the design/status to reflect the implemented in-memory session store, lazy expiry purge, and backend session mapping/teardown behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread frameworks/light-pingora/src/mcp.rs
Comment thread frameworks/light-pingora/src/mcp.rs
@stevehu

stevehu commented Jun 13, 2026

Copy link
Copy Markdown
Contributor Author

Reviewed PR #119 comments. There are two Copilot comments, and both were valid, so I patched them locally.

In light-fabric/frameworks/light-pingora/src/mcp.rs:1242, backend MCP session teardown now sends both mcp-session-id and mcp-protocol-version.

In light-fabric/frameworks/light-pingora/src/mcp.rs:1892, 405 Method Not Allowed now advertises Allow: POST, DELETE since DELETE /mcp is supported.

I also updated the existing tests to assert both behaviors.

Copilot AI 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.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

Comment thread frameworks/light-pingora/src/mcp.rs
Comment thread frameworks/light-pingora/src/mcp.rs
Comment thread frameworks/light-pingora/src/mcp.rs Outdated

Copilot AI 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.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comment thread frameworks/light-pingora/src/mcp.rs Outdated
Comment thread frameworks/light-pingora/src/mcp.rs Outdated

Copilot AI 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.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

Comment thread frameworks/light-pingora/src/mcp.rs Outdated
Comment thread frameworks/light-pingora/src/mcp.rs Outdated
Comment thread frameworks/light-pingora/src/mcp.rs Outdated
@stevehu

stevehu commented Jun 13, 2026

Copy link
Copy Markdown
Contributor Author

What changed in light-fabric/frameworks/light-pingora/src/mcp.rs:23:

  • Replaced the frontend session store’s std::sync::Mutex with tokio::sync::Mutex.
  • Session-bound responses now use the stored negotiated mcp-protocol-version, including tools/list, tools/call, and notifications.
  • Expired session purge now removes sessions synchronously but offloads backend MCP DELETE cleanup to a background task.
  • Added regression coverage for session-bound protocol headers.

Copilot AI 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.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comment thread frameworks/light-pingora/src/mcp.rs Outdated
Comment thread frameworks/light-pingora/src/mcp.rs Outdated
@stevehu

stevehu commented Jun 13, 2026

Copy link
Copy Markdown
Contributor Author
  • DELETE /mcp now removes the frontend session and returns 202 without waiting for backend MCP session teardown; backend DELETE calls run in the background.
  • Lazy expired-session purge is now throttled to once per 60s instead of scanning the whole session map on every POST/DELETE.
  • If the total session limit or per-client limit is reached, initialization forces an expired-session purge before rejecting the new session.
  • Added tests for forced purge on both total store limit and per-client limit.

Copilot AI 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.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comment thread frameworks/light-pingora/src/mcp.rs Outdated
Comment on lines +2019 to +2025
let mut outbound = outbound_headers(headers)?;
if !outbound.contains_key(ACCEPT) {
outbound.insert(
ACCEPT,
HeaderValue::from_static("application/json, text/event-stream"),
);
}
Comment thread frameworks/light-pingora/src/mcp.rs Outdated
Comment on lines +752 to +755
let client_sessions = sessions
.values()
.filter(|session| session.client_key == client_key)
.count();
@stevehu

stevehu commented Jun 13, 2026

Copy link
Copy Markdown
Contributor Author
  • Backend MCP calls now force Accept: application/json, so initialize, notifications/initialized, and backend tools/call do not inherit client SSE preferences.
  • Replaced the O(n) per-client session scan with an indexed McpSessionStore that tracks client_key counts alongside the session map.
  • Session insert/remove/expiry purge now maintain that count index consistently.
  • Added test assertions that proxied MCP backend requests send only JSON Accept.

@stevehu stevehu requested a review from Copilot June 13, 2026 02:35

Copilot AI 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.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comment on lines +1451 to +1467
async fn terminate_backend_session(&self, backend_session: McpBackendSession) {
let Some(session_id) = backend_session.session_id.as_deref() else {
return;
};
let mut headers = HeaderMap::new();
let Ok(value) = HeaderValue::from_str(session_id) else {
return;
};
headers.insert(HeaderName::from_static(MCP_SESSION_ID_HEADER), value);
if let Ok(value) = HeaderValue::from_str(backend_session.protocol_version.as_str()) {
headers.insert(HeaderName::from_static(MCP_PROTOCOL_VERSION_HEADER), value);
}
if let Err(error) = self
.client
.delete(backend_session.target_url.as_str())
.headers(headers)
.send()
Comment thread frameworks/light-pingora/src/mcp.rs Outdated
Comment on lines +2087 to +2090
} else if !outbound.contains_key(MCP_PROTOCOL_VERSION_HEADER) {
let value = HeaderValue::from_static(DEFAULT_PROTOCOL_VERSION);
outbound.insert(HeaderName::from_static(MCP_PROTOCOL_VERSION_HEADER), value);
}
@stevehu

stevehu commented Jun 13, 2026

Copy link
Copy Markdown
Contributor Author
  • Backend MCP sessions now retain the sanitized agent headers used during initialization.
    • Backend session teardown now uses backend_headers(...), so DELETE includes Authorization and other allowed context headers plus mcp-session-id and mcp-protocol-version.
    • Simplified backend_headers protocol-version insertion to remove the dead contains_key branch.
    • Added test coverage that backend DELETE receives the stored Authorization header.

Copilot AI 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.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

Comment thread frameworks/light-pingora/src/mcp.rs Outdated
Comment thread frameworks/light-pingora/src/mcp.rs Outdated
Comment thread frameworks/light-pingora/src/mcp.rs
@stevehu

stevehu commented Jun 13, 2026

Copy link
Copy Markdown
Contributor Author

Change made: aliased Tokio’s mutex as AsyncMutex in frameworks/light-pingora/src/mcp.rs, then updated the runtime session fields and constructor initializers. The test module can keep
using std::sync::Mutex without name collision.

Copilot AI 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.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

@stevehu stevehu merged commit 3ae69e0 into master Jun 13, 2026
1 check passed
@stevehu stevehu deleted the issue118 branch June 13, 2026 02:59
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.

2 participants