Skip to main content

MCP: The Differential for Modern APIs and Systems

ยท 14 min read
Steve Manuel
CEO, Co-founder @ Dylibso
TL;DR

MCP enables vastly more resilient system integrations by acting as a differential between APIs, absorbing changes and inconsistencies that would typically break traditional integrations. With "the prompt is the program," we can build more adaptable, intention-based integrations that focus on what needs to be done rather than how it's technically implemented.

Try it now โ†’

The Problem with Traditional API Integrationโ€‹

When engineers connect software systems, they're engaging in an unspoken contract: "I will send you data in exactly this format, and you will do exactly this with it." This rigid dependency creates brittle integrations that break when either side makes changes.

Traditional API integration looks like this:

// System A rigidly calls System B with exact parameters
const response = await fetch("https://api.system-b.com/v2/widgets", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer " + token,
},
body: JSON.stringify({
name: widgetName,
color: "#FF5733",
dimensions: {
height: 100,
width: 50,
},
metadata: {
created_by: userId,
department: "engineering",
},
}),
});

// If System B changes ANY part of this structure, this code breaks

This approach has several fundamental problems:

  1. Version Lock: Systems get locked into specific API versions
  2. Brittle Dependencies: Small changes can cause catastrophic failures
  3. High Maintenance Burden: Keeping integrations working requires constant vigilance and updates
  4. Implementation Details Exposure: Systems need to know too much about each other

The Automobile Differential: A Mechanical Analogyโ€‹

To understand how MCP addresses these issues, let's examine a mechanical engineering breakthrough: the differential gear in automobiles.

Before the differential, cars had a serious problem. When turning a corner, the outer wheel needs to travel farther than the inner wheel. With both wheels rigidly connected to the same axle, this created enormous stress, causing wheels to slip, skid, and wear out prematurely.

The differential solved this by allowing wheels on the same axle to rotate at different speeds while still delivering power to both. It absorbed the differences between what each wheel needed.

MCP: The API Differentialโ€‹

MCP functions as an API differential โ€“ it sits between systems and absorbs their differences, allowing them to effectively work together despite technical inconsistencies.

How does this work? Through intention-based instructions rather than implementation-specific calls.

Traditional API Calls vs. MCP Callsโ€‹

Traditional API:

// Extremely specific requirements
await client.createWidget({
name: "Customer Dashboard",
type: "analytics",
visibility: "team",
access_level: 3,
resource_id: "res_8675309",
parent_id: "dash_12345",
metadata: {
created_by: "user_abc123",
department_id: 42,
},
});

MCP Approach:

// High-level intention
"Create a new analytics widget called 'Customer Dashboard'
for the marketing team's main dashboard"

With the MCP approach, the client doesn't need to know all the specific parameters upfront. Instead, it engages in a discovery-based workflow:

How MCP Clients Resolve Required Parametersโ€‹

Tool Discovery, Dependency Analysis, Parameter Resolutionโ€‹

When an MCP Client receives a high-level instruction like creating a dashboard widget, it follows a sophisticated process:

  1. Tool Discovery: The client first queries the MCP Server for available tools:
// MCP Client requests available tools
const toolList = await listTools();

// Server returns available tools with their descriptions
[
{
"name": "create_widget",
"description": "Creates a new widget on a dashboard",
"inputSchema": {
"type": "object",
"required": ["name", "dashboard_id", "widget_type"],
"properties": {
"name": {
"type": "string",
"description": "Display name for the widget",
},
"dashboard_id": {
"type": "string",
"description": "ID of the dashboard to add the widget to",
},
"widget_type": { ... },
"team_id": { ... },
// Other parameters...
},
},
},
{
"name": "list_dashboards",
"description": "List available dashboards, optionally filtered by team",
"inputSchema": { ... },
},
{
"name": "get_user_info",
"description": "Get information about the current user or a specified user",
"inputSchema": { ... },
},
{
"name": "get_team_info",
"description": "Get information about a team",
"inputSchema": { ... },
},
];
  1. Dependency Analysis: The LLM analyzes the instruction and the available tools, recognizing that to create a widget, it needs:

    • The dashboard ID for "marketing team's main dashboard"
    • Possibly the team ID for the "marketing team"
  2. Parameter Resolution: The LLM plans and executes a sequence of dependent calls:

(This is deterministic code for demonstration, but the model infers these steps on its own!)

// First, get the marketing team's ID
const teamResponse = await callTool("get_team_info", {
team_name: "marketing",
});
// teamResponse = { team_id: "team_mktg123", department_id: 42, ... }

// Next, find the marketing team's main dashboard
const dashboardsResponse = await callTool("list_dashboards", {
team_name: "marketing",
});
// dashboardsResponse = [
// { id: "dash_12345", name: "Main Dashboard", is_primary: true, ... },
// { id: "dash_67890", name: "Campaign Performance", ... }
// ]

// Filter for the main dashboard
const mainDashboard = dashboardsResponse.find((d) => d.is_primary) ||
dashboardsResponse.find((d) => d.name.toLowerCase().includes("main"));

// Finally, create the widget with all required parameters
const widgetResponse = await callTool("create_widget", {
name: "Customer Dashboard",
dashboard_id: mainDashboard.id,
widget_type: "analytics",
team_id: teamResponse.team_id,
});
  1. Semantic Mapping: The MCP Server handles translating from the standardized tool parameters to the specific API requirements, which might involve:
    • Translating team_id to the internal department_id format
    • Setting the appropriate access_level based on team permissions
    • Generating a unique resource_id
    • Populating metadata based on contextual information

This approach is revolutionary because:

  1. Resilient to Changes: If the underlying API changes (e.g., requiring new parameters or renaming fields), only the MCP Server needs to update โ€“ the high-level client instruction stays the same
  2. Intent Preservation: The focus remains on what needs to be accomplished, not how
  3. Progressive Enhancement: New API capabilities can be leveraged without client changes
  4. Contextual Intelligence: The LLM can make smart decisions about which dashboard is the "main" one based on naming, flags, or other context

With MCP, the instruction doesn't change even when the underlying API changes dramatically. The MCP Server handles the translation from high-level intent to specific API requirements.

Why This Matters for System Resilienceโ€‹

In an MCP-enabled world, system upgrades, API changes, and even complete backend replacements can happen with minimal disruption to connected systems.

Consider a company migrating from Salesforce to HubSpot. Traditionally, this would require rewriting dozens or hundreds of integrations. With MCP:

  1. The high-level instructions ("Create a new contact for John Smith from Acme Corp") stay the same
  2. Only the MCP Server implementation changes to target the new system
  3. Existing systems continue functioning with minimal disruption

The Technical Magic Behind MCP's Differential Capabilitiesโ€‹

MCP achieves this resilience through several key mechanisms:

1. Dynamic Tool Discoveryโ€‹

Unlike traditional SDKs where available methods are fixed at compile/build time, MCP Clients discover tools dynamically at runtime. This means:

  • New capabilities can be added without client updates
  • Deprecated features can be gracefully removed
  • Feature flags can be applied at the server level

2. Semantic Parameter Mappingโ€‹

Semantic Parameter Mapping enables systems to communicate based on meaning rather than rigid structure. This approach drastically improves resilience and adaptability in integrations.

In traditional API integration, parameters are often implementation-specific and tightly coupled to the underlying data model. For example, a CRM API might require a customer record to be created with fields like cust_fname, cust_lname, and cust_type_id - names that reflect internal database schema rather than their semantic meaning.

With MCP's semantic parameter mapping, tools are defined with parameters that reflect their conceptual purpose, not their technical implementation:

Traditional API Parameters:

{
"cust_fname": "Jane",
"cust_lname": "Smith",
"cust_type_id": 3,
"cust_status_cd": "A",
"addr_line1": "123 Main St",
"addr_city": "Springfield",
"addr_state_cd": "IL",
"addr_zip": "62701",
"cust_src_id": 7,
"rep_emp_id": "EMP82736"
}

MCP Tool Description with Semantic Parameters:

{
"name": "create_customer",
"description": "Create a new customer record in the CRM system",
"inputSchema": {
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "Customer's first or given name"
},
"lastName": {
"type": "string",
"description": "Customer's last or family name"
},
"customerType": {
"type": "string",
"enum": ["individual", "business", "government", "non-profit"],
"description": "The category of customer being created"
},
"address": {
"type": "object",
"description": "Customer's primary address",
"properties": {
"street": {
"type": "string",
"description": "Street address including number and name"
},
"city": {
"type": "string",
"description": "City name"
},
"state": {
"type": "string",
"description": "State, province, or region"
},
"postalCode": {
"type": "string",
"description": "ZIP or postal code"
},
"country": {
"type": "string",
"description": "Country name",
"default": "United States"
}
}
},
"source": {
"type": "string",
"description": "How the customer was acquired (e.g., 'website', 'referral', 'trade show')"
},
"assignedRepresentative": {
"type": "string",
"description": "Name or identifier of the sales representative assigned to this customer",
"required": false
}
},
"required": ["firstName", "lastName", "customerType"]
}
}

The key differences in the semantic approach:

  1. Human-readable parameter names: Using firstName instead of cust_fname makes the parameters self-descriptive

  2. Hierarchical organization: Related parameters like address fields are nested in a logical structure

  3. Descriptive enumerations: Instead of opaque codes (like cust_type_id: 3), semantically meaningful values like "business" are used

  4. Clear descriptions: Each parameter includes a description of its purpose rather than just its data type

  5. Meaningful defaults: When appropriate, semantic defaults can be provided

This semantic approach provides tremendous advantages:

Future-proofingโ€‹

If the underlying CRM changes its internal codes or structure, only the mapping function in the MCP Server needs to be updated

Interoperabilityโ€‹

Multiple different CRM systems could implement MCP Servers with the same semantic parameters, allowing seamless switching between backends

Conceptual clarityโ€‹

People and AI systems can more easily understand the parameters and their purpose

Field validationโ€‹

Semantic validation becomes possible (e.g., ensuring state names are valid) rather than just type checking

Extensibilityโ€‹

New parameters can be added to the semantic schema without breaking existing integrations

When combined with intent-based execution, semantic parameter mapping creates a powerful abstraction layer that shields systems from the implementation details of their integration partners, making the entire ecosystem more adaptable and resilient to change.

3. Intent-Based Executionโ€‹

Intent-based execution is perhaps the most transformative aspect of MCP. Let me walk you through a detailed example that illustrates how this works in practice.

Imagine a scenario where a business wants to "send a quarterly performance report to all department heads." This seemingly simple task involves multiple steps and systems in a traditional integration context:

Traditional Integration Approach:

  1. Query the HR system to identify department heads
  2. Access the financial system to gather quarterly performance data
  3. Generate a PDF report using a reporting engine
  4. Connect to the email system to send personalized emails with attachments
  5. Log the communication in the CRM system

Each of these steps would require detailed knowledge of the respective APIs, authentication methods, data formats, and error handling. If any system changes its API, the entire integration could break.

With MCP's Intent-Based Execution:

The MCP Client (like Tasks) might simply receive the instruction:

"Send our Q1 2024 performance report to all department heads. Include YoY comparisons and highlight areas exceeding targets by more than 10%."

Behind the scenes, the MCP Client would:

  1. Recognize the high-level intent and determine this requires multiple tool calls
  2. Query the MCP Server for available tools related to reporting, employee data, and communications
  3. Based on the tool descriptions, construct a workflow:

(Again, not executed code, but to illustrate the inferred logic the LLM runs!)

// In step 2 listed above, the MCP Client has all the
// static identifiers and parameters from the available
// tool descriptions to be used in this code

// First, identify who the department heads are
const departmentHeads = await callTool("get_employees", {
filters: { position_type: "department_head", status: "active" },
});

// Get financial performance data for Q1 2024
const financialData = await callTool("get_financial_report", {
period: "q1_2024",
metrics: ["revenue", "expenses", "profit_margin", "growth"],
comparisons: ["year_over_year"],
});

// The LLM analyzes the data to identify high-performing areas
const highlights = financialData.metrics.filter(
(metric) => metric.year_over_year_change > 10,
);

// Generate a report with the appropriate formatting and emphasis
const report = await callTool("create_report", {
title: "Q1 2024 Performance Report",
data: financialData,
highlights: highlights,
format: "pdf",
template: "quarterly_executive",
});

// Send the report to each department head with a personalized message
for (const head of departmentHeads) {
await callTool("send_email", {
recipient: head.email,
subject: "Q1 2024 Performance Report",
body:
`Dear ${head.name},\n\nPlease find attached our Q1 2024 performance report. Your department ${head.department} showed ${
highlights.some((h) => h.department === head.department)
? "exceptional performance in some areas"
: "consistent results"
}.\n\nRegards,\nExecutive Team`,
attachments: [report.file_id],
log_to_crm: true,
});
}

The crucial difference is that the MCP Server for each system is responsible for translating these semantic, intent-based calls into whatever specific API calls its system requires.

For example, the HR system's MCP Server might translate get_employees with a position or role filter into a complex SQL query or LDAP search, while the reporting system's MCP Server might convert create_report into a series of API calls to a business intelligence platform.

If any of these backend systems change:

  • The HR system might switch from an on-premise solution to Workday
  • The financial system might upgrade to a new version with a completely different API
  • The reporting engine might be replaced with a different vendor
  • The email system might move from Exchange to Gmail

None of these changes would affect the high-level intent-based instruction. Only the corresponding MCP Servers would need to be updated to translate the same semantic calls into the new underlying system's language.

This is the true power of intent-based execution with MCP - it decouples what you want to accomplish from the technical details of how to accomplish it, creating resilient integrations that can withstand significant changes in the underlying technology landscape.

Building Resilient Systems with MCPโ€‹

To leverage MCP as a differential in your own systems:

  1. Focus on intent over implementation: Design your tools around what they accomplish, not how
  2. Embrace semantic parameters: Name and structure parameters based on their meaning, not your current implementation
  3. Build for adaptation: Assume underlying APIs will change and design your MCP Servers to absorb these changes

The Future of System Integrationโ€‹

As we move toward a world where "the prompt is the program," traditional rigid API contracts will increasingly be replaced by intent-based interfaces. MCP provides a standardized protocol for this transition.

The implications are profound:

  • Reduced integration maintenance: Systems connected via MCP require less ongoing maintenance
  • Faster adoption of new technologies: Backend systems can be replaced without disrupting front-end experiences
  • Greater composability: Systems can be combined in ways their original designers never anticipated
  • Longer component lifespan: Software components can remain useful far longer despite ecosystem changes

The differential revolutionized transportation by solving a mechanical impedance mismatch. MCP is poised to do the same for software integration by solving the API impedance mismatch that has plagued systems for decades.

The future of integration isn't more rigid contracts โ€“ it's more flexible, intent-based communication between systems that can adapt as technology evolves.

Get Started with MCPโ€‹

Ready to build more resilient integrations? Here's how to start:

  1. Explore the MCP specification at mcp.run
  2. Install mcpx, or generate an SSE URL from your Profile to start using MCP tools immediately in any MCP Client
  3. Consider which of your systems would benefit from an MCP interface
  4. Join our community to learn MCP best practices