googleapis/mcp-toolbox · error

parameter %q is not secure and must not be passed in secureA

Error message

parameter %q is not secure and must not be passed in secureArguments

What it means

validateAndMergeSecureParams rejects secureArguments entries whose names do not correspond to a parameter marked secure. This is a protocol-level error (nil agent error, protocol error returned) — the client is misusing the secureArguments channel for a regular parameter.

Source

Thrown at internal/server/mcp/v20260728/method.go:898

	urlParams, _ := util.UrlParamsFromContext(ctx)

	for _, p := range paramDefs {
		if p != nil && p.GetSecure() {
			secureParamMap[p.GetName()] = true
		}
	}

	// Validate that secure parameters are not passed in standard arguments (Agent error)
	for argName := range req.Params.Arguments {
		if secureParamMap[argName] {
			return nil, fmt.Errorf("parameter %q is secure and must not be passed in standard arguments", argName), nil
		}
	}

	// Validate that non-secure parameters are not passed in secureArguments (Protocol error)
	for argName := range req.Params.SecureArguments {
		if !secureParamMap[argName] {
			return nil, nil, fmt.Errorf("parameter %q is not secure and must not be passed in secureArguments", argName)
		}
	}

	// Validate that required secure parameters are present in secureArguments (Protocol error)
	for _, p := range paramDefs {
		if p != nil && p.GetSecure() {
			name := p.GetName()
			if p.GetValueFromParam() == "" {
				if _, bound := urlParams[name]; !bound {
					if parameters.CheckParamRequired(p.GetRequired(), p.GetDefault()) {
						if req.Params.SecureArguments == nil {
							return nil, nil, fmt.Errorf("missing required secure parameter %q in secureArguments", name)
						}
						if _, ok := req.Params.SecureArguments[name]; !ok {
							return nil, nil, fmt.Errorf("missing required secure parameter %q in secureArguments", name)
						}
					}
				}

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Remove the non-secure parameter from params.secureArguments and pass it in params.arguments instead
  2. Verify the tool's parameter definitions in tools.yaml match what the client sends (name and secure flag)
  3. Update the client so only parameters with secure: true go into secureArguments

Example fix

// before
{"params": {"arguments": {}, "secureArguments": {"query": "SELECT 1"}}}  // query is not secure
// after
{"params": {"arguments": {"query": "SELECT 1"}, "secureArguments": {}}}
Defensive patterns

Strategy: validation

Validate before calling

const secureNames = new Set(toolParams.filter(p => p.secure).map(p => p.name));
for (const key of Object.keys(secureArgs)) {
  if (!secureNames.has(key)) throw new Error(`"${key}" is not secure; move it to arguments`);
}

Type guard

function secureArgsOnlyContainsSecure(secureArgs, secureNames) {
  return Object.keys(secureArgs).every(k => secureNames.has(k));
}

Try / catch

try {
  await mcp.toolsCall({ name: tool, arguments: args, secureArguments: secureArgs });
} catch (e) {
  if (/is not secure and must not be passed in secureArguments/.test(e.message)) {
    const key = e.message.match(/parameter "([^"]+)"/)?.[1];
    args[key] = secureArgs[key]; delete secureArgs[key]; // retry correctly split
  } else { throw e; }
}

Prevention

When it happens

Trigger: A tools/call request includes params.secureArguments containing a key that maps to a non-secure parameter (or an entirely unknown parameter) of the invoked tool.

Common situations: Client blanket-copies every argument into secureArguments after learning about the extension; parameter definitions changed in tools.yaml so a formerly-secure param is now plain; typo in a secure parameter name making it unresolvable in secureParamMap.

Related errors


AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05). Data as JSON: /api/errors/cf8720a94ad890d8. Report an issue: GitHub.