fix: change codex/sandbox-state/update from a notification to a request - #8142

Merged
bolinfest merged 1 commit into
mainfrom
pr8142
Dec 18, 2025
Merged

fix: change codex/sandbox-state/update from a notification to a request#8142
bolinfest merged 1 commit into
mainfrom
pr8142

Conversation

@bolinfest

@bolinfestbolinfest commented Dec 16, 2025

Copy link
Copy Markdown
Collaborator

Historically, accept_elicitation_for_prompt_rule() was flaky because we were using a notification to update the sandbox followed by a shell tool request that we expected to be subject to the new sandbox config, but because rmcp MCP servers delegate each incoming message to a new Tokio task, messages are not guaranteed to be processed in order, so sometimes the shell tool call would run before the notification was processed.

Prior to this PR, we relied on a generous sleep() between the notification and the request to reduce the change of the test flaking out.

This PR implements a proper fix, which is to use a request instead of a notification for the sandbox update so that we can wait for the response to the sandbox request before sending the request to the shell tool call. Previously, rmcp did not support custom requests, but I fixed that in modelcontextprotocol/rust-sdk#590, which made it into the 0.12.0 release (see #8288).

This PR updates shell-tool-mcp to expect "codex/sandbox-state/update" as a request instead of a notification and sends the appropriate ack. Note this behavior is tied to our custom codex/sandbox-state capability, which Codex honors as an MCP client, which is why core/src/mcp_connection_manager.rs had to be updated as part of this PR, as well.

This PR also updates the docs at shell-tool-mcp/README.md.

@bolinfest
bolinfest marked this pull request as draft December 16, 2025 22:39
bolinfest added a commit to bolinfest/rust-sdk that referenced this pull request Dec 16, 2025
modelcontextprotocol#580 and modelcontextprotocol#556 introduced support for custom notifications,
so this PR takes the next logical step and adds support for custom requests:
- Introduces `CustomRequest` and `CustomResult` model types, wires them into the client/server
request and result unions, and allows `ClientRequest::method()` to return the dynamic method
name.
- Implements serde and meta handling for `CustomRequest` so `_meta` is carried through
extensions; adds default `on_custom_request` handlers that return `METHOD_NOT_FOUND` unless
overridden.
- Updates JSON schema fixtures to include the new request/result shapes and `EmptyObject`
strictness.
- Adds tests for custom request roundtrips and end-to-end client↔server handling.
- Focused integration test in `crates/rmcp/tests/test_custom_request.rs`.
For additional testing, I used this locally to update Codex to use a custom
request instead of a custom notification so that it gets an "ack" from the MCP
server to ensure it has processed the update before sending more messages:
openai/codex#8142.
alexhancock pushed a commit to modelcontextprotocol/rust-sdk that referenced this pull request Dec 18, 2025
#580 and #556 introduced support for custom notifications,
so this PR takes the next logical step and adds support for custom requests:
- Introduces `CustomRequest` and `CustomResult` model types, wires them into the client/server
request and result unions, and allows `ClientRequest::method()` to return the dynamic method
name.
- Implements serde and meta handling for `CustomRequest` so `_meta` is carried through
extensions; adds default `on_custom_request` handlers that return `METHOD_NOT_FOUND` unless
overridden.
- Updates JSON schema fixtures to include the new request/result shapes and `EmptyObject`
strictness.
- Adds tests for custom request roundtrips and end-to-end client↔server handling.
- Focused integration test in `crates/rmcp/tests/test_custom_request.rs`.
For additional testing, I used this locally to update Codex to use a custom
request instead of a custom notification so that it gets an "ack" from the MCP
server to ensure it has processed the update before sending more messages:
openai/codex#8142.
bolinfest added a commit that referenced this pull request Dec 18, 2025
Version `0.12.0` includes
modelcontextprotocol/rust-sdk#590, which I will
use in #8142.
Changes:
- `rmcp::model::CustomClientNotification` was renamed to
`rmcp::model::CustomNotification`
- a bunch of types have a `meta` field now, but it is `Option`, so I
added `meta: None` to a bunch of things
@bolinfest
bolinfestforce-pushed the pr8142 branch 2 times, most recently from fd36082 to b6ec022CompareDecember 18, 2025 22:49
@bolinfest
bolinfest marked this pull request as ready for review December 18, 2025 23:20
@bolinfest
bolinfest merged commit 46baedd into mainDec 18, 2025
55 checks passed
@bolinfest
bolinfest deleted the pr8142 branch December 18, 2025 23:32
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Dec 18, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@bolinfest@gpeal
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

fix: change codex/sandbox-state/update from a notification to a request - #8142

Merged
bolinfest merged 1 commit into
mainfrom
pr8142
Dec 18, 2025
Merged

fix: change codex/sandbox-state/update from a notification to a request#8142
bolinfest merged 1 commit into
mainfrom
pr8142

Conversation

@bolinfest

@bolinfestbolinfest commented Dec 16, 2025

Copy link
Copy Markdown
Collaborator

Historically, accept_elicitation_for_prompt_rule() was flaky because we were using a notification to update the sandbox followed by a shell tool request that we expected to be subject to the new sandbox config, but because rmcp MCP servers delegate each incoming message to a new Tokio task, messages are not guaranteed to be processed in order, so sometimes the shell tool call would run before the notification was processed.

Prior to this PR, we relied on a generous sleep() between the notification and the request to reduce the change of the test flaking out.

This PR implements a proper fix, which is to use a request instead of a notification for the sandbox update so that we can wait for the response to the sandbox request before sending the request to the shell tool call. Previously, rmcp did not support custom requests, but I fixed that in modelcontextprotocol/rust-sdk#590, which made it into the 0.12.0 release (see #8288).

This PR updates shell-tool-mcp to expect "codex/sandbox-state/update" as a request instead of a notification and sends the appropriate ack. Note this behavior is tied to our custom codex/sandbox-state capability, which Codex honors as an MCP client, which is why core/src/mcp_connection_manager.rs had to be updated as part of this PR, as well.

This PR also updates the docs at shell-tool-mcp/README.md.

@bolinfest
bolinfest marked this pull request as draft December 16, 2025 22:39
bolinfest added a commit to bolinfest/rust-sdk that referenced this pull request Dec 16, 2025
modelcontextprotocol#580 and modelcontextprotocol#556 introduced support for custom notifications,
so this PR takes the next logical step and adds support for custom requests:
- Introduces `CustomRequest` and `CustomResult` model types, wires them into the client/server
request and result unions, and allows `ClientRequest::method()` to return the dynamic method
name.
- Implements serde and meta handling for `CustomRequest` so `_meta` is carried through
extensions; adds default `on_custom_request` handlers that return `METHOD_NOT_FOUND` unless
overridden.
- Updates JSON schema fixtures to include the new request/result shapes and `EmptyObject`
strictness.
- Adds tests for custom request roundtrips and end-to-end client↔server handling.
- Focused integration test in `crates/rmcp/tests/test_custom_request.rs`.
For additional testing, I used this locally to update Codex to use a custom
request instead of a custom notification so that it gets an "ack" from the MCP
server to ensure it has processed the update before sending more messages:
openai/codex#8142.
alexhancock pushed a commit to modelcontextprotocol/rust-sdk that referenced this pull request Dec 18, 2025
#580 and #556 introduced support for custom notifications,
so this PR takes the next logical step and adds support for custom requests:
- Introduces `CustomRequest` and `CustomResult` model types, wires them into the client/server
request and result unions, and allows `ClientRequest::method()` to return the dynamic method
name.
- Implements serde and meta handling for `CustomRequest` so `_meta` is carried through
extensions; adds default `on_custom_request` handlers that return `METHOD_NOT_FOUND` unless
overridden.
- Updates JSON schema fixtures to include the new request/result shapes and `EmptyObject`
strictness.
- Adds tests for custom request roundtrips and end-to-end client↔server handling.
- Focused integration test in `crates/rmcp/tests/test_custom_request.rs`.
For additional testing, I used this locally to update Codex to use a custom
request instead of a custom notification so that it gets an "ack" from the MCP
server to ensure it has processed the update before sending more messages:
openai/codex#8142.
bolinfest added a commit that referenced this pull request Dec 18, 2025
Version `0.12.0` includes
modelcontextprotocol/rust-sdk#590, which I will
use in #8142.
Changes:
- `rmcp::model::CustomClientNotification` was renamed to
`rmcp::model::CustomNotification`
- a bunch of types have a `meta` field now, but it is `Option`, so I
added `meta: None` to a bunch of things
@bolinfest
bolinfestforce-pushed the pr8142 branch 2 times, most recently from fd36082 to b6ec022CompareDecember 18, 2025 22:49
@bolinfest
bolinfest marked this pull request as ready for review December 18, 2025 23:20
@bolinfest
bolinfest merged commit 46baedd into mainDec 18, 2025
55 checks passed
@bolinfest
bolinfest deleted the pr8142 branch December 18, 2025 23:32
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Dec 18, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@bolinfest@gpeal
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix: change codex/sandbox-state/update from a notification to a request - #8142

Merged
bolinfest merged 1 commit into
mainfrom
pr8142
Dec 18, 2025
Merged

fix: change codex/sandbox-state/update from a notification to a request#8142
bolinfest merged 1 commit into
mainfrom
pr8142

Conversation

@bolinfest

@bolinfestbolinfest commented Dec 16, 2025

Copy link
Copy Markdown
Collaborator

Historically, accept_elicitation_for_prompt_rule() was flaky because we were using a notification to update the sandbox followed by a shell tool request that we expected to be subject to the new sandbox config, but because rmcp MCP servers delegate each incoming message to a new Tokio task, messages are not guaranteed to be processed in order, so sometimes the shell tool call would run before the notification was processed.

Prior to this PR, we relied on a generous sleep() between the notification and the request to reduce the change of the test flaking out.

This PR implements a proper fix, which is to use a request instead of a notification for the sandbox update so that we can wait for the response to the sandbox request before sending the request to the shell tool call. Previously, rmcp did not support custom requests, but I fixed that in modelcontextprotocol/rust-sdk#590, which made it into the 0.12.0 release (see #8288).

This PR updates shell-tool-mcp to expect "codex/sandbox-state/update" as a request instead of a notification and sends the appropriate ack. Note this behavior is tied to our custom codex/sandbox-state capability, which Codex honors as an MCP client, which is why core/src/mcp_connection_manager.rs had to be updated as part of this PR, as well.

This PR also updates the docs at shell-tool-mcp/README.md.

@bolinfest
bolinfest marked this pull request as draft December 16, 2025 22:39
bolinfest added a commit to bolinfest/rust-sdk that referenced this pull request Dec 16, 2025
modelcontextprotocol#580 and modelcontextprotocol#556 introduced support for custom notifications,
so this PR takes the next logical step and adds support for custom requests:
- Introduces `CustomRequest` and `CustomResult` model types, wires them into the client/server
request and result unions, and allows `ClientRequest::method()` to return the dynamic method
name.
- Implements serde and meta handling for `CustomRequest` so `_meta` is carried through
extensions; adds default `on_custom_request` handlers that return `METHOD_NOT_FOUND` unless
overridden.
- Updates JSON schema fixtures to include the new request/result shapes and `EmptyObject`
strictness.
- Adds tests for custom request roundtrips and end-to-end client↔server handling.
- Focused integration test in `crates/rmcp/tests/test_custom_request.rs`.
For additional testing, I used this locally to update Codex to use a custom
request instead of a custom notification so that it gets an "ack" from the MCP
server to ensure it has processed the update before sending more messages:
openai/codex#8142.
alexhancock pushed a commit to modelcontextprotocol/rust-sdk that referenced this pull request Dec 18, 2025
#580 and #556 introduced support for custom notifications,
so this PR takes the next logical step and adds support for custom requests:
- Introduces `CustomRequest` and `CustomResult` model types, wires them into the client/server
request and result unions, and allows `ClientRequest::method()` to return the dynamic method
name.
- Implements serde and meta handling for `CustomRequest` so `_meta` is carried through
extensions; adds default `on_custom_request` handlers that return `METHOD_NOT_FOUND` unless
overridden.
- Updates JSON schema fixtures to include the new request/result shapes and `EmptyObject`
strictness.
- Adds tests for custom request roundtrips and end-to-end client↔server handling.
- Focused integration test in `crates/rmcp/tests/test_custom_request.rs`.
For additional testing, I used this locally to update Codex to use a custom
request instead of a custom notification so that it gets an "ack" from the MCP
server to ensure it has processed the update before sending more messages:
openai/codex#8142.
bolinfest added a commit that referenced this pull request Dec 18, 2025
Version `0.12.0` includes
modelcontextprotocol/rust-sdk#590, which I will
use in #8142.
Changes:
- `rmcp::model::CustomClientNotification` was renamed to
`rmcp::model::CustomNotification`
- a bunch of types have a `meta` field now, but it is `Option`, so I
added `meta: None` to a bunch of things
@bolinfest
bolinfestforce-pushed the pr8142 branch 2 times, most recently from fd36082 to b6ec022CompareDecember 18, 2025 22:49
@bolinfest
bolinfest marked this pull request as ready for review December 18, 2025 23:20
@bolinfest
bolinfest merged commit 46baedd into mainDec 18, 2025
55 checks passed
@bolinfest
bolinfest deleted the pr8142 branch December 18, 2025 23:32
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Dec 18, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@bolinfest@gpeal
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix: change codex/sandbox-state/update from a notification to a request - #8142

Merged
bolinfest merged 1 commit into
mainfrom
pr8142
Dec 18, 2025
Merged

fix: change codex/sandbox-state/update from a notification to a request#8142
bolinfest merged 1 commit into
mainfrom
pr8142

Conversation

@bolinfest

@bolinfestbolinfest commented Dec 16, 2025

Copy link
Copy Markdown
Collaborator

Historically, accept_elicitation_for_prompt_rule() was flaky because we were using a notification to update the sandbox followed by a shell tool request that we expected to be subject to the new sandbox config, but because rmcp MCP servers delegate each incoming message to a new Tokio task, messages are not guaranteed to be processed in order, so sometimes the shell tool call would run before the notification was processed.

Prior to this PR, we relied on a generous sleep() between the notification and the request to reduce the change of the test flaking out.

This PR implements a proper fix, which is to use a request instead of a notification for the sandbox update so that we can wait for the response to the sandbox request before sending the request to the shell tool call. Previously, rmcp did not support custom requests, but I fixed that in modelcontextprotocol/rust-sdk#590, which made it into the 0.12.0 release (see #8288).

This PR updates shell-tool-mcp to expect "codex/sandbox-state/update" as a request instead of a notification and sends the appropriate ack. Note this behavior is tied to our custom codex/sandbox-state capability, which Codex honors as an MCP client, which is why core/src/mcp_connection_manager.rs had to be updated as part of this PR, as well.

This PR also updates the docs at shell-tool-mcp/README.md.

@bolinfest
bolinfest marked this pull request as draft December 16, 2025 22:39
bolinfest added a commit to bolinfest/rust-sdk that referenced this pull request Dec 16, 2025
modelcontextprotocol#580 and modelcontextprotocol#556 introduced support for custom notifications,
so this PR takes the next logical step and adds support for custom requests:
- Introduces `CustomRequest` and `CustomResult` model types, wires them into the client/server
request and result unions, and allows `ClientRequest::method()` to return the dynamic method
name.
- Implements serde and meta handling for `CustomRequest` so `_meta` is carried through
extensions; adds default `on_custom_request` handlers that return `METHOD_NOT_FOUND` unless
overridden.
- Updates JSON schema fixtures to include the new request/result shapes and `EmptyObject`
strictness.
- Adds tests for custom request roundtrips and end-to-end client↔server handling.
- Focused integration test in `crates/rmcp/tests/test_custom_request.rs`.
For additional testing, I used this locally to update Codex to use a custom
request instead of a custom notification so that it gets an "ack" from the MCP
server to ensure it has processed the update before sending more messages:
openai/codex#8142.
alexhancock pushed a commit to modelcontextprotocol/rust-sdk that referenced this pull request Dec 18, 2025
#580 and #556 introduced support for custom notifications,
so this PR takes the next logical step and adds support for custom requests:
- Introduces `CustomRequest` and `CustomResult` model types, wires them into the client/server
request and result unions, and allows `ClientRequest::method()` to return the dynamic method
name.
- Implements serde and meta handling for `CustomRequest` so `_meta` is carried through
extensions; adds default `on_custom_request` handlers that return `METHOD_NOT_FOUND` unless
overridden.
- Updates JSON schema fixtures to include the new request/result shapes and `EmptyObject`
strictness.
- Adds tests for custom request roundtrips and end-to-end client↔server handling.
- Focused integration test in `crates/rmcp/tests/test_custom_request.rs`.
For additional testing, I used this locally to update Codex to use a custom
request instead of a custom notification so that it gets an "ack" from the MCP
server to ensure it has processed the update before sending more messages:
openai/codex#8142.
bolinfest added a commit that referenced this pull request Dec 18, 2025
Version `0.12.0` includes
modelcontextprotocol/rust-sdk#590, which I will
use in #8142.
Changes:
- `rmcp::model::CustomClientNotification` was renamed to
`rmcp::model::CustomNotification`
- a bunch of types have a `meta` field now, but it is `Option`, so I
added `meta: None` to a bunch of things
@bolinfest
bolinfestforce-pushed the pr8142 branch 2 times, most recently from fd36082 to b6ec022CompareDecember 18, 2025 22:49
@bolinfest
bolinfest marked this pull request as ready for review December 18, 2025 23:20
@bolinfest
bolinfest merged commit 46baedd into mainDec 18, 2025
55 checks passed
@bolinfest
bolinfest deleted the pr8142 branch December 18, 2025 23:32
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Dec 18, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@bolinfest@gpeal
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

fix: change codex/sandbox-state/update from a notification to a request - #8142

Merged
bolinfest merged 1 commit into
mainfrom
pr8142
Dec 18, 2025
Merged

fix: change codex/sandbox-state/update from a notification to a request#8142
bolinfest merged 1 commit into
mainfrom
pr8142

Conversation

@bolinfest

@bolinfestbolinfest commented Dec 16, 2025

Copy link
Copy Markdown
Collaborator

Historically, accept_elicitation_for_prompt_rule() was flaky because we were using a notification to update the sandbox followed by a shell tool request that we expected to be subject to the new sandbox config, but because rmcp MCP servers delegate each incoming message to a new Tokio task, messages are not guaranteed to be processed in order, so sometimes the shell tool call would run before the notification was processed.

Prior to this PR, we relied on a generous sleep() between the notification and the request to reduce the change of the test flaking out.

This PR implements a proper fix, which is to use a request instead of a notification for the sandbox update so that we can wait for the response to the sandbox request before sending the request to the shell tool call. Previously, rmcp did not support custom requests, but I fixed that in modelcontextprotocol/rust-sdk#590, which made it into the 0.12.0 release (see #8288).

This PR updates shell-tool-mcp to expect "codex/sandbox-state/update" as a request instead of a notification and sends the appropriate ack. Note this behavior is tied to our custom codex/sandbox-state capability, which Codex honors as an MCP client, which is why core/src/mcp_connection_manager.rs had to be updated as part of this PR, as well.

This PR also updates the docs at shell-tool-mcp/README.md.

@bolinfest
bolinfest marked this pull request as draft December 16, 2025 22:39
bolinfest added a commit to bolinfest/rust-sdk that referenced this pull request Dec 16, 2025
modelcontextprotocol#580 and modelcontextprotocol#556 introduced support for custom notifications,
so this PR takes the next logical step and adds support for custom requests:
- Introduces `CustomRequest` and `CustomResult` model types, wires them into the client/server
request and result unions, and allows `ClientRequest::method()` to return the dynamic method
name.
- Implements serde and meta handling for `CustomRequest` so `_meta` is carried through
extensions; adds default `on_custom_request` handlers that return `METHOD_NOT_FOUND` unless
overridden.
- Updates JSON schema fixtures to include the new request/result shapes and `EmptyObject`
strictness.
- Adds tests for custom request roundtrips and end-to-end client↔server handling.
- Focused integration test in `crates/rmcp/tests/test_custom_request.rs`.
For additional testing, I used this locally to update Codex to use a custom
request instead of a custom notification so that it gets an "ack" from the MCP
server to ensure it has processed the update before sending more messages:
openai/codex#8142.
alexhancock pushed a commit to modelcontextprotocol/rust-sdk that referenced this pull request Dec 18, 2025
#580 and #556 introduced support for custom notifications,
so this PR takes the next logical step and adds support for custom requests:
- Introduces `CustomRequest` and `CustomResult` model types, wires them into the client/server
request and result unions, and allows `ClientRequest::method()` to return the dynamic method
name.
- Implements serde and meta handling for `CustomRequest` so `_meta` is carried through
extensions; adds default `on_custom_request` handlers that return `METHOD_NOT_FOUND` unless
overridden.
- Updates JSON schema fixtures to include the new request/result shapes and `EmptyObject`
strictness.
- Adds tests for custom request roundtrips and end-to-end client↔server handling.
- Focused integration test in `crates/rmcp/tests/test_custom_request.rs`.
For additional testing, I used this locally to update Codex to use a custom
request instead of a custom notification so that it gets an "ack" from the MCP
server to ensure it has processed the update before sending more messages:
openai/codex#8142.
bolinfest added a commit that referenced this pull request Dec 18, 2025
Version `0.12.0` includes
modelcontextprotocol/rust-sdk#590, which I will
use in #8142.
Changes:
- `rmcp::model::CustomClientNotification` was renamed to
`rmcp::model::CustomNotification`
- a bunch of types have a `meta` field now, but it is `Option`, so I
added `meta: None` to a bunch of things
@bolinfest
bolinfestforce-pushed the pr8142 branch 2 times, most recently from fd36082 to b6ec022CompareDecember 18, 2025 22:49
@bolinfest
bolinfest marked this pull request as ready for review December 18, 2025 23:20
@bolinfest
bolinfest merged commit 46baedd into mainDec 18, 2025
55 checks passed
@bolinfest
bolinfest deleted the pr8142 branch December 18, 2025 23:32
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Dec 18, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@bolinfest@gpeal
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix: change codex/sandbox-state/update from a notification to a request - #8142

Merged
bolinfest merged 1 commit into
mainfrom
pr8142
Dec 18, 2025
Merged

fix: change codex/sandbox-state/update from a notification to a request#8142
bolinfest merged 1 commit into
mainfrom
pr8142

Conversation

@bolinfest

@bolinfestbolinfest commented Dec 16, 2025

Copy link
Copy Markdown
Collaborator

Historically, accept_elicitation_for_prompt_rule() was flaky because we were using a notification to update the sandbox followed by a shell tool request that we expected to be subject to the new sandbox config, but because rmcp MCP servers delegate each incoming message to a new Tokio task, messages are not guaranteed to be processed in order, so sometimes the shell tool call would run before the notification was processed.

Prior to this PR, we relied on a generous sleep() between the notification and the request to reduce the change of the test flaking out.

This PR implements a proper fix, which is to use a request instead of a notification for the sandbox update so that we can wait for the response to the sandbox request before sending the request to the shell tool call. Previously, rmcp did not support custom requests, but I fixed that in modelcontextprotocol/rust-sdk#590, which made it into the 0.12.0 release (see #8288).

This PR updates shell-tool-mcp to expect "codex/sandbox-state/update" as a request instead of a notification and sends the appropriate ack. Note this behavior is tied to our custom codex/sandbox-state capability, which Codex honors as an MCP client, which is why core/src/mcp_connection_manager.rs had to be updated as part of this PR, as well.

This PR also updates the docs at shell-tool-mcp/README.md.

@bolinfest
bolinfest marked this pull request as draft December 16, 2025 22:39
bolinfest added a commit to bolinfest/rust-sdk that referenced this pull request Dec 16, 2025
modelcontextprotocol#580 and modelcontextprotocol#556 introduced support for custom notifications,
so this PR takes the next logical step and adds support for custom requests:
- Introduces `CustomRequest` and `CustomResult` model types, wires them into the client/server
request and result unions, and allows `ClientRequest::method()` to return the dynamic method
name.
- Implements serde and meta handling for `CustomRequest` so `_meta` is carried through
extensions; adds default `on_custom_request` handlers that return `METHOD_NOT_FOUND` unless
overridden.
- Updates JSON schema fixtures to include the new request/result shapes and `EmptyObject`
strictness.
- Adds tests for custom request roundtrips and end-to-end client↔server handling.
- Focused integration test in `crates/rmcp/tests/test_custom_request.rs`.
For additional testing, I used this locally to update Codex to use a custom
request instead of a custom notification so that it gets an "ack" from the MCP
server to ensure it has processed the update before sending more messages:
openai/codex#8142.
alexhancock pushed a commit to modelcontextprotocol/rust-sdk that referenced this pull request Dec 18, 2025
#580 and #556 introduced support for custom notifications,
so this PR takes the next logical step and adds support for custom requests:
- Introduces `CustomRequest` and `CustomResult` model types, wires them into the client/server
request and result unions, and allows `ClientRequest::method()` to return the dynamic method
name.
- Implements serde and meta handling for `CustomRequest` so `_meta` is carried through
extensions; adds default `on_custom_request` handlers that return `METHOD_NOT_FOUND` unless
overridden.
- Updates JSON schema fixtures to include the new request/result shapes and `EmptyObject`
strictness.
- Adds tests for custom request roundtrips and end-to-end client↔server handling.
- Focused integration test in `crates/rmcp/tests/test_custom_request.rs`.
For additional testing, I used this locally to update Codex to use a custom
request instead of a custom notification so that it gets an "ack" from the MCP
server to ensure it has processed the update before sending more messages:
openai/codex#8142.
bolinfest added a commit that referenced this pull request Dec 18, 2025
Version `0.12.0` includes
modelcontextprotocol/rust-sdk#590, which I will
use in #8142.
Changes:
- `rmcp::model::CustomClientNotification` was renamed to
`rmcp::model::CustomNotification`
- a bunch of types have a `meta` field now, but it is `Option`, so I
added `meta: None` to a bunch of things
@bolinfest
bolinfestforce-pushed the pr8142 branch 2 times, most recently from fd36082 to b6ec022CompareDecember 18, 2025 22:49
@bolinfest
bolinfest marked this pull request as ready for review December 18, 2025 23:20
@bolinfest
bolinfest merged commit 46baedd into mainDec 18, 2025
55 checks passed
@bolinfest
bolinfest deleted the pr8142 branch December 18, 2025 23:32
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Dec 18, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@bolinfest@gpeal
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix: change codex/sandbox-state/update from a notification to a request - #8142

Merged
bolinfest merged 1 commit into
mainfrom
pr8142
Dec 18, 2025
Merged

fix: change codex/sandbox-state/update from a notification to a request#8142
bolinfest merged 1 commit into
mainfrom
pr8142

Conversation

@bolinfest

@bolinfestbolinfest commented Dec 16, 2025

Copy link
Copy Markdown
Collaborator

Historically, accept_elicitation_for_prompt_rule() was flaky because we were using a notification to update the sandbox followed by a shell tool request that we expected to be subject to the new sandbox config, but because rmcp MCP servers delegate each incoming message to a new Tokio task, messages are not guaranteed to be processed in order, so sometimes the shell tool call would run before the notification was processed.

Prior to this PR, we relied on a generous sleep() between the notification and the request to reduce the change of the test flaking out.

This PR implements a proper fix, which is to use a request instead of a notification for the sandbox update so that we can wait for the response to the sandbox request before sending the request to the shell tool call. Previously, rmcp did not support custom requests, but I fixed that in modelcontextprotocol/rust-sdk#590, which made it into the 0.12.0 release (see #8288).

This PR updates shell-tool-mcp to expect "codex/sandbox-state/update" as a request instead of a notification and sends the appropriate ack. Note this behavior is tied to our custom codex/sandbox-state capability, which Codex honors as an MCP client, which is why core/src/mcp_connection_manager.rs had to be updated as part of this PR, as well.

This PR also updates the docs at shell-tool-mcp/README.md.

@bolinfest
bolinfest marked this pull request as draft December 16, 2025 22:39
bolinfest added a commit to bolinfest/rust-sdk that referenced this pull request Dec 16, 2025
modelcontextprotocol#580 and modelcontextprotocol#556 introduced support for custom notifications,
so this PR takes the next logical step and adds support for custom requests:
- Introduces `CustomRequest` and `CustomResult` model types, wires them into the client/server
request and result unions, and allows `ClientRequest::method()` to return the dynamic method
name.
- Implements serde and meta handling for `CustomRequest` so `_meta` is carried through
extensions; adds default `on_custom_request` handlers that return `METHOD_NOT_FOUND` unless
overridden.
- Updates JSON schema fixtures to include the new request/result shapes and `EmptyObject`
strictness.
- Adds tests for custom request roundtrips and end-to-end client↔server handling.
- Focused integration test in `crates/rmcp/tests/test_custom_request.rs`.
For additional testing, I used this locally to update Codex to use a custom
request instead of a custom notification so that it gets an "ack" from the MCP
server to ensure it has processed the update before sending more messages:
openai/codex#8142.
alexhancock pushed a commit to modelcontextprotocol/rust-sdk that referenced this pull request Dec 18, 2025
#580 and #556 introduced support for custom notifications,
so this PR takes the next logical step and adds support for custom requests:
- Introduces `CustomRequest` and `CustomResult` model types, wires them into the client/server
request and result unions, and allows `ClientRequest::method()` to return the dynamic method
name.
- Implements serde and meta handling for `CustomRequest` so `_meta` is carried through
extensions; adds default `on_custom_request` handlers that return `METHOD_NOT_FOUND` unless
overridden.
- Updates JSON schema fixtures to include the new request/result shapes and `EmptyObject`
strictness.
- Adds tests for custom request roundtrips and end-to-end client↔server handling.
- Focused integration test in `crates/rmcp/tests/test_custom_request.rs`.
For additional testing, I used this locally to update Codex to use a custom
request instead of a custom notification so that it gets an "ack" from the MCP
server to ensure it has processed the update before sending more messages:
openai/codex#8142.
bolinfest added a commit that referenced this pull request Dec 18, 2025
Version `0.12.0` includes
modelcontextprotocol/rust-sdk#590, which I will
use in #8142.
Changes:
- `rmcp::model::CustomClientNotification` was renamed to
`rmcp::model::CustomNotification`
- a bunch of types have a `meta` field now, but it is `Option`, so I
added `meta: None` to a bunch of things
@bolinfest
bolinfestforce-pushed the pr8142 branch 2 times, most recently from fd36082 to b6ec022CompareDecember 18, 2025 22:49
@bolinfest
bolinfest marked this pull request as ready for review December 18, 2025 23:20
@bolinfest
bolinfest merged commit 46baedd into mainDec 18, 2025
55 checks passed
@bolinfest
bolinfest deleted the pr8142 branch December 18, 2025 23:32
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Dec 18, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@bolinfest@gpeal
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

fix: change codex/sandbox-state/update from a notification to a request - #8142

Merged
bolinfest merged 1 commit into
mainfrom
pr8142
Dec 18, 2025
Merged

fix: change codex/sandbox-state/update from a notification to a request#8142
bolinfest merged 1 commit into
mainfrom
pr8142

Conversation

@bolinfest

@bolinfestbolinfest commented Dec 16, 2025

Copy link
Copy Markdown
Collaborator

Historically, accept_elicitation_for_prompt_rule() was flaky because we were using a notification to update the sandbox followed by a shell tool request that we expected to be subject to the new sandbox config, but because rmcp MCP servers delegate each incoming message to a new Tokio task, messages are not guaranteed to be processed in order, so sometimes the shell tool call would run before the notification was processed.

Prior to this PR, we relied on a generous sleep() between the notification and the request to reduce the change of the test flaking out.

This PR implements a proper fix, which is to use a request instead of a notification for the sandbox update so that we can wait for the response to the sandbox request before sending the request to the shell tool call. Previously, rmcp did not support custom requests, but I fixed that in modelcontextprotocol/rust-sdk#590, which made it into the 0.12.0 release (see #8288).

This PR updates shell-tool-mcp to expect "codex/sandbox-state/update" as a request instead of a notification and sends the appropriate ack. Note this behavior is tied to our custom codex/sandbox-state capability, which Codex honors as an MCP client, which is why core/src/mcp_connection_manager.rs had to be updated as part of this PR, as well.

This PR also updates the docs at shell-tool-mcp/README.md.

@bolinfest
bolinfest marked this pull request as draft December 16, 2025 22:39
bolinfest added a commit to bolinfest/rust-sdk that referenced this pull request Dec 16, 2025
modelcontextprotocol#580 and modelcontextprotocol#556 introduced support for custom notifications,
so this PR takes the next logical step and adds support for custom requests:
- Introduces `CustomRequest` and `CustomResult` model types, wires them into the client/server
request and result unions, and allows `ClientRequest::method()` to return the dynamic method
name.
- Implements serde and meta handling for `CustomRequest` so `_meta` is carried through
extensions; adds default `on_custom_request` handlers that return `METHOD_NOT_FOUND` unless
overridden.
- Updates JSON schema fixtures to include the new request/result shapes and `EmptyObject`
strictness.
- Adds tests for custom request roundtrips and end-to-end client↔server handling.
- Focused integration test in `crates/rmcp/tests/test_custom_request.rs`.
For additional testing, I used this locally to update Codex to use a custom
request instead of a custom notification so that it gets an "ack" from the MCP
server to ensure it has processed the update before sending more messages:
openai/codex#8142.
alexhancock pushed a commit to modelcontextprotocol/rust-sdk that referenced this pull request Dec 18, 2025
#580 and #556 introduced support for custom notifications,
so this PR takes the next logical step and adds support for custom requests:
- Introduces `CustomRequest` and `CustomResult` model types, wires them into the client/server
request and result unions, and allows `ClientRequest::method()` to return the dynamic method
name.
- Implements serde and meta handling for `CustomRequest` so `_meta` is carried through
extensions; adds default `on_custom_request` handlers that return `METHOD_NOT_FOUND` unless
overridden.
- Updates JSON schema fixtures to include the new request/result shapes and `EmptyObject`
strictness.
- Adds tests for custom request roundtrips and end-to-end client↔server handling.
- Focused integration test in `crates/rmcp/tests/test_custom_request.rs`.
For additional testing, I used this locally to update Codex to use a custom
request instead of a custom notification so that it gets an "ack" from the MCP
server to ensure it has processed the update before sending more messages:
openai/codex#8142.
bolinfest added a commit that referenced this pull request Dec 18, 2025
Version `0.12.0` includes
modelcontextprotocol/rust-sdk#590, which I will
use in #8142.
Changes:
- `rmcp::model::CustomClientNotification` was renamed to
`rmcp::model::CustomNotification`
- a bunch of types have a `meta` field now, but it is `Option`, so I
added `meta: None` to a bunch of things
@bolinfest
bolinfestforce-pushed the pr8142 branch 2 times, most recently from fd36082 to b6ec022CompareDecember 18, 2025 22:49
@bolinfest
bolinfest marked this pull request as ready for review December 18, 2025 23:20
@bolinfest
bolinfest merged commit 46baedd into mainDec 18, 2025
55 checks passed
@bolinfest
bolinfest deleted the pr8142 branch December 18, 2025 23:32
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Dec 18, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@bolinfest@gpeal