← 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
M internal/cli/mcp_sync.goM internal/openapi/parser.goM internal/openapi/parser_test.goM internal/pipeline/mcpsync/sync.goM internal/pipeline/mcpsync/sync_test.goM testdata/golden/expected/generate-golden-api/printing-press-golden/.printing-press.jsonM testdata/golden/expected/generate-golden-api/printing-press-golden/cmd/printing-press-golden-pp-mcp/main.goM testdata/golden/expected/generate-golden-api/printing-press-golden/manifest.jsonM testdata/golden/fixtures/golden-api.yaml
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, ®istry); 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 →