Problem
server.Server builds a composer.ElicitationProtocolHandler internally (pkg/vmcp/server/server.go:347 via composer.NewDefaultElicitationHandler) and feeds it a mark3labs *mcpserver.MCPServer via the unexported newSDKElicitationAdapter (pkg/vmcp/server/sdk_elicitation_adapter.go:39). Three seams are closed to embedders:
*Server.mcpServer field is unexported.
- No
MCPServer() accessor or equivalent on *Server.
newSDKElicitationAdapter is unexported.
Use case
Embedders who wrap toolhive's composer in their own pipeline (gateway-level audit, custom elicitation surface, ahead-of-time elicitation schema validation) cannot re-target their elicitation flow through the server toolhive constructs internally. Holding a parallel mark3labs server does not work because /mcp requests are served by toolhive's internal instance, so server.ClientSession correlation lands on the wrong server.
Proposed API
Pick one (in order of smallest surface):
a) Add (*Server).MCPServer() *mcpserver.MCPServer accessor. Minimal disclosure, lets embedders install their own elicitation handler via server.WithElicitation(...) against the actual serving server.
b) Export NewSDKElicitationAdapter(srv *mcpserver.MCPServer) composer.ElicitationProtocolHandler. Useful in its own right for embedders that construct their own composer separately from server.New.
c) Add server.WithElicitationHandler(h composer.ElicitationProtocolHandler) Option so callers can inject their own handler end-to-end, bypassing the SDK adapter entirely.
Scope
- Additive.
- Choice (a) is the thinnest change; (b) is orthogonal and useful on its own; (c) is the most complete but requires coordinating with the composer's existing handler-wiring logic.
Problem
server.Serverbuilds acomposer.ElicitationProtocolHandlerinternally (pkg/vmcp/server/server.go:347viacomposer.NewDefaultElicitationHandler) and feeds it a mark3labs*mcpserver.MCPServervia the unexportednewSDKElicitationAdapter(pkg/vmcp/server/sdk_elicitation_adapter.go:39). Three seams are closed to embedders:*Server.mcpServerfield is unexported.MCPServer()accessor or equivalent on*Server.newSDKElicitationAdapteris unexported.Use case
Embedders who wrap toolhive's composer in their own pipeline (gateway-level audit, custom elicitation surface, ahead-of-time elicitation schema validation) cannot re-target their elicitation flow through the server toolhive constructs internally. Holding a parallel mark3labs server does not work because
/mcprequests are served by toolhive's internal instance, soserver.ClientSessioncorrelation lands on the wrong server.Proposed API
Pick one (in order of smallest surface):
a) Add
(*Server).MCPServer() *mcpserver.MCPServeraccessor. Minimal disclosure, lets embedders install their own elicitation handler viaserver.WithElicitation(...)against the actual serving server.b) Export
NewSDKElicitationAdapter(srv *mcpserver.MCPServer) composer.ElicitationProtocolHandler. Useful in its own right for embedders that construct their own composer separately fromserver.New.c) Add
server.WithElicitationHandler(h composer.ElicitationProtocolHandler) Optionso callers can inject their own handler end-to-end, bypassing the SDK adapter entirely.Scope