mcp

package
v0.9.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 30, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Index

Constants

View Source
const (
	MethodInitialize    = "initialize"
	MethodInitialized   = "notifications/initialized"
	MethodToolsList     = "tools/list"
	MethodToolsCall     = "tools/call"
	MethodResourcesList = "resources/list"
	MethodResourcesRead = "resources/read"
	MethodPromptsList   = "prompts/list"
	MethodPromptsGet    = "prompts/get"
	MethodPing          = "ping"
	MethodShutdown      = "shutdown"
)
View Source
const (
	ErrCodeParseError     = -32700
	ErrCodeInvalidRequest = -32600
	ErrCodeMethodNotFound = -32601
	ErrCodeInvalidParams  = -32602
	ErrCodeInternalError  = -32603
	ErrCodeServerError    = -32000
)
View Source
const JSONRPCVersion = "2.0"

Variables

View Source
var ErrorHintRegistry = map[string][]ErrorHint{
	"repository": {
		{
			Original:   "Could not resolve to a Repository",
			Suggestion: "Check the owner/repo spelling. Ensure the repository exists and you have access. Tip: Use the exact format 'owner/repo' (e.g., 'mmornati/leanproxy-mcp').",
			Action:     "check_repo",
			Reference:  "https://docs.github.com/en/github/finding-open-source-projects-on-github",
		},
	},
	"not running": {
		{
			Original:   "is not running",
			Suggestion: "The MCP server is not running. Run 'leanproxy server start <server_name>' or check server status with 'leanproxy status'.",
			Action:     "restart_server",
		},
	},
	"not healthy": {
		{
			Original:   "not healthy",
			Suggestion: "The server is in an error state. Check 'leanproxy-mcp status --running' for details. The server will automatically restart on the next request.",
			Action:     "restart_server",
		},
	},
	"server not available": {
		{
			Original:   "server not available",
			Suggestion: "The server crashed or failed to start. Check the logs at /tmp/leanproxy.log for error details. The server will attempt to restart automatically.",
			Action:     "check_logs",
		},
	},
	"signal: killed": {
		{
			Original:   "signal: killed",
			Suggestion: "The server process was killed (likely by the system or OOM). Check /tmp/leanproxy.log for more details. Auto-restart will attempt recovery.",
			Action:     "check_logs",
		},
	},
	"command not found": {
		{
			Original:   "command not found",
			Suggestion: "The server command (e.g., npx, uv) is not installed or not in PATH. Check your configuration and install the required dependencies.",
			Action:     "check_dependencies",
		},
	},
	"failed": {
		{
			Original:   "server error",
			Suggestion: "The remote server encountered an error. Try again in a few moments, or check the server logs for more details.",
			Action:     "retry",
		},
	},
	"not authenticated": {
		{
			Original:   "not authenticated",
			Suggestion: "Authentication required. Check your credentials configuration for this server.",
			Action:     "check_auth",
		},
		{
			Original:   "401",
			Suggestion: "Authentication failed. Verify your API token or credentials are correct.",
			Action:     "check_auth",
		},
	},
	"forbidden": {
		{
			Original:   "403",
			Suggestion: "Access denied. You may not have permission for this operation. Check your API token scopes.",
			Action:     "check_permissions",
		},
		{
			Original:   "permission denied",
			Suggestion: "Insufficient permissions. Verify your account has the required access rights.",
			Action:     "check_permissions",
		},
	},
	"not found": {
		{
			Original:   "404",
			Suggestion: "The requested resource was not found. Check if the resource exists and the URL is correct.",
			Action:     "verify_resource",
		},
	},
	"rate limited": {
		{
			Original:   "429",
			Suggestion: "Rate limit exceeded. Wait a moment before retrying, or check if you need to configure rate limiting.",
			Action:     "wait_retry",
		},
		{
			Original:   "rate limit",
			Suggestion: "Too many requests. Consider adding a delay between requests or reducing request frequency.",
			Action:     "wait_retry",
		},
	},
	"timeout": {
		{
			Original:   "timeout",
			Suggestion: "The request timed out. The server may be slow or unavailable. Try again or increase timeout settings.",
			Action:     "retry",
		},
		{
			Original:   "context deadline exceeded",
			Suggestion: "The request took too long. Try again or check if the server is experiencing issues.",
			Action:     "retry",
		},
	},
	"invalid params": {
		{
			Original:   "invalid params",
			Suggestion: "Check the parameter names and types. Use list_servers to get servers, then list_tools to see available parameters.",
			Action:     "check_params",
		},
		{
			Original:   "missing",
			Suggestion: "A required parameter is missing. Use list_servers to get servers, then list_tools to see required parameters.",
			Action:     "check_params",
		},
	},
	"connection refused": {
		{
			Original:   "connection refused",
			Suggestion: "Cannot connect to the server. Verify the server is running and the connection settings are correct.",
			Action:     "check_server",
		},
	},
	"tool not found": {
		{
			Original:   "tool not found",
			Suggestion: "The tool doesn't exist on this server. Use list_servers to get servers, then list_tools to discover available tools.",
			Action:     "list_tools",
		},
	},
}
View Source
var InvokeToolParamDefaults = map[string]interface{}{}
View Source
var InvokeToolParamMeta = map[string]ParameterMeta{
	"server": {
		Required:    true,
		Description: "Server name from list_servers (e.g., 'github', 'garmin', 'filesystem'). Must be a configured and running MCP server.",
	},
	"tool": {
		Required:    true,
		Description: "Tool name from list_tools (e.g., 'list_issues', 'get_activities'). Do NOT prefix with server name.",
	},
	"arguments": {
		Required:    false,
		Description: "Tool arguments as key-value pairs. Refer to list_tools output for available parameters. Pass empty object {} if no arguments needed.",
	},
}
View Source
var LeanproxyTools = []ToolDefinition{
	{
		Name:        "list_tools",
		Description: "List all tools available on a specific MCP server. **IMPORTANT:** Always call list_servers first to get available server names, then use this tool to see tools on a specific server.",
		Categories:  []string{"discovery", "meta"},
		Examples: []ToolExample{
			{
				Input: map[string]interface{}{
					"server_name": "github",
				},
				Description: "List all tools available on the github server",
			},
			{
				Input: map[string]interface{}{
					"server_name": "garmin",
				},
				Description: "List all tools available on the garmin server",
			},
			{
				Input: map[string]interface{}{
					"server_name":           "github",
					"max_description_chars": 150,
				},
				Description: "List github tools with shorter descriptions",
			},
		},
		Returns: ReturnSchema{
			Type:        "object",
			Description: "Returns a content block with formatted tool list for the specified server",
			Fields: []FieldDescription{
				{Name: "content", Type: "array", Desc: "Array of text content blocks"},
			},
		},
		InputSchema: json.RawMessage(`{
			"type": "object",
			"properties": {
				"server_name": {
					"type": "string",
					"description": "MCP server name (from list_servers). Required - identifies which server's tools to list."
				},
				"max_description_chars": {
					"type": "number",
					"description": "Maximum characters for tool descriptions (default: 200, min: 50, max: 500)",
					"default": 200
				}
			},
			"required": ["server_name"]
		}`),
	},
	{
		Name:        "invoke_tool",
		Description: "Invoke a tool on a configured MCP server. **Required:** First use list_servers to get server names, then use list_tools to discover available tools on that server.",
		Categories:  []string{"execution", "meta"},
		Examples: []ToolExample{
			{
				Input: map[string]interface{}{
					"server": "github",
					"tool":   "list_issues",
					"arguments": map[string]interface{}{
						"owner":   "mmornati",
						"repo":    "leanproxy-mcp",
						"state":   "open",
						"perPage": 10,
					},
				},
				Description: "List open issues on leanproxy-mcp repository",
			},
			{
				Input: map[string]interface{}{
					"server": "github",
					"tool":   "search_issues",
					"arguments": map[string]interface{}{
						"query":   "is:issue is:open label:bug",
						"owner":   "mmornati",
						"repo":    "leanproxy-mcp",
						"perPage": 5,
					},
				},
				Description: "Search for open bug issues",
			},
		},
		Returns: ReturnSchema{
			Type:        "object",
			Description: "Returns the result from the remote MCP tool invocation",
			Fields: []FieldDescription{
				{Name: "content", Type: "array", Desc: "Array of content blocks from tool"},
			},
		},
		InputSchema: json.RawMessage(`{
			"type": "object",
			"properties": {
				"server": {
					"type": "string",
					"description": "Server name from list_servers (e.g., 'github', 'garmin', 'filesystem'). Must be a configured MCP server."
				},
				"tool": {
					"type": "string",
					"description": "Tool name from list_tools (e.g., 'list_issues', 'get_activities'). Do NOT prefix with server name."
				},
				"arguments": {
					"type": "object",
					"description": "Tool arguments as key-value pairs. Refer to list_tools output for available parameters."
				}
			},
			"required": ["server", "tool"],
			"additionalProperties": false
		}`),
	},
}
View Source
var ListToolsParamDefaults = map[string]interface{}{
	"max_description_chars": 200,
}
View Source
var ListToolsParamMeta = map[string]ParameterMeta{
	"server_name": {
		Required:        true,
		Default:         nil,
		Description:     "MCP server name (from list_servers). Required - identifies which server's tools to list.",
		SuggestedValues: []string{"github", "garmin", "filesystem", "intervals"},
	},
	"max_description_chars": {
		Required:    false,
		Default:     200,
		Min:         50,
		Max:         500,
		Description: "Maximum characters for tool descriptions. Default: 200. Range: 50-500.",
	},
}

Functions

func AddErrorContext added in v0.5.2

func AddErrorContext(originalMessage, serverName, toolName string) string

func ApplyDefaults added in v0.5.2

func ApplyDefaults(toolName string, args map[string]interface{}) map[string]interface{}

func EnrichError added in v0.5.2

func EnrichError(originalMessage string) string

func FormatErrorWithHint added in v0.5.2

func FormatErrorWithHint(originalMessage, serverName, toolName string) string

func GetAllParamDefaults added in v0.5.2

func GetAllParamDefaults(toolName string) map[string]interface{}

func GetParamDefault added in v0.5.2

func GetParamDefault(toolName, paramName string) interface{}

func ValidateParam added in v0.5.2

func ValidateParam(toolName, paramName string, value interface{}) (bool, string)

Types

type AggregatedManifest

type AggregatedManifest struct {
	Tools     []Tool
	Resources []Resource
	Prompts   []Prompt
}

type ClientCapabilities

type ClientCapabilities struct {
	Roots    *RootsCapability          `json:"roots,omitempty"`
	Sampling *ClientSamplingCapability `json:"sampling,omitempty"`
}

type ClientInfo

type ClientInfo struct {
	Name    string `json:"name"`
	Version string `json:"version"`
}

type ClientSamplingCapability

type ClientSamplingCapability struct{}

type ContentBlock

type ContentBlock struct {
	Type string `json:"type"`
	Text string `json:"text,omitempty"`
}

type Error

type Error struct {
	Code    int             `json:"code"`
	Message string          `json:"message"`
	Data    json.RawMessage `json:"data,omitempty"`
}

func NewError

func NewError(code int, message string) *Error

func (*Error) Error

func (e *Error) Error() string

type ErrorHint added in v0.5.2

type ErrorHint struct {
	Original   string
	Suggestion string
	Action     string
	Reference  string
}

func GetAllHintsForError added in v0.5.2

func GetAllHintsForError(originalMessage string) []ErrorHint

func GetErrorHint added in v0.5.2

func GetErrorHint(originalMessage string) *ErrorHint

type FieldDescription added in v0.5.2

type FieldDescription struct {
	Name string `json:"name"`
	Type string `json:"type"`
	Req  bool   `json:"required,omitempty"`
	Desc string `json:"description"`
}

type Handler

type Handler struct {
	// contains filtered or unexported fields
}

func NewHandler

func NewHandler(p pool.ServerSource, logger *slog.Logger) *Handler

func NewHandlerWithToolStore

func NewHandlerWithToolStore(p pool.ServerSource, logger *slog.Logger, store toolstore.Cache) *Handler

func (*Handler) CachedTools added in v0.9.2

func (h *Handler) CachedTools() map[string][]Tool

CachedTools returns a snapshot of the tools known per server name. It is used by the serve listener to register backend tools with the router so tool calls can be routed to the owning server.

func (*Handler) EnableLazyLoading added in v0.7.0

func (h *Handler) EnableLazyLoading(ttl time.Duration)

func (*Handler) HandleRequest

func (h *Handler) HandleRequest(ctx context.Context, req *Request) (*Response, error)

func (*Handler) PopulateToolCache added in v0.5.0

func (h *Handler) PopulateToolCache(ctx context.Context)

func (*Handler) ResetManifest

func (h *Handler) ResetManifest()

func (*Handler) SetDefaultTimeout added in v0.9.1

func (h *Handler) SetDefaultTimeout(timeout time.Duration)

SetDefaultTimeout overrides the fallback timeout used when a server has no explicit per-server entry. A zero or negative value is ignored (the 30s default remains in effect).

func (*Handler) SetTimeout added in v0.9.1

func (h *Handler) SetTimeout(serverName string, timeout time.Duration)

SetTimeout registers a per-server request timeout. The handler falls back to its default timeout (30s unless changed via SetDefaultTimeout) for any server that has no explicit entry. A zero duration clears the entry.

type HealthcheckCapability

type HealthcheckCapability struct{}

type InitializeParams

type InitializeParams struct {
	ProtocolVersion string             `json:"protocolVersion"`
	Capabilities    ClientCapabilities `json:"capabilities"`
	ClientInfo      ClientInfo         `json:"clientInfo"`
}

type InitializeResult

type InitializeResult struct {
	ProtocolVersion string             `json:"protocolVersion"`
	Capabilities    ServerCapabilities `json:"capabilities"`
	ServerInfo      ServerInfo         `json:"serverInfo"`
}

type MCPServerInstance

type MCPServerInstance struct {
	// contains filtered or unexported fields
}

func NewMCPServerInstance

func NewMCPServerInstance(logger *slog.Logger) *MCPServerInstance

func (*MCPServerInstance) GetServer

func (m *MCPServerInstance) GetServer() *server.MCPServer

func (*MCPServerInstance) ServeSSE

func (m *MCPServerInstance) ServeSSE(addr string) error

func (*MCPServerInstance) ServeStdio

func (m *MCPServerInstance) ServeStdio() error

func (*MCPServerInstance) ServeStreamableHTTP

func (m *MCPServerInstance) ServeStreamableHTTP(addr string) error

func (*MCPServerInstance) SetStdioPool

func (m *MCPServerInstance) SetStdioPool(p *pool.StdioPool)

func (*MCPServerInstance) SetupGatewayTools

func (m *MCPServerInstance) SetupGatewayTools()

type ParamInfo

type ParamInfo struct {
	Name        string
	Type        string
	IsRequired  bool
	Description string
}

type ParameterMeta added in v0.5.2

type ParameterMeta struct {
	Required        bool
	Default         interface{}
	Min             interface{}
	Max             interface{}
	Description     string
	SuggestedValues []string
}

func GetParamMeta added in v0.5.2

func GetParamMeta(toolName, paramName string) *ParameterMeta

type Prompt

type Prompt struct {
	Name        string           `json:"name"`
	Description string           `json:"description,omitempty"`
	Arguments   []PromptArgument `json:"arguments,omitempty"`
}

type PromptArgument

type PromptArgument struct {
	Name        string `json:"name"`
	Description string `json:"description,omitempty"`
	Required    bool   `json:"required,omitempty"`
}

type PromptsCapability

type PromptsCapability struct {
	ListChanged bool `json:"listChanged,omitempty"`
}

type PromptsListParams

type PromptsListParams struct {
	Cursor string `json:"cursor,omitempty"`
}

type PromptsListResult

type PromptsListResult struct {
	Prompts    []Prompt `json:"prompts"`
	NextCursor string   `json:"nextCursor,omitempty"`
}

type Request

type Request struct {
	JSONRPC string          `json:"jsonrpc"`
	Method  string          `json:"method"`
	Params  json.RawMessage `json:"params,omitempty"`
	ID      interface{}     `json:"id"`
}

func (*Request) IsNotification

func (r *Request) IsNotification() bool

type Resource

type Resource struct {
	URI         string `json:"uri"`
	Name        string `json:"name"`
	Description string `json:"description,omitempty"`
	MimeType    string `json:"mimeType,omitempty"`
}

type ResourcesCapability

type ResourcesCapability struct {
	Subscribe   bool `json:"subscribe,omitempty"`
	ListChanged bool `json:"listChanged,omitempty"`
}

type ResourcesListParams

type ResourcesListParams struct {
	Cursor string `json:"cursor,omitempty"`
}

type ResourcesListResult

type ResourcesListResult struct {
	Resources  []Resource `json:"resources"`
	NextCursor string     `json:"nextCursor,omitempty"`
}

type Response

type Response struct {
	JSONRPC string          `json:"jsonrpc"`
	Result  json.RawMessage `json:"result,omitempty"`
	Error   *Error          `json:"error,omitempty"`
	ID      interface{}     `json:"id"`
}

type ReturnSchema added in v0.5.2

type ReturnSchema struct {
	Type        string             `json:"type"`
	Description string             `json:"description"`
	Fields      []FieldDescription `json:"fields,omitempty"`
}

type RootsCapability

type RootsCapability struct {
	ListChanged bool `json:"listChanged,omitempty"`
}

type ServerCapabilities

type ServerCapabilities struct {
	Tools     *ToolsCapability          `json:"tools,omitempty"`
	Resources *ResourcesCapability      `json:"resources,omitempty"`
	Prompts   *PromptsCapability        `json:"prompts,omitempty"`
	Sampling  *ServerSamplingCapability `json:"sampling,omitempty"`
	Health    *HealthcheckCapability    `json:"healthcheck,omitempty"`
}

type ServerInfo

type ServerInfo struct {
	Name    string `json:"name"`
	Version string `json:"version"`
}

type ServerSamplingCapability

type ServerSamplingCapability struct{}

type Tool

type Tool struct {
	Name        string          `json:"name"`
	Description string          `json:"description"`
	InputSchema json.RawMessage `json:"inputSchema"`
}

type ToolCache

type ToolCache struct {
	// contains filtered or unexported fields
}

type ToolDefinition added in v0.5.2

type ToolDefinition struct {
	Name        string          `json:"name"`
	Description string          `json:"description"`
	Examples    []ToolExample   `json:"examples,omitempty"`
	Returns     ReturnSchema    `json:"returns,omitempty"`
	Categories  []string        `json:"categories,omitempty"`
	InputSchema json.RawMessage `json:"inputSchema"`
}

func GetAllToolDefinitions added in v0.5.2

func GetAllToolDefinitions() []ToolDefinition

func GetToolDefinition added in v0.5.2

func GetToolDefinition(name string) *ToolDefinition

type ToolExample added in v0.5.2

type ToolExample struct {
	Input       map[string]interface{} `json:"input"`
	Description string                 `json:"description"`
}

type ToolsCallParams

type ToolsCallParams struct {
	Name      string          `json:"name"`
	Arguments json.RawMessage `json:"arguments,omitempty"`
}

type ToolsCallResult

type ToolsCallResult struct {
	Content []ContentBlock `json:"content"`
	IsError bool           `json:"isError,omitempty"`
}

type ToolsCapability

type ToolsCapability struct {
	ListChanged bool `json:"listChanged,omitempty"`
}

type ToolsListParams

type ToolsListParams struct {
	Cursor string `json:"cursor,omitempty"`
}

type ToolsListResult

type ToolsListResult struct {
	Tools      []Tool `json:"tools"`
	NextCursor string `json:"nextCursor,omitempty"`
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL