mcp

package
v0.4.2 Latest Latest
Warning

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

Go to latest
Published: Sep 24, 2026 License: MIT Imports: 13 Imported by: 0

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

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

func NewSSEClient(ctx context.Context, baseURL string, headers map[string]string) (*Client, error)

NewSSEClient creates a new MCP client that communicates via Server-Sent Events with an HTTP server at the specified URL.

func NewStdioClient

func NewStdioClient(ctx context.Context, command string, args ...string) (*Client, error)

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

func (m *Client) CallTool(ctx context.Context, name string, args json.RawMessage) (string, error)

CallTool executes a tool on the MCP server with the given arguments. Returns the tool result as a string.

func (*Client) Close

func (m *Client) Close() error

Close terminates the MCP connection and cleans up resources.

func (*Client) FetchTools

func (m *Client) FetchTools(ctx context.Context) error

FetchTools asks the server for its tools and keeps them for GetToolDefinitions.

func (*Client) GetToolDefinitions

func (m *Client) GetToolDefinitions() []llm.Tool

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)
}

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

func (m *Manager) CallTool(ctx context.Context, name string, args json.RawMessage) (string, error)

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

func (m *Manager) Close() error

Close disconnects every server. Errors from closing sessions are ignored. Connect may be called again afterwards.

func (*Manager) Connect

func (m *Manager) Connect(ctx context.Context) error

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

func (m *Manager) FetchTools(ctx context.Context) error

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

func (m *Manager) GetToolDefinitions() []llm.Tool

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.

Jump to

Keyboard shortcuts

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