Skip to content

Commit 1f22f5b

Browse files
authored
feat(profiles): bootstrap initial support for profiles
1 parent 6afb60f commit 1f22f5b

File tree

4 files changed

+99
-23
lines changed

4 files changed

+99
-23
lines changed

pkg/kubernetes-mcp-server/cmd/root.go

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,18 @@ Kubernetes Model Context Protocol (MCP) server
4040
# TODO: add more examples`,
4141
Run: func(cmd *cobra.Command, args []string) {
4242
initLogging()
43-
klog.V(5).Infof("Starting kubernetes-mcp-server")
43+
profile := mcp.ProfileFromString(viper.GetString("profile"))
44+
if profile == nil {
45+
fmt.Printf("Invalid profile name: %s, valid names are: %s\n", viper.GetString("profile"), mcp.ProfileNames)
46+
os.Exit(1)
47+
}
48+
klog.V(1).Infof("Starting kubernetes-mcp-server with profile: %s", profile.GetName())
4449
if viper.GetBool("version") {
4550
fmt.Println(version.Version)
4651
return
4752
}
4853
mcpServer, err := mcp.NewSever(mcp.Configuration{
54+
Profile: profile,
4955
Kubeconfig: viper.GetString("kubeconfig"),
5056
})
5157
if err != nil {
@@ -70,27 +76,51 @@ Kubernetes Model Context Protocol (MCP) server
7076
},
7177
}
7278

73-
func init() {
74-
rootCmd.Flags().BoolP("version", "v", false, "Print version information and quit")
75-
rootCmd.Flags().IntP("log-level", "", 0, "Set the log level (from 0 to 9)")
76-
rootCmd.Flags().IntP("sse-port", "", 0, "Start a SSE server on the specified port")
77-
rootCmd.Flags().StringP("sse-base-url", "", "", "SSE public base URL to use when sending the endpoint message (e.g. https://example.com)")
78-
rootCmd.Flags().StringP("kubeconfig", "", "", "Path to the kubeconfig file to use for authentication")
79-
_ = viper.BindPFlags(rootCmd.Flags())
80-
}
81-
8279
func Execute() {
8380
if err := rootCmd.Execute(); err != nil {
84-
panic(err)
81+
klog.Errorf("Failed to execute command: %s", err)
82+
os.Exit(1)
8583
}
8684
}
8785

8886
func initLogging() {
89-
logger := textlogger.NewLogger(textlogger.NewConfig(textlogger.Output(os.Stdout)))
90-
klog.SetLoggerWithOptions(logger)
9187
flagSet := flag.NewFlagSet("kubernetes-mcp-server", flag.ContinueOnError)
9288
klog.InitFlags(flagSet)
89+
loggerOptions := []textlogger.ConfigOption{textlogger.Output(os.Stdout)}
9390
if logLevel := viper.GetInt("log-level"); logLevel >= 0 {
91+
loggerOptions = append(loggerOptions, textlogger.Verbosity(logLevel))
9492
_ = flagSet.Parse([]string{"--v", strconv.Itoa(logLevel)})
9593
}
94+
logger := textlogger.NewLogger(textlogger.NewConfig(loggerOptions...))
95+
klog.SetLoggerWithOptions(logger)
96+
}
97+
98+
type profileFlag struct {
99+
mcp.Profile
100+
}
101+
102+
func (p *profileFlag) String() string {
103+
return p.GetName()
104+
}
105+
106+
func (p *profileFlag) Set(v string) error {
107+
p.Profile = mcp.ProfileFromString(v)
108+
if p.Profile != nil {
109+
return nil
110+
}
111+
return fmt.Errorf("invalid profile name: %s, valid names are: %s", v, mcp.ProfileNames)
112+
}
113+
114+
func (p *profileFlag) Type() string {
115+
return "profile"
116+
}
117+
118+
func init() {
119+
rootCmd.Flags().BoolP("version", "v", false, "Print version information and quit")
120+
rootCmd.Flags().IntP("log-level", "", 0, "Set the log level (from 0 to 9)")
121+
rootCmd.Flags().IntP("sse-port", "", 0, "Start a SSE server on the specified port")
122+
rootCmd.Flags().StringP("sse-base-url", "", "", "SSE public base URL to use when sending the endpoint message (e.g. https://example.com)")
123+
rootCmd.Flags().StringP("kubeconfig", "", "", "Path to the kubeconfig file to use for authentication")
124+
rootCmd.Flags().Var(&profileFlag{&mcp.FullProfile{}}, "profile", "MCP profile to use")
125+
_ = viper.BindPFlags(rootCmd.Flags())
96126
}

pkg/mcp/common_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ func (c *mcpContext) beforeEach(t *testing.T) {
105105
c.ctx, c.cancel = context.WithCancel(context.Background())
106106
c.tempDir = t.TempDir()
107107
c.withKubeConfig(nil)
108-
if c.mcpServer, err = NewSever(Configuration{}); err != nil {
108+
if c.mcpServer, err = NewSever(Configuration{Profile: &FullProfile{}}); err != nil {
109109
t.Fatal(err)
110110
return
111111
}

pkg/mcp/mcp.go

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ import (
55
"github.com/manusa/kubernetes-mcp-server/pkg/version"
66
"github.com/mark3labs/mcp-go/mcp"
77
"github.com/mark3labs/mcp-go/server"
8-
"slices"
98
)
109

1110
type Configuration struct {
11+
Profile Profile
1212
Kubeconfig string
1313
}
1414

@@ -43,14 +43,7 @@ func (s *Server) reloadKubernetesClient() error {
4343
return err
4444
}
4545
s.k = k
46-
s.server.SetTools(slices.Concat(
47-
s.initConfiguration(),
48-
s.initEvents(),
49-
s.initNamespaces(),
50-
s.initPods(),
51-
s.initResources(),
52-
s.initHelm(),
53-
)...)
46+
s.server.SetTools(s.configuration.Profile.GetTools(s)...)
5447
return nil
5548
}
5649

pkg/mcp/profiles.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package mcp
2+
3+
import (
4+
"github.com/mark3labs/mcp-go/server"
5+
"slices"
6+
)
7+
8+
var Profiles = []Profile{
9+
&FullProfile{},
10+
}
11+
12+
var ProfileNames []string
13+
14+
type Profile interface {
15+
GetName() string
16+
GetDescription() string
17+
GetTools(s *Server) []server.ServerTool
18+
}
19+
20+
func ProfileFromString(name string) Profile {
21+
for _, profile := range Profiles {
22+
if profile.GetName() == name {
23+
return profile
24+
}
25+
}
26+
return nil
27+
}
28+
29+
type FullProfile struct{}
30+
31+
func (p *FullProfile) GetName() string {
32+
return "full"
33+
}
34+
func (p *FullProfile) GetDescription() string {
35+
return "Complete profile with all tools and extended outputs"
36+
}
37+
func (p *FullProfile) GetTools(s *Server) []server.ServerTool {
38+
return slices.Concat(
39+
s.initConfiguration(),
40+
s.initEvents(),
41+
s.initNamespaces(),
42+
s.initPods(),
43+
s.initResources(),
44+
s.initHelm(),
45+
)
46+
}
47+
48+
func init() {
49+
ProfileNames = make([]string, 0)
50+
for _, profile := range Profiles {
51+
ProfileNames = append(ProfileNames, profile.GetName())
52+
}
53+
}

0 commit comments

Comments
 (0)