Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions examples/completion/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright 2025 The Go MCP SDK Authors. All rights reserved.
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

package main

import (
"context"
"fmt"
"log"

"github.com/modelcontextprotocol/go-sdk/mcp"
)

// This example demonstrates the minimal code to declare and assign
// a CompletionHandler to an MCP Server's options.
func main() {
// Define your custom CompletionHandler logic.
myCompletionHandler := func(_ context.Context, _ *mcp.ServerSession, params *mcp.CompleteParams) (*mcp.CompleteResult, error) {
// In a real application, you'd implement actual completion logic here.
// For this example, we return a fixed set of suggestions.
var suggestions []string
switch params.Ref.Type {
case "ref/prompt":
suggestions = []string{"suggestion1", "suggestion2", "suggestion3"}
case "ref/resource":
suggestions = []string{"suggestion4", "suggestion5", "suggestion6"}
default:
return nil, fmt.Errorf("unrecognized content type %s", params.Ref.Type)
}

return &mcp.CompleteResult{
Completion: mcp.CompletionResultDetails{
HasMore: false,
Total: len(suggestions),
Values: suggestions,
},
}, nil
}

// Create the MCP Server instance and assign the handler.
// No server running, just showing the configuration.
_ = mcp.NewServer("myServer", "v1.0.0", &mcp.ServerOptions{
CompletionHandler: myCompletionHandler,
})

log.Println("MCP Server instance created with a CompletionHandler assigned (but not running).")
log.Println("This example demonstrates configuration, not live interaction.")
}
5 changes: 5 additions & 0 deletions mcp/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ func (c *Client) AddReceivingMiddleware(middleware ...Middleware[*ClientSession]

// clientMethodInfos maps from the RPC method name to serverMethodInfos.
var clientMethodInfos = map[string]methodInfo{
methodComplete: newMethodInfo(sessionMethod((*ClientSession).Complete)),
methodPing: newMethodInfo(sessionMethod((*ClientSession).ping)),
methodListRoots: newMethodInfo(clientMethod((*Client).listRoots)),
methodCreateMessage: newMethodInfo(clientMethod((*Client).createMessage)),
Expand Down Expand Up @@ -352,6 +353,10 @@ func (cs *ClientSession) ReadResource(ctx context.Context, params *ReadResourceP
return handleSend[*ReadResourceResult](ctx, cs, methodReadResource, orZero[Params](params))
}

func (cs *ClientSession) Complete(ctx context.Context, params *CompleteParams) (*CompleteResult, error) {
return handleSend[*CompleteResult](ctx, cs, methodComplete, orZero[Params](params))
}

func (c *Client) callToolChangedHandler(ctx context.Context, s *ClientSession, params *ToolListChangedParams) (Result, error) {
return callNotificationHandler(ctx, c.opts.ToolListChangedHandler, s, params)
}
Expand Down
93 changes: 92 additions & 1 deletion mcp/protocol.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ package mcp

import (
"encoding/json"
"fmt"

"github.com/modelcontextprotocol/go-sdk/jsonschema"
)
Expand Down Expand Up @@ -182,6 +183,93 @@ type ClientCapabilities struct {
Elicitation *ElicitationCapabilities `json:"elicitation,omitempty"`
}

type CompleteParamsArgument struct {
// The name of the argument
Name string `json:"name"`
// The value of the argument to use for completion matching.
Value string `json:"value"`
}

// CompleteContext represents additional, optional context for completions.
type CompleteContext struct {
// Previously-resolved variables in a URI template or prompt.
Arguments []string `json:"arguments,omitempty"`
}

// CompleteReference represents a completion reference type (ref/prompt ref/resource).
// The Type field determines which other fields are relevant.
type CompleteReference struct {
Type string `json:"type"`
// Name is relevant when Type is "ref/prompt".
Name string `json:"name,omitempty"`
// URI is relevant when Type is "ref/resource".
URI string `json:"uri,omitempty"`
}

func (r *CompleteReference) UnmarshalJSON(data []byte) error {
type wireCompleteReference CompleteReference // for naive unmarshaling
var r2 wireCompleteReference
if err := json.Unmarshal(data, &r2); err != nil {
return err
}
switch r2.Type {
case "ref/prompt", "ref/resource":
if r2.Type == "ref/prompt" && r2.URI != "" {
return fmt.Errorf("reference of type %q must not have a URI set", r2.Type)
}
if r2.Type == "ref/resource" && r2.Name != "" {
return fmt.Errorf("reference of type %q must not have a Name set", r2.Type)
}
default:
return fmt.Errorf("unrecognized content type %q", r2.Type)
}
*r = CompleteReference(r2)
return nil
}

func (r *CompleteReference) MarshalJSON() ([]byte, error) {
// Validation for marshalling: ensure consistency before converting to JSON.
switch r.Type {
case "ref/prompt":
if r.URI != "" {
return nil, fmt.Errorf("reference of type %q must not have a URI set for marshalling", r.Type)
}
case "ref/resource":
if r.Name != "" {
return nil, fmt.Errorf("reference of type %q must not have a Name set for marshalling", r.Type)
}
default:
return nil, fmt.Errorf("unrecognized reference type %q for marshalling", r.Type)
}

type wireReference CompleteReference
return json.Marshal(wireReference(*r))
}

type CompleteParams struct {
// This property is reserved by the protocol to allow clients and servers to
// attach additional metadata to their responses.
Meta `json:"_meta,omitempty"`
// The argument's information
Argument CompleteParamsArgument `json:"argument"`
Context *CompleteContext `json:"context,omitempty"`
Ref *CompleteReference `json:"ref"`
}

type CompletionResultDetails struct {
HasMore bool `json:"hasMore,omitempty"`
Total int `json:"total,omitempty"`
Values []string `json:"values"`
}

// The server's response to a completion/complete request
type CompleteResult struct {
// This property is reserved by the protocol to allow clients and servers to
// attach additional metadata to their responses.
Meta `json:"_meta,omitempty"`
Completion CompletionResultDetails `json:"completion"`
}

type CreateMessageParams struct {
// This property is reserved by the protocol to allow clients and servers to
// attach additional metadata to their responses.
Expand Down Expand Up @@ -836,6 +924,9 @@ type implementation struct {
Version string `json:"version"`
}

// Present if the server supports argument autocompletion suggestions.
type completionCapabilities struct{}

// Present if the server supports sending log messages to the client.
type loggingCapabilities struct{}

Expand All @@ -858,7 +949,7 @@ type resourceCapabilities struct {
// additional capabilities.
type serverCapabilities struct {
// Present if the server supports argument autocompletion suggestions.
Completions struct{} `json:"completions,omitempty"`
Completions *completionCapabilities `json:"completions,omitempty"`
// Experimental, non-standard capabilities that the server supports.
Experimental map[string]struct{} `json:"experimental,omitempty"`
// Present if the server supports sending log messages to the client.
Expand Down
Loading
Loading