Completion

Completion is the SDK feature that lets an MCP server provide autocomplete suggestions while a user is filling in a prompt argument or a resource template variable. In this workflow the client owns the user interface, sends the partial value the user has typed, and receives a bounded suggestion list from the server. The server author only marks the relevant schema field as completable and supplies a callback that turns a prefix into candidate strings. This keeps ordinary prompt and resource validation intact while adding a user-friendly discovery path for values such as programming languages, repositories, branches, identifiers, or templated resource segments.

Sources: docs/servers/completion.md

Purpose and Scope

Use completion when a field has a known or discoverable vocabulary and you want the host to guide the user before the actual prompt or resource request is submitted. A prompt named for code review can complete a language field from a short static array; a pull request review prompt can complete a repository from an asynchronous lookup and then complete branches using the selected repository as context. The important boundary is that completion is advisory. The schema still validates the final argument value when the prompt or resource is invoked, so suggestions improve selection without becoming the only accepted values unless your schema also enforces that restriction.

Sources: docs/servers/completion.md

Completion is also distinct from server-to-client input requests. Elicitation asks the user a question during a running tool call, and the newer input_required flow returns embedded requests that a client fulfils before retrying the original call. Completion happens earlier, while the client is assembling a prompt argument or resource URI. That difference matters for server design: completion callbacks should be fast, side-effect-light lookup functions, while elicitation and input_required handlers participate in the execution of a request and must handle user decisions such as accept, decline, or cancel.

Sources: docs/servers/completion.md, docs/servers/elicitation.md, docs/servers/input-required.md

Relevant Source Files

  • docs/servers/completion.md — Primary how-to for server-side autocomplete, including completable prompt fields, async callbacks, contextual arguments, result truncation, and client-side invocation with client.complete.
  • docs/servers/elicitation.md — Contrasts completion with mid-call user input collected through ctx.mcpReq.elicitInput on older protocol connections.
  • docs/servers/input-required.md — Shows the 2026-era pattern for asking for input during tools, prompts, or resource reads, which is a separate lifecycle from autocomplete.
  • docs/servers/errors.md — Defines how prompt, resource, and completion callbacks should report invalid requests through protocol errors rather than tool-style error results.
  • docs/servers/logging-progress-cancellation.md — Provides context for request-scoped helpers such as progress, logging, and cancellation, which are not the main completion mechanism but inform long-running server behavior.
  • docs/servers/notifications.md — Explains change notifications and capability signaling for lists and resources, useful when comparing autocomplete with cache invalidation and subscription-oriented updates.

Core Primitives

The central server primitive is completable, imported from the server package alongside McpServer and, when resource variables are involved, ResourceTemplate. completable wraps a single schema field, such as a string inside a prompt argsSchema. The wrapped field continues to validate as the original schema, including descriptions that clients can show beside input controls, while the second argument supplies the completion callback. The first completable field also causes the high-level McpServer to register the completion/complete handler and advertise the completions capability, so application code does not need a separate capability declaration for the common path.

Sources: docs/servers/completion.md

A completion callback receives the typed prefix and returns every match as either a string array or a promise resolving to one. The SDK shapes that list into a completion result, truncating values to one hundred entries and filling total and hasMore so the client can present a clear bounded result. Returning the full match list is still the recommended callback contract because the SDK owns the wire-level limits. For static values, a simple prefix filter is enough; for dynamic values, the callback can await a repository, database, or service lookup and then apply the same filtering rule.

Sources: docs/servers/completion.md

System-to-Code Mapping

Reader taskSDK or protocol surfaceSource-backed behavior
Mark a prompt argument as autocompletablecompletable(schema, callback) inside argsSchemaThe schema validates as before, and the callback provides suggestions for that one field.
Expose completion supportFirst completable field on McpServerThe server registers completion/complete and advertises the completions capability automatically.
Complete from an async sourceCallback returning Promise<string[]>The callback can await a lookup such as a repository list and return matching strings.
Depend on another fieldCallback context argumentsThe optional second parameter can include already-filled arguments, such as using repo to choose branch suggestions.
Handle bad completion requestsProtocolErrorCompletion callbacks do not have a tool-style isError result channel, so invalid requests should be protocol errors.

Sources: docs/servers/completion.md, docs/servers/errors.md

The mapping above is intentionally focused on public server behavior rather than internal implementation details. As a server author, you usually do not need to hand-write the completion/complete JSON-RPC handler when using McpServer. You define the prompt or resource shape, wrap the fields that have useful suggestions, and let the SDK route client requests to the correct callback. This arrangement keeps the completion feature close to the data it describes: the autocomplete rule lives beside the schema field, and the prompt or resource callback still receives normal validated arguments once the user submits the request.

Sources: docs/servers/completion.md

Execution Flow

A typical flow starts when the server registers a prompt with an argsSchema that contains a completable language field. The host lists prompts, sees the argument metadata, and presents a form or command palette to the user. When the user types a partial value such as ty, the client sends a completion request naming the field and carrying the partial value. The server calls the field callback, filters the configured language list, and returns a result whose values include typescript. The client can then display that suggestion and later call the prompt with the chosen argument.

Sources: docs/servers/completion.md

Contextual completion adds one more step. In the pull request example, the repo field completes from an asynchronous repository list, while the branch field delegates to a function that reads the already supplied repo argument from the completion context. If no repository has been selected, the branch callback can return an empty list because it cannot determine the correct branch set. Once repo is filled with a value such as typescript-sdk, the branch callback can choose from that repository’s branch array and return only branches matching the current prefix.

Sources: docs/servers/completion.md

A compact prompt example follows the documented pattern: wrap one schema field, filter by prefix, and let the prompt callback consume the final value after normal validation.

import { completable, McpServer } from '@modelcontextprotocol/server';
import * as z from 'zod/v4';
 
const languages = ['typescript', 'javascript', 'python', 'rust', 'go'];
const server = new McpServer({ name: 'review', version: '1.0.0' });
 
server.registerPrompt(
  'review-code',
  {
    description: 'Review code for best practices',
    argsSchema: z.object({
      language: completable(z.string().describe('Programming language'), value =>
        languages.filter(language => language.startsWith(value))
      )
    })
  },
  ({ language }) => ({
    messages: [{ role: 'user', content: { type: 'text', text: `Review this ${language} code.` } }]
  })
);

Client Calls and Result Shape

The completion page frames its examples around client.complete on an in-memory Client connected to the server under test. That is the same protocol behavior an MCP host uses when a person is editing a prompt argument. For a prompt field, the client identifies the prompt argument and supplies the partial value. The server returns a completion object containing values, total, and hasMore. For the documented repository example, completing repo with the prefix ty returns a single value, reports a total of one, and marks hasMore false because the bounded result set contains every match.

Sources: docs/servers/completion.md

The result limit has a practical implication for user experience. If a backing system can produce thousands of matches, the callback should still return the matches according to the server’s chosen ordering, but authors should consider prefix filtering, permission filtering, and stable sorting before returning the array. The SDK truncates the wire values to one hundred entries, so the client receives a manageable list. total and hasMore let the client explain whether there are additional matches, but they do not replace the need for meaningful prefixes and context-sensitive narrowing on the server side.

Sources: docs/servers/completion.md

Error Handling and Operational Boundaries

Completion callbacks are closer to prompt and resource callbacks than to tool handlers. Tool handlers can return a normal result with isError true so a model can read the failure and recover, but resource, prompt, and completion callbacks have no such result channel. When a completion request is malformed or semantically invalid, the server should throw a protocol error such as an invalid-params error. This distinction keeps autocomplete failures at the protocol layer, where the client can repair the request or surface a UI error, instead of pretending that an autocomplete response is model-readable tool content.

Sources: docs/servers/errors.md

Completion should not be used as a substitute for notifications, progress, or cancellation. Notifications are one-way server pushes that tell clients a list or cached resource is stale, and list-changed notifications are tied to tools, prompts, and resources. Progress and cancellation live on the request context for long-running handlers and are driven by request metadata and cancellation signals. Completion is a request-response lookup initiated by the client while editing input. Keeping these mechanisms separate makes servers easier to reason about and helps hosts decide when to refresh lists, show progress, or display suggestions.

Sources: docs/servers/logging-progress-cancellation.md, docs/servers/notifications.md

Next Steps

After adding a completable field, test it from a client rather than only calling the prompt callback directly. The completion documentation explicitly uses an in-memory Client and client.complete to verify the result shape, which catches capability registration, handler wiring, and callback behavior together. Then exercise the final prompt or resource call with the completed value so schema validation and message generation are covered as well. If the lookup depends on another argument, include tests for missing context, unknown context, and a valid context that narrows the suggestions.

Sources: docs/servers/completion.md

Read the prompt and resource pages next for the request types that consume completed values, then read the client calling page for the host-side call patterns. If you are designing flows that ask for information after execution begins, use the elicitation and input_required pages instead of adding side effects to completion callbacks. For production servers, also review the errors page so invalid autocomplete requests become protocol errors, and the notifications page so changing prompt or resource inventories are announced through the correct mechanism rather than being hidden behind stale completion results.