You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Reduce server.New's body to the thin wrapper Serve(ctx, New(deriveCoreConfig(cfg, …)), deriveServerConfig(cfg, healthMon)), keeping
the existing 7-param signature byte-for-byte unchanged. This is the moment the
god-object server.New (anti-pattern #3) is dismantled and the single live path
becomes the New/Serve split — so it is also where the A1-deferred cleanup lands:
build the health monitor at the composition root (A2), then delete the now-dead
authz/annotation HTTP blocks and retire the discovery middleware/seam + its s.core == nil guard that Phase 2 left in place behind guards. Both //nolint:gocyclo directives
are removed (the complexity is gone, not suppressed). This is the highest-integration-risk
PR in the epic: until now the behavioral-parity suite exercised the legacy path; here server.New is rerouted through Serve for real, so the full parity suite is the gate.
Context
This is the final code change of Phase 3 (RFC THV-0076). #5444 introduced deriveCoreConfig/deriveServerConfig, which split the in-memory server.Config
into the core Config and transport ServerConfig (and threaded the built health
monitor). This task wires those derivers into server.New so its body delegates entirely
to New + Serve. Per architecture.md "server.New compatibility wrapper" (14-17, 43-47,
368, 480-482, 501), the 7-param signature and observable MCP behavior stay stable
throughout — the only in-repo caller (cli/serve.go:421) and the external brood-box
embedder must require no changes.
Why the A1 cleanup lands here. Phase 2 deliberately did not delete the
authz/annotation middleware (#5441) or the discovery middleware (#5442) from the
shared (*Server).Handler, because server.New still used the legacy chain and deleting
shared middleware would have opened an authz/aggregation regression window. Instead, Phase
2 made those layers inert on the Serve path (authz/annotation via a nil AuthzMiddleware; discovery via a s.core == nil guard). Once this task routes server.New through Serve, the legacy path is gone — every request flows through a Serve-built *Server (core present, AuthzMiddleware nil) — so those layers are now dead on all paths and can be safely deleted, completing the "shrink the middleware
chain" goal (anti-patterns #1/#4).
The AuthzMiddleware field stays.cli/serve.go (serve.go:~374) still assigns Config.AuthzMiddleware, and the "cli/serve.go unchanged" constraint forbids editing that
assignment. So the field is kept as a vestigial input; only the HTTP blocks that
read it are deleted, and deriveServerConfig already omits it so the Serve path never
applies it. The core admission seam enforces authz from the Authz config instead.
Health monitor (A2). Because the wrapper is Serve(ctx, New(deriveCoreConfig(cfg)), deriveServerConfig(cfg)), New is evaluated before Serve. The wrapper therefore builds
the *health.Monitorat the composition root (mirroring the old server.go:436-450
construction) and threads it both ways: as a health.StatusProvider into deriveCoreConfig
(so the core can filterHealthyBackends) and as the built *health.Monitor into deriveServerConfig (so Serve owns its Start/Stop lifecycle, #5443).
Because the body is fully reimplemented behind a stable surface, the full behavioral-parity
suite is the acceptance gate (research.md / architecture.md "Behavioral parity /
integration", 468-473).
Split note: this PR likely exceeds the 400 LOC / 10 file limit because it both
reroutes server.Newand removes a swath of now-dead middleware. Recommended split:
TASK-302a — build the monitor at the root + reduce server.New's body to Serve(ctx, New(deriveCoreConfig(...)), deriveServerConfig(..., healthMon)) + remove the
two //nolint:gocyclo. After this, the legacy path is gone (everything routes through Serve); the dead authz/annotation/discovery blocks remain but are unreachable.
TASK-302b — delete the now-dead authz block (606-609), annotation-enrichment block
(611-617) + AnnotationEnrichmentMiddleware (keep convertAnnotations, reused by the
core seam), the discovery middleware + handleSubsequentRequest + WithDiscoveredCapabilities
context seam, and the s.core == nil discovery guard. Pure dead-code removal; compiles and
passes parity on its own.
Both keep the AuthzMiddleware field and cli/serve.go unchanged. Use the /split-pr skill.
Acceptance Criteria
server.New body is Serve(ctx, New(deriveCoreConfig(cfg, …)), deriveServerConfig(cfg, healthMon)); the transport/core wiring no longer lives inline in server.New.
The 7-param New(ctx, cfg, rt, backendClient, discoveryMgr, backendRegistry, workflowDefs) (*Server, error) signature is byte-for-byte unchanged.
Health monitor (A2): the wrapper builds the *health.Monitor at the composition root (nil when HealthMonitorConfig is nil), injects its StatusProvider into New via deriveCoreConfig, and passes the same *health.Monitor into Serve via deriveServerConfig. The core filters; Serve lifecycles (P2.5 Move AS runner, status reporter, optimizer, health monitor under Serve #5443).
A1 cleanup (now safe — legacy path gone): the now-dead authz block (server.go:606-609), the AnnotationEnrichmentMiddleware block (611-617) and middleware symbol, the discovery middleware + handleSubsequentRequest routing injection + the WithDiscoveredCapabilities/DiscoveredCapabilitiesFromContext context seam, and the s.core == nil discovery guard are deleted. convertAnnotations (annotation_enrichment.go:92) is retained (reused by the core admission seam).
The AuthzMiddlewarefield on server.Config is kept (vestigial); cli/serve.go is unchanged and still sets it. Only the HTTP blocks that read it are removed.
Both //nolint:gocyclo directives are removed — New (server.go:300) and Start (server.go:682) — and lint is clean without them (task lint-fix).
cli/serve.go is unchanged; no caller change is required (the external brood-box embedder likewise requires none).
Acceptance gate: the full behavioral-parity suite (tools/list, tools/call, resources, prompts, composite workflows, session lifecycle, cross-pod Redis paths) passes equivalently before/after — this is the first PR where server.New actually runs through Serve, so it carries the epic's concentrated integration risk.
PR (or each split PR) is ≤ 400 LOC and ≤ 10 files changed (excluding tests/docs/generated)
server.New signature and observable behavior unchanged
All tests pass (task test); lint clean (task lint-fix)
Code reviewed and approved
Technical Approach
Recommended Implementation
Replace the inline body of server.New with a delegation to the two constructors
relocated in Phases 1–2, building the health monitor at the composition root first:
healthMon, err := <build monitor> — mirror server.go:436-450 (nil HealthMonitorConfig
⇒ nil monitor / disabled; otherwise health.NewMonitor(backendClient, backendRegistry.List(ctx), *cfg.HealthMonitorConfig)). This runs at the composition root because New (next) needs the StatusProvider at construction (A2).
core, err := New(deriveCoreConfig(cfg, rt, backendClient, discoveryMgr, backendRegistry, workflowDefs, healthMon))
— assembles the core VMCP (aggregator/router/backend registry/composer/admission seam/
elicitation) with healthMon injected as the StatusProvider (architecture.md "New (core)
wiring relocated", 278-284).
return Serve(ctx, core, deriveServerConfig(cfg, healthMon)) — assembles the transport *Server (mcp-go server/hooks, streamable HTTP, session manager, middleware chain, AS
runner, status reporter) and owns healthMon's lifecycle (architecture.md "Serve (transport)
wiring relocated", 285-290; P2.5 Move AS runner, status reporter, optimizer, health monitor under Serve #5443).
Defaults currently applied at the top of server.New (Host/EndpointPath/Name/Version/
SessionTTL, server.go:310-327) must continue to be honored — fold them into the deriver path
or keep them in the wrapper so the derived configs carry the same resolved values.
Cross-cutting fields (TelemetryProvider, AuditConfig, the health monitor) reach both New and Serve (R3; architecture.md 483-487).
A1 cleanup (safe now that the legacy path is gone). With server.New routed through Serve, every *Server has s.core != nil and AuthzMiddleware == nil, so the guarded
layers are unreachable. Delete them:
the authz block (server.go:606-609) and the AnnotationEnrichmentMiddleware block
(server.go:611-617); remove the AnnotationEnrichmentMiddleware symbol but keep convertAnnotations (annotation_enrichment.go:92, reused by the core admission seam);
the discovery middleware (the application site at server.go:633-637 and the s.core == nil guard P2.4 Replace discovery-into-context with direct VMCP calls #5442 added), handleSubsequentRequest
(discovery/middleware.go:273-315), and the WithDiscoveredCapabilities / DiscoveredCapabilitiesFromContext seam (discovery/context.go:26,35);
update the chain's leading comment (server.go:574-579) to the post-cleanup order.
Do not remove the AuthzMiddleware field from server.Config (cli/serve.go sets it;
the field is now vestigial, the new path ignores it). The Start//nolint:gocyclo is
removed because the orchestration complexity it suppressed moved into the decomposed Serve.
Patterns & Frameworks
mcp-go SDK boundary stays inside Serve/adapter — no mcp-go types cross the VMCP boundary (core principle fix(typo): corrects readme #1; anti-pattern Implement secret injection #5). server.New must not reintroduce any mcp-go wiring inline.
Delete only what is dead — the authz/annotation/discovery removals are valid only because routing through Serve eliminates the legacy path; keep convertAnnotations and the AuthzMiddleware field (still referenced by cli/serve.go).
Stable interface, additive change — pkg/vmcp/server is Stable (vmcp-library.md table); the signature does not move (core principle Start simple hardcoded registry #8). Do not widen or alter it.
pkg/vmcp/server/server.go:301 — server.New(...). Signature unchanged; body becomes the wrapper. The default-application block (310-327) and all inline transport/core wiring below it are replaced by the build-monitor + Serve(ctx, New(deriveCoreConfig(...)), deriveServerConfig(..., healthMon)) delegation.
pkg/vmcp/server/server.go:436-450 — health monitor construction; relocated into the wrapper (composition root), its StatusProvider injected into New (A2).
pkg/vmcp/server/server.go:300 — //nolint:gocyclo on New. Remove.
pkg/vmcp/server/server.go:682 — //nolint:gocyclo on (*Server).Start (server.go:683). Remove.
architecture.md "Key Files to Modify" (43-47) and "server.New compatibility wrapper" (14-17, 368, 480-482, 501).
Parity suite homes (mirror existing cases; do not rewrite): pkg/vmcp/server/server_test.go, pkg/vmcp/server/integration_test.go, and the reusable harness test/integration/vmcp/helpers/vmcp_server.go.
Component Interfaces
// Signature byte-for-byte unchanged; only the body changes.// The two //nolint:gocyclo directives (New @300, Start @682) are removed.funcNew(
ctx context.Context,
cfg*Config,
rt router.Router,
backendClient vmcp.BackendClient,
discoveryMgr discovery.Manager,
backendRegistry vmcp.BackendRegistry,
workflowDefsmap[string]*composer.WorkflowDefinition,
) (*Server, error) {
// defaults honored as today (via the derivers/wrapper).healthMon, err:=buildHealthMonitor(ctx, cfg, backendClient, backendRegistry) // nil => disabled (A2)iferr!=nil {
returnnil, err
}
core, err:=New(deriveCoreConfig(cfg, rt, backendClient, discoveryMgr, backendRegistry, workflowDefs, healthMon))
iferr!=nil {
returnnil, err
}
returnServe(ctx, core, deriveServerConfig(cfg, healthMon))
}
Testing Strategy
Unit Tests
server.New still applies Host/EndpointPath/Name/Version/SessionTTL defaults (server.go:310-327) — same resolved values reach the derived Config/ServerConfig.
The wrapper builds the health monitor once and injects the same instance as the core's StatusProvider and Serve's lifecycle *Monitor (A2); nil HealthMonitorConfig ⇒ disabled on both sides.
server.New propagates the error (and returns nil *Server) when monitor build, the core New, or Serve fails.
Lint passes with both //nolint:gocyclo removed (gocyclo no longer triggers on New or Start).
After cleanup, the middleware chain no longer contains authz/annotation/discovery layers; convertAnnotations and the AuthzMiddleware field still compile (the field is set by cli/serve.go, read by nothing).
Integration / Behavioral Parity Tests
Drive the stable server.New wrapper and assert MCP responses equivalent before/after for: tools/list, tools/call, resources, prompts, and composite workflows (homes: server_test.go, integration_test.go, helpers/vmcp_server.go).
Authz parity is critical here — this is the first PR where server.New enforces authz via the core admission seam instead of the HTTP middleware; assert allow/deny outcomes for tools/list filtering and tools/call denial match pre-refactor behavior (cross-check the R1 suite from P1.5 Core admission seam (bounded rewrite) #5438).
Description
Reduce
server.New's body to the thin wrapperServe(ctx, New(deriveCoreConfig(cfg, …)), deriveServerConfig(cfg, healthMon)), keepingthe existing 7-param signature byte-for-byte unchanged. This is the moment the
god-object
server.New(anti-pattern #3) is dismantled and the single live pathbecomes the
New/Servesplit — so it is also where the A1-deferred cleanup lands:build the health monitor at the composition root (A2), then delete the now-dead
authz/annotation HTTP blocks and retire the discovery middleware/seam + its
s.core == nilguard that Phase 2 left in place behind guards. Both//nolint:gocyclodirectivesare removed (the complexity is gone, not suppressed). This is the highest-integration-risk
PR in the epic: until now the behavioral-parity suite exercised the legacy path; here
server.Newis rerouted throughServefor real, so the full parity suite is the gate.Context
This is the final code change of Phase 3 (RFC THV-0076). #5444 introduced
deriveCoreConfig/deriveServerConfig, which split the in-memoryserver.Configinto the core
Configand transportServerConfig(and threaded the built healthmonitor). This task wires those derivers into
server.Newso its body delegates entirelyto
New+Serve. Per architecture.md "server.New compatibility wrapper" (14-17, 43-47,368, 480-482, 501), the 7-param signature and observable MCP behavior stay stable
throughout — the only in-repo caller (
cli/serve.go:421) and the externalbrood-boxembedder must require no changes.
Why the A1 cleanup lands here. Phase 2 deliberately did not delete the
authz/annotation middleware (#5441) or the discovery middleware (#5442) from the
shared
(*Server).Handler, becauseserver.Newstill used the legacy chain and deletingshared middleware would have opened an authz/aggregation regression window. Instead, Phase
2 made those layers inert on the
Servepath (authz/annotation via a nilAuthzMiddleware; discovery via as.core == nilguard). Once this task routesserver.NewthroughServe, the legacy path is gone — every request flows through aServe-built*Server(core present,AuthzMiddlewarenil) — so those layers are nowdead on all paths and can be safely deleted, completing the "shrink the middleware
chain" goal (anti-patterns #1/#4).
The
AuthzMiddlewarefield stays.cli/serve.go(serve.go:~374) still assignsConfig.AuthzMiddleware, and the "cli/serve.go unchanged" constraint forbids editing thatassignment. So the field is kept as a vestigial input; only the HTTP blocks that
read it are deleted, and
deriveServerConfigalready omits it so theServepath neverapplies it. The core admission seam enforces authz from the
Authzconfig instead.Health monitor (A2). Because the wrapper is
Serve(ctx, New(deriveCoreConfig(cfg)), deriveServerConfig(cfg)),Newis evaluated beforeServe. The wrapper therefore buildsthe
*health.Monitorat the composition root (mirroring the oldserver.go:436-450construction) and threads it both ways: as a
health.StatusProviderintoderiveCoreConfig(so the core can
filterHealthyBackends) and as the built*health.MonitorintoderiveServerConfig(soServeowns itsStart/Stoplifecycle, #5443).Because the body is fully reimplemented behind a stable surface, the full behavioral-parity
suite is the acceptance gate (research.md / architecture.md "Behavioral parity /
integration", 468-473).
Parent Story: #[#5432-issue]
Dependencies: #[#5444-issue] (#5444 —
deriveCoreConfig/deriveServerConfigconfig split)Blocks: #5446
Acceptance Criteria
server.Newbody isServe(ctx, New(deriveCoreConfig(cfg, …)), deriveServerConfig(cfg, healthMon)); the transport/core wiring no longer lives inline inserver.New.New(ctx, cfg, rt, backendClient, discoveryMgr, backendRegistry, workflowDefs) (*Server, error)signature is byte-for-byte unchanged.*health.Monitorat the composition root (nil whenHealthMonitorConfigis nil), injects itsStatusProviderintoNewviaderiveCoreConfig, and passes the same*health.MonitorintoServeviaderiveServerConfig. The core filters;Servelifecycles (P2.5 Move AS runner, status reporter, optimizer, health monitor under Serve #5443).server.go:606-609), theAnnotationEnrichmentMiddlewareblock (611-617) and middleware symbol, the discovery middleware +handleSubsequentRequestrouting injection + theWithDiscoveredCapabilities/DiscoveredCapabilitiesFromContextcontext seam, and thes.core == nildiscovery guard are deleted.convertAnnotations(annotation_enrichment.go:92) is retained (reused by the core admission seam).AuthzMiddlewarefield onserver.Configis kept (vestigial);cli/serve.gois unchanged and still sets it. Only the HTTP blocks that read it are removed.//nolint:gocyclodirectives are removed —New(server.go:300) andStart(server.go:682) — and lint is clean without them (task lint-fix).cli/serve.gois unchanged; no caller change is required (the externalbrood-boxembedder likewise requires none).server.Newactually runs throughServe, so it carries the epic's concentrated integration risk.thv vmcp serveE2E suite (test/e2e/vmcp_cli_*test.go, chainsaw operator scenarios) passes unchanged.server.Newsignature and observable behavior unchangedtask test); lint clean (task lint-fix)Technical Approach
Recommended Implementation
Replace the inline body of
server.Newwith a delegation to the two constructorsrelocated in Phases 1–2, building the health monitor at the composition root first:
healthMon, err := <build monitor>— mirrorserver.go:436-450(nilHealthMonitorConfig⇒ nil monitor / disabled; otherwise
health.NewMonitor(backendClient, backendRegistry.List(ctx), *cfg.HealthMonitorConfig)). This runs at the composition root becauseNew(next) needs theStatusProviderat construction (A2).core, err := New(deriveCoreConfig(cfg, rt, backendClient, discoveryMgr, backendRegistry, workflowDefs, healthMon))— assembles the core
VMCP(aggregator/router/backend registry/composer/admission seam/elicitation) with
healthMoninjected as theStatusProvider(architecture.md "New (core)wiring relocated", 278-284).
return Serve(ctx, core, deriveServerConfig(cfg, healthMon))— assembles the transport*Server(mcp-go server/hooks, streamable HTTP, session manager, middleware chain, ASrunner, status reporter) and owns
healthMon's lifecycle (architecture.md "Serve (transport)wiring relocated", 285-290; P2.5 Move AS runner, status reporter, optimizer, health monitor under Serve #5443).
Defaults currently applied at the top of
server.New(Host/EndpointPath/Name/Version/SessionTTL, server.go:310-327) must continue to be honored — fold them into the deriver path
or keep them in the wrapper so the derived configs carry the same resolved values.
Cross-cutting fields (
TelemetryProvider,AuditConfig, the health monitor) reach bothNewandServe(R3; architecture.md 483-487).A1 cleanup (safe now that the legacy path is gone). With
server.Newrouted throughServe, every*Serverhass.core != nilandAuthzMiddleware == nil, so the guardedlayers are unreachable. Delete them:
server.go:606-609) and theAnnotationEnrichmentMiddlewareblock(
server.go:611-617); remove theAnnotationEnrichmentMiddlewaresymbol but keepconvertAnnotations(annotation_enrichment.go:92, reused by the core admission seam);server.go:633-637and thes.core == nilguard P2.4 Replace discovery-into-context with direct VMCP calls #5442 added),handleSubsequentRequest(
discovery/middleware.go:273-315), and theWithDiscoveredCapabilities/DiscoveredCapabilitiesFromContextseam (discovery/context.go:26,35);server.go:574-579) to the post-cleanup order.Do not remove the
AuthzMiddlewarefield fromserver.Config(cli/serve.gosets it;the field is now vestigial, the new path ignores it). The
Start//nolint:gocycloisremoved because the orchestration complexity it suppressed moved into the decomposed
Serve.Patterns & Frameworks
Serve/adapter— no mcp-go types cross theVMCPboundary (core principle fix(typo): corrects readme #1; anti-pattern Implement secret injection #5).server.Newmust not reintroduce any mcp-go wiring inline.server.Newbecomes the textbook fix for the God-Object anti-pattern (Bump golangci/golangci-lint-action from 2f856675483cb8b9378ee77ee0beb67955aca9d7 to 4696ba8babb6127d732c3c6dde519db15edab9ea #3): a thin shim composingNew+Serve, not a 380-line constructor.Serveeliminates the legacy path; keepconvertAnnotationsand theAuthzMiddlewarefield (still referenced bycli/serve.go).pkg/vmcp/serveris Stable (vmcp-library.md table); the signature does not move (core principle Start simple hardcoded registry #8). Do not widen or alter it..claude/rules/go-style.md(immutable assignment, copy-before-mutate, no//nolintunless a confirmed false positive — here we are removing suppressions),.claude/rules/vmcp-anti-patterns.md(fix(typo): corrects readme #1 context coupling, Bump golangci/golangci-lint-action from 2f856675483cb8b9378ee77ee0beb67955aca9d7 to 4696ba8babb6127d732c3c6dde519db15edab9ea #3 God Object, Implement secret store #4 middleware overuse, Implement secret injection #5 SDK coupling, Figure out ergonomics for exposing directories #6 config-everywhere). Run thevmcp-reviewskill on the PR.Code Pointers
pkg/vmcp/server/server.go:301—server.New(...). Signature unchanged; body becomes the wrapper. The default-application block (310-327) and all inline transport/core wiring below it are replaced by the build-monitor +Serve(ctx, New(deriveCoreConfig(...)), deriveServerConfig(..., healthMon))delegation.pkg/vmcp/server/server.go:436-450— health monitor construction; relocated into the wrapper (composition root), itsStatusProviderinjected intoNew(A2).pkg/vmcp/server/server.go:300—//nolint:gocycloonNew. Remove.pkg/vmcp/server/server.go:682—//nolint:gocycloon(*Server).Start(server.go:683). Remove.pkg/vmcp/server/server.go:606-609,:611-617— the now-dead authz + annotation-enrichment blocks. Delete (legacy path gone). KeepconvertAnnotations(annotation_enrichment.go:92).pkg/vmcp/server/server.go:633-637+ thes.core == nilguard from P2.4 Replace discovery-into-context with direct VMCP calls #5442 — the discovery-middleware application. Delete.pkg/vmcp/discovery/middleware.go:273-315(handleSubsequentRequest),discovery/context.go:26,35(WithDiscoveredCapabilities/DiscoveredCapabilitiesFromContext) — the context seam. Delete/retire.pkg/vmcp/server/server.go:121-125—AuthzMiddlewarefield onserver.Config. Keep (vestigial;cli/serve.gosets it). Do not remove.pkg/vmcp/cli/serve.go:382-421— composition root; callsvmcpserver.New(...)at line 421 and assignsAuthzMiddlewareat ~374. Must require no changes.deriveCoreConfig/deriveServerConfig— introduced by P3.1 deriveCoreConfig/deriveServerConfig config split #5444 (dependency); this task consumes them (deriveServerConfignow takes the builthealthMon).pkg/vmcp/server/server_test.go,pkg/vmcp/server/integration_test.go, and the reusable harnesstest/integration/vmcp/helpers/vmcp_server.go.Component Interfaces
Testing Strategy
Unit Tests
server.Newstill applies Host/EndpointPath/Name/Version/SessionTTL defaults (server.go:310-327) — same resolved values reach the derivedConfig/ServerConfig.StatusProviderandServe's lifecycle*Monitor(A2); nilHealthMonitorConfig⇒ disabled on both sides.server.Newpropagates the error (and returns nil*Server) when monitor build, the coreNew, orServefails.//nolint:gocycloremoved (gocyclo no longer triggers onNeworStart).convertAnnotationsand theAuthzMiddlewarefield still compile (the field is set bycli/serve.go, read by nothing).Integration / Behavioral Parity Tests
server.Newwrapper and assert MCP responses equivalent before/after for: tools/list, tools/call, resources, prompts, and composite workflows (homes:server_test.go,integration_test.go,helpers/vmcp_server.go).server.Newenforces authz via the core admission seam instead of the HTTP middleware; assert allow/deny outcomes for tools/list filtering and tools/call denial match pre-refactor behavior (cross-check the R1 suite from P1.5 Core admission seam (bounded rewrite) #5438).lazyInjectSessionToolspath produces equivalent behavior.thv vmcp servesuite (test/e2e/vmcp_cli_*test.go) and chainsaw operator scenarios pass unchanged.Edge Cases
Watcherhandling (cli/serve.go:404-409) is unaffected by the wrapper.Out of Scope
server.New's signature, parameter order, or types (stays byte-for-byte).cli/serve.goor the externalbrood-boxembedder — including removing the now-vestigialAuthzMiddlewareassignment (the field is kept).vmcpconfig.Config/ CRD / YAML / wire / storage format (in-memory only).deriveCoreConfig/deriveServerConfigthemselves — that is P3.1 deriveCoreConfig/deriveServerConfig config split #5444.doc.goupdates and the decorator example — those are P4.1 Update vMCP architecture docs + doc.go #5446 / P4.2 Runnable decorator example embedder #5447.server.Newwrapper or deprecating it — it is retained as a stable shim.References