Skip to content

Elicitation

Elicitation lets GitLab MCP Server ask the user for input through structured forms, enabling wizard-style creation flows for complex resources such as issues, merge requests, releases, and projects. Instead of requiring the AI to supply every parameter upfront, the server collects fields one step at a time, validates each answer, and confirms before creating the resource.

This capability is server-to-client and client-dependent: the MCP client must declare support: in initialize on protocol 2025-11-25 and earlier, and on each request from 2026-07-28. When a client does not support elicitation, GitLab MCP Server falls back to standard parameterized tools, so resource creation still works without the interactive flow.

Standard MCP tools require the AI to provide all parameters upfront in a single tool call. For complex resources — where fields depend on earlier choices and missing data leads to errors — the AI must either guess values or ask multiple chat questions before calling the tool. Elicitation removes that guesswork by letting the server gather and validate each field interactively.

With elicitation, the server pauses execution and asks the user directly for input through the MCP client’s UI. Each answer is checked against the question before the next one is asked, and the flow ends with an explicit confirmation before any GitLab API call.

GitLab APIMCP ServerAI AssistantUserGitLab APIMCP ServerAI AssistantUser"Create a merge request"gitlab_interactive_mr_create"Source branch?" (form field)"feature/login""Target branch?" (form field)"main""Title?" (form field)"Fix login redirect""Squash commits?" (checkbox)Yes"Create MR with these settings?" (confirmation)ConfirmCreate merge requestMR createdMR !123 created successfully

Each step is its own request to the client: one elicitation/create per question, carrying the question and a JSON Schema for the answer (a text field, a choice from a list, or a yes/no), so the client can draw the right control. The user answers each one with accept, decline or cancel.

  1. Capability check: before asking anything, the wizard checks that the client declared elicitation. If it did not, the wizard stops and names the action that does the same work (see What happens without elicitation support?).
  2. Gathering: the questions follow one another. An optional one can be declined or left empty, and the flow carries on without that field.
  3. Confirmation: the wizard shows a summary of everything it collected and asks for a final yes or no.
  4. Execution: only after that yes does it call GitLab, and it returns the object GitLab created.

Cancelling at any step, or answering no at the confirmation, ends the flow with nothing sent to GitLab.

The flow is the same for every client; how the questions travel depends on the MCP protocol version the client speaks:

Client protocolMechanismOn the wire
2025-11-25 and earlierSynchronous server-initiated requestsWhile the tool call runs, the server sends one elicitation/create request per question and waits for the answer: an action (accept, decline or cancel) and, on accept, the content
2026-07-28Multi-round-trip requests (MRTR, SEP-2322)The tool result carries an inputRequests map keyed by question and an opaque requestState; the client asks the user, then repeats the same call with the answers in inputResponses and the requestState echoed

On the multi-round-trip path one round carries one question. An abridged first round of the issue wizard looks like this:

{
"resultType": "input_required",
"inputRequests": {
"title": {
"method": "elicitation/create",
"params": {
"message": "Enter the issue title",
"requestedSchema": {
"type": "object",
"properties": {
"title": { "type": "string", "title": "title", "description": "Enter the issue title" }
},
"required": ["title"]
}
}
}
},
"requestState": "<opaque, signed by the server>"
}

The wizard runs again from the start on every round, replaying the answers carried in requestState instead of asking them again, so the user sees the same questions in the same order on both paths.

The version that decides is the one the client declared, not the one its session negotiated, and on the legacy handshake those two can differ. initialize is deprecated in 2026-07-28, so the Go SDK this server is built on (v1.8.0) answers an initialize asking for 2026-07-28 with 2025-11-25, while keeping the version the client asked for. The server reads the version the request states, which a 2026-07-28 client sends with every request and an older client stated once in initialize. A client that asks for 2026-07-28 in initialize is therefore served multi-round-trip input requests although its session negotiated 2025-11-25.

The SDK decides the same way, and its own client answers inputRequests whatever version it negotiated, so a client built on it is unaffected. A client that claimed 2026-07-28 in initialize and cannot handle inputRequests would receive a result it cannot act on. The negotiated version should drive both sides, which is the SDK’s to change; the defect is recorded upstream.

On a 2026-07-28 session every tool result carries resultType: input_required on a result that asks for input, complete on any other. It follows the declared version too, so a client that asked for 2026-07-28 in initialize gets resultType: "complete" on ordinary calls that elicit nothing. Results on a legacy session carry no resultType.

HTTP mode is stateless by default, and that decides which of the two forms is available:

TransportClient protocolElicitation
stdio, or HTTP --stateless=false2025-11-25 and earlierAvailable: synchronous elicitation/create requests
stdio2026-07-28Available: multi-round-trip input requests
HTTP stateless (default)2026-07-28Available: the input requests travel inside the tool result, so no session or server-initiated channel is needed
HTTP stateless (default)2025-11-25 and earlierUnavailable: no channel outlives the request, so the wizards answer with their alternative action and a destructive action needs confirm: true
HTTP --stateless=false2026-07-28Unavailable: the deployment does not serve this revision and answers 400

A --stateless=false deployment does not offer 2026-07-28 at all, because the SDK’s streamable transport serves that revision only without sessions. A request naming it is answered 400 with a JSON-RPC -32022 error whose data.supported lists the revisions the deployment does negotiate, so the client can retry on one of them and use the synchronous form (Protocol revisions this server negotiates).

GitLab MCP Server provides four wizard-style creation tools. Each guides the user through the fields a resource needs and confirms before performing the final API call.

ToolDescription
gitlab_interactive_issue_createStep-by-step issue creation: title, description, labels, confidentiality, confirmation
gitlab_interactive_mr_createGuided merge request creation: branches, title, description, labels, remove-source and squash options, confirmation
gitlab_interactive_release_createRelease creation wizard: tag name, release name, description, confirmation
gitlab_interactive_project_createProject creation: name, description, visibility, README initialization, default branch with a README, confirmation

The issue, merge request and release wizards take the target project_id as a tool parameter; the prompts collect the remaining fields. These four tools are registered by name on the meta and individual surfaces; on the default dynamic surface they are reached through gitlab_execute_action with the catalog IDs interactive.issue_create, interactive.mr_create, interactive.release_create and interactive.project_create, which gitlab_find_action returns.

The questions come in the order below. Declining an optional question continues without that field; declining a required one, or cancelling at any question, ends the flow. Every yes/no question starts on no. In the final summary a long description shows its first 100 characters.

StepQuestionAnswerRequired
1TitleTextYes
2Description (Markdown)TextNo
3Labels, comma-separatedTextNo
4Should it be confidential?Yes/noNo
5Create the issue? (summary)Yes/noYes
StepQuestionAnswerRequired
1Source branchTextYes
2Target branchTextYes
3TitleTextYes
4Description (Markdown)TextNo
5Labels, comma-separatedTextNo
6Remove the source branch after merge?Yes/noNo
7Squash commits on merge?Yes/noNo
8Create the merge request? (summary)Yes/noYes
StepQuestionAnswerRequired
1Tag name (the tag must already exist)TextYes
2Release name (empty lets GitLab use the tag name)TextYes
3Description, the release notesTextNo
4Create the release? (summary)Yes/noYes
StepQuestionAnswerRequired
1Project nameTextYes
2DescriptionTextNo
3Visibility: private, internal or publicChoiceYes
4Initialize the repository with a README?Yes/noNo
5Default branch, asked only after a README (empty for the instance’s default)TextNo
6Create the project? (summary)Yes/noYes

The release name has to be answered, though the answer may be empty. A declined README question means no README, and then no default branch question either: GitLab applies a default branch on creation only together with a README, and a project created empty takes the instance’s default branch name, so the wizard skips step 5 and goes straight to the summary.

Why use a wizard instead of a single tool call?

Section titled “Why use a wizard instead of a single tool call?”

Wizards add safeguards that a single upfront call cannot, which is what makes them valuable for complex resources:

  • One field at a time: each form asks for a single value, so nothing has to be supplied all at once.
  • Validation at each step: an answer that does not fit its question is caught before the final API call.
  • Direct input: the user types each value into a form instead of the AI relaying it from chat.
  • User confirmation: the resource is created only after the user approves a summary.

Both kinds of action exist side by side:

AspectStandard actionWizard
InputThe AI provides every parameter at onceThe server asks the user, one question at a time
User interactionIndirect, through the AI chatDirect, through structured forms
ValidationWhen the call runsAt each answer, before going on
CancellationNot possible once calledAt any question
Best forAutomation, scripting, batch operationsInteractive creation, first-time users
AI context neededEvery parameter, upfrontOnly which wizard to call

Cancelling at any question, declining a required one, or answering no at the final review ends the flow before anything is sent to GitLab. The tool answers with a short message, such as Issue creation cancelled by user., and marks the result as an error (isError: true): the call produced none of the output its schema describes, and the message tells the model the user decided rather than that something failed.

An answer that does not fit the question asked (a missing field, a choice that was not offered) is a client fault rather than a decision: it is reported as an error, never as a cancellation, and the value is never used.

How does elicitation guard destructive actions?

Section titled “How does elicitation guard destructive actions?”

Elicitation is also used for confirmation prompts before destructive operations on the meta and individual surfaces. There a destructive call proceeds on the first of these that holds:

  1. GITLAB_MCP_YOLO_MODE is truthy, or, when it is unset, AUTOPILOT is.
  2. The call carries "confirm": true.
  3. The client supports elicitation, and the user approves the question.

A client that cannot elicit is refused with a message asking it to send the call again with confirm: true only after the user approves, and nothing reaches GitLab. On a 2026-07-28 session the question travels as one multi-round-trip input request.

The default dynamic surface never asks: gitlab_execute_action refuses an action classified destructive unless the call carries confirm: true or GITLAB_MCP_YOLO_MODE (or AUTOPILOT) skips the confirmation, as step 1 does on the other two surfaces. Only the two guards that depend on the arguments elicit there too. Destructive actions lists which actions count as destructive and describes both guards.

  • Every answer is checked against its question before the wizard uses it: a choice must be one of the options offered, a number must be a real number within its bounds, and a structured answer is validated against the JSON Schema it was asked with. An answer that fails is refused and never handed on.
  • The summary cannot be impersonated. Each value shown in the confirmation is escaped: line breaks collapse, link schemes are defanged (https[:]//), and Markdown inside the value is shown rather than rendered, so text that came from the model cannot pass itself off as the server’s own question.
  • Yes/no questions default to no, so a client that pre-fills defaults opens them on no.
  • The answers are bound to the call. On the multi-round-trip path the answers travel in requestState, which the server signs, ties to the tool and the exact arguments of the call, and accepts for 10 minutes. State that has expired, or was issued for another call, is ignored and the questions are asked again; state the server did not sign is refused. The signing key is created fresh in each process, so state issued before a restart, or by another replica behind a balancer, is refused rather than continued.
  • The user always has the last word. Every wizard confirms before it writes anything to GitLab, and the user can cancel at any point without side effects.

The MCP client must declare the elicitation capability as it connects, with form mode or with no mode named (which the protocol reads as form). The server reads that declaration on every call, so nothing needs configuring on this side, and the same server serves clients with and without it.

Which clients declare it changes from release to release. Today the documentation of VS Code (from release 1.102), Cursor and Claude Code lists elicitation as supported. For any other client, check its own documentation.

The wizard does not run. Its answer is an error result saying that the client does not support elicitation and naming the one action that does the same work with every field passed in the call. Each wizard names its own, by its catalog ID, and its description promises the same one:

WizardAlternative it names
gitlab_interactive_issue_createissue.create
gitlab_interactive_mr_createmerge_request.create
gitlab_interactive_project_createproject.create
gitlab_interactive_release_createrelease.create

The tool that runs the alternative depends on the surface: on the default dynamic surface it is gitlab_execute_action with the ID as action ({"action": "issue.create", "params": {...}}), on the meta surface the domain tool with action set to create (gitlab_issue, gitlab_merge_request, gitlab_project, gitlab_release), and on the individual surface a tool of its own (gitlab_issue_create, gitlab_mr_create, gitlab_project_create, gitlab_release_create). Functionality is preserved; only the interactive experience is lost.

Frequently asked questions

What is MCP elicitation?

Elicitation is an MCP capability that lets GitLab MCP Server pause and ask the user for input through structured forms rendered by the client. It powers wizard-style creation of complex resources such as issues, merge requests, releases, and projects. Rather than requiring all parameters upfront, the server collects fields one question at a time, checks each answer against what it asked, and confirms before creating the resource.

Which interactive wizard tools are available?

GitLab MCP Server provides four elicitation wizards: gitlab_interactive_issue_create (title, description, labels, confidentiality), gitlab_interactive_mr_create (source and target branch, title, description, labels, remove-source-branch and squash options), gitlab_interactive_release_create (tag name, release name, description), and gitlab_interactive_project_create (name, description, visibility, README initialization, and the default branch when a README is requested). The issue, MR and release wizards take the target project_id as a tool parameter, and each confirms with the user before performing the final GitLab API call.

What happens when a client does not support elicitation?

The wizard does not run, and its answer names the standard action that does the same work with every field passed in one call: issue.create for the issue wizard, merge_request.create for the merge request wizard, project.create for the project wizard and release.create for the release wizard. Only the step-by-step experience is lost. On the default surface the assistant runs that action through gitlab_execute_action; with GITLAB_MCP_TOOL_SURFACE=meta it is the domain tool with action: create, such as gitlab_issue.

Which MCP clients support elicitation?

A client supports it when it declares the elicitation capability as it connects, and the server reads that declaration on every call, so there is nothing to configure here. The documentation of VS Code (from release 1.102), Cursor and Claude Code lists elicitation as supported. Support changes from release to release, so for any other client check its own documentation.

Can a wizard change GitLab without my confirmation?

No. Every wizard ends with a yes/no review of the summary it assembled, and nothing reaches GitLab before you accept it. Every yes/no question starts on no, so an accidental Enter declines. Cancelling at any step, or answering no at the review, ends the flow without a GitLab call.