MCPcopy
hub / github.com/modelcontextprotocol/registry / ValidateNPM

Function ValidateNPM

internal/validators/registries/npm.go:26–90  ·  view source on GitHub ↗

ValidateNPM validates that an NPM package contains the correct MCP server name

(ctx context.Context, pkg model.Package, serverName string)

Source from the content-addressed store, hash-verified

24
25// ValidateNPM validates that an NPM package contains the correct MCP server name
26func ValidateNPM(ctx context.Context, pkg model.Package, serverName string) error {
27 // Set default registry base URL if empty
28 if pkg.RegistryBaseURL == "" {
29 pkg.RegistryBaseURL = model.RegistryURLNPM
30 }
31
32 if pkg.Identifier == "" {
33 return ErrMissingIdentifierForNPM
34 }
35
36 // we need version to look up the package metadata
37 // not providing version will return all the versions
38 // and we won't be able to validate the mcpName field
39 // against the server name
40 if pkg.Version == "" {
41 return ErrMissingVersionForNPM
42 }
43
44 // Validate that MCPB-specific fields are not present
45 if pkg.FileSHA256 != "" {
46 return fmt.Errorf("NPM packages must not have 'fileSha256' field")
47 }
48
49 // Validate that the registry base URL matches NPM exactly
50 if pkg.RegistryBaseURL != model.RegistryURLNPM {
51 return fmt.Errorf("registry type and base URL do not match: '%s' is not valid for registry type '%s'. Expected: %s",
52 pkg.RegistryBaseURL, model.RegistryTypeNPM, model.RegistryURLNPM)
53 }
54
55 client := &http.Client{Timeout: 10 * time.Second}
56
57 requestURL := pkg.RegistryBaseURL + "/" + url.PathEscape(pkg.Identifier) + "/" + url.PathEscape(pkg.Version)
58 req, err := http.NewRequestWithContext(ctx, http.MethodGet, requestURL, nil)
59 if err != nil {
60 return fmt.Errorf("failed to create request: %w", err)
61 }
62
63 req.Header.Set("User-Agent", "MCP-Registry-Validator/1.0")
64 req.Header.Set("Accept", "application/json")
65
66 resp, err := client.Do(req)
67 if err != nil {
68 return fmt.Errorf("failed to fetch package metadata from NPM: %w", err)
69 }
70 defer resp.Body.Close()
71
72 if resp.StatusCode != http.StatusOK {
73 return fmt.Errorf("NPM package '%s' not found (status: %d)", pkg.Identifier, resp.StatusCode)
74 }
75
76 var npmResp NPMPackageResponse
77 if err := json.NewDecoder(resp.Body).Decode(&npmResp); err != nil {
78 return fmt.Errorf("failed to parse NPM package metadata: %w", err)
79 }
80
81 if npmResp.MCPName == "" {
82 return fmt.Errorf("NPM package '%s' is missing required 'mcpName' field. Add this to your package.json: \"mcpName\": \"%s\"", pkg.Identifier, serverName)
83 }

Callers 2

ValidatePackageFunction · 0.92

Calls 2

SetMethod · 0.80
CloseMethod · 0.65

Tested by 1

Used in the wild real call sites across dependent graphs

searching dependent graphs…