mirror of
https://github.com/openai/codex.git
synced 2026-04-29 08:56:38 +00:00
[mcp] Support MCP Apps part 3 - Add mcp tool call support. (#17364)
- [x] Add a new app-server method so that MCP Apps can call their own MCP server directly.
This commit is contained in:
@@ -129,12 +129,7 @@ pub fn generate_ts_with_options(
|
||||
}
|
||||
|
||||
// Ensure our header is present on all TS files (root + subdirs like v2/).
|
||||
let mut ts_files = Vec::new();
|
||||
let should_collect_ts_files =
|
||||
options.ensure_headers || (options.run_prettier && prettier.is_some());
|
||||
if should_collect_ts_files {
|
||||
ts_files = ts_files_in_recursive(out_dir)?;
|
||||
}
|
||||
let ts_files = ts_files_in_recursive(out_dir)?;
|
||||
|
||||
if options.ensure_headers {
|
||||
let worker_count = thread::available_parallelism()
|
||||
@@ -179,6 +174,8 @@ pub fn generate_ts_with_options(
|
||||
}
|
||||
}
|
||||
|
||||
trim_trailing_whitespace_in_ts_files(&ts_files)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1942,6 +1939,32 @@ fn ts_files_in_recursive(dir: &Path) -> Result<Vec<PathBuf>> {
|
||||
Ok(files)
|
||||
}
|
||||
|
||||
fn trim_trailing_whitespace_in_ts_files(paths: &[PathBuf]) -> Result<()> {
|
||||
for path in paths {
|
||||
let content = fs::read_to_string(path)
|
||||
.with_context(|| format!("Failed to read {}", path.display()))?;
|
||||
let trimmed = trim_trailing_line_whitespace(&content);
|
||||
if trimmed != content {
|
||||
fs::write(path, trimmed)
|
||||
.with_context(|| format!("Failed to write {}", path.display()))?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn trim_trailing_line_whitespace(content: &str) -> String {
|
||||
let mut trimmed = String::with_capacity(content.len());
|
||||
for line in content.split_inclusive('\n') {
|
||||
if let Some(line_without_newline) = line.strip_suffix('\n') {
|
||||
trimmed.push_str(line_without_newline.trim_end_matches([' ', '\t']));
|
||||
trimmed.push('\n');
|
||||
} else {
|
||||
trimmed.push_str(line.trim_end_matches([' ', '\t']));
|
||||
}
|
||||
}
|
||||
trimmed
|
||||
}
|
||||
|
||||
/// Generate an index.ts file that re-exports all generated types.
|
||||
/// This allows consumers to import all types from a single file.
|
||||
fn generate_index_ts(out_dir: &Path) -> Result<PathBuf> {
|
||||
|
||||
@@ -470,6 +470,11 @@ client_request_definitions! {
|
||||
response: v2::McpResourceReadResponse,
|
||||
},
|
||||
|
||||
McpServerToolCall => "mcpServer/tool/call" {
|
||||
params: v2::McpServerToolCallParams,
|
||||
response: v2::McpServerToolCallResponse,
|
||||
},
|
||||
|
||||
WindowsSandboxSetupStart => "windowsSandbox/setupStart" {
|
||||
params: v2::WindowsSandboxSetupStartParams,
|
||||
response: v2::WindowsSandboxSetupStartResponse,
|
||||
|
||||
@@ -29,6 +29,7 @@ use codex_protocol::config_types::WebSearchMode;
|
||||
use codex_protocol::config_types::WebSearchToolConfig;
|
||||
use codex_protocol::items::AgentMessageContent as CoreAgentMessageContent;
|
||||
use codex_protocol::items::TurnItem as CoreTurnItem;
|
||||
use codex_protocol::mcp::CallToolResult as CoreMcpCallToolResult;
|
||||
use codex_protocol::mcp::Resource as McpResource;
|
||||
pub use codex_protocol::mcp::ResourceContent as McpResourceContent;
|
||||
use codex_protocol::mcp::ResourceTemplate as McpResourceTemplate;
|
||||
@@ -2017,6 +2018,48 @@ pub struct McpResourceReadResponse {
|
||||
pub contents: Vec<McpResourceContent>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct McpServerToolCallParams {
|
||||
pub thread_id: String,
|
||||
pub server: String,
|
||||
pub tool: String,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
pub arguments: Option<JsonValue>,
|
||||
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
pub meta: Option<JsonValue>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct McpServerToolCallResponse {
|
||||
pub content: Vec<JsonValue>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
pub structured_content: Option<JsonValue>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
pub is_error: Option<bool>,
|
||||
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
pub meta: Option<JsonValue>,
|
||||
}
|
||||
|
||||
impl From<CoreMcpCallToolResult> for McpServerToolCallResponse {
|
||||
fn from(result: CoreMcpCallToolResult) -> Self {
|
||||
Self {
|
||||
content: result.content,
|
||||
structured_content: result.structured_content,
|
||||
is_error: result.is_error,
|
||||
meta: result.meta,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
|
||||
@@ -5,6 +5,7 @@ use crate::ServerRequest;
|
||||
use crate::export::GENERATED_TS_HEADER;
|
||||
use crate::export::filter_experimental_ts_tree;
|
||||
use crate::export::generate_index_ts_tree;
|
||||
use crate::export::trim_trailing_line_whitespace;
|
||||
use crate::protocol::common::visit_client_response_types;
|
||||
use crate::protocol::common::visit_server_response_types;
|
||||
use anyhow::Context;
|
||||
@@ -68,6 +69,9 @@ pub fn generate_typescript_schema_fixture_subtree_for_tests() -> Result<BTreeMap
|
||||
|
||||
filter_experimental_ts_tree(&mut files)?;
|
||||
generate_index_ts_tree(&mut files);
|
||||
for content in files.values_mut() {
|
||||
*content = trim_trailing_line_whitespace(content);
|
||||
}
|
||||
|
||||
Ok(files
|
||||
.into_iter()
|
||||
|
||||
Reference in New Issue
Block a user