feat: v6 polish — per-publisher namespacing + auto-create project #71
Reference in New Issue
Block a user
Delete Branch "feat/v6-polish"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Two small org-grade quality-of-life fixes for first-five-minutes
friction. Both close items the original v1-v3 docs deferred.
Stage 1 (
c346b93) — per-publisher namespacingmcplocal can now append a suffix to its published Llm/Agent names so
two users running the same config template don't collide on the
cluster-wide unique-name constraint. Pair with an explicit
poolName(v4) and the rows still load-balance as one pool.
Resolves to:
vllm-local-qwen3(alice's mcplocal) → wire namevllm-local-qwen3-alicevllm-local-qwen3(bob's mcplocal) → wire namevllm-local-qwen3-bobBoth rows are addressable; agents pinned to either dispatch through
the v4 pool. Inbound infer/wake task lookups match by wire name on
the registrar side, so the local registry stays keyed by its
original (non-suffixed) name.
Stage 2 (
ee18c51) — auto-create project for virtual agentsregisterVirtualAgentsnow creates the named project if missing(with the publishing user as owner) instead of 404'ing. Idempotent:
second publisher landing on the same project name reuses the
existing row. Closes the v3-out-of-scope item.
Test plan
publisherfield, no auto-create) keepworking byte-identically — empty suffix is the no-op code path,
and ensureByName only kicks in when the project would have
404'd anyway.
Note on stacking with v5
This branch is from main (= v4 final). v5 (PR #70) is still open;
when it merges I'll rebase v6 onto it before deploy. Both v6 stages
touch paths v5 didn't change, so the rebase should be mechanical.
Two mcplocals sharing the same config template (`vllm-local-qwen3`) no longer collide on mcpd's cluster-wide unique-name constraint. Each publisher can append a suffix derived from hostname (or any other stable per-host identifier) so the wire-side names become distinct (`vllm-local-qwen3-alice`, `vllm-local-qwen3-bob`). Pair with an explicit `poolName` (v4) and the rows still appear as one logical pool — agents pinned to any member load-balance across both. Config (`~/.mcpctl/config.json`): { "publisher": { "suffix": "auto" } // → os.hostname() sanitized // or { "suffix": "alice" } for explicit override } Or via env: `MCPCTL_PUBLISHER_SUFFIX=alice` (operations override). Resolution order: env var → config.publisher.suffix → empty (legacy behavior, no mangling). Sanitization lowercases, replaces non-`[a-z0-9-]` runs with `-`, strips leading/trailing dashes — the result must satisfy mcpd's name validation, otherwise the register POST would 422. Wire shape: RegistrarPublishedProvider gets an optional `publishName` field. When set, the wire payload's `name` is `publishName` (suffixed); when not, today's `provider.name`. Inbound infer/wake task lookups match `publishName ?? provider.name` so the local registry stays addressable by its original name — SSE frames carrying the suffixed wire name still find their provider. Agents are forwarded with their own suffixed name AND a `llmName` rewritten through the same per-local→wire map so the agent rows pin to the suffixed Llm wire name (otherwise registerVirtualAgents would 404). Tests: 8 new tests covering applyPublisherSuffix (empty, normal, length limit, exact-100) and loadPublisherSuffix (env override, absent, sanitization, dash stripping). Existing registrar tests untouched — no suffix means no behavior change.