Last reviewed: 2026-09-02
Direct answer
Treat every MCP elicitation as a privileged, user-mediated boundary in a CometAPI coding-agent adapter. Declare only the modes the client really implements, show the requesting server and its reason, validate form responses against the restricted schema, and direct sensitive interactions through an approved URL-mode flow. A model should never silently accept a prompt, navigate to an unexamined host, or turn elicited content into an automatic side effect.
For the current MCP 2026-07-28 lifecycle, include supported form and URL modes in _meta.io.modelcontextprotocol/clientCapabilities on each request. When a server needs input, that call completes with an InputRequiredResult containing an elicitation/create request. After the user acts, the client issues a new request carrying the corresponding inputResponses and preserved requestState. Do not implement this current flow as a tool call waiting on a server-initiated back-channel response.
The MCP client elicitation specification separates form mode from URL mode. Form mode collects non-sensitive structured values in the client and can use a limited JSON Schema. URL mode sends the user to an external destination for sensitive interactions such as authentication or payment. The client receives consent to start that flow, not the secret and not proof that the flow finished. That distinction should shape the adapter contract, user interface, new-request cycle, and logs.
Keep the provider boundary explicit in a CometAPI-backed setup. The CometAPI Codex integration guide describes a named provider, a Responses wire API, and command- or environment-backed authentication. Elicitation state is a separate concern: a request for a third-party credential must never be copied into the provider key store, a prompt transcript, or a model context window.
A safe decision rule is straightforward. Accept only after the user sees who is asking, what is needed, where data will go, and what happens next. Decline when the request is unnecessary or overly broad. Cancel when the user abandons the operation or a timeout expires. On validation or transport error, stop the dependent action and retain enough sanitized evidence for an operator to investigate.
Who this is for
This guide is for engineers who run Codex or another coding agent through CometAPI and connect it to MCP servers that can ask questions during tool workflows. It is useful when a server needs a project choice, a destructive-action confirmation, an OAuth handoff, or another value that was not known when the operation began.
It is also for platform and security teams reviewing the client adapter rather than the MCP server itself. You will benefit if you own the consent screen, per-request capability metadata, pending request state, URL policy, structured logging, or incident response around agent runs. The article assumes you can change an MCP client or gateway wrapper and can require a human approval step; it does not assume a particular programming language or UI framework.
If your workflow only sends static prompts to a model and never invokes MCP tools, elicitation is not in your execution path. If you already have an MCP client, use the contract and workflow below as a focused review checklist. A successful demo is not evidence that protocol-version boundaries, sensitive requests, retries, and cancellation are safe.
Key takeaways
- For MCP 2026-07-28, declare supported elicitation modes in
_meta.io.modelcontextprotocol/clientCapabilitieson every request, not only during initialization. - Treat an
InputRequiredResultas completion of the current call. Collect the user action, then issue a new request withinputResponsesand the preserved state expected by the server. - Keep form mode for reviewable, non-sensitive values. Do not ask for passwords, API keys, access tokens, or payment credentials in an in-band form.
- Use URL mode for sensitive or third-party authorization flows. Show the exact destination host, obtain explicit consent, and do not claim that acceptance means the external flow completed.
- Model all three actions: accept, decline, and cancel. Give each a distinct operational consequence.
- Treat schemas, messages, URLs, response content, and state as untrusted input. Validate them before issuing the next request or allowing side effects.
- Log the event envelope and decision evidence, not secrets, raw form answers, authorization codes, complete URLs, query strings, or state blobs.
- Keep handshake-era blocking elicitation in a separate version branch. Do not apply its back-channel lifecycle to modern requests.
- For URL mode, provide manual retry and cancellation. A completion notification may exist in a particular SDK or protocol-era implementation, but it is not a portable prerequisite.
For a broader release gate, pair this workflow with the site’s production-readiness review for AI coding-agent workflows . For source freshness and citation checks, see CometAPI source-evidence checks for agent tutorials .
Sources checked
The protocol contract comes from the MCP client elicitation reference
. It defines per-request capability metadata, form and URL request fields, the InputRequiredResult message pattern, response actions, preserved state, manual URL-flow controls, and client-facing safety expectations. Use it as the authority for the current wire lifecycle.
The FastMCP elicitation guide makes the protocol-era split explicit. Its handshake-era path can pause a running tool and use a session back-channel, while its modern 2026-07-28 guard pattern completes each round and has the client issue another call with the answer. This distinction is useful for compatibility tests, but application code should branch on the negotiated protocol version rather than blending the two paths.
The MCP-Go elicitation guide provides an independent implementation view: capability registration, mode-specific validation, client handlers, timeout handling, response actions, and a completion-notification API for its URL workflow. Treat that notification as an SDK-specific implementation mechanism. The portable 2026-07-28 client behavior remains preserving state and offering retry or cancellation when completion is not directly known.
The MCP security best-practices guide supplies the threat model for consent, token boundaries, SSRF, redirect and state validation, and exfiltration. Apply those controls to the adapter and any proxy between the coding agent and the MCP server.
Finally, the CometAPI Codex integration documentation anchors the provider-specific part of this article: user-level provider configuration, Responses transport, model selection, and command- or environment-backed key handling. Recheck that guide whenever your Codex integration changes; do not infer MCP elicitation behavior from provider setup alone.
Contract details to verify
For MCP 2026-07-28, construct the client capability metadata from tested features and attach it to every request under _meta.io.modelcontextprotocol/clientCapabilities. If the client supports only forms, declare only form mode. If it supports forms and URLs, verify that its interface can show the server identity, message, form fields, and target host before declaring both. An empty elicitation capability means form-only support for backward compatibility; avoid relying on that shorthand when explicit modes make audits clearer.
Keep protocol-era handling separate. On a current connection, the server returns an InputRequiredResult, the current call ends, and the client later issues a new request with the user’s response and preserved state. On a handshake-era connection, an SDK may support a blocking ctx.elicit() back-channel that pauses and resumes a running tool. Detect the protocol version and call the matching adapter path. Returning a modern guard result to an older path, or invoking a blocking elicitation API on the modern path, should fail clearly rather than fall through to an unsafe fallback.
For form mode, require a human-readable message and a requested schema. The supported schema is intentionally narrow: a flat object with primitive properties, including strings, numbers or integers, booleans, and constrained enum choices. Enforce required fields, length or numeric limits, formats you claim to understand, and the allowed property set. Reject nested objects or unsupported schema constructs instead of passing them to a permissive renderer. Display defaults as suggestions, never as invisible consent.
For URL mode, require the mode, message, and a valid URL. Parse it with a strict URL library, reject malformed values, and apply an explicit host and scheme policy before showing it. The security guidance calls out SSRF and authorization URL validation; the client should not fetch the URL merely to preview it. Display the host and meaningful path to the user, prevent deceptive rendering, and require deliberate navigation approval. Never append a secret, token, password, credential, or authorization code to an example or operational URL.
Separate consent from completion. An accepted URL-mode response means the user agreed to begin the out-of-band interaction. The client may not learn directly when that interaction finishes. Preserve the bounded request state, expose manual retry and cancellation, and let the server determine completion when the client issues the new request. The server can return its final result or another InputRequiredResult if the external work is still incomplete. If an SDK supplies a completion notification, treat it as an implementation-specific hint that can enable a retry, not as universal proof of success.
Bind pending state to the relevant session and user, expire it, and prevent unsafe reuse. Keep raw requestState out of ordinary logs because it is server-controlled data. Do not put provider credentials, raw elicited content, or external-flow data into the CometAPI request context.
Use an adapter contract that makes decisions observable without making sensitive data observable. A minimal event can look like this:
protocol_version=2026-07-28
event=mcp_elicitation
run_id=run-2026-09-02-001
server_id=repo-tools
mode=form
request_round=2
state_present=true
schema_fingerprint=[REDACTED]
action=accept
validation=passed
next_request=issued
reason=none
The identifiers and fingerprint above are placeholders, not credentials. In production, use generated identifiers that are not derived from secrets. Redact or hash values before logging. Do not log form content, the full URL, query strings, cookies, authorization codes, key material, or the state blob. Keep a bounded reason code such as unsupported_mode, invalid_schema, host_not_allowed, user_declined, user_cancelled, timeout, retry_available, or completion_pending. Set retention and access controls for these event records as you would for other agent-run telemetry.
Verify the new-request contract explicitly. For a form response, validate accepted content before placing it in inputResponses; for decline or cancel, preserve the action without inventing content. Issue the next request with the state required to correlate the round, and make any side-effecting operation idempotent. For URL mode, an accepted action starts the external interaction. A user-controlled retry sends the preserved response and state so the server can decide whether to finish or request more input.
Failure modes
Missing per-request capability metadata is an early, recoverable failure. A client may advertise support only during initialization, omit the current request metadata, or declare URL mode without a safe URL interface. Fail closed, return a clear capability error to the operator, and do not silently downgrade a sensitive request into a form.
Protocol-era confusion can duplicate or strand work. A modern call may be left open waiting for a back-channel response that will never arrive, while an older connection may receive a guard result it cannot process. Branch on the negotiated protocol version, test each supported path independently, and record the version with every elicitation event. Never retry a side-effecting tool solely because the adapter confused a completed modern round with an interrupted call.
Schema drift can turn a harmless form into an unsafe one. A server may send a nested schema, an unexpected property, an impossible bound, or a default that the renderer interprets incorrectly. Reject the request before display, record the schema error code and fingerprint, and ask the server owner to update the contract. Never coerce arbitrary fields into a tool argument just because parsing succeeded.
A malicious or compromised server can supply a look-alike URL, an internal address, or a redirect chain. This is an SSRF and phishing concern, not merely a user-experience defect. Apply scheme and host allowlists, evaluate redirects under policy, block private or link-local destinations where appropriate, and show the final approved host before navigation. If validation fails, cancel the dependent operation and preserve only the host-policy reason, not the complete attacker-controlled URL in ordinary logs.
Consent confusion is another common failure. An agent may phrase an elicitation as an instruction, preselect an approval control, or retry after a decline until the user gives up. Make accept, decline, and cancel separate controls, show the requesting server, and stop automated repetition after a bounded policy. A decline should produce a non-sensitive outcome; a cancel or timeout should end the pending round and release local state.
State and completion races occur when a user finishes a browser flow while the client holds pending request state, or when two retries reuse the same state. Bind state to one interaction, enforce expiration and single-use rules where appropriate, and make the next operation idempotent. If completion is unknown, show completion_pending and offer manual retry or cancellation. Never assume success because navigation occurred or because an SDK emitted a notification.
Provider-boundary leakage can happen when an adapter forwards form content into a CometAPI prompt, writes it beside the provider key, or includes it in telemetry. Keep provider configuration, MCP state, and tool arguments in separate stores with least-privilege access. If a leak is suspected, stop the run, rotate affected credentials through the approved process, and retain a sanitized incident record. The MCP security guidance’s token-audience and exfiltration warnings still matter when CometAPI is only the model transport.
A practical happy-path and error-path operator workflow for MCP 2026-07-28 is:
1. Send the request with tested form or URL capabilities in the required metadata.
2. If the server returns InputRequiredResult, mark the current call complete and retain bounded state.
3. Validate the mode, message, schema, or URL policy before showing anything to the user.
4. Happy form path: collect accept, validate content, and issue a new request with response and state.
5. Happy URL path: record consent, open the approved host, and expose manual retry and cancel controls.
6. On retry, issue the new request with response and state; let the server finish or request more input.
7. Error path: decline, cancel, timeout, unsupported mode, invalid schema, or blocked host stops side effects
and records a bounded reason without raw content, complete URLs, or state blobs.
8. If an older connection is supported, route it to a separately tested handshake-era adapter.
Exercise every branch with a disposable MCP server or test fixture. Assert that no side-effecting operation runs after a decline, cancel, validation error, or timeout. Assert that repeated modern requests are idempotent. If an SDK exposes completion notifications, test them as hints and verify that duplicate notifications cannot trigger duplicate work.
FAQ
Does modern elicitation keep a tool call open?
No. In the MCP 2026-07-28 flow described by the current specification, the call completes with an InputRequiredResult. The client gathers the user’s action and issues a new request with inputResponses and preserved state. A blocking, mid-execution back-channel belongs to the older handshake-era path and should live behind a separate protocol-version branch.
Can a form ask for an API key if the field is masked?
No. Masking changes presentation, not exposure. The MCP contract reserves form mode for data the client can safely receive and inspect. Sensitive credentials belong in URL mode or another separately governed secret-entry flow. Keep the value out of model context and logs.
Does accepting a URL elicitation prove authentication succeeded?
No. Acceptance records consent to start the out-of-band interaction. The client may not be directly informed when it finishes. Provide manual retry and cancellation; on a retried request, the server determines whether to return the result or another input-required response.
Is a completion notification required for URL mode?
No. An SDK may provide a completion-notification mechanism, but that is implementation- or protocol-era-specific. The portable current flow must work when no notification arrives by preserving state and giving the user explicit retry and cancellation controls.
Should the client fetch or scan the elicitation URL first?
Do not make an automatic server-side request just to preview an untrusted target. Validate syntax and policy locally, show the destination clearly, and let the user decide. If your organization performs reputation or allowlist checks, run them through a controlled service that cannot reach protected networks and does not send credentials.
What should happen after a decline?
The current round should preserve the decline action for the next protocol request where required, and the operation should end without side effects. A later, user-initiated attempt can begin a fresh interaction. Do not loop automatically or reuse stale approval state.
How does CometAPI change the elicitation contract?
CometAPI provides the model-provider path for the coding agent; it does not replace MCP’s client consent or request-lifecycle contract. Keep the provider configuration and key handling documented by CometAPI separate from MCP requests, and test the adapter at the protocol boundary before changing models or wire settings.
Reader next step
Add one elicitation test harness to your next agent integration run. For MCP 2026-07-28, assert that capabilities appear on every request, each input-required round completes, and the user response travels on a new request with preserved state. Cover a valid non-sensitive form, an unsupported mode, a rejected schema, a blocked host, each of accept, decline, and cancel, a URL flow that remains pending, manual retry and cancellation, and an idempotent completion attempt. If you support an older handshake-era connection, test it as a separate adapter path.
Also assert that every error path stops side effects and that logs contain the protocol version, identifiers, round number, state presence, action, validation result, and bounded reason—but no form content, complete URLs, sensitive query data, state blobs, or credentials.
Then review the evidence with your team’s release checklist and document who owns capability declarations, protocol-version routing, host policy, consent copy, state expiry, and incident response. When you are ready to evaluate a CometAPI-backed coding-agent setup, use Start with CometAPI . Keep the elicitation policy beside the provider configuration, rerun the tests whenever either changes, and make a human reviewer the final authority for sensitive actions.