Files
codex/codex-rs/memories/mcp/src/schema.rs
jif-oai f20f8a719e memories/mcp: generate tool schemas with schemars (#21012)
## Why

The memories MCP server currently keeps handwritten JSON Schema beside
the Rust types that actually serialize and deserialize the tool
payloads:
[`schema.rs`](2f5c06a29c/codex-rs/memories/mcp/src/schema.rs (L4-L133)),
[`server.rs`](2f5c06a29c/codex-rs/memories/mcp/src/server.rs (L44-L75)),
and
[`backend.rs`](2f5c06a29c/codex-rs/memories/mcp/src/backend.rs (L41-L117)).
That duplicates the tool contract and makes schema drift easier as the
API evolves.

## What changed

- derive `JsonSchema` for the memories tool arguments, responses, and
nested response types
- replace the handwritten schema builders with shared `schemars`
generation
- preserve the existing wire shape while generating schemas, including
nullable output `Option` fields and non-nullable optional input fields
- wire the `list`, `read`, and `search` tools to the generated schemas

## Verification

- CI pending
2026-05-04 18:40:17 +02:00

43 lines
1.3 KiB
Rust

use rmcp::model::JsonObject;
use schemars::JsonSchema;
use schemars::r#gen::SchemaSettings;
pub(crate) fn input_schema_for<T: JsonSchema>() -> JsonObject {
schema_for::<T>(/*option_add_null_type*/ false)
}
pub(crate) fn output_schema_for<T: JsonSchema>() -> JsonObject {
schema_for::<T>(/*option_add_null_type*/ true)
}
fn schema_for<T: JsonSchema>(option_add_null_type: bool) -> JsonObject {
let schema = SchemaSettings::draft2019_09()
.with(|settings| {
settings.inline_subschemas = true;
settings.option_add_null_type = option_add_null_type;
})
.into_generator()
.into_root_schema_for::<T>();
let schema_value = serde_json::to_value(schema)
.unwrap_or_else(|err| panic!("generated tool schema should serialize: {err}"));
let serde_json::Value::Object(mut schema_object) = schema_value else {
unreachable!("root tool schema must be an object");
};
// MCP tools only need the JSON Schema body, not schemars' root metadata.
let mut tool_schema = JsonObject::new();
for key in [
"properties",
"required",
"type",
"additionalProperties",
"$defs",
"definitions",
] {
if let Some(value) = schema_object.remove(key) {
tool_schema.insert(key.to_string(), value);
}
}
tool_schema
}