Skip to content

Commit

Permalink
added: generic get and list tools for any k8s resource
Browse files Browse the repository at this point in the history
  • Loading branch information
strowk committed Jan 9, 2025
1 parent 8a084c2 commit 2abf514
Show file tree
Hide file tree
Showing 25 changed files with 722 additions and 507 deletions.
48 changes: 24 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,11 @@
- 🤖 tool: list-k8s-contexts
- 🤖 tool: list-k8s-namespaces in a given context
- 🤖 tool: list-k8s-nodes in a given context
- 🤖 tool: list-k8s-pods in a given context and namespace
- 🤖 tool: list-k8s-resources in a given context and namespace for specified resource kind
- includes custom mappings for resources like pods, services, deployments
- 🤖 tool: get-k8s-resource in a given context and namespace for specified name and resource kind
- 🤖 tool: list-k8s-events in a given context and namespace
- 🤖 tool: list-k8s-services in a given context and namespace
- 🤖 tool: get-k8s-pod-logs in a given context and namespace for specified pod
- 🤖 tool: list-k8s-deployments in a given context and namespace
- 🤖 tool: get-k8s-deployment in a given context and namespace for specified deployment
- 💬 prompt: list-k8s-namespaces in a given context
- 💬 prompt: list-k8s-pods in current context and with given namespace

Expand Down Expand Up @@ -67,15 +66,14 @@ Following chat with Claude Desktop demonstrates how it looks when selected parti

</details>


To use this MCP server with Claude Desktop you would firstly need to install it.

You have several options for installation:

| | <a href="#using-smithery">Smithery</a> | <a href="#using-mcp-get">mcp-get</a> | <a href="#prebuilt-from-npm">Pre-built NPM</a> | <a href="#from-github-releases">Pre-built in Github</a> | <a href="#building-from-source">From sources</a> |
|---|---|---|---|---|---|
| Claude Setup | Auto | Auto | Manual | Manual | Manual |
| Prerequisite | Node.js | Node.js | Node.js | None | Golang |
| | <a href="#using-smithery">Smithery</a> | <a href="#using-mcp-get">mcp-get</a> | <a href="#prebuilt-from-npm">Pre-built NPM</a> | <a href="#from-github-releases">Pre-built in Github</a> | <a href="#building-from-source">From sources</a> |
| ------------ | -------------------------------------- | ------------------------------------ | ---------------------------------------------- | ------------------------------------------------------- | ------------------------------------------------ |
| Claude Setup | Auto | Auto | Manual | Manual | Manual |
| Prerequisite | Node.js | Node.js | Node.js | None | Golang |

### Using Smithery

Expand Down Expand Up @@ -107,12 +105,12 @@ Then check version by running `mcp-k8s --version` and if this printed installed

```json
{
"mcpServers": {
"mcp_k8s": {
"command": "mcp-k8s",
"args": []
}
"mcpServers": {
"mcp_k8s": {
"command": "mcp-k8s",
"args": []
}
}
}
```

Expand All @@ -124,12 +122,12 @@ Unpack the archive, which would contain binary named `mcp-k8s-go`, put that bina

```json
{
"mcpServers": {
"mcp_k8s": {
"command": "mcp-k8s-go",
"args": []
}
"mcpServers": {
"mcp_k8s": {
"command": "mcp-k8s-go",
"args": []
}
}
}
```

Expand All @@ -146,18 +144,19 @@ go install github.com/strowk/mcp-k8s-go

```json
{
"mcpServers": {
"mcp_k8s_go": {
"command": "mcp-k8s-go",
"args": []
}
"mcpServers": {
"mcp_k8s_go": {
"command": "mcp-k8s-go",
"args": []
}
}
}
```

### Using from Claude Desktop

Now you should be able to run Claude Desktop and:

- see K8S contexts available to attach to conversation as a resource
- ask Claude to list contexts
- ask Claude to list pods in a given context and namespace
Expand All @@ -167,6 +166,7 @@ Now you should be able to run Claude Desktop and:
### Environment Variables

The following environment variables are used by the MCP server:

- `KUBECONFIG`: Path to your Kubernetes configuration file (optional, defaults to ~/.kube/config)

## Contributing
Expand Down
30 changes: 30 additions & 0 deletions internal/k8s/apps/v1/deployment/get_deployment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package deployment

import (
"context"

"github.com/strowk/foxy-contexts/pkg/mcp"
"github.com/strowk/mcp-k8s-go/internal/content"
"github.com/strowk/mcp-k8s-go/internal/utils"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
)

func GetDeployment(clientset kubernetes.Interface, namespace string, name string) *mcp.CallToolResult {
deployment, err := clientset.AppsV1().Deployments(namespace).Get(context.Background(), name, metav1.GetOptions{})
if err != nil {
return utils.ErrResponse(err)
}
utils.SanitizeObjectMeta(&deployment.ObjectMeta)

c, err := content.NewJsonContent(deployment)
if err != nil {
return utils.ErrResponse(err)
}
return &mcp.CallToolResult{
Meta: map[string]interface{}{},
Content: []interface{}{c},
IsError: utils.Ptr(false),
}
}
3 changes: 2 additions & 1 deletion internal/k8s/apps/v1/deployment/get_deployment_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ in:
"id": 2,
"params":
{
"name": "get-k8s-deployment",
"name": "get-k8s-resource",
"arguments":
{
"context": "k3d-mcp-k8s-integration-test",
"namespace": "test-deployment",
"kind": "deployment",
"name": "nginx-deployment",
},
},
Expand Down
73 changes: 0 additions & 73 deletions internal/k8s/apps/v1/deployment/get_deployment_tool.go

This file was deleted.

84 changes: 84 additions & 0 deletions internal/k8s/apps/v1/deployment/list_deployments.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package deployment

import (
"context"
"sort"
"time"

"github.com/strowk/foxy-contexts/pkg/mcp"
"github.com/strowk/mcp-k8s-go/internal/content"
"github.com/strowk/mcp-k8s-go/internal/utils"

appsv1 "k8s.io/api/apps/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
)

// DeploymentInList provides a structured representation of Deployment information
type DeploymentInList struct {
Name string `json:"name"`
Namespace string `json:"namespace"`
Age string `json:"age"`
DesiredReplicas int `json:"desired_replicas"`
ReadyReplicas int `json:"ready_replicas"`
UpdatedReplicas int `json:"updated_replicas"`
AvailableReplicas int `json:"available_replicas"`
CreatedAt string `json:"created_at"`
}

func ListDeployments(clientset kubernetes.Interface, namespace string) *mcp.CallToolResult {
var deployments *appsv1.DeploymentList
var err error
if namespace == "" {
// List Deployments from all namespaces
deployments, err = clientset.AppsV1().Deployments(metav1.NamespaceAll).List(context.Background(), metav1.ListOptions{})
} else {
// List Deployments from specific namespace
deployments, err = clientset.AppsV1().Deployments(namespace).List(context.Background(), metav1.ListOptions{})
}

if err != nil {
return utils.ErrResponse(err)
}

sort.Slice(deployments.Items, func(i, j int) bool {
// Sort by namespace, then by name
if deployments.Items[i].Namespace == deployments.Items[j].Namespace {
return deployments.Items[i].Name < deployments.Items[j].Name
}
return deployments.Items[i].Namespace < deployments.Items[j].Namespace
})

var contents []interface{} = make([]interface{}, len(deployments.Items))
for i, deployment := range deployments.Items {
// Calculate age
age := time.Since(deployment.CreationTimestamp.Time)

// Extract deployment status information
desiredReplicas := int(*(deployment.Spec.Replicas))
readyReplicas := deployment.Status.ReadyReplicas
updatedReplicas := deployment.Status.UpdatedReplicas
availableReplicas := deployment.Status.AvailableReplicas

content, err := content.NewJsonContent(DeploymentInList{
Name: deployment.Name,
Namespace: deployment.Namespace,
Age: utils.FormatAge(age),
DesiredReplicas: desiredReplicas,
ReadyReplicas: int(readyReplicas),
UpdatedReplicas: int(updatedReplicas),
AvailableReplicas: int(availableReplicas),
CreatedAt: deployment.CreationTimestamp.Format(time.RFC3339),
})
if err != nil {
return utils.ErrResponse(err)
}
contents[i] = content
}

return &mcp.CallToolResult{
Meta: map[string]interface{}{},
Content: contents,
IsError: utils.Ptr(false),
}
}
3 changes: 2 additions & 1 deletion internal/k8s/apps/v1/deployment/list_deployments_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ in:
"id": 2,
"params":
{
"name": "list-k8s-deployments",
"name": "list-k8s-resources",
"arguments":
{
"context": "k3d-mcp-k8s-integration-test",
"namespace": "test-deployment",
"kind": "deployment",
},
},
}
Expand Down
Loading

0 comments on commit 2abf514

Please sign in to comment.