Spurlock Studios
Contact
Share LinkedIn X
A scuffed work smartphone with a blank glowing circular button. Thesis: MCP NATIVE FUNCTION CALLING PORTABILITY.

MCP vs function calling is a boundary decision, not a religion. Native function calling wins when tools live inside one agent loop you own. MCP earns its overhead when the same capabilities must be discovered, scoped, and reused across hosts — IDEs, desktops, and your production agent — without rewriting the integration each time.

This spoke belongs to the Agentic Systems Operating Manual. Pair it with tool schemas agents follow: protocol choice does not replace a schema the model can obey.

The short answer

  • Native function calling = provider feature (tools/functions on the model API). Shortest path inside one app.
  • MCP = open protocol for hosts to talk to tool/context servers. Not an orchestration framework.
  • Pin three roles: host (the AI app), client (one connection per server), server (where tools actually run).
  • Default for one agent, few private tools: native function calling + your policy gate.
  • Reach for MCP when multiple clients share tools, credentials must stay behind a server boundary, or discovery/governance matters.

What is MCP architecturally?

The 2026-07-28 MCP specification is an open protocol for exchanging context between LLM applications and external tools. The architecture overview is explicit: MCP does not tell you how to loop the model, branch, or evaluate. It only standardizes how a host talks to servers.

RoleWhat it isExample
MCP HostAI application that coordinates clientsClaude Desktop, VS Code, your agent worker
MCP ClientConnection object the host creates per serverOne client ↔ filesystem; another ↔ CRM
MCP ServerProgram that exposes tools, resources, promptsLocal stdio process or remote Streamable HTTP service

If someone says “we rewrote our agent in MCP,” they usually mean “we exposed tools over MCP.” The loop is still yours. The host still decides when to call the model. The server still executes the side effect.

MCP’s own scope note is the whole argument against treating it as a framework swap: it focuses on context exchange. Control flow stays in the host.

How do host, client, and server actually connect?

The architecture docs walk a VS Code example: the editor is the host; connecting to Sentry instantiates one client; connecting to a local filesystem server instantiates a second client. One host, many clients, one client per server. Remote servers using Streamable HTTP typically serve many clients. Local stdio servers typically serve one.

FactWhy it matters in production
Client is 1:1 with a serverYou do not “have MCP.” You have N connections.
Host owns coordinationPolicy, HITL, and the model loop live here
Server owns executionSecrets and side effects belong here
Same JSON-RPC on every transportTransport is a pipe, not a new product

Messages follow JSON-RPC 2.0. The base protocol requires a string or integer request id — not null — and defines result vs error responses. That is a wire contract. It is not an agent runtime.

Pin the three nouns on a whiteboard before you pick a library. Most “MCP vs tools” arguments collapse once those roles are named.

What does native function calling actually do?

OpenAI’s function calling guide calls the same idea tool calling. You declare functions on the request. The model may return a structured tool call. Your application executes it. You send the output back. Repeat until the model answers in prose.

Anthropic’s tool-use overview splits the same loop into client tools (you execute, then return a tool_result) and server tools (Anthropic executes web_search / code_execution on their infrastructure). Client tools are the native-function-calling cousin. Server tools are a vendor-hosted helper. Neither is MCP.

StepOpenAI function / tool callAnthropic client tool
1Send tools with JSON Schema parametersSend tools with input_schema
2Model returns a tool call + argumentsModel returns tool_use + input
3Your process runs the functionYour process runs the function
4You return tool output / call_idYou return tool_result
5Model continues or finishesModel continues or finishes

How tool use works is blunt about location: if the response contains a tool_use block, your code runs the operation. The model proposed a call. You accepted or rejected it.

That is the shortest loop. No second process. No discovery handshake. No client-per-server object. Schema in, call out, your handler, result in.

When does native function calling win?

Prefer native if most of these are true:

  1. One production host owns the agent
  2. Tools are not products for other teams’ IDEs
  3. Sub-100ms local helpers matter (hash, format, pure transforms)
  4. You already have an HTTP API for cross-service work and do not need a second wrapper
  5. Approval UX lives in your app, not in a desktop MCP client
SignalNative is enoughNative starts to hurt
HostsOne workerIDE + desktop + overnight agent
Tool ownersSame repo as the loopAnother team’s service
SecretsWorkload identity on the workerMust never enter the host process
Catalog3–8 private toolsShared platform catalog
AuditApp logs you already haveOne trail across clients

Native is not “legacy.” It is the correct application pattern for a closed loop. Most Spurlock Studios pilots start here. After 500+ automations and 20,000+ hours on agentic systems, the expensive mistake is wrapping a private helper in a protocol nobody else will call.

When does MCP earn the portability tax?

MCP costs you process or network hops, catalog management, auth between client and server, and operational ownership of servers. Anthropic’s MCP announcement framed the job as a standard so hosts do not each invent a connector. That is a platform pitch. It is not a reason to wrap format_date.

NeedWhy MCP fits
Same tool in IDE + prod agentWrite the server once
Credential isolationSecrets stay in the server; hosts get scoped access
Dynamic discoveryClients learn tools at runtime via server/discover and tools/list
Central audit at the tool boundaryLog and approve at the server or gateway
Multi-team platformTool ownership matches service ownership

A useful mental model: function calling is an app pattern; MCP is a platform boundary. Mature stacks use both. The tax is justified when a second host is real — or will be real this quarter — and you refuse to maintain two integrations for one capability.

If the second host is a slide in a strategy deck, stay native.

Where does the tool actually execute?

Confusion usually starts here. The model never “runs” the tool. The model proposes a call. Something in your trust boundary executes it.

PathExecution locationWho holds secrets
Native function callingYour host process, or a service you call from itThe worker / its IAM role
Anthropic client toolSame as native: your processYour process
Anthropic server toolAnthropic infrastructureAnthropic + whatever you passed in
MCP + stdio serverChild process on the host machineServer environment on that machine
MCP + remote HTTP serverRemote service; host sees protocol responsesServer / its secret store

OpenAI’s tools overview adds another fork: built-in tools (web search, code, remote MCP) versus function tools you execute. OpenAI can consume a remote MCP server as a host. That does not make MCP a replacement for function calling. It makes OpenAI one more host that can attach to a server you already run.

Put policy on the process that executes. Protocol branding does not sanitize a write.

What transports does MCP actually use?

The architecture page names two current transports. The 2026-07-28 changelog reclassifies HTTP+SSE (deprecated since 2025-03-26) as Deprecated. New remote work is Streamable HTTP.

TransportShapeAuth storyTypical use
stdioLocal process, stdin/stdoutEnvironment / OS user. No Authorization headerDesktop host, one user, local files
Streamable HTTPHTTP POST, optional SSE streamingBearer / API key / headers; OAuth recommendedRemote shared servers
HTTP+SSE (legacy)Old remote transportDo not start hereMigrate off

stdio is fast and local. It is not a multi-tenant security model. A pipe has no token. The security boundary is the process that launched the server. If you spawn stdio servers inside a shared cloud worker without isolation, you imported a desktop assumption into a tenancy problem.

Streamable HTTP is the remote product. It is also where authorization exists as a protocol concern. Choose the transport for the trust boundary, not for the blog post you read.

How do credentials stay isolated in MCP?

The MCP authorization spec applies to HTTP transports. Authorization is optional. When you use it: HTTP implementations should follow the spec; stdio implementations should not — they take credentials from the environment.

On HTTP, a protected MCP server is an OAuth 2.1 resource server. The client is an OAuth 2.1 client. The authorization server issues tokens. MCP servers must publish OAuth 2.0 Protected Resource Metadata (RFC 9728) so clients can discover the authorization server. Client ID Metadata Documents are the preferred registration path; Dynamic Client Registration is deprecated and kept for compatibility.

RuleDo thisDo not do this
Secret homeServer env / secret managerPaste the SaaS key into every host
Client identityScoped token per hostOne god key for desktop + prod
Tool authzRead vs write vs admin per tool“If you can list it, you can run it”
ResultsTreat tool output as untrusted model inputConcatenate CRM dumps into the system prompt
Many remotesGateway: authn, rate limits, allowlists, auditEvery host talks to every server

If your “MCP server” is a thin wrapper that dumps the company SaaS key into every desktop host, you did not gain isolation. You distributed a blast radius and called it a platform.

What is the token tax of a large MCP catalog?

Tool schemas are context. Whether you load twenty OpenAI functions or twenty MCP tools into the prompt, you pay input tokens for names, descriptions, and JSON schemas. OpenAI’s function-calling guide now pairs large catalogs with tool search so rarely used tools stay deferred. That is an admission: dumping the zoo is expensive and it makes selection worse.

MCP discovery can be broad. The per-run catalog must be narrow.

Catalog the model seesRiskMitigation
3–8 toolsUsually fineClear descriptions; no duplicates
15–40 toolsWorse picks; cost climbsSplit servers; filter by job type
100+ toolsContext bloat + tool confusionRouter / gateway; never dump the universe

Practical rule: the model should see the tools for this job, not the company’s entire MCP zoo. tools/list can return a platform. The host still chooses what enters the next model request. Schema quality still matters — that is the tool-schema spoke.

Is MCP a LangChain swap?

No. MCP does not replace LangChain, LangGraph, CrewAI, or a fifty-line custom loop. Those choose orchestration. MCP chooses how tools are exposed to hosts.

LayerJobExamples
OrchestrationPlan, branch, revise, stop, HITLCustom loop, LangGraph, CrewAI
Tool protocolHow hosts discover and call toolsNative function schemas, MCP
Execution policyAllow / deny / pending, sandbox, idempotencyYour gate

You can use MCP tools from a custom loop. You can use native tools inside LangGraph. Mixing is normal. Double-maintaining the same tool twice without a shared module is not.

If a vendor slide says “adopt MCP instead of your framework,” they collapsed two layers. Keep them separate on the design doc. The operating manual owns the loop. This spoke owns the tool boundary.

How do OpenAI and Anthropic treat MCP vs tools?

Vendors now ship both surfaces. That is the trap. Teams see an mcp tool type and conclude native function calling is deprecated. Read the pages.

Vendor surfaceWhat it isWho executes
OpenAI function / custom toolsYou declare schemas; model calls themYour app (function calling)
OpenAI built-in toolsWeb, code, files, tool searchOpenAI, unless it is your function
OpenAI remote MCP / connectorsHost attaches to a remote MCP serverThe MCP server (MCP and Connectors)
Anthropic client toolsYou declare input_schemaYour app
Anthropic server toolsweb_search, code_execution, …Anthropic
Anthropic MCP hostsDesktop / Claude as an MCP hostYour MCP server

OpenAI’s MCP guide is explicit: remote MCP is in addition to function calling. You can require approval on MCP tool calls. You must trust the remote server — a malicious server can exfiltrate whatever entered the model context. That sentence is the whole security review for “just add the URL.”

Anthropic’s client-vs-server split is a different axis than MCP host-vs-server. Do not mash the words. “Server tool” in Claude’s API means Anthropic ran it. “MCP server” means your (or a vendor’s) process exposed tools over the protocol.

What did the 2026-07-28 spec change that operators should pin?

Pin a spec version the way you pin a model. The spec blog for 2026-07-28 and the changelog are the receipts:

ChangeOperator takeaway
Protocol-level sessions / Mcp-Session-Id removedTreat requests as self-contained; do not build sticky-session folklore
server/discover + per-request _metaVersion and capabilities travel on the call
HTTP+SSE deprecatedNew remotes: Streamable HTTP
DCR deprecated; CIMD preferredPlan client registration on metadata documents
RFC 9207 iss validationClients must check issuer before redeeming a code
Sampling / logging deprecatedLog to stderr or OpenTelemetry; do not wait on client sampling
Mcp-Method / Mcp-Name headersGateways can route and authorize without parsing the body

“MCP is production-ready” is only true if you pin this line (or the line you actually deployed) and run servers like services. Flakiness in 2026 is usually unbounded catalogs, missing auth, or treating MCP as orchestration — not “the protocol cannot work.”

Do not cite unaudited Fortune-500 adoption percentages. Judge readiness by auth, audit, health checks, and eval coverage on your servers.

How do you run both without double maintenance?

Recommended ownership:

  1. Define the capability once (code module with clear input/output types)
  2. Adapter A: native tool wrapper for the production agent loop
  3. Adapter B: MCP server handlers that call the same module
  4. One eval suite against the module, not against each adapter’s JSON dialect
  5. Promote sensitive/shared tools to MCP first; keep app-local helpers native

Checklist:

  • Single source of truth for business logic
  • Adapters stay thin (serialize / deserialize only)
  • Version the capability; advertise version in MCP metadata
  • Golden cases call the module directly in CI
  • Native schema and MCP inputSchema generated from the same source
  • Per-run allowlist is a host concern, not a second copy of the handler

If the adapters grow if host == desktop branches, the module is lying. Push policy up to the host or down to the server. Do not hide it in the serializer.

Worked example: one CRM write tool, two boundaries

Job: Agent drafts a CRM note. Humans approve high-risk fields.

ApproachShapeWhen it is correct
Nativecrm.upsert_note in the worker; policy gate checks payload; secrets via workload identityOnly the worker will ever call CRM
MCPcrm server owns the SaaS token; desktop and prod agent both connect; approvals at client or gatewaySales’ IDE assistant and the overnight agent share one audit trail
OpenAI as MCP hostWorker still native; ChatGPT / Responses attaches to the same remote serverYou already paid for a remote server and a second host is real
WrongMCP server that returns the API key to the model “for flexibility”Never

Decision procedure:

  1. Count hosts that must call this tool in the next quarter (not “someday”).
  2. Ask whether the SaaS token may enter the agent worker.
  3. Ask whether desktop users must use the same allowlist and audit log.
  4. If hosts = 1 and the worker may hold the token: native.
  5. If hosts ≥ 2 or the token must not enter the worker: MCP server + gateway.

The schema is the same either way. Write it once. See tool schemas agents follow for enums, required, and killing the omnibus do_anything tool. Protocol does not fix a vague note field.

Failure mode: MCP as fashion middleware

What breaks: A team wraps every internal function in MCP “for the future,” including a pure string formatter called forty times per run. Cold starts and JSON-RPC hops show up in p95. Nobody else consumes the servers. The agent is slower and harder to debug.

What it costs: Latency budget, on-call surface area, and a false sense of platform maturity.

What you do instead: Native for private high-frequency helpers. MCP for shared or credentialed capabilities with more than one client (or a clear second client on the roadmap within a quarter).

Second failure we keep seeing: stdio servers copied into a multi-tenant worker because “local is simpler.” Local is simpler for one user on one machine. It is not a tenancy model. Use Streamable HTTP, isolate processes, or do not share the host.

Third failure: attaching an untrusted remote MCP URL to a host that already holds customer context. OpenAI’s MCP guide warns that a malicious server can exfiltrate whatever entered the model. Review the server like you review a dependency with network and data access — because that is what it is.

One-agent / few-tools default

For a single production agent with a handful of tools:

ChoiceDefault
ProtocolNative function calling
Shared company tools laterExtract to MCP when a second host appears
OrchestrationCustom loop or graph — independent of MCP
SafetyPolicy before side effects; treat tool results as untrusted
CatalogJob-sized, not platform-sized

If your only host is the agent service, MCP is optional. Optional is not forbidden. It is a cost you should justify in the design doc with a second host or a credential boundary.

Default checklist before you add MCP:

  • I can name the second host (product, not aspiration)
  • I can name the secret that must not enter the first host
  • I can name who pages when the server is down
  • I can name the per-run subset the model is allowed to see
  • I can run the capability’s evals without either adapter

Zero boxes checked: stay native. Two or more: the tax is probably real.

What should the host send the model this turn?

Discovery and the prompt are different jobs. MCP clients may call server/discover and tools/list. That tells the host what exists. It does not obligate you to stuff every advertised tool into the next model request.

LayerQuestion it answersWho consumes it
server/discoverWhich protocol version and capabilities is this server?Host / client
tools/listWhich tools could this server run?Host / gateway
Per-run tools / filtered setWhich tools may this model call now?The model
Policy gateWhich of those calls may execute?Your worker

Procedure for every production turn:

  1. Resolve the job type (support reply, CRM note, invoice, research).
  2. Select the server(s) that own that job — not the whole zoo.
  3. Filter the listed tools to the verbs this job is allowed to use.
  4. Send that subset as native functions or as the MCP tools the host will honor.
  5. Execute only after the gate. Return errors the model can correct once.

If step 3 is “send everything,” you are paying the catalog tax on purpose. OpenAI’s own function-calling docs added tool search for the same reason: large schemas crowd out the task.

Who pages when an MCP server dies?

Native function calling fails like the rest of your worker: one process, one deploy, one on-call. MCP adds a second runtime. Treat it like a service or do not ship it.

SymptomNativeMCP stdioMCP remote HTTP
Cold startYour worker bootChild process spawnServer / scale-to-zero
Auth expiryWorkload identity refreshEnv on that machineOAuth token / CIMD client
Version skewOne deployHost SDK vs server specSame, plus gateway
Blast radiusThis agentThis machine’s hostsEvery host attached

On-call checklist before the second host goes live:

  • Health endpoint or server/discover probe on a schedule
  • Alert on tool-error rate, not only HTTP 500s
  • Pin spec + SDK versions in the deploy manifest
  • Rollback plan that leaves the native adapter working
  • Named owner for the server (not “the AI team”)

If nobody will page, you do not have a platform. You have a hobby process in the critical path.

Comparison table (paste into a design doc)

DimensionNative function callingMCP
AbstractionProvider tool / function APIHost ↔ client ↔ server protocol
Best fitOne app, private toolsMulti-client, shared tools
ExecutionYour processServer process / service
Auth storyApp secrets / IAM rolesClient↔server auth (+ gateway) on HTTP
DiscoveryStatic schemas you sendserver/discover, tools/list
OrchestrationNot includedNot included
Main taxProvider lock-in of schema shapeOps + catalog + hops
Spec to pinCurrent vendor tool docsMCP 2026-07-28

Copy that table into the RFC. Fill the “second host” cell. If it stays blank, you already have the answer.

Anti-patterns

“MCP replaces our agent framework.” Category error. Frameworks loop. MCP exposes tools.

Dumping 80 tools into every run. Token tax plus worse tool selection. Filter at the host.

Stdio servers in multi-tenant cloud without isolation. Local transport ≠ multi-tenant security model.

Skipping policy because “MCP is standardized.” Standards do not sanitize side effects.

Returning secrets in a tool result. The model will see them. So will the next host that logs the transcript.

One god token for every client. You built a distribution system for a key.

Treating OpenAI’s mcp tool type as “we no longer write functions.” OpenAI still documents function calling as the way your app exposes your code.

Pinning no spec version. 2025 SSE assumptions will bite a 2026 Streamable HTTP server.

Pilot guidance

On a Spurlock Studios $1,500 · 5-day agentic pilot we usually ship native tools first, with a policy gate and an evaluator. We introduce MCP when a second host is real or when credential isolation at a server boundary is part of the acceptance criteria — not because a keynote said MCP is the future.

Continue with the operating manual. If the schemas are still vague, fix those before you pay the protocol tax.

FAQ

Where does the tool actually execute?

With native function calling, in your application or a service you invoke from it. With MCP, in the MCP server process or remote service the client called. The model only proposes the call; your trust boundary runs it. Anthropic server tools are a third case: Anthropic runs those on their infrastructure, which is still not “the model ran the tool.”

Do I need LangChain if I have MCP?

No. MCP does not run the agent loop. LangChain, LangGraph, CrewAI, or a custom loop decide control flow. MCP exposes tools and context to hosts. You can use MCP with zero LangChain code, and you can use native tools inside a graph.

How do credentials stay isolated in MCP servers?

Keep secrets in the server’s environment or secret manager, authenticate HTTP clients with scoped tokens, and enforce per-tool authorization. Do not ship long-lived god keys to every host. Prefer a gateway when you have many remote servers. stdio has no OAuth header — isolation there is process and OS, not tokens.

What’s the token tax of large MCP catalogs?

Every tool schema you expose to the model consumes context and can confuse tool selection. Keep per-run catalogs small; filter by job type; split servers so hosts connect only to what they need. Discovery can stay broad. The prompt should not.

Is MCP production-ready or still flaky?

The protocol is production-capable in 2026 when you pin a spec and SDK version and run servers with auth, audit, and health checks. The 2026-07-28 line tightened HTTP auth and dropped protocol sessions. Flakiness usually comes from ops gaps and oversized catalogs, not from “MCP cannot work.” Verify the current spec features you depend on before promising them to a client.

What’s the one-agent / few-tools default?

Native function calling inside a thin harness with a policy gate. Add MCP when a second client, shared ownership, or credential boundary makes the portability tax worth paying. If you cannot name that second host, you are not late. You are early.

CTA

Shortest safe loop first. Shared tool platform second.

/agentic · /contact?intent=agentic-pilot

FAQ

What questions does this article answer?

Where does the tool actually execute?
With native function calling, in your application or a service you invoke from it. With MCP, in the MCP server process or remote service the client called. The model only proposes the call; your trust boundary runs it. Anthropic server tools are a third case: Anthropic runs those on their infrastructure, which is still not “the model ran the tool.”
Do I need LangChain if I have MCP?
No. MCP does not run the agent loop. LangChain, LangGraph, CrewAI, or a custom loop decide control flow. MCP exposes tools and context to hosts. You can use MCP with zero LangChain code, and you can use native tools inside a graph.
How do credentials stay isolated in MCP servers?
Keep secrets in the server’s environment or secret manager, authenticate HTTP clients with scoped tokens, and enforce per-tool authorization. Do not ship long-lived god keys to every host. Prefer a gateway when you have many remote servers. stdio has no OAuth header — isolation there is process and OS, not tokens.
What’s the token tax of large MCP catalogs?
Every tool schema you expose to the model consumes context and can confuse tool selection. Keep per-run catalogs small; filter by job type; split servers so hosts connect only to what they need. Discovery can stay broad. The prompt should not.
Is MCP production-ready or still flaky?
The protocol is production-capable in 2026 when you pin a spec and SDK version and run servers with auth, audit, and health checks. The 2026-07-28 line tightened HTTP auth and dropped protocol sessions. Flakiness usually comes from ops gaps and oversized catalogs, not from “MCP cannot work.” Verify the current spec features you depend on before promising them to a client.
What’s the one-agent / few-tools default?
Native function calling inside a thin harness with a policy gate. Add MCP when a second client, shared ownership, or credential boundary makes the portability tax worth paying. If you cannot name that second host, you are not late. You are early.
Sources

Last reviewed

More from this lane

AI Agents

All →
Start a pilot