// SPDX-FileCopyrightText: Copyright 2025 Stacklok, Inc.
// SPDX-License-Identifier: Apache-2.0

package vmcp

import (
	"context"
	"time"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

	authtypes "github.com/stacklok/toolhive/pkg/vmcp/auth/types"
)

// This file contains shared domain types used across multiple vmcp subpackages.
// Following DDD principles, these are core domain concepts that cross bounded contexts.

// HeaderForwardConfig configures HTTP headers injected into outbound requests
// from the vMCP runtime to a static backend. AddPlaintextHeaders carries literal
// values; AddHeadersFromSecret maps header names to secret identifiers resolved
// via secrets.EnvironmentProvider at request time (env var TOOLHIVE_SECRET_<identifier>).
//
// Secret values MUST NOT appear in this struct — only identifiers. The operator
// injects actual Secret values into the vMCP pod as env vars via
// valueFrom.secretKeyRef at Deployment rendering time. Plaintext values are
// also injected via env vars by the operator (literal values, not secret refs)
// and ingested at vMCP startup; the type is therefore purely a runtime
// representation and is not part of any CRD schema.
type HeaderForwardConfig struct {
	// AddPlaintextHeaders is a map of canonical HTTP header name to literal value.
	AddPlaintextHeaders map[string]string `json:"addPlaintextHeaders,omitempty" yaml:"addPlaintextHeaders,omitempty"`

	// AddHeadersFromSecret maps canonical HTTP header name to secret identifier.
	// The vMCP runtime resolves each identifier via secrets.EnvironmentProvider,
	// which reads TOOLHIVE_SECRET_<identifier> from the pod environment.
	AddHeadersFromSecret map[string]string `json:"addHeadersFromSecret,omitempty" yaml:"addHeadersFromSecret,omitempty"`
}

// BackendTarget identifies a specific backend workload and provides
// the information needed to forward requests to it.
type BackendTarget struct {
	// WorkloadID is the unique identifier for the backend workload.
	WorkloadID string

	// WorkloadName is the human-readable name of the workload.
	WorkloadName string

	// BaseURL is the base URL for the backend's MCP server.
	// For local deployments: http://localhost:PORT
	// For Kubernetes: http://service-name.namespace.svc.cluster.local:PORT
	BaseURL string

	// TransportType specifies the MCP transport protocol.
	// Supported: "stdio", "http", "sse", "streamable-http"
	TransportType string

	// CABundlePath is the file path to a custom CA certificate bundle for TLS verification.
	// When set, the HTTP client uses this CA (appended to system roots) for backend connections.
	// Only applicable to entry-type backends with self-signed or internal certificates.
	// Used in static mode where CA bundles are volume-mounted by the operator.
	CABundlePath string

	// CABundleData contains raw CA certificate PEM bytes for TLS verification.
	// Used in dynamic mode where CA bundles are fetched from K8s ConfigMaps at
	// discovery time (no volume mount available). Takes precedence over CABundlePath.
	CABundleData []byte

	// OriginalCapabilityName is the original name of the capability (tool/resource/prompt)
	// as known by the backend. This is used when forwarding requests to the backend.
	//
	// When conflict resolution renames capabilities, this field preserves the original name:
	// - Prefix strategy: "fetch" → "fetch_fetch" (OriginalCapabilityName="fetch")
	// - Priority strategy: usually unchanged (OriginalCapabilityName="tool_name")
	// - Manual strategy: "fetch" → "custom_name" (OriginalCapabilityName="fetch")
	//
	// If empty, the resolved name is used when forwarding to the backend.
	//
	// IMPORTANT: Do NOT access this field directly when forwarding requests to backends.
	// Use GetBackendCapabilityName() method instead, which handles both renamed and
	// non-renamed capabilities correctly. Direct access can lead to incorrect behavior
	// when capabilities are not renamed (OriginalCapabilityName will be empty).
	//
	// Example (WRONG):
	//   client.CallTool(ctx, target, target.OriginalCapabilityName, args) // BUG: fails when empty
	//
	// Example (CORRECT):
	//   client.CallTool(ctx, target, target.GetBackendCapabilityName(toolName), args)
	OriginalCapabilityName string

	// AuthConfig contains the typed authentication configuration for this backend.
	// The actual authentication is handled by OutgoingAuthRegistry interface.
	// If nil, the backend requires no authentication.
	AuthConfig *authtypes.BackendAuthStrategy

	// SessionAffinity indicates if requests from the same session
	// must be routed to this specific backend instance.
	SessionAffinity bool

	// HealthStatus indicates the current health of the backend.
	HealthStatus BackendHealthStatus

	// HeaderForward carries per-backend HTTP header injection configuration
	// applied by the vMCP client to every outbound request targeting this backend
	// (list, call, health-check). Nil when no headers are configured.
	HeaderForward *HeaderForwardConfig

	// Metadata stores additional backend-specific information.
	Metadata map[string]string
}

// GetBackendCapabilityName returns the name to use when forwarding a request to the backend.
// If conflict resolution renamed the capability, this returns the original name that the backend expects.
// Otherwise, it returns the resolved name as-is.
//
// This method encapsulates the name translation logic for all capability types (tools, resources, prompts).
//
// ALWAYS use this method when forwarding capability calls to backends. Do NOT access
// OriginalCapabilityName directly, as it may be empty when no renaming occurred.
//
// Usage example:
//
//	target, _ := router.RouteTool(ctx, "fetch_fetch")  // Prefixed name from client
//	backendName := target.GetBackendCapabilityName("fetch_fetch")  // Returns "fetch"
//	client.CallTool(ctx, target, backendName, args)  // Backend receives original name
//
// This ensures correct behavior regardless of conflict resolution strategy:
//   - Prefix strategy: "fetch_fetch" → "fetch" (renamed, uses OriginalCapabilityName)
//   - Priority strategy: "list_issues" → "list_issues" (not renamed, returns resolvedName)
//   - Manual strategy: "custom_fetch" → "fetch" (renamed, uses OriginalCapabilityName)
func (t *BackendTarget) GetBackendCapabilityName(resolvedName string) string {
	if t.OriginalCapabilityName != "" {
		return t.OriginalCapabilityName
	}
	return resolvedName
}

// BackendType represents the type of backend workload.
type BackendType string

const (
	// BackendTypeContainer indicates a container-based backend managed by ToolHive.
	// Currently represented by an empty Type field for backward compatibility.
	BackendTypeContainer BackendType = "container"

	// BackendTypeProxy indicates a proxy-based backend (MCPRemoteProxy).
	// Currently represented by an empty Type field for backward compatibility.
	BackendTypeProxy BackendType = "proxy"

	// BackendTypeEntry indicates an external MCP server declared via MCPServerEntry.
	BackendTypeEntry BackendType = "entry"
)

// BackendHealthStatus represents the health state of a backend.
type BackendHealthStatus string

const (
	// BackendHealthy indicates the backend is healthy and accepting requests.
	BackendHealthy BackendHealthStatus = "healthy"

	// BackendDegraded indicates the backend is operational but experiencing issues.
	// This occurs when:
	// - Health checks succeed but response times exceed the degraded threshold (slow but working)
	// - Backend just recovered from failures and is in a stabilizing state
	BackendDegraded BackendHealthStatus = "degraded"

	// BackendUnhealthy indicates the backend is not responding to health checks.
	BackendUnhealthy BackendHealthStatus = "unhealthy"

	// BackendUnknown indicates the backend health status is unknown.
	BackendUnknown BackendHealthStatus = "unknown"

	// BackendUnauthenticated indicates the backend returned an authentication error
	// (HTTP 401/403) while the backend target had no outgoing auth strategy
	// configured (AuthConfig nil or StrategyTypeUnauthenticated). This signals
	// operator misconfiguration: the backend requires authentication but no
	// auth strategy was configured on the backend target.
	//
	// Note: a 401/403 from a backend with a configured outgoing auth strategy is
	// treated as BackendHealthy, because health probes deliberately do not carry
	// user credentials and the backend's challenge proves reachability and a
	// working auth layer.
	BackendUnauthenticated BackendHealthStatus = "unauthenticated"
)

// ToCRDStatus converts BackendHealthStatus to CRD-friendly status string.
// This maps internal health states to user-facing status values:
//   - healthy → ready
//   - degraded → degraded
//   - unhealthy → unavailable
//   - unauthenticated → unauthenticated (misconfig: backend requires auth but none configured)
//   - unknown → unknown
func (s BackendHealthStatus) ToCRDStatus() string {
	switch s {
	case BackendHealthy:
		return "ready"
	case BackendDegraded:
		return "degraded"
	case BackendUnhealthy:
		return "unavailable"
	case BackendUnauthenticated:
		return "unauthenticated"
	case BackendUnknown:
		return "unknown"
	default:
		return "unknown"
	}
}

// Condition represents a specific aspect of vMCP server status.
type Condition = metav1.Condition

// Phase represents the operational lifecycle phase of a vMCP server.
type Phase string

// Phase constants for vMCP server lifecycle.
const (
	PhasePending  Phase = "Pending"
	PhaseReady    Phase = "Ready"
	PhaseDegraded Phase = "Degraded"
	PhaseFailed   Phase = "Failed"
)

// Condition type constants for common vMCP conditions.
const (
	ConditionTypeBackendsDiscovered = "BackendsDiscovered"
	ConditionTypeReady              = "Ready"
	ConditionTypeAuthConfigured     = "AuthConfigured"
)

// Reason constants for condition reasons.
const (
	ReasonBackendDiscoverySucceeded = "BackendDiscoverySucceeded"
	ReasonBackendDiscoveryFailed    = "BackendDiscoveryFailed"
	ReasonServerReady               = "ServerReady"
	ReasonServerStarting            = "ServerStarting"
	ReasonServerDegraded            = "ServerDegraded"
	ReasonServerFailed              = "ServerFailed"
)

// DiscoveredBackend represents a backend server discovered by vMCP runtime.
// This type is shared with the Kubernetes operator CRD (VirtualMCPServer.Status.DiscoveredBackends).
type DiscoveredBackend struct {
	// Name is the name of the backend MCPServer
	Name string `json:"name"`

	// URL is the URL of the backend MCPServer
	// +optional
	URL string `json:"url,omitempty"`

	// Status is the current status of the backend (ready, degraded, unavailable, unauthenticated, unknown).
	// Use BackendHealthStatus.ToCRDStatus() to populate this field.
	// +optional
	Status string `json:"status,omitempty"`

	// AuthConfigRef is the name of the discovered MCPExternalAuthConfig (if any)
	// +optional
	AuthConfigRef string `json:"authConfigRef,omitempty"`

	// AuthType is the type of authentication configured
	// +optional
	AuthType string `json:"authType,omitempty"`

	// LastHealthCheck is the timestamp of the last health check
	// +optional
	LastHealthCheck metav1.Time `json:"lastHealthCheck,omitempty"`

	// Message provides additional information about the backend status
	// +optional
	Message string `json:"message,omitempty"`

	// CircuitBreakerState is the current circuit breaker state (closed, open, half-open).
	// Empty when circuit breaker is disabled or not configured.
	// +optional
	// +kubebuilder:validation:Enum=closed;open;half-open
	CircuitBreakerState string `json:"circuitBreakerState,omitempty"`

	// CircuitLastChanged is the timestamp when the circuit breaker state last changed.
	// Empty when circuit breaker is disabled or has never changed state.
	// +optional
	CircuitLastChanged metav1.Time `json:"circuitLastChanged,omitempty"`

	// ConsecutiveFailures is the current count of consecutive health check failures.
	// Resets to 0 when the backend becomes healthy again.
	// +optional
	ConsecutiveFailures int `json:"consecutiveFailures,omitempty"`
}

// DeepCopyInto copies the receiver into out. Required for Kubernetes CRD types.
func (in *DiscoveredBackend) DeepCopyInto(out *DiscoveredBackend) {
	*out = *in
	in.LastHealthCheck.DeepCopyInto(&out.LastHealthCheck)
}

// DeepCopy creates a deep copy of DiscoveredBackend. Required for Kubernetes CRD types.
func (in *DiscoveredBackend) DeepCopy() *DiscoveredBackend {
	if in == nil {
		return nil
	}
	out := new(DiscoveredBackend)
	in.DeepCopyInto(out)
	return out
}

// Status represents the runtime status of a vMCP server.
type Status struct {
	Phase              Phase               `json:"phase"`
	Message            string              `json:"message,omitempty"`
	Conditions         []Condition         `json:"conditions,omitempty"`
	DiscoveredBackends []DiscoveredBackend `json:"discoveredBackends,omitempty"`
	BackendCount       int32               `json:"backendCount,omitempty"`
	ObservedGeneration int64               `json:"observedGeneration,omitempty"`
	Timestamp          time.Time           `json:"timestamp"`
}

// Backend represents a discovered backend MCP server workload.
type Backend struct {
	// ID is the unique identifier for this backend.
	ID string

	// Name is the human-readable name.
	Name string

	// BaseURL is the backend's MCP server URL.
	BaseURL string

	// TransportType is the MCP transport protocol.
	TransportType string

	// Type is the backend workload type (container, proxy, entry).
	// Empty string is treated as container/proxy for backward compatibility.
	Type BackendType

	// CABundlePath is the file path to a custom CA certificate bundle for TLS verification.
	// Only applicable to entry-type backends with self-signed or internal certificates.
	// Used in static mode where CA bundles are volume-mounted by the operator.
	CABundlePath string

	// CABundleData contains raw CA certificate PEM bytes for TLS verification.
	// Used in dynamic mode where CA bundles are fetched from K8s ConfigMaps at
	// discovery time (no volume mount available). Takes precedence over CABundlePath.
	CABundleData []byte

	// HealthStatus is the current health state.
	HealthStatus BackendHealthStatus

	// AuthConfig contains the typed authentication configuration for this backend.
	// The actual authentication is handled by OutgoingAuthRegistry interface.
	// If nil, the backend requires no authentication.
	AuthConfig *authtypes.BackendAuthStrategy

	// AuthConfigRef is the name of the MCPExternalAuthConfig resource (if any).
	// This field is populated during backend discovery and is useful for
	// debugging and status reporting.
	// +optional
	AuthConfigRef string

	// HeaderForward carries per-backend HTTP header injection configuration.
	// Only populated for entry-type backends whose MCPServerEntry declares
	// spec.headerForward. Nil when the entry has no header forwarding configured.
	HeaderForward *HeaderForwardConfig

	// Metadata stores additional backend information.
	Metadata map[string]string
}

// Tool represents an MCP tool capability.
type Tool struct {
	// Name is the tool name (may conflict with other backends).
	Name string

	// Description describes what the tool does.
	Description string

	// InputSchema is the JSON Schema for tool parameters.
	InputSchema map[string]any

	// OutputSchema is the JSON Schema for tool output (optional).
	// Per MCP specification, this describes the structure of the tool's response.
	OutputSchema map[string]any

	// Annotations describes behavioral hints for the tool (optional).
	// Per MCP specification, these include readOnlyHint, destructiveHint, etc.
	Annotations *ToolAnnotations

	// BackendID identifies the backend that provides this tool.
	BackendID string
}

// ToolAnnotations describes behavioral hints for a tool.
// These are the vmcp-domain equivalents of mcp.ToolAnnotation, following the
// Anti-Corruption Layer pattern (vmcp types are decoupled from mcp-go).
type ToolAnnotations struct {
	// Title is a human-readable title for the tool.
	Title string `json:"title,omitempty"`
	// ReadOnlyHint indicates whether the tool does not modify its environment.
	ReadOnlyHint *bool `json:"readOnlyHint,omitempty"`
	// DestructiveHint indicates whether the tool may perform destructive updates.
	DestructiveHint *bool `json:"destructiveHint,omitempty"`
	// IdempotentHint indicates whether repeated calls with same args have no additional effect.
	IdempotentHint *bool `json:"idempotentHint,omitempty"`
	// OpenWorldHint indicates whether the tool interacts with external entities.
	OpenWorldHint *bool `json:"openWorldHint,omitempty"`
}

// Resource represents an MCP resource capability.
type Resource struct {
	// URI is the resource URI (should be globally unique).
	URI string

	// Name is a human-readable name.
	Name string

	// Description describes the resource.
	Description string

	// MimeType is the resource's MIME type (optional).
	MimeType string

	// BackendID identifies the backend that provides this resource.
	BackendID string
}

// Prompt represents an MCP prompt capability.
type Prompt struct {
	// Name is the prompt name (may conflict with other backends).
	Name string

	// Description describes the prompt.
	Description string

	// Arguments are the prompt parameters.
	Arguments []PromptArgument

	// BackendID identifies the backend that provides this prompt.
	BackendID string
}

// PromptArgument represents a prompt parameter.
type PromptArgument struct {
	// Name is the argument name.
	Name string

	// Description describes the argument.
	Description string

	// Required indicates if the argument is mandatory.
	Required bool
}

// ContentType represents the type of content in an MCP message.
type ContentType string

const (
	// ContentTypeText represents text content.
	ContentTypeText ContentType = "text"
	// ContentTypeImage represents image content.
	ContentTypeImage ContentType = "image"
	// ContentTypeAudio represents audio content.
	ContentTypeAudio ContentType = "audio"
	// ContentTypeResource represents embedded resource content.
	ContentTypeResource ContentType = "resource"
	// ContentTypeLink represents a resource link.
	ContentTypeLink ContentType = "resource_link"
)

// ContentAnnotations describes per-content metadata annotations.
// These are the vmcp-domain equivalents of mcp.Annotations, following the
// Anti-Corruption Layer pattern (vmcp types are decoupled from mcp-go).
type ContentAnnotations struct {
	// Audience describes who the content is intended for.
	// Valid values are the mcp.Role constants: "user" and "assistant".
	Audience []string `json:"audience,omitempty"`
	// Priority is a hint for display ordering in the closed interval [0.0, 1.0]
	// per the MCP spec, where 0.0 is least important and 1.0 is most important.
	// Nil means no priority hint was provided.
	Priority *float64 `json:"priority,omitempty"`
	// LastModified is an ISO 8601 timestamp (e.g., "2025-01-12T15:00:58Z").
	LastModified string `json:"lastModified,omitempty"`
}

// Content represents MCP content (text, image, audio, embedded resource, resource link).
// This is used by ToolCallResult to preserve the full content structure from backends.
type Content struct {
	// Type indicates the content type.
	Type ContentType

	// Text is the content text (for TextContent)
	Text string

	// Data is the base64-encoded data (for ImageContent/AudioContent)
	Data string

	// MimeType is the MIME type (for ImageContent/AudioContent/ResourceLink)
	MimeType string

	// URI is the resource URI (for EmbeddedResource/ResourceLink)
	URI string

	// Name is the resource name (for ResourceLink)
	Name string

	// Description is the resource description (for ResourceLink)
	Description string

	// Annotations contains per-content metadata (audience, priority, lastModified).
	// Nil means no annotations were provided by the backend.
	Annotations *ContentAnnotations
}

// ToolCallResult wraps a tool call response with metadata.
// This preserves both the tool output AND the _meta field from the backend MCP server.
type ToolCallResult struct {
	// Content is the tool output (text, image, etc.)
	// This is the array of content items returned by the backend.
	Content []Content

	// StructuredContent is structured output (preferred for composite tools and workflows).
	// If the backend MCP server provides StructuredContent, it is used directly.
	// Otherwise, this is populated by converting the Content array to a map:
	//   - First text item: key="text"
	//   - Additional text items: key="text_1", "text_2", etc.
	//   - Image items: key="image_0", "image_1", etc.
	// This allows templates to access fields via {{.steps.stepID.output.text}}.
	// Note: No JSON parsing is performed - backends must provide structured data explicitly.
	StructuredContent map[string]any

	// IsError indicates if the tool call failed.
	IsError bool

	// Meta contains protocol-level metadata from the backend (_meta field).
	// This includes progressToken, trace context, and custom backend metadata.
	// Per MCP specification, this field is optional and may be nil.
	Meta map[string]any
}

// ResourceContent represents a single resource content item,
// preserving the text vs blob distinction from the MCP protocol.
type ResourceContent struct {
	// URI is the resource URI.
	URI string
	// MimeType is the content type of this resource item.
	MimeType string
	// Text is the text content (non-empty for text resources).
	Text string
	// Blob is the base64-encoded binary content (non-empty for blob resources).
	// Exactly one of Text or Blob should be set; Blob takes precedence in ToMCPResourceContents.
	Blob string
}

// ResourceReadResult wraps a resource read response with metadata.
// This preserves both the resource data AND the _meta field from the backend MCP server.
type ResourceReadResult struct {
	// Contents preserves individual resource content items with their
	// per-item URIs, MIME types, and text/blob distinction.
	Contents []ResourceContent

	// Meta contains protocol-level metadata from the backend (_meta field).
	// NOTE: Due to MCP SDK limitations, resources/read handlers cannot forward _meta
	// because they return []ResourceContents directly, not a result wrapper.
	// This field is preserved for future SDK improvements but may be nil.
	Meta map[string]any
}

// PromptMessage represents a single message in a prompt response,
// preserving the role and content structure from the backend.
type PromptMessage struct {
	// Role is the message role. The MCP spec defines "user" and "assistant";
	// backends may also send other values which are relayed as-is.
	Role string
	// Content is the message content, supporting all MCP content types.
	Content Content
}

// PromptGetResult wraps a prompt response with metadata.
// This preserves both the prompt messages AND the _meta field from the backend MCP server.
type PromptGetResult struct {
	// Messages preserves individual prompt messages with their roles
	// and full content structure (text, images, audio, resources).
	Messages []PromptMessage

	// Description is an optional description of the prompt.
	Description string

	// Meta contains protocol-level metadata from the backend (_meta field).
	// This includes progressToken, trace context, and custom backend metadata.
	// Per MCP specification, this field is optional and may be nil.
	Meta map[string]any
}

// RoutingTable contains the mappings from capability names to backend targets.
// This is the output of the aggregation phase and input to the router.
// Placed in vmcp root package to avoid circular dependencies between
// aggregator and router packages.
//
// Note: Composite tools are NOT included here. They are executed by the composer
// package and do not route to a single backend.
type RoutingTable struct {
	// Tools maps tool names to their backend targets.
	// After conflict resolution, tool names are unique.
	Tools map[string]*BackendTarget

	// Resources maps resource URIs to their backend targets.
	Resources map[string]*BackendTarget

	// Prompts maps prompt names to their backend targets.
	Prompts map[string]*BackendTarget
}

// ConflictResolutionStrategy defines how to handle capability name conflicts.
// Placed in vmcp root package to be shared by config and aggregator packages.
type ConflictResolutionStrategy string

const (
	// ConflictStrategyPrefix prefixes all tools with workload identifier.
	ConflictStrategyPrefix ConflictResolutionStrategy = "prefix"

	// ConflictStrategyPriority uses explicit priority ordering (first wins).
	ConflictStrategyPriority ConflictResolutionStrategy = "priority"

	// ConflictStrategyManual requires explicit overrides for all conflicts.
	ConflictStrategyManual ConflictResolutionStrategy = "manual"
)

// HealthChecker performs health checks on backend MCP servers.
type HealthChecker interface {
	// CheckHealth checks if a backend is healthy and responding.
	// Returns the current health status and any error encountered.
	CheckHealth(ctx context.Context, target *BackendTarget) (BackendHealthStatus, error)
}

// BackendClient abstracts MCP protocol communication with backend servers.
// This interface handles the protocol-level details of calling backend MCP servers,
// supporting multiple transport types (HTTP, SSE, stdio, streamable-http).
//
// All methods return wrapper types that preserve the _meta field from backend
// MCP server responses. Protocol-level metadata (progress tokens, trace context,
// custom metadata) is forwarded to clients where supported (tools and prompts).
// Note: Resource _meta forwarding is not currently supported due to MCP SDK handler
// signature limitations; the Meta field is preserved for future SDK improvements.
//
//go:generate mockgen -destination=mocks/mock_backend_client.go -package=mocks -source=types.go BackendClient HealthChecker
type BackendClient interface {
	// CallTool invokes a tool on the backend MCP server.
	// The meta parameter contains _meta fields from the client request that should be forwarded to the backend.
	// Returns the complete tool result including _meta field from the backend response.
	CallTool(
		ctx context.Context, target *BackendTarget, toolName string, arguments map[string]any, meta map[string]any,
	) (*ToolCallResult, error)

	// ReadResource retrieves a resource from the backend MCP server.
	// Returns the complete resource result including _meta field.
	ReadResource(ctx context.Context, target *BackendTarget, uri string) (*ResourceReadResult, error)

	// GetPrompt retrieves a prompt from the backend MCP server.
	// Returns the complete prompt result including _meta field.
	GetPrompt(ctx context.Context, target *BackendTarget, name string, arguments map[string]any) (*PromptGetResult, error)

	// ListCapabilities queries a backend for its capabilities.
	// Returns tools, resources, and prompts exposed by the backend.
	ListCapabilities(ctx context.Context, target *BackendTarget) (*CapabilityList, error)
}

// CapabilityList contains the capabilities from a backend's MCP server.
// This is returned by BackendClient.ListCapabilities().
type CapabilityList struct {
	// Tools available on this backend.
	Tools []Tool

	// Resources available on this backend.
	Resources []Resource

	// Prompts available on this backend.
	Prompts []Prompt

	// SupportsLogging indicates if the backend supports MCP logging.
	SupportsLogging bool

	// SupportsSampling indicates if the backend supports MCP sampling.
	SupportsSampling bool
}
