No, that's wrong. The models have special syntax for function calls. They're not simply regular responses, they're special message types. You're partially right though: most models don't output or accept JSON, they have their own syntax internally. But that syntax is different for every model, and all the tools that invoke the models have parsers that convert it to the standard JSON+JSONSchema format. That's what vLLM and llama.cpp (or your tool of choice) are doing.
But that's irrelevant, because it's the tool call. The tool call is what invokes the HTTP client, not what's in the request payload. It could be asn.1 or RDF or TOML. JSON just happens to be convenient and universally supported. MCP could easily be implemented on literally anything you throw at it: that's an internal detail to your agent harness. That's not the point.
MCP is the OAS/WSDL/whatever contract described as tool calls instead of as network requests that the agent has to construct from scratch. Its whole purpose is to eliminate the whole layer of indirection.