MCP Isn’t Just Tool Calling Anymore

Jul 14 2026 · updated Jul 28 2026 · 14 min · Sieon

For a while, it was easy to explain the Model Context Protocol as “a standard way for AI agents to call tools.” That explanation was useful, but it is now too small.

The interesting part of MCP is no longer whether a model can invoke a function. Most agent systems can already do that. The harder question is whether an AI product can connect to many external systems without turning every integration into a custom, unsafe, unobservable adapter.

That is where MCP is becoming more important.

MCP is turning into the infrastructure boundary between an agent and the outside world. It gives teams a way to model context, actions, reusable workflows, user input, authorization, long-running work, and transport behavior through a shared protocol instead of through one-off glue code.

That shift matters because production agents fail less often at “calling a function” and more often at everything around the function:

Who approved this action?
Which server owns this capability?
Is this data context or an executable operation?
Can the model see this secret?
What happens if the tool takes five minutes?
Can the client reconnect safely?
Was the token scoped to this resource?
Can we audit what happened later?

Function calling answers only one part of that list. MCP is starting to cover the rest.

The old framing: MCP as tool calling

The most visible MCP primitive is the tool. A server exposes a list of tools, the client discovers them, the model chooses one, and the server executes it.

That maps cleanly to the mental model most developers already have from function calling.

Model decides it needs an action
    ↓
Host calls a named tool
    ↓
Tool returns a result
    ↓
Model continues

This is still useful. Tools are how agents query databases, call APIs, run calculations, create tickets, search files, or trigger internal workflows.

But if we stop there, we miss the reason MCP exists.

A production AI system does not just need actions. It needs safe access to context, structured workflows, permission boundaries, user confirmation, server discovery, streaming transport, reconnect behavior, and long-running execution. If every one of those concerns is implemented differently for every integration, the platform becomes impossible to govern.

That is why MCP should be treated as an integration protocol, not just a tool-call format.

Function calling vs MCP

A useful way to separate the two is this:

Function calling is an execution primitive.
MCP is an integration protocol.

Function calling usually means one application gives a model a list of callable functions. MCP defines a broader client-server relationship.

Dimension Function calling MCP
Main abstraction Functions the model can call Servers exposing protocol-defined capabilities
Typical owner One application or model runtime Independent MCP servers connected through a host
Discovery Often static or app-specific Standard capability discovery
Scope Mostly tool invocation Tools, resources, prompts, elicitation, sampling, transports, auth, notifications
Policy Built into the app Split between host policy and server enforcement
Best fit Small set of in-app actions Multi-system agent platforms

The difference becomes obvious when an AI product grows from one or two tools to dozens of systems: files, GitHub, Slack, Jira, Postgres, internal docs, observability, deployment systems, payment systems, and customer data.

At that point, the problem is no longer “can the model call create_ticket?”

The problem is:

Which server owns ticket creation?
What scopes does it need?
Should the user approve it?
Can the model read the ticket template as context first?
Is the output structured enough for another step?
Can this operation be retried safely?
Where is the audit trail?

MCP gives those questions a place to live.

The real MCP model: host, client, server

The official architecture separates MCP into three roles:

Host
= the user-facing AI application or agent runtime

Client
= the connector inside the host that maintains one session with one server

Server
= the external capability provider

A host might be an IDE, desktop assistant, chat product, automation agent, or internal developer platform. A server might expose filesystem context, GitHub operations, database metadata, Slack actions, deployment workflows, or a publishing system.

The important design point is that the model is not supposed to own the whole boundary.

A good host owns routing, policy, user consent, rendering, timeouts, and audit behavior. A good server owns capability definitions, input validation, access control, downstream API calls, and honest error reporting.

That separation is what makes MCP useful.

Model
    decides what it wants to do

Host
    decides what is visible, allowed, confirmed, logged, and safely rendered

MCP server
    owns the actual integration and enforces its own boundary

If you let the model decide whether a URL is safe, whether a token is scoped correctly, or whether a destructive tool should run, you have not built an MCP platform. You have built a prompt-controlled integration layer.

MCP has more than tools

The easiest way to misunderstand MCP is to treat every capability as a tool.

MCP has separate primitives because different things need different control models.

Resources
= context the application can read

Tools
= executable actions the model can invoke

Prompts
= reusable workflows the user can select

Elicitation
= structured user input requested by a server

Sampling
= server-requested model generation through the client

That distinction is not academic. It changes product behavior and security behavior.

Resources are context

Resources are for data the application or model can read: files, database schemas, runbooks, documents, issue descriptions, API docs, logs, or application state.

A database schema should usually be a resource, not a tool. The host can load it as context, summarize it, cache it, cite it, and pass it to the model before any query is executed.

Resource example:
db://warehouse/analytics/orders/schema

The model can inspect the schema without triggering side effects.

Tools are actions

Tools are for executable behavior: run a query, create a ticket, send a Slack message, deploy a service, fetch logs, or generate a report.

Tools need stronger policy. They may require user approval, role checks, input validation, timeouts, rate limits, and audit logs.

Tool example:
run_sql_readonly(query, max_rows)

Even a read-only tool can be sensitive. A query can leak data or create load. A production host should not treat every tool as equally safe.

Prompts are workflows

Prompts are reusable templates selected by the user. They are useful when a server knows a good workflow shape, such as incident review, deployment risk analysis, PR review, or customer escalation summary.

A prompt is not an action by itself. It is a user-controlled way to start a structured interaction.

Prompt example:
deployment_risk_review(service, environment)

If you hide every workflow as a tool, users lose visibility into what they are choosing.

Elicitation is user input

Elicitation lets a server ask the user for more information through the client.

This is important because servers often need human input before proceeding. Maybe the user needs to choose a region, confirm a risk level, enter a ticket priority, or select which account to connect.

The newer MCP direction makes a key distinction:

Form mode
= non-sensitive structured input

URL mode
= sensitive flows that must happen outside the agent UI

A server should not ask the MCP client to show a text field for an API key. Secrets, payment details, and downstream OAuth flows belong in URL mode, where the user is sent to a server-owned page and the client does not collect the secret.

That one distinction prevents a common security mistake: treating an agent chat UI as a safe place to gather credentials.

Sampling is model access through the host

Sampling lets a server request model generation from the client. This is useful when a server needs summarization or transformation but should not own model credentials directly.

The host still controls model choice, budget, review, and policy.

That matters because servers should not quietly become independent agent runtimes unless the host explicitly allows it.

Why the 2025-11-25 direction matters

The 2025-11-25 MCP revision is interesting because it continues the shift from demo protocol to production protocol.

The release is not just about adding more fields. It clarifies several seams that matter in real systems:

Area Why it matters
Authorization discovery Clients need to work with real identity providers instead of hand-coded issuer rules.
Client registration Public clients often connect to servers with no prior relationship.
Incremental consent Clients should request narrow scopes and escalate only when needed.
Elicitation modes Secrets should not be collected through the agent UI.
Tool metadata and schemas Large tool catalogs need consistent rendering and validation.
Tool execution errors Models need correctable errors, not opaque protocol failures.
Tasks Long-running operations need durable lifecycle semantics.
Streamable HTTP behavior Remote servers need safer reconnect, polling, and Origin handling.

The common thread is operational maturity.

MCP is becoming less about whether a tool call can happen and more about whether the system around that tool call can be trusted.

Authorization is now part of the product architecture

Authorization is one of the places where “just tool calling” falls apart.

A local toy agent can call a tool with whatever credentials the developer put in the environment. A production MCP client cannot work that way.

Protected MCP servers are OAuth resource servers. Clients need to discover protected resource metadata, locate authorization server metadata, request scoped tokens, and send audience-bound tokens to the right resource.

The newer direction improves that flow in three important ways.

First, clients need to support both OAuth Authorization Server Metadata and OpenID Connect Discovery. That makes real identity-provider integration less brittle.

Second, Client ID Metadata Documents give public clients a practical way to identify themselves without every server operator manually pre-registering them.

Third, WWW-Authenticate can carry scope guidance for the current request. That enables incremental consent.

The flow should look like this:

Client calls a tool with current token
    ↓
Server says: this operation needs files:write
    ↓
Client discovers auth metadata
    ↓
Client asks user for that narrow scope
    ↓
Client retries with an audience-bound token

That is much safer than asking for every possible scope during onboarding.

Incremental consent is not just better UX. It reduces blast radius. A broad token is convenient until it leaks, gets logged, or is misused by a compromised integration.

URL elicitation fixes a subtle credential problem

A common agent anti-pattern is asking the user to paste secrets into a chat or form.

Please paste your GitHub token here.
Please enter your API key.
Please type your payment credentials.

That is not a safe interaction model.

MCP’s form and URL elicitation split is a clean way to draw the boundary.

Use form elicitation for non-sensitive structured input:

Choose a region.
Pick a risk level.
Enter a ticket title.
Confirm a reason.

Use URL elicitation for sensitive workflows:

Connect a GitHub account.
Authorize a SaaS integration.
Enter payment details.
Complete a vendor login.

In URL mode, the MCP client should show the destination domain and ask the user to approve navigation. The secret entry happens on the server-owned or provider-owned page, not inside the agent UI.

The server still has to do real security work. It must bind the browser interaction to the same user who initiated the MCP request. It must prevent open redirects. It must not let one user’s generated URL attach credentials to another user’s session.

But the primitive gives teams the right shape.

Tasks are the missing shape for long-running tools

Many early MCP tools behave like simple functions.

request in
result out

Production operations often do not fit that shape.

Index a repository
Export a warehouse table
Run a vulnerability scan
Generate a video
Replay a test suite
Run a deployment check

These operations may take minutes. They may need progress updates, cancellation, retry behavior, and result retrieval after reconnect.

That is why task support matters, even if teams adopt it gradually.

A long-running operation needs:

stable operation id
idempotent start behavior
durable progress states
separate result retrieval
explicit cancellation
safe retry semantics

MCP should not replace your queue. Your internal job system should still own execution. MCP should expose the lifecycle in a way clients and users can understand.

That is the production pattern: queue inside, protocol outside.

Tool errors should help the model recover

Another small but important distinction is protocol error vs tool execution error.

If the JSON-RPC method is invalid, that is a protocol error.

If the model called a valid tool but forgot a required business field, used a bad date, or supplied a query that violates a read-only policy, that should usually be a tool execution error.

Why?

Because the model can often correct it.

Bad:
Protocol error: invalid request

Better:
Tool execution error: query must be a SELECT statement over approved analytics views.

The second response gives the model a chance to repair the call. It also gives the user a clearer explanation.

This distinction becomes important when agents chain multiple operations. If every recoverable problem looks like a protocol failure, the host cannot tell whether to retry, ask the user, repair arguments, or stop.

Tool schemas should be boring and strict

Tool schemas are not documentation. They are contracts.

A production MCP server should prefer predictable names, explicit input schemas, output schemas where possible, and strict no-argument tool schemas.

For example, a no-parameter health tool should still declare an object schema:

{
  "name": "system.health",
  "description": "Return a lightweight health summary for the MCP server.",
  "inputSchema": {
    "type": "object",
    "additionalProperties": false
  }
}

This looks boring, which is the point.

Boring schemas make tool catalogs easier to render, validate, cache, and audit. They also reduce the chance that different clients interpret the same tool differently.

In large agent platforms, schema consistency is not polish. It is operational safety.

The architecture I would use

A production MCP platform should be designed around separation of responsibility.

User-facing host
    owns policy, consent, routing, rendering, logs, and model context

MCP client session
    owns connection lifecycle, capability negotiation, retries, and transport state

MCP server
    owns integration logic, schemas, access control, validation, and downstream APIs

External system
    remains behind the server-owned boundary

A useful mental model looks like this:

                 ┌────────────────────┐
                 │        Host        │
                 │ policy + consent   │
                 │ model context      │
                 └─────────┬──────────┘
                           │
              MCP client sessions
                           │
        ┌──────────────────┼──────────────────┐
        ▼                  ▼                  ▼
┌──────────────┐   ┌──────────────┐   ┌──────────────┐
│ Docs Server  │   │ Git Server   │   │ Deploy Server│
│ resources    │   │ tools        │   │ tools/tasks  │
└──────┬───────┘   └──────┬───────┘   └──────┬───────┘
       ▼                  ▼                  ▼
  Search index          GitHub          Internal platform

The model can reason across these capabilities, but it should not own the boundaries. The host and servers do.

Common migration mistakes

Treating every capability as a tool

This makes the system harder to govern. Context becomes actions, workflows become hidden functions, and user input becomes tool arguments.

Model context should usually start as resources. Repeatable user-selected workflows should be prompts. Executable behavior should be tools.

Requesting every OAuth scope up front

This is convenient for developers and bad for users. Start narrow. Escalate only when a privileged operation requires it.

Using form elicitation for secrets

Do not collect API keys, access tokens, passwords, or payment credentials through an agent UI. Use URL elicitation and a server-owned flow.

Forwarding MCP bearer tokens downstream

An MCP server that calls another API should use a proper downstream authorization flow. Passing the MCP client’s bearer token to another service is usually an audience-boundary failure.

Returning protocol errors for fixable tool inputs

If the model can correct the arguments, return a tool execution error with actionable text.

Assuming a disconnected stream means cancelled work

Network disconnects happen. Long-running work needs explicit cancellation and durable state.

Skipping Origin validation for local HTTP servers

Local Streamable HTTP servers can be exposed to browser-based attacks such as DNS rebinding. Validate Origin headers and bind narrowly.

How this maps to Hermes-style agents

Hermes is a good example of why MCP should not be treated as only tool calling.

In a Hermes-style workflow, the agent may use built-in tools for filesystem access, browser automation, terminal commands, scheduled jobs, memory, and delegation. It may also use MCP servers for external systems such as publishing, documents, or custom infrastructure.

The useful pattern is not “the model has more functions.”

The useful pattern is that each capability has an owner.

For example, a publishing workflow can look like this:

Hermes agent
    ↓
Forge MCP tools
    ↓
Canonical markdown store
    ↓
WordPress draft
    ↓
Human review
    ↓
Explicit publish action

The model can request that an article be saved or updated, but the Forge system owns canonical state, WordPress IDs, draft status, preview URLs, divergence checks, and publish behavior.

That is exactly the kind of boundary MCP is good at.

The model should not hand-edit WordPress through random HTTP calls when a publishing server can expose safer operations with clear status and audit trails.

Practical rollout order

If I were upgrading an MCP platform, I would use this order:

  1. Inventory servers, tools, resources, prompts, and trust levels.
  2. Separate context resources from executable tools.
  3. Add host-side policy for risky tools.
  4. Tighten tool schemas and output contracts.
  5. Audit authorization: resource metadata, audience validation, scopes, and token separation.
  6. Add incremental scope challenges instead of broad onboarding scopes.
  7. Split elicitation into form and URL paths, then ban secrets from form mode.
  8. Put long-running tools behind durable internal jobs.
  9. Expose task lifecycle once your client and SDK stack can use it safely.
  10. Improve observability: user, server, tool, arguments after redaction, approval state, duration, result size, and error class.

That order reduces risk before it adds surface area.

Final take

MCP started with a simple pitch: connect AI applications to tools and data sources through a standard protocol.

That pitch is still true, but it understates what is happening.

MCP is becoming the control boundary for agent infrastructure. It separates context from actions, workflows from tools, user input from model output, and authorization from prompting.

That is why the phrase “MCP is tool calling” is no longer enough.

Tool calling is one primitive. MCP is the platform contract around it.

The teams that get the most value from MCP will not be the ones that expose the largest tool list. They will be the ones that design the cleanest boundaries: resources for context, tools for actions, prompts for workflows, elicitation for user input, tasks for long-running work, and host policy for everything the model should not decide by itself.

That is the difference between an agent demo that can call a function and an agent platform you can operate.

References

  1. Model Context Protocol 2025-11-25 changelog
  2. MCP Authorization
  3. MCP Elicitation
  4. MCP Tools
  5. MCP Streamable HTTP transport
  6. MCP Resources