Skip to content

Conversation

TomorJM
Copy link
Contributor

@TomorJM TomorJM commented Aug 8, 2025

When using GenAI's Schema.fromJson(jsonString) to convert tool schemas provided by some third-party MCP servers, a GenAiIOException is thrown. For example:

{
    "type": "object",
    "properties": {
        "address": {
            "title": "Address",
            "type": "string"
        },
        "city": {
            "anyOf": [
                {
                    "type": "string"
                },
                {
                    "type": "null"
                }
            ],
            "default": null,
            "title": "City"
        }
    },
    "required": [
        "address"
    ]
}

It will trigger a runtime exception.

Caused by: com.google.genai.errors.GenAiIOException: Failed to deserialize the JSON string.
	at com.google.genai.JsonSerializable.fromJsonString(JsonSerializable.java:128)
	at com.google.genai.types.Schema.fromJson(Schema.java:437)
	at com.google.adk.tools.mcp.McpTool.toGeminiSchema(McpTool.java:110)
	... 184 common frames omitted
Caused by: com.fasterxml.jackson.databind.JsonMappingException: N/A
 at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 140] (through reference chain: com.google.genai.types.AutoValue_Schema$Builder["properties"]->java.util.LinkedHashMap["city"]->com.google.genai.types.AutoValue_Schema$Builder["default"])
	at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:276)
	at com.fasterxml.jackson.databind.deser.SettableBeanProperty._throwAsIOE(SettableBeanProperty.java:628)
	at com.fasterxml.jackson.databind.deser.SettableBeanProperty._throwAsIOE(SettableBeanProperty.java:616)
	at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeSetAndReturn(MethodProperty.java:173)
	at com.fasterxml.jackson.databind.deser.BuilderBasedDeserializer.vanillaDeserialize(BuilderBasedDeserializer.java:294)
	at com.fasterxml.jackson.databind.deser.BuilderBasedDeserializer.deserialize(BuilderBasedDeserializer.java:218)
	at com.fasterxml.jackson.databind.deser.std.MapDeserializer._readAndBindStringKeyMap(MapDeserializer.java:623)
	at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:449)
	at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:32)
	at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeSetAndReturn(MethodProperty.java:158)
	at com.fasterxml.jackson.databind.deser.BuilderBasedDeserializer.vanillaDeserialize(BuilderBasedDeserializer.java:294)
	at com.fasterxml.jackson.databind.deser.BuilderBasedDeserializer.deserialize(BuilderBasedDeserializer.java:218)
	at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:342)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4917)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3860)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3828)
	at com.google.genai.JsonSerializable.fromJsonString(JsonSerializable.java:126)
	... 186 common frames omitted
Caused by: java.lang.NullPointerException: null
	at java.base/java.util.Objects.requireNonNull(Objects.java:208)
	at java.base/java.util.Optional.of(Optional.java:113)
	at com.google.genai.types.AutoValue_Schema$Builder.default_(AutoValue_Schema.java:407)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeSetAndReturn(MethodProperty.java:170)
	... 199 common frames omitted

This PR will help developers quickly identify the problematic tool.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Summary of Changes

Hello @TomorJM, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request aims to enhance the error logging for failures encountered during the conversion of MCP server tool schemas to Gemini schemas. Previously, a generic GenAiIOException was thrown, making it difficult to pinpoint the exact cause or the problematic tool. With these changes, developers will receive more detailed error messages, including the tool name and the specific JSON schema that failed conversion, facilitating quicker debugging.

Highlights

  • Improved Error Reporting: Enhanced the toGeminiSchema methods in McpAsyncTool and McpTool to catch conversion exceptions and re-throw them with more context.
  • New Exception Type: Introduced McpToolException and McpToolSchemaException to specifically categorize errors related to MCP tool schema conversion.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments or fill out our survey to provide feedback.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request improves error handling when converting MCP schemas by wrapping potential exceptions and providing more detailed error messages. My review focuses on improving the robustness of the exception handling and ensuring code style consistency. I've suggested replacing catch (Throwable) with catch (Exception) to avoid catching Errors, and I've also recommended a formatting change in the new exception class for better readability and consistency with the project's coding style.

@@ -104,7 +105,12 @@ public McpSyncClient getMcpSession() {
}

public Schema toGeminiSchema(JsonSchema openApiSchema) {
return Schema.fromJson(objectMapper.valueToTree(openApiSchema).toString());
Copy link
Member

Choose a reason for hiding this comment

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

Instead of copy/pasting these (few) lines here, how about instead adding a static Schema toGeminiSchema(JsonSchema openApiSchema) helper method to the

?

Copy link
Contributor

Choose a reason for hiding this comment

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

That's an excellent suggestion, @vorburger! Moving the toGeminiSchema logic to a static helper method in GeminiSchemaUtil.java would indeed prevent code duplication and centralize the schema conversion logic, improving maintainability.

I recommend creating a new static method in GeminiSchemaUtil.java like this:

// In core/src/main/java/com/google/adk/tools/mcp/GeminiSchemaUtil.java
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.adk.tools.mcp.McpToolException;
import com.google.genai.types.Schema;
import io.swagger.v3.oas.models.media.Schema as JsonSchema;

public final class GeminiSchemaUtil {
  private GeminiSchemaUtil() {}

  public static Schema toGeminiSchema(ObjectMapper objectMapper, JsonSchema openApiSchema, String toolName) {
    String jsonString = objectMapper.valueToTree(openApiSchema).toString();
    try {
      return Schema.fromJson(jsonString);
    } catch (Exception e) {
      throw new McpToolException.McpToolSchemaException(
          String.format("MCP tool:%s, schema:%s failed to convert openApiSchema to GeminiSchema.", toolName, jsonString), e);
    }
  }
}

Then, in McpTool.java (and similarly in McpAsyncTool.java), you can update the toGeminiSchema method to call this new utility method:

// In core/src/main/java/com/google/adk/tools/mcp/McpTool.java
// ... (imports)
import com.google.adk.tools.mcp.GeminiSchemaUtil;
// ...

  public Schema toGeminiSchema(JsonSchema openApiSchema) {
    return GeminiSchemaUtil.toGeminiSchema(objectMapper, openApiSchema, this.name());
  }

This approach aligns well with the goal of providing more detailed logs while also adhering to the DRY principle.

Comment on lines 17 to 32
}

}
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
}
}
}
}

But more generally speaking, the Maven build will automagically run google-java-format when you locally build this project.

Your Pull Requests as-is currently fail to build because you need to git commit --amend the reformatted code.

Also, Pull Requests must contain only a single commit.

This is due to how Google replicates this Git repository both into and from its
internal monorepo (see Wikipedia and
Paper)
with 🦛 Copybara.

When adjusting a PR to code review feedback, please use git commit --amend.

You can use git rebase -i main to meld/squash existing commits into one.

Then use git push --force-with-lease to update the branch of your PR.

We unfortunately cannot merge your PR until you fix both of this.

Copy link
Member

Choose a reason for hiding this comment

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

PS: We're going to document this more clearly in #357, just FYI.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But more generally speaking, the Maven build will automagically run google-java-format when you locally build this project.

Your Pull Requests as-is currently fail to build because you need to git commit --amend the reformatted code.

Also, Pull Requests must contain only a single commit.

This is due to how Google replicates this Git repository both into and from its internal monorepo (see Wikipedia and Paper) with 🦛 Copybara.

When adjusting a PR to code review feedback, please use git commit --amend.

You can use git rebase -i main to meld/squash existing commits into one.

Then use git push --force-with-lease to update the branch of your PR.

We unfortunately cannot merge your PR until you fix both of this.

OK,I will fix it later. Thank you for your advice~

@vorburger
Copy link
Member

@TomorJM FYI #358 ... perhaps it's easier if you wait for that to get merged first, and only then rebase this one?

@TomorJM
Copy link
Contributor Author

TomorJM commented Aug 16, 2025

@TomorJM FYI #358 ... perhaps it's easier if you wait for that to get merged first, and only then rebase this one?

ok

@TomorJM TomorJM force-pushed the github_dev_mcp_tool_schema_log branch from 2741ca2 to 181fdbd Compare August 16, 2025 16:24
@TomorJM TomorJM changed the title feat: provide more detailed logs when mcp schema conversion fails. feat: provide more detailed logs when mcp tool declaration failed. Aug 16, 2025
@TomorJM
Copy link
Contributor Author

TomorJM commented Aug 16, 2025

@vorburger Thank you very much for your valuable suggestions. In the new submission, I have adapted the optimization of AbstractMcpTool as you suggested, and modified the code that originally captured exceptions during the schema conversion process, thereby enabling comprehensive exception handling and detailed logging for the entire declaration.😁

@TomorJM TomorJM force-pushed the github_dev_mcp_tool_schema_log branch from 181fdbd to 92206b5 Compare August 16, 2025 16:40
Copy link
Member

@vorburger vorburger left a comment

Choose a reason for hiding this comment

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

@TomorJM this is great! Thank You for having reworking it.

The build is still failing due to a formatting issue, but this is very minor, now.

If you fix that, I'd love to LGTM this!

Keep your contributions coming!!

@TomorJM TomorJM force-pushed the github_dev_mcp_tool_schema_log branch from 6d6130b to 1c86d92 Compare August 17, 2025 02:02
@TomorJM
Copy link
Contributor Author

TomorJM commented Aug 17, 2025

@TomorJM this is great! Thank You for having reworking it.

The build is still failing due to a formatting issue, but this is very minor, now.

If you fix that, I'd love to LGTM this!

Keep your contributions coming!!

fixed~

Copy link
Member

@vorburger vorburger left a comment

Choose a reason for hiding this comment

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

LGMT. We'll get this merged ASAP.

@vorburger vorburger force-pushed the github_dev_mcp_tool_schema_log branch from 1c86d92 to 4d5b63a Compare August 18, 2025 11:49
@copybara-service copybara-service bot merged commit 806e985 into google:main Aug 18, 2025
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants