---
phase: 42-add-outputschema-top-level-support
plan: 02
type: execute
wave: 2
depends_on: ["42-01"]
files_modified:
  - cargo-pmcp/src/commands/schema.rs
  - cargo-pmcp/src/templates/calculator.rs
  - tests/tool_annotations_test.rs
  - examples/48_structured_output_schema.rs
  - docs/OUTPUT_SCHEMA_ANNOTATIONS.md
autonomous: true
requirements:
  - OS-05
  - OS-06

must_haves:
  truths:
    - "cargo-pmcp schema export deserializes top-level outputSchema from servers"
    - "All tests pass verifying top-level output_schema on ToolInfo and pmcp:outputTypeName in annotations"
    - "Documentation reflects outputSchema as top-level field per MCP spec 2025-06-18"
  artifacts:
    - path: "cargo-pmcp/src/commands/schema.rs"
      provides: "Local ToolSchema with top-level output_schema, local ToolAnnotations without output_schema"
      contains: "output_schema"
    - path: "tests/tool_annotations_test.rs"
      provides: "Rewritten tests verifying top-level output_schema on ToolInfo"
      contains: "tool_info.output_schema"
    - path: "docs/OUTPUT_SCHEMA_ANNOTATIONS.md"
      provides: "Updated documentation for top-level outputSchema"
      contains: "outputSchema"
  key_links:
    - from: "cargo-pmcp/src/commands/schema.rs"
      to: "MCP server JSON response"
      via: "Deserializes outputSchema from top-level Tool object"
      pattern: "output_schema"
    - from: "tests/tool_annotations_test.rs"
      to: "src/types/protocol.rs"
      via: "Tests verify ToolInfo.output_schema and ToolAnnotations.output_type_name"
      pattern: "output_schema|output_type_name"
---

<objective>
Update all consumers of the old ToolAnnotations.output_schema pattern: cargo-pmcp local structs, test assertions, example code, and documentation. This completes the migration by ensuring all non-compile-critical artifacts reflect the top-level outputSchema.

Purpose: Complete the MCP spec 2025-06-18 alignment by updating tests, CLI deserialization, and docs.
Output: All tests pass, docs accurate, cargo-pmcp deserializes new format.
</objective>

<execution_context>
@./.claude/get-shit-done/workflows/execute-plan.md
@./.claude/get-shit-done/templates/summary.md
</execution_context>

<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/42-add-outputschema-top-level-support/42-CONTEXT.md
@.planning/phases/42-add-outputschema-top-level-support/42-RESEARCH.md
@.planning/phases/42-add-outputschema-top-level-support/42-01-SUMMARY.md

<interfaces>
<!-- After Plan 01, ToolInfo has: -->
From src/types/protocol.rs (after plan 01):
```rust
pub struct ToolInfo {
    pub name: String,
    pub description: Option<String>,
    pub input_schema: Value,
    pub output_schema: Option<Value>,  // NEW top-level
    pub annotations: Option<ToolAnnotations>,
    pub _meta: Option<serde_json::Map<String, Value>>,
    pub execution: Option<Value>,
}

impl ToolInfo {
    pub fn with_output_schema(mut self, schema: Value) -> Self;
}
```

<!-- After Plan 01, ToolAnnotations has: -->
```rust
pub struct ToolAnnotations {
    pub title: Option<String>,
    pub read_only_hint: Option<bool>,
    pub destructive_hint: Option<bool>,
    pub idempotent_hint: Option<bool>,
    pub open_world_hint: Option<bool>,
    // output_schema REMOVED
    pub output_type_name: Option<String>,  // pmcp:outputTypeName KEPT
}

impl ToolAnnotations {
    pub fn with_output_type_name(mut self, name: impl Into<String>) -> Self;
}
```

<!-- Current cargo-pmcp local structs to update -->
From cargo-pmcp/src/commands/schema.rs:
```rust
// Local ToolSchema (line ~112) -- needs output_schema field added
// Local ToolAnnotations (line ~137) -- needs output_schema field removed
```
</interfaces>
</context>

<tasks>

<task type="auto">
  <name>Task 1: Update cargo-pmcp schema structs and calculator template</name>
  <files>cargo-pmcp/src/commands/schema.rs, cargo-pmcp/src/templates/calculator.rs</files>
  <action>
1. In `cargo-pmcp/src/commands/schema.rs`:
   - In local `ToolSchema` struct (~line 112): add `output_schema: Option<Value>` field with `#[serde(rename = "outputSchema", skip_serializing_if = "Option::is_none")]` (or just `#[serde(alias = "outputSchema")]` for deserialization -- check how input_schema is handled and mirror)
   - In local `ToolAnnotations` struct (~line 137): REMOVE the `output_schema` field and its `#[serde(rename = "pmcp:outputSchema")]` attribute. KEEP `output_type_name` with its `pmcp:outputTypeName` rename.
   - If there is display/formatting code that references `annotations.output_schema`, update it to reference `tool.output_schema` at the top level instead
   - If the schema export command's output/display logic shows output schema info, update the source from annotations to the top-level field

2. In `cargo-pmcp/src/templates/calculator.rs`:
   - Update doc comments that reference `pmcp:outputSchema` in annotations to reference top-level `outputSchema`
   - If there is code (not just docs) referencing annotations output_schema, update it
  </action>
  <verify>
    <automated>cd /Users/guy/Development/mcp/sdk/rust-mcp-sdk && cargo check -p cargo-pmcp 2>&1 | head -30</automated>
  </verify>
  <done>cargo-pmcp compiles. Local ToolSchema has top-level output_schema. Local ToolAnnotations has no output_schema. Calculator template docs reference top-level outputSchema.</done>
</task>

<task type="auto">
  <name>Task 2: Rewrite tests and update example and docs</name>
  <files>tests/tool_annotations_test.rs, examples/48_structured_output_schema.rs, docs/OUTPUT_SCHEMA_ANNOTATIONS.md</files>
  <action>
1. In `tests/tool_annotations_test.rs`:
   - Rewrite ALL test functions that reference `output_schema` on annotations or `with_output_schema()` on annotations:
     - `test_output_schema_annotation`: Rewrite to test ToolInfo::with_output_schema() builder. Assert `tool_info.output_schema == Some(schema)`.
     - Tests checking JSON serialization of `pmcp:outputSchema`: Rewrite to verify `outputSchema` appears at top level of ToolInfo JSON (sibling to `inputSchema`), NOT inside annotations.
     - Tests checking `annotations.output_schema`: Change to check `tool_info.output_schema` and `annotations.output_type_name`.
     - `test_output_schema_complex_types`: Rewrite to use ToolInfo builder, verify top-level output_schema round-trips through serde.
     - Tests checking `with_output_schema(schema, type_name)`: Split into `ToolInfo::with_output_schema(schema)` and `ToolAnnotations::with_output_type_name(type_name)`.
   - Add a new test `test_output_schema_json_format` that constructs a ToolInfo with both input_schema and output_schema, serializes to JSON, and verifies the output matches MCP spec 2025-06-18 format:
     ```json
     {
       "name": "...",
       "inputSchema": {...},
       "outputSchema": {...},
       "annotations": { "pmcp:outputTypeName": "..." }
     }
     ```
   - Verify that when output_schema is None, `outputSchema` key does NOT appear in JSON output (skip_serializing_if works).

2. In `examples/48_structured_output_schema.rs`:
   - Update doc comments at top of file to reference top-level `outputSchema` on ToolInfo (not annotations)
   - If the example constructs ToolAnnotations with output_schema, update to use ToolInfo builder
   - The example likely uses TypedToolWithOutput which is already rewired by plan 01, so runtime behavior should be correct. Focus on doc comments and any explicit annotation construction.

3. In `docs/OUTPUT_SCHEMA_ANNOTATIONS.md`:
   - Update title/introduction to reflect that outputSchema is a top-level ToolInfo field per MCP spec 2025-06-18
   - Update all code examples showing `ToolAnnotations::new().with_output_schema(...)` to show `ToolInfo::new(...).with_output_schema(schema)` and `ToolAnnotations::new().with_output_type_name("TypeName")`
   - Update JSON examples to show outputSchema at top level
   - Note that pmcp:outputTypeName remains in annotations as a PMCP codegen extension
   - Remove any references to `pmcp:outputSchema` annotation key
   - Keep the document focused and accurate -- minimal rewrite, just correcting the field location

4. Check if `pmcp-course/src/part2-design/ch05-02-output-schemas.md` and `ch05-03-annotations.md` exist and need updates. If they exist, update references from annotations output_schema to top-level ToolInfo output_schema. Minimal changes -- just correct the location references.
  </action>
  <verify>
    <automated>cd /Users/guy/Development/mcp/sdk/rust-mcp-sdk && cargo test --workspace -- --test-threads=1 2>&1 | tail -30</automated>
  </verify>
  <done>All workspace tests pass. Tests verify output_schema on ToolInfo top-level. Tests verify pmcp:outputTypeName in annotations. JSON serialization matches MCP spec 2025-06-18. Docs accurately describe top-level outputSchema.</done>
</task>

</tasks>

<verification>
```bash
# Full workspace tests
cargo test --workspace -- --test-threads=1

# Specific annotation tests
cargo test tool_annotations_test -- --test-threads=1

# Quality gate
cargo fmt --all --check
cargo clippy --workspace -- -D warnings

# Verify example compiles
cargo check --example 48_structured_output_schema
```
</verification>

<success_criteria>
- `cargo test --workspace -- --test-threads=1` passes with zero failures
- `cargo clippy --workspace -- -D warnings` passes with zero warnings
- `cargo fmt --all --check` passes
- cargo-pmcp local structs mirror the SDK types correctly
- Tests verify: top-level output_schema on ToolInfo, pmcp:outputTypeName in annotations, correct JSON serialization
- Documentation accurately describes the top-level outputSchema pattern
</success_criteria>

<output>
After completion, create `.planning/phases/42-add-outputschema-top-level-support/42-02-SUMMARY.md`
</output>
