Skip to content

Commit 59510a9

Browse files
aljesusgmanusa
andauthored
feat(kiali): consolidate kiali tools from 20 to 6 (#496)
* feat(kiali): Consolidate tools Signed-off-by: Alberto Gutierrez <aljesusg@gmail.com> * Address Marc comments Signed-off-by: Alberto Gutierrez <aljesusg@gmail.com> Co-authored-by: Marc Nuri <marc@marcnuri.com> --------- Signed-off-by: Alberto Gutierrez <aljesusg@gmail.com> Co-authored-by: Marc Nuri <marc@marcnuri.com>
1 parent 8d76426 commit 59510a9

20 files changed

+866
-1487
lines changed

README.md

Lines changed: 26 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -348,92 +348,38 @@ In case multi-cluster support is enabled (default) and you have access to multip
348348

349349
<summary>kiali</summary>
350350

351-
- **kiali_graph** - Check the status of my mesh by querying Kiali graph
351+
- **kiali_get_mesh_graph** - Returns the topology of a specific namespaces, health, status of the mesh and namespaces. Use this for high-level overviews
352+
- `graphType` (`string`) - Type of graph to return: 'versionedApp', 'app', 'service', 'workload', 'mesh'. Default: 'versionedApp'
352353
- `namespace` (`string`) - Optional single namespace to include in the graph (alternative to namespaces)
353354
- `namespaces` (`string`) - Optional comma-separated list of namespaces to include in the graph
354-
355-
- **kiali_mesh_status** - Get the status of mesh components including Istio, Kiali, Grafana, Prometheus and their interactions, versions, and health status
356-
357-
- **kiali_istio_config** - Get all Istio configuration objects in the mesh including their full YAML resources and details
358-
359-
- **kiali_istio_object_details** - Get detailed information about a specific Istio object including validation and help information
360-
- `group` (`string`) **(required)** - API group of the Istio object (e.g., 'networking.istio.io', 'gateway.networking.k8s.io')
361-
- `kind` (`string`) **(required)** - Kind of the Istio object (e.g., 'DestinationRule', 'VirtualService', 'HTTPRoute', 'Gateway')
362-
- `name` (`string`) **(required)** - Name of the Istio object
363-
- `namespace` (`string`) **(required)** - Namespace containing the Istio object
364-
- `version` (`string`) **(required)** - API version of the Istio object (e.g., 'v1', 'v1beta1')
365-
366-
- **kiali_istio_object_patch** - Modify an existing Istio object using PATCH method. The JSON patch data will be applied to the existing object.
367-
- `group` (`string`) **(required)** - API group of the Istio object (e.g., 'networking.istio.io', 'gateway.networking.k8s.io')
368-
- `json_patch` (`string`) **(required)** - JSON patch data to apply to the object
369-
- `kind` (`string`) **(required)** - Kind of the Istio object (e.g., 'DestinationRule', 'VirtualService', 'HTTPRoute', 'Gateway')
370-
- `name` (`string`) **(required)** - Name of the Istio object
371-
- `namespace` (`string`) **(required)** - Namespace containing the Istio object
372-
- `version` (`string`) **(required)** - API version of the Istio object (e.g., 'v1', 'v1beta1')
373-
374-
- **kiali_istio_object_create** - Create a new Istio object using POST method. The JSON data will be used to create the new object.
375-
- `group` (`string`) **(required)** - API group of the Istio object (e.g., 'networking.istio.io', 'gateway.networking.k8s.io')
376-
- `json_data` (`string`) **(required)** - JSON data for the new object
377-
- `kind` (`string`) **(required)** - Kind of the Istio object (e.g., 'DestinationRule', 'VirtualService', 'HTTPRoute', 'Gateway')
378-
- `namespace` (`string`) **(required)** - Namespace where the Istio object will be created
379-
- `version` (`string`) **(required)** - API version of the Istio object (e.g., 'v1', 'v1beta1')
380-
381-
- **kiali_istio_object_delete** - Delete an existing Istio object using DELETE method.
382-
- `group` (`string`) **(required)** - API group of the Istio object (e.g., 'networking.istio.io', 'gateway.networking.k8s.io')
383-
- `kind` (`string`) **(required)** - Kind of the Istio object (e.g., 'DestinationRule', 'VirtualService', 'HTTPRoute', 'Gateway')
384-
- `name` (`string`) **(required)** - Name of the Istio object
385-
- `namespace` (`string`) **(required)** - Namespace containing the Istio object
386-
- `version` (`string`) **(required)** - API version of the Istio object (e.g., 'v1', 'v1beta1')
387-
388-
- **kiali_validations_list** - List all the validations in the current cluster from all namespaces
389-
- `namespace` (`string`) - Optional single namespace to retrieve validations from (alternative to namespaces)
390-
- `namespaces` (`string`) - Optional comma-separated list of namespaces to retrieve validations from
391-
392-
- **kiali_namespaces** - Get all namespaces in the mesh that the user has access to
393-
394-
- **kiali_services_list** - Get all services in the mesh across specified namespaces with health and Istio resource information
355+
- `rateInterval` (`string`) - Rate interval for fetching (e.g., '10m', '5m', '1h'). Default: '60s'
356+
357+
- **kiali_manage_istio_config** - Manages Istio configuration objects (Gateways, VirtualServices, etc.). Can list (objects and validations), get, create, patch, or delete objects
358+
- `action` (`string`) **(required)** - Action to perform: list, get, create, patch, or delete
359+
- `group` (`string`) - API group of the Istio object (e.g., 'networking.istio.io', 'gateway.networking.k8s.io')
360+
- `json_data` (`string`) - JSON data to apply or create the object
361+
- `kind` (`string`) - Kind of the Istio object (e.g., 'DestinationRule', 'VirtualService', 'HTTPRoute', 'Gateway')
362+
- `name` (`string`) - Name of the Istio object
363+
- `namespace` (`string`) - Namespace containing the Istio object
364+
- `version` (`string`) - API version of the Istio object (e.g., 'v1', 'v1beta1')
365+
366+
- **kiali_get_resource_details** - Gets lists or detailed info for Kubernetes resources (services, workloads) within the mesh
395367
- `namespaces` (`string`) - Comma-separated list of namespaces to get services from (e.g. 'bookinfo' or 'bookinfo,default'). If not provided, will list services from all accessible namespaces
368+
- `resource_name` (`string`) - Name of the resource to get details for (optional string - if provided, gets details; if empty, lists all).
369+
- `resource_type` (`string`) - Type of resource to get details for (service, workload)
396370

397-
- **kiali_service_details** - Get detailed information for a specific service in a namespace, including validation, health status, and configuration
398-
- `namespace` (`string`) **(required)** - Namespace containing the service
399-
- `service` (`string`) **(required)** - Name of the service to get details for
400-
401-
- **kiali_service_metrics** - Get metrics for a specific service in a namespace. Supports filtering by time range, direction (inbound/outbound), reporter, and other query parameters
402-
- `byLabels` (`string`) - Comma-separated list of labels to group metrics by (e.g., 'source_workload,destination_service'). Optional
403-
- `direction` (`string`) - Traffic direction: 'inbound' or 'outbound'. Optional, defaults to 'outbound'
404-
- `duration` (`string`) - Duration of the query period in seconds (e.g., '1800' for 30 minutes). Optional, defaults to 1800 seconds
405-
- `namespace` (`string`) **(required)** - Namespace containing the service
406-
- `quantiles` (`string`) - Comma-separated list of quantiles for histogram metrics (e.g., '0.5,0.95,0.99'). Optional
407-
- `rateInterval` (`string`) - Rate interval for metrics (e.g., '1m', '5m'). Optional, defaults to '1m'
408-
- `reporter` (`string`) - Metrics reporter: 'source', 'destination', or 'both'. Optional, defaults to 'source'
409-
- `requestProtocol` (`string`) - Filter by request protocol (e.g., 'http', 'grpc', 'tcp'). Optional
410-
- `service` (`string`) **(required)** - Name of the service to get metrics for
411-
- `step` (`string`) - Step between data points in seconds (e.g., '15'). Optional, defaults to 15 seconds
412-
413-
- **kiali_workloads_list** - Get all workloads in the mesh across specified namespaces with health and Istio resource information
414-
- `namespaces` (`string`) - Comma-separated list of namespaces to get workloads from (e.g. 'bookinfo' or 'bookinfo,default'). If not provided, will list workloads from all accessible namespaces
415-
416-
- **kiali_workload_details** - Get detailed information for a specific workload in a namespace, including validation, health status, and configuration
417-
- `namespace` (`string`) **(required)** - Namespace containing the workload
418-
- `workload` (`string`) **(required)** - Name of the workload to get details for
419-
420-
- **kiali_workload_metrics** - Get metrics for a specific workload in a namespace. Supports filtering by time range, direction (inbound/outbound), reporter, and other query parameters
371+
- **kiali_get_metrics** - Gets lists or detailed info for Kubernetes resources (services, workloads) within the mesh
421372
- `byLabels` (`string`) - Comma-separated list of labels to group metrics by (e.g., 'source_workload,destination_service'). Optional
422373
- `direction` (`string`) - Traffic direction: 'inbound' or 'outbound'. Optional, defaults to 'outbound'
423-
- `duration` (`string`) - Duration of the query period in seconds (e.g., '1800' for 30 minutes). Optional, defaults to 1800 seconds
424-
- `namespace` (`string`) **(required)** - Namespace containing the workload
374+
- `duration` (`string`) - Time range to get metrics for (optional string - if provided, gets metrics; if empty, get default 1800s).
375+
- `namespace` (`string`) **(required)** - Namespace to get resources from
425376
- `quantiles` (`string`) - Comma-separated list of quantiles for histogram metrics (e.g., '0.5,0.95,0.99'). Optional
426377
- `rateInterval` (`string`) - Rate interval for metrics (e.g., '1m', '5m'). Optional, defaults to '1m'
427378
- `reporter` (`string`) - Metrics reporter: 'source', 'destination', or 'both'. Optional, defaults to 'source'
428379
- `requestProtocol` (`string`) - Filter by request protocol (e.g., 'http', 'grpc', 'tcp'). Optional
380+
- `resource_name` (`string`) **(required)** - Name of the resource to get details for (optional string - if provided, gets details; if empty, lists all).
381+
- `resource_type` (`string`) **(required)** - Type of resource to get details for (service, workload)
429382
- `step` (`string`) - Step between data points in seconds (e.g., '15'). Optional, defaults to 15 seconds
430-
- `workload` (`string`) **(required)** - Name of the workload to get metrics for
431-
432-
- **kiali_health** - Get health status for apps, workloads, and services across specified namespaces in the mesh. Returns health information including error rates and status for the requested resource type
433-
- `namespaces` (`string`) - Comma-separated list of namespaces to get health from (e.g. 'bookinfo' or 'bookinfo,default'). If not provided, returns health for all accessible namespaces
434-
- `queryTime` (`string`) - Unix timestamp (in seconds) for the prometheus query. If not provided, uses current time. Optional
435-
- `rateInterval` (`string`) - Rate interval for fetching error rate (e.g., '10m', '5m', '1h'). Default: '10m'
436-
- `type` (`string`) - Type of health to retrieve: 'app', 'service', or 'workload'. Default: 'app'
437383

438384
- **workload_logs** - Get logs for a specific workload's pods in a namespace. Only requires namespace and workload name - automatically discovers pods and containers. Optionally filter by container name, time range, and other parameters. Container is auto-detected if not specified.
439385
- `container` (`string`) - Optional container name to filter logs. If not provided, automatically detects and uses the main application container (excludes istio-proxy and istio-init)
@@ -442,36 +388,17 @@ In case multi-cluster support is enabled (default) and you have access to multip
442388
- `tail` (`integer`) - Number of lines to retrieve from the end of logs (default: 100)
443389
- `workload` (`string`) **(required)** - Name of the workload to get logs for
444390

445-
- **kiali_app_traces** - Get distributed tracing data for a specific app in a namespace. Returns trace information including spans, duration, and error details for troubleshooting and performance analysis.
446-
- `app` (`string`) **(required)** - Name of the app to get traces for
391+
- **kiali_get_traces** - Gets traces for a specific resource (app, service, workload) in a namespace
447392
- `clusterName` (`string`) - Cluster name for multi-cluster environments (optional)
448393
- `endMicros` (`string`) - End time for traces in microseconds since epoch (optional)
449394
- `limit` (`integer`) - Maximum number of traces to return (default: 100)
450395
- `minDuration` (`integer`) - Minimum trace duration in microseconds (optional)
451-
- `namespace` (`string`) **(required)** - Namespace containing the app
396+
- `namespace` (`string`) **(required)** - Namespace to get resources from
397+
- `resource_name` (`string`) **(required)** - Name of the resource to get details for (optional string - if provided, gets details; if empty, lists all).
398+
- `resource_type` (`string`) **(required)** - Type of resource to get metrics for (app, service, workload)
452399
- `startMicros` (`string`) - Start time for traces in microseconds since epoch (optional)
453400
- `tags` (`string`) - JSON string of tags to filter traces (optional)
454401

455-
- **kiali_service_traces** - Get distributed tracing data for a specific service in a namespace. Returns trace information including spans, duration, and error details for troubleshooting and performance analysis.
456-
- `clusterName` (`string`) - Cluster name for multi-cluster environments (optional)
457-
- `endMicros` (`string`) - End time for traces in microseconds since epoch (optional)
458-
- `limit` (`integer`) - Maximum number of traces to return (default: 100)
459-
- `minDuration` (`integer`) - Minimum trace duration in microseconds (optional)
460-
- `namespace` (`string`) **(required)** - Namespace containing the service
461-
- `service` (`string`) **(required)** - Name of the service to get traces for
462-
- `startMicros` (`string`) - Start time for traces in microseconds since epoch (optional)
463-
- `tags` (`string`) - JSON string of tags to filter traces (optional)
464-
465-
- **kiali_workload_traces** - Get distributed tracing data for a specific workload in a namespace. Returns trace information including spans, duration, and error details for troubleshooting and performance analysis.
466-
- `clusterName` (`string`) - Cluster name for multi-cluster environments (optional)
467-
- `endMicros` (`string`) - End time for traces in microseconds since epoch (optional)
468-
- `limit` (`integer`) - Maximum number of traces to return (default: 100)
469-
- `minDuration` (`integer`) - Minimum trace duration in microseconds (optional)
470-
- `namespace` (`string`) **(required)** - Namespace containing the workload
471-
- `startMicros` (`string`) - Start time for traces in microseconds since epoch (optional)
472-
- `tags` (`string`) - JSON string of tags to filter traces (optional)
473-
- `workload` (`string`) **(required)** - Name of the workload to get traces for
474-
475402
</details>
476403

477404

@@ -492,4 +419,4 @@ Compile the project and run the Kubernetes MCP server with [mcp-inspector](https
492419
make build
493420
# Run the Kubernetes MCP server with mcp-inspector
494421
npx @modelcontextprotocol/inspector@latest $(pwd)/kubernetes-mcp-server
495-
```
422+
```

pkg/kiali/endpoints.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,4 @@ const (
2323
WorkloadDetailsEndpoint = "/api/namespaces/%s/workloads/%s"
2424
WorkloadMetricsEndpoint = "/api/namespaces/%s/workloads/%s/metrics"
2525
ValidationsEndpoint = "/api/istio/validations"
26-
ValidationsListEndpoint = "/api/istio/validations"
2726
)

pkg/kiali/get_mesh_graph.go

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
package kiali
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"strings"
7+
"sync"
8+
)
9+
10+
type GetMeshGraphResponse struct {
11+
Graph json.RawMessage `json:"graph,omitempty"`
12+
Health json.RawMessage `json:"health,omitempty"`
13+
MeshStatus json.RawMessage `json:"mesh_status,omitempty"`
14+
Namespaces json.RawMessage `json:"namespaces,omitempty"`
15+
Errors map[string]string `json:"errors,omitempty"`
16+
}
17+
18+
// GetMeshGraph fetches multiple Kiali endpoints in parallel and returns a combined response.
19+
// Each field in the response corresponds to one API call result.
20+
// - graph: /api/namespaces/graph (optionally filtered by namespaces)
21+
// - health: /api/clusters/health (optionally filtered by namespaces and queryParams)
22+
// - status(mesh):/api/mesh/graph
23+
// - namespaces: /api/namespaces
24+
func (k *Kiali) GetMeshGraph(ctx context.Context, namespaces []string, queryParams map[string]string) (string, error) {
25+
cleaned := make([]string, 0, len(namespaces))
26+
for _, ns := range namespaces {
27+
ns = strings.TrimSpace(ns)
28+
if ns != "" {
29+
cleaned = append(cleaned, ns)
30+
}
31+
}
32+
33+
resp := GetMeshGraphResponse{
34+
Errors: make(map[string]string),
35+
}
36+
37+
var errorsMu sync.Mutex
38+
var wg sync.WaitGroup
39+
wg.Add(4)
40+
41+
// Graph
42+
go func() {
43+
defer wg.Done()
44+
data, err := k.getGraph(ctx, cleaned, queryParams)
45+
if err != nil {
46+
errorsMu.Lock()
47+
resp.Errors["graph"] = err.Error()
48+
errorsMu.Unlock()
49+
return
50+
}
51+
resp.Graph = data
52+
}()
53+
54+
// Health
55+
go func() {
56+
defer wg.Done()
57+
data, err := k.getHealth(ctx, cleaned, queryParams)
58+
if err != nil {
59+
errorsMu.Lock()
60+
resp.Errors["health"] = err.Error()
61+
errorsMu.Unlock()
62+
return
63+
}
64+
resp.Health = data
65+
}()
66+
67+
// Mesh status
68+
go func() {
69+
defer wg.Done()
70+
data, err := k.getMeshStatus(ctx)
71+
if err != nil {
72+
errorsMu.Lock()
73+
resp.Errors["mesh_status"] = err.Error()
74+
errorsMu.Unlock()
75+
return
76+
}
77+
resp.MeshStatus = data
78+
}()
79+
80+
// Namespaces
81+
go func() {
82+
defer wg.Done()
83+
data, err := k.getNamespaces(ctx)
84+
if err != nil {
85+
errorsMu.Lock()
86+
resp.Errors["namespaces"] = err.Error()
87+
errorsMu.Unlock()
88+
return
89+
}
90+
resp.Namespaces = data
91+
}()
92+
93+
wg.Wait()
94+
95+
// If no errors occurred, omit the errors map in the final JSON
96+
if len(resp.Errors) == 0 {
97+
resp.Errors = nil
98+
}
99+
100+
encoded, err := json.Marshal(resp)
101+
if err != nil {
102+
return "", err
103+
}
104+
return string(encoded), nil
105+
}
106+
107+
// getGraph wraps the Graph call and returns raw JSON.
108+
func (k *Kiali) getGraph(ctx context.Context, namespaces []string, queryParams map[string]string) (json.RawMessage, error) {
109+
out, err := k.Graph(ctx, namespaces, queryParams)
110+
if err != nil {
111+
return nil, err
112+
}
113+
return json.RawMessage([]byte(out)), nil
114+
}
115+
116+
// getHealth wraps the Health call and returns raw JSON.
117+
func (k *Kiali) getHealth(ctx context.Context, namespaces []string, queryParams map[string]string) (json.RawMessage, error) {
118+
nsParam := strings.Join(namespaces, ",")
119+
out, err := k.Health(ctx, nsParam, queryParams)
120+
if err != nil {
121+
return nil, err
122+
}
123+
return json.RawMessage([]byte(out)), nil
124+
}
125+
126+
// getMeshStatus wraps the MeshStatus call and returns raw JSON.
127+
func (k *Kiali) getMeshStatus(ctx context.Context) (json.RawMessage, error) {
128+
out, err := k.MeshStatus(ctx)
129+
if err != nil {
130+
return nil, err
131+
}
132+
return json.RawMessage([]byte(out)), nil
133+
}
134+
135+
// getNamespaces wraps the ListNamespaces call and returns raw JSON.
136+
func (k *Kiali) getNamespaces(ctx context.Context) (json.RawMessage, error) {
137+
out, err := k.ListNamespaces(ctx)
138+
if err != nil {
139+
return nil, err
140+
}
141+
return json.RawMessage([]byte(out)), nil
142+
}

pkg/kiali/graph.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,24 @@ import (
1010
// Graph calls the Kiali graph API using the provided Authorization header value.
1111
// `namespaces` may contain zero, one or many namespaces. If empty, the API may return an empty graph
1212
// or the server default, depending on Kiali configuration.
13-
func (k *Kiali) Graph(ctx context.Context, namespaces []string) (string, error) {
13+
func (k *Kiali) Graph(ctx context.Context, namespaces []string, queryParams map[string]string) (string, error) {
1414
u, err := url.Parse(GraphEndpoint)
1515
if err != nil {
1616
return "", err
1717
}
1818
q := u.Query()
1919
// Static graph parameters per requirements
20-
q.Set("duration", "60s")
21-
q.Set("graphType", "versionedApp")
20+
// Defaults with optional overrides via queryParams
21+
duration := "60s"
22+
graphType := "versionedApp"
23+
if v, ok := queryParams["rateInterval"]; ok && strings.TrimSpace(v) != "" {
24+
duration = strings.TrimSpace(v)
25+
}
26+
if v, ok := queryParams["graphType"]; ok && strings.TrimSpace(v) != "" {
27+
graphType = strings.TrimSpace(v)
28+
}
29+
q.Set("duration", duration)
30+
q.Set("graphType", graphType)
2231
q.Set("includeIdleEdges", "false")
2332
q.Set("injectServiceNodes", "true")
2433
q.Set("boxBy", "cluster,namespace,app")

0 commit comments

Comments
 (0)