climcp

package module
v0.0.0-...-8845e25 Latest Latest
Warning

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

Go to latest
Published: May 26, 2026 License: MIT Imports: 15 Imported by: 0

README

cli-mcp

[![Go Reference][goreference_badge]][goreference_link] [![Go Report Card][goreportcard_badge]][goreportcard_link] [![Tests status][test_badge]][test_link]

cli-mcp turns a [urfave/cli][urfave/cli] v3 command tree into a CLI by default, with a batteries-included [Model Context Protocol][mcp] server attached. One binary, three usage forms, same code path.

app := &cli.Command{Name: "demo", Commands: []*cli.Command{ /* your tree */ }}
climcp.AttachMCP(app, climcp.Options{Name: "demo", Version: "v0.0.0"})
app.Run(ctx, os.Args)

That's it. app is now a regular CLI you can run directly, AND an MCP server when invoked as app mcp serve (stdio) or app mcp serve-http (Streamable HTTP).

The three forms

Given a hello subcommand, the same code is reachable as:

1. Plain CLI — humans run subcommands directly:

./demo hello kai --loud
# HELLO, KAI!

2. MCP server, raw JSON-RPC over the [Streamable HTTP][streamable] transport: start ./demo mcp serve-http --addr 127.0.0.1:8080, POST a tools/call payload to /mcp with the standard MCP headers. Returns "HELLO, KAI!" for the same args.

3. MCP server, called via [mcporter][mcporter] — the client wraps MCP tools as subcommands, so the caller sees a CLI shape again:

# mcporter.json
# {"mcpServers":{"demo":{"command":"./demo","args":["mcp","serve"]}}}
mcporter call demo hello kai --loud
# HELLO, KAI!

Form 1 runs the Action directly. Forms 2 and 3 round-trip through MCP and end up running the same Action with the same flags and args. The mcp subcommand group is auto-excluded from the MCP tool surface so calling MCP doesn't expose "how to start MCP".

See examples/dual-mode for the runnable version.

Features

  • Every leaf command becomes an MCP tool; tool name is the dot-joined path from the root's children.
  • Input schema derived from urfave flags (typed) and positional args.
  • stdio transport for editor/agent integrations, [Streamable HTTP][streamable] (current spec) for remote.
  • Built on the official [modelcontextprotocol/go-sdk][go-sdk].
  • Relays webops.* metadata onto MCP tool.Meta for [cli-web-ops] consumption.
  • Composes with [cli-guard]: Guard-wrapped actions audit and validate every tool call.

Documentation

docs/FEATURES.md inventory, examples/ demos, CLI reference, deploy/Caddyfile.example production posture. Dev verbs in .agent-guard/agent-guard.yaml; agent-guard lint validates against the Makefile.

Support

Bug or feature request: [create a new issue]. Conduct: Code of Conduct. Security: SECURITY.md. Siblings: [cli-guard], [cli-web-docs], [cli-web-ops].

See also

Cross-reference convention from coilysiren/agentic-os#59.

Documentation

Overview

Package climcp projects a urfave/cli v3 command tree as a Model Context Protocol (MCP) server. See docs/climcp.md.

Index

Examples

Constants

View Source
const MetaSessionIDField = "claudeSessionId"

MetaSessionIDField is the wire-level key read off MCP params._meta. See docs/session.md.

Variables

This section is empty.

Functions

func AddrFromEnv

func AddrFromEnv(fallback string) string

AddrFromEnv returns os.Getenv("ADDR") if non-empty, otherwise fallback. See docs/serve.md for the convention.

func AttachMCP

func AttachMCP(root *cli.Command, opts Options)

AttachMCP appends an "mcp" subcommand group to root with "serve" and "serve-http" leaves. See docs/attach.md.

func NewServer

func NewServer(root *cli.Command, opts Options) (*mcp.Server, error)

NewServer wires up an *mcp.Server with one tool per leaf command in root. Caller is responsible for running the server on a transport.

Example

Project a urfave/cli command tree as an MCP server. See docs/climcp.md.

package main

import (
	"fmt"

	climcp "github.com/coilysiren/cli-mcp"
	"github.com/urfave/cli/v3"
)

func main() {
	app := &cli.Command{
		Name: "demo",
		Commands: []*cli.Command{
			{Name: "hello", Usage: "greet someone"},
		},
	}

	srv, err := climcp.NewServer(app, climcp.Options{Name: "demo", Version: "v0.0.0"})
	fmt.Println("ok:", srv != nil && err == nil)
}
Output:
ok: true

func RunStreamableHTTP

func RunStreamableHTTP(ctx context.Context, root *cli.Command, opts Options, srv HTTPServerOptions) error

RunStreamableHTTP builds the projected MCP server and serves it over Streamable HTTP. Blocks until ctx is cancelled. See docs/serve.md.

func ServeStdio

func ServeStdio(ctx context.Context, root *cli.Command, opts Options) error

ServeStdio is the convenience entry point: build a server from root and run it over stdio until the context is cancelled or the peer disconnects.

func StreamableHTTPHandler

func StreamableHTTPHandler(root *cli.Command, opts Options) (http.Handler, error)

StreamableHTTPHandler returns an http.Handler exposing the projected command tree over MCP Streamable HTTP. See docs/climcp.md.

Example

StreamableHTTPHandler returns an http.Handler for MCP remote transport. See docs/serve.md.

package main

import (
	"fmt"

	climcp "github.com/coilysiren/cli-mcp"
	"github.com/urfave/cli/v3"
)

func main() {
	app := &cli.Command{
		Name:     "demo",
		Commands: []*cli.Command{{Name: "hello"}},
	}

	handler, err := climcp.StreamableHTTPHandler(app, climcp.Options{Name: "demo", Version: "v0.0.0"})
	fmt.Println("ok:", handler != nil && err == nil)
}
Output:
ok: true

func WriteJSON

func WriteJSON(w io.Writer, v any) error

WriteJSON encodes v as indented JSON onto w. See docs/serve.md.

Types

type HTTPServerOptions

type HTTPServerOptions struct {
	// Addr is the listen address. Default "127.0.0.1:8080".
	Addr string

	// MCPPath is the Streamable HTTP handler mount route. Default "/mcp".
	MCPPath string

	// HealthPath is a GET endpoint returning 200 + "ok\n". Default "/healthz".
	HealthPath string

	// DisableHealth suppresses the healthcheck endpoint when true.
	DisableHealth bool

	// Landing, if non-empty, is served as text/plain on GET /.
	Landing string

	// ReadHeaderTimeout is forwarded to http.Server. Default 10s.
	ReadHeaderTimeout time.Duration
}

HTTPServerOptions configure RunStreamableHTTP. See docs/serve.md.

type Options

type Options struct {
	// Name is the MCP server name advertised to the client. Required.
	Name string

	// Version is the MCP server version. Required.
	Version string

	// SkipPaths lists dot-joined command paths to hide as MCP tools.
	SkipPaths []string

	// IncludeGroups exposes non-leaf groups as MCP tools printing --help.
	IncludeGroups bool

	// NameJoiner joins command-path segments. Default "_". Use "." if
	// every consumer handles dots. SkipPaths always uses dots internally.
	NameJoiner string
}

Options configure the MCP server projection. See docs/climcp.md.

type ToolInput

type ToolInput map[string]any

ToolInput is the dynamic shape passed to AddTool's handler. Keys are flag names; "args" is the positional array.

Directories

Path Synopsis
examples
annotated-favorites command
Command annotated-favorites projects a CLI carrying webops.* metadata.
Command annotated-favorites projects a CLI carrying webops.* metadata.
composition-with-guard command
Command composition-with-guard shows cli-mcp composed with cli-guard.
Command composition-with-guard shows cli-mcp composed with cli-guard.
dual-mode command
Command dual-mode shows cli-mcp's headline shape: one binary, both CLI and MCP server.
Command dual-mode shows cli-mcp's headline shape: one binary, both CLI and MCP server.
large-tree command
Command large-tree projects a realistic multi-level CLI over stdio.
Command large-tree projects a realistic multi-level CLI over stdio.
serve command
Command serve runs a tiny CLI as an MCP server over stdio.
Command serve runs a tiny CLI as an MCP server over stdio.
serve-http command
Command serve-http runs a CLI as MCP over Streamable HTTP.
Command serve-http runs a CLI as MCP over Streamable HTTP.
skip-paths command
Command skip-paths demonstrates Options.SkipPaths and IncludeGroups.
Command skip-paths demonstrates Options.SkipPaths and IncludeGroups.
treebuilders
Package treebuilders exports each example's *cli.Command tree.
Package treebuilders exports each example's *cli.Command tree.

Jump to

Keyboard shortcuts

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