Documentation
¶
Overview ¶
Package mcp connects to Model Context Protocol servers over stdio, SSE or streamable HTTP, and exposes their tools in the llm.Tool format so an agent can call them next to its own tools.
Client is one connection, built with Dial. Manager connects a fixed list of servers, lists their tools in the order of that list, routes calls, reports each server's state and closes them. Neither reads nor writes any file.
Index ¶
- type Client
- func Dial(ctx context.Context, cfg ServerConfig) (*Client, error)
- func NewSSEClient(ctx context.Context, baseURL string, headers map[string]string) (*Client, error)
- func NewStdioClient(ctx context.Context, command string, args ...string) (*Client, error)
- func NewStreamableClient(ctx context.Context, baseURL string, headers map[string]string) (*Client, error)
- type Manager
- func (m *Manager) CallTool(ctx context.Context, name string, args json.RawMessage) (string, error)
- func (m *Manager) Close() error
- func (m *Manager) Connect(ctx context.Context) error
- func (m *Manager) FetchTools(ctx context.Context) error
- func (m *Manager) GetToolDefinitions() []llm.Tool
- func (m *Manager) Status() []ServerStatus
- type ServerConfig
- type ServerStatus
- type ToolExecutor
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is a connection to one MCP server. It lists the server's tools in the llm.Tool format and calls them. Build one with Dial or with one of the New*Client functions.
func Dial ¶
func Dial(ctx context.Context, cfg ServerConfig) (*Client, error)
Dial connects to the server described by cfg and fetches its tools. ${VAR} placeholders in Command, URL and header values are replaced with environment variables first. Fetching is tried three times, 500 ms apart, since a stdio server may still be starting. The caller closes the returned client.
func NewSSEClient ¶
NewSSEClient creates a new MCP client that communicates via Server-Sent Events with an HTTP server at the specified URL.
func NewStdioClient ¶
NewStdioClient creates a new MCP client that communicates via stdio with a subprocess running the specified command.
func NewStreamableClient ¶
func NewStreamableClient(ctx context.Context, baseURL string, headers map[string]string) (*Client, error)
NewStreamableClient creates a new MCP client that communicates via StreamableHTTP with an HTTP server at the specified URL. This is the modern MCP transport.
func (*Client) CallTool ¶
CallTool executes a tool on the MCP server with the given arguments. Returns the tool result as a string.
func (*Client) FetchTools ¶
FetchTools asks the server for its tools and keeps them for GetToolDefinitions.
func (*Client) GetToolDefinitions ¶
GetToolDefinitions converts MCP tools to the llm.Tool format. This allows the LLM to see and use MCP tools as if they were local tools.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager connects the servers it was built with and routes each tool call to the server that declared the tool. It is safe for concurrent use.
Example ¶
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"github.com/ThiraSoft/agentkit/mcp"
)
func main() {
ctx := context.Background()
m := mcp.NewManager([]mcp.ServerConfig{
{Name: "files", Transport: "stdio", Command: "/usr/local/bin/files-mcp --root /tmp"},
{Name: "search", Transport: "streamable", URL: "https://mcp.example.com/mcp", Headers: map[string]string{"Authorization": "Bearer ${SEARCH_TOKEN}"}},
})
defer m.Close()
if err := m.Connect(ctx); err != nil {
log.Print(err) // servers that answered stay connected
}
for _, s := range m.Status() {
fmt.Println(s.Name, s.Status, s.Tools)
}
out, err := m.CallTool(ctx, "list_files", json.RawMessage(`{"path":"/tmp"}`))
fmt.Println(out, err)
}
Output:
func NewManager ¶
func NewManager(configs []ServerConfig) *Manager
NewManager returns a Manager for configs, not connected yet. It keeps its own copy of the slice.
func (*Manager) CallTool ¶
CallTool calls the tool name on the server that declared it. When two servers declare the same name, the first one in the configs wins.
func (*Manager) Close ¶
Close disconnects every server. Errors from closing sessions are ignored. Connect may be called again afterwards.
func (*Manager) Connect ¶
Connect connects every enabled server, after closing its client from a previous Connect if any, and returns the joined errors of those that failed. Servers that answered stay connected. A disabled server is not dialed; Status reports it as "disabled". If multiple configs share the same name, the first is dialed and subsequent ones return an error without being dialed.
func (*Manager) FetchTools ¶
FetchTools asks every connected server for its tools again and returns the joined errors of those that failed. A failing server stays connected; its error shows in Status.
func (*Manager) GetToolDefinitions ¶
GetToolDefinitions returns the tools of the connected servers, in the order of the configs and, within a server, in the order it returned them.
func (*Manager) Status ¶
func (m *Manager) Status() []ServerStatus
Status returns the state of each server, in the order of the configs. Error holds the last error; for a connected server, the error of the last FetchTools.
type ServerConfig ¶
type ServerConfig struct {
Name string `json:"name"`
Transport string `json:"transport"` // "stdio", "sse" or "streamable"
// Command is the executable and its arguments for the stdio transport,
// split on spaces. There is no quoting: an argument containing a
// space cannot be expressed here.
Command string `json:"command,omitempty"`
URL string `json:"url,omitempty"` // for "sse" and "streamable"
Headers map[string]string `json:"headers,omitempty"`
// Enabled set to false keeps the server out of Manager.Connect. Nil
// (the field left out) means enabled, so a config that never mentions
// it connects.
Enabled *bool `json:"enabled,omitempty"`
}
ServerConfig describes one MCP server. Command, URL and header values may hold ${VAR} placeholders, replaced with environment variables when connecting.
func (ServerConfig) IsEnabled ¶
func (c ServerConfig) IsEnabled() bool
IsEnabled reports whether the server should be connected: true unless Enabled is set to false.
type ServerStatus ¶
type ServerStatus struct {
ServerConfig
Status string `json:"status"` // "connected", "disconnected", "disabled" or "error"
// Error is the last error; for a connected server, the error of the last FetchTools.
Error string `json:"error,omitempty"`
Tools []string `json:"tools"`
}
ServerStatus is the state of one server of a Manager. It embeds the ServerConfig as given, Headers included (placeholders unexpanded), so a caller serializing Status should not put tokens in clear in Headers.
type ToolExecutor ¶
type ToolExecutor interface {
FetchTools(ctx context.Context) error
GetToolDefinitions() []llm.Tool
CallTool(ctx context.Context, name string, args json.RawMessage) (string, error)
Close() error
}
ToolExecutor is a source of tools that can be listed and called. Client and Manager implement it.