
Services
MCP vs function calling: use a function call when one process owns the tool. Use MCP when a second host must call it, or the tool needs its own auth and deploy.

Use function calling when one process owns the model request and the tool. Use MCP when a second host must call that tool, or the tool needs its own auth, rate limit, and deploy. A ten-line helper that only your agent calls should stay a function. A notes tool that Cursor, Claude, and a second service all call should be an MCP server.
By Tayyab Javed, AI agent developer.
On the OpenAI Responses API a tool is a flat object: type, name, description, parameters, and strict. I checked that shape against OpenAI's function-calling guide on October 12, 2026. I did not send it to the API. I did run the dispatcher. It returned Saved: ship it.
const tools = [{
type: 'function',
name: 'add-note',
description: 'Save a note and echo it back',
parameters: {
type: 'object',
properties: {
text: { type: 'string', description: 'The note to save' }
},
required: ['text'],
additionalProperties: false
},
strict: true
}];
function addNote(text) {
return 'Saved: ' + text;
}
const handlers = {
'add-note': (args) => addNote(args.text)
};
// Shape of a function_call item on the Responses API.
const call = {
type: 'function_call',
name: 'add-note',
arguments: '{"text":"ship it"}'
};
const output = handlers[call.name](JSON.parse(call.arguments));
// output === 'Saved: ship it'
That handler lives in the same process as the model call. There is no URL, no bearer token, and no second team that can call add-note without copying this file. Anthropic's tool object uses input_schema instead of parameters. The dispatch is the same idea.
Register the function once. A host connects, lists tools, and calls one. I ran this on @modelcontextprotocol/server 2.3.1. A tools/call for add-note with {"text":"ship it"} returned a text block Saved: ship it. The wiring around it, including Python, is how to build an MCP server.
import { McpServer } from '@modelcontextprotocol/server';
import * as z from 'zod/v4';
const server = new McpServer({ name: 'notes', version: '1.0.0' });
server.registerTool(
'add-note',
{
description: 'Save a note and echo it back',
inputSchema: z.object({
text: z.string().describe('The note to save')
})
},
async ({ text }) => ({
content: [{ type: 'text', text: 'Saved: ' + text }]
})
);
This snippet registers the tool. Serving it over stdio or Streamable HTTP is a separate step, covered in the build post and in how to deploy an MCP server. The schema the model sees is generated from the Zod object. You do not hand-write the JSON Schema.
| Situation | Use |
|---|---|
| One agent, one codebase, the tool is a function you already import | Function calling |
| You are still changing the prompt and the tool is a few lines | Function calling |
| Cursor, Claude, and your own agent must share the tool | MCP |
| The tool needs its own bearer auth, rate limit, and release | MCP |
| The agent runtime only emits function calls, and the tool is already a server | Both: the function calls MCP |
A function call stays in the process. An MCP call crosses a pipe (stdio) or an HTTP request (Streamable HTTP). Pay that cost when the boundary buys you something: one implementation for several hosts, or a place to put authentication. Skip the server when the only caller is the file next to it.
Schemas travel. The OpenAI object above and the Zod tool describe the same string argument. What does not travel is the running code, the credential, and the deploy. The MCP production guide has the longer version of this table, including LangChain tools. If the surrounding loop is new, start with how to build an AI agent.
Use MCP when a second host needs the tool, or the tool must be authenticated and deployed on its own. Use function calling when one process owns both the model request and the function.
No. Function calling is how a model asks your process to run something. MCP is how a tool is exposed to clients. An agent can function-call a short handler that then calls an MCP server.
A function call stays in process. An MCP call crosses a local pipe or an HTTP request. Choose MCP when sharing the tool, or isolating its auth and deploy, is worth that hop.
Function calling is the dispatch. MCP is the shared server. Start with the function. Move the tool to MCP when a second caller shows up, or when the tool is dangerous enough to need its own token check. If you want that boundary drawn for a product that already has users, hire me and we will pick it on one call.
Free 30-minute scoping call. We will decide which tools stay in process and which become a server.
Book a Scoping CallTayyab is a freelance AI agent developer and founder of Workly. He does research, spec, architecture, UX, and the build — solo, no handoff failures. Ex-Principal PM behind a Fortune 500 AI contact center (40% CSAT lift). He helps founders and SMBs ship production-grade agentic systems end to end.