Skip to content

ToolInputSchema doesn't inherit MarshalJSON from ToolArgumentsSchema #694

@BTForIT

Description

@BTForIT

Description

ToolInputSchema is defined as a type definition (not a type alias) of ToolArgumentsSchema:

type ToolInputSchema ToolArgumentsSchema // For retro-compatibility

This means ToolInputSchema does not inherit the MarshalJSON method from ToolArgumentsSchema. As a result, when marshaling a Tool struct, the inputSchema field loses important data.

Reproduction

package main

import (
	"encoding/json"
	"fmt"
	"github.com/mark3labs/mcp-go/mcp"
)

func main() {
	schema := mcp.ToolInputSchema{
		Type:       "object",
		Properties: map[string]any{},  // empty but not nil
	}
	
	b, _ := json.Marshal(schema)
	fmt.Println(string(b))
	// Output: {"type":"object"}
	// Expected: {"properties":{},"type":"object"}
}

Impact

This breaks compatibility with systems that require properties to be present in JSON schemas, even when empty. For example, Letta's schema validation fails when properties is missing:

Failed to auto-sync tools from MCP server: {'type': 'object', 'additionalProperties': False}. 
Server was created successfully but tools were not persisted.

Suggested Fix

Change the type definition to a true type alias:

type ToolInputSchema = ToolArgumentsSchema // true alias, inherits methods

Or add a separate MarshalJSON method for ToolInputSchema:

func (tis ToolInputSchema) MarshalJSON() ([]byte, error) {
    return ToolArgumentsSchema(tis).MarshalJSON()
}

Environment

  • mcp-go version: v0.41.1 (also verified in v0.43.2)
  • Go version: 1.21+

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions