Skip to content

Commit 0794aae

Browse files
fix: use correct field names for missing secrets in doctor output
Update doctor command to use field names from contracts.MissingSecretInfo: - secret_name instead of name - used_by (array) instead of server Also fix tests to match the actual backend JSON structure.
1 parent a2a50b4 commit 0794aae

2 files changed

Lines changed: 77 additions & 20 deletions

File tree

cmd/mcpproxy/doctor_cmd.go

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -253,16 +253,22 @@ func outputDiagnostics(diag map[string]interface{}, info map[string]interface{})
253253
fmt.Println("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
254254
for _, secretItem := range missingSecrets {
255255
if secretMap, ok := secretItem.(map[string]interface{}); ok {
256-
name := getStringField(secretMap, "name")
257-
server := getStringField(secretMap, "server")
258-
reference := getStringField(secretMap, "reference")
259-
260-
fmt.Printf("\n • %s\n", name)
261-
if server != "" {
262-
fmt.Printf(" Server: %s\n", server)
263-
}
264-
if reference != "" {
265-
fmt.Printf(" Reference: %s\n", reference)
256+
// Use correct field names from contracts.MissingSecretInfo
257+
secretName := getStringField(secretMap, "secret_name")
258+
usedBy := getArrayField(secretMap, "used_by")
259+
260+
fmt.Printf("\n • %s\n", secretName)
261+
if len(usedBy) > 0 {
262+
fmt.Printf(" Used by: ")
263+
for i, server := range usedBy {
264+
if serverStr, ok := server.(string); ok {
265+
if i > 0 {
266+
fmt.Printf(", ")
267+
}
268+
fmt.Printf("%s", serverStr)
269+
}
270+
}
271+
fmt.Println()
266272
}
267273
}
268274
}

cmd/mcpproxy/doctor_cmd_test.go

Lines changed: 61 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,17 @@ func TestOutputDiagnostics_PrettyFormat_WithUpstreamErrors(t *testing.T) {
147147

148148
func TestOutputDiagnostics_PrettyFormat_WithOAuthRequired(t *testing.T) {
149149
diag := map[string]interface{}{
150-
"total_issues": 2,
151-
"oauth_required": []interface{}{"sentry-server", "github-server"},
150+
"total_issues": 2,
151+
"oauth_required": []interface{}{
152+
map[string]interface{}{
153+
"server_name": "sentry-server",
154+
"message": "Authentication required",
155+
},
156+
map[string]interface{}{
157+
"server_name": "github-server",
158+
"message": "",
159+
},
160+
},
152161
}
153162

154163
// Capture stdout
@@ -191,9 +200,8 @@ func TestOutputDiagnostics_PrettyFormat_WithMissingSecrets(t *testing.T) {
191200
"total_issues": 1,
192201
"missing_secrets": []interface{}{
193202
map[string]interface{}{
194-
"name": "API_KEY",
195-
"server": "weather-api",
196-
"reference": "${WEATHER_API_KEY}",
203+
"secret_name": "API_KEY",
204+
"used_by": []interface{}{"weather-api"},
197205
},
198206
},
199207
}
@@ -226,9 +234,6 @@ func TestOutputDiagnostics_PrettyFormat_WithMissingSecrets(t *testing.T) {
226234
if !strings.Contains(output, "weather-api") {
227235
t.Error("Missing server name")
228236
}
229-
if !strings.Contains(output, "${WEATHER_API_KEY}") {
230-
t.Error("Missing secret reference")
231-
}
232237
}
233238

234239
func TestOutputDiagnostics_PrettyFormat_WithRuntimeWarnings(t *testing.T) {
@@ -606,8 +611,8 @@ func TestOutputDiagnostics_SecretWithoutOptionalFields(t *testing.T) {
606611
"total_issues": 1,
607612
"missing_secrets": []interface{}{
608613
map[string]interface{}{
609-
"name": "API_KEY",
610-
// server and reference are optional
614+
"secret_name": "API_KEY",
615+
// used_by is optional
611616
},
612617
},
613618
}
@@ -635,3 +640,49 @@ func TestOutputDiagnostics_SecretWithoutOptionalFields(t *testing.T) {
635640
t.Error("Should display secret name even without optional fields")
636641
}
637642
}
643+
644+
// TestOutputDiagnostics_MissingSecretsRealJSON tests that the doctor command
645+
// correctly parses the actual JSON field names produced by the backend.
646+
// The MissingSecretInfo struct uses json:"secret_name" and json:"used_by",
647+
// NOT "name", "server", "reference".
648+
func TestOutputDiagnostics_MissingSecretsRealJSON(t *testing.T) {
649+
// This is the ACTUAL JSON structure produced by the backend
650+
// (see internal/contracts/types.go MissingSecretInfo struct)
651+
diag := map[string]interface{}{
652+
"total_issues": 1,
653+
"missing_secrets": []interface{}{
654+
map[string]interface{}{
655+
"secret_name": "GITHUB_TOKEN", // NOT "name"
656+
"used_by": []interface{}{"github-mcp"}, // NOT "server" (and it's an array)
657+
},
658+
},
659+
}
660+
661+
// Capture stdout
662+
oldStdout := os.Stdout
663+
r, w, _ := os.Pipe()
664+
os.Stdout = w
665+
defer func() { os.Stdout = oldStdout }()
666+
667+
doctorOutput = "pretty"
668+
err := outputDiagnostics(diag, nil)
669+
670+
w.Close()
671+
var buf bytes.Buffer
672+
buf.ReadFrom(r)
673+
output := buf.String()
674+
675+
if err != nil {
676+
t.Errorf("outputDiagnostics() returned error: %v", err)
677+
}
678+
679+
// Verify the secret name is displayed
680+
if !strings.Contains(output, "GITHUB_TOKEN") {
681+
t.Errorf("Should display secret name 'GITHUB_TOKEN' from secret_name field.\nGot output:\n%s", output)
682+
}
683+
684+
// Verify the server name is displayed
685+
if !strings.Contains(output, "github-mcp") {
686+
t.Errorf("Should display server 'github-mcp' from used_by field.\nGot output:\n%s", output)
687+
}
688+
}

0 commit comments

Comments
 (0)