Moving from Custom Tool Calling to Standard MCP

When integrating tool-calling capabilities into an application powered by large language models (LLMs), engineers inevitably find themselves wrestling with monolithic, vendor-specific JSON schemas and brittle HTTP glue code. The subtle structural discrepancies between OpenAI's Function Calling specifications, Anthropic's Tool Use format, and Gemini's Function Declarations quickly turn an application's integration layer into a maintenance nightmare. Examining the Garmin Connect MCP implementation that gained traction on Hacker News demonstrated that the Model Context Protocol is far from a niche gimmick reserved for Claude Desktop or IDE extensions; it represents a mature, open standard for decoupling contextual data and functional tooling within modern mobile and web products.
The Fragility of Bespoke Function Calling Wrappers
In conventional setups, enabling a web or mobile application to interact with backend services through an LLM relies on custom wrappers. These components construct raw API payloads, validate arguments emitted by the model, execute HTTP requests, and format the response payload back into a conversational system prompt. While this ad-hoc architecture remains manageable for two or three straightforward tools, it rapidly degrades as functional complexity scales. Maintaining twenty independent tools with handcrafted JSON schemas pollutes the context window, exacerbates parameter hallucination, and requires continuous client updates whenever an upstream endpoint contract shifts.
Furthermore, tightly coupling the application's runtime data layer to a specific model provider creates severe technical debt. Migrating from proprietary APIs to a locally hosted open-source model using frameworks like Ollama demands rewriting schema serializers and validation logic from scratch. The Model Context Protocol resolves this friction by establishing a universal abstraction boundary between AI orchestrators and backend capabilities.
How the Model Context Protocol Architecture Operates
Standardized by Anthropic as an open specification, MCP is a client-server architecture running over the JSON-RPC 2.0 protocol. The specification categorizes contextual capabilities into three primitive constructs: Resources, Prompts, and Tools. Tools expose executable server-side procedures, while Resources stream read-only data assets into the context. In the aforementioned Garmin ecosystem implementation, sleep metrics and daily heart rate records are modeled as queryable Resources, whereas scheduling a workout session is exposed as an actionable Tool.
The Model Context Protocol establishes the same foundational interoperability for agentic workflows and backend data sources that HTTP and REST delivered for web service communication.
MCP supports two primary transport layers: standard input/output (stdio) for local process communication, and Server-Sent Events (SSE) over HTTP for networked systems. While desktop tooling leverages stdio processes, web and mobile client integration necessitates HTTP with SSE streams. Under this paradigm, the MCP server advertises its schema dynamically over the wire. When the model selects a tool, the client dispatches a structured JSON-RPC execution request, which the server processes before returning a normalized content block.
Designing a Resilient MCP Server in Production
Building a robust MCP server is straightforward using the official @modelcontextprotocol/sdk library (v1.x) in the TypeScript ecosystem. Leveraging runtime schema validators such as Zod guarantees strict type safety, preventing malformed model parameters from propagating to core application logic. The following minimal example illustrates an MCP tool exposing historical telemetry data with validated inputs:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
const server = new McpServer({ name: "health-api", version: "1.0.0" });
server.tool("getActivities", { days: z.number().min(1).max(30) }, async ({ days }) => {
const data = await fetchActivitiesFromDB(days);
return { content: [{ type: "text", text: JSON.stringify(data) }] };
});
The core advantage of this structure is that the input schema is dynamically translated into standard JSON Schema primitives without requiring duplicate declarations. When the client initializes an agent session, it queries the server using tools/list and injects the retrieved definitions directly into the model context. Upstream database updates or schema adjustments remain confined entirely to the MCP service layer, eliminating the need to deploy breaking mobile updates or trigger App Store review cycles.
Architectural Considerations for Web and Mobile Workflows
Deploying MCP servers within consumer-facing web and mobile architectures introduces critical design considerations that differ significantly from local desktop configurations. Security, authentication, and execution boundaries require meticulous architectural planning:
- Tenant and Session Isolation: Unlike local desktop instances operating with root workstation access, networked MCP servers handling multi-tenant traffic must validate JSON-RPC requests via cryptographically signed JWTs to scope tool execution strictly to the authenticated user.
- Rate Limiting and Token Governance: Autonomous model loops can inadvertently spam a specific tool dozens of times in seconds. Implementing token-bucket rate limits directly inside the MCP tool resolver mitigates downstream denial-of-service risks.
- Network Latency and Transport Resilience: Mobile network handoffs routinely disrupt persistent SSE connections. Implementing robust reconnect protocols alongside aggressive caching of static tool definitions ensures responsive UI states.
From an architectural standpoint, allowing mobile clients to directly orchestrate remote MCP servers introduces unnecessary attack surfaces. A more defensible pattern involves positioning the existing backend API gateway as the MCP client. The gateway manages model interactions, validates intent, and enforces strict human-in-the-loop confirmations before executing high-consequence operations such as payments or identity mutations.
Long-Term Maintainability and Next Steps
Migrating away from brittle, bespoke function calling logic toward an open standard like MCP incurs an upfront engineering cost, yet it dramatically reduces operational debt across multi-platform codebases. Instead of continuously chasing shifting vendor APIs, engineering teams gain a stable, decoupled protocol layer that treats external capabilities as pluggable modules. As demonstrated by community projects like the Garmin integration, adopting MCP allows teams to integrate external contexts effortlessly while future-proofing internal architectures against rapid shifts in AI infrastructure. A logical next step is identifying your product's two most frequently coupled data points and implementing an internal proof-of-concept MCP server to evaluate runtime stability firsthand.