# MCP Tool Schema Validation Requirements

## Problem

When integrating Plexus with Claude Code via the rmcp MCP server, tool registration failed with validation errors:

```
MCP server "plexus-starter" Failed to fetch tools: [
  {
    "code": "invalid_value",
    "path": ["tools", 3, "inputSchema", "type"],
    "message": "Invalid input: expected \"object\""
  },
  ...
]
```

Tools at indices 3, 7, 8, 23, 28, 32, 33 failed validation.

## Root Cause

MCP specification requires all tool `inputSchema` to be JSON Schema objects with `"type": "object"` at the root level. However, `schemars` can produce schemas without this property:

1. **Unit types `()`**: Serialize to `{}` (empty schema, no type)
2. **Option wrappers**: May omit type at root
3. **Simple primitives**: Might have type but not "object"

### Example: Failing Schema

```json
{
  "properties": { ... },
  "required": [ ... ]
}
```

Missing `"type": "object"` causes Claude Code to reject the tool.

### Example: Valid Schema

```json
{
  "type": "object",
  "properties": { ... },
  "required": [ ... ]
}
```

## Solution

In `schemas_to_rmcp_tools()`, ensure every schema has `"type": "object"`:

```rust
let input_schema = method
    .params
    .and_then(|s| serde_json::to_value(s).ok())
    .and_then(|v| v.as_object().cloned())
    .map(|mut obj| {
        // MCP requires "type": "object" at schema root
        if !obj.contains_key("type") {
            obj.insert("type".to_string(), json!("object"));
        }
        Arc::new(obj)
    })
    .unwrap_or_else(|| {
        // Empty params = empty object schema
        Arc::new(serde_json::Map::from_iter([
            ("type".to_string(), json!("object")),
        ]))
    });
```

## Development Workflow

### Auto-Reload with entr

During development, we use `entr` to automatically rebuild and restart the MCP server on file changes:

```bash
# Terminal 1: Watch and rebuild
ls examples/rmcp_mcp_server.rs src/**/*.rs | entr -r cargo run --example rmcp_mcp_server

# Terminal 2: Claude Code session
claude
```

When source files change:
1. `entr` kills the running server
2. Cargo rebuilds the example
3. Server restarts on port 3000
4. Claude Code auto-reconnects (seen in debug logs)

### Debug Logs

Claude Code debug logs are at `~/.claude/debug/<session-id>.txt`. Key lines to watch:

```
MCP server "plexus-starter": Successfully connected to http server in 88ms
MCP server "plexus-starter": Connection established with capabilities: {"hasTools":true,...}
```

Or on failure:

```
MCP server "plexus-starter" Failed to fetch tools: [...]
```

### MCP Server Configuration

In `~/.claude.json`:

```json
{
  "mcpServers": {
    "plexus-starter": {
      "type": "http",
      "url": "http://127.0.0.1:3000/mcp"
    }
  }
}
```

## Affected Tools

The following Plexus methods had schemas without `"type": "object"`:

| Index | Likely Method | Issue |
|-------|--------------|-------|
| 3 | health.check | Unit params `()` |
| 7 | arbor.* | Unit params |
| 8 | arbor.* | Unit params |
| 23 | cone.* | Unit params |
| 28 | claudecode.* | Unit params |
| 32 | claudecode.* | Unit params |
| 33 | claudecode.* | Unit params |

## Future Considerations

1. **Upstream fix in schemars**: Could configure schemars to always emit `"type": "object"` for struct schemas
2. **Plexus schema normalization**: Add a `normalize_for_mcp()` method to `ActivationFullSchema`
3. **Validation layer**: Add schema validation before serving to catch issues early

## References

- [MCP Tool Schema Spec](https://modelcontextprotocol.io/specification/2024-11-05/server/tools)
- [JSON Schema Object Type](https://json-schema.org/understanding-json-schema/reference/object.html)
- [schemars Documentation](https://docs.rs/schemars/latest/schemars/)
