fix: resolve schema generation regression with dual-pattern support (v0.10.1) - #56
Merged
Conversation
Fixes critical bug where parameter schemas were hardcoded as empty objects instead of using JsonSchema trait implementations. ## Problem - Issue #55: Tools showed empty schemas `{"properties": {}, "type": "object"}` - MCP clients couldn't validate parameters or provide autocomplete - Root cause: macro generated hardcoded empty schemas instead of calling JsonSchema ## Solution - Rewrote `generate_input_schema_for_method()` to detect single parameter structs - Now calls `<ParamType>::json_schema()` to generate real schemas from JsonSchema derives - Added clear compile errors for multi-parameter patterns with migration guidance - Added comprehensive test demonstrating proper schema generation ## Results - Tools now generate proper typed schemas with required/optional field detection - Resolves "Missing required parameter 'params'" errors in MCP clients - Enforces best practice single-struct parameter pattern ## Breaking Change Multi-parameter tools now require migration to single struct pattern: ```rust // Old (now compile error) fn tool(&self, name: String, count: Option<u32>) -> String // New (required) fn tool(&self, params: ToolParams) -> String ``` Closes #55 Version: 0.10.0 → 0.10.1
5 tasks
Updates examples to work with the schema generation fix: - Add schemars dependency and imports - Convert multi-parameter tools to single parameter structs - Add JsonSchema derives for proper schema generation Examples fixed: - hello-world: SayHelloParams struct - hello-world-with-auth: SayHelloParams struct - ultra-simple: SayHelloParams and AddParams structs This resolves CI compilation failures and demonstrates the new pattern.
PR Validation ResultsQuick Validation: ✅
Summary: ✅ All checks passed |
- Add explicit JsonSchema trait import in generated code - Use fully qualified trait path for json_schema method call - Ensures compatibility with primitive types (String, i32, bool, etc.) - Maintains support for custom struct parameters with JsonSchema derives This improves upon the initial fix by making the macro work with both primitive parameter types and custom JsonSchema-derived structs. Part of fix for #55
avrabe
force-pushed
the
fix/schema-generation-v0.10.1
branch
from
September 5, 2025 04:02
ab68ef5 to
feb928c
Compare
- Fix async_sync_tests.rs: Convert multi-parameter methods to single structs with JsonSchema - Fix performance_tests.rs: Convert all multi-parameter methods (bulk_lookup, memory_intensive, etc.) - Fix core_functionality.rs: Convert tool_with_params to use ToolParams struct - Fix mcp_resource_tests.rs: Convert database table and API methods to use parameter structs All fixes maintain the same functionality while conforming to the new single-struct parameter requirement introduced to fix schema generation regression. Part of resolving #55
- Workspace version: 0.10.1 → 0.11.0 - All package versions: 0.10.0 → 0.11.0 - Properly reflects breaking change requiring code migration - Multi-parameter tools now require single-struct pattern - Resolves semantic versioning issue from #57 This is a breaking change that requires users to migrate: - FROM: fn tool(&self, a: String, b: i32) - TO: fn tool(&self, params: MyParams) with #[derive(JsonSchema)]
…ameter and JsonSchema patterns
🎯 **NON-BREAKING SOLUTION**: Instead of forcing users to migrate, we now support both patterns:
✅ **Pattern 1: Multi-parameter (auto-generated schemas)**
fn tool(&self, name: String, age: u32, active: bool) -> String
→ Generates: {"properties": {"name": {"type": "string"}, ...}, "required": [...]}
✅ **Pattern 2: JsonSchema struct (rich schemas)**
fn tool(&self, params: MyParams) -> String // MyParams: #[derive(JsonSchema)]
→ Uses JsonSchema trait: Full validation, descriptions, format hints
🔧 **Implementation**:
- Enhanced generate_input_schema_for_method() to detect parameter patterns
- Multi-parameter: Auto-generate schemas from Rust primitive types
- Single JsonSchema struct: Use existing JsonSchema trait implementation
- Comprehensive type mapping: String→string, u32→integer+minimum:0, Option<T>→nullable
📊 **Results**:
- ✅ Fixes original schema regression (empty schemas → proper schemas)
- ✅ No breaking changes (our 37 multi-param methods keep working)
- ✅ No user migration required (existing code works unchanged)
- ✅ Optional handling: Option<T> correctly excluded from required fields
- ✅ Rich schemas: JsonSchema structs get descriptions and validation
This approach resolves #55 without the hypocrisy of forcing a pattern we don't use ourselves.
- Fixed formatting issues in test files (clippy uninlined_format_args) - Updated test function calls to use proper parameter structs - Added missing JsonSchema derives for type system tests - Added schemars dependency to test-tools-server example
Code Coverage Report 📊Local Coverage: 19.64%
Coverage Details📋 Full Report: View on Codecov |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🐛 Problem
Issue #55 reported that parameter schema generation was completely broken in v0.10.0:
{"properties": {}, "type": "object"}🎯 Root Cause
The macro was generating hardcoded empty schemas instead of using JsonSchema trait implementations:
✅ Solution: Branch 2 - Dual Pattern Support
Instead of forcing a breaking change, we now support both patterns:
Pattern 1: Multi-parameter → Auto-generated schema
Generated schema:
{ "properties": { "name": {"type": "string"}, "age": {"type": "integer", "minimum": 0}, "active": {"type": "boolean"} }, "required": ["name", "age", "active"] }Pattern 2: JsonSchema struct → Rich schema
Generated schema:
{ "description": "Rich schema with descriptions", "properties": { "message": { "description": "Required message with validation", "type": "string" }, "count": { "description": "Optional count", "type": ["integer", "null"], "minimum": 0 } }, "required": ["message"] }🚫 Non-Breaking Change
Before (Broken): Empty schemas for all tools
After (Fixed): Proper schemas for both patterns - no code changes required
📊 Impact
This resolves the schema generation regression while supporting both the multi-parameter pattern we use extensively and the JsonSchema struct pattern for rich validation.