Part of stacklok/toolhive#6027.
Problem
mcpcompat server resource handlers cannot return _meta, so any backend
resource metadata is dropped before it reaches the wire — even though go-sdk
supports the field.
// server/server.go:70
type ResourceHandlerFunc func(ctx context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error)
The bridge to go-sdk then builds a result with no meta to populate:
// server/server.go:1024-1043, wrapResourceHandler
contents, err := h(ctx, mreq)
...
jsonConvert(mcp.ReadResourceResult{Contents: contents}, out) // Meta always nil
Both ends already support it — only the handler signature is in the way:
- go-sdk:
ResourceHandler func(ctx, *ReadResourceRequest) (*ReadResourceResult, error),
and ReadResourceResult embeds Meta (mcp/resource.go:39, mcp/protocol.go:1595).
- mcpcompat:
mcp.ReadResourceResult embeds Result, which carries Meta
(mcp/resources.go:191).
The []ResourceContents shape came from mark3labs/mcp-go and was kept for
source compatibility during the migration.
Proposal
Add a result-returning variant alongside the existing handler — e.g. a
ResourceResultHandlerFunc returning (*mcp.ReadResourceResult, error) plus
AddResourceWithResult / an equivalent registration path, and the same for
resource templates (wrapResourceHandler is shared by
AddResourceTemplate via server.go:608).
wrapResourceHandler then forwards the handler's Meta into the go-sdk result
instead of constructing a meta-less one.
Additive on purpose. Existing ResourceHandlerFunc callers keep compiling.
This does not weaken the mcp-go source-compatibility contract: mcp-go has no
result-returning resource handler, so there is no upstream shape to diverge
from.
Consumers waiting on this
In ToolHive, both drop resource _meta for this reason today:
pkg/vmcp/server/serve_handlers.go — coreResourceHandler /
coreResourceTemplateHandler
pkg/transport/bridge.go:226,241
Tracked downstream in stacklok/toolhive#6027.
Acceptance
- A resource handler can set
_meta and it appears on the resources/read wire result.
- Existing
ResourceHandlerFunc registrations are unchanged and still compile.
- Covered for both
AddResource and AddResourceTemplate.
Generated with Claude Code
Part of stacklok/toolhive#6027.
Problem
mcpcompatserver resource handlers cannot return_meta, so any backendresource metadata is dropped before it reaches the wire — even though go-sdk
supports the field.
The bridge to go-sdk then builds a result with no meta to populate:
Both ends already support it — only the handler signature is in the way:
ResourceHandler func(ctx, *ReadResourceRequest) (*ReadResourceResult, error),and
ReadResourceResultembedsMeta(mcp/resource.go:39,mcp/protocol.go:1595).mcp.ReadResourceResultembedsResult, which carriesMeta(
mcp/resources.go:191).The
[]ResourceContentsshape came from mark3labs/mcp-go and was kept forsource compatibility during the migration.
Proposal
Add a result-returning variant alongside the existing handler — e.g. a
ResourceResultHandlerFuncreturning(*mcp.ReadResourceResult, error)plusAddResourceWithResult/ an equivalent registration path, and the same forresource templates (
wrapResourceHandleris shared byAddResourceTemplateviaserver.go:608).wrapResourceHandlerthen forwards the handler'sMetainto the go-sdk resultinstead of constructing a meta-less one.
Additive on purpose. Existing
ResourceHandlerFunccallers keep compiling.This does not weaken the mcp-go source-compatibility contract: mcp-go has no
result-returning resource handler, so there is no upstream shape to diverge
from.
Consumers waiting on this
In ToolHive, both drop resource
_metafor this reason today:pkg/vmcp/server/serve_handlers.go—coreResourceHandler/coreResourceTemplateHandlerpkg/transport/bridge.go:226,241Tracked downstream in stacklok/toolhive#6027.
Acceptance
_metaand it appears on theresources/readwire result.ResourceHandlerFuncregistrations are unchanged and still compile.AddResourceandAddResourceTemplate.Generated with Claude Code