DS DevShelfHub Projects · AI tools
Tutorials / MCP / Tools Deep Dive
MCP Intermediate · 9 min read Page 7 of 23

MCP Tools: Input Schemas and Error Handling

By DevShelfHub

Master tool design: JSON Schema for inputs, proper result formatting, error handling, and best practices for naming and describing tools.

Series progress7 / 23
MCP tools deep dive — JSON Schema input validation and error handling

Input schemas with JSON Schema

Tools take inputs. The inputSchema field describes what the tool expects using JSON Schema. Claude reads this to decide when and how to call your tool.

json
"inputSchema": {
  "type": "object",
  "properties": {
    "query": {
      "type": "string",
      "description": "Search query"
    },
    "limit": {
      "type": "integer",
      "description": "Max results",
      "default": 10
    }
  },
  "required": ["query"]
}

required fields must be provided by Claude. Optional fields have defaults.

Tool naming and descriptions

Claude reads your tool name and description to decide when to use it. Write them to be crystal clear:

Good: "search_google" — "Search Google for web results"

Better: "web_search" — "Search the web for current information. Use this when the user asks questions about recent events or needs up-to-date information."

Include context: when should Claude use this tool? What can it do well?

Returning results

Tools can return text, structured data, or images. Always return results as a list of Content objects:

from mcp.types import TextContent, ImageContent

# Text result
return [TextContent(type="text", text="Hello")]

# JSON data
import json
return [TextContent(
    type="text",
    text=json.dumps({"status": "ok", "count": 5})
)]

# Image
return [ImageContent(
    type="image",
    data="base64_encoded_image_data",
    mimeType="image/png"
)]

Error handling

When a tool encounters an error, be explicit about it:

python
from mcp.types import TextContent
from mcp.server import McpError

@server.call_tool()
def call_tool(name: str, arguments: dict):
    try:
        # Your tool logic
        result = do_something(arguments)
        return [TextContent(type="text", text=result)]
    except ValueError as e:
        # Return error as content
        return [TextContent(
            type="text",
            text=f"Error: Invalid input. {str(e)}"
        )]
    except Exception as e:
        # Or raise McpError for critical failures
        raise McpError(f"Tool failed: {str(e)}")

Return errors as text content when the user should see them. Raise McpError for system failures.

Best practices for tools

💡 Single responsibility

One tool = one task. "search_web" is better than "general_assistant_function".

💡 Clear inputs

Required fields should be essential. Optional fields need sensible defaults.

💡 Consistent output format

Always return the same structure. If you return JSON, keep the schema consistent.

💡 Document edge cases

What happens if the tool is called with invalid input? Include that in the description.

Quick summary

  • Define inputSchema using JSON Schema — tell Claude what your tool expects
  • Write tool names and descriptions for clarity — Claude relies on them
  • Return results as Content objects (text, JSON, or images)
  • Handle errors gracefully — return error messages or raise McpError
  • Follow best practices: single responsibility, clear inputs, consistent output

MCP Tools Deep Dive FAQ

How do you define a JSON Schema for an MCP tool?

Each MCP tool has an inputSchema field containing a JSON Schema object that describes expected parameters. Include type, description, and required fields so the AI model knows how to call the tool correctly.

What is the difference between a tool error and an isError result?

A JSON-RPC error (thrown as an exception) means the tool invocation itself failed at the protocol level. An isError: true result means the tool ran but its operation failed — the model can read the error message and decide what to do next.

What are MCP tool annotations?

Tool annotations (readOnlyHint, destructiveHint, idempotentHint, openWorldHint) are metadata hints that tell hosts and models about a tool's side effects. They help clients decide whether to show confirmation dialogs or allow automatic execution.

How should MCP tools be named?

Use lowercase snake_case names that are verb-first and descriptive — e.g., get_weather, create_issue, search_documents. Avoid generic names like 'run' or 'execute'. A clear name helps the model pick the right tool.

Can MCP tools return multiple content types?

Yes. Tool results can include text, images (base64 encoded), and embedded resources. Use the content array with typed objects — TextContent, ImageContent, or EmbeddedResource — to return mixed-type results.

Quick jump: API Reference