Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ Central registry that manages all available toolsets and their tools.
- `get_clusters_with_orchestrator_cve`: Find clusters where vulnerability is detected in orchestrator components

2. **Config Manager Toolset**: Manage cluster configurations
- `list_clusters`: List all managed clusters with pagination
- `list_secured_clusters`: List all managed clusters with pagination

### StackRox Client

Expand Down Expand Up @@ -234,7 +234,7 @@ All errors are converted to user-friendly messages with:

### Config Management Tools

**list_clusters**
**list_secured_clusters**
- List all clusters managed by StackRox
- Client-side pagination support
- Returns cluster metadata and status
Expand Down
4 changes: 2 additions & 2 deletions e2e-tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,12 @@ jq '[.[] | .callHistory.ToolCalls[]? | {name: .request.Params.name, arguments: .

| Test | Description | Tool |
|------|-------------|------|
| `list-clusters` | List all clusters | `list_clusters` | - |
| `list-clusters` | List all clusters | `list_secured_clusters` | - |
| `cve-detected-workloads` | CVE detected in deployments | `get_deployments_for_cve` |
| `cve-detected-clusters` | CVE detected in clusters | `get_clusters_with_orchestrator_cve` |
| `cve-nonexistent` | Handle non-existent CVE | `get_clusters_with_orchestrator_cve` |
| `cve-cluster-does-exist` | CVE with cluster filter | `get_clusters_with_orchestrator_cve` |
| `cve-cluster-does-not-exist` | CVE with non-existent cluster | `list_clusters` |
| `cve-cluster-does-not-exist` | CVE with non-existent cluster | `list_secured_clusters` |
| `cve-clusters-general` | General CVE query | `get_clusters_with_orchestrator_cve` |
| `cve-cluster-list` | CVE across clusters | `get_clusters_with_orchestrator_cve` |
| `cve-log4shell` | Well-known CVE (log4shell) | `get_deployments_for_cve` |
Expand Down
4 changes: 2 additions & 2 deletions e2e-tests/mcpchecker/eval.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ config:
assertions:
toolsUsed:
- server: stackrox-mcp
toolPattern: "list_clusters"
toolPattern: "list_secured_clusters"
minToolCalls: 1
maxToolCalls: 1

Expand Down Expand Up @@ -83,7 +83,7 @@ config:
assertions:
toolsUsed:
- server: stackrox-mcp
toolPattern: "get_clusters_with_orchestrator_cve|list_clusters"
toolPattern: "get_clusters_with_orchestrator_cve|list_secured_clusters"
minToolCalls: 1
maxToolCalls: 5

Expand Down
6 changes: 3 additions & 3 deletions integration/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func TestIntegration_ListTools(t *testing.T) {
}

assert.Contains(t, toolNames, "get_deployments_for_cve", "should have get_deployments_for_cve tool")
assert.Contains(t, toolNames, "list_clusters", "should have list_clusters tool")
assert.Contains(t, toolNames, "list_secured_clusters", "should have list_secured_clusters tool")
}

// TestIntegration_ToolCalls tests successful tool calls using table-driven tests.
Expand All @@ -50,8 +50,8 @@ func TestIntegration_ToolCalls(t *testing.T) {
args: map[string]any{"cveName": "CVE-9999-99999"},
expectedJSON: EmptyDeploymentsJSON,
},
"list_clusters": {
toolName: "list_clusters",
"list_secured_clusters": {
toolName: "list_secured_clusters",
args: map[string]any{},
expectedJSON: AllClustersFixture.ExpectedJSON,
},
Expand Down
21 changes: 10 additions & 11 deletions internal/toolsets/config/tools.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const (
defaultLimit = 0
)

// listClustersInput defines the input parameters for list_clusters tool.
// listClustersInput defines the input parameters for list_secured_clusters tool.
type listClustersInput struct {
Offset int `json:"offset,omitempty"`
Limit int `json:"limit,omitempty"`
Expand All @@ -34,24 +34,24 @@ type ClusterInfo struct {
Type string `json:"type"`
}

// listClustersOutput defines the output structure for list_clusters tool.
// listClustersOutput defines the output structure for list_secured_clusters tool.
type listClustersOutput struct {
Clusters []ClusterInfo `json:"clusters"`
TotalCount int `json:"totalCount"`
Offset int `json:"offset"`
Limit int `json:"limit"`
}

// listClustersTool implements the list_clusters tool.
// listClustersTool implements the list_secured_clusters tool.
type listClustersTool struct {
name string
client *client.Client
}

// NewListClustersTool creates a new list_clusters tool.
// NewListClustersTool creates a new list_secured_clusters tool.
func NewListClustersTool(c *client.Client) toolsets.Tool {
return &listClustersTool{
name: "list_clusters",
name: "list_secured_clusters",
client: c,
}
}
Expand All @@ -70,17 +70,16 @@ func (t *listClustersTool) GetName() string {
func (t *listClustersTool) GetTool() *mcp.Tool {
return &mcp.Tool{
Name: t.name,
Description: "List all clusters secured by " + config.GetProductDisplayName() +
" with their IDs, names, and types. Use this tool to get cluster information," +
" or when you need to map a cluster name to its cluster ID for use in other tools.",
Description: "List all clusters secured by " + config.GetProductDisplayName() + "." +
" Returns cluster IDs, names, and types. Use this tool to discover available clusters.",
InputSchema: listClustersInputSchema(),
}
}

func listClustersInputSchema() *jsonschema.Schema {
schema, err := jsonschema.For[listClustersInput](nil)
if err != nil {
logging.Fatal("Could not get jsonschema for list_clusters input", err)
logging.Fatal("Could not get jsonschema for list_secured_clusters input", err)

return nil
}
Expand All @@ -98,7 +97,7 @@ func listClustersInputSchema() *jsonschema.Schema {
return schema
}

// RegisterWith registers the list_clusters tool handler with the MCP server.
// RegisterWith registers the list_secured_clusters tool handler with the MCP server.
func (t *listClustersTool) RegisterWith(server *mcp.Server) {
mcp.AddTool(server, t.GetTool(), t.handle)
}
Expand Down Expand Up @@ -137,7 +136,7 @@ func (t *listClustersTool) getClusters(ctx context.Context, req *mcp.CallToolReq
return allClusters, nil
}

// handle is the handler for list_clusters tool.
// handle is the handler for list_secured_clusters tool.
func (t *listClustersTool) handle(
ctx context.Context,
req *mcp.CallToolRequest,
Expand Down
6 changes: 3 additions & 3 deletions internal/toolsets/config/tools_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ func TestNewListClustersTool(t *testing.T) {
tool := NewListClustersTool(&client.Client{})

require.NotNil(t, tool)
assert.Equal(t, "list_clusters", tool.GetName())
assert.Equal(t, "list_secured_clusters", tool.GetName())
}

func TestListClustersTool_IsReadOnly(t *testing.T) {
tool := NewListClustersTool(&client.Client{})

assert.True(t, tool.IsReadOnly(), "list_clusters should be read-only")
assert.True(t, tool.IsReadOnly(), "list_secured_clusters should be read-only")
}

func TestListClustersTool_GetTool(t *testing.T) {
Expand All @@ -39,7 +39,7 @@ func TestListClustersTool_GetTool(t *testing.T) {
mcpTool := tool.GetTool()

require.NotNil(t, mcpTool)
assert.Equal(t, "list_clusters", mcpTool.Name)
assert.Equal(t, "list_secured_clusters", mcpTool.Name)
assert.NotEmpty(t, mcpTool.Description)
require.NotNil(t, mcpTool.InputSchema, "InputSchema should be defined")
}
Expand Down
4 changes: 2 additions & 2 deletions internal/toolsets/config/toolset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ func TestToolset_IsEnabled_True(t *testing.T) {

tools := toolset.GetTools()
require.NotEmpty(t, tools, "Should return tools when enabled")
require.Len(t, tools, 1, "Should have list_clusters tool")
assert.Equal(t, "list_clusters", tools[0].GetName())
require.Len(t, tools, 1, "Should have list_secured_clusters tool")
assert.Equal(t, "list_secured_clusters", tools[0].GetName())
}

func TestToolset_IsEnabled_False(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion smoke/smoke_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func TestSmoke_RealCluster(t *testing.T) {

client := createSmokeTestClient(t, endpoint, apiToken)

result := testutil.CallToolAndGetResult(t, client, "list_clusters", map[string]any{})
result := testutil.CallToolAndGetResult(t, client, "list_secured_clusters", map[string]any{})
responseText := testutil.GetTextContent(t, result)

var data struct {
Expand Down
Loading