[object Object]

← back to Cli Printing Press

feat(cli): mcp-sync reads display_name from public library registry.json fallback (#391)

64f67981e8979e53f09880438665d7c81697ad63 · 2026-04-29 11:24:54 -0700 · Trevin Chow

* feat(cli): mcp-sync reads display_name from public library registry.json as fallback

When spec.yaml lacks display_name and manifest.json has no usable
value (browser-sniffed CLIs that never had a manifest, or one already
corrupted to the slug form), mcp-sync now consults the public
library's registry.json. The fallback chain becomes:

    spec.yaml.display_name
    → existing manifest.json
    → public library registry.json `api` field
    → naming.HumanName(slug)

The registry path is read from $PRINTING_PRESS_LIBRARY_PUBLIC; when
that's unset, the file is unreadable, the schema_version doesn't
match what this binary knows, the slug isn't in the registry, or the
api field is unusable, the chain falls through unchanged. The binary
doesn't search the filesystem — that belongs in skill prose.

The api field is overloaded across registry entries: most carry a
short brand name ("Cal.com", "Company GOAT"), but a minority carry a
full descriptive sentence (recipe-goat ships ~200 chars). 40 chars
fits every observed real brand name with margin. Whitespace is
trimmed before comparison so " Wikipedia " yields "Wikipedia". The
schema_version check fails closed: a future schema bump degrades
silently to HumanName rather than mis-extracting from a different
shape.

mcp-sync's command help now documents the env var so users
discovering brand-name regressions can see where the fallback comes
from.

Tests cover: env unset, file missing, malformed JSON, slug not in
registry, api equal to slug, api too long (recipe-goat case), api
empty/whitespace, mismatched schema_version, missing schema_version,
happy path. Plus an end-to-end TestSyncFallsThroughToRegistryDisplayName
that runs full Sync against a generated CLI with no usable
display_name and asserts the registry value lands in
.printing-press.json.

Closes #386

* feat(cli): OpenAPI parser reads x-display-name extension; lock contract via golden

OpenAPI specs had no way to carry an explicit brand name — the parser
left parsed.DisplayName empty for OpenAPI input, so downstream
consumers always fell through to naming.HumanName(slug). For multi-
word brands the deformed result ("Cal Com" instead of "Cal.com",
"Hubspot" instead of "HubSpot") clobbered manifest.json on every
mcp-sync regen.

Add x-display-name extension reading parallel to the existing
x-website / x-api-name handlers. The OpenAPI spec author can now
declare the canonical brand explicitly; whitespace is trimmed before
use.

Lock the spec → manifest → MCP server identity chain via golden
fixture: golden-api.yaml gains x-display-name: "Printing Press
Studio", a value distinctively different from the HumanName form
("Printing Press Golden") so the fixture proves the extension
overrode the fallback rather than coinciding with it. The expected
.printing-press.json, manifest.json, and cmd/.../main.go all reflect
the new value.

Three new parser tests cover: extension present, whitespace trimmed,
absent leaves DisplayName empty.

Files touched

Diff

commit 64f67981e8979e53f09880438665d7c81697ad63
Author: Trevin Chow <trevin@trevinchow.com>
Date:   Wed Apr 29 11:24:54 2026 -0700

    feat(cli): mcp-sync reads display_name from public library registry.json fallback (#391)
    
    * feat(cli): mcp-sync reads display_name from public library registry.json as fallback
    
    When spec.yaml lacks display_name and manifest.json has no usable
    value (browser-sniffed CLIs that never had a manifest, or one already
    corrupted to the slug form), mcp-sync now consults the public
    library's registry.json. The fallback chain becomes:
    
        spec.yaml.display_name
        → existing manifest.json
        → public library registry.json `api` field
        → naming.HumanName(slug)
    
    The registry path is read from $PRINTING_PRESS_LIBRARY_PUBLIC; when
    that's unset, the file is unreadable, the schema_version doesn't
    match what this binary knows, the slug isn't in the registry, or the
    api field is unusable, the chain falls through unchanged. The binary
    doesn't search the filesystem — that belongs in skill prose.
    
    The api field is overloaded across registry entries: most carry a
    short brand name ("Cal.com", "Company GOAT"), but a minority carry a
    full descriptive sentence (recipe-goat ships ~200 chars). 40 chars
    fits every observed real brand name with margin. Whitespace is
    trimmed before comparison so " Wikipedia " yields "Wikipedia". The
    schema_version check fails closed: a future schema bump degrades
    silently to HumanName rather than mis-extracting from a different
    shape.
    
    mcp-sync's command help now documents the env var so users
    discovering brand-name regressions can see where the fallback comes
    from.
    
    Tests cover: env unset, file missing, malformed JSON, slug not in
    registry, api equal to slug, api too long (recipe-goat case), api
    empty/whitespace, mismatched schema_version, missing schema_version,
    happy path. Plus an end-to-end TestSyncFallsThroughToRegistryDisplayName
    that runs full Sync against a generated CLI with no usable
    display_name and asserts the registry value lands in
    .printing-press.json.
    
    Closes #386
    
    * feat(cli): OpenAPI parser reads x-display-name extension; lock contract via golden
    
    OpenAPI specs had no way to carry an explicit brand name — the parser
    left parsed.DisplayName empty for OpenAPI input, so downstream
    consumers always fell through to naming.HumanName(slug). For multi-
    word brands the deformed result ("Cal Com" instead of "Cal.com",
    "Hubspot" instead of "HubSpot") clobbered manifest.json on every
    mcp-sync regen.
    
    Add x-display-name extension reading parallel to the existing
    x-website / x-api-name handlers. The OpenAPI spec author can now
    declare the canonical brand explicitly; whitespace is trimmed before
    use.
    
    Lock the spec → manifest → MCP server identity chain via golden
    fixture: golden-api.yaml gains x-display-name: "Printing Press
    Studio", a value distinctively different from the HumanName form
    ("Printing Press Golden") so the fixture proves the extension
    overrode the fallback rather than coinciding with it. The expected
    .printing-press.json, manifest.json, and cmd/.../main.go all reflect
    the new value.
    
    Three new parser tests cover: extension present, whitespace trimmed,
    absent leaves DisplayName empty.
---
 internal/cli/mcp_sync.go                           |  11 +-
 internal/openapi/parser.go                         |  15 ++
 internal/openapi/parser_test.go                    |  65 +++++++
 internal/pipeline/mcpsync/sync.go                  |  67 +++++++
 internal/pipeline/mcpsync/sync_test.go             | 196 +++++++++++++++++++++
 .../printing-press-golden/.printing-press.json     |   4 +-
 .../cmd/printing-press-golden-pp-mcp/main.go       |   2 +-
 .../printing-press-golden/manifest.json            |   6 +-
 testdata/golden/fixtures/golden-api.yaml           |   6 +
 9 files changed, 365 insertions(+), 7 deletions(-)

diff --git a/internal/cli/mcp_sync.go b/internal/cli/mcp_sync.go
index 5e0d4c56..2cbbf59f 100644
--- a/internal/cli/mcp_sync.go
+++ b/internal/cli/mcp_sync.go
@@ -14,7 +14,16 @@ func newMCPSyncCmd() *cobra.Command {
 	cmd := &cobra.Command{
 		Use:   "mcp-sync <cli-dir>",
 		Short: "Migrate a printed CLI to the runtime Cobra-tree MCP surface",
-		Args:  cobra.ExactArgs(1),
+		Long: `Regenerates the MCP surface (tools.go + tools-manifest.json + manifest.json)
+from the spec, current generator templates, and any mcp-descriptions.json
+overrides. Refreshes spec-derived fields in .printing-press.json so the
+chain spec.yaml → .printing-press.json → manifest.json stays consistent.
+
+Honors PRINTING_PRESS_LIBRARY_PUBLIC: when set to a public-library
+clone, mcp-sync consults that clone's registry.json as a final fallback
+for display_name when the spec and existing manifest.json don't carry
+a usable brand name.`,
+		Args: cobra.ExactArgs(1),
 		RunE: func(cmd *cobra.Command, args []string) error {
 			cliDir, err := filepath.Abs(args[0])
 			if err != nil {
diff --git a/internal/openapi/parser.go b/internal/openapi/parser.go
index 93ad0be9..21c15680 100644
--- a/internal/openapi/parser.go
+++ b/internal/openapi/parser.go
@@ -180,6 +180,20 @@ func parse(data []byte, lenient bool) (*spec.APISpec, error) {
 		version = strings.TrimSpace(doc.Info.Version)
 	}
 
+	// Extract x-display-name extension. Carries the human-readable
+	// brand name when it differs from the slug-derived form ("Cal.com"
+	// vs "Cal Com"). Without this, the OpenAPI parser leaves
+	// DisplayName empty and downstream consumers fall back to
+	// naming.HumanName(slug), which deforms multi-word brands.
+	var displayName string
+	if doc.Info != nil && doc.Info.Extensions != nil {
+		if raw, ok := doc.Info.Extensions["x-display-name"]; ok {
+			if s, ok := raw.(string); ok {
+				displayName = strings.TrimSpace(s)
+			}
+		}
+	}
+
 	// Extract website URL from spec metadata (contact URL, externalDocs, or x-website)
 	var websiteURL string
 	if doc.Info != nil {
@@ -262,6 +276,7 @@ func parse(data []byte, lenient bool) (*spec.APISpec, error) {
 
 	result := &spec.APISpec{
 		Name:        name,
+		DisplayName: displayName,
 		Description: description,
 		Version:     version,
 		BaseURL:     baseURL,
diff --git a/internal/openapi/parser_test.go b/internal/openapi/parser_test.go
index cb146387..e9babbcd 100644
--- a/internal/openapi/parser_test.go
+++ b/internal/openapi/parser_test.go
@@ -130,6 +130,71 @@ components:
 	assert.NotContains(t, fieldNames, "_internal")
 }
 
+func TestParseReadsXDisplayName(t *testing.T) {
+	spec := []byte(`
+openapi: "3.0.0"
+info:
+  title: Cal.com API v2
+  x-display-name: "Cal.com"
+  version: "1.0"
+servers:
+  - url: https://api.example.com
+paths:
+  /items:
+    get:
+      operationId: listItems
+      responses:
+        "200":
+          description: OK
+`)
+	parsed, err := Parse(spec)
+	require.NoError(t, err)
+	assert.Equal(t, "Cal.com", parsed.DisplayName)
+}
+
+func TestParseTrimsWhitespaceFromXDisplayName(t *testing.T) {
+	spec := []byte(`
+openapi: "3.0.0"
+info:
+  title: Test API
+  x-display-name: "  Brand Name  "
+  version: "1.0"
+servers:
+  - url: https://api.example.com
+paths:
+  /items:
+    get:
+      operationId: listItems
+      responses:
+        "200":
+          description: OK
+`)
+	parsed, err := Parse(spec)
+	require.NoError(t, err)
+	assert.Equal(t, "Brand Name", parsed.DisplayName)
+}
+
+func TestParseLeavesDisplayNameEmptyWhenAbsent(t *testing.T) {
+	spec := []byte(`
+openapi: "3.0.0"
+info:
+  title: Test API
+  version: "1.0"
+servers:
+  - url: https://api.example.com
+paths:
+  /items:
+    get:
+      operationId: listItems
+      responses:
+        "200":
+          description: OK
+`)
+	parsed, err := Parse(spec)
+	require.NoError(t, err)
+	assert.Equal(t, "", parsed.DisplayName)
+}
+
 func TestIsOpenAPI(t *testing.T) {
 	t.Parallel()
 
diff --git a/internal/pipeline/mcpsync/sync.go b/internal/pipeline/mcpsync/sync.go
index c72e232e..0d782e33 100644
--- a/internal/pipeline/mcpsync/sync.go
+++ b/internal/pipeline/mcpsync/sync.go
@@ -88,9 +88,17 @@ func Sync(cliDir string, opts Options) (Result, error) {
 	// regeneration drops "ESPN" back to the title-cased slug ("Espn"),
 	// regressing both the MCP server identity (NewMCPServer first arg)
 	// and the bundled manifest's display_name field.
+	//
+	// Falls through to the public library's registry.json when
+	// manifest.json has no usable value (browser-sniffed CLIs that
+	// never had a manifest, or a manifest already corrupted to the
+	// slug form). The registry is the catalog source of truth for
+	// brand names.
 	if parsed.DisplayName == "" {
 		if existing := readExistingManifestDisplayName(cliDir); existing != "" {
 			parsed.DisplayName = existing
+		} else if registryName := readRegistryDisplayName(parsed.Name); registryName != "" {
+			parsed.DisplayName = registryName
 		}
 	}
 	// Apply hand-authored MCP description overrides before generating
@@ -456,6 +464,65 @@ func readExistingManifestDisplayName(cliDir string) string {
 	return existing.DisplayName
 }
 
+// registryDisplayNameMaxLen caps the length of registry.json's `api`
+// field when used as a display_name. The field is overloaded — most
+// entries hold a short brand name ("Cal.com", "Company GOAT") but a
+// minority hold a full descriptive sentence (recipe-goat ships ~200
+// chars). 40 fits every observed real brand name with margin.
+const registryDisplayNameMaxLen = 40
+
+// registrySchemaVersion is the registry.json schema this reader knows
+// how to parse. A future schema bump (renamed fields, restructured
+// entries) would silently mis-extract from a different shape; failing
+// closed when the version doesn't match means a stale binary degrades
+// to the HumanName fallback rather than emitting wrong values.
+const registrySchemaVersion = 1
+
+// readRegistryDisplayName looks up an API's brand name in the public
+// library's registry.json. Returns "" when the env var
+// PRINTING_PRESS_LIBRARY_PUBLIC is unset, the file is unreadable, the
+// schema_version doesn't match, the slug isn't in the registry, or
+// the api field is unusable (empty, equal to the slug, or too long
+// to plausibly be a display_name).
+//
+// Last fallback in the display_name preservation chain: spec.yaml →
+// manifest.json → registry.json → naming.HumanName. Filesystem
+// scanning belongs in skill prose; the binary trusts the env var.
+func readRegistryDisplayName(slug string) string {
+	libDir := os.Getenv("PRINTING_PRESS_LIBRARY_PUBLIC")
+	if libDir == "" {
+		return ""
+	}
+	data, err := os.ReadFile(filepath.Join(libDir, "registry.json"))
+	if err != nil {
+		return ""
+	}
+	var registry struct {
+		SchemaVersion int `json:"schema_version"`
+		Entries       []struct {
+			Name string `json:"name"`
+			API  string `json:"api"`
+		} `json:"entries"`
+	}
+	if err := json.Unmarshal(data, &registry); err != nil {
+		return ""
+	}
+	if registry.SchemaVersion != registrySchemaVersion {
+		return ""
+	}
+	for _, e := range registry.Entries {
+		if e.Name != slug {
+			continue
+		}
+		api := strings.TrimSpace(e.API)
+		if api == "" || api == slug || len(api) > registryDisplayNameMaxLen {
+			return ""
+		}
+		return api
+	}
+	return ""
+}
+
 // validateSpecNameMatchesDir refuses to migrate when spec.yaml.name
 // diverges from the CLI directory's basename. This catches the
 // weather-goat / open-meteo class of drift where an old emboss/rename
diff --git a/internal/pipeline/mcpsync/sync_test.go b/internal/pipeline/mcpsync/sync_test.go
index 5160ebab..debbe88f 100644
--- a/internal/pipeline/mcpsync/sync_test.go
+++ b/internal/pipeline/mcpsync/sync_test.go
@@ -723,3 +723,199 @@ func Execute() error {
 	require.Error(t, err)
 	assert.Contains(t, err.Error(), "does not match the generated Execute shape")
 }
+
+func TestReadRegistryDisplayName(t *testing.T) {
+	writeRegistry := func(t *testing.T, libDir string, entries any) {
+		t.Helper()
+		body := map[string]any{"schema_version": 1, "entries": entries}
+		data, err := json.Marshal(body)
+		require.NoError(t, err)
+		require.NoError(t, os.WriteFile(filepath.Join(libDir, "registry.json"), data, 0o644))
+	}
+
+	t.Run("env unset returns empty", func(t *testing.T) {
+		t.Setenv("PRINTING_PRESS_LIBRARY_PUBLIC", "")
+		assert.Equal(t, "", readRegistryDisplayName("cal-com"))
+	})
+
+	t.Run("env set but file missing returns empty", func(t *testing.T) {
+		t.Setenv("PRINTING_PRESS_LIBRARY_PUBLIC", t.TempDir())
+		assert.Equal(t, "", readRegistryDisplayName("cal-com"))
+	})
+
+	t.Run("malformed JSON returns empty", func(t *testing.T) {
+		libDir := t.TempDir()
+		require.NoError(t, os.WriteFile(filepath.Join(libDir, "registry.json"), []byte("not json"), 0o644))
+		t.Setenv("PRINTING_PRESS_LIBRARY_PUBLIC", libDir)
+		assert.Equal(t, "", readRegistryDisplayName("cal-com"))
+	})
+
+	t.Run("slug not in registry returns empty", func(t *testing.T) {
+		libDir := t.TempDir()
+		writeRegistry(t, libDir, []map[string]string{
+			{"name": "wikipedia", "api": "Wikipedia"},
+		})
+		t.Setenv("PRINTING_PRESS_LIBRARY_PUBLIC", libDir)
+		assert.Equal(t, "", readRegistryDisplayName("cal-com"))
+	})
+
+	t.Run("api equal to slug returns empty", func(t *testing.T) {
+		libDir := t.TempDir()
+		writeRegistry(t, libDir, []map[string]string{
+			{"name": "agent-capture", "api": "agent-capture"},
+		})
+		t.Setenv("PRINTING_PRESS_LIBRARY_PUBLIC", libDir)
+		assert.Equal(t, "", readRegistryDisplayName("agent-capture"))
+	})
+
+	t.Run("api too long returns empty", func(t *testing.T) {
+		libDir := t.TempDir()
+		writeRegistry(t, libDir, []map[string]string{
+			{"name": "recipe-goat", "api": "Cross-site recipe aggregator (37 trusted sites: King Arthur, Serious Eats, Smitten Kitchen, AllRecipes, Food52, BBC Food, EatingWell, Food Network, and 29 more) + USDA FoodData Central"},
+		})
+		t.Setenv("PRINTING_PRESS_LIBRARY_PUBLIC", libDir)
+		assert.Equal(t, "", readRegistryDisplayName("recipe-goat"))
+	})
+
+	t.Run("usable api returns it", func(t *testing.T) {
+		libDir := t.TempDir()
+		writeRegistry(t, libDir, []map[string]string{
+			{"name": "wikipedia", "api": "Wikipedia"},
+			{"name": "cal-com", "api": "Cal.com"},
+			{"name": "company-goat", "api": "Company GOAT"},
+		})
+		t.Setenv("PRINTING_PRESS_LIBRARY_PUBLIC", libDir)
+		assert.Equal(t, "Cal.com", readRegistryDisplayName("cal-com"))
+		assert.Equal(t, "Wikipedia", readRegistryDisplayName("wikipedia"))
+		assert.Equal(t, "Company GOAT", readRegistryDisplayName("company-goat"))
+	})
+
+	t.Run("whitespace-only api returns empty", func(t *testing.T) {
+		libDir := t.TempDir()
+		writeRegistry(t, libDir, []map[string]string{
+			{"name": "wikipedia", "api": "  \t\n"},
+		})
+		t.Setenv("PRINTING_PRESS_LIBRARY_PUBLIC", libDir)
+		assert.Equal(t, "", readRegistryDisplayName("wikipedia"))
+	})
+
+	t.Run("api whitespace is trimmed", func(t *testing.T) {
+		libDir := t.TempDir()
+		writeRegistry(t, libDir, []map[string]string{
+			{"name": "wikipedia", "api": "  Wikipedia  "},
+		})
+		t.Setenv("PRINTING_PRESS_LIBRARY_PUBLIC", libDir)
+		assert.Equal(t, "Wikipedia", readRegistryDisplayName("wikipedia"))
+	})
+
+	t.Run("unknown schema_version returns empty", func(t *testing.T) {
+		libDir := t.TempDir()
+		body := map[string]any{
+			"schema_version": 2, // future schema, this binary doesn't understand
+			"entries": []map[string]string{
+				{"name": "cal-com", "api": "Cal.com"},
+			},
+		}
+		data, err := json.Marshal(body)
+		require.NoError(t, err)
+		require.NoError(t, os.WriteFile(filepath.Join(libDir, "registry.json"), data, 0o644))
+		t.Setenv("PRINTING_PRESS_LIBRARY_PUBLIC", libDir)
+		assert.Equal(t, "", readRegistryDisplayName("cal-com"))
+	})
+
+	t.Run("missing schema_version returns empty", func(t *testing.T) {
+		libDir := t.TempDir()
+		body := map[string]any{
+			// schema_version omitted; defaults to 0, which doesn't match.
+			"entries": []map[string]string{
+				{"name": "cal-com", "api": "Cal.com"},
+			},
+		}
+		data, err := json.Marshal(body)
+		require.NoError(t, err)
+		require.NoError(t, os.WriteFile(filepath.Join(libDir, "registry.json"), data, 0o644))
+		t.Setenv("PRINTING_PRESS_LIBRARY_PUBLIC", libDir)
+		assert.Equal(t, "", readRegistryDisplayName("cal-com"))
+	})
+}
+
+// TestSyncFallsThroughToRegistryDisplayName exercises the new branch
+// in Sync's preservation block end-to-end: spec.yaml without
+// display_name, manifest.json with no usable value, registry.json
+// with a brand name. Asserts the registry value lands in
+// .printing-press.json so subsequent WriteMCPBManifest carries it
+// into the published manifest.
+func TestSyncFallsThroughToRegistryDisplayName(t *testing.T) {
+	apiSpec := &spec.APISpec{
+		Name:    "testbrand",
+		Version: "0.1.0",
+		BaseURL: "https://api.example.com",
+		Auth: spec.AuthConfig{
+			Type:    "api_key",
+			Header:  "Authorization",
+			Format:  "Bearer {token}",
+			EnvVars: []string{"TESTBRAND_TOKEN"},
+		},
+		Config: spec.ConfigSpec{
+			Format: "toml",
+			Path:   "~/.config/testbrand-pp-cli/config.toml",
+		},
+		Resources: map[string]spec.Resource{
+			"items": {
+				Description: "Manage items",
+				Endpoints: map[string]spec.Endpoint{
+					"list": {Method: "GET", Path: "/items", Description: "List items"},
+				},
+			},
+		},
+	}
+	cliDir := filepath.Join(t.TempDir(), "testbrand")
+	gen := generator.New(apiSpec, cliDir)
+	require.NoError(t, gen.Generate())
+	require.NoError(t, pipeline.WriteManifestForGenerate(pipeline.GenerateManifestParams{
+		APIName:   apiSpec.Name,
+		OutputDir: cliDir,
+		Spec:      apiSpec,
+	}))
+	specData, err := yaml.Marshal(apiSpec)
+	require.NoError(t, err)
+	require.NoError(t, os.WriteFile(filepath.Join(cliDir, "spec.yaml"), specData, 0o644))
+
+	// Force manifest.json's display_name to empty so the manifest-side
+	// preservation step rejects it and falls through to the registry.
+	// Without this, the generator's HumanName-derived "Testbrand" would
+	// be preserved and the registry path never gets exercised.
+	manifestPath := filepath.Join(cliDir, pipeline.MCPBManifestFilename)
+	mcpbData, err := os.ReadFile(manifestPath)
+	require.NoError(t, err)
+	var mcpb pipeline.MCPBManifest
+	require.NoError(t, json.Unmarshal(mcpbData, &mcpb))
+	mcpb.DisplayName = ""
+	modifiedData, err := json.Marshal(mcpb)
+	require.NoError(t, err)
+	require.NoError(t, os.WriteFile(manifestPath, modifiedData, 0o644))
+
+	// Set up the public library with a registry.json the fallback can read.
+	libDir := t.TempDir()
+	registry := map[string]any{
+		"schema_version": 1,
+		"entries": []map[string]string{
+			{"name": "testbrand", "api": "TestBrand!"},
+		},
+	}
+	registryData, err := json.Marshal(registry)
+	require.NoError(t, err)
+	require.NoError(t, os.WriteFile(filepath.Join(libDir, "registry.json"), registryData, 0o644))
+	t.Setenv("PRINTING_PRESS_LIBRARY_PUBLIC", libDir)
+
+	_, err = Sync(cliDir, Options{})
+	require.NoError(t, err)
+
+	// .printing-press.json must reflect the registry-derived value;
+	// the broken alternative is silently regressing to "Testbrand".
+	provData, err := os.ReadFile(filepath.Join(cliDir, pipeline.CLIManifestFilename))
+	require.NoError(t, err)
+	var prov pipeline.CLIManifest
+	require.NoError(t, json.Unmarshal(provData, &prov))
+	assert.Equal(t, "TestBrand!", prov.DisplayName)
+}
diff --git a/testdata/golden/expected/generate-golden-api/printing-press-golden/.printing-press.json b/testdata/golden/expected/generate-golden-api/printing-press-golden/.printing-press.json
index e41458e5..f74d7e2c 100644
--- a/testdata/golden/expected/generate-golden-api/printing-press-golden/.printing-press.json
+++ b/testdata/golden/expected/generate-golden-api/printing-press-golden/.printing-press.json
@@ -6,7 +6,7 @@
   ],
   "auth_type": "api_key",
   "cli_name": "printing-press-golden-pp-cli",
-  "display_name": "Printing Press Golden",
+  "display_name": "Printing Press Studio",
   "generated_at": "<GENERATED_AT>",
   "mcp_binary": "printing-press-golden-pp-mcp",
   "mcp_public_tool_count": 1,
@@ -14,7 +14,7 @@
   "mcp_tool_count": 7,
   "printing_press_version": "<PRINTING_PRESS_VERSION>",
   "schema_version": 1,
-  "spec_checksum": "sha256:eef12554186abf8e871a9a5bb166d23555d219de4c9b0513c1d482ecfbe34e0f",
+  "spec_checksum": "sha256:d9a3383e991f59bed6be8fe19357ef81dc60e68854268fbcc6e6bbb092a4c2be",
   "spec_format": "openapi3",
   "spec_path": "testdata/golden/fixtures/golden-api.yaml",
   "spec_url": "file://testdata/golden/fixtures/golden-api.yaml"
diff --git a/testdata/golden/expected/generate-golden-api/printing-press-golden/cmd/printing-press-golden-pp-mcp/main.go b/testdata/golden/expected/generate-golden-api/printing-press-golden/cmd/printing-press-golden-pp-mcp/main.go
index d54751b5..272d8b45 100644
--- a/testdata/golden/expected/generate-golden-api/printing-press-golden/cmd/printing-press-golden-pp-mcp/main.go
+++ b/testdata/golden/expected/generate-golden-api/printing-press-golden/cmd/printing-press-golden-pp-mcp/main.go
@@ -13,7 +13,7 @@ import (
 
 func main() {
 	s := server.NewMCPServer(
-		"Printing Press Golden",
+		"Printing Press Studio",
 		"1.0.0",
 		server.WithToolCapabilities(false),
 	)
diff --git a/testdata/golden/expected/generate-golden-api/printing-press-golden/manifest.json b/testdata/golden/expected/generate-golden-api/printing-press-golden/manifest.json
index 962b0f42..aace3978 100644
--- a/testdata/golden/expected/generate-golden-api/printing-press-golden/manifest.json
+++ b/testdata/golden/expected/generate-golden-api/printing-press-golden/manifest.json
@@ -10,8 +10,8 @@
       "win32"
     ]
   },
-  "description": "Printing Press Golden API surface as MCP tools.",
-  "display_name": "Printing Press Golden",
+  "description": "Printing Press Studio API surface as MCP tools.",
+  "display_name": "Printing Press Studio",
   "license": "Apache-2.0",
   "manifest_version": "0.3",
   "name": "printing-press-golden-pp-mcp",
@@ -28,7 +28,7 @@
   },
   "user_config": {
     "printing_press_golden_api_key_auth": {
-      "description": "Sets PRINTING_PRESS_GOLDEN_API_KEY_AUTH for the Printing Press Golden MCP server.",
+      "description": "Sets PRINTING_PRESS_GOLDEN_API_KEY_AUTH for the Printing Press Studio MCP server.",
       "required": true,
       "sensitive": true,
       "title": "PRINTING_PRESS_GOLDEN_API_KEY_AUTH",
diff --git a/testdata/golden/fixtures/golden-api.yaml b/testdata/golden/fixtures/golden-api.yaml
index da3caa95..cb1ed9dd 100644
--- a/testdata/golden/fixtures/golden-api.yaml
+++ b/testdata/golden/fixtures/golden-api.yaml
@@ -1,6 +1,12 @@
 openapi: "3.0.3"
 info:
   title: Printing Press Golden API
+  # Distinctively non-slug-derived ("Printing Press Studio" vs HumanName
+  # of slug "printing-press-golden" -> "Printing Press Golden"). Locks
+  # in that x-display-name overrides the slug-derived fallback all the
+  # way through to .printing-press.json, manifest.json, and the MCP
+  # server identity in cmd/.../main.go.
+  x-display-name: "Printing Press Studio"
   version: "2026.04"
   description: Purpose-built fixture for golden generation coverage.
 servers:

← 401bda54 fix(cli,skills): manifest display_name preservation + diverg  ·  back to Cli Printing Press  ·  fix(cli): tools-manifest.json classifies reclassified path p cdd9153b →