mcpclient

package
v1.41.1 Latest Latest
Warning

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

Go to latest
Published: Sep 3, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package mcpclient implements an MCP client that connects to external MCP servers over stdio. This allows odek to use tools from any MCP server (e.g., Claude Code's MCP servers for web scraping, databases, APIs, etc.) alongside its built-in tools.

Protocol: JSON-RPC 2.0 over stdin/stdout

  • initialize — protocol handshake
  • tools/list — discover available tools
  • tools/call — invoke a tool
  • ping — health check

Usage:

client, err := mcpclient.New("some-server", "node", []string{"server.js"})
tools, err := client.Discover(ctx)
result, err := client.CallTool(ctx, "tool_name", `{"arg":"val"}`)
client.Close()

Config in odek.json:

{
  "mcp_servers": {
    "my-server": {
      "command": "node",
      "args": ["/path/to/server.js"]
    }
  }
}

Extension contract constants for the odek generic extension surface.

This file is purely additive: it introduces the versioned contract under which third-party MCP servers can interoperate with odek, without changing any existing client behavior. The full normative specification lives in docs/EXTENSIONS.md.

Compatibility rule: all schemas below are additive. Producers may add new fields in future contract versions; consumers MUST ignore fields they do not recognize rather than failing.

Index

Constants

View Source
const (
	ProtocolVersion = "2025-03-26"

	// MaxResponseBytesCeiling is the absolute ceiling for
	// ServerConfig.MaxResponseBytes. No configuration may raise the response
	// cap above this value; attempting to do so is an error.
	MaxResponseBytesCeiling = 64 << 20 // 64 MiB

	// MaxTimeoutSeconds is the hard cap for ServerConfig.TimeoutSeconds.
	// Values above it are clamped to this cap with a warning.
	MaxTimeoutSeconds = 3600

	// DefaultMaxResultChars is the default cap on tool result text forwarded
	// to the model. Oversized (but valid) results receive a structured
	// truncation notice instead of being silently cut.
	DefaultMaxResultChars = 200000

	// MaxResultCharsCap is the hard cap for ServerConfig.MaxResultChars.
	// Values above it are clamped to this cap with a warning.
	MaxResultCharsCap = 1000000
)
View Source
const (
	// SchemaToolResult names the odek tool-result envelope. An MCP tool may
	// return this envelope (as a JSON text content item) to attach
	// out-of-band artifact references to an otherwise compact text result.
	SchemaToolResult = artifact.SchemaToolResult

	// SchemaArtifactRef names a single artifact reference inside a
	// tool-result envelope. An artifact ref points at a file produced by the
	// tool (e.g. a full log-analysis report) that is intentionally NOT
	// inlined into the model context.
	SchemaArtifactRef = artifact.SchemaArtifactRef

	// SchemaEvent names one structured runtime event, emitted as a single
	// JSON object per line on an event stream (JSONL).
	SchemaEvent = "odek.event/v1"
)

Schema names carried in the "schema" field of structured payloads so consumers can detect and version-check them. The tool-result envelope and artifact-ref schema names are aliased from internal/artifact (the canonical definition and parser/validator live there) so the contract has a single source of truth.

View Source
const ExtensionContractVersion = "odek-extension/v1"

ExtensionContractVersion identifies the version of the odek extension contract implemented by this package. Extension servers and odek itself use this string to negotiate/document which schema set they speak.

Variables

View Source
var DefaultTimeout = 30 * time.Second

DefaultTimeout bounds each MCP request when neither the caller nor the server config supplies a deadline. It is a var so tests can temporarily lower it. Per-server config never mutates this global; it is only read as the default value source.

Functions

This section is empty.

Types

type Client

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

Client manages a connection to an external MCP server over stdio.

func New

func New(name string, cfg ServerConfig) (*Client, error)

New spawns an MCP server process and returns a client connected to it. The server process is started immediately and cleaned up on Close().

func (*Client) ArtifactRoots added in v1.24.0

func (c *Client) ArtifactRoots() []string

ArtifactRoots returns the configured artifact roots for this server. Empty means every artifact ref from this server must be rejected (fail closed). Validation against these roots is performed by the artifact subsystem.

func (*Client) CallTool

func (c *Client) CallTool(ctx context.Context, name string, argsJSON string) (string, error)

CallTool invokes a tool on the MCP server with the given JSON arguments and returns the text content of the result.

func (*Client) Close

func (c *Client) Close() error

Close terminates the MCP server process and cleans up resources. Safe to call multiple times.

func (*Client) Discover

func (c *Client) Discover(ctx context.Context) ([]ToolDef, error)

Discover performs the MCP handshake and returns all available tools.

func (*Client) Name

func (c *Client) Name() string

Name returns the server name for this client.

func (*Client) Warnings added in v1.24.0

func (c *Client) Warnings() []string

Warnings returns non-fatal configuration issues recorded at construction time (e.g. timeout_seconds or max_result_chars clamped to their hard caps). Callers should surface these to the operator.

type ServerConfig

type ServerConfig struct {
	// Command is the executable to run (e.g., "node", "python3", "uvx").
	Command string `json:"command"`
	// Args are the command-line arguments.
	Args []string `json:"args,omitempty"`
	// Env overrides environment variables for the subprocess.
	// Empty strings remove the variable from the environment.
	Env map[string]string `json:"env,omitempty"`

	// TimeoutSeconds bounds each request to this server when the caller does
	// not supply a deadline. Zero uses DefaultTimeout (30s). Values above
	// MaxTimeoutSeconds (3600) are clamped to the cap with a warning.
	TimeoutSeconds int `json:"timeout_seconds,omitempty"`

	// MaxResponseBytes caps the size of a single JSON-RPC response line from
	// this server. Zero uses the 10 MiB default. The absolute ceiling is
	// MaxResponseBytesCeiling (64 MiB); exceeding it is an error.
	MaxResponseBytes int64 `json:"max_response_bytes,omitempty"`

	// MaxResultChars caps the tool result text forwarded to the model. Zero
	// uses DefaultMaxResultChars (200000). Values above MaxResultCharsCap
	// (1000000) are clamped to the cap with a warning. Valid-but-oversized
	// results get a structured truncation notice (artifact refs retained),
	// never a silent cut.
	MaxResultChars int `json:"max_result_chars,omitempty"`

	// ArtifactRoots lists directories under which file:// artifact refs from
	// this server are accepted. Empty means every artifact ref is rejected
	// (fail closed). Refs in odek.tool-result/v1 envelopes are validated
	// against these roots by the artifact subsystem (internal/artifact)
	// before the result is rendered for the model.
	ArtifactRoots []string `json:"artifact_roots,omitempty"`

	// AutoApprove marks the server as trusted by the operator: it skips the
	// project-server approval prompt and the per-tool registration prompts
	// (schema guard scans still apply). TRUST RULES: the flag is honored
	// only when it comes from the operator-owned global config
	// (~/.odek/config.json) — either on a global server entry or as a
	// command-less trust marker for a project-defined server name. The
	// config loader strips auto_approve from project ./odek.json with a
	// warning: a cloned repo must never be able to approve its own MCP
	// servers. Trust metadata only — deliberately excluded from approval
	// keys, which hash execution-relevant fields.
	AutoApprove bool `json:"auto_approve,omitempty"`
}

ServerConfig defines an external MCP server to connect to. Matches the Claude Code MCP server config format, extended with the odek-extension/v1 timeout/limit fields (see docs/EXTENSIONS.md).

type ToolAdapter

type ToolAdapter struct {
	// Client is the MCP client connection.
	Client *Client

	// ToolName is the name of the tool on the MCP server.
	ToolName string

	// Desc is the tool description.
	Desc string

	// ParamSchema is the JSON schema for the tool's parameters.
	ParamSchema any
}

ToolAdapter wraps an MCP client tool as a odek.Tool-compatible value. It implements the Name(), Description(), Schema(), and Call() methods that odek's agent loop expects, forwarding calls to the MCP server.

func (*ToolAdapter) Call

func (a *ToolAdapter) Call(args string) (string, error)

Call invokes the tool on the MCP server with the given JSON arguments.

func (*ToolAdapter) Description

func (a *ToolAdapter) Description() string

Description returns the tool's description.

func (*ToolAdapter) Name

func (a *ToolAdapter) Name() string

Name returns the tool's name, prefixed with the server name to avoid collisions when multiple MCP servers expose tools with the same name.

func (*ToolAdapter) Schema

func (a *ToolAdapter) Schema() any

Schema returns the tool's input JSON schema.

type ToolDef

type ToolDef struct {
	Name        string `json:"name"`
	Description string `json:"description"`
	InputSchema any    `json:"inputSchema"`
}

ToolDef is the definition of a tool from tools/list.

Jump to

Keyboard shortcuts

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