-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdoc.go
More file actions
114 lines (114 loc) · 3.93 KB
/
Copy pathdoc.go
File metadata and controls
114 lines (114 loc) · 3.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// Package cobrax transforms Cobra CLI applications into MCP (Model Context Protocol) servers,
// enabling AI assistants to interact with command-line tools.
//
// Ophis automatically converts existing Cobra commands into MCP tools, handling
// protocol complexity, command execution, and tool registration.
//
// # Two Execution Models
//
// Ophis supports two execution models:
//
// 1. Subprocess model ([Command] / [Config]): The MCP server re-invokes the
// same binary as a subprocess for each tool call. This works well when all
// necessary state can be reconstructed from CLI flags alone.
//
// 2. In-process model ([NewMCPServer] / [MCPServer]): The MCP server calls the
// cobra.Command's Run/RunE function directly in-process. Because the command
// closures already hold references to runtime dependencies (API clients,
// database handles, business-logic objects, etc.), those objects are
// available without any additional wiring. This is the preferred model when
// commands depend on non-serialisable state.
//
// # In-Process Usage (NewMCPServer)
//
// Provide a factory function that produces a fresh *cobra.Command tree on each
// call. The factory is invoked once at registration time (read-only, for schema
// generation) and once per tool invocation at runtime. Using a factory ensures
// that every tool call gets its own Options structs, flag values, and
// closure-captured variables — eliminating all shared-state hazards and making
// concurrent tool calls fully independent.
//
// package main
//
// import (
// "context"
// "log"
// "github.com/onexstack/cobrax"
// )
//
// func main() {
// // Dependencies are injected at construction time and shared safely
// // because they are read-only after initialisation.
// biz := newBotSreBiz(apiClient, dbClient)
//
// // Factory produces a fresh command tree per invocation.
// // Each call allocates new Options structs and closure state.
// factory := func() *cobra.Command {
// return buildRootCommand(biz) // adds all subcommands with biz in closures
// }
//
// srv, err := cobrax.NewMCPServer(cobrax.MCPOptions{
// Enabled: true,
// Addr: ":8090",
// Name: "myapp",
// Version: "1.0.0",
// }, factory)
// if err != nil {
// log.Fatal(err)
// }
//
// if err := srv.Start(context.Background()); err != nil {
// log.Fatal(err)
// }
// }
//
// # Subprocess Usage (Command)
//
// Add MCP server management subcommands to an existing Cobra application:
//
// package main
//
// import (
// "os"
// "github.com/onexstack/cobrax"
// )
//
// func main() {
// rootCmd := createMyRootCommand()
//
// // Adds: mcp start, mcp tools, mcp claude enable/disable/list, etc.
// rootCmd.AddCommand(cobrax.Command(nil))
//
// if err := rootCmd.Execute(); err != nil {
// os.Exit(1)
// }
// }
//
// # Configuration (Subprocess model)
//
// The [Config] struct provides fine-grained control over which commands and
// flags are exposed as MCP tools through a selector system.
//
// Basic filters are always applied automatically:
// - Hidden and deprecated commands/flags are excluded
// - Commands without executable functions are excluded
// - Built-in commands (mcp, help, completion) are excluded
//
// Example with selectors:
//
// config := &cobrax.Config{
// Selectors: []cobrax.Selector{
// {
// CmdSelector: cobrax.AllowCmdsContaining("get", "list"),
// LocalFlagSelector: cobrax.AllowFlags("namespace", "output"),
// InheritedFlagSelector: cobrax.NoFlags,
// },
// {
// CmdSelector: cobrax.AllowCmds("mycli delete"),
// LocalFlagSelector: cobrax.ExcludeFlags("all", "force"),
// InheritedFlagSelector: cobrax.NoFlags,
// },
// },
// SloggerOptions: &slog.HandlerOptions{Level: slog.LevelDebug},
// }
package cobrax