ElicitationToRequest
Go · module github.com/muthuishere/toolnexus/golang · SPEC §10 · golang/mcp.go
func ElicitationToRequest(params mcp.ElicitationParams) Requestfunc AnswerToElicitResult(answer Answer) *mcp.ElicitationResultAn MCP server can reach back mid-tools/call and ask the human for input — elicitation/create is
a reverse request, server → client. ElicitationToRequest maps that request onto toolnexus’s
own suspension contract (Request), so a host that already knows how to
resolve a §10 suspension (a form, an auth link) can resolve an MCP elicitation the same way, with no
separate code path. AnswerToElicitResult maps the resolution back onto the shape the MCP SDK
expects.
When to use it
Section titled “When to use it”You call these two functions directly only if you are building your own MCP client integration
outside LoadMcp/LoadMcpWithContext. In the normal path you never call them — you pass a waitFor func(Request) (Answer, error) to LoadMcp, and toolnexus wires this mapping internally (the
elicitationBridge in golang/mcp.go). Reach for them directly when writing a test double for a
host resolver, or when porting the same mapping into your own MCP client.
Why this and not the alternative
Section titled “Why this and not the alternative”Examples
Section titled “Examples”1. Form-mode elicitation becomes a kind:"input" Request
Section titled “1. Form-mode elicitation becomes a kind:"input" Request”package main
import ( "fmt" "log"
"github.com/mark3labs/mcp-go/mcp" toolnexus "github.com/muthuishere/toolnexus/golang")
func main() { params := mcp.ElicitationParams{ Mode: "form", Message: "What is your deployment region?", RequestedSchema: map[string]any{ "type": "object", "properties": map[string]any{"region": map[string]any{"type": "string"}}, }, }
req := toolnexus.ElicitationToRequest(params)
if req.Kind != "input" { log.Fatalf("expected kind=input, got %q", req.Kind) } if req.Prompt != params.Message { log.Fatalf("expected prompt to carry the message, got %q", req.Prompt) } if req.ID == "" { log.Fatal("expected a generated, unique request id") } schema, ok := req.Data["schema"] if !ok || schema == nil { log.Fatal("expected the requested schema under data.schema") }
fmt.Println("ok:", req.Kind, "|", req.Prompt)}2. URL-mode elicitation becomes a kind:"authorization" Request
Section titled “2. URL-mode elicitation becomes a kind:"authorization" Request”package main
import ( "fmt" "log"
"github.com/mark3labs/mcp-go/mcp" toolnexus "github.com/muthuishere/toolnexus/golang")
func main() { params := mcp.ElicitationParams{ Mode: "url", Message: "Sign in to continue", URL: "https://example.com/oauth/authorize", }
req := toolnexus.ElicitationToRequest(params)
if req.Kind != "authorization" { log.Fatalf("expected kind=authorization, got %q", req.Kind) } if req.URL != params.URL { log.Fatalf("expected url to carry through, got %q", req.URL) }
fmt.Println("ok:", req.Kind, "|", req.URL)}3. Round-tripping an Answer back to an ElicitationResult
Section titled “3. Round-tripping an Answer back to an ElicitationResult”AnswerToElicitResult covers three outcomes: accepted (with data), explicitly declined, and
everything else treated as a cancellation — a dismissal, a timeout, an unspecified reason.
package main
import ( "fmt" "log"
"github.com/mark3labs/mcp-go/mcp" toolnexus "github.com/muthuishere/toolnexus/golang")
func main() { accepted := toolnexus.AnswerToElicitResult(toolnexus.Answer{ Ok: true, Data: map[string]any{"region": "apac"}, }) if accepted.Action != mcp.ElicitationResponseActionAccept { log.Fatalf("expected accept, got %v", accepted.Action) } if content, ok := accepted.Content.(map[string]any); !ok || content["region"] != "apac" { log.Fatalf("expected content to carry the answer data, got %v", accepted.Content) }
declined := toolnexus.AnswerToElicitResult(toolnexus.Answer{Ok: false, Reason: "declined"}) if declined.Action != mcp.ElicitationResponseActionDecline { log.Fatalf("expected decline, got %v", declined.Action) }
cancelled := toolnexus.AnswerToElicitResult(toolnexus.Answer{Ok: false, Reason: "expired"}) if cancelled.Action != mcp.ElicitationResponseActionCancel { log.Fatalf("expected cancel for a non-declined refusal, got %v", cancelled.Action) }
fmt.Println("ok:", accepted.Action, declined.Action, cancelled.Action)}Mapping
Section titled “Mapping”ElicitationParams |
Request |
|---|---|
Mode == "url" |
Kind: "authorization", URL: params.URL |
Mode != "url" (form, default) |
Kind: "input", Data["schema"]: params.RequestedSchema |
Message |
Prompt |
| — | ID — freshly generated, unique per call |
Answer |
ElicitationResult |
|---|---|
Ok: true |
Action: accept, Content: Answer.Data (or {} if nil) |
Ok: false, Reason: "declined" |
Action: decline |
Ok: false, any other reason |
Action: cancel |
See also
Section titled “See also”LoadMcp— passwaitForhere for the ordinary integration path; this mapping runs automatically.LoadMcpWithContext— the ctx-aware load, same elicitation bridge.ListMcpTools— list what each configured server would expose, plus per-server status, without wiring it into a toolkit.ParseMcpConfig— parse and validate config without connecting — the fast fail for a malformed or misspelled server block.