Files
llmx/codex-rs/mcp-client/src/main.rs

44 lines
1.4 KiB
Rust
Raw Normal View History

feat: initial McpClient for Rust (#822) This PR introduces an initial `McpClient` that we will use to give Codex itself programmatic access to foreign MCPs. This does not wire it up in Codex itself yet, but the new `mcp-client` crate includes a `main.rs` for basic testing for now. Manually tested by sending a `tools/list` request to Codex's own MCP server: ``` codex-rs$ cargo build codex-rs$ cargo run --bin codex-mcp-client ./target/debug/codex-mcp-server { "tools": [ { "description": "Run a Codex session. Accepts configuration parameters matching the Codex Config struct.", "inputSchema": { "properties": { "approval-policy": { "description": "Execution approval policy expressed as the kebab-case variant name (`unless-allow-listed`, `auto-edit`, `on-failure`, `never`).", "enum": [ "auto-edit", "unless-allow-listed", "on-failure", "never" ], "type": "string" }, "cwd": { "description": "Working directory for the session. If relative, it is resolved against the server process's current working directory.", "type": "string" }, "disable-response-storage": { "description": "Disable server-side response storage.", "type": "boolean" }, "model": { "description": "Optional override for the model name (e.g. \"o3\", \"o4-mini\")", "type": "string" }, "prompt": { "description": "The *initial user prompt* to start the Codex conversation.", "type": "string" }, "sandbox-permissions": { "description": "Sandbox permissions using the same string values accepted by the CLI (e.g. \"disk-write-cwd\", \"network-full-access\").", "items": { "enum": [ "disk-full-read-access", "disk-write-cwd", "disk-write-platform-user-temp-folder", "disk-write-platform-global-temp-folder", "disk-full-write-access", "network-full-access" ], "type": "string" }, "type": "array" } }, "required": [ "prompt" ], "type": "object" }, "name": "codex" } ] } ```
2025-05-05 12:52:55 -07:00
//! Simple command-line utility to exercise `McpClient`.
//!
//! Example usage:
//!
//! ```bash
//! cargo run -p codex-mcp-client -- `codex-mcp-server`
//! ```
//!
//! Any additional arguments after the first one are forwarded to the spawned
//! program. The utility connects, issues a `tools/list` request and prints the
//! server's response as pretty JSON.
use anyhow::Context;
use anyhow::Result;
use codex_mcp_client::McpClient;
use mcp_types::ListToolsRequestParams;
#[tokio::main]
async fn main() -> Result<()> {
// Collect command-line arguments excluding the program name itself.
let cmd_args: Vec<String> = std::env::args().skip(1).collect();
if cmd_args.is_empty() || cmd_args[0] == "--help" || cmd_args[0] == "-h" {
eprintln!("Usage: mcp-client <program> [args..]\n\nExample: mcp-client codex-mcp-server");
std::process::exit(1);
}
// Spawn the subprocess and connect the client.
let client = McpClient::new_stdio_client(cmd_args.clone())
.await
.with_context(|| format!("failed to spawn subprocess: {:?}", cmd_args))?;
// Issue `tools/list` request (no params).
let tools = client
.list_tools(None::<ListToolsRequestParams>)
.await
.context("tools/list request failed")?;
// Print the result in a human readable form.
println!("{}", serde_json::to_string_pretty(&tools)?);
Ok(())
}