mcp/server: advertise completions only if installed (#213)

Previously, completions would always be advertised as a capability even
if the CompletionHandler was not installed by the server. This CL fixes
that.
This commit is contained in:
Sam Thanawalla 2025-08-04 10:12:01 -04:00 • committed by GitHub
commit faaf77dc05
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 38 additions and 36 deletions

View file

@ -238,9 +238,7 @@ func (s *Server) capabilities() *serverCapabilities {
defer s.mu.Unlock() defer s.mu.Unlock()
caps := &serverCapabilities{ caps := &serverCapabilities{
// TODO(samthanawalla): check for completionHandler before advertising capability. Logging: &loggingCapabilities{},
Completions: &completionCapabilities{},
Logging: &loggingCapabilities{},
} }
if s.opts.HasTools || s.tools.len() > 0 { if s.opts.HasTools || s.tools.len() > 0 {
caps.Tools = &toolCapabilities{ListChanged: true} caps.Tools = &toolCapabilities{ListChanged: true}
@ -254,6 +252,9 @@ func (s *Server) capabilities() *serverCapabilities {
caps.Resources.Subscribe = true caps.Resources.Subscribe = true
} }
} }
if s.opts.CompletionHandler != nil {
caps.Completions = &completionCapabilities{}
}
return caps return caps
} }

View file

@ -242,8 +242,7 @@ func TestServerCapabilities(t *testing.T) {
name: "No capabilities", name: "No capabilities",
configureServer: func(s *Server) {}, configureServer: func(s *Server) {},
wantCapabilities: &serverCapabilities{ wantCapabilities: &serverCapabilities{
Completions: &completionCapabilities{}, Logging: &loggingCapabilities{},
Logging: &loggingCapabilities{},
}, },
}, },
{ {
@ -252,9 +251,8 @@ func TestServerCapabilities(t *testing.T) {
s.AddPrompt(&Prompt{Name: "p"}, nil) s.AddPrompt(&Prompt{Name: "p"}, nil)
}, },
wantCapabilities: &serverCapabilities{ wantCapabilities: &serverCapabilities{
Completions: &completionCapabilities{}, Logging: &loggingCapabilities{},
Logging: &loggingCapabilities{}, Prompts: &promptCapabilities{ListChanged: true},
Prompts: &promptCapabilities{ListChanged: true},
}, },
}, },
{ {
@ -263,9 +261,8 @@ func TestServerCapabilities(t *testing.T) {
s.AddResource(&Resource{URI: "file:///r"}, nil) s.AddResource(&Resource{URI: "file:///r"}, nil)
}, },
wantCapabilities: &serverCapabilities{ wantCapabilities: &serverCapabilities{
Completions: &completionCapabilities{}, Logging: &loggingCapabilities{},
Logging: &loggingCapabilities{}, Resources: &resourceCapabilities{ListChanged: true},
Resources: &resourceCapabilities{ListChanged: true},
}, },
}, },
{ {
@ -274,9 +271,8 @@ func TestServerCapabilities(t *testing.T) {
s.AddResourceTemplate(&ResourceTemplate{URITemplate: "file:///rt"}, nil) s.AddResourceTemplate(&ResourceTemplate{URITemplate: "file:///rt"}, nil)
}, },
wantCapabilities: &serverCapabilities{ wantCapabilities: &serverCapabilities{
Completions: &completionCapabilities{}, Logging: &loggingCapabilities{},
Logging: &loggingCapabilities{}, Resources: &resourceCapabilities{ListChanged: true},
Resources: &resourceCapabilities{ListChanged: true},
}, },
}, },
{ {
@ -293,9 +289,8 @@ func TestServerCapabilities(t *testing.T) {
}, },
}, },
wantCapabilities: &serverCapabilities{ wantCapabilities: &serverCapabilities{
Completions: &completionCapabilities{}, Logging: &loggingCapabilities{},
Logging: &loggingCapabilities{}, Resources: &resourceCapabilities{ListChanged: true, Subscribe: true},
Resources: &resourceCapabilities{ListChanged: true, Subscribe: true},
}, },
}, },
{ {
@ -304,9 +299,21 @@ func TestServerCapabilities(t *testing.T) {
s.AddTool(tool, nil) s.AddTool(tool, nil)
}, },
wantCapabilities: &serverCapabilities{ wantCapabilities: &serverCapabilities{
Completions: &completionCapabilities{}, Logging: &loggingCapabilities{},
Tools: &toolCapabilities{ListChanged: true},
},
},
{
name: "With completions",
configureServer: func(s *Server) {},
serverOpts: ServerOptions{
CompletionHandler: func(ctx context.Context, ss *ServerSession, params *CompleteParams) (*CompleteResult, error) {
return nil, nil
},
},
wantCapabilities: &serverCapabilities{
Logging: &loggingCapabilities{}, Logging: &loggingCapabilities{},
Tools: &toolCapabilities{ListChanged: true}, Completions: &completionCapabilities{},
}, },
}, },
{ {
@ -324,6 +331,9 @@ func TestServerCapabilities(t *testing.T) {
UnsubscribeHandler: func(ctx context.Context, up *UnsubscribeParams) error { UnsubscribeHandler: func(ctx context.Context, up *UnsubscribeParams) error {
return nil return nil
}, },
CompletionHandler: func(ctx context.Context, ss *ServerSession, params *CompleteParams) (*CompleteResult, error) {
return nil, nil
},
}, },
wantCapabilities: &serverCapabilities{ wantCapabilities: &serverCapabilities{
Completions: &completionCapabilities{}, Completions: &completionCapabilities{},
@ -342,11 +352,10 @@ func TestServerCapabilities(t *testing.T) {
HasTools: true, HasTools: true,
}, },
wantCapabilities: &serverCapabilities{ wantCapabilities: &serverCapabilities{
Completions: &completionCapabilities{}, Logging: &loggingCapabilities{},
Logging: &loggingCapabilities{}, Prompts: &promptCapabilities{ListChanged: true},
Prompts: &promptCapabilities{ListChanged: true}, Resources: &resourceCapabilities{ListChanged: true},
Resources: &resourceCapabilities{ListChanged: true}, Tools: &toolCapabilities{ListChanged: true},
Tools: &toolCapabilities{ListChanged: true},
}, },
}, },
} }

View file

@ -314,9 +314,8 @@ func TestStreamableServerTransport(t *testing.T) {
initReq := req(1, methodInitialize, &InitializeParams{}) initReq := req(1, methodInitialize, &InitializeParams{})
initResp := resp(1, &InitializeResult{ initResp := resp(1, &InitializeResult{
Capabilities: &serverCapabilities{ Capabilities: &serverCapabilities{
Completions: &completionCapabilities{}, Logging: &loggingCapabilities{},
Logging: &loggingCapabilities{}, Tools: &toolCapabilities{ListChanged: true},
Tools: &toolCapabilities{ListChanged: true},
}, },
ProtocolVersion: latestProtocolVersion, ProtocolVersion: latestProtocolVersion,
ServerInfo: &Implementation{Name: "testServer", Version: "v1.0.0"}, ServerInfo: &Implementation{Name: "testServer", Version: "v1.0.0"},
@ -732,9 +731,8 @@ func TestStreamableClientTransportApplicationJSON(t *testing.T) {
} }
initResult := &InitializeResult{ initResult := &InitializeResult{
Capabilities: &serverCapabilities{ Capabilities: &serverCapabilities{
Completions: &completionCapabilities{}, Logging: &loggingCapabilities{},
Logging: &loggingCapabilities{}, Tools: &toolCapabilities{ListChanged: true},
Tools: &toolCapabilities{ListChanged: true},
}, },
ProtocolVersion: latestProtocolVersion, ProtocolVersion: latestProtocolVersion,
ServerInfo: &Implementation{Name: "testServer", Version: "v1.0.0"}, ServerInfo: &Implementation{Name: "testServer", Version: "v1.0.0"},

View file

@ -58,7 +58,6 @@ code_review
"id": 2, "id": 2,
"result": { "result": {
"capabilities": { "capabilities": {
"completions": {},
"logging": {}, "logging": {},
"prompts": { "prompts": {
"listChanged": true "listChanged": true

View file

@ -27,7 +27,6 @@ code_review
"id": 1, "id": 1,
"result": { "result": {
"capabilities": { "capabilities": {
"completions": {},
"logging": {}, "logging": {},
"prompts": { "prompts": {
"listChanged": true "listChanged": true

View file

@ -50,7 +50,6 @@ info.txt
"id": 1, "id": 1,
"result": { "result": {
"capabilities": { "capabilities": {
"completions": {},
"logging": {}, "logging": {},
"resources": { "resources": {
"listChanged": true "listChanged": true

View file

@ -30,7 +30,6 @@ greet
"id": 1, "id": 1,
"result": { "result": {
"capabilities": { "capabilities": {
"completions": {},
"logging": {}, "logging": {},
"tools": { "tools": {
"listChanged": true "listChanged": true

View file

@ -18,7 +18,6 @@ response with its latest supported version.
"id": 1, "id": 1,
"result": { "result": {
"capabilities": { "capabilities": {
"completions": {},
"logging": {} "logging": {}
}, },
"protocolVersion": "2025-06-18", "protocolVersion": "2025-06-18",

View file

@ -18,7 +18,6 @@ support.
"id": 1, "id": 1,
"result": { "result": {
"capabilities": { "capabilities": {
"completions": {},
"logging": {} "logging": {}
}, },
"protocolVersion": "2024-11-05", "protocolVersion": "2024-11-05",