From 2b6f7b51854e813c06ddec75a1abb5da33345574 Mon Sep 17 00:00:00 2001 From: Sam Thanawalla <17936816+samthanawalla@users.noreply.github.com> Date: Tue, 29 Jul 2025 05:20:08 -0400 Subject: [PATCH] mcp/server: add initial capability server option (#182) This CL adds an option for servers to advertise support for features that have not been added yet. This includes Prompts, Tools, and Resources as these could be dynamically added after initialization. Fixes: #135. --- mcp/server.go | 16 +++++++++++++--- mcp/server_test.go | 16 ++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/mcp/server.go b/mcp/server.go index 4270578..e88455a 100644 --- a/mcp/server.go +++ b/mcp/server.go @@ -69,6 +69,15 @@ type ServerOptions struct { SubscribeHandler func(context.Context, *SubscribeParams) error // Function called when a client session unsubscribes from a resource. UnsubscribeHandler func(context.Context, *UnsubscribeParams) error + // If true, advertises the prompts capability during initialization, + // even if no prompts have been registered. + HasPrompts bool + // If true, advertises the resources capability during initialization, + // even if no resources have been registered. + HasResources bool + // If true, advertises the tools capability during initialization, + // even if no tools have been registered. + HasTools bool } // NewServer creates a new MCP server. The resulting server has no features: @@ -229,16 +238,17 @@ func (s *Server) capabilities() *serverCapabilities { defer s.mu.Unlock() caps := &serverCapabilities{ + // TODO(samthanawalla): check for completionHandler before advertising capability. Completions: &completionCapabilities{}, Logging: &loggingCapabilities{}, } - if s.tools.len() > 0 { + if s.opts.HasTools || s.tools.len() > 0 { caps.Tools = &toolCapabilities{ListChanged: true} } - if s.prompts.len() > 0 { + if s.opts.HasPrompts || s.prompts.len() > 0 { caps.Prompts = &promptCapabilities{ListChanged: true} } - if s.resources.len() > 0 || s.resourceTemplates.len() > 0 { + if s.opts.HasResources || s.resources.len() > 0 || s.resourceTemplates.len() > 0 { caps.Resources = &resourceCapabilities{ListChanged: true} if s.opts.SubscribeHandler != nil { caps.Resources.Subscribe = true diff --git a/mcp/server_test.go b/mcp/server_test.go index 9a36c96..79c607e 100644 --- a/mcp/server_test.go +++ b/mcp/server_test.go @@ -333,6 +333,22 @@ func TestServerCapabilities(t *testing.T) { Tools: &toolCapabilities{ListChanged: true}, }, }, + { + name: "With initial capabilities", + configureServer: func(s *Server) {}, + serverOpts: ServerOptions{ + HasPrompts: true, + HasResources: true, + HasTools: true, + }, + wantCapabilities: &serverCapabilities{ + Completions: &completionCapabilities{}, + Logging: &loggingCapabilities{}, + Prompts: &promptCapabilities{ListChanged: true}, + Resources: &resourceCapabilities{ListChanged: true}, + Tools: &toolCapabilities{ListChanged: true}, + }, + }, } for _, tc := range testCases {