Documentation
¶
Overview ¶
cmd/celeste/tools/mcp/adapter.go
cmd/celeste/tools/mcp/client.go
cmd/celeste/tools/mcp/config.go
cmd/celeste/tools/mcp/discovery.go
cmd/celeste/tools/mcp/jsonrpc.go
cmd/celeste/tools/mcp/manager.go
cmd/celeste/tools/mcp/sse.go
cmd/celeste/tools/mcp/stdio.go
cmd/celeste/tools/mcp/transport.go
Index ¶
- Variables
- func DiscoverConfigPaths(cwd, home string) []string
- func GlobalConfigPaths(home string) []string
- func IsGlobalConfig(home, path string) bool
- func SetServerEnabled(path, name string, enabled bool) error
- func SplitGlobal(paths []string, home string) (global, workspace []string)
- func ToolName(server, tool string) string
- type Client
- type ContentBlock
- type ErrorObject
- type HTTPTransport
- func (t *HTTPTransport) Close() error
- func (t *HTTPTransport) Receive() (*Response, error)
- func (t *HTTPTransport) Send(req *Request) error
- func (t *HTTPTransport) SendContext(ctx context.Context, req *Request) error
- func (t *HTTPTransport) SendNotification(notif *Notification) error
- func (t *HTTPTransport) SendNotificationContext(ctx context.Context, notif *Notification) error
- func (t *HTTPTransport) SetProtocolVersion(v string)
- type MCPConfig
- type MCPTool
- func (m *MCPTool) Description() string
- func (m *MCPTool) Execute(ctx context.Context, input map[string]any, progress chan<- tools.ProgressEvent) (tools.ToolResult, error)
- func (m *MCPTool) InterruptBehavior() tools.InterruptBehavior
- func (m *MCPTool) IsConcurrencySafe(input map[string]any) bool
- func (m *MCPTool) IsReadOnly() bool
- func (m *MCPTool) Name() string
- func (m *MCPTool) Parameters() json.RawMessage
- func (m *MCPTool) ValidateInput(input map[string]any) error
- type MCPToolDef
- type Manager
- func (m *Manager) Connect(ctx context.Context, name string, cfg ServerConfig) error
- func (m *Manager) Disconnect(name string) error
- func (m *Manager) IsConnected(name string) bool
- func (m *Manager) RegisterGlobalInto(dst *tools.Registry, home string) int
- func (m *Manager) RegisterInto(dst *tools.Registry) int
- func (m *Manager) ServerStatus() []ServerInfo
- func (m *Manager) SetAdmit(admit func(name string, cfg ServerConfig) bool)
- func (m *Manager) Start(ctx context.Context) error
- func (m *Manager) Stop() error
- type Notification
- type Request
- type Response
- type SSETransport
- func (t *SSETransport) Close() error
- func (t *SSETransport) Receive() (*Response, error)
- func (t *SSETransport) Send(req *Request) error
- func (t *SSETransport) SendContext(ctx context.Context, req *Request) error
- func (t *SSETransport) SendNotification(notif *Notification) error
- func (t *SSETransport) SendNotificationContext(ctx context.Context, notif *Notification) error
- type ServerConfig
- type ServerInfo
- type SkippedConfigError
- type StdioTransport
- type ToolAnnotations
- type ToolCallResult
- type ToolError
- type Transport
Constants ¶
This section is empty.
Variables ¶
var ErrWorkspaceConfigSkipped = errors.New("skipped workspace MCP config")
ErrWorkspaceConfigSkipped matches (errors.Is) the error of a workspace MCP config that did not load and was skipped: a warning, not a failure, since the other configs' servers still start.
Functions ¶
func DiscoverConfigPaths ¶
DiscoverConfigPaths returns the MCP config files that exist on disk, ordered from lowest to highest precedence. Later paths override earlier ones on server-name collision (see LoadMerged). Non-existent candidates, and any that is not a regular file, are skipped, so an empty slice means no MCP config anywhere.
func GlobalConfigPaths ¶
GlobalConfigPaths returns the home-level MCP config candidates, in the precedence order DiscoverConfigPaths uses, whether or not they exist. Any other path DiscoverConfigPaths returns came from the workspace.
func IsGlobalConfig ¶
IsGlobalConfig reports whether path is one of home's GlobalConfigPaths: the user's own config, whose servers start without approval. With no home, nothing is.
func SetServerEnabled ¶
SetServerEnabled flips the `enabled` flag of one server in the config file at path and writes it back, preserving all other fields. Errors if the file or the named server does not exist.
func SplitGlobal ¶
SplitGlobal splits paths (as DiscoverConfigPaths returns them) into the home-level configs every mode loads and the workspace configs only the interactive chat loads, each in its original order. With no home every path is a workspace one.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is a high-level MCP client that handles the protocol handshake, tool discovery, and tool execution over a Transport.
func (*Client) CallTool ¶
func (c *Client) CallTool(ctx context.Context, name string, arguments map[string]any) (string, error)
CallTool executes a tool on the MCP server and returns the text result. Multiple text content blocks are joined with newlines. A result the server marked isError comes back as a *ToolError carrying that text.
func (*Client) Initialize ¶
Initialize performs the MCP initialize handshake. Sends initialize request, validates the server's protocol version, then sends notifications/initialized.
func (*Client) ListTools ¶
func (c *Client) ListTools(ctx context.Context) ([]MCPToolDef, error)
ListTools discovers available tools from the MCP server.
func (*Client) ProtocolVersion ¶
ProtocolVersion returns the MCP protocol version negotiated with the server during Initialize. Empty until Initialize succeeds.
type ContentBlock ¶
ContentBlock is a single content item in a tool call response.
type ErrorObject ¶
type ErrorObject struct {
Code int `json:"code"`
Message string `json:"message"`
Data json.RawMessage `json:"data,omitempty"`
}
ErrorObject is the error payload in a JSON-RPC 2.0 response.
func (*ErrorObject) Error ¶
func (e *ErrorObject) Error() string
Error implements the error interface.
type HTTPTransport ¶
type HTTPTransport struct {
// contains filtered or unexported fields
}
HTTPTransport speaks MCP over Streamable HTTP: each outbound message is POSTed to the endpoint; the response is either a single JSON object or an SSE stream of JSON-RPC messages. Decoded responses are queued for Receive to drain.
func NewHTTPTransport ¶
func NewHTTPTransport(url string) (*HTTPTransport, error)
NewHTTPTransport creates a Streamable-HTTP transport for the given endpoint.
func (*HTTPTransport) Close ¶
func (t *HTTPTransport) Close() error
Close is a no-op for the stateless HTTP transport.
func (*HTTPTransport) Receive ¶
func (t *HTTPTransport) Receive() (*Response, error)
Receive drains the next queued response.
func (*HTTPTransport) Send ¶
func (t *HTTPTransport) Send(req *Request) error
Send POSTs a request and queues the resulting response(s).
func (*HTTPTransport) SendContext ¶
func (t *HTTPTransport) SendContext(ctx context.Context, req *Request) error
SendContext is Send, abandoned when ctx is done. The server answers inside the POST, so this bounds the whole call.
func (*HTTPTransport) SendNotification ¶
func (t *HTTPTransport) SendNotification(notif *Notification) error
SendNotification POSTs a notification; no response is queued.
func (*HTTPTransport) SendNotificationContext ¶
func (t *HTTPTransport) SendNotificationContext(ctx context.Context, notif *Notification) error
SendNotificationContext is SendNotification, abandoned when ctx is done.
func (*HTTPTransport) SetProtocolVersion ¶
func (t *HTTPTransport) SetProtocolVersion(v string)
SetProtocolVersion sets the value sent as the MCP-Protocol-Version header.
type MCPConfig ¶
type MCPConfig struct {
Servers map[string]ServerConfig `json:"mcpServers"`
}
MCPConfig is the top-level configuration for MCP servers. Loaded from ~/.celeste/mcp.json.
func LoadConfig ¶
LoadConfig reads and parses the MCP configuration from a JSON file. If the file does not exist, returns an empty config (not an error). This allows celeste to start without any MCP servers configured.
Only a regular file of at most maxConfigBytes is read: a workspace's .mcp.json is untrusted, and a FIFO or a link to a device would block or never end (Aikido 806869859).
func LoadMerged ¶
LoadMerged folds every config in paths into a single MCPConfig. paths must be ordered lowest-to-highest precedence (as DiscoverConfigPaths returns them): a server name present in a later path replaces the earlier definition wholesale. Each surviving server is stamped with the Origin path it came from. A missing file is skipped (LoadConfig already treats os.ErrNotExist as empty).
func LoadMergedLenient ¶
LoadMergedLenient is LoadMerged, except that a workspace config (a path not among home's GlobalConfigPaths) that fails to load or parse is skipped, its error returned in skipped, instead of failing the whole load: a broken repository .mcp.json must not turn off the user's own servers (Aikido 806869709). A home config that fails still fails it.
type MCPTool ¶
type MCPTool struct {
// contains filtered or unexported fields
}
MCPTool wraps an MCP tool definition and implements the tools.Tool interface. It delegates execution to the MCP Client, bridging external MCP servers into celeste's unified tool system.
func NewMCPTool ¶
func NewMCPTool(def MCPToolDef, client *Client, serverName string) *MCPTool
NewMCPTool creates a new MCPTool adapter for the given MCP tool definition.
func (*MCPTool) Description ¶
func (*MCPTool) Execute ¶
func (m *MCPTool) Execute(ctx context.Context, input map[string]any, progress chan<- tools.ProgressEvent) (tools.ToolResult, error)
Execute calls the MCP tool via the client and returns the result. Server-side errors are returned as ToolResult with Error=true so the LLM can see and react to the error message.
func (*MCPTool) InterruptBehavior ¶
func (m *MCPTool) InterruptBehavior() tools.InterruptBehavior
func (*MCPTool) IsConcurrencySafe ¶
IsConcurrencySafe returns false because MCP tool calls go over a shared transport and we cannot guarantee the server handles concurrent calls safely.
func (*MCPTool) IsReadOnly ¶
IsReadOnly is the tool's readOnlyHint when the user marked its server "trusted": true; otherwise false. The hint is the server's own unverified claim, and IsReadOnly auto-approves in default mode, so an untrusted server's hint is ignored.
func (*MCPTool) Parameters ¶
func (m *MCPTool) Parameters() json.RawMessage
type MCPToolDef ¶
type MCPToolDef struct {
Name string `json:"name"`
Description string `json:"description"`
InputSchema json.RawMessage `json:"inputSchema"`
Annotations *ToolAnnotations `json:"annotations,omitempty"`
}
MCPToolDef is a tool definition returned by the MCP server.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager handles the lifecycle of all MCP server connections. It loads configuration, connects to servers, discovers tools, and registers them in the tool registry.
func NewManager ¶
NewManager creates a new MCP Manager. configPath is the path to the MCP configuration file (e.g., ~/.celeste/mcp.json). registry is the tool registry where discovered MCP tools will be registered.
func NewManagerMulti ¶
NewManagerMulti creates a Manager that merges MCP config from multiple discovered paths (see DiscoverConfigPaths / LoadMerged) instead of a single file. Lower-index paths are overridden by higher-index paths on name clash.
func (*Manager) Connect ¶
Connect builds a transport from cfg, connects, and registers the server's tools at runtime. Safe to call after Start (lazy connect). A server that is already connected is a no-op. The connect is in flight, and a Disconnect or Stop revokes it, from before the transport is built (Aikido review of #424).
func (*Manager) Disconnect ¶
Disconnect closes a server's client and removes exactly the tools it added. No-op if the server is not connected.
func (*Manager) IsConnected ¶
IsConnected reports whether a server currently has a live client.
func (*Manager) RegisterGlobalInto ¶
RegisterGlobalInto is RegisterInto for a non-interactive run nested under the chat (2.0 F2e): only servers configured in one of home's global files (GlobalConfigPaths) are mirrored. A server from the workspace's .mcp.json or .celeste/mcp.json, or of unknown origin, stays the chat's: non-interactive runs never run a repo's MCP servers.
func (*Manager) RegisterInto ¶
RegisterInto registers every connected server's tools in dst, hidden until find_tools activates them (as discoverAndRegister does), and returns how many it added. A nested run's registry uses it to share this manager's clients instead of starting its own servers. Tools a server adds later are not mirrored; the nested registry is a snapshot.
func (*Manager) ServerStatus ¶
func (m *Manager) ServerStatus() []ServerInfo
ServerStatus returns health information for all connected MCP servers.
func (*Manager) SetAdmit ¶
func (m *Manager) SetAdmit(admit func(name string, cfg ServerConfig) bool)
SetAdmit makes Start skip an enabled server admit refuses (a workspace server nobody approved). Connect is unaffected: the /mcp panel connects a server only when the person asks. Call it before Start.
func (*Manager) Start ¶
Start loads the MCP configuration, connects to all configured servers, discovers their tools, and registers them in the tool registry. If the config file does not exist, it returns nil (no MCP configured). If a server fails to connect, it logs a warning and continues with others.
type Notification ¶
type Notification struct {
JSONRPC string `json:"jsonrpc"`
Method string `json:"method"`
Params json.RawMessage `json:"params,omitempty"`
}
Notification is a JSON-RPC 2.0 notification (no ID, no response expected).
func NewNotification ¶
func NewNotification(method string) *Notification
NewNotification creates a JSON-RPC 2.0 notification (no ID).
type Request ¶
type Request struct {
JSONRPC string `json:"jsonrpc"`
ID int64 `json:"id"`
Method string `json:"method"`
Params json.RawMessage `json:"params,omitempty"`
}
Request is a JSON-RPC 2.0 request.
type Response ¶
type Response struct {
JSONRPC string `json:"jsonrpc"`
ID json.Number `json:"id,omitempty"`
Result json.RawMessage `json:"result,omitempty"`
Error *ErrorObject `json:"error,omitempty"`
}
Response is a JSON-RPC 2.0 response.
type SSETransport ¶
type SSETransport struct {
// contains filtered or unexported fields
}
SSETransport communicates with an MCP server over HTTP Server-Sent Events. Requests are sent via POST to the server's endpoint URL. Responses are received via an SSE event stream from a GET connection.
func NewSSETransport ¶
func NewSSETransport(url string) (*SSETransport, error)
NewSSETransport connects to an MCP server's SSE endpoint. url is the base URL of the MCP server (e.g., "http://localhost:3000/sse").
func (*SSETransport) Close ¶
func (t *SSETransport) Close() error
Close shuts down the SSE connection.
func (*SSETransport) Receive ¶
func (t *SSETransport) Receive() (*Response, error)
Receive reads the next JSON-RPC response from the SSE event stream. It also returns once the transport is closed, so a Receive the client left running for a cancelled call doesn't outlive Close. It returns the stream's error once the stream has ended and every response it delivered has been read.
func (*SSETransport) Send ¶
func (t *SSETransport) Send(req *Request) error
Send sends a JSON-RPC request via HTTP POST to the server's endpoint.
func (*SSETransport) SendContext ¶
func (t *SSETransport) SendContext(ctx context.Context, req *Request) error
SendContext is Send, abandoned when ctx is done.
func (*SSETransport) SendNotification ¶
func (t *SSETransport) SendNotification(notif *Notification) error
SendNotification sends a JSON-RPC notification via HTTP POST.
func (*SSETransport) SendNotificationContext ¶
func (t *SSETransport) SendNotificationContext(ctx context.Context, notif *Notification) error
SendNotificationContext is SendNotification, abandoned when ctx is done.
type ServerConfig ¶
type ServerConfig struct {
// Enabled opts the server into auto-connection at startup. It is false by
// default: a server is only connected if it explicitly sets
// "enabled": true. This keeps configured-but-unused servers (e.g. an X
// bridge awaiting its first OAuth login) from delaying startup.
Enabled bool `json:"enabled,omitempty"`
// Transport is "stdio" or "sse". Defaults to "stdio" if not set.
Transport string `json:"transport"`
// Command is the executable to spawn (stdio transport only).
Command string `json:"command,omitempty"`
// Args are command-line arguments (stdio transport only).
Args []string `json:"args,omitempty"`
// URL is the SSE endpoint URL (sse transport only).
URL string `json:"url,omitempty"`
// Env is a map of environment variables passed to the child process.
// Values support ${VAR} expansion from the host environment.
Env map[string]string `json:"env,omitempty"`
// Trusted honours this server's readOnlyHint, which auto-approves the
// tools it marks read-only. Set it only for servers you control. It is
// read only from the home-level configs (GlobalConfigPaths): a
// repository's .mcp.json cannot vouch for its own server (2.0 W4).
Trusted bool `json:"trusted,omitempty"`
// Dir is the working directory a stdio server starts in; empty is
// celeste's own. Set by the caller (an ACP session uses its folder),
// never parsed from JSON.
Dir string `json:"-"`
// Origin is the absolute path of the config file this server was loaded
// from. Set by the discovery/merge layer, never parsed from JSON. Used by
// the /mcp panel to show provenance.
Origin string `json:"-"`
}
ServerConfig defines how to connect to a single MCP server.
func (ServerConfig) TrustHash ¶
func (c ServerConfig) TrustHash() string
TrustHash is what a workspace server's approval is pinned to: its transport, command, args, env (names and values as written, before ${VAR} expansion) and url. Any edit to them asks again; "enabled", "trusted" and the file it sits in do not count.
func (ServerConfig) TrustSummary ¶
func (c ServerConfig) TrustSummary() string
TrustSummary describes the server for an approval prompt: what it runs or connects to. Strings from the file are Go-quoted so they cannot act on the terminal; env values, a URL's password and its query are left out, since they often hold secrets.
type ServerInfo ¶
ServerInfo contains health/status information for a connected MCP server.
type SkippedConfigError ¶
SkippedConfigError is one workspace MCP config LoadMergedLenient skipped.
func SkippedConfigs ¶
func SkippedConfigs(err error) []*SkippedConfigError
SkippedConfigs returns the skipped configs err carries (Start's error).
func (*SkippedConfigError) Error ¶
func (e *SkippedConfigError) Error() string
func (*SkippedConfigError) Is ¶
func (e *SkippedConfigError) Is(target error) bool
Is makes every SkippedConfigError match ErrWorkspaceConfigSkipped.
func (*SkippedConfigError) Unwrap ¶
func (e *SkippedConfigError) Unwrap() error
type StdioTransport ¶
type StdioTransport struct {
// contains filtered or unexported fields
}
StdioTransport communicates with an MCP server via a child process's stdin and stdout. Each JSON-RPC message is a single line of JSON.
func (*StdioTransport) Close ¶
func (t *StdioTransport) Close() error
Close shuts down the child process and closes pipes.
func (*StdioTransport) Receive ¶
func (t *StdioTransport) Receive() (*Response, error)
Receive reads the next JSON line from stdout and parses it as a Response. A line over maxResponseBytes fails and closes the transport: the rest of it cannot be skipped reliably (Aikido 806869944).
func (*StdioTransport) Send ¶
func (t *StdioTransport) Send(req *Request) error
Send sends a JSON-RPC request as a single JSON line to the child process stdin.
func (*StdioTransport) SendNotification ¶
func (t *StdioTransport) SendNotification(notif *Notification) error
SendNotification sends a JSON-RPC notification as a single JSON line.
type ToolAnnotations ¶
type ToolAnnotations struct {
ReadOnlyHint *bool `json:"readOnlyHint,omitempty"`
DestructiveHint *bool `json:"destructiveHint,omitempty"`
IdempotentHint *bool `json:"idempotentHint,omitempty"`
OpenWorldHint *bool `json:"openWorldHint,omitempty"`
}
ToolAnnotations are a tool's hints from tools/list. They are the server's own claims: only readOnlyHint is used, and only for a server the user marked "trusted": true (2.0 W4). The others are kept, unused.
type ToolCallResult ¶
type ToolCallResult struct {
Content []ContentBlock `json:"content"`
IsError bool `json:"isError,omitempty"`
}
ToolCallResult is the server's response to tools/call. IsError marks a call the tool itself reported as failed (MCP's isError).
type ToolError ¶
type ToolError struct {
Text string
}
ToolError is CallTool's error for a result the server marked isError. Text is the result's own text, which the model gets as the failure.
type Transport ¶
type Transport interface {
// Send sends a JSON-RPC request to the server.
// For requests, the caller should subsequently call Receive to get the response.
Send(req *Request) error
// SendNotification sends a JSON-RPC notification (no response expected).
SendNotification(notif *Notification) error
// Receive reads the next JSON-RPC response from the server.
// Blocks until a response is available or the transport is closed.
Receive() (*Response, error)
// Close shuts down the transport, releasing all resources.
Close() error
}
Transport is the abstraction over MCP communication channels. Implementations handle the physical sending and receiving of JSON-RPC messages over stdio (child process) or SSE (HTTP).