MCPcopy Create free account
hub / github.com/modelcontextprotocol/go-sdk / urlElicitationMiddleware

Function urlElicitationMiddleware

mcp/client.go:517–608  ·  view source on GitHub ↗

urlElicitationMiddleware returns middleware that automatically handles URL elicitation required errors by executing the elicitation handler, waiting for completion notifications, and retrying the operation. This middleware should be added to clients that want automatic URL elicitation handling: c

()

Source from the content-addressed store, hash-verified

515// TODO(rfindley): this isn't strictly necessary for the SEP, but may be
516// useful. Propose exporting it.
517func urlElicitationMiddleware() Middleware {
518 return func(next MethodHandler) MethodHandler {
519 return func(ctx context.Context, method string, req Request) (Result, error) {
520 // Call the underlying handler.
521 res, err := next(ctx, method, req)
522 if err == nil {
523 return res, nil
524 }
525
526 // Check if this is a URL elicitation required error.
527 var rpcErr *jsonrpc.Error
528 if !errors.As(err, &rpcErr) || rpcErr.Code != CodeURLElicitationRequired {
529 return res, err
530 }
531
532 // Notifications don't support retries.
533 if strings.HasPrefix(method, "notifications/") {
534 return res, err
535 }
536
537 // Extract the client session.
538 cs, ok := req.GetSession().(*ClientSession)
539 if !ok {
540 return res, err
541 }
542
543 // Check if the client has an elicitation handler.
544 if cs.client.opts.ElicitationHandler == nil {
545 return res, err
546 }
547
548 // Parse the elicitations from the error data.
549 var errorData struct {
550 Elicitations []*ElicitParams `json:"elicitations"`
551 }
552 if rpcErr.Data != nil {
553 if err := json.Unmarshal(rpcErr.Data, &errorData); err != nil {
554 return nil, fmt.Errorf("failed to parse URL elicitation error data: %w", err)
555 }
556 }
557
558 // Validate that all elicitations are URL mode.
559 for _, elicit := range errorData.Elicitations {
560 mode := elicit.Mode
561 if mode == "" {
562 mode = "form" // Default mode.
563 }
564 if mode != "url" {
565 return nil, fmt.Errorf("URLElicitationRequired error must only contain URL mode elicitations, got %q", mode)
566 }
567 }
568
569 // Register waiters for all elicitations before executing handlers
570 // to avoid race condition where notification arrives before waiter is registered.
571 type waiter struct {
572 await func(context.Context) error
573 cleanup func()
574 }

Callers 1

Calls 5

UnmarshalFunction · 0.92
newClientRequestFunction · 0.85
elicitMethod · 0.80
GetSessionMethod · 0.65

Tested by 1

Used in the wild real call sites across dependent graphs

searching dependent graphs…