googleapis/mcp-toolbox · error

INVALID_REQUEST

INVALID_REQUEST

Error message

invalid server discover request: %w

What it means

serverDiscoverHandler unmarshals the request body into DiscoverRequest before doing anything else. If the JSON is malformed or doesn't match the expected shape (jsonrpc envelope with params), the wrapped error is returned as a jsonrpc INVALID_REQUEST error (internal/server/mcp/v20260728/method.go:173).

Source

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

		newMeta[k] = v
	}
	// copy the ResultMetaObject items over
	for k, v := range resMeta {
		newMeta[k] = v
	}
	return newMeta, nil
}

func serverDiscoverHandler(ctx context.Context, id jsonrpc.RequestId, body []byte, header http.Header) (any, error) {
	enableDraft, ok := util.EnableDraftSpecsFromContext(ctx)
	if !ok {
		err := fmt.Errorf("unable to retrieve enableDraftSpecs from context")
		return jsonrpc.NewError(id, jsonrpc.INTERNAL_ERROR, err.Error(), nil), err
	}

	var req DiscoverRequest
	if err := json.Unmarshal(body, &req); err != nil {
		err = fmt.Errorf("invalid server discover request: %w", err)
		return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, err.Error(), nil), err
	}
	validateHeaderErr, err := validateHeader(id, header, SERVER_DISCOVER, "")
	if err != nil {
		return validateHeaderErr, err
	}
	validateErr, err := validateMetadata(id, req.Params, header == nil)
	if err != nil {
		return validateErr, err
	}

	toolsListChanged := false
	promptsListChanged := false
	meta, err := getResultMetadata(ctx, nil)
	if err != nil {
		return jsonrpc.NewError(id, jsonrpc.INTERNAL_ERROR, err.Error(), nil), err
	}
	result := DiscoverResult{

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Validate the request body is well-formed JSON matching the JSON-RPC 2.0 structure with the correct params object.
  2. Log/print the raw body before sending to spot encoding issues (BOM, encoding, truncation).
  3. Use an official MCP client SDK to construct the request instead of hand-rolling JSON.
  4. Ensure Content-Type is application/json so no intermediary transforms the payload.

Example fix

// before
-d '{jsonrpc: 2.0, method: server/discover}'  // invalid JSON
// after
-d '{"jsonrpc":"2.0","id":1,"method":"server/discover","params":{}}'
Defensive patterns

Strategy: validation

Validate before calling

function buildDiscoverRequest() {
  const body = JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'server/discover', params: {} });
  JSON.parse(body); // throws early if serialization is broken
  return body;
}

Try / catch

try {
  const res = await discover();
} catch (e) {
  if (e.code === -32600) { // INVALID_REQUEST
    console.error('Malformed discover request:', e.message);
    // re-serialize and retry
  }
}

Prevention

When it happens

Trigger: POSTing a server/discover request whose body is not valid JSON, is empty, or has fields of the wrong type for DiscoverRequest (e.g. "params": "string" instead of an object).

Common situations: Hand-written curl/Postman requests with quoting mistakes; clients sending form-encoded or non-JSON payloads; a proxy truncating the body; JSON with BOM or trailing garbage.

Related errors


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