chatmcptools

package module
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Oct 6, 2026 License: MIT Imports: 11 Imported by: 0

README

chat-mcptools

Go Reference

Publishes a chat.Tool set on a loopback MCP server, so a provider driving a CLI in another process can offer that CLI the caller's in-process Go handlers.

It is a support library for the chat family, not a provider. It registers nothing, holds no vendor SDK and speaks to no API. If you are looking for a chat client, start with the core.

Why it exists

A local-CLI provider such as claude-local runs the vendor's binary as a subprocess. The tools a caller registers are Go closures in the calling process, and the binary cannot reach a closure, so the handlers are published over MCP on 127.0.0.1 and the CLI is pointed at them.

The server's life is one subprocess call. Every such provider spawns a process and waits for it, so that is exactly how long the handlers need to be reachable, and a listener costs microseconds to create. That is what keeps a Close method off chat.ChatClient.

Usage

session, err := chatmcptools.Serve(ctx, logger, tools)
if err != nil {
    return err
}
defer session.Stop()

if session.Endpoint != "" {
    // Point the CLI at session.Endpoint, presenting session.Token as
    // "Authorization: Bearer <token>". How that is expressed is the CLI's
    // business: a config file for one, a command-line override for another.
}

An empty tool set is not an error and starts nothing, so a provider can call Serve unconditionally and check Endpoint.

What it guarantees, and what it does not

  • Loopback only, on a port the kernel chooses, with the go-sdk's DNS-rebinding and cross-origin protections left on.
  • A fresh bearer token per call. Anything on the loopback interface can reach the port while it is open, so the token is a real credential. Keep it out of argv, which is world-readable through ps.
  • Dispatch is the core's. Every call goes through chat.ExecuteTool, so an unknown tool, a panicking handler and result marshalling behave exactly as they do for the API providers.

It does not decide what the CLI is allowed to do. Restricting the CLI's own tools is the provider's business, and every local-CLI provider in this family does it.

Specifications

Design and the reasoning behind it live in the core's wiki:

Licence

MIT. See LICENSE.

Documentation

Overview

Package chatmcptools publishes a chat.Tool set on a loopback MCP server, so a provider that drives a CLI in another process can offer that CLI the caller's in-process Go handlers.

The server's life is one subprocess call. Every local-CLI provider spawns a process and waits for it, so the useful span is exactly that, and a listener costs microseconds to create. That is what keeps a Close method off chat.ChatClient. See https://gitlab.com/phpboyscout/go/chat/-/wikis/specs/0009-claude-local-mcp-tools

A program links it with a blank import, which registers Serve with the core; local-CLI providers look the server up rather than importing this package:

import _ "gitlab.com/phpboyscout/go/chat-mcptools"

It knows nothing about any particular CLI. Serve returns where to reach the server and the token to present; turning that into command-line arguments is the provider's job, because that is the part that genuinely differs. See https://gitlab.com/phpboyscout/go/chat/-/wikis/specs/0022-codex-and-agy-local

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Session

type Session = chat.ToolSession

Session is a running tool server: the core's chat.ToolSession, so a provider can take it from the registry without importing this package. Stop is idempotent and must be called. Keep Token out of argv: a command line is world-readable through ps.

func Serve

func Serve(ctx context.Context, log *slog.Logger, tools map[string]chat.Tool) (*Session, error)

Serve publishes tools and returns where to reach them.

An empty set is not an error and starts nothing: the returned Session has an empty Endpoint and a Stop that does nothing, so a provider can call this unconditionally and check Endpoint to decide whether it has anything to tell its CLI about.

Jump to

Keyboard shortcuts

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