Commit Graph

21 Commits

  • chore: unify cargo versions (#4044)
    Unify cargo versions at root
  • fix: add check to ensure output of generate_mcp_types.py matches codex-rs/mcp-types/src/lib.rs (#3450)
    As a follow-up to https://github.com/openai/codex/pull/3439, this adds a
    CI job to ensure the codegen script has to be updated in order to change
    `codex-rs/mcp-types/src/lib.rs`.
  • fix: ensure output of codex-rs/mcp-types/generate_mcp_types.py matches codex-rs/mcp-types/src/lib.rs (#3439)
    https://github.com/openai/codex/pull/3395 updated `mcp-types/src/lib.rs`
    by hand, but that file is generated code that is produced by
    `mcp-types/generate_mcp_types.py`. Unfortunately, we do not have
    anything in CI to verify this right now, but I will address that in a
    subsequent PR.
    
    #3395 ended up introducing a change that added a required field when
    deserializing `InitializeResult`, breaking Codex when used as an MCP
    client, so the quick fix in #3436 was to make the new field `Optional`
    with `skip_serializing_if = "Option::is_none"`, but that did not address
    the problem that `mcp-types/generate_mcp_types.py` and
    `mcp-types/src/lib.rs` are out of sync.
    
    This PR gets things back to where they are in sync. It removes the
    custom `mcp_types::McpClientInfo` type that was added to
    `mcp-types/src/lib.rs` and forces us to use the generated
    `mcp_types::Implementation` type. Though this PR also updates
    `generate_mcp_types.py` to generate the additional `user_agent:
    Optional<String>` field on `Implementation` so that we can continue to
    specify it when Codex operates as an MCP server.
    
    However, this also requires us to specify `user_agent: None` when Codex
    operates as an MCP client.
    
    We may want to introduce our own `InitializeResult` type that is
    specific to when we run as a server to avoid this in the future, but my
    immediate goal is just to get things back in sync.
  • Make user_agent optional (#3436)
    # External (non-OpenAI) Pull Request Requirements
    
    Currently, mcp server fail to start with:
    ```
    🖐  MCP client for `<CLIENT>` failed to start: missing field `user_agent`
    ````
    
    It isn't clear to me yet why this is happening. My understanding is that
    this struct is simply added as a new field to the response but this
    should fix it until I figure out the full story here.
    
    <img width="714" height="262" alt="CleanShot 2025-09-10 at 13 58 59"
    src="https://github.com/user-attachments/assets/946b1313-5c1c-43d3-8ae8-ecc3de3406fc"
    />
  • Set a user agent suffix when used as a mcp server (#3395)
    This automatically adds a user agent suffix whenever the CLI is used as
    a MCP server
  • Generate more typescript types and return conversation id with ConversationSummary (#3219)
    This PR does multiple things that are necessary for conversation resume
    to work from the extension. I wanted to make sure everything worked so
    these changes wound up in one PR:
    1. Generate more ts types
    2. Resume rollout history files rather than create a new one every time
    it is resumed so you don't see a duplicate conversation in history for
    every resume. Chatted with @aibrahim-oai to verify this
    3. Return conversation_id in conversation summaries
    4. [Cleanup] Use serde and strong types for a lot of the rollout file
    parsing
  • test: faster test execution in codex-core (#2633)
    this dramatically improves time to run `cargo test -p codex-core` (~25x
    speedup).
    
    before:
    ```
    cargo test -p codex-core  35.96s user 68.63s system 19% cpu 8:49.80 total
    ```
    
    after:
    ```
    cargo test -p codex-core  5.51s user 8.16s system 63% cpu 21.407 total
    ```
    
    both tests measured "hot", i.e. on a 2nd run with no filesystem changes,
    to exclude compile times.
    
    approach inspired by [Delete Cargo Integration
    Tests](https://matklad.github.io/2021/02/27/delete-cargo-integration-tests.html),
    we move all test cases in tests/ into a single suite in order to have a
    single binary, as there is significant overhead for each test binary
    executed, and because test execution is only parallelized with a single
    binary.
  • chore: add TS annotation to generated mcp-types (#2424)
    Adds the `TS` annotation from https://crates.io/crates/ts-rs to all
    types to facilitate codegen.
    
    ---
    [//]: # (BEGIN SAPLING FOOTER)
    Stack created with [Sapling](https://sapling-scm.com). Best reviewed
    with [ReviewStack](https://reviewstack.dev/openai/codex/pull/2424).
    * __->__ #2424
    * #2423
  • Added allow-expect-in-tests / allow-unwrap-in-tests (#2328)
    This PR:
    * Added the clippy.toml to configure allowable expect / unwrap usage in
    tests
    * Removed as many expect/allow lines as possible from tests
    * moved a bunch of allows to expects where possible
    
    Note: in integration tests, non `#[test]` helper functions are not
    covered by this so we had to leave a few lingering `expect(expect_used`
    checks around
  • Auto format toml (#1745)
    Add recommended extension and configure it to auto format prompt.
  • 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
  • chore: support MCP schema 2025-06-18 (#1621)
    This updates the schema in `generate_mcp_types.py` from `2025-03-26` to
    `2025-06-18`, regenerates `mcp-types/src/lib.rs`, and then updates all
    the code that uses `mcp-types` to honor the changes.
    
    Ran
    
    ```
    npx @modelcontextprotocol/inspector just codex mcp
    ```
    
    and verified that I was able to invoke the `codex` tool, as expected.
    
    
    ---
    [//]: # (BEGIN SAPLING FOOTER)
    Stack created with [Sapling](https://sapling-scm.com). Best reviewed
    with [ReviewStack](https://reviewstack.dev/openai/codex/pull/1621).
    * #1623
    * #1622
    * __->__ #1621
  • codex-rs: make tool calls prettier (#1211)
    This PR overhauls how active tool calls and completed tool calls are
    displayed:
    
    1. More use of colour to indicate success/failure and distinguish
    between components like tool name+arguments
    2. Previously, the entire `CallToolResult` was serialized to JSON and
    pretty-printed. Now, we extract each individual `CallToolResultContent`
    and print those
    1. The previous solution was wasting space by unnecessarily showing
    details of the `CallToolResult` struct to users, without formatting the
    actual tool call results nicely
    2. We're now able to show users more information from tool results in
    less space, with nicer formatting when tools return JSON results
    
    ### Before:
    
    <img width="1251" alt="Screenshot 2025-06-03 at 11 24 26"
    src="https://github.com/user-attachments/assets/5a58f222-219c-4c53-ace7-d887194e30cf"
    />
    
    ### After:
    
    <img width="1265" alt="image"
    src="https://github.com/user-attachments/assets/99fe54d0-9ebe-406a-855b-7aa529b91274"
    />
    
    ## Future Work
    
    1. Integrate image tool result handling better. We should be able to
    display images even if they're not the first `CallToolResultContent`
    2. Users should have some way to view the full version of truncated tool
    results
    3. It would be nice to add some left padding for tool results, make it
    more clear that they are results. This is doable, just a little fiddly
    due to the way `first_visible_line` scrolling works
    4. There's almost certainly a better way to format JSON than "all on 1
    line with spaces to make Ratatui wrapping work". But I think that works
    OK for now.
  • Disallow expect via lints (#865)
    Adds `expect()` as a denied lint. Same deal applies with `unwrap()`
    where we now need to put `#[expect(...` on ones that we legit want. Took
    care to enable `expect()` in test contexts.
    
    # Tests
    
    ```
    cargo fmt
    cargo clippy --all-features --all-targets --no-deps -- -D warnings
    cargo test
    ```
  • Workspace lints and disallow unwrap (#855)
    Sets submodules to use workspace lints. Added denying unwrap as a
    workspace level lint, which found a couple of cases where we could have
    propagated errors. Also manually labeled ones that were fine by my eye.
  • Update submodules version to come from the workspace (#850)
    Tie the version of submodules to the workspace version.
  • Update cargo to 2024 edition (#842)
    Some effects of this change:
    - New formatting changes across many files. No functionality changes
    should occur from that.
    - Calls to `set_env` are considered unsafe, since this only happens in
    tests we wrap them in `unsafe` blocks
  • feat: introduce mcp-server crate (#792)
    This introduces the `mcp-server` crate, which contains a barebones MCP
    server that provides an `echo` tool that echoes the user's request back
    to them.
    
    To test it out, I launched
    [modelcontextprotocol/inspector](https://github.com/modelcontextprotocol/inspector)
    like so:
    
    ```
    mcp-server$ npx @modelcontextprotocol/inspector cargo run --
    ```
    
    and opened up `http://127.0.0.1:6274` in my browser:
    
    
    ![image](https://github.com/user-attachments/assets/83fc55d4-25c2-4497-80cd-e9702283ff93)
    
    I also had to make a small fix to `mcp-types`, adding
    `#[serde(untagged)]` to a number of `enum`s.
  • fix: mcp-types serialization wasn't quite working (#791)
    While creating a basic MCP server in
    https://github.com/openai/codex/pull/792, I discovered a number of bugs
    with the initial `mcp-types` crate that I needed to fix in order to
    implement the server.
    
    For example, I discovered that when serializing a message, `"jsonrpc":
    "2.0"` was not being included.
    
    I changed the codegen so that the field is added as:
    
    ```rust
        #[serde(rename = "jsonrpc", default = "default_jsonrpc")]
        pub jsonrpc: String,
    ```
    
    This ensures that the field is serialized as `"2.0"`, though the field
    still has to be assigned, which is tedious. I may experiment with
    `Default` or something else in the future. (I also considered creating a
    custom serializer, but I'm not sure it's worth the trouble.)
    
    While here, I also added `MCP_SCHEMA_VERSION` and `JSONRPC_VERSION` as
    `pub const`s for the crate.
    
    I also discovered that MCP rejects sending `null` for optional fields,
    so I had to add `#[serde(skip_serializing_if = "Option::is_none")]` on
    `Option` fields.
    
    ---
    [//]: # (BEGIN SAPLING FOOTER)
    Stack created with [Sapling](https://sapling-scm.com). Best reviewed
    with [ReviewStack](https://reviewstack.dev/openai/codex/pull/791).
    * #792
    * __->__ #791
  • feat: introduce mcp-types crate (#787)
    This adds our own `mcp-types` crate to our Cargo workspace. We vendor in
    the
    [`2025-03-26/schema.json`](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/05f204513641c05bd78d056791af99c6c84520fa/schema/2025-03-26/schema.json)
    from the MCP repo and introduce a `generate_mcp_types.py` script to
    codegen the `lib.rs` from the JSON schema.
    
    Test coverage is currently light, but I plan to refine things as we
    start making use of this crate.
    
    And yes, I am aware that
    https://github.com/modelcontextprotocol/rust-sdk exists, though the
    published https://crates.io/crates/rmcp appears to be a competing
    effort. While things are up in the air, it seems better for us to
    control our own version of this code.
    
    Incidentally, Codex did a lot of the work for this PR. I told it to
    never edit `lib.rs` directly and instead to update
    `generate_mcp_types.py` and then re-run it to update `lib.rs`. It
    followed these instructions and once things were working end-to-end, I
    iteratively asked for changes to the tests until the API looked
    reasonable (and the code worked). Codex was responsible for figuring out
    what to do to `generate_mcp_types.py` to achieve the requested test/API
    changes.