Sandbox
@njayp/ophis

Cobra CLI to MCP server library

Ophis plugs into a Cobra command tree and generates MCP tool schemas from commands, flags, and arguments. It then runs the CLI as a subprocess when a tool is called, and it can also manage editor config for MCP clients.

91 stars16 forksGoUpdated 1mo ago
Who it's for

Builders who want to expose an existing Cobra CLI to MCP clients without rewriting the app.

What it delivers

You can reuse one CLI as an MCP server and make its commands available inside your agent or editor.

What it does

Expose Cobra commands as MCP tools

Walks the Cobra command tree and turns commands into tools.

Generate tool schemas from flags and args

Builds JSON schemas so MCP clients can call the right command inputs.

Run the CLI as a subprocess

Executes the underlying Cobra command and captures output for the MCP response.

Filter exposed commands and flags

Uses selectors to include or exclude commands, local flags, and inherited flags.

Add editor config commands

Provides `claude`, `vscode`, and `cursor` subcommands to enable, disable, and list MCP servers.

Stream over HTTP

Offers `mcp stream` for remote access instead of only stdio.

Set default environment variables

Merges configured env values into the editor config written by `enable`.

How to get it

  1. 1Run
    go get github.com/njayp/ophis
  2. 2Expose your MCP server over HTTP for remote access
    ./my-cli mcp stream --host localhost --port 8080

README

Project Logo

Transform any Cobra CLI into an MCP server

Ophis automatically converts your Cobra commands into MCP tools, and provides CLI commands for integration with Claude Desktop, VSCode, and Cursor.

Quick Start

Install

go get github.com/njayp/ophis

Add to your CLI

package main

import (
    "os"
    "github.com/njayp/ophis"
)

func main() {
    rootCmd := createMyRootCommand()
    rootCmd.AddCommand(ophis.Command(nil))

    if err := rootCmd.Execute(); err != nil {
        os.Exit(1)
    }
}

Enable in Claude Desktop, VSCode, or Cursor

# Claude Desktop
./my-cli mcp claude enable
# Restart Claude Desktop

# VSCode (requires Copilot in Agent Mode)
./my-cli mcp vscode enable

# Cursor
./my-cli mcp cursor enable

Your CLI commands are now available as MCP tools!

Stream over HTTP

Expose your MCP server over HTTP for remote access:

./my-cli mcp stream --host localhost --port 8080

Commands

The ophis.Command(nil) adds these subcommands to your CLI (the default command name is mcp, configurable via Config.CommandName):

mcp
├── start            # Start MCP server on stdio
├── stream           # Stream MCP server over HTTP
├── tools            # Export available MCP tools as JSON
├── claude
│   ├── enable       # Add server to Claude Desktop config
│   ├── disable      # Remove server from Claude Desktop config
│   └── list         # List Claude Desktop MCP servers
├── vscode
│   ├── enable       # Add server to VSCode config
│   ├── disable      # Remove server from VSCode config
│   └── list         # List VSCode MCP servers
└── cursor
    ├── enable       # Add server to Cursor config
    ├── disable      # Remove server from Cursor config
    └── list         # List Cursor MCP servers

Configuration

Control which commands and flags are exposed as MCP tools using selectors. By default, all commands and flags are exposed (except hidden/deprecated).

config := &ophis.Config{
    Selectors: []ophis.Selector{
        {
            CmdSelector: ophis.AllowCmdsContaining("get", "list"),
            LocalFlagSelector: ophis.ExcludeFlags("token", "secret"),
            InheritedFlagSelector: ophis.NoFlags,  // Exclude persistent flags

            // Middleware wraps command execution
            Middleware: func(ctx context.Context, req *mcp.CallToolRequest, in ophis.ToolInput, next func(context.Context, *mcp.CallToolRequest, ophis.ToolInput) (*mcp.CallToolResult, ophis.ToolOutput, error)) (*mcp.CallToolResult, ophis.ToolOutput, error) {
                ctx, cancel := context.WithTimeout(ctx, time.Minute)
                defer cancel()
                return next(ctx, req, in)
            },
        },
    },
}

rootCmd.AddCommand(ophis.Command(config))

Custom Command Name

By default the ophis command is named mcp. If your CLI already uses mcp for something else, set CommandName to avoid the collision:

config := &ophis.Config{
    CommandName: "agent",
}

rootCmd.AddCommand(ophis.Command(config))

The command tree, editor config (enable/disable), and internal filters all use the configured name automatically.

Default Environment Variables

Editors launch MCP server subprocesses with a minimal environment. On macOS this means a PATH of just /usr/bin:/bin:/usr/sbin:/sbin, so tools like helm, kubectl, or docker installed via mise/homebrew/nix won't be found. Use DefaultEnv to capture the current PATH (or any other variables) at enable time:

config := &ophis.Config{
    DefaultEnv: map[string]string{
        "PATH": os.Getenv("PATH"),
    },
}

rootCmd.AddCommand(ophis.Command(config))

These are merged into the editor config written by enable. User-provided --env values take precedence on conflict.

See docs/config.md for detailed configuration options.

How It Works

Ophis bridges Cobra commands and the Model Context Protocol:

  1. Command Discovery: Recursively walks your Cobra command tree
  2. Schema Generation: Creates JSON schemas from command flags and arguments (docs/schema.md)
  3. Tool Execution: Spawns your CLI as a subprocess and captures output (docs/execution.md)

Contributing

Contributions welcome! See CONTRIBUTING.md.

Files in the repo

Repository payload32 top-level entries
  • .github
  • docs
  • examples
  • internal
  • test
  • .gitignore
  • .golangci.yml
  • annotations_test.go
  • annotations.go
  • config_test.go
  • config.go
  • CONTRIBUTING.md
  • doc.go
  • execute_test.go
  • execute.go
  • go.mod
  • go.sum
  • LICENSE
  • logo.png
  • makefile
  • README.md
  • root.go
  • schema.go
  • selector_test.go
  • selector.go
  • selectors_test.go
  • selectors.go
  • start.go
  • stream.go
  • tools.go
  • utils_test.go
  • utils.go

Discussion (0)

Ask about usage, or say what you built with it

Sign in to join the discussion.

No comments yet. Be the first to say what this is good for.

More frameworks & sdks

HKUDS/nanobotFrameworks & SDKs

Ultra-lightweight, open-source, self-hosted personal AI agent framework in Python with WebUI, tools, memory, MCP, multi-agent workflows, automation, and chat apps

48k
microsoft/
SkillOpt
microsoft/SkillOptFrameworks & SDKs

SkillOpt is a text-space optimizer that trains reusable natural-language skills for frozen LLM agents through trajectory-driven edits, validation-gated updates, and deployable best_skill.md artifacts.

17k
omnigent-ai/omnigentFrameworks & SDKs

Omnigent is an open-source AI agent framework and meta-harness: orchestrate Claude Code, Codex, Cursor, Pi, and custom agents — swap harnesses without rewriting, enforce policies and sandboxing, and collaborate in real time from any device.

9.8k
kyegomez/
OpenMythos
kyegomez/OpenMythosFrameworks & SDKs

A theoretical reconstruction of the Claude Mythos architecture, built from first principles using the available research literature.

15k
D4Vinci/ScraplingFrameworks & SDKs

🕷️ An adaptive Web Scraping framework that handles everything from a single request to a full-scale crawl!

80k