Skip to content

fix(tool): remove unnecessary schema validation - #375

Merged
4t145 merged 1 commit into
modelcontextprotocol:mainfrom
4t145:fix-remove-useless-schema-validation
Aug 15, 2025
Merged

fix(tool): remove unnecessary schema validation#375
4t145 merged 1 commit into
modelcontextprotocol:mainfrom
4t145:fix-remove-useless-schema-validation

Conversation

@4t145

Copy link
Copy Markdown
Contributor
  1. remove unnecessary schema validation
  2. add a method directly convert the structured output into typed data.

Motivation and Context

We don't really need to do the validation in rust, because deserilization already is a validation. And if user want to do the validation, they can use the jsonschame crate.

And also, the original validation method is a wrong implementation, as I mentioned in #374

How Has This Been Tested?

Breaking Changes

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

@github-actionsgithub-actionsBot added T-test Testing related changes T-core Core library changes T-handler Handler implementation changes labels Aug 14, 2025
@4t145

4t145 commented Aug 14, 2025

Copy link
Copy Markdown
ContributorAuthor

@ccamel55 please review this. I didn't notice the problem when I merge the pr.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR removes unnecessary JSON schema validation from the tool system and introduces a type-safe conversion method for structured outputs. The changes eliminate redundant validation since Rust's deserialization already provides type safety, and replace it with a more idiomatic approach.

Key changes:

  • Removes schema validation functions and related validation logic
  • Adds into_typed() method to CallToolResult for type-safe conversion of structured content
  • Updates tests to use the new type-safe approach instead of validation

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

FileDescription
crates/rmcp/src/model.rsReplaces validation method with into_typed() for type-safe conversion and simplifies deserialization validation
crates/rmcp/src/handler/server/tool.rsRemoves schema validation functions (validate_against_schema and get_json_value_type)
crates/rmcp/src/handler/server/router/tool.rsRemoves schema validation logic from tool call execution
crates/rmcp/tests/test_structured_output.rsUpdates test to use new into_typed() method instead of validation

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

if let Some(text) = raw_text {
return serde_json::from_str(text);
}
serde_json::from_value(serde_json::Value::Null)

CopilotAIAug 14, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line will always attempt to deserialize null into type T, which will likely fail for most types. Consider returning an error indicating that no structured content or valid text content was found instead of trying to deserialize null.

Suggested change
serde_json::from_value(serde_json::Value::Null)
Err(serde_json::Error::custom("No structured content or valid text content found"))

Copilot uses AI. Check for mistakes.
(None, Some(contents)) => {
if let Some(text) = contents.first().and_then(|c| c.as_text()) {
let text = &text.text;
Some(text)

CopilotAIAug 14, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The logic for extracting content could be simplified. The current implementation checks for text content only in the first element of the content array. Consider making this behavior more explicit or handling multiple content items if that's the intended behavior.

Suggested change
Some(text)
// Collect all text content from the vector
let texts:Vec<&str> = contents.iter()
.filter_map(|c| c.as_text().map(|t| t.text.as_str()))
.collect();
if !texts.is_empty(){
// Concatenate all text content with a space separator
Some(texts.join(" "))

Copilot uses AI. Check for mistakes.
let raw_text = match (self.structured_content, &self.content) {
(Some(value), _) => return serde_json::from_value(value),
(None, Some(contents)) => {
if let Some(text) = contents.first().and_then(|c| c.as_text()) {

CopilotAIAug 14, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method only considers the first content item when extracting text. This behavior should be documented in the method's docstring to clarify that only the first text content will be used for deserialization.

Copilot uses AI. Check for mistakes.

@ccamel55ccamel55 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM but wouldn't this technically be a breaking change since it removes public facing API? I'll leave it to the maintainers to to decide though 😄

@4t145

Copy link
Copy Markdown
ContributorAuthor

@ccamel55 It's ok to introduce breaking changes, we haven't release the deleted api.

@jokemanfirejokemanfire left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can be Deserialized , so it is structed json data, If I understand it ?

@4t145
4t145 merged commit 1555c0f into modelcontextprotocol:mainAug 15, 2025
11 checks passed
@github-actionsgithub-actionsBot mentioned this pull request Aug 13, 2025
@snowmeadsnowmead mentioned this pull request Aug 19, 2025
9 tasks
takumi-earth pushed a commit to earthlings-dev/rmcp that referenced this pull request Jan 27, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

T-coreCore library changesT-handlerHandler implementation changesT-testTesting related changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@4t145@jokemanfire@ccamel55
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
fix(tool): remove unnecessary schema validation by 4t145 · Pull Request #375 · modelcontextprotocol/rust-sdk · GitHub
Skip to content

fix(tool): remove unnecessary schema validation - #375

Merged
4t145 merged 1 commit into
modelcontextprotocol:mainfrom
4t145:fix-remove-useless-schema-validation
Aug 15, 2025
Merged

fix(tool): remove unnecessary schema validation#375
4t145 merged 1 commit into
modelcontextprotocol:mainfrom
4t145:fix-remove-useless-schema-validation

Conversation

@4t145

Copy link
Copy Markdown
Contributor
  1. remove unnecessary schema validation
  2. add a method directly convert the structured output into typed data.

Motivation and Context

We don't really need to do the validation in rust, because deserilization already is a validation. And if user want to do the validation, they can use the jsonschame crate.

And also, the original validation method is a wrong implementation, as I mentioned in #374

How Has This Been Tested?

Breaking Changes

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

@github-actionsgithub-actionsBot added T-test Testing related changes T-core Core library changes T-handler Handler implementation changes labels Aug 14, 2025
@4t145

4t145 commented Aug 14, 2025

Copy link
Copy Markdown
ContributorAuthor

@ccamel55 please review this. I didn't notice the problem when I merge the pr.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR removes unnecessary JSON schema validation from the tool system and introduces a type-safe conversion method for structured outputs. The changes eliminate redundant validation since Rust's deserialization already provides type safety, and replace it with a more idiomatic approach.

Key changes:

  • Removes schema validation functions and related validation logic
  • Adds into_typed() method to CallToolResult for type-safe conversion of structured content
  • Updates tests to use the new type-safe approach instead of validation

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

FileDescription
crates/rmcp/src/model.rsReplaces validation method with into_typed() for type-safe conversion and simplifies deserialization validation
crates/rmcp/src/handler/server/tool.rsRemoves schema validation functions (validate_against_schema and get_json_value_type)
crates/rmcp/src/handler/server/router/tool.rsRemoves schema validation logic from tool call execution
crates/rmcp/tests/test_structured_output.rsUpdates test to use new into_typed() method instead of validation

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

if let Some(text) = raw_text {
return serde_json::from_str(text);
}
serde_json::from_value(serde_json::Value::Null)

CopilotAIAug 14, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line will always attempt to deserialize null into type T, which will likely fail for most types. Consider returning an error indicating that no structured content or valid text content was found instead of trying to deserialize null.

Suggested change
serde_json::from_value(serde_json::Value::Null)
Err(serde_json::Error::custom("No structured content or valid text content found"))

Copilot uses AI. Check for mistakes.
(None, Some(contents)) => {
if let Some(text) = contents.first().and_then(|c| c.as_text()) {
let text = &text.text;
Some(text)

CopilotAIAug 14, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The logic for extracting content could be simplified. The current implementation checks for text content only in the first element of the content array. Consider making this behavior more explicit or handling multiple content items if that's the intended behavior.

Suggested change
Some(text)
// Collect all text content from the vector
let texts:Vec<&str> = contents.iter()
.filter_map(|c| c.as_text().map(|t| t.text.as_str()))
.collect();
if !texts.is_empty(){
// Concatenate all text content with a space separator
Some(texts.join(" "))

Copilot uses AI. Check for mistakes.
let raw_text = match (self.structured_content, &self.content) {
(Some(value), _) => return serde_json::from_value(value),
(None, Some(contents)) => {
if let Some(text) = contents.first().and_then(|c| c.as_text()) {

CopilotAIAug 14, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method only considers the first content item when extracting text. This behavior should be documented in the method's docstring to clarify that only the first text content will be used for deserialization.

Copilot uses AI. Check for mistakes.

@ccamel55ccamel55 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM but wouldn't this technically be a breaking change since it removes public facing API? I'll leave it to the maintainers to to decide though 😄

@4t145

Copy link
Copy Markdown
ContributorAuthor

@ccamel55 It's ok to introduce breaking changes, we haven't release the deleted api.

@jokemanfirejokemanfire left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can be Deserialized , so it is structed json data, If I understand it ?

@4t145
4t145 merged commit 1555c0f into modelcontextprotocol:mainAug 15, 2025
11 checks passed
@github-actionsgithub-actionsBot mentioned this pull request Aug 13, 2025
@snowmeadsnowmead mentioned this pull request Aug 19, 2025
9 tasks
takumi-earth pushed a commit to earthlings-dev/rmcp that referenced this pull request Jan 27, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

T-coreCore library changesT-handlerHandler implementation changesT-testTesting related changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@4t145@jokemanfire@ccamel55
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix(tool): remove unnecessary schema validation by 4t145 · Pull Request #375 · modelcontextprotocol/rust-sdk · GitHub
Skip to content

fix(tool): remove unnecessary schema validation - #375

Merged
4t145 merged 1 commit into
modelcontextprotocol:mainfrom
4t145:fix-remove-useless-schema-validation
Aug 15, 2025
Merged

fix(tool): remove unnecessary schema validation#375
4t145 merged 1 commit into
modelcontextprotocol:mainfrom
4t145:fix-remove-useless-schema-validation

Conversation

@4t145

Copy link
Copy Markdown
Contributor
  1. remove unnecessary schema validation
  2. add a method directly convert the structured output into typed data.

Motivation and Context

We don't really need to do the validation in rust, because deserilization already is a validation. And if user want to do the validation, they can use the jsonschame crate.

And also, the original validation method is a wrong implementation, as I mentioned in #374

How Has This Been Tested?

Breaking Changes

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

@github-actionsgithub-actionsBot added T-test Testing related changes T-core Core library changes T-handler Handler implementation changes labels Aug 14, 2025
@4t145

4t145 commented Aug 14, 2025

Copy link
Copy Markdown
ContributorAuthor

@ccamel55 please review this. I didn't notice the problem when I merge the pr.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR removes unnecessary JSON schema validation from the tool system and introduces a type-safe conversion method for structured outputs. The changes eliminate redundant validation since Rust's deserialization already provides type safety, and replace it with a more idiomatic approach.

Key changes:

  • Removes schema validation functions and related validation logic
  • Adds into_typed() method to CallToolResult for type-safe conversion of structured content
  • Updates tests to use the new type-safe approach instead of validation

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

FileDescription
crates/rmcp/src/model.rsReplaces validation method with into_typed() for type-safe conversion and simplifies deserialization validation
crates/rmcp/src/handler/server/tool.rsRemoves schema validation functions (validate_against_schema and get_json_value_type)
crates/rmcp/src/handler/server/router/tool.rsRemoves schema validation logic from tool call execution
crates/rmcp/tests/test_structured_output.rsUpdates test to use new into_typed() method instead of validation

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

if let Some(text) = raw_text {
return serde_json::from_str(text);
}
serde_json::from_value(serde_json::Value::Null)

CopilotAIAug 14, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line will always attempt to deserialize null into type T, which will likely fail for most types. Consider returning an error indicating that no structured content or valid text content was found instead of trying to deserialize null.

Suggested change
serde_json::from_value(serde_json::Value::Null)
Err(serde_json::Error::custom("No structured content or valid text content found"))

Copilot uses AI. Check for mistakes.
(None, Some(contents)) => {
if let Some(text) = contents.first().and_then(|c| c.as_text()) {
let text = &text.text;
Some(text)

CopilotAIAug 14, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The logic for extracting content could be simplified. The current implementation checks for text content only in the first element of the content array. Consider making this behavior more explicit or handling multiple content items if that's the intended behavior.

Suggested change
Some(text)
// Collect all text content from the vector
let texts:Vec<&str> = contents.iter()
.filter_map(|c| c.as_text().map(|t| t.text.as_str()))
.collect();
if !texts.is_empty(){
// Concatenate all text content with a space separator
Some(texts.join(" "))

Copilot uses AI. Check for mistakes.
let raw_text = match (self.structured_content, &self.content) {
(Some(value), _) => return serde_json::from_value(value),
(None, Some(contents)) => {
if let Some(text) = contents.first().and_then(|c| c.as_text()) {

CopilotAIAug 14, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method only considers the first content item when extracting text. This behavior should be documented in the method's docstring to clarify that only the first text content will be used for deserialization.

Copilot uses AI. Check for mistakes.

@ccamel55ccamel55 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM but wouldn't this technically be a breaking change since it removes public facing API? I'll leave it to the maintainers to to decide though 😄

@4t145

Copy link
Copy Markdown
ContributorAuthor

@ccamel55 It's ok to introduce breaking changes, we haven't release the deleted api.

@jokemanfirejokemanfire left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can be Deserialized , so it is structed json data, If I understand it ?

@4t145
4t145 merged commit 1555c0f into modelcontextprotocol:mainAug 15, 2025
11 checks passed
@github-actionsgithub-actionsBot mentioned this pull request Aug 13, 2025
@snowmeadsnowmead mentioned this pull request Aug 19, 2025
9 tasks
takumi-earth pushed a commit to earthlings-dev/rmcp that referenced this pull request Jan 27, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

T-coreCore library changesT-handlerHandler implementation changesT-testTesting related changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@4t145@jokemanfire@ccamel55
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix(tool): remove unnecessary schema validation by 4t145 · Pull Request #375 · modelcontextprotocol/rust-sdk · GitHub
Skip to content

fix(tool): remove unnecessary schema validation - #375

Merged
4t145 merged 1 commit into
modelcontextprotocol:mainfrom
4t145:fix-remove-useless-schema-validation
Aug 15, 2025
Merged

fix(tool): remove unnecessary schema validation#375
4t145 merged 1 commit into
modelcontextprotocol:mainfrom
4t145:fix-remove-useless-schema-validation

Conversation

@4t145

Copy link
Copy Markdown
Contributor
  1. remove unnecessary schema validation
  2. add a method directly convert the structured output into typed data.

Motivation and Context

We don't really need to do the validation in rust, because deserilization already is a validation. And if user want to do the validation, they can use the jsonschame crate.

And also, the original validation method is a wrong implementation, as I mentioned in #374

How Has This Been Tested?

Breaking Changes

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

@github-actionsgithub-actionsBot added T-test Testing related changes T-core Core library changes T-handler Handler implementation changes labels Aug 14, 2025
@4t145

4t145 commented Aug 14, 2025

Copy link
Copy Markdown
ContributorAuthor

@ccamel55 please review this. I didn't notice the problem when I merge the pr.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR removes unnecessary JSON schema validation from the tool system and introduces a type-safe conversion method for structured outputs. The changes eliminate redundant validation since Rust's deserialization already provides type safety, and replace it with a more idiomatic approach.

Key changes:

  • Removes schema validation functions and related validation logic
  • Adds into_typed() method to CallToolResult for type-safe conversion of structured content
  • Updates tests to use the new type-safe approach instead of validation

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

FileDescription
crates/rmcp/src/model.rsReplaces validation method with into_typed() for type-safe conversion and simplifies deserialization validation
crates/rmcp/src/handler/server/tool.rsRemoves schema validation functions (validate_against_schema and get_json_value_type)
crates/rmcp/src/handler/server/router/tool.rsRemoves schema validation logic from tool call execution
crates/rmcp/tests/test_structured_output.rsUpdates test to use new into_typed() method instead of validation

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

if let Some(text) = raw_text {
return serde_json::from_str(text);
}
serde_json::from_value(serde_json::Value::Null)

CopilotAIAug 14, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line will always attempt to deserialize null into type T, which will likely fail for most types. Consider returning an error indicating that no structured content or valid text content was found instead of trying to deserialize null.

Suggested change
serde_json::from_value(serde_json::Value::Null)
Err(serde_json::Error::custom("No structured content or valid text content found"))

Copilot uses AI. Check for mistakes.
(None, Some(contents)) => {
if let Some(text) = contents.first().and_then(|c| c.as_text()) {
let text = &text.text;
Some(text)

CopilotAIAug 14, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The logic for extracting content could be simplified. The current implementation checks for text content only in the first element of the content array. Consider making this behavior more explicit or handling multiple content items if that's the intended behavior.

Suggested change
Some(text)
// Collect all text content from the vector
let texts:Vec<&str> = contents.iter()
.filter_map(|c| c.as_text().map(|t| t.text.as_str()))
.collect();
if !texts.is_empty(){
// Concatenate all text content with a space separator
Some(texts.join(" "))

Copilot uses AI. Check for mistakes.
let raw_text = match (self.structured_content, &self.content) {
(Some(value), _) => return serde_json::from_value(value),
(None, Some(contents)) => {
if let Some(text) = contents.first().and_then(|c| c.as_text()) {

CopilotAIAug 14, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method only considers the first content item when extracting text. This behavior should be documented in the method's docstring to clarify that only the first text content will be used for deserialization.

Copilot uses AI. Check for mistakes.

@ccamel55ccamel55 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM but wouldn't this technically be a breaking change since it removes public facing API? I'll leave it to the maintainers to to decide though 😄

@4t145

Copy link
Copy Markdown
ContributorAuthor

@ccamel55 It's ok to introduce breaking changes, we haven't release the deleted api.

@jokemanfirejokemanfire left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can be Deserialized , so it is structed json data, If I understand it ?

@4t145
4t145 merged commit 1555c0f into modelcontextprotocol:mainAug 15, 2025
11 checks passed
@github-actionsgithub-actionsBot mentioned this pull request Aug 13, 2025
@snowmeadsnowmead mentioned this pull request Aug 19, 2025
9 tasks
takumi-earth pushed a commit to earthlings-dev/rmcp that referenced this pull request Jan 27, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

T-coreCore library changesT-handlerHandler implementation changesT-testTesting related changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@4t145@jokemanfire@ccamel55
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' fix(tool): remove unnecessary schema validation by 4t145 · Pull Request #375 · modelcontextprotocol/rust-sdk · GitHub
Skip to content

fix(tool): remove unnecessary schema validation - #375

Merged
4t145 merged 1 commit into
modelcontextprotocol:mainfrom
4t145:fix-remove-useless-schema-validation
Aug 15, 2025
Merged

fix(tool): remove unnecessary schema validation#375
4t145 merged 1 commit into
modelcontextprotocol:mainfrom
4t145:fix-remove-useless-schema-validation

Conversation

@4t145

Copy link
Copy Markdown
Contributor
  1. remove unnecessary schema validation
  2. add a method directly convert the structured output into typed data.

Motivation and Context

We don't really need to do the validation in rust, because deserilization already is a validation. And if user want to do the validation, they can use the jsonschame crate.

And also, the original validation method is a wrong implementation, as I mentioned in #374

How Has This Been Tested?

Breaking Changes

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

@github-actionsgithub-actionsBot added T-test Testing related changes T-core Core library changes T-handler Handler implementation changes labels Aug 14, 2025
@4t145

4t145 commented Aug 14, 2025

Copy link
Copy Markdown
ContributorAuthor

@ccamel55 please review this. I didn't notice the problem when I merge the pr.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR removes unnecessary JSON schema validation from the tool system and introduces a type-safe conversion method for structured outputs. The changes eliminate redundant validation since Rust's deserialization already provides type safety, and replace it with a more idiomatic approach.

Key changes:

  • Removes schema validation functions and related validation logic
  • Adds into_typed() method to CallToolResult for type-safe conversion of structured content
  • Updates tests to use the new type-safe approach instead of validation

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

FileDescription
crates/rmcp/src/model.rsReplaces validation method with into_typed() for type-safe conversion and simplifies deserialization validation
crates/rmcp/src/handler/server/tool.rsRemoves schema validation functions (validate_against_schema and get_json_value_type)
crates/rmcp/src/handler/server/router/tool.rsRemoves schema validation logic from tool call execution
crates/rmcp/tests/test_structured_output.rsUpdates test to use new into_typed() method instead of validation

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

if let Some(text) = raw_text {
return serde_json::from_str(text);
}
serde_json::from_value(serde_json::Value::Null)

CopilotAIAug 14, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line will always attempt to deserialize null into type T, which will likely fail for most types. Consider returning an error indicating that no structured content or valid text content was found instead of trying to deserialize null.

Suggested change
serde_json::from_value(serde_json::Value::Null)
Err(serde_json::Error::custom("No structured content or valid text content found"))

Copilot uses AI. Check for mistakes.
(None, Some(contents)) => {
if let Some(text) = contents.first().and_then(|c| c.as_text()) {
let text = &text.text;
Some(text)

CopilotAIAug 14, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The logic for extracting content could be simplified. The current implementation checks for text content only in the first element of the content array. Consider making this behavior more explicit or handling multiple content items if that's the intended behavior.

Suggested change
Some(text)
// Collect all text content from the vector
let texts:Vec<&str> = contents.iter()
.filter_map(|c| c.as_text().map(|t| t.text.as_str()))
.collect();
if !texts.is_empty(){
// Concatenate all text content with a space separator
Some(texts.join(" "))

Copilot uses AI. Check for mistakes.
let raw_text = match (self.structured_content, &self.content) {
(Some(value), _) => return serde_json::from_value(value),
(None, Some(contents)) => {
if let Some(text) = contents.first().and_then(|c| c.as_text()) {

CopilotAIAug 14, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method only considers the first content item when extracting text. This behavior should be documented in the method's docstring to clarify that only the first text content will be used for deserialization.

Copilot uses AI. Check for mistakes.

@ccamel55ccamel55 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM but wouldn't this technically be a breaking change since it removes public facing API? I'll leave it to the maintainers to to decide though 😄

@4t145

Copy link
Copy Markdown
ContributorAuthor

@ccamel55 It's ok to introduce breaking changes, we haven't release the deleted api.

@jokemanfirejokemanfire left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can be Deserialized , so it is structed json data, If I understand it ?

@4t145
4t145 merged commit 1555c0f into modelcontextprotocol:mainAug 15, 2025
11 checks passed
@github-actionsgithub-actionsBot mentioned this pull request Aug 13, 2025
@snowmeadsnowmead mentioned this pull request Aug 19, 2025
9 tasks
takumi-earth pushed a commit to earthlings-dev/rmcp that referenced this pull request Jan 27, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

T-coreCore library changesT-handlerHandler implementation changesT-testTesting related changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@4t145@jokemanfire@ccamel55
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix(tool): remove unnecessary schema validation by 4t145 · Pull Request #375 · modelcontextprotocol/rust-sdk · GitHub
Skip to content

fix(tool): remove unnecessary schema validation - #375

Merged
4t145 merged 1 commit into
modelcontextprotocol:mainfrom
4t145:fix-remove-useless-schema-validation
Aug 15, 2025
Merged

fix(tool): remove unnecessary schema validation#375
4t145 merged 1 commit into
modelcontextprotocol:mainfrom
4t145:fix-remove-useless-schema-validation

Conversation

@4t145

Copy link
Copy Markdown
Contributor
  1. remove unnecessary schema validation
  2. add a method directly convert the structured output into typed data.

Motivation and Context

We don't really need to do the validation in rust, because deserilization already is a validation. And if user want to do the validation, they can use the jsonschame crate.

And also, the original validation method is a wrong implementation, as I mentioned in #374

How Has This Been Tested?

Breaking Changes

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

@github-actionsgithub-actionsBot added T-test Testing related changes T-core Core library changes T-handler Handler implementation changes labels Aug 14, 2025
@4t145

4t145 commented Aug 14, 2025

Copy link
Copy Markdown
ContributorAuthor

@ccamel55 please review this. I didn't notice the problem when I merge the pr.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR removes unnecessary JSON schema validation from the tool system and introduces a type-safe conversion method for structured outputs. The changes eliminate redundant validation since Rust's deserialization already provides type safety, and replace it with a more idiomatic approach.

Key changes:

  • Removes schema validation functions and related validation logic
  • Adds into_typed() method to CallToolResult for type-safe conversion of structured content
  • Updates tests to use the new type-safe approach instead of validation

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

FileDescription
crates/rmcp/src/model.rsReplaces validation method with into_typed() for type-safe conversion and simplifies deserialization validation
crates/rmcp/src/handler/server/tool.rsRemoves schema validation functions (validate_against_schema and get_json_value_type)
crates/rmcp/src/handler/server/router/tool.rsRemoves schema validation logic from tool call execution
crates/rmcp/tests/test_structured_output.rsUpdates test to use new into_typed() method instead of validation

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

if let Some(text) = raw_text {
return serde_json::from_str(text);
}
serde_json::from_value(serde_json::Value::Null)

CopilotAIAug 14, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line will always attempt to deserialize null into type T, which will likely fail for most types. Consider returning an error indicating that no structured content or valid text content was found instead of trying to deserialize null.

Suggested change
serde_json::from_value(serde_json::Value::Null)
Err(serde_json::Error::custom("No structured content or valid text content found"))

Copilot uses AI. Check for mistakes.
(None, Some(contents)) => {
if let Some(text) = contents.first().and_then(|c| c.as_text()) {
let text = &text.text;
Some(text)

CopilotAIAug 14, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The logic for extracting content could be simplified. The current implementation checks for text content only in the first element of the content array. Consider making this behavior more explicit or handling multiple content items if that's the intended behavior.

Suggested change
Some(text)
// Collect all text content from the vector
let texts:Vec<&str> = contents.iter()
.filter_map(|c| c.as_text().map(|t| t.text.as_str()))
.collect();
if !texts.is_empty(){
// Concatenate all text content with a space separator
Some(texts.join(" "))

Copilot uses AI. Check for mistakes.
let raw_text = match (self.structured_content, &self.content) {
(Some(value), _) => return serde_json::from_value(value),
(None, Some(contents)) => {
if let Some(text) = contents.first().and_then(|c| c.as_text()) {

CopilotAIAug 14, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method only considers the first content item when extracting text. This behavior should be documented in the method's docstring to clarify that only the first text content will be used for deserialization.

Copilot uses AI. Check for mistakes.

@ccamel55ccamel55 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM but wouldn't this technically be a breaking change since it removes public facing API? I'll leave it to the maintainers to to decide though 😄

@4t145

Copy link
Copy Markdown
ContributorAuthor

@ccamel55 It's ok to introduce breaking changes, we haven't release the deleted api.

@jokemanfirejokemanfire left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can be Deserialized , so it is structed json data, If I understand it ?

@4t145
4t145 merged commit 1555c0f into modelcontextprotocol:mainAug 15, 2025
11 checks passed
@github-actionsgithub-actionsBot mentioned this pull request Aug 13, 2025
@snowmeadsnowmead mentioned this pull request Aug 19, 2025
9 tasks
takumi-earth pushed a commit to earthlings-dev/rmcp that referenced this pull request Jan 27, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

T-coreCore library changesT-handlerHandler implementation changesT-testTesting related changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@4t145@jokemanfire@ccamel55
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix(tool): remove unnecessary schema validation by 4t145 · Pull Request #375 · modelcontextprotocol/rust-sdk · GitHub
Skip to content

fix(tool): remove unnecessary schema validation - #375

Merged
4t145 merged 1 commit into
modelcontextprotocol:mainfrom
4t145:fix-remove-useless-schema-validation
Aug 15, 2025
Merged

fix(tool): remove unnecessary schema validation#375
4t145 merged 1 commit into
modelcontextprotocol:mainfrom
4t145:fix-remove-useless-schema-validation

Conversation

@4t145

Copy link
Copy Markdown
Contributor
  1. remove unnecessary schema validation
  2. add a method directly convert the structured output into typed data.

Motivation and Context

We don't really need to do the validation in rust, because deserilization already is a validation. And if user want to do the validation, they can use the jsonschame crate.

And also, the original validation method is a wrong implementation, as I mentioned in #374

How Has This Been Tested?

Breaking Changes

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

@github-actionsgithub-actionsBot added T-test Testing related changes T-core Core library changes T-handler Handler implementation changes labels Aug 14, 2025
@4t145

4t145 commented Aug 14, 2025

Copy link
Copy Markdown
ContributorAuthor

@ccamel55 please review this. I didn't notice the problem when I merge the pr.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR removes unnecessary JSON schema validation from the tool system and introduces a type-safe conversion method for structured outputs. The changes eliminate redundant validation since Rust's deserialization already provides type safety, and replace it with a more idiomatic approach.

Key changes:

  • Removes schema validation functions and related validation logic
  • Adds into_typed() method to CallToolResult for type-safe conversion of structured content
  • Updates tests to use the new type-safe approach instead of validation

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

FileDescription
crates/rmcp/src/model.rsReplaces validation method with into_typed() for type-safe conversion and simplifies deserialization validation
crates/rmcp/src/handler/server/tool.rsRemoves schema validation functions (validate_against_schema and get_json_value_type)
crates/rmcp/src/handler/server/router/tool.rsRemoves schema validation logic from tool call execution
crates/rmcp/tests/test_structured_output.rsUpdates test to use new into_typed() method instead of validation

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

if let Some(text) = raw_text {
return serde_json::from_str(text);
}
serde_json::from_value(serde_json::Value::Null)

CopilotAIAug 14, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line will always attempt to deserialize null into type T, which will likely fail for most types. Consider returning an error indicating that no structured content or valid text content was found instead of trying to deserialize null.

Suggested change
serde_json::from_value(serde_json::Value::Null)
Err(serde_json::Error::custom("No structured content or valid text content found"))

Copilot uses AI. Check for mistakes.
(None, Some(contents)) => {
if let Some(text) = contents.first().and_then(|c| c.as_text()) {
let text = &text.text;
Some(text)

CopilotAIAug 14, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The logic for extracting content could be simplified. The current implementation checks for text content only in the first element of the content array. Consider making this behavior more explicit or handling multiple content items if that's the intended behavior.

Suggested change
Some(text)
// Collect all text content from the vector
let texts:Vec<&str> = contents.iter()
.filter_map(|c| c.as_text().map(|t| t.text.as_str()))
.collect();
if !texts.is_empty(){
// Concatenate all text content with a space separator
Some(texts.join(" "))

Copilot uses AI. Check for mistakes.
let raw_text = match (self.structured_content, &self.content) {
(Some(value), _) => return serde_json::from_value(value),
(None, Some(contents)) => {
if let Some(text) = contents.first().and_then(|c| c.as_text()) {

CopilotAIAug 14, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method only considers the first content item when extracting text. This behavior should be documented in the method's docstring to clarify that only the first text content will be used for deserialization.

Copilot uses AI. Check for mistakes.

@ccamel55ccamel55 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM but wouldn't this technically be a breaking change since it removes public facing API? I'll leave it to the maintainers to to decide though 😄

@4t145

Copy link
Copy Markdown
ContributorAuthor

@ccamel55 It's ok to introduce breaking changes, we haven't release the deleted api.

@jokemanfirejokemanfire left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can be Deserialized , so it is structed json data, If I understand it ?

@4t145
4t145 merged commit 1555c0f into modelcontextprotocol:mainAug 15, 2025
11 checks passed
@github-actionsgithub-actionsBot mentioned this pull request Aug 13, 2025
@snowmeadsnowmead mentioned this pull request Aug 19, 2025
9 tasks
takumi-earth pushed a commit to earthlings-dev/rmcp that referenced this pull request Jan 27, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

T-coreCore library changesT-handlerHandler implementation changesT-testTesting related changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@4t145@jokemanfire@ccamel55
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); fix(tool): remove unnecessary schema validation by 4t145 · Pull Request #375 · modelcontextprotocol/rust-sdk · GitHub
Skip to content

fix(tool): remove unnecessary schema validation - #375

Merged
4t145 merged 1 commit into
modelcontextprotocol:mainfrom
4t145:fix-remove-useless-schema-validation
Aug 15, 2025
Merged

fix(tool): remove unnecessary schema validation#375
4t145 merged 1 commit into
modelcontextprotocol:mainfrom
4t145:fix-remove-useless-schema-validation

Conversation

@4t145

Copy link
Copy Markdown
Contributor
  1. remove unnecessary schema validation
  2. add a method directly convert the structured output into typed data.

Motivation and Context

We don't really need to do the validation in rust, because deserilization already is a validation. And if user want to do the validation, they can use the jsonschame crate.

And also, the original validation method is a wrong implementation, as I mentioned in #374

How Has This Been Tested?

Breaking Changes

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

@github-actionsgithub-actionsBot added T-test Testing related changes T-core Core library changes T-handler Handler implementation changes labels Aug 14, 2025
@4t145

4t145 commented Aug 14, 2025

Copy link
Copy Markdown
ContributorAuthor

@ccamel55 please review this. I didn't notice the problem when I merge the pr.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR removes unnecessary JSON schema validation from the tool system and introduces a type-safe conversion method for structured outputs. The changes eliminate redundant validation since Rust's deserialization already provides type safety, and replace it with a more idiomatic approach.

Key changes:

  • Removes schema validation functions and related validation logic
  • Adds into_typed() method to CallToolResult for type-safe conversion of structured content
  • Updates tests to use the new type-safe approach instead of validation

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

FileDescription
crates/rmcp/src/model.rsReplaces validation method with into_typed() for type-safe conversion and simplifies deserialization validation
crates/rmcp/src/handler/server/tool.rsRemoves schema validation functions (validate_against_schema and get_json_value_type)
crates/rmcp/src/handler/server/router/tool.rsRemoves schema validation logic from tool call execution
crates/rmcp/tests/test_structured_output.rsUpdates test to use new into_typed() method instead of validation

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

if let Some(text) = raw_text {
return serde_json::from_str(text);
}
serde_json::from_value(serde_json::Value::Null)

CopilotAIAug 14, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line will always attempt to deserialize null into type T, which will likely fail for most types. Consider returning an error indicating that no structured content or valid text content was found instead of trying to deserialize null.

Suggested change
serde_json::from_value(serde_json::Value::Null)
Err(serde_json::Error::custom("No structured content or valid text content found"))

Copilot uses AI. Check for mistakes.
(None, Some(contents)) => {
if let Some(text) = contents.first().and_then(|c| c.as_text()) {
let text = &text.text;
Some(text)

CopilotAIAug 14, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The logic for extracting content could be simplified. The current implementation checks for text content only in the first element of the content array. Consider making this behavior more explicit or handling multiple content items if that's the intended behavior.

Suggested change
Some(text)
// Collect all text content from the vector
let texts:Vec<&str> = contents.iter()
.filter_map(|c| c.as_text().map(|t| t.text.as_str()))
.collect();
if !texts.is_empty(){
// Concatenate all text content with a space separator
Some(texts.join(" "))

Copilot uses AI. Check for mistakes.
let raw_text = match (self.structured_content, &self.content) {
(Some(value), _) => return serde_json::from_value(value),
(None, Some(contents)) => {
if let Some(text) = contents.first().and_then(|c| c.as_text()) {

CopilotAIAug 14, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method only considers the first content item when extracting text. This behavior should be documented in the method's docstring to clarify that only the first text content will be used for deserialization.

Copilot uses AI. Check for mistakes.

@ccamel55ccamel55 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM but wouldn't this technically be a breaking change since it removes public facing API? I'll leave it to the maintainers to to decide though 😄

@4t145

Copy link
Copy Markdown
ContributorAuthor

@ccamel55 It's ok to introduce breaking changes, we haven't release the deleted api.

@jokemanfirejokemanfire left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can be Deserialized , so it is structed json data, If I understand it ?

@4t145
4t145 merged commit 1555c0f into modelcontextprotocol:mainAug 15, 2025
11 checks passed
@github-actionsgithub-actionsBot mentioned this pull request Aug 13, 2025
@snowmeadsnowmead mentioned this pull request Aug 19, 2025
9 tasks
takumi-earth pushed a commit to earthlings-dev/rmcp that referenced this pull request Jan 27, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

T-coreCore library changesT-handlerHandler implementation changesT-testTesting related changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@4t145@jokemanfire@ccamel55