Skip to content

Commit 89c0442

Browse files
Fix bug on v1 application. (#8)
1 parent a53772d commit 89c0442

File tree

11 files changed

+873
-297
lines changed

11 files changed

+873
-297
lines changed

go.mod

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ go 1.24.3
44

55
require (
66
github.com/mark3labs/mcp-go v0.34.0
7-
k8s.io/api v0.33.2
7+
k8s.io/api v0.33.3
88
k8s.io/apimachinery v0.33.3
9-
k8s.io/client-go v0.33.2
10-
k8s.io/metrics v0.33.2
9+
k8s.io/client-go v0.33.3
10+
k8s.io/metrics v0.33.3
1111
)
1212

1313
require (

go.sum

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -138,18 +138,18 @@ gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
138138
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
139139
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
140140
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
141-
k8s.io/api v0.33.2 h1:YgwIS5jKfA+BZg//OQhkJNIfie/kmRsO0BmNaVSimvY=
142-
k8s.io/api v0.33.2/go.mod h1:fhrbphQJSM2cXzCWgqU29xLDuks4mu7ti9vveEnpSXs=
141+
k8s.io/api v0.33.3 h1:SRd5t//hhkI1buzxb288fy2xvjubstenEKL9K51KBI8=
142+
k8s.io/api v0.33.3/go.mod h1:01Y/iLUjNBM3TAvypct7DIj0M0NIZc+PzAHCIo0CYGE=
143143
k8s.io/apimachinery v0.33.3 h1:4ZSrmNa0c/ZpZJhAgRdcsFcZOw1PQU1bALVQ0B3I5LA=
144144
k8s.io/apimachinery v0.33.3/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
145-
k8s.io/client-go v0.33.2 h1:z8CIcc0P581x/J1ZYf4CNzRKxRvQAwoAolYPbtQes+E=
146-
k8s.io/client-go v0.33.2/go.mod h1:9mCgT4wROvL948w6f6ArJNb7yQd7QsvqavDeZHvNmHo=
145+
k8s.io/client-go v0.33.3 h1:M5AfDnKfYmVJif92ngN532gFqakcGi6RvaOF16efrpA=
146+
k8s.io/client-go v0.33.3/go.mod h1:luqKBQggEf3shbxHY4uVENAxrDISLOarxpTKMiUuujg=
147147
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
148148
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
149149
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4=
150150
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8=
151-
k8s.io/metrics v0.33.2 h1:gNCBmtnUMDMCRg9Ly5ehxP3OdKISMsOnh1vzk01iCgE=
152-
k8s.io/metrics v0.33.2/go.mod h1:yxoAosKGRsZisv3BGekC5W6T1J8XSV+PoUEevACRv7c=
151+
k8s.io/metrics v0.33.3 h1:9CcqBz15JZfISqwca33gdHS8I6XfsK1vA8WUdEnG70g=
152+
k8s.io/metrics v0.33.3/go.mod h1:Aw+cdg4AYHw0HvUY+lCyq40FOO84awrqvJRTw0cmXDs=
153153
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro=
154154
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
155155
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8=

internal/handlers/logs.go

Lines changed: 112 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,60 @@ import (
1212
"github.com/patrickdappollonio/mcp-kubernetes-ro/internal/response"
1313
)
1414

15+
// LogHandler provides MCP tools for retrieving and filtering Kubernetes pod logs.
16+
// It supports advanced log filtering with grep-like capabilities, time-based filtering,
17+
// container selection in multi-container pods, and access to previous container logs.
1518
type LogHandler struct {
1619
client *kubernetes.Client
1720
baseConfig *kubernetes.Config
1821
}
1922

23+
// NewLogHandler creates a new LogHandler with the provided Kubernetes client
24+
// and base configuration. The base configuration provides default values that can
25+
// be overridden on a per-request basis.
2026
func NewLogHandler(client *kubernetes.Client, baseConfig *kubernetes.Config) *LogHandler {
2127
return &LogHandler{
2228
client: client,
2329
baseConfig: baseConfig,
2430
}
2531
}
2632

33+
// GetLogs implements the get_logs MCP tool.
34+
// It retrieves pod logs with comprehensive filtering options including grep-like
35+
// pattern matching, time-based filtering, line limits, and container selection.
36+
// The logs can be filtered both by inclusion and exclusion patterns, supporting
37+
// both literal strings and regular expressions.
2738
func (h *LogHandler) GetLogs(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
2839
var params struct {
29-
Namespace string `json:"namespace"`
30-
Name string `json:"name"`
31-
Container string `json:"container"`
32-
Context string `json:"context"`
33-
MaxLines string `json:"max_lines"`
40+
// Namespace specifies the pod's namespace.
41+
Namespace string `json:"namespace"`
42+
43+
// Name specifies which pod's logs to retrieve.
44+
Name string `json:"name"`
45+
46+
// Container specifies which container's logs to retrieve (optional for single-container pods).
47+
Container string `json:"container"`
48+
49+
// Context specifies which Kubernetes context to use for this operation.
50+
Context string `json:"context"`
51+
52+
// MaxLines limits the number of log lines to retrieve.
53+
MaxLines string `json:"max_lines"`
54+
55+
// GrepInclude contains comma-separated patterns that lines must match to be included.
3456
GrepInclude string `json:"grep_include"`
57+
58+
// GrepExclude contains comma-separated patterns that exclude lines from output.
3559
GrepExclude string `json:"grep_exclude"`
36-
UseRegex bool `json:"use_regex"`
37-
Since string `json:"since"`
38-
Previous bool `json:"previous"`
60+
61+
// UseRegex determines whether to treat patterns as regular expressions.
62+
UseRegex bool `json:"use_regex"`
63+
64+
// Since retrieves logs newer than this time (supports durations like "5m" or absolute times).
65+
Since string `json:"since"`
66+
67+
// Previous retrieves logs from the previous terminated container instance.
68+
Previous bool `json:"previous"`
3969
}
4070

4171
if err := request.BindArguments(&params); err != nil {
@@ -146,11 +176,19 @@ func (h *LogHandler) GetLogs(ctx context.Context, request mcp.CallToolRequest) (
146176
return response.JSON(responseData)
147177
}
148178

179+
// GetPodContainers implements the get_pod_containers MCP tool.
180+
// It retrieves the list of container names within a specific pod, which is useful
181+
// for identifying available containers before retrieving logs from multi-container pods.
149182
func (h *LogHandler) GetPodContainers(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
150183
var params struct {
184+
// Namespace specifies the pod's namespace.
151185
Namespace string `json:"namespace"`
152-
Name string `json:"name"`
153-
Context string `json:"context"`
186+
187+
// Name specifies which pod to inspect for containers.
188+
Name string `json:"name"`
189+
190+
// Context specifies which Kubernetes context to use for this operation.
191+
Context string `json:"context"`
154192
}
155193

156194
if err := request.BindArguments(&params); err != nil {
@@ -176,11 +214,70 @@ func (h *LogHandler) GetPodContainers(ctx context.Context, request mcp.CallToolR
176214
return nil, fmt.Errorf("failed to get pod containers: %w", err)
177215
}
178216

179-
responseData := map[string]interface{}{
180-
"namespace": params.Namespace,
181-
"pod": params.Name,
217+
return response.JSON(map[string]interface{}{
182218
"containers": containers,
183-
}
219+
})
220+
}
184221

185-
return response.JSON(responseData)
222+
// GetTools returns all log-related MCP tools provided by this handler.
223+
// This includes tools for retrieving filtered pod logs and discovering
224+
// containers within pods.
225+
func (h *LogHandler) GetTools() []MCPTool {
226+
return []MCPTool{
227+
NewMCPTool(
228+
mcp.NewTool("get_logs",
229+
mcp.WithDescription("Get pod logs with advanced filtering options including grep patterns, time filtering, and previous logs"),
230+
mcp.WithString("namespace",
231+
mcp.Required(),
232+
mcp.Description("Pod namespace"),
233+
),
234+
mcp.WithString("name",
235+
mcp.Required(),
236+
mcp.Description("Pod name"),
237+
),
238+
mcp.WithString("container",
239+
mcp.Description("Container name (required for multi-container pods)"),
240+
),
241+
mcp.WithString("context",
242+
mcp.Description("Kubernetes context to use (defaults to current context from kubeconfig)"),
243+
),
244+
mcp.WithString("max_lines",
245+
mcp.Description("Maximum number of lines to retrieve"),
246+
),
247+
mcp.WithString("grep_include",
248+
mcp.Description("Include only lines matching these patterns (comma-separated). Works like grep - includes lines containing any of these patterns"),
249+
),
250+
mcp.WithString("grep_exclude",
251+
mcp.Description("Exclude lines matching these patterns (comma-separated). Works like grep -v - excludes lines containing any of these patterns"),
252+
),
253+
mcp.WithBoolean("use_regex",
254+
mcp.Description("Whether to treat grep patterns as regular expressions instead of literal strings"),
255+
),
256+
mcp.WithString("since",
257+
mcp.Description("Return logs newer than this time. Supports durations like \"5m\", \"1h\", \"2h30m\", \"1d\" or absolute times like \"2023-01-01T10:00:00Z\""),
258+
),
259+
mcp.WithBoolean("previous",
260+
mcp.Description("Return logs from the previous terminated container instance (like kubectl logs --previous)"),
261+
),
262+
),
263+
h.GetLogs,
264+
),
265+
NewMCPTool(
266+
mcp.NewTool("get_pod_containers",
267+
mcp.WithDescription("List containers in a pod for log access"),
268+
mcp.WithString("namespace",
269+
mcp.Required(),
270+
mcp.Description("Pod namespace"),
271+
),
272+
mcp.WithString("name",
273+
mcp.Required(),
274+
mcp.Description("Pod name"),
275+
),
276+
mcp.WithString("context",
277+
mcp.Description("Kubernetes context to use (defaults to current context from kubeconfig)"),
278+
),
279+
),
280+
h.GetPodContainers,
281+
),
282+
}
186283
}

0 commit comments

Comments
 (0)