Skip to main content
Glama
main.go5.26 kB
// Copyright 2025 The Inspektor Gadget authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "context" "flag" "fmt" "log/slog" "os" "os/signal" "strings" "syscall" "k8s.io/cli-runtime/pkg/genericclioptions" "github.com/inspektor-gadget/ig-mcp-server/pkg/discoverer" "github.com/inspektor-gadget/ig-mcp-server/pkg/gadgetmanager" "github.com/inspektor-gadget/ig-mcp-server/pkg/server" "github.com/inspektor-gadget/ig-mcp-server/pkg/tools" ) // This variable is used by the "version" command and is set during build var version = "undefined" var ( // MCP server configuration readOnly = flag.Bool("read-only", false, "run the server in read-only mode") transport = flag.String("transport", "stdio", fmt.Sprintf("transport to use (%s)", strings.Join(server.SupportedTransports, ", "))) transportHost = flag.String("transport-host", "localhost", "host for the transport") transportPort = flag.String("transport-port", "8080", "port for the transport") // Inspektor Gadget configuration environment = flag.String("environment", "kubernetes", "environment to use (currently only 'kubernetes' or 'linux' is supported)") linuxRemoteAddress = flag.String("linux-remote-address", "unix:///var/run/ig/ig.socket", "Comma-separated list of remote address (gRPC) to connect (unix:///var/run/ig/ig.socket)") gadgetImages = flag.String("gadget-images", "", "comma-separated list of gadget images to use (e.g. 'trace_dns:latest,trace_open:latest')") gadgetDiscoverer = flag.String("gadget-discoverer", "artifacthub", "gadget discoverer to use (artifacthub)") artifactHubDiscovererOfficial = flag.Bool("artifacthub-official", true, "use only official gadgets from Artifact Hub") // Server configuration logLevel = flag.String("log-level", "", "log level (debug, info, warn, error)") versionFlag = flag.Bool("version", false, "print version and exit") // Kubernetes configuration k8sConfig = genericclioptions.NewConfigFlags(false) ) var log = slog.Default().With("component", "ig-mcp-server") func init() { if k8sConfig.KubeConfig != nil { flag.StringVar(k8sConfig.KubeConfig, "kubeconfig", "", "Path to the kubeconfig file to use") } if k8sConfig.Context != nil { flag.StringVar(k8sConfig.Context, "context", "", "The name of the kubeconfig context to use") } if k8sConfig.AuthInfoName != nil { flag.StringVar(k8sConfig.AuthInfoName, "user", "", "The name of the kubeconfig user to use") } if k8sConfig.BearerToken != nil { flag.StringVar(k8sConfig.BearerToken, "token", "", "Bearer token to use for authentication") } } func main() { flag.Parse() if *versionFlag { log.Info("Inspektor Gadget MCP Server", "version", version) os.Exit(0) } if *environment != "kubernetes" && *environment != "linux" { logFatal("invalid environment, must be 'kubernetes' or 'linux'", "environment", *environment) } if *logLevel != "" { l, err := parseLogLevel(*logLevel) if err != nil { logFatal("invalid log level", "error", err) } slog.SetLogLoggerLevel(l) } ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) defer stop() mgr, err := gadgetmanager.NewGadgetManager(*environment, *linuxRemoteAddress, k8sConfig) if err != nil { logFatal("failed to create gadget manager", "error", err) } var dis discoverer.Discoverer if *gadgetDiscoverer != "" { dis, err = discoverer.New(*gadgetDiscoverer, discoverer.WithArtifactHubOfficialOnly(*artifactHubDiscovererOfficial)) if err != nil { logFatal("failed to create gadget discoverer", "error", err) } } registry := tools.NewToolRegistry(mgr, *environment, k8sConfig, dis, *readOnly) srv := server.New(version, registry) var images []string if gadgetImages != nil && *gadgetImages != "" { images = strings.Split(*gadgetImages, ",") } if err = registry.Prepare(ctx, images); err != nil { logFatal("failed to prepare tool registry", "error", err) } go func() { defer stop() if err = srv.Start(*transport, *transportHost, *transportPort); err != nil { log.Error("failed to start server", "error", err) } }() <-ctx.Done() log.Info("Received shutdown signal, shutting down server") if err = srv.Shutdown(ctx); err != nil { logFatal("failed to shutdown server", "error", err) } } func logFatal(msg string, args ...any) { log.Error(msg, args...) os.Exit(1) } func parseLogLevel(level string) (slog.Level, error) { switch strings.ToLower(level) { case "debug": return slog.LevelDebug, nil case "info": return slog.LevelInfo, nil case "warn": return slog.LevelWarn, nil case "error": return slog.LevelError, nil } return 0, fmt.Errorf("invalid log level: %s", level) }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/inspektor-gadget/ig-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server