Completions

The Model Context Protocol (MCP) provides a mechanism for servers to offer completion suggestions for prompt arguments and resource template URIs. This enables a richer user experience in client applications, such as IDEs or chat interfaces, by providing real-time suggestions as the user types.

Note

The MCP completion/complete protocol supports completions for prompts (via PromptReference) and resource templates (via ResourceTemplateReference). The CompleteReference variant in this SDK reflects the spec exactly — it does not include a tool reference type. Clients use a PromptReference or ResourceTemplateReference to identify what is being completed.

Overview

Completions are triggered by the client using the completion/complete request. The server responds with a list of possible values based on the current argument name and partial value provided by the client.

Key use cases include: - Auto-completing prompt argument values (e.g., programming language names, environment names). - Suggesting valid resource template URI components (e.g., file paths, identifiers). - Providing valid options for a configuration prompt.

Server-side Setup

To support completions, a server must register a completion provider using set_completion_provider(). This handler receives a CompleteParams object and returns a CompleteResult.

server.set_completion_provider([](const CompleteParams& params) -> Task<CompleteResult> {
    std::cout << "Server: Completion request for argument: " << params.argument.name << " = "
              << params.argument.value << "\n";

    CompleteResult result;

    // Provide completions based on argument name
    if (params.argument.name == "language") {
        // Language completions
        std::vector<std::string> languages = {"C++",        "C",    "Python", "JavaScript",
                                              "TypeScript", "Java", "Go",     "Rust",
                                              "Ruby",       "PHP"};

        // Filter by partial match
        std::string partial = params.argument.value;
        for (const auto& lang : languages) {
            if (lang.find(partial) == 0) {  // Starts with partial
                result.completion.values.push_back(lang);
            }
        }
    } else if (params.argument.name == "framework") {
        // Framework completions
        std::vector<std::string> frameworks = {"React", "Vue",    "Angular", "Django",
                                               "Flask", "Spring", "Express", "FastAPI",
                                               "Rails", "Laravel"};

        // Filter by partial match
        std::string partial = params.argument.value;
        for (const auto& fw : frameworks) {
            if (fw.find(partial) == 0) {  // Starts with partial
                result.completion.values.push_back(fw);
            }
        }
    }

    std::cout << "Server: Returning " << result.completion.values.size() << " completions\n";
    co_return result;
});

The handler typically inspects params.argument.name to determine which argument is being completed and uses params.argument.value to filter suggestions based on what the user has already typed.

CompleteParams

The CompleteParams structure provides the context for the completion request:

  • ref: A CompleteReference variant — either a PromptReference (type: "ref/prompt") or a ResourceTemplateReference (type: "ref/resource"). This identifies which prompt or resource template the argument belongs to.

  • argument: The specific argument name and its current partial value.

  • context: Optional additional context, such as values of other arguments already filled by the user.

CompleteResult

The server returns a CompleteResult containing:

  • values: A list of string suggestions.

  • total: (Optional) The total number of completions available if the list is truncated.

  • hasMore: (Optional) A boolean indicating if more completions can be retrieved.

Client-side Usage

Clients can request completions by calling client.complete(). This is typically done as the user interacts with a prompt or resource template interface.

std::cout << "\n--- Test 1: Language completions for 'C' ---\n";
CompleteParamsArgument lang_arg;
lang_arg.name = "language";
lang_arg.value = "C";

CompleteParams lang_params;
lang_params.ref = PromptReference{"ref/prompt", "code_analyzer"};
lang_params.argument = lang_arg;

auto lang_result = co_await client.complete(lang_params);
std::cout << "Client: Received " << lang_result.completion.values.size()
          << " language completions:\n";
for (const auto& val : lang_result.completion.values) {
    std::cout << "  - " << val << "\n";
}

Example Walkthrough

The completions example (examples/features/completions.cpp) demonstrates a full round-trip:

  1. Server Setup: The server registers a completion provider that knows how to suggest “language” and “framework” values for a prompt named code_analyzer.

  2. Client Request: The client simulates a user typing “C” for the “language” argument of that prompt, using a PromptReference.

  3. Server Response: The server filters its internal list and returns “C++” and “C” as suggestions.

  4. Result Handling: The client receives and prints the suggestions.

This flow allows clients to provide interactive, type-ahead style interfaces for MCP prompts and resource templates.