Pawlo
Pawlo
ExploreSEO vs AEODocsPricingExamplesBlog
For BusinessJoin Waitlist →
Engineering

Building the MCP Layer for Local Intent Data

December 27, 2025 · Eric Yeung

If you're building an AI agent that needs to interact with the real world — book a table, find a deal, recommend a local service — you've hit the data problem. Your model is smart, your prompts are dialed in, but the information your agent needs simply isn't available through any API you can find.

We hit this problem while building Pawlo. We had structured local business data — live deals, seller intent, hidden inventory — sourced directly from businesses. The data was good. The question was: how do you make it accessible to every AI agent, regardless of framework, in a way that's fast, reliable, and cheap to operate?

The answer, for us, was MCP — the Model Context Protocol. This post walks through what MCP is, why we chose it, and how we built the Pawlo MCP server on Cloudflare Workers.

What MCP is (and isn't)

Model Context Protocol is an open standard, originally developed by Anthropic, that defines how AI agents discover and call external tools. Think of it as a contract: the server declares what tools it offers, what parameters each tool accepts, and what it returns. The agent reads this declaration, decides which tools are relevant, and calls them with the right parameters.

MCP is not a REST API. A REST API is designed for application developers who read documentation, understand endpoints, and write integration code. MCP is designed for AI models — the tool descriptions are written in natural language so the model can reason about when and how to use them.

Here's a simplified example. A REST API endpoint might look like this:

GET /api/v1/deals?sector=auto&city=calgary&limit=5
Authorization: Bearer pk_live_abc123

The equivalent MCP tool declaration looks like this:

{
  "name": "fetch_deals",
  "description": "Fetch current deals and time-sensitive
    offers from local businesses. Returns live signals
    like pricing, inventory urgency, and expiration dates.
    Use when the user is looking for active promotions
    or wants to know what's available right now.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "sector_id": {
        "type": "string",
        "description": "Business sector (e.g. 'auto', 'hospitality')"
      },
      "city": {
        "type": "string",
        "description": "City name for geographic filtering"
      }
    }
  }
}

The difference is intent. The REST endpoint is for a developer who already knows what fetch_deals does. The MCP declaration is for a model that needs to decide — in the middle of a conversation — whether this tool is relevant and what arguments to pass.

Why MCP over REST

We considered just building a REST API. It would have been simpler. But three factors pushed us toward MCP.

Agent-native discovery. With a REST API, every agent developer needs to write custom integration code. They need to read our docs, understand our endpoints, map their user's intent to our parameters, and handle our response format. With MCP, the agent discovers our tools automatically. The model reads the tool descriptions, understands what they do, and calls them when relevant. No integration code. No custom mapping. The agent framework handles it.

Multi-tool orchestration. A local query often requires multiple data lookups. "Find me a quiet hotel in Banff that's pet-friendly and has a deal this weekend" might need a call to match_buyer (to find matching properties), then fetch_deals (to check for weekend specials), then context from the business profile. MCP lets the model orchestrate these calls naturally within a conversation, deciding what to call next based on what it already knows. REST APIs can do this too, but the orchestration logic has to be hand-coded.

Framework agnostic. Claude Desktop, OpenAI's GPT Actions, LangChain, AutoGPT, custom agents — they all support or are adding support for MCP. Building one MCP server means every agent framework can connect to Pawlo's data without us building separate integrations for each one.

Architecture: Cloudflare at the edge

We run the Pawlo MCP server on Cloudflare Workers. The architecture looks like this:

Agent Request
      |
      v
[Gateway Worker]  gateway.pawlo.ai
   - API key validation
   - Rate limiting
   - Request routing
      |
      v
[MCP Worker]  mcp.pawlo.ai
   - Tool declarations
   - Business logic
   - D1 queries
      |
      v
[Cloudflare D1]  pawlo-db
   - Business profiles
   - Deals & signals
   - Sector schemas

Every request enters through the Gateway Worker, which validates the API key, enforces rate limits, and routes to the MCP Worker. The MCP Worker handles tool execution — parsing parameters, querying D1, formatting responses.

Why Cloudflare Workers? Three reasons that matter for local data.

Cold start is effectively zero. Workers run on V8 isolates, not containers. There's no cold start penalty. When an agent calls fetch_deals, the response starts generating in single-digit milliseconds. For real-time agent interactions where the user is waiting, this matters.

D1 is colocated. Cloudflare D1 is a SQLite-based database that runs at the edge. Our queries — "find all auto dealerships in Calgary with active deals" — execute on the same infrastructure that serves the request. No round-trip to a centralized database.

Cost scales to zero. Workers bills per request, not per hour. If no agent calls Pawlo for an hour, we pay nothing for that hour. For an early-stage data layer where traffic is spiky and unpredictable, this is the right economic model.

The tool surface

Pawlo currently exposes a small, deliberate tool surface. We resist the urge to add tools and instead focus on making each one return the data agents actually need.

fetch_deals — Returns live deals and time-sensitive signals for a sector and location. Deals have expiration dates and urgency indicators. An agent calling this tool gets data that's useful today and will be stale tomorrow.

match_buyer — The core matching tool. Takes a natural language description of what the buyer needs and returns ranked businesses with match explanations. This is where nuance matters most — the match quality depends entirely on the depth of the business profiles in our database.

resolve_sector_id — A utility tool that helps agents map natural language sector descriptions ("car dealerships," "pet groomers," "boutique hotels") to our internal sector identifiers. This makes the other tools easier to call correctly.

Each tool is designed to be self-contained. An agent can call one tool and get a useful result, or chain multiple tools together for a richer answer. The tool descriptions are written so that a model can decide which to call without any prior knowledge of Pawlo's API.

What we learned

Building an MCP server is straightforward. Making it useful for agents in practice required learning a few things the hard way.

Tool descriptions are prompts. The natural language description of each tool is, in effect, a prompt that every calling model will read. Vague descriptions lead to wrong calls. We iterated on our tool descriptions more than on any other part of the system. The description for match_buyer went through eleven revisions before agents consistently called it with the right parameters.

Return less, explain more. Our early responses dumped entire business profiles into the tool output. Models struggled to synthesize this into natural conversation. We switched to returning structured summaries with a match_reason field — a one-sentence explanation of why this business matches the query. Agent responses immediately improved.

Agents will surprise you. Once your MCP server is live, agents will call your tools in ways you didn't anticipate. We saw agents chain resolve_sector_id into match_buyer into fetch_deals in a single turn — a workflow we hadn't explicitly designed but that worked because each tool returned clean, composable data.

If you're building an agent that handles local queries and you need data that goes beyond what's publicly scrapable, this is the kind of infrastructure that makes it possible. The code is open, the protocol is standard, and the data layer is the part that actually matters.

Pawlo is the data layer for local AI — structured business intelligence that AI agents can fetch in milliseconds.

Join WaitlistList Your Business Free
← Back to blog