MCP vs. Function Calling vs. Plugins: What's the Difference?
Three Terms, One Underlying Problem
Function calling, plugins, and the Model Context Protocol (MCP) all try to solve the same core problem: letting a language model do something beyond generating text — call an API, query a database, read a file, or take an action in the real world. Because they solve overlapping problems, it's easy to conflate them. But they operate at different layers of the stack, and understanding those layers matters if you're architecting an AI agent rather than just prompting a chatbot.
Function Calling: A Model-Level Feature
Function calling (sometimes called 'tool use') is a capability built into the model's inference API. You send the model a list of function definitions — names, descriptions, and JSON schemas for their parameters — alongside your prompt. The model doesn't execute anything itself; it decides, based on the conversation, that a function should be called and returns a structured JSON object describing which function and with what arguments. Your application code is responsible for actually running that function and feeding the result back into the conversation.
This is a per-request, per-provider mechanism. OpenAI, Anthropic, Google, and others each implement their own flavor of function calling, with slightly different schemas and conventions. There's no standard way to discover what functions exist across a fleet of tools, no shared transport, and no persistent connection — it's just structured output plus a contract you build yourself. Function calling is the primitive; it's what makes tool use possible at the model level, but it says nothing about how tools are packaged, distributed, or discovered.
Plugins: An Early Attempt at Distribution
'Plugins' refers to an earlier pattern, popularized by ChatGPT's plugin system, for exposing third-party APIs to a model in a more distributable way. A plugin typically consisted of a manifest file and an OpenAPI specification describing available endpoints, hosted by the plugin developer. The host application would fetch this manifest, translate the OpenAPI operations into something resembling function definitions, and let the model choose which endpoint to call, similar in spirit to function calling but with a packaging and discovery layer on top.
The plugin model was tied tightly to a single vendor's ecosystem and its UI (an app store, installation flow, and manifest format specific to that product). It never became a cross-vendor standard, and most major providers have moved away from the term. Conceptually, though, plugins were an important stepping stone: they showed that developers wanted a reusable, shareable unit of 'a tool an AI can use' rather than reimplementing function schemas for every model and every app.
MCP: A Protocol, Not a Model Feature
The Model Context Protocol takes the idea plugins gestured at and formalizes it as an open, model-agnostic protocol. Instead of a manifest fetched by one specific chat product, MCP defines a client-server architecture: an MCP server exposes tools, resources, and prompts through a standardized interface, and any MCP-compatible client — a chat app, an IDE, a custom agent — can connect to it over a defined transport (stdio for local processes, or HTTP-based transports for remote servers).
Crucially, MCP separates concerns that function calling bundles together. The model still ultimately decides to invoke a tool, and that decision still surfaces as something resembling a function call. But the server side — what tools exist, their schemas, how they're versioned, how authentication works, how results are returned — is standardized and reusable across any client that speaks MCP. You write an MCP server once and it works with every compatible client, rather than writing bespoke function definitions and glue code for each provider's API.
MCP also goes further than a simple RPC mechanism: servers can expose 'resources' (readable context like files or documents) and 'prompts' (reusable prompt templates), and servers can be discovered and introspected at connection time rather than hardcoded into a system prompt. This makes MCP better suited to multi-tool, multi-agent environments where the set of available capabilities might change dynamically.
How They Actually Relate
It helps to think of these three concepts as different layers rather than competing standards. Function calling is the mechanism a model uses to express intent to call something — it's present inside MCP-based systems too, since the model still emits structured calls that match a tool's schema. Plugins were a product-specific packaging attempt that has largely been superseded. MCP is a transport and interface standard that sits between the model's function-calling behavior and the actual tool implementation, making the tool side portable across models and applications.
In practice, this means adopting MCP doesn't mean giving up function calling — it means your function definitions come from a standardized server instead of being hand-rolled per integration. If you've built five different tool integrations for five different AI products, each with its own schema quirks, MCP is the layer that lets you collapse that into one implementation.
Choosing an Approach in Practice
If you're building a single-provider application with a handful of internal functions, raw function calling is often simplest — there's no need for a server process or discovery protocol. If you're exposing tools that should work across multiple AI clients, or you want tool logic to live outside your prompt-engineering code entirely, MCP is the more durable choice, especially as more IDEs, agents, and chat clients add native MCP support.
This is exactly the gap our own product fills for document-heavy workflows: Document Analysis MCP is a hosted MCP server exposing summarize_document and find_red_flags tools, callable directly by any MCP-compatible AI client via subscription, without you having to write and maintain the extraction, chunking, and analysis logic yourself.
Whichever layer you're working at, the underlying goal is the same: give the model reliable, well-described access to real data and real actions, with enough structure that the results are predictable rather than improvised.