Repository: modelcontextprotocol/registry
File: cmd/publisher/commands/publish.go (Go)

Code before:
	response, err := publishToRegistry(registryURL, serverData, token)
	if err != nil {
		return fmt.Errorf("publish failed: %w", err)
	}

	_, _ = fmt.Fprintln(os.Stdout, "✓ Successfully published")
	if serverID := id(response); serverID != "" {
		_, _ = fmt.Fprintf(os.Stdout, "✓ Server Id %s", serverID)
	}

	return nil
}

func id(response apiv0.ServerJSON) string {
	if response.Meta != nil && response.Meta.IOModelContextProtocolRegistry != nil {
		return response.Meta.IOModelContextProtocolRegistry.ID
	}
	return ""
}

func publishToRegistry(registryURL string, serverData []byte, token string) (apiv0.ServerJSON, error) {
	// Parse the server JSON data
	var serverJSON apiv0.ServerJSON
	err := json.Unmarshal(serverData, &serverJSON)
	if err != nil {
		return serverJSON, fmt.Errorf("error parsing server.json file: %w", err)
	}

	// Convert to JSON
	jsonData, err := json.Marshal(serverJSON)
	if err != nil {
		return serverJSON, fmt.Errorf("error serializing request: %w", err)
	}

	// Ensure URL ends with the publish endpoint
	if !strings.HasSuffix(registryURL, "/") {
		registryURL += "/"
	}
	publishURL := registryURL + "v0/publish"

	// Create and send request
	req, err := http.NewRequestWithContext(context.Background(), http.MethodPost, publishURL, bytes.NewBuffer(jsonData))
	if err != nil {
		return serverJSON, fmt.Errorf("error creating request: %w", err)
	}
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", "Bearer "+token)

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {

Review comment (suggestion):
I think we probably shouldn't return the serverJSON if it didn't actually get published - probably better to return nil in these cases and just return the error to avoid confusion/surprise.

Code after:
	response, err := publishToRegistry(registryURL, serverData, token)
	if err != nil {
		return fmt.Errorf("publish failed: %w", err)
	}

	_, _ = fmt.Fprintln(os.Stdout, "✓ Successfully published")
	if serverID := response.GetID(); serverID != "" {
		_, _ = fmt.Fprintf(os.Stdout, "✓ Server Id %s", serverID)
	}

	return nil
}

func publishToRegistry(registryURL string, serverData []byte, token string) (*apiv0.ServerJSON, error) {
	// Parse the server JSON data
	var serverJSON apiv0.ServerJSON
	err := json.Unmarshal(serverData, &serverJSON)
	if err != nil {
		return nil, fmt.Errorf("error parsing server.json file: %w", err)
	}

	// Convert to JSON
	jsonData, err := json.Marshal(serverJSON)
	if err != nil {
		return nil, fmt.Errorf("error serializing request: %w", err)
	}

	// Ensure URL ends with the publish endpoint
	if !strings.HasSuffix(registryURL, "/") {
		registryURL += "/"
	}
	publishURL := registryURL + "v0/publish"

	// Create and send request
	req, err := http.NewRequestWithContext(context.Background(), http.MethodPost, publishURL, bytes.NewBuffer(jsonData))
	if err != nil {
		return nil, fmt.Errorf("error creating request: %w", err)
	}
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", "Bearer "+token)

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("error sending request: %w", err)
	}
	defer resp.Body.Close()

	// Read response
	body, err := io.ReadAll(resp.Body)
	if err != nil {