Tencent/WeKnora · error
MCP service is required
Error message
MCP service is required
What it means
ValidateServiceOutboundURLs enforces the SSRF policy on every URL an MCP service may contact. This error is returned when the function is called with a nil *types.MCPService pointer. It is a guard against validating a nonexistent service record.
Source
Thrown at internal/mcp/security.go:17
package mcp
import (
"fmt"
"strings"
"github.com/Tencent/WeKnora/internal/types"
secutils "github.com/Tencent/WeKnora/internal/utils"
)
// ValidateServiceOutboundURLs validates every URL that the MCP transport or
// OAuth discovery flow may contact. It is intentionally called both at
// persistence boundaries and immediately before client construction so stale
// or imported rows cannot bypass the current SSRF policy.
func ValidateServiceOutboundURLs(service *types.MCPService) error {
if service == nil {
return fmt.Errorf("MCP service is required")
}
if service.URL != nil {
serviceURL := strings.TrimSpace(*service.URL)
if serviceURL != "" {
if err := secutils.ValidateURLForSSRF(serviceURL); err != nil {
return fmt.Errorf("MCP service URL failed SSRF validation: %w", err)
}
}
}
if service.AuthConfig != nil {
metadataURL := strings.TrimSpace(service.AuthConfig.AuthServerMetadataURL)
if metadataURL != "" {
if err := secutils.ValidateURLForSSRF(metadataURL); err != nil {
return fmt.Errorf("MCP OAuth metadata URL failed SSRF validation: %w", err)
}
}
}
return nilView on GitHub (pinned to 988cbb0330)
Solutions
- Ensure the MCPService is constructed and non-nil before calling validation (check decode/unmarshal errors from the request body).
- Return a 400 Bad Request to clients that submit an empty service payload instead of reaching validation with nil.
- If a lookup can miss, check for not-found before validation and return your domain not-found error.
- In tests, pass a minimal valid MCPService{} rather than nil unless testing the guard itself.
Example fix
// before
var svc *types.MCPService
_ = json.NewDecoder(r.Body).Decode(&svc)
if err := ValidateServiceOutboundURLs(svc); err != nil { ... }
// after
svc := &types.MCPService{}
if err := json.NewDecoder(r.Body).Decode(svc); err != nil {
return nil, fmt.Errorf("invalid MCP service payload: %w", err)
}
if err := ValidateServiceOutboundURLs(svc); err != nil { ... } Defensive patterns
Strategy: validation
Validate before calling
if service == nil {
return fmt.Errorf("MCP service is required")
} Type guard
func serviceProvided(s *types.MCPService) bool { return s != nil } Try / catch
if err := ValidateServiceOutboundURLs(service); err != nil {
if strings.Contains(err.Error(), "is required") {
return httpBadRequest("MCP service payload missing")
}
return err
} Prevention
- Always decode request bodies into a non-nil value and surface decode errors early.
- Check repository lookups for not-found before validation.
- Add a nil check at handler entry for all pointer-shaped request payloads.
- In tests, construct a minimal &types.MCPService{} instead of passing nil unintentionally.
When it happens
Trigger: Passing a nil *types.MCPService to ValidateServiceOutboundURLs — e.g. a lookup returned no row but the code proceeded, or a JSON decode produced a nil pointer.
Common situations: CreateMCPService/UpdateMCPService handlers invoked with a missing/unparsed request body; imported or migrated rows failing to materialize into a service struct; test harness passing nil to check guard behavior.
Related errors
- MCP client config and service are required
- MCP service URL failed SSRF validation: %w
- mcp service not found
- tool_name is required
- %s failed SSRF validation: %w
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/43da25ffc2dc3e45.
Report an issue: GitHub.