Skip to content

Commit 005f0b9

Browse files
authored
mcp: use Skills and rename tools (#55)
1. Define a skill in `.cursor/skills` to validate the MCP tools. MCP Tools should respect the following naming scheme: - Use snake_case with service prefix - Format: {service}_{action}_{resource} - Example: slack_send_message, github_create_issue 2. Run the Cursor agent to validate existing the MCP tools 3. Update the tools to respect the naming scheme, based on the suggestions from the Cursor agent 4. Run the tests to verify that the tools are working as expected Assisted-by: Cursor Signed-off-by: Xavier Coulon <xcoulon@redhat.com>
1 parent 9cbd683 commit 005f0b9

5 files changed

Lines changed: 40 additions & 22 deletions

File tree

.cursor/skills/validating/SKILL.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
---
2+
name: validate
3+
description: validate the MCP tools
4+
---
5+
6+
# Usage
7+
8+
Use this skill to validate that existing MCP tools conform to the best-practices
9+
10+
# Checklist
11+
12+
## Tool naming
13+
14+
Verify that the tools defined in the `internal/argocd` package respect the following naming scheme:
15+
16+
- Use snake_case with service prefix
17+
- Format: {service}_{action}_{resource}
18+
- Example: slack_send_message, github_create_issue

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ Argo CD MCP is a Model Context Protocol Server to converse with Argo CD from a U
77
- Prompts:
88
- `argocd-unhealthy-application-resources`: list the Unhealthy (`Degraded` and `Progressing`) Applications in Argo CD
99
- Tools:
10-
- `unhealthyApplications`: list the Unhealthy (`Degraded` and `Progressing`) Applications in Argo CD
11-
- `unhealthyApplicationResources`: list unhealthy resources of a given Argo CD Application
10+
- `argocd_list_unhealthy_applications`: list the unhealthy (`Degraded` and `Progressing`) Applications in Argo CD
11+
- `argocd_list_unhealthy_application_resources`: list unhealthy resources of a given Argo CD Application
1212

1313
Example:
1414

internal/argocd/unhealthy_application_resources.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ func UnhealthyApplicationResourcesPromptHandle(logger *slog.Logger, cl *Client)
5757
}
5858

5959
var UnhealthyApplicationResourcesTool = &mcp.Tool{
60-
Name: "unhealthyApplicationResources",
60+
Name: "argocd_list_unhealthy_application_resources",
6161
Description: "list unhealthy resources of a given Argo CD Application",
6262
InputSchema: &jsonschema.Schema{
6363
Type: "object",
@@ -108,7 +108,7 @@ func listUnhealthyApplicationResources(ctx context.Context, logger *slog.Logger,
108108
if err != nil {
109109
logger.Error("failed to convert unhealthy resources to text", "error", err.Error())
110110
}
111-
logger.DebugContext(ctx, "returned 'tools/call' response", "tool", "unhealthyApplicationResources", "app", name, "result", string(unhealthyResourcesStr))
111+
logger.DebugContext(ctx, "returned 'tools/call' response", "tool", "argocd_list_unhealthy_application_resources", "app", name, "result", string(unhealthyResourcesStr))
112112
}
113113
return UnhealthyResources{
114114
Resources: unhealthyResources,

internal/argocd/unhealthy_applications.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import (
1313
)
1414

1515
var UnhealthyApplicationsTool = &mcp.Tool{
16-
Name: "unhealthyApplications",
16+
Name: "argocd_list_unhealthy_applications",
1717
Description: "list the unhealthy ('degraded' and 'progressing') Applications in Argo CD",
1818
InputSchema: UnhealthyApplicationsInputSchema,
1919
OutputSchema: UnhealthyApplicationsOutputSchema,
@@ -84,7 +84,7 @@ func listUnhealthyApplications(ctx context.Context, logger *slog.Logger, cl *Cli
8484
if err != nil {
8585
logger.Error("failed to convert unhealthy resources to text", "error", err.Error())
8686
}
87-
logger.DebugContext(ctx, "returned 'tools/call' response", "tool", "unhealthyApplications", "result", string(unhealthyAppsStr))
87+
logger.DebugContext(ctx, "returned 'tools/call' response", "tool", "argocd_list_unhealthy_applications", "result", string(unhealthyAppsStr))
8888
}
8989
return unhealthyApps, nil
9090
}

test/e2e/server_test.go

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import (
2525

2626
// TestServer verifies basic MCP functionality with both stdio and http transports.
2727
// Both transports run in stateful mode (ListChanged enabled) and test:
28-
// - Tool calls (unhealthyApplications, unhealthyApplicationResources)
28+
// - Tool calls (argocd_list_unhealthy_applications, argocd_list_unhealthy_application_resources)
2929
// - Error handling (argocd-error, unreachable scenarios)
3030
// - Metrics collection (for http transport)
3131
// - Session reuse across multiple tool calls
@@ -57,22 +57,22 @@ func TestStatefulServer(t *testing.T) {
5757
session := td.init(t)
5858
defer session.Close()
5959

60-
t.Run("call/unhealthyApplications/ok", func(t *testing.T) {
60+
t.Run("call/argocd_list_unhealthy_applications/ok", func(t *testing.T) {
6161
// get the metrics before the call
6262
var mcpCallsTotalMetricBefore int64
6363
var mcpCallsDurationSecondsInfBucketBefore int64
6464
if td.name == "http" {
6565
mcpCallsTotalMetricBefore, mcpCallsDurationSecondsInfBucketBefore = getMetrics(t, "http://localhost:50081", map[string]string{
6666
"server": "argocd-mcp-server",
6767
"method": "tools/call",
68-
"name": "unhealthyApplications",
68+
"name": "argocd_list_unhealthy_applications",
6969
"success": "true",
7070
})
7171
}
7272

7373
// when
7474
result, err := session.CallTool(context.Background(), &mcp.CallToolParams{
75-
Name: "unhealthyApplications",
75+
Name: "argocd_list_unhealthy_applications",
7676
})
7777

7878
// then
@@ -102,7 +102,7 @@ func TestStatefulServer(t *testing.T) {
102102
mcpCallsTotalMetricAfter, mcpCallsDurationSecondsInfBucketAfter := getMetrics(t, "http://localhost:50081", map[string]string{
103103
"server": "argocd-mcp-server",
104104
"method": "tools/call",
105-
"name": "unhealthyApplications",
105+
"name": "argocd_list_unhealthy_applications",
106106
"success": "true",
107107
})
108108
assert.Equal(t, mcpCallsTotalMetricBefore+1, mcpCallsTotalMetricAfter)
@@ -111,21 +111,21 @@ func TestStatefulServer(t *testing.T) {
111111

112112
})
113113

114-
t.Run("call/unhealthyApplicationResources/ok", func(t *testing.T) {
114+
t.Run("call/argocd_list_unhealthy_application_resources/ok", func(t *testing.T) {
115115
var mcpCallsTotalMetricBefore int64
116116
var mcpCallsDurationSecondsInfBucketBefore int64
117117
if td.name == "http" {
118118
mcpCallsTotalMetricBefore, mcpCallsDurationSecondsInfBucketBefore = getMetrics(t, "http://localhost:50081", map[string]string{
119119
"server": "argocd-mcp-server",
120120
"method": "tools/call",
121-
"name": "unhealthyApplicationResources",
121+
"name": "argocd_list_unhealthy_application_resources",
122122
"success": "true",
123123
})
124124
}
125125

126126
// when
127127
result, err := session.CallTool(context.Background(), &mcp.CallToolParams{
128-
Name: "unhealthyApplicationResources",
128+
Name: "argocd_list_unhealthy_application_resources",
129129
Arguments: map[string]any{
130130
"name": "example",
131131
},
@@ -186,29 +186,29 @@ func TestStatefulServer(t *testing.T) {
186186
mcpCallsTotalMetricAfter, mcpCallsDurationSecondsInfBucketAfter := getMetrics(t, "http://localhost:50081", map[string]string{
187187
"server": "argocd-mcp-server",
188188
"method": "tools/call",
189-
"name": "unhealthyApplicationResources",
189+
"name": "argocd_list_unhealthy_application_resources",
190190
"success": "true",
191191
})
192192
assert.Equal(t, mcpCallsTotalMetricBefore+1, mcpCallsTotalMetricAfter)
193193
assert.Equal(t, mcpCallsDurationSecondsInfBucketBefore+1, mcpCallsDurationSecondsInfBucketAfter)
194194
}
195195
})
196196

197-
t.Run("call/unhealthyApplicationResources/argocd-error", func(t *testing.T) {
197+
t.Run("call/argocd_list_unhealthy_application_resources/argocd-error", func(t *testing.T) {
198198
var mcpCallsTotalMetricBefore int64
199199
var mcpCallsDurationSecondsInfBucketBefore int64
200200
if td.name == "http" {
201201
mcpCallsTotalMetricBefore, mcpCallsDurationSecondsInfBucketBefore = getMetrics(t, "http://localhost:50081", map[string]string{
202202
"server": "argocd-mcp-server",
203203
"method": "tools/call",
204-
"name": "unhealthyApplicationResources",
204+
"name": "argocd_list_unhealthy_application_resources",
205205
"success": "false",
206206
})
207207
}
208208

209209
// when
210210
result, err := session.CallTool(context.Background(), &mcp.CallToolParams{
211-
Name: "unhealthyApplicationResources",
211+
Name: "argocd_list_unhealthy_application_resources",
212212
Arguments: map[string]any{
213213
"name": "example-error",
214214
},
@@ -222,7 +222,7 @@ func TestStatefulServer(t *testing.T) {
222222
mcpCallsTotalMetricAfter, mcpCallsDurationSecondsInfBucketAfter := getMetrics(t, "http://localhost:50081", map[string]string{
223223
"server": "argocd-mcp-server",
224224
"method": "tools/call",
225-
"name": "unhealthyApplicationResources",
225+
"name": "argocd_list_unhealthy_application_resources",
226226
"success": "false",
227227
})
228228
assert.Equal(t, mcpCallsTotalMetricBefore+1, mcpCallsTotalMetricAfter)
@@ -262,10 +262,10 @@ func TestStatefulServer(t *testing.T) {
262262
// given
263263
session := td.init(t)
264264
defer session.Close()
265-
t.Run("call/unhealthyApplications/argocd-unreachable", func(t *testing.T) {
265+
t.Run("call/argocd_list_unhealthy_applications/argocd-unreachable", func(t *testing.T) {
266266
// when
267267
result, err := session.CallTool(context.Background(), &mcp.CallToolParams{
268-
Name: "unhealthyApplications",
268+
Name: "argocd_list_unhealthy_applications",
269269
})
270270

271271
// then
@@ -306,7 +306,7 @@ func TestStatelessServer(t *testing.T) {
306306

307307
// Step 4: Verify tools work correctly with content validation
308308
result, callErr := session.CallTool(ctx, &mcp.CallToolParams{
309-
Name: "unhealthyApplications",
309+
Name: "argocd_list_unhealthy_applications",
310310
})
311311
require.NoError(t, callErr)
312312
require.False(t, result.IsError, "tool call should succeed")

0 commit comments

Comments
 (0)