Skip to main content

Building a BatchData MCP Demo App with Replit

Learn how to rapidly build an AI-powered chatbot that demonstrates the BatchData MCP server using Replit's coding agent.

Written by Charles Parra
Updated over 2 months ago

Learn how to rapidly build an AI-powered chatbot that demonstrates the BatchData MCP server using Replit's coding agent and AI-assisted development best practices.

Overview

This guide walks you through creating a demo application that showcases the BatchData MCP (Model Context Protocol) server. The app provides a simple AI chatbot interface where users can query property data using natural language—making it an excellent tool for exploring MCP capabilities before integrating them into production applications.

What You'll Build: - A real-time chatbot interface - Natural language queries for property lookups, skip tracing, and comparable properties - Dual response display: human-readable summaries and raw JSON data - WebSocket-based communication with the BatchData MCP server

Time to Build: ~15-30 minutes with Replit Agent

Prerequisites

The AI-Assisted Development Approach

Why Start with Planning?

When using AI coding assistants like Replit Agent, the quality of your output directly correlates with the quality of your input. Rather than jumping straight into code, we followed established best practices for AI-assisted development:

  1. Define the goal clearly - What exactly should the app do?

  2. Capture requirements - What features, tools, and behaviors are needed?

  3. Create a structured prompt - Translate requirements into actionable instructions

  4. Iterate and refine - Test and adjust based on results

How We Built This Prompt

We used Claude to help compile requirements and create the Replit Agent prompt. Here's how the process worked:

Starting Point:

"I want to create a demo app that could be built in Replit that would create a simple AI chatbot that makes use of the BatchData MCP server."

Key Decisions Made During Planning:

  1. Reference Property - We chose a specific address for all examples:

  2. 632 W Palmaire Ave, Phoenix, AZ 85021

  3. Coordinates: 33.541474, -112.081784

  4. Response Display - We specified that the app should show both:

  5. A formatted, human-readable summary of key data points

  6. The complete raw JSON response for transparency and debugging

  7. Tool Selection - We identified which BatchData MCP tools to support and how to map natural language queries to them

  8. API Response Structure - We documented the actual response format from testing to ensure the app parses data correctly

This planning process with Claude produced a comprehensive prompt that Replit Agent can use to build the complete application.

Step-by-Step Guide

Step 1: Create a New Replit Project

  1. Go to replit.com and sign in

  2. Click Projects in the left sidebar

  3. Click Create Project

  4. Name your project (e.g., "BatchData-MCP-Demo")

  5. Click Create Project to confirm

Step 2: Create an App with Replit Agent

  1. Inside your new project, click Create App (or use the + button)

  2. Select Agent to use the AI coding assistant

  3. Copy the entire prompt from the The Prompt section below

  4. Paste it into the Replit Agent chat

  5. Let the agent build your application

The agent will: - Set up the Express server with WebSocket support - Implement the MCP client integration - Create the React frontend with the chat interface - Build the ResponseCard component for formatting responses - Configure the build system

Step 3: Add Your API Key

After the agent creates your app, add your BatchData API key as a secret:

  1. In your Replit app workspace, use the Search bar (magnifying glass icon) and type "Secrets"

  2. Select Secrets from the search results

  3. Click New Secret

  4. Set the Key as BATCHDATA_API_KEY

  5. Paste your BatchData API key as the Value

  6. Click Add Secret

Note: Secrets are encrypted and injected as environment variables when your app runs. They are not committed to version control.

Step 4: Test Your App

Once the agent finishes, click Run to start the application. Try these example queries:

Query

What It Does

"Verify the address 632 W Palmaire Ave, Phoenix, AZ 85021"

Validates and standardizes the address

"Lookup property details for 632 W Palmaire Ave, Phoenix, AZ 85021"

Returns property characteristics, valuation, and owner info

"Find comparable properties to 632 W Palmaire Ave, Phoenix, AZ 85021"

Finds similar properties with pricing metrics

"Geocode 632 W Palmaire Ave, Phoenix, AZ 85021"

Converts address to latitude/longitude

"Reverse geocode 33.541474, -112.081784"

Converts coordinates to an address

"Skip trace the owner at 632 W Palmaire Ave, Phoenix, AZ 85021"

Finds owner contact information

Step 5: Deploy (Optional)

To share your demo app:

  1. Click Publish in the top-right corner

  2. Choose your deployment settings

  3. Click Publish to make it live

Understanding the App Architecture

How It Works

┌─────────────────┐     WebSocket      ┌─────────────────┐
│   React Frontend │◄──────────────────►│  Express Server  │
│   (Chat UI)      │                    │  (Node.js)       │
└─────────────────┘                    └────────┬────────┘
                                                │
                                                │ HTTP + Bearer Auth
                                                ▼
                                       ┌─────────────────┐
                                       │  BatchData MCP   │
                                       │  Server          │
                                       │  mcp.batchdata.com│
                                       └─────────────────┘

  1. User enters a query in the chat interface

  2. Frontend sends query via WebSocket to the Express server

  3. Server parses the query to determine intent and extract parameters

  4. Server calls the appropriate MCP tool via the Vercel AI SDK

  5. Response is formatted and sent back to the frontend

  6. Frontend displays both formatted summary and raw JSON

Supported MCP Tools

Tool

Description

Example Query

verify_address

Validate and standardize addresses

"Verify 123 Main St, Phoenix, AZ"

lookup_property

Get property details and valuation

"Lookup property at 123 Main St"

geocode_address

Convert address to coordinates

"Geocode 123 Main St, Phoenix, AZ"

reverse_geocode_address

Convert coordinates to address

"Reverse geocode 33.45, -112.07"

comparable_property_preview

Find comparable properties

"Find comps for 123 Main St"

skip_trace_property

Find owner contact info

"Skip trace owner at 123 Main St"

verify_phone

Validate phone numbers

"Verify phone 6025551234"

check_dnc_status

Check Do Not Call registry

"Check DNC for 6025551234"

check_tcpa_status

Check TCPA compliance

"Check TCPA for 6025551234"

Response Display

Each response shows two views:

Formatted Summary - Human-readable card highlighting key information:

✅ Address Verified632 W Palmaire Ave
Phoenix, AZ 85021-8767County: Maricopa
Congressional District: 01
Time Zone: Mountain (UTC-7)
Vacant: No📍 Coordinates: 33.541180, -112.081990

Raw JSON - Collapsible section with the complete API response for debugging and integration planning.

The Prompt

Copy the entire prompt below and paste it into Replit Agent to build your demo app.

Create a real-time chatbot application that demonstrates the BatchData MCP (Model Context Protocol) server for property intelligence. The app should let users query real estate data using natural language.## Tech Stack
- **Frontend**: React, TypeScript, TailwindCSS
- **Backend**: Express.js with WebSocket support
- **MCP Integration**: Vercel AI SDK (@ai-sdk/mcp)
- **Build**: Vite for frontend, esbuild for server bundling## Environment Variables
BATCHDATA_API_KEY=<user's BatchData API key>## Key Dependencies
{
  "dependencies": {
    "@ai-sdk/mcp": "^0.0.12",
    "@modelcontextprotocol/sdk": "^1.25.1",
    "express": "^4.21.2",
    "ws": "^8.18.0",
    "react": "^19.2.0",
    "react-dom": "^19.2.0"
  }
}---## SERVER IMPLEMENTATION### MCP Client Integrationimport { experimental_createMCPClient as createMCPClient } from "@ai-sdk/mcp";const MCP_SERVER_URL = "https://mcp.batchdata.com";export async function connectToMCP(serverUrl: string, apiKey: string) {
  const mcpClient = await createMCPClient({
    transport: {
      type: "http",
      url: serverUrl,
      headers: {
        Authorization: `Bearer ${apiKey}`,
      },
    },
  });
  const toolSet = await mcpClient.tools();
  return { mcpClient, toolSet };
}export async function callMCPTool(toolName: string, args: Record<string, any>) {
  const tool = cachedToolSet[toolName];
  return await tool.execute(args, { toolCallId: `call_${Date.now()}` });
}### Available BatchData MCP Tools
- verify_address: Verify and standardize an address
- lookup_property: Get property details
- geocode_address: Convert address to coordinates
- reverse_geocode_address: Convert coordinates to address
- comparable_property_preview: Find comparable properties (use this for "find comps" queries)
- skip_trace_property: Find owner contact info
- verify_phone: Validate phone numbers
- check_dnc_status: Check Do Not Call registry
- check_tcpa_status: Check TCPA complianceIMPORTANT: Do NOT use the deprecated `comparable_property` tool. Use `comparable_property_preview` instead.### Query-to-Tool Mapping
Parse natural language queries and map to BatchData MCP tools:
- "verify address..." → verify_address
- "lookup property..." → lookup_property
- "geocode..." → geocode_address
- "reverse geocode..." → reverse_geocode_address
- "comparable properties..." or "find comps..." → comparable_property_preview
- "skip trace..." → skip_trace_property
- "verify phone..." → verify_phone
- "check dnc..." → check_dnc_status
- "check tcpa..." → check_tcpa_status### Tool Parameter Naming
BatchData MCP uses specific parameter prefixes:
- Property lookups: property_street, property_city, property_state, property_zip
- Comparables: subject_property_street, subject_property_city, subject_property_state, subject_property_zip
- Address verification: street, city, state, zip
- Geocoding: property_address (full address string)
- Phone tools: phone_number (10-digit string, no formatting)---## FRONTEND REQUIREMENTS### Core Functionality
1. Chat interface for natural language queries
2. Real-time WebSocket communication with the server
3. Connection status indicator
4. Example queries users can click to try### Response Display (CRITICAL)
Each response MUST display BOTH:
1. **Formatted Summary** - Human-readable display of key data points from the response
2. **Raw JSON** - Collapsible section showing the complete API response (for debugging/transparency)### API Response Structure
MCP tool responses come wrapped in this structure:
{
  "content": [{ "type": "text", "text": "<stringified JSON>" }],
  "structuredContent": { /* actual data object */ },
  "isError": false
}ALWAYS parse from `structuredContent` - this contains the actual data object.
Do NOT parse from `content[0].text` as that's just a stringified version.### Data Parsing HelpersOwner names in responses can be either strings OR objects with {first, last, full} properties.
Use a helper function to safely display names:    function getDisplayName(name: any): string {
      if (!name) return 'Unknown';
      if (typeof name === 'string') return name;
      if (typeof name === 'object') {
        if (name.full) return name.full;
        if (name.first || name.last) {
          return ((name.first || '') + ' ' + (name.last || '')).trim();
        }
      }
      return 'Unknown';
    }Use this helper for: lookup_property (owner names), skip_trace_property (owner/contact names).Geocode responses may have nested coordinates. Check these paths:
- structuredContent.results[0].latitude/longitude
- structuredContent.result.latitude/longitude
- structuredContent.location.latitude/longitude
- structuredContent.latitude/longitude (direct)### Key Data Points by Tool**verify_address** - structuredContent.address:
- Standardized address (street, city, state, zip, zipPlus4)
- addressValidity field indicates if valid
- County, coordinates, time zone info**lookup_property** - structuredContent.property:
- Address, building info (beds, baths, sqft, year built)
- Valuation (estimatedValue)
- Owner names (use getDisplayName helper)
- Lot size**comparable_property_preview** - structuredContent:
- comparableCount, aggregatedMetrics (averagePrice, pricePerSqFt)
- comparableProperties[] array with address, salePrice, squareFeet, distance**skip_trace_property** - structuredContent:
- Owner/contact names (use getDisplayName helper - names can be objects!)
- Phone numbers with lineType
- Email addresses**geocode_address / reverse_geocode_address**:
- Coordinates (latitude, longitude) - may be nested in results[0] or location
- Formatted address**verify_phone** - structuredContent:
- Valid/invalid status
- Line type, carrier, location**check_dnc_status** - structuredContent:
- Whether phone is on Do Not Call list**check_tcpa_status** - structuredContent:
- Litigator status and compliance info---## BUILD CONFIGURATIONIMPORTANT: Bundle ALL dependencies for reliable deployments. Do NOT mark packages as external.esbuild external setting should be empty or only include Node.js built-ins.
Bundle these packages (required for deployment):
- @ai-sdk/mcp
- @modelcontextprotocol/sdk
- express, ws, and all other dependenciesThis prevents MODULE_NOT_FOUND errors in deployment.### .replit Configuration
modules = ["nodejs-20"]
[deployment]
deploymentTarget = "autoscale"
run = ["npm", "run", "start"]
build = ["npm", "run", "build"]
[[ports]]
localPort = 5000
externalPort = 80---## EXAMPLE QUERIES TO SUPPORTUse this reference address for testing: 632 W Palmaire Ave, Phoenix, AZ 85021
Coordinates: 33.541474, -112.081784- "Verify the address 632 W Palmaire Ave, Phoenix, AZ 85021"
- "Lookup property details for 632 W Palmaire Ave, Phoenix, AZ 85021"
- "Find comparable properties to 632 W Palmaire Ave, Phoenix, AZ 85021"
- "Geocode 632 W Palmaire Ave, Phoenix, AZ 85021"
- "Reverse geocode 33.541474, -112.081784"
- "Skip trace the owner at 632 W Palmaire Ave, Phoenix, AZ 85021"---## DEMO/FALLBACK MODEIf MCP connection fails (e.g., missing API key), show a demo mode that:
- Indicates the app is in demo mode
- Prompts user to add BATCHDATA_API_KEY to secrets
- Explains what each tool would return---Create this application with a clean, modern UI. Focus on making the tool responses easy to read while also providing access to the raw JSON data.


Customizing Your Demo

Once you have the basic app running, consider these enhancements:

Add More Example Queries

Edit the "Try These" section in the sidebar to include queries relevant to your use case.

Customize the UI

The app uses TailwindCSS and Shadcn/UI components. Modify colors, layouts, and branding in: - client/src/index.css - Global styles - client/src/pages/home.tsx - Main layout

Extend Tool Support

To support additional BatchData MCP tools: 1. Add the query pattern in server/routes.ts 2. Create a formatter in client/src/components/ResponseCard.tsx

Troubleshooting

"Connection failed" error - Verify BATCHDATA_API_KEY is set in Replit Secrets - Check that your API key is valid at batchdata.com

"Tool not found" error - The app discovers tools dynamically on connection - Try disconnecting and reconnecting

WebSocket disconnects - The app auto-reconnects after 3 seconds - Check the System Logs panel for error details

Comparables showing "0 found" - Ensure the app uses comparable_property_preview (not the deprecated comparable_property)

App crashes when displaying skip trace results - Owner names in skip trace responses can be objects ({first, last, full}) instead of plain strings - Use the getDisplayName() helper function to safely handle both formats

Deployment crash loops with MODULE_NOT_FOUND - This happens when dependencies are marked as "external" in esbuild but not available at runtime - Fix: In script/build.ts, ensure esbuild does NOT externalize @ai-sdk/mcp or @modelcontextprotocol/sdk - All dependencies should be bundled into dist/index.cjs

Best Practices for AI-Assisted Development

Based on our experience building this demo, here are key takeaways:

  1. Start with clear requirements - Define what you want before engaging the AI

  2. Use a reference example - Concrete examples (like our Phoenix address) help the AI understand expected behavior

  3. Specify output formats - We explicitly requested both JSON and human-readable formats

  4. Document API structures - Include actual response formats to ensure correct parsing

  5. Iterate incrementally - Test each feature before moving to the next

  6. Keep prompts structured - Use headings, lists, and code blocks for clarity

Next Steps

Now that you have a working demo app, explore these resources:

Support

For technical support, questions, or integration assistance:

When contacting support, please include: - BatchData Account name - Tool name and parameters used - Error messages or unexpected behavior

Did this answer your question?