Commit Graph

2115 Commits

Author SHA1 Message Date
Michael Bolin
a7263bbf97 Merge 022c5dc997 into sapling-pr-archive-bolinfest 2025-07-21 21:55:36 -07:00
Michael Bolin
022c5dc997 fix 2025-07-21 21:55:30 -07:00
Dylan
18b2b30841 [mcp-server] Add reply tool call (#1643)
## Summary
Adds a new mcp tool call, `codex-reply`, so we can continue existing
sessions. This is a first draft and does not yet support sessions from
previous processes.

## Testing
- [x] tested with mcp client
2025-07-21 21:01:56 -07:00
Michael Bolin
6567a14a3d merge commit for archive created by Sapling 2025-07-21 17:13:33 -07:00
Michael Bolin
50f38401d4 fix 2025-07-21 17:13:23 -07:00
Michael Bolin
3d8537b850 Merge 94f1a946ae into sapling-pr-archive-bolinfest 2025-07-21 17:09:11 -07:00
Michael Bolin
94f1a946ae fix 2025-07-21 17:08:58 -07:00
Michael Bolin
4ea6d54de9 Merge ac85a01ea7 into sapling-pr-archive-bolinfest 2025-07-21 10:27:44 -07:00
Michael Bolin
ac85a01ea7 fix: use PR_SET_PDEATHSIG so to ensure child processes are killed in a timely manner 2025-07-21 10:27:34 -07:00
Michael Bolin
d49d802b06 test: add integration test for MCP server (#1633)
This PR introduces a single integration test for `cargo mcp`, though it
also introduces a number of reusable components so that it should be
easier to introduce more integration tests going forward.

The new test is introduced in `codex-rs/mcp-server/tests/elicitation.rs`
and the reusable pieces are in `codex-rs/mcp-server/tests/common`.

The test itself verifies new functionality around elicitations
introduced in https://github.com/openai/codex/pull/1623 (and the fix
introduced in https://github.com/openai/codex/pull/1629) by doing the
following:

- starts a mock model provider with canned responses for
`/v1/chat/completions`
- starts the MCP server with a `config.toml` to use that model provider
(and `approval_policy = "untrusted"`)
- sends the `codex` tool call which causes the mock model provider to
request a shell call for `git init`
- the MCP server sends an elicitation to the client to approve the
request
- the client replies to the elicitation with `"approved"`
- the MCP server runs the command and re-samples the model, getting a
`"finish_reason": "stop"`
- in turn, the MCP server sends the final response to the original
`codex` tool call
- verifies that `git init` ran as expected

To test:

```
cargo test shell_command_approval_triggers_elicitation
```

In writing this test, I discovered that `ExecApprovalResponse` does not
conform to `ElicitResult`, so I added a TODO to fix that, since I think
that should be updated in a separate PR. As it stands, this PR does not
update any business logic, though it does make a number of members of
the `mcp-server` crate `pub` so they can be used in the test.

One additional learning from this PR is that
`std::process::Command::cargo_bin()` from the `assert_cmd` trait is only
available for `std::process::Command`, but we really want to use
`tokio::process::Command` so that everything is async and we can
leverage utilities like `tokio::time::timeout()`. The trick I came up
with was to use `cargo_bin()` to locate the program, and then to use
`std::process::Command::get_program()` when constructing the
`tokio::process::Command`.
2025-07-21 10:27:07 -07:00
Michael Bolin
f5d3cb0dd6 merge commit for archive created by Sapling 2025-07-20 20:09:58 -07:00
Michael Bolin
24a80cf9d7 fix: integration test for MCP server 2025-07-20 20:09:52 -07:00
Michael Bolin
12c516f7ba merge commit for archive created by Sapling 2025-07-20 19:56:42 -07:00
Michael Bolin
111bab0a61 fix: integration test for MCP server 2025-07-20 19:56:19 -07:00
Michael Bolin
d7e6ba42d8 merge commit for archive created by Sapling 2025-07-20 19:44:22 -07:00
Michael Bolin
4640946c05 fix: integration test for MCP server 2025-07-20 19:44:17 -07:00
Michael Bolin
547342b2e1 merge commit for archive created by Sapling 2025-07-20 19:41:26 -07:00
Michael Bolin
69bdec9824 fix: integration test for MCP server 2025-07-20 19:41:20 -07:00
Michael Bolin
0022eeeee5 merge commit for archive created by Sapling 2025-07-20 19:23:30 -07:00
Michael Bolin
78ad35a6a9 fix: integration test for MCP server 2025-07-20 19:23:05 -07:00
Michael Bolin
20d74a9562 merge commit for archive created by Sapling 2025-07-20 19:16:20 -07:00
Michael Bolin
cfd24302bb fix: integration test for MCP server 2025-07-20 19:16:15 -07:00
Michael Bolin
6c9a411cc8 merge commit for archive created by Sapling 2025-07-20 19:15:47 -07:00
Michael Bolin
58bcc91c7f fix: integration test for MCP server 2025-07-20 19:13:33 -07:00
Michael Bolin
62fe3fc4db Merge 96092108b1 into sapling-pr-archive-bolinfest 2025-07-20 17:42:23 -04:00
Michael Bolin
96092108b1 fix: integration test for MCP server 2025-07-20 14:42:17 -07:00
Michael Bolin
8a6c6cee88 fix: address review feedback on #1621 and #1623 (#1631)
- formalizes `ExecApprovalElicitRequestParams`
- adds some defensive logic when messages fail to parse
- fixes a typo in a comment
2025-07-20 14:42:11 -07:00
Michael Bolin
9bce460754 merge commit for archive created by Sapling 2025-07-20 14:37:13 -07:00
Michael Bolin
1a608d680b fix: integration test for MCP server 2025-07-20 14:36:51 -07:00
Michael Bolin
96343988f2 fix: address review feedback on #1621 and #1623 2025-07-20 14:36:51 -07:00
Gabriel Peal
8b590105de Don't drop sessions on elicitation responses (#1629) 2025-07-20 13:31:19 -04:00
Michael Bolin
e3827fcb43 Merge 900509d12c into sapling-pr-archive-bolinfest 2025-07-20 11:15:06 -04:00
Michael Bolin
900509d12c fix: address review feedback on #1621 and #1623 2025-07-20 11:14:52 -04:00
Michael Bolin
4c6c7addda merge commit for archive created by Sapling 2025-07-19 12:31:30 -04:00
Michael Bolin
45b0b67c10 fix: use PR_SET_PDEATHSIG so to ensure child processes are killed in a timely manner 2025-07-19 12:31:21 -04:00
Michael Bolin
adcad5b1de merge commit for archive created by Sapling 2025-07-19 12:01:21 -04:00
Michael Bolin
b9a18b9a24 fix: use PR_SET_PDEATHSIG so to ensure child processes are killed in a timely manner 2025-07-19 12:01:16 -04:00
Michael Bolin
e7741647bd merge commit for archive created by Sapling 2025-07-19 11:24:00 -04:00
Michael Bolin
0c9247556a fix: use PR_SET_PDEATHSIG so to ensure child processes are killed in a timely manner 2025-07-19 11:23:55 -04:00
Michael Bolin
34fbfe59c9 merge commit for archive created by Sapling 2025-07-19 11:17:14 -04:00
Michael Bolin
32767b7ee1 fix: use PR_SET_PDEATHSIG so to ensure child processes are killed in a timely manner 2025-07-19 11:17:09 -04:00
Michael Bolin
4f97301423 Merge 3d782880e3 into sapling-pr-archive-bolinfest 2025-07-19 11:12:13 -04:00
Michael Bolin
3d782880e3 fix: use PR_SET_PDEATHSIG so to ensure child processes are killed in a timely manner 2025-07-19 11:12:06 -04:00
Michael Bolin
018003e52f feat: leverage elicitations in the MCP server (#1623)
This updates the MCP server so that if it receives an
`ExecApprovalRequest` from the `Codex` session, it in turn sends an [MCP
elicitation](https://modelcontextprotocol.io/specification/draft/client/elicitation)
to the client to ask for the approval decision. Upon getting a response,
it forwards the client's decision via `Op::ExecApproval`.

Admittedly, we should be doing the same thing for
`ApplyPatchApprovalRequest`, but this is our first time experimenting
with elicitations, so I'm inclined to defer wiring that code path up
until we feel good about how this one works.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/1623).
* __->__ #1623
* #1622
* #1621
* #1620
2025-07-19 01:32:03 -04:00
Michael Bolin
d704b83b03 merge commit for archive created by Sapling 2025-07-19 01:08:05 -04:00
Michael Bolin
5724b3bf58 feat: leverage elicitations in the MCP server 2025-07-19 01:06:40 -04:00
Michael Bolin
170aa5f9ca Merge 7d7d3084bc into sapling-pr-archive-bolinfest 2025-07-19 00:31:28 -04:00
Michael Bolin
7d7d3084bc feat: leverage elicitations in the MCP server 2025-07-19 00:31:04 -04:00
Michael Bolin
11fd3123be chore: introduce OutgoingMessageSender (#1622)
Previous to this change, `MessageProcessor` had a
`tokio::sync::mpsc::Sender<JSONRPCMessage>` as an abstraction for server
code to send a message down to the MCP client. Because `Sender` is cheap
to `clone()`, it was straightforward to make it available to tasks
scheduled with `tokio::task::spawn()`.

This worked well when we were only sending notifications or responses
back down to the client, but we want to add support for sending
elicitations in #1623, which means that we need to be able to send
_requests_ to the client, and now we need a bit of centralization to
ensure all request ids are unique.

To that end, this PR introduces `OutgoingMessageSender`, which houses
the existing `Sender<OutgoingMessage>` as well as an `AtomicI64` to mint
out new, unique request ids. It has methods like `send_request()` and
`send_response()` so that callers do not have to deal with
`JSONRPCMessage` directly, as having to set the `jsonrpc` for each
message was a bit tedious (this cleans up `codex_tool_runner.rs` quite a
bit).

We do not have `OutgoingMessageSender` implement `Clone` because it is
important that the `AtomicI64` is shared across all users of
`OutgoingMessageSender`. As such, `Arc<OutgoingMessageSender>` must be
used instead, as it is frequently shared with new tokio tasks.

As part of this change, we update `message_processor.rs` to embrace
`await`, though we must be careful that no individual handler blocks the
main loop and prevents other messages from being handled.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/1622).
* #1623
* __->__ #1622
* #1621
* #1620
2025-07-19 00:30:56 -04:00
Michael Bolin
24c0c2985a Merge 4a70da083e into sapling-pr-archive-bolinfest 2025-07-19 00:18:31 -04:00