apache/shardingsphere · error · MCPInvalidRequestException

Completion argument `%s` is not declared for %s `%s`.

Error message

Completion argument `%s` is not declared for %s `%s`.

What it means

MCPCompletionService validates that the argument being completed is actually declared by the target completion descriptor (a tool's or prompt's declared argument list). If argumentName is not in descriptor.getArguments(), it throws MCPInvalidRequestException formatted with the argument name, reference type ('tool'/'prompt') and reference name. This guards against completion requests for arguments the referenced tool/prompt never declares.

Source

Thrown at mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/completion/MCPCompletionService.java:124

        Collection<MCPCompletionCandidate> candidates = handlerResult.getCandidates();
        int maxValues = Math.min(MAX_VALUES_LIMIT, 0 == descriptor.getMaxValues() ? DEFAULT_MAX_VALUES : descriptor.getMaxValues());
        List<MCPCompletionCandidate> filteredCandidates = candidates.stream().filter(each -> matchesPrefix(each.getValue(), prefix)).sorted(createCandidateComparator(prefix)).toList();
        String matchStrategy = "prefix";
        if (filteredCandidates.isEmpty() && !prefix.isEmpty()) {
            filteredCandidates = candidates.stream().filter(each -> matchesContains(each.getValue(), prefix)).sorted(createCandidateComparator(prefix)).toList();
            matchStrategy = "contains_fallback";
        }
        List<MCPCompletionCandidate> returnedCandidates = filteredCandidates.stream().limit(maxValues).toList();
        CompletionMetadataContext metadataContext = new CompletionMetadataContext(descriptor, argumentName, prefix, matchStrategy, actualContextArguments, handlerResult,
                filteredCandidates, returnedCandidates);
        Map<String, Object> meta = createMeta(metadataContext);
        return new MCPCompletionResult(returnedCandidates.stream().map(MCPCompletionCandidate::getValue).toList(), filteredCandidates.size(), filteredCandidates.size() > returnedCandidates.size(),
                meta);
    }
    
    private void validateDeclaredArgument(final MCPCompletionTargetDescriptor descriptor, final String argumentName) {
        if (!descriptor.getArguments().contains(argumentName)) {
            throw new MCPInvalidRequestException(String.format("Completion argument `%s` is not declared for %s `%s`.",
                    Objects.toString(argumentName, ""), descriptor.getReferenceType(), descriptor.getReference()));
        }
    }
    
    private void mergeInferredContextArguments(final Map<String, String> contextArguments, final Map<String, Object> inferredContextArguments) {
        for (Entry<String, Object> entry : inferredContextArguments.entrySet()) {
            if (Objects.toString(contextArguments.get(entry.getKey()), "").isEmpty()) {
                contextArguments.put(entry.getKey(), Objects.toString(entry.getValue(), ""));
            }
        }
    }
    
    private Comparator<MCPCompletionCandidate> createCandidateComparator(final String prefix) {
        String normalizedPrefix = prefix.toLowerCase(Locale.ENGLISH);
        return Comparator.comparingInt((MCPCompletionCandidate each) -> getExactMatchRank(each, normalizedPrefix))
                .thenComparing(this::compareUpdateTime)
                .thenComparing(each -> each.getValue().toLowerCase(Locale.ENGLISH))
                .thenComparing(MCPCompletionCandidate::getValue);

View on GitHub (pinned to e952770a21)

Solutions

  1. List the tool/prompt (tools/list, prompts/list) and use an argument name from its current declared arguments.
  2. Fix typos in argument.name so it matches the tool input schema exactly (case-sensitive).
  3. If the client caches schemas, refresh it after upgrading the MCP server.
  4. Server-side, add the missing argument to the tool descriptor if it was intended to be completable.

Example fix

// before
{ "method": "completion/complete",
  "params": { "ref": { "type": "ref/tool", "name": "database_gateway_execute_query" },
              "argument": { "name": "maxRow", "prefix": "1" } } } // typo -> error

// after
{ "method": "completion/complete",
  "params": { "ref": { "type": "ref/tool", "name": "database_gateway_execute_query" },
              "argument": { "name": "max_rows", "prefix": "1" } } }
Defensive patterns

Strategy: validation

Validate before calling

// Validate against the live tool/prompt schema before completing
const tools = (await mcp.request('tools/list')).tools;
const tool = tools.find(t => t.name === params.ref.name);
const declared = tool ? Object.keys(tool.inputSchema?.properties ?? {}) : [];
if (!declared.includes(params.argument.name)) {
  throw new Error(`argument '${params.argument.name}' not declared; choose from: ${declared.join(', ')}`);
}
return mcp.request('completion/complete', params);

Type guard

function isDeclaredCompletionArgument(toolsList, refName, argName) {
  const tool = toolsList.find(t => t.name === refName);
  return Boolean(tool) && Object.keys(tool.inputSchema?.properties ?? {}).includes(argName);
}

Try / catch

try {
  return await mcp.request('completion/complete', params);
} catch (e) {
  if (/is not declared for/.test(e.message)) { /* fix argument name from tools/list and retry once */ }
  throw e;
}

Prevention

When it happens

Trigger: Calling the completion/complete endpoint with ref.name='some_tool' and argument.name='foo' when some_tool's input schema does not declare an argument named 'foo' — usually a typo, a stale client hardcoding an argument that was renamed, or completing against the wrong reference.

Common situations: Argument renamed between MCP server versions while the client caches the old schema; misspelled argument names; copying a completion request example that targets a different tool; drifting tool schemas between environments.

Related errors


AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14). Data as JSON: /api/errors/28d50ee8702beb6b. Report an issue: GitHub.