mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
Complete MCP 2026 client support (#35725)
## What changed - Drive multi-round `tools/call` and `resources/read` requests through `input_required` responses, preserving opaque request state and elicitation metadata across JSON, SSE, and stdio transports. - Decode modern discovery and elicitation result shapes while retaining legacy initialization, elicitation defaults, and discovery fallback behavior. - Apply the 8 MiB modern-protocol response limit to JSON, SSE events, and stdio messages, and reject executor stream recovery when output sequence gaps would corrupt the protocol stream. ## Testing Added integration coverage for discovery, multi-round requests, legacy fallbacks, message limits, stdio launchers, SSE responses, session recovery, and executor output recovery. GitOrigin-RevId: d26a08883a2825e8ce2408ac498114b33859225e
This commit is contained in:
1 parent
be2e4afcd7
commit
f2bee854a7
13 files changed
+2352
-39
No files matched your search
@@ -356,11 +356,24 @@ impl ExecutorProcessTransport {
|
||||
.await
|
||||
.map_err(io::Error::other)?;
|
||||
for chunk in response.chunks {
|
||||
let expected_seq = self.last_seq.saturating_add(1);
|
||||
if chunk.seq > expected_seq {
|
||||
return Err(self.close_for_lost_output(expected_seq, chunk.seq));
|
||||
}
|
||||
self.push_process_output_if_new(chunk);
|
||||
if self.closed {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
// Process reads include output chunks but not the sequenced `Exited`
|
||||
// and `Closed` events. Account for those terminal events without
|
||||
// allowing an evicted output chunk to be silently spliced into MCP.
|
||||
let terminal_event_count = u64::from(response.exited) + u64::from(response.closed);
|
||||
let next_output_seq = response.next_seq.saturating_sub(terminal_event_count);
|
||||
let expected_seq = self.last_seq.saturating_add(1);
|
||||
if next_output_seq > expected_seq {
|
||||
return Err(self.close_for_lost_output(expected_seq, next_output_seq));
|
||||
}
|
||||
self.last_seq = self.last_seq.max(response.next_seq.saturating_sub(1));
|
||||
if let Some(message) = response.failure {
|
||||
warn!(
|
||||
@@ -374,6 +387,18 @@ impl ExecutorProcessTransport {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn close_for_lost_output(&mut self, expected_seq: u64, received_seq: u64) -> io::Error {
|
||||
self.stdout.clear();
|
||||
self.stderr.clear();
|
||||
self.closed = true;
|
||||
io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
format!(
|
||||
"remote MCP server output stream lost process events: expected sequence {expected_seq}, received {received_seq}"
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fn push_process_output_if_new(&mut self, chunk: ProcessOutputChunk) {
|
||||
if !self.should_accept_seq(chunk.seq) {
|
||||
return;
|
||||
|
||||
Reference in new issue
Block a user