package mcp

import (
	
	
	
	
	
	

	
)

var errToolSchemaConflict = errors.New("provide either InputSchema or RawInputSchema, not both")

// ListToolsRequest is sent from the client to request a list of tools the
// server has.
type ListToolsRequest struct {
	PaginatedRequest
	Header http.Header `json:"-"`
}

// ListToolsResult is the server's response to a tools/list request from the
// client.
type ListToolsResult struct {
	PaginatedResult
	Tools []Tool `json:"tools"`
}

// CallToolResult is the server's response to a tool call.
//
// Any errors that originate from the tool SHOULD be reported inside the result
// object, with `isError` set to true, _not_ as an MCP protocol-level error
// response. Otherwise, the LLM would not be able to see that an error occurred
// and self-correct.
//
// However, any errors in _finding_ the tool, an error indicating that the
// server does not support tool calls, or any other exceptional conditions,
// should be reported as an MCP error response.
type CallToolResult struct {
	Result
	Content []Content `json:"content"` // Can be TextContent, ImageContent, AudioContent, or EmbeddedResource
	// Structured content returned as a JSON object in the structuredContent field of a result.
	// For backwards compatibility, a tool that returns structured content SHOULD also return
	// functionally equivalent unstructured content.
	StructuredContent any `json:"structuredContent,omitempty"`
	// Whether the tool call ended in an error.
	//
	// If not set, this is assumed to be false (the call was successful).
	IsError bool `json:"isError,omitempty"`
}

// CallToolRequest is used by the client to invoke a tool provided by the server.
type CallToolRequest struct {
	Request
	Header http.Header    `json:"-"` // HTTP headers from the original request
	Params CallToolParams `json:"params"`
}

type CallToolParams struct {
	Name      string      `json:"name"`
	Arguments any         `json:"arguments,omitempty"`
	Meta      *Meta       `json:"_meta,omitempty"`
	Task      *TaskParams `json:"task,omitempty"`
}

// GetArguments returns the Arguments as map[string]any for backward compatibility
// If Arguments is not a map, it returns an empty map
func ( CallToolRequest) () map[string]any {
	if ,  := .Params.Arguments.(map[string]any);  {
		return 
	}
	return nil
}

// GetRawArguments returns the Arguments as-is without type conversion
// This allows users to access the raw arguments in any format
func ( CallToolRequest) () any {
	return .Params.Arguments
}

// BindArguments unmarshals the Arguments into the provided struct
// This is useful for working with strongly-typed arguments
func ( CallToolRequest) ( any) error {
	if  == nil || reflect.ValueOf().Kind() != reflect.Ptr {
		return fmt.Errorf("target must be a non-nil pointer")
	}

	// Fast-path: already raw JSON
	if ,  := .Params.Arguments.(json.RawMessage);  {
		return json.Unmarshal(, )
	}

	,  := json.Marshal(.Params.Arguments)
	if  != nil {
		return fmt.Errorf("failed to marshal arguments: %w", )
	}

	return json.Unmarshal(, )
}

// GetString returns a string argument by key, or the default value if not found
func ( CallToolRequest) ( string,  string) string {
	 := .GetArguments()
	if ,  := [];  {
		if ,  := .(string);  {
			return 
		}
	}
	return 
}

// RequireString returns a string argument by key, or an error if not found or not a string
func ( CallToolRequest) ( string) (string, error) {
	 := .GetArguments()
	if ,  := [];  {
		if ,  := .(string);  {
			return , nil
		}
		return "", fmt.Errorf("argument %q is not a string", )
	}
	return "", fmt.Errorf("required argument %q not found", )
}

// GetInt returns an int argument by key, or the default value if not found
func ( CallToolRequest) ( string,  int) int {
	 := .GetArguments()
	if ,  := [];  {
		switch v := .(type) {
		case int:
			return 
		case float64:
			return int()
		case string:
			if ,  := strconv.Atoi();  == nil {
				return 
			}
		}
	}
	return 
}

// RequireInt returns an int argument by key, or an error if not found or not convertible to int
func ( CallToolRequest) ( string) (int, error) {
	 := .GetArguments()
	if ,  := [];  {
		switch v := .(type) {
		case int:
			return , nil
		case float64:
			return int(), nil
		case string:
			if ,  := strconv.Atoi();  == nil {
				return , nil
			}
			return 0, fmt.Errorf("argument %q cannot be converted to int", )
		default:
			return 0, fmt.Errorf("argument %q is not an int", )
		}
	}
	return 0, fmt.Errorf("required argument %q not found", )
}

// GetFloat returns a float64 argument by key, or the default value if not found
func ( CallToolRequest) ( string,  float64) float64 {
	 := .GetArguments()
	if ,  := [];  {
		switch v := .(type) {
		case float64:
			return 
		case int:
			return float64()
		case string:
			if ,  := strconv.ParseFloat(, 64);  == nil {
				return 
			}
		}
	}
	return 
}

// RequireFloat returns a float64 argument by key, or an error if not found or not convertible to float64
func ( CallToolRequest) ( string) (float64, error) {
	 := .GetArguments()
	if ,  := [];  {
		switch v := .(type) {
		case float64:
			return , nil
		case int:
			return float64(), nil
		case string:
			if ,  := strconv.ParseFloat(, 64);  == nil {
				return , nil
			}
			return 0, fmt.Errorf("argument %q cannot be converted to float64", )
		default:
			return 0, fmt.Errorf("argument %q is not a float64", )
		}
	}
	return 0, fmt.Errorf("required argument %q not found", )
}

// GetBool returns a bool argument by key, or the default value if not found
func ( CallToolRequest) ( string,  bool) bool {
	 := .GetArguments()
	if ,  := [];  {
		switch v := .(type) {
		case bool:
			return 
		case string:
			if ,  := strconv.ParseBool();  == nil {
				return 
			}
		case int:
			return  != 0
		case float64:
			return  != 0
		}
	}
	return 
}

// RequireBool returns a bool argument by key, or an error if not found or not convertible to bool
func ( CallToolRequest) ( string) (bool, error) {
	 := .GetArguments()
	if ,  := [];  {
		switch v := .(type) {
		case bool:
			return , nil
		case string:
			if ,  := strconv.ParseBool();  == nil {
				return , nil
			}
			return false, fmt.Errorf("argument %q cannot be converted to bool", )
		case int:
			return  != 0, nil
		case float64:
			return  != 0, nil
		default:
			return false, fmt.Errorf("argument %q is not a bool", )
		}
	}
	return false, fmt.Errorf("required argument %q not found", )
}

// GetStringSlice returns a string slice argument by key, or the default value if not found
func ( CallToolRequest) ( string,  []string) []string {
	 := .GetArguments()
	if ,  := [];  {
		switch v := .(type) {
		case []string:
			return 
		case []any:
			 := make([]string, 0, len())
			for ,  := range  {
				if ,  := .(string);  {
					 = append(, )
				}
			}
			return 
		}
	}
	return 
}

// RequireStringSlice returns a string slice argument by key, or an error if not found or not convertible to string slice
func ( CallToolRequest) ( string) ([]string, error) {
	 := .GetArguments()
	if ,  := [];  {
		switch v := .(type) {
		case []string:
			return , nil
		case []any:
			 := make([]string, 0, len())
			for ,  := range  {
				if ,  := .(string);  {
					 = append(, )
				} else {
					return nil, fmt.Errorf("item %d in argument %q is not a string", , )
				}
			}
			return , nil
		default:
			return nil, fmt.Errorf("argument %q is not a string slice", )
		}
	}
	return nil, fmt.Errorf("required argument %q not found", )
}

// GetIntSlice returns an int slice argument by key, or the default value if not found
func ( CallToolRequest) ( string,  []int) []int {
	 := .GetArguments()
	if ,  := [];  {
		switch v := .(type) {
		case []int:
			return 
		case []any:
			 := make([]int, 0, len())
			for ,  := range  {
				switch num := .(type) {
				case int:
					 = append(, )
				case float64:
					 = append(, int())
				case string:
					if ,  := strconv.Atoi();  == nil {
						 = append(, )
					}
				}
			}
			return 
		}
	}
	return 
}

// RequireIntSlice returns an int slice argument by key, or an error if not found or not convertible to int slice
func ( CallToolRequest) ( string) ([]int, error) {
	 := .GetArguments()
	if ,  := [];  {
		switch v := .(type) {
		case []int:
			return , nil
		case []any:
			 := make([]int, 0, len())
			for ,  := range  {
				switch num := .(type) {
				case int:
					 = append(, )
				case float64:
					 = append(, int())
				case string:
					if ,  := strconv.Atoi();  == nil {
						 = append(, )
					} else {
						return nil, fmt.Errorf("item %d in argument %q cannot be converted to int", , )
					}
				default:
					return nil, fmt.Errorf("item %d in argument %q is not an int", , )
				}
			}
			return , nil
		default:
			return nil, fmt.Errorf("argument %q is not an int slice", )
		}
	}
	return nil, fmt.Errorf("required argument %q not found", )
}

// GetFloatSlice returns a float64 slice argument by key, or the default value if not found
func ( CallToolRequest) ( string,  []float64) []float64 {
	 := .GetArguments()
	if ,  := [];  {
		switch v := .(type) {
		case []float64:
			return 
		case []any:
			 := make([]float64, 0, len())
			for ,  := range  {
				switch num := .(type) {
				case float64:
					 = append(, )
				case int:
					 = append(, float64())
				case string:
					if ,  := strconv.ParseFloat(, 64);  == nil {
						 = append(, )
					}
				}
			}
			return 
		}
	}
	return 
}

// RequireFloatSlice returns a float64 slice argument by key, or an error if not found or not convertible to float64 slice
func ( CallToolRequest) ( string) ([]float64, error) {
	 := .GetArguments()
	if ,  := [];  {
		switch v := .(type) {
		case []float64:
			return , nil
		case []any:
			 := make([]float64, 0, len())
			for ,  := range  {
				switch num := .(type) {
				case float64:
					 = append(, )
				case int:
					 = append(, float64())
				case string:
					if ,  := strconv.ParseFloat(, 64);  == nil {
						 = append(, )
					} else {
						return nil, fmt.Errorf("item %d in argument %q cannot be converted to float64", , )
					}
				default:
					return nil, fmt.Errorf("item %d in argument %q is not a float64", , )
				}
			}
			return , nil
		default:
			return nil, fmt.Errorf("argument %q is not a float64 slice", )
		}
	}
	return nil, fmt.Errorf("required argument %q not found", )
}

// GetBoolSlice returns a bool slice argument by key, or the default value if not found
func ( CallToolRequest) ( string,  []bool) []bool {
	 := .GetArguments()
	if ,  := [];  {
		switch v := .(type) {
		case []bool:
			return 
		case []any:
			 := make([]bool, 0, len())
			for ,  := range  {
				switch b := .(type) {
				case bool:
					 = append(, )
				case string:
					if ,  := strconv.ParseBool();  == nil {
						 = append(, )
					}
				case int:
					 = append(,  != 0)
				case float64:
					 = append(,  != 0)
				}
			}
			return 
		}
	}
	return 
}

// RequireBoolSlice returns a bool slice argument by key, or an error if not found or not convertible to bool slice
func ( CallToolRequest) ( string) ([]bool, error) {
	 := .GetArguments()
	if ,  := [];  {
		switch v := .(type) {
		case []bool:
			return , nil
		case []any:
			 := make([]bool, 0, len())
			for ,  := range  {
				switch b := .(type) {
				case bool:
					 = append(, )
				case string:
					if ,  := strconv.ParseBool();  == nil {
						 = append(, )
					} else {
						return nil, fmt.Errorf("item %d in argument %q cannot be converted to bool", , )
					}
				case int:
					 = append(,  != 0)
				case float64:
					 = append(,  != 0)
				default:
					return nil, fmt.Errorf("item %d in argument %q is not a bool", , )
				}
			}
			return , nil
		default:
			return nil, fmt.Errorf("argument %q is not a bool slice", )
		}
	}
	return nil, fmt.Errorf("required argument %q not found", )
}

// MarshalJSON implements custom JSON marshaling for CallToolResult
func ( CallToolResult) () ([]byte, error) {
	 := make(map[string]any)

	// Marshal Meta if present
	if .Meta != nil {
		["_meta"] = .Meta
	}

	// Marshal Content array
	 := make([]any, len(.Content))
	for ,  := range .Content {
		[] = 
	}
	["content"] = 

	// Marshal StructuredContent if present
	if .StructuredContent != nil {
		["structuredContent"] = .StructuredContent
	}

	// Marshal IsError if true
	if .IsError {
		["isError"] = .IsError
	}

	return json.Marshal()
}

// UnmarshalJSON implements custom JSON unmarshaling for CallToolResult
func ( *CallToolResult) ( []byte) error {
	var  map[string]any
	if  := json.Unmarshal(, &);  != nil {
		return 
	}

	// Unmarshal Meta
	if ,  := ["_meta"];  {
		if ,  := .(map[string]any);  {
			.Meta = NewMetaFromMap()
		}
	}

	// Unmarshal Content array
	if ,  := ["content"];  {
		if ,  := .([]any);  {
			.Content = make([]Content, len())
			for ,  := range  {
				,  := json.Marshal()
				if  != nil {
					return 
				}
				,  := UnmarshalContent()
				if  != nil {
					return 
				}
				.Content[] = 
			}
		}
	}

	// Unmarshal StructuredContent if present
	if ,  := ["structuredContent"];  {
		.StructuredContent = 
	}

	// Unmarshal IsError
	if ,  := ["isError"];  {
		if ,  := .(bool);  {
			.IsError = 
		}
	}

	return nil
}

// ToolListChangedNotification is an optional notification from the server to
// the client, informing it that the list of tools it offers has changed. This may
// be issued by servers without any previous subscription from the client.
type ToolListChangedNotification struct {
	Notification
}

// TaskSupport indicates how a tool supports task augmentation.
type TaskSupport string

const (
	// TaskSupportForbidden means the tool cannot be invoked as a task (default).
	TaskSupportForbidden TaskSupport = "forbidden"
	// TaskSupportOptional means the tool can be invoked as a task or normally.
	TaskSupportOptional TaskSupport = "optional"
	// TaskSupportRequired means the tool must be invoked as a task.
	TaskSupportRequired TaskSupport = "required"
)

// ToolExecution describes execution behavior for a tool.
type ToolExecution struct {
	// TaskSupport indicates whether the tool supports task augmentation.
	TaskSupport TaskSupport `json:"taskSupport,omitempty"`
}

// Tool represents the definition for a tool the client can call.
type Tool struct {
	// Meta is a metadata object that is reserved by MCP for storing additional information.
	Meta *Meta `json:"_meta,omitempty"`
	// The name of the tool.
	Name string `json:"name"`
	// A human-readable description of the tool.
	Description string `json:"description,omitempty"`
	// A JSON Schema object defining the expected parameters for the tool.
	InputSchema ToolInputSchema `json:"inputSchema"`
	// Alternative to InputSchema - allows arbitrary JSON Schema to be provided
	RawInputSchema json.RawMessage `json:"-"` // Hide this from JSON marshaling
	// A JSON Schema object defining the expected output returned by the tool .
	OutputSchema ToolOutputSchema `json:"outputSchema,omitempty"`
	// Optional JSON Schema defining expected output structure
	RawOutputSchema json.RawMessage `json:"-"` // Hide this from JSON marshaling
	// Optional properties describing tool behavior
	Annotations ToolAnnotation `json:"annotations"`
	// Support for deferred loading
	DeferLoading bool `json:"defer_loading,omitempty"`
	// Icons provides visual identifiers for the tool
	Icons []Icon `json:"icons,omitempty"`
	// Execution describes execution behavior for the tool
	Execution *ToolExecution `json:"execution,omitempty"`
}

// GetName returns the name of the tool.
func ( Tool) () string {
	return .Name
}

// MarshalJSON implements the json.Marshaler interface for Tool.
// It handles marshaling either InputSchema or RawInputSchema based on which is set.
func ( Tool) () ([]byte, error) {
	// Create a map to build the JSON structure
	 := make(map[string]any, 5)

	// Add the name and description
	["name"] = .Name
	if .Description != "" {
		["description"] = .Description
	}

	// Determine which input schema to use
	if .RawInputSchema != nil {
		if .InputSchema.Type != "" {
			return nil, fmt.Errorf("tool %s has both InputSchema and RawInputSchema set: %w", .Name, errToolSchemaConflict)
		}
		["inputSchema"] = .RawInputSchema
	} else {
		// Use the structured InputSchema
		["inputSchema"] = .InputSchema
	}

	// Add output schema if present
	if .RawOutputSchema != nil {
		if .OutputSchema.Type != "" {
			return nil, fmt.Errorf("tool %s has both OutputSchema and RawOutputSchema set: %w", .Name, errToolSchemaConflict)
		}
		["outputSchema"] = .RawOutputSchema
	} else if .OutputSchema.Type != "" { // If no output schema is specified, do not return anything
		["outputSchema"] = .OutputSchema
	}

	["annotations"] = .Annotations

	if .DeferLoading {
		["defer_loading"] = .DeferLoading
	}

	// Marshal Meta if present
	if .Meta != nil {
		["_meta"] = .Meta
	}

	if .Icons != nil {
		["icons"] = .Icons
	}

	if .Execution != nil {
		["execution"] = .Execution
	}

	return json.Marshal()
}

// ToolArgumentsSchema represents a JSON Schema for tool arguments.
type ToolArgumentsSchema struct {
	Defs                 map[string]any `json:"$defs,omitempty"`
	Type                 string         `json:"type"`
	Properties           map[string]any `json:"properties"`
	Required             []string       `json:"required,omitempty"`
	AdditionalProperties any            `json:"additionalProperties,omitempty"`
}

type ToolInputSchema ToolArgumentsSchema // For retro-compatibility
type ToolOutputSchema ToolArgumentsSchema

// MarshalJSON implements the json.Marshaler interface for ToolInputSchema.
func ( ToolInputSchema) () ([]byte, error) {
	return toolArgumentsSchemaMarshalJSON(ToolArgumentsSchema())
}

// MarshalJSON implements the json.Marshaler interface for ToolOutputSchema.
func ( ToolOutputSchema) () ([]byte, error) {
	return toolArgumentsSchemaMarshalJSON(ToolArgumentsSchema())
}

// MarshalJSON implements the json.Marshaler interface for ToolArgumentsSchema.
func ( ToolArgumentsSchema) () ([]byte, error) {
	return toolArgumentsSchemaMarshalJSON()
}

// UnmarshalJSON implements the json.Unmarshaler interface for ToolInputSchema.
func ( *ToolInputSchema) ( []byte) error {
	return toolArgumentsSchemaUnmarshalJSON(, (*ToolArgumentsSchema)())
}

// UnmarshalJSON implements the json.Unmarshaler interface for ToolOutputSchema.
func ( *ToolOutputSchema) ( []byte) error {
	return toolArgumentsSchemaUnmarshalJSON(, (*ToolArgumentsSchema)())
}

// UnmarshalJSON implements the json.Unmarshaler interface for ToolArgumentsSchema.
func ( *ToolArgumentsSchema) ( []byte) error {
	return toolArgumentsSchemaUnmarshalJSON(, )
}

// toolArgumentsSchemaMarshalJSON handles the fields stored in ToolArgumentsSchema when json.Marshaler is called
func toolArgumentsSchemaMarshalJSON( ToolArgumentsSchema) ([]byte, error) {
	 := make(map[string]any)
	["type"] = .Type

	if .Defs != nil {
		["$defs"] = .Defs
	}

	// Marshal Properties to '{}' rather than `nil` when its length equals zero
	if .Properties != nil {
		["properties"] = .Properties
	} else {
		["properties"] = map[string]any{}
	}

	// Marshal Required to '[]' rather than `nil` when its length equals zero
	if len(.Required) > 0 {
		["required"] = .Required
	} else {
		["required"] = []string{}
	}

	if .AdditionalProperties != nil {
		["additionalProperties"] = .AdditionalProperties
	}

	return json.Marshal()
}

// It handles both "$defs" (JSON Schema 2019-09+) and "definitions" (JSON Schema draft-07)
// by reading either field and storing it in the Defs field.
func toolArgumentsSchemaUnmarshalJSON( []byte,  *ToolArgumentsSchema) error {
	// Use a temporary type to avoid infinite recursion
	type  ToolArgumentsSchema
	 := &struct {
		 map[string]any `json:"definitions,omitempty"`
		*
	}{
		: (*)(),
	}

	if  := json.Unmarshal(, );  != nil {
		return 
	}

	// If $defs wasn't provided but definitions was, use definitions
	if .Defs == nil && . != nil {
		.Defs = .
	}

	return nil
}

type ToolAnnotation struct {
	// Human-readable title for the tool
	Title string `json:"title,omitempty"`
	// If true, the tool does not modify its environment
	ReadOnlyHint *bool `json:"readOnlyHint,omitempty"`
	// If true, the tool may perform destructive updates
	DestructiveHint *bool `json:"destructiveHint,omitempty"`
	// If true, repeated calls with same args have no additional effect
	IdempotentHint *bool `json:"idempotentHint,omitempty"`
	// If true, tool interacts with external entities
	OpenWorldHint *bool `json:"openWorldHint,omitempty"`
}

// ToolOption is a function that configures a Tool.
// It provides a flexible way to set various properties of a Tool using the functional options pattern.
type ToolOption func(*Tool)

// PropertyOption is a function that configures a property in a Tool's input schema.
// It allows for flexible configuration of JSON Schema properties using the functional options pattern.
type PropertyOption func(map[string]any)

//
// Core Tool Functions
//

// NewTool creates a new Tool with the given name and options.
// The tool will have an object-type input schema with configurable properties.
// Options are applied in order, allowing for flexible tool configuration.
func ( string,  ...ToolOption) Tool {
	 := Tool{
		Name: ,
		InputSchema: ToolInputSchema{
			Type:       "object",
			Properties: make(map[string]any),
			Required:   nil, // Will be omitted from JSON if empty
		},
		Annotations: ToolAnnotation{
			Title:           "",
			ReadOnlyHint:    ToBoolPtr(false),
			DestructiveHint: ToBoolPtr(true),
			IdempotentHint:  ToBoolPtr(false),
			OpenWorldHint:   ToBoolPtr(true),
		},
	}

	for ,  := range  {
		(&)
	}

	return 
}

// NewToolWithRawSchema creates a new Tool with the given name and a raw JSON
// Schema. This allows for arbitrary JSON Schema to be used for the tool's input
// schema.
//
// NOTE a [Tool] built in such a way is incompatible with the [ToolOption] and
// runtime errors will result from supplying a [ToolOption] to a [Tool] built
// with this function.
func (,  string,  json.RawMessage) Tool {
	 := Tool{
		Name:           ,
		Description:    ,
		RawInputSchema: ,
	}

	return 
}

// WithDescription adds a description to the Tool.
// The description should provide a clear, human-readable explanation of what the tool does.
func ( string) ToolOption {
	return func( *Tool) {
		.Description = 
	}
}

// WithDeferLoading sets the defer_loading flag for the tool.
// This is used to implement dynamic tool loading/searching patterns.
func ( bool) ToolOption {
	return func( *Tool) {
		.DeferLoading = 
	}
}

// WithInputSchema creates a ToolOption that sets the input schema for a tool.
// It accepts any Go type, usually a struct, and automatically generates a JSON schema from it.
func [ any]() ToolOption {
	return func( *Tool) {
		,  := jsonschema.For[](&jsonschema.ForOptions{IgnoreInvalidTypes: true})
		if  != nil {
			return
		}

		,  := json.Marshal()
		if  != nil {
			return
		}

		.InputSchema.Type = ""
		.RawInputSchema = json.RawMessage()
	}
}

// WithToolIcons adds icons to the Tool.
// Icons provide visual identifiers for the tool.
func ( ...Icon) ToolOption {
	return func( *Tool) {
		.Icons = 
	}
}

// WithTaskSupport sets the task support mode for the tool.
// It configures whether the tool can be invoked as a task (asynchronously).
// Valid values are TaskSupportForbidden (default), TaskSupportOptional, or TaskSupportRequired.
func ( TaskSupport) ToolOption {
	return func( *Tool) {
		if .Execution == nil {
			.Execution = &ToolExecution{}
		}
		.Execution.TaskSupport = 
	}
}

// WithRawInputSchema sets a raw JSON schema for the tool's input.
// Use this when you need full control over the schema or when working with
// complex schemas that can't be generated from Go types. The jsonschema library
// can handle complex schemas and provides nice extension points, so be sure to
// check that out before using this.
func ( json.RawMessage) ToolOption {
	return func( *Tool) {
		.RawInputSchema = 
	}
}

// WithOutputSchema creates a ToolOption that sets the output schema for a tool.
// It accepts any Go type, usually a struct, and automatically generates a JSON schema from it.
func [ any]() ToolOption {
	return func( *Tool) {
		,  := jsonschema.For[](&jsonschema.ForOptions{IgnoreInvalidTypes: true})
		if  != nil {
			return
		}

		,  := json.Marshal()
		if  != nil {
			return
		}

		if  := json.Unmarshal(, &.OutputSchema);  != nil {
			return
		}

		// Always set the type to "object" as of the current MCP spec
		// https://modelcontextprotocol.io/specification/2025-06-18/server/tools#output-schema
		.OutputSchema.Type = "object"
	}
}

// WithRawOutputSchema sets a raw JSON schema for the tool's output.
// Use this when you need full control over the schema or when working with
// complex schemas that can't be generated from Go types. The jsonschema library
// can handle complex schemas and provides nice extension points, so be sure to
// check that out before using this.
func ( json.RawMessage) ToolOption {
	return func( *Tool) {
		.RawOutputSchema = 
	}
}

// WithToolAnnotation adds optional hints about the Tool.
func ( ToolAnnotation) ToolOption {
	return func( *Tool) {
		.Annotations = 
	}
}

// WithTitleAnnotation sets the Title field of the Tool's Annotations.
// It provides a human-readable title for the tool.
func ( string) ToolOption {
	return func( *Tool) {
		.Annotations.Title = 
	}
}

// WithReadOnlyHintAnnotation sets the ReadOnlyHint field of the Tool's Annotations.
// If true, it indicates the tool does not modify its environment.
func ( bool) ToolOption {
	return func( *Tool) {
		.Annotations.ReadOnlyHint = &
	}
}

// WithDestructiveHintAnnotation sets the DestructiveHint field of the Tool's Annotations.
// If true, it indicates the tool may perform destructive updates.
func ( bool) ToolOption {
	return func( *Tool) {
		.Annotations.DestructiveHint = &
	}
}

// WithIdempotentHintAnnotation sets the IdempotentHint field of the Tool's Annotations.
// If true, it indicates repeated calls with the same arguments have no additional effect.
func ( bool) ToolOption {
	return func( *Tool) {
		.Annotations.IdempotentHint = &
	}
}

// WithOpenWorldHintAnnotation sets the OpenWorldHint field of the Tool's Annotations.
// If true, it indicates the tool interacts with external entities.
func ( bool) ToolOption {
	return func( *Tool) {
		.Annotations.OpenWorldHint = &
	}
}

// WithSchemaAdditionalProperties sets the additionalProperties field on the tool's input schema.
// It accepts false (disallow extra properties), true (allow any), or a schema map
// to validate additional properties against.
func ( any) ToolOption {
	return func( *Tool) {
		.InputSchema.AdditionalProperties = 
	}
}

//
// Common Property Options
//

// Description adds a description to a property in the JSON Schema.
// The description should explain the purpose and expected values of the property.
func ( string) PropertyOption {
	return func( map[string]any) {
		["description"] = 
	}
}

// Required marks a property as required in the tool's input schema.
// Required properties must be provided when using the tool.
func () PropertyOption {
	return func( map[string]any) {
		["required"] = true
	}
}

// Title adds a display-friendly title to a property in the JSON Schema.
// This title can be used by UI components to show a more readable property name.
func ( string) PropertyOption {
	return func( map[string]any) {
		["title"] = 
	}
}

//
// String Property Options
//

// DefaultString sets the default value for a string property.
// This value will be used if the property is not explicitly provided.
func ( string) PropertyOption {
	return func( map[string]any) {
		["default"] = 
	}
}

// Enum specifies a list of allowed values for a string property.
// The property value must be one of the specified enum values.
func ( ...string) PropertyOption {
	return func( map[string]any) {
		["enum"] = 
	}
}

// MaxLength sets the maximum length for a string property.
// The string value must not exceed this length.
func ( int) PropertyOption {
	return func( map[string]any) {
		["maxLength"] = 
	}
}

// MinLength sets the minimum length for a string property.
// The string value must be at least this length.
func ( int) PropertyOption {
	return func( map[string]any) {
		["minLength"] = 
	}
}

// Pattern sets a regex pattern that a string property must match.
// The string value must conform to the specified regular expression.
func ( string) PropertyOption {
	return func( map[string]any) {
		["pattern"] = 
	}
}

//
// Number Property Options
//

// DefaultNumber sets the default value for a number property.
// This value will be used if the property is not explicitly provided.
func ( float64) PropertyOption {
	return func( map[string]any) {
		["default"] = 
	}
}

// Max sets the maximum value for a number property.
// The number value must not exceed this maximum.
func ( float64) PropertyOption {
	return func( map[string]any) {
		["maximum"] = 
	}
}

// Min sets the minimum value for a number property.
// The number value must not be less than this minimum.
func ( float64) PropertyOption {
	return func( map[string]any) {
		["minimum"] = 
	}
}

// MultipleOf specifies that a number must be a multiple of the given value.
// The number value must be divisible by this value.
func ( float64) PropertyOption {
	return func( map[string]any) {
		["multipleOf"] = 
	}
}

//
// Boolean Property Options
//

// DefaultBool sets the default value for a boolean property.
// This value will be used if the property is not explicitly provided.
func ( bool) PropertyOption {
	return func( map[string]any) {
		["default"] = 
	}
}

//
// Array Property Options
//

// DefaultArray sets the default value for an array property.
// This value will be used if the property is not explicitly provided.
func [ any]( []) PropertyOption {
	return func( map[string]any) {
		["default"] = 
	}
}

//
// Property Type Helpers
//

// WithBoolean adds a boolean property to the tool schema.
// It accepts property options to configure the boolean property's behavior and constraints.
func ( string,  ...PropertyOption) ToolOption {
	return func( *Tool) {
		 := map[string]any{
			"type": "boolean",
		}

		for ,  := range  {
			()
		}

		// Remove required from property schema and add to InputSchema.required
		if ,  := ["required"].(bool);  &&  {
			delete(, "required")
			.InputSchema.Required = append(.InputSchema.Required, )
		}

		.InputSchema.Properties[] = 
	}
}

// WithNumber adds a number property to the tool schema.
// It accepts property options to configure the number property's behavior and constraints.
func ( string,  ...PropertyOption) ToolOption {
	return func( *Tool) {
		 := map[string]any{
			"type": "number",
		}

		for ,  := range  {
			()
		}

		// Remove required from property schema and add to InputSchema.required
		if ,  := ["required"].(bool);  &&  {
			delete(, "required")
			.InputSchema.Required = append(.InputSchema.Required, )
		}

		.InputSchema.Properties[] = 
	}
}

// WithString adds a string property to the tool schema.
// It accepts property options to configure the string property's behavior and constraints.
func ( string,  ...PropertyOption) ToolOption {
	return func( *Tool) {
		 := map[string]any{
			"type": "string",
		}

		for ,  := range  {
			()
		}

		// Remove required from property schema and add to InputSchema.required
		if ,  := ["required"].(bool);  &&  {
			delete(, "required")
			.InputSchema.Required = append(.InputSchema.Required, )
		}

		.InputSchema.Properties[] = 
	}
}

// WithObject adds an object property to the tool schema.
// It accepts property options to configure the object property's behavior and constraints.
func ( string,  ...PropertyOption) ToolOption {
	return func( *Tool) {
		 := map[string]any{
			"type":       "object",
			"properties": map[string]any{},
		}

		for ,  := range  {
			()
		}

		// Remove required from property schema and add to InputSchema.required
		if ,  := ["required"].(bool);  &&  {
			delete(, "required")
			.InputSchema.Required = append(.InputSchema.Required, )
		}

		.InputSchema.Properties[] = 
	}
}

// WithArray returns a ToolOption that adds an array-typed property with the given name to a Tool's input schema.
// It applies provided PropertyOption functions to configure the property's schema, moves a `required` flag
// from the property schema into the Tool's InputSchema.Required slice when present, and registers the resulting
// schema under InputSchema.Properties[name].
func ( string,  ...PropertyOption) ToolOption {
	return func( *Tool) {
		 := map[string]any{
			"type": "array",
		}

		for ,  := range  {
			()
		}

		// Remove required from property schema and add to InputSchema.required
		if ,  := ["required"].(bool);  &&  {
			delete(, "required")
			.InputSchema.Required = append(.InputSchema.Required, )
		}

		.InputSchema.Properties[] = 
	}
}

// WithAny adds an input property named name with no predefined JSON Schema type to the Tool's input schema.
// The returned ToolOption applies the provided PropertyOption functions to the property's schema, moves a property-level
// `required` flag into the Tool's InputSchema.Required list if present, and stores the resulting schema under InputSchema.Properties[name].
func ( string,  ...PropertyOption) ToolOption {
	return func( *Tool) {
		 := map[string]any{}

		for ,  := range  {
			()
		}

		// Remove required from property schema and add to InputSchema.required
		if ,  := ["required"].(bool);  &&  {
			delete(, "required")
			.InputSchema.Required = append(.InputSchema.Required, )
		}

		.InputSchema.Properties[] = 
	}
}

// Properties sets the "properties" map for an object schema.
// The returned PropertyOption stores the provided map under the schema's "properties" key.
func ( map[string]any) PropertyOption {
	return func( map[string]any) {
		["properties"] = 
	}
}

// AdditionalProperties specifies whether additional properties are allowed in the object
// or defines a schema for additional properties
func ( any) PropertyOption {
	return func( map[string]any) {
		["additionalProperties"] = 
	}
}

// MinProperties sets the minimum number of properties for an object
func ( int) PropertyOption {
	return func( map[string]any) {
		["minProperties"] = 
	}
}

// MaxProperties sets the maximum number of properties for an object
func ( int) PropertyOption {
	return func( map[string]any) {
		["maxProperties"] = 
	}
}

// PropertyNames defines a schema for property names in an object
func ( map[string]any) PropertyOption {
	return func( map[string]any) {
		["propertyNames"] = 
	}
}

// Items defines the schema for array items.
// Accepts any schema definition for maximum flexibility.
//
// Example:
//
//	Items(map[string]any{
//	    "type": "object",
//	    "properties": map[string]any{
//	        "name": map[string]any{"type": "string"},
//	        "age": map[string]any{"type": "number"},
//	    },
//	})
//
// For simple types, use ItemsString(), ItemsNumber(), ItemsBoolean() instead.
func ( any) PropertyOption {
	return func( map[string]any) {
		["items"] = 
	}
}

// MinItems sets the minimum number of items for an array
func ( int) PropertyOption {
	return func( map[string]any) {
		["minItems"] = 
	}
}

// MaxItems sets the maximum number of items for an array
func ( int) PropertyOption {
	return func( map[string]any) {
		["maxItems"] = 
	}
}

// UniqueItems specifies whether array items must be unique
func ( bool) PropertyOption {
	return func( map[string]any) {
		["uniqueItems"] = 
	}
}

// WithStringItems configures an array's items to be of type string.
//
// Supported options: Description(), DefaultString(), Enum(), MaxLength(), MinLength(), Pattern()
// Note: Options like Required() are not valid for item schemas and will be ignored.
//
// Examples:
//
//	mcp.WithArray("tags", mcp.WithStringItems())
//	mcp.WithArray("colors", mcp.WithStringItems(mcp.Enum("red", "green", "blue")))
//	mcp.WithArray("names", mcp.WithStringItems(mcp.MinLength(1), mcp.MaxLength(50)))
//
// Limitations: Only supports simple string arrays. Use Items() for complex objects.
func ( ...PropertyOption) PropertyOption {
	return func( map[string]any) {
		 := map[string]any{
			"type": "string",
		}

		for ,  := range  {
			()
		}

		["items"] = 
	}
}

// WithStringEnumItems configures an array's items to be of type string with a specified enum.
// Example:
//
//	mcp.WithArray("priority", mcp.WithStringEnumItems([]string{"low", "medium", "high"}))
//
// Limitations: Only supports string enums. Use WithStringItems(Enum(...)) for more flexibility.
func ( []string) PropertyOption {
	return func( map[string]any) {
		["items"] = map[string]any{
			"type": "string",
			"enum": ,
		}
	}
}

// WithNumberItems configures an array's items to be of type number.
//
// Supported options: Description(), DefaultNumber(), Min(), Max(), MultipleOf()
// Note: Options like Required() are not valid for item schemas and will be ignored.
//
// Examples:
//
//	mcp.WithArray("scores", mcp.WithNumberItems(mcp.Min(0), mcp.Max(100)))
//	mcp.WithArray("prices", mcp.WithNumberItems(mcp.Min(0)))
//
// Limitations: Only supports simple number arrays. Use Items() for complex objects.
func ( ...PropertyOption) PropertyOption {
	return func( map[string]any) {
		 := map[string]any{
			"type": "number",
		}

		for ,  := range  {
			()
		}

		["items"] = 
	}
}

// WithBooleanItems configures an array's items to be of type boolean.
//
// Supported options: Description(), DefaultBool()
// Note: Options like Required() are not valid for item schemas and will be ignored.
//
// Examples:
//
//	mcp.WithArray("flags", mcp.WithBooleanItems())
//	mcp.WithArray("permissions", mcp.WithBooleanItems(mcp.Description("User permissions")))
//
// Limitations: Only supports simple boolean arrays. Use Items() for complex objects.
func ( ...PropertyOption) PropertyOption {
	return func( map[string]any) {
		 := map[string]any{
			"type": "boolean",
		}

		for ,  := range  {
			()
		}

		["items"] = 
	}
}