Skip to content

Commit 09531f9

Browse files
committed
feat: add support for elicitation
1 parent bde89a3 commit 09531f9

File tree

4 files changed

+45
-2
lines changed

4 files changed

+45
-2
lines changed

mcp/client.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ type ClientOptions struct {
5656
// Handler for sampling.
5757
// Called when a server calls CreateMessage.
5858
CreateMessageHandler func(context.Context, *ClientSession, *CreateMessageParams) (*CreateMessageResult, error)
59+
// Handler for elicitation.
60+
// Called when a server requests user input via Elicit.
61+
ElicitationHandler func(context.Context, *ClientSession, *ElicitParams) (*ElicitResult, error)
5962
// Handlers for notifications from the server.
6063
ToolListChangedHandler func(context.Context, *ClientSession, *ToolListChangedParams)
6164
PromptListChangedHandler func(context.Context, *ClientSession, *PromptListChangedParams)
@@ -119,6 +122,9 @@ func (c *Client) Connect(ctx context.Context, t Transport) (cs *ClientSession, e
119122
if c.opts.CreateMessageHandler != nil {
120123
caps.Sampling = &SamplingCapabilities{}
121124
}
125+
if c.opts.ElicitationHandler != nil {
126+
caps.Elicitation = &ElicitationCapabilities{}
127+
}
122128

123129
params := &InitializeParams{
124130
ProtocolVersion: latestProtocolVersion,
@@ -255,6 +261,14 @@ func (c *Client) createMessage(ctx context.Context, cs *ClientSession, params *C
255261
return c.opts.CreateMessageHandler(ctx, cs, params)
256262
}
257263

264+
func (c *Client) elicit(ctx context.Context, cs *ClientSession, params *ElicitParams) (*ElicitResult, error) {
265+
if c.opts.ElicitationHandler == nil {
266+
// TODO: wrap or annotate this error? Pick a standard code?
267+
return nil, &jsonrpc2.WireError{Code: CodeUnsupportedMethod, Message: "client does not support elicitation"}
268+
}
269+
return c.opts.ElicitationHandler(ctx, cs, params)
270+
}
271+
258272
// AddSendingMiddleware wraps the current sending method handler using the provided
259273
// middleware. Middleware is applied from right to left, so that the first one is
260274
// executed first.
@@ -291,6 +305,7 @@ var clientMethodInfos = map[string]methodInfo{
291305
methodPing: newMethodInfo(sessionMethod((*ClientSession).ping)),
292306
methodListRoots: newMethodInfo(clientMethod((*Client).listRoots)),
293307
methodCreateMessage: newMethodInfo(clientMethod((*Client).createMessage)),
308+
methodElicit: newMethodInfo(clientMethod((*Client).elicit)),
294309
notificationToolListChanged: newMethodInfo(clientMethod((*Client).callToolChangedHandler)),
295310
notificationPromptListChanged: newMethodInfo(clientMethod((*Client).callPromptChangedHandler)),
296311
notificationResourceListChanged: newMethodInfo(clientMethod((*Client).callResourceChangedHandler)),

mcp/cmd.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
package mcp
66

77
import (
8-
"context"
8+
"context" <-
99
"fmt"
1010
"io"
1111
"os/exec"

mcp/protocol.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -893,7 +893,30 @@ type ResourceUpdatedNotificationParams struct {
893893

894894
// TODO(jba): add CompleteRequest and related types.
895895

896-
// TODO(jba): add ElicitRequest and related types.
896+
type ElicitParams struct {
897+
// This property is reserved by the protocol to allow clients and servers to
898+
// attach additional metadata to their responses.
899+
Meta `json:"_meta,omitempty"`
900+
// A human-readable message describing what information is being requested.
901+
Message string `json:"message"`
902+
// A JSON Schema object defining the structure of the requested data.
903+
RequestedSchema *jsonschema.Schema `json:"requestedSchema"`
904+
}
905+
906+
func (x *ElicitParams) GetProgressToken() any { return getProgressToken(x) }
907+
func (x *ElicitParams) SetProgressToken(t any) { setProgressToken(x, t) }
908+
909+
// The client's response to an elicitation/create request from the server.
910+
type ElicitResult struct {
911+
// This property is reserved by the protocol to allow clients and servers to
912+
// attach additional metadata to their responses.
913+
Meta `json:"_meta,omitempty"`
914+
// The action taken by the user: "accept", "decline", or "cancel".
915+
Action string `json:"action"`
916+
// The data provided by the user if action is "accept". This should conform
917+
// to the requested schema.
918+
Content map[string]any `json:"content,omitempty"`
919+
}
897920

898921
// An Implementation describes the name and version of an MCP implementation, with an optional
899922
// title for UI representation.

mcp/server.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,11 @@ func (ss *ServerSession) CreateMessage(ctx context.Context, params *CreateMessag
628628
return handleSend[*CreateMessageResult](ctx, ss, methodCreateMessage, orZero[Params](params))
629629
}
630630

631+
// Elicit sends an elicitation request to the client asking for user input.
632+
func (ss *ServerSession) Elicit(ctx context.Context, params *ElicitParams) (*ElicitResult, error) {
633+
return handleSend[*ElicitResult](ctx, ss, methodElicit, orZero[Params](params))
634+
}
635+
631636
// Log sends a log message to the client.
632637
// The message is not sent if the client has not called SetLevel, or if its level
633638
// is below that of the last SetLevel.

0 commit comments

Comments
 (0)