mirror of
https://github.com/k8sgpt-ai/k8sgpt.git
synced 2025-09-17 23:59:21 +00:00
feat(mcp): implement MCP server and handler
- Implement MCP server and handler - Add MCP server to serve - Add MCP handler to handle MCP requests - Add MCP server to serve - Add MCP handler to handle MCP requests
This commit is contained in:
@@ -187,7 +187,11 @@ var ServeCmd = &cobra.Command{
|
||||
|
||||
if enableMCP {
|
||||
// Create and start MCP server
|
||||
mcpServer := k8sgptserver.NewMCPServer(mcpPort, aiProvider)
|
||||
mcpServer, err := k8sgptserver.NewMCPServer(mcpPort, aiProvider)
|
||||
if err != nil {
|
||||
color.Red("Error creating MCP server: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
go func() {
|
||||
if err := mcpServer.Start(); err != nil {
|
||||
color.Red("Error starting MCP server: %v", err)
|
||||
|
@@ -28,19 +28,41 @@ type MCPServer struct {
|
||||
server *mcp_golang.Server
|
||||
port string
|
||||
aiProvider *ai.AIProvider
|
||||
analysis *analysis.Analysis
|
||||
}
|
||||
|
||||
// NewMCPServer creates a new MCP server
|
||||
func NewMCPServer(port string, aiProvider *ai.AIProvider) *MCPServer {
|
||||
func NewMCPServer(port string, aiProvider *ai.AIProvider) (*MCPServer, error) {
|
||||
// Create MCP server with stdio transport
|
||||
transport := stdio.NewStdioServerTransport()
|
||||
|
||||
server := mcp_golang.NewServer(transport)
|
||||
|
||||
// Initialize analysis configuration
|
||||
analysis, err := analysis.NewAnalysis(
|
||||
aiProvider.Name, // backend
|
||||
"english", // language
|
||||
[]string{}, // filters
|
||||
"", // namespace
|
||||
"", // labelSelector
|
||||
false, // nocache
|
||||
false, // explain
|
||||
10, // maxConcurrency
|
||||
false, // withDoc
|
||||
false, // interactiveMode
|
||||
[]string{}, // customHeaders
|
||||
false, // withStats
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to initialize analysis: %v", err)
|
||||
}
|
||||
|
||||
return &MCPServer{
|
||||
server: server,
|
||||
port: port,
|
||||
aiProvider: aiProvider,
|
||||
}
|
||||
analysis: analysis,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Start starts the MCP server
|
||||
@@ -75,7 +97,18 @@ func (s *MCPServer) Start() error {
|
||||
|
||||
// AnalyzeRequest represents the input parameters for the analyze tool
|
||||
type AnalyzeRequest struct {
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
Backend string `json:"backend,omitempty"`
|
||||
Language string `json:"language,omitempty"`
|
||||
Filters []string `json:"filters,omitempty"`
|
||||
LabelSelector string `json:"labelSelector,omitempty"`
|
||||
NoCache bool `json:"noCache,omitempty"`
|
||||
Explain bool `json:"explain,omitempty"`
|
||||
MaxConcurrency int `json:"maxConcurrency,omitempty"`
|
||||
WithDoc bool `json:"withDoc,omitempty"`
|
||||
InteractiveMode bool `json:"interactiveMode,omitempty"`
|
||||
CustomHeaders []string `json:"customHeaders,omitempty"`
|
||||
WithStats bool `json:"withStats,omitempty"`
|
||||
}
|
||||
|
||||
// AnalyzeResponse represents the output of the analyze tool
|
||||
@@ -95,67 +128,42 @@ type ClusterInfoResponse struct {
|
||||
|
||||
// handleAnalyze handles the analyze tool
|
||||
func (s *MCPServer) handleAnalyze(ctx context.Context, request *AnalyzeRequest) (*mcp_golang.ToolResponse, error) {
|
||||
namespace := "default"
|
||||
if request != nil && request.Namespace != "" {
|
||||
namespace = request.Namespace
|
||||
}
|
||||
|
||||
// Create analysis configuration
|
||||
config, err := analysis.NewAnalysis(
|
||||
s.aiProvider.Name, // backend
|
||||
"english", // language
|
||||
[]string{}, // filters
|
||||
namespace, // namespace
|
||||
"", // labelSelector
|
||||
false, // nocache
|
||||
false, // explain
|
||||
10, // maxConcurrency
|
||||
false, // withDoc
|
||||
false, // interactiveMode
|
||||
[]string{}, // customHeaders
|
||||
false, // withStats
|
||||
// Create a new analysis with the request parameters
|
||||
analysis, err := analysis.NewAnalysis(
|
||||
request.Backend,
|
||||
request.Language,
|
||||
request.Filters,
|
||||
request.Namespace,
|
||||
request.LabelSelector,
|
||||
request.NoCache,
|
||||
request.Explain,
|
||||
request.MaxConcurrency,
|
||||
request.WithDoc,
|
||||
request.InteractiveMode,
|
||||
request.CustomHeaders,
|
||||
request.WithStats,
|
||||
)
|
||||
if err != nil {
|
||||
return mcp_golang.NewToolResponse(mcp_golang.NewTextContent(fmt.Sprintf("failed to create analysis: %v", err))), nil
|
||||
return mcp_golang.NewToolResponse(mcp_golang.NewTextContent(fmt.Sprintf("Failed to create analysis: %v", err))), nil
|
||||
}
|
||||
defer config.Close()
|
||||
defer analysis.Close()
|
||||
|
||||
// Run the analysis
|
||||
config.RunAnalysis()
|
||||
analysis.RunAnalysis()
|
||||
|
||||
// Get the results
|
||||
results, err := config.PrintOutput("json")
|
||||
// Get the output
|
||||
output, err := analysis.PrintOutput("json")
|
||||
if err != nil {
|
||||
return mcp_golang.NewToolResponse(mcp_golang.NewTextContent(fmt.Sprintf("failed to get analysis results: %v", err))), nil
|
||||
return mcp_golang.NewToolResponse(mcp_golang.NewTextContent(fmt.Sprintf("Failed to print output: %v", err))), nil
|
||||
}
|
||||
|
||||
return mcp_golang.NewToolResponse(mcp_golang.NewTextContent(string(results))), nil
|
||||
return mcp_golang.NewToolResponse(mcp_golang.NewTextContent(string(output))), nil
|
||||
}
|
||||
|
||||
// handleClusterInfo handles the cluster-info tool
|
||||
func (s *MCPServer) handleClusterInfo(ctx context.Context, request *ClusterInfoRequest) (*mcp_golang.ToolResponse, error) {
|
||||
// Create analysis configuration to get cluster info
|
||||
config, err := analysis.NewAnalysis(
|
||||
s.aiProvider.Name, // backend
|
||||
"english", // language
|
||||
[]string{}, // filters
|
||||
"", // namespace
|
||||
"", // labelSelector
|
||||
false, // nocache
|
||||
false, // explain
|
||||
10, // maxConcurrency
|
||||
false, // withDoc
|
||||
false, // interactiveMode
|
||||
[]string{}, // customHeaders
|
||||
false, // withStats
|
||||
)
|
||||
if err != nil {
|
||||
return mcp_golang.NewToolResponse(mcp_golang.NewTextContent(fmt.Sprintf("failed to create analysis: %v", err))), nil
|
||||
}
|
||||
defer config.Close()
|
||||
|
||||
// Get cluster info from the client
|
||||
version, err := config.Client.Client.Discovery().ServerVersion()
|
||||
version, err := s.analysis.Client.Client.Discovery().ServerVersion()
|
||||
if err != nil {
|
||||
return mcp_golang.NewToolResponse(mcp_golang.NewTextContent(fmt.Sprintf("failed to get cluster version: %v", err))), nil
|
||||
}
|
||||
@@ -179,28 +187,8 @@ func (s *MCPServer) registerResources() error {
|
||||
}
|
||||
|
||||
func (s *MCPServer) getClusterInfo(ctx context.Context) (interface{}, error) {
|
||||
// Create analysis configuration to get cluster info
|
||||
config, err := analysis.NewAnalysis(
|
||||
s.aiProvider.Name, // backend
|
||||
"english", // language
|
||||
[]string{}, // filters
|
||||
"", // namespace
|
||||
"", // labelSelector
|
||||
false, // nocache
|
||||
false, // explain
|
||||
10, // maxConcurrency
|
||||
false, // withDoc
|
||||
false, // interactiveMode
|
||||
[]string{}, // customHeaders
|
||||
false, // withStats
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create analysis: %v", err)
|
||||
}
|
||||
defer config.Close()
|
||||
|
||||
// Get cluster info from the client
|
||||
version, err := config.Client.Client.Discovery().ServerVersion()
|
||||
version, err := s.analysis.Client.Client.Discovery().ServerVersion()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get cluster version: %v", err)
|
||||
}
|
||||
@@ -211,3 +199,11 @@ func (s *MCPServer) getClusterInfo(ctx context.Context) (interface{}, error) {
|
||||
"gitVersion": version.GitVersion,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Close closes the MCP server and releases resources
|
||||
func (s *MCPServer) Close() error {
|
||||
if s.analysis != nil {
|
||||
s.analysis.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user