How to use MCP agents to access multiple data stores

David Tracey

How to use MCP agents to access multiple data stores

This blog is the second of a three part series on the Agent2Agent (A2A) protocol and agentic querying of data. It will demonstrate how easy it is to create two simple agents to query different data sources using MCP and then analyse their outputs using Claude. The first agent can access a SQL database and the second agent uses Bronto's REST API to access our dedicated, high performance logging platform.

The Bronto API client in the MCP Server could be extended to offer other features, but a better approach for more complex usage of the API and to use Bronto's rich set of features would be to install the local Bronto MCP Server detailed in an earlier blog or the recently released remote MCP Server.

You can set up a 14 day Free Trial to test the Bronto REST API client used here.

The final post in the series will extend the scenario from this blog by using A2A enabled agents to simply access multiple, disparate data sources including the Bronto logging platform. (Part 1 was an introduction to Agent2Agent (A2A) protocol and agentic search, explaining how agents collaborate, how A2A complements Model Context Protocol (MCP), and how to build a simple working agent example.)

The scenario

The example use case to be demonstrated here is what happens when an employee leaves a company and the IT department wants to determine that their name and access has been removed from all systems, such as the HR database and the company's logging service, using Bronto's platform as an example. Traditionally, that would be done by an IT person checking each system separately, using specific tools or in-house scripts, having been notified of the employee's departure.

In order to demonstrate the usage of MCP for this scenario and shown in the diagram below, we will:

  • Create a simple Bronto REST API client to get Bronto users

  • Create a simple database server representing a SQL database holding HR details

  • Create an MCP Demonstration that will:

    • Extend the sample clients and make their services available as tools using an MCP server

    • Show Claude using those MCP servers to check for a user name with a prompt like "Show me Bronto employees, check if they have Bronto user accounts and summarise what you find"

Architecture diagram showing Claude orchestrating two MCP servers — one wrapping the Bronto REST API and one wrapping a SQLite employee database

Create a Bronto REST API client

We begin by creating a REST API client, bronto-user-get.py, that makes an API request with the correct credentials and role to the Bronto /users endpoint (https://api.{region}.brontobytes.io/users). The source code is shown in Appendix 1. Run the client with:

python -m venv ./env
source ./env/bin/activate
pip install requests
python bronto-user-get.py

This will return a JSON response with information for all users, as shown in the following example for one user:

{
  "users": [
    {
      "id": "00000ffff",
      "first_name": "Paul",
      "last_name": "McCartney",
      "email": "paul@beatles.io",
      "roles": ["1111", "Admin"],
      "last_logins": { "Google": 22228 },
      "login_methods": [],
      "tags": { "team": "fabfour" },
      "status": "ACTIVE",
      "invited_at": 0,
      "invited_by": "john"
    }
  ]
}

Create a simple employee database

The setup instructions for SQLite and the code for a simple SQLite client can be found in Appendix 2.

Once SQLite is installed, connect to it and create the database bronto_employee.db for the demo:

sqlite3 bronto_employee.db

At the sqlite> prompt, create the table and add some employees. Note that Id is set as INTEGER PRIMARY KEY AUTOINCREMENT for automatic ID generation:

CREATE TABLE Employee (
  Id INTEGER PRIMARY KEY AUTOINCREMENT,
  FirstName TEXT NOT NULL,
  LastName TEXT NOT NULL,
  HireDate DATE NOT NULL
);

INSERT INTO Employee (FirstName, LastName, HireDate) VALUES
  ('Paul', 'McCartney', '2025-07-22'),
  ('Ringo', 'Starr', '2024-10-22'),
  ('George', 'Harrison', '2024-06-01'),
  ('John', 'Lennon', '2025-11-05');

MCP demonstration

The Model Context Protocol (MCP) is an open specification that provides a standardized way to connect LLMs to tools and data, giving a secure, reliable way for LLMs to access APIs and data. We will use FastMCP in this demo. A useful link explaining how to use FastMCP and code samples can be found at apidog.com/blog/fastmcp.

Add an MCP server to the sample Bronto REST API client

For this demo, we will extend the Bronto REST API client to create a simple MCP server, mcp-bronto-user-get.py, that uses FastMCP to expose a get_bronto_users() tool, which gets the users in your Bronto account.

To do this, we make the following changes to the simple Bronto REST API client (full sample source code in Appendix 1):

  • Add an import for FastMCP — from fastmcp import FastMCP

  • Initialize the MCP server with a friendly name — mcp = FastMCP("Bronto Users")

  • Add an annotation before each method to be exposed as a tool to the MCP server — @mcp.tool() above def get_bronto_users():

  • Run the MCP server locally by replacing the call to get_bronto_users() in main with mcp.run()

A simple client to use with this MCP server, mcp-client.py, is shown in Appendix 1. It uses an imported Client from FastMCP and async operation, checks the tools returned by the MCP server for the get_bronto_users tool, and then calls it with result = await client.call_tool("get_bronto_users").

To demonstrate this MCP server and MCP client, in one terminal create a virtual Python environment and run the Bronto get users MCP server with the FastMCP CLI:

python -m venv ./env
source ./env/bin/activate
pip install fastmcp
fastmcp run mcp-bronto-user-get.py:mcp --transport sse --port 8080 --host 0.0.0.0 --log-level DEBUG

In another terminal, run the MCP client to receive the REST API JSON response with the users:

python mcp-client.py

Add an MCP server to the employee database client

For this demo, we can extend the simple DB client into an MCP server to access the employee database. To create the MCP server mcp-sqlite-server.py and its client mcp-get-employees-client.py, take the same steps as for the Bronto REST API server and client (with full source code for both in Appendix 2):

  • Add an import for FastMCP — from fastmcp import FastMCP

  • Initialize the MCP server with a friendly name — mcp = FastMCP("Employee DB")

  • Add an annotation before each method to be exposed as a tool to the MCP server — @mcp.tool() above def get_employees():

  • Run the MCP server locally by replacing the call to get_employees() in main with mcp.run()

The simple client to use with this MCP server is shown in Appendix 2. It uses an imported Client from FastMCP and async operation, and calls the get_employees tool in the MCP server with result = await client.call_tool("get_employees").

To demonstrate this MCP server and MCP client, in one terminal create a virtual Python environment and run the employee database MCP server with the FastMCP CLI:

python -m venv ./env
source ./env/bin/activate
pip install fastmcp
fastmcp run mcp-sqlite-server.py:mcp --transport sse --port 8081

In another terminal, run the employee database client. It's the MCP client used above for Bronto users, updated to use the port for this MCP server and to check for and call the get_employees tool, and it returns a JSON response with the employees:

python mcp-get-employees-client.py

FastMCP CLI

Note we ran the MCP servers with the FastMCP CLI, which also has some other useful commands, depending on the version, that can help when getting your clients and servers working. For example, running fastmcp inspect mcp-sqlite-server.py returns a summary like this:

✓ Inspected server: FastMCP Employee DB
Tools: 2 · Prompts: 0 · Resources: 0 · Templates: 0
Report saved to: server-info.json

Add the MCP Servers to Claude

Rather than running an MCP server and having to code a client to call tools in that MCP server, we can simplify their use by installing Claude Desktop locally.

Both mcp-bronto-user-get.py and mcp-sqlite-server.py can be added to the local JSON configuration file for Claude, as shown in the snippet below; just adjust the command and directories for your setup. On a Mac, this configuration file is located at ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "EmployeeDB": {
      "command": "/path/to/test-mcp/mcp-env/bin/python",
      "args": ["/path/to/test-mcp/mcp-sqlite-server.py"],
      "description": "A simple MCP server to query employeeId data from a database"
    },
    "BrontoUsers": {
      "command": "/path/to/test-mcp/mcp-env/bin/python",
      "args": ["/path/to/test-mcp/mcp-bronto-user-get.py"],
      "description": "A simple MCP server to query Bronto Users"
    }
  }
}

With this configuration, both servers are registered as MCP servers with Claude and will be started automatically by Claude.

To see if this worked, go into Claude Settings, then select Developer, and you should see a screen "Local MCP Servers".

Then enter a prompt in Claude that accesses both data stores as in the example below. Depending on what users you have in the database or added to your Bronto account, Claude will give a reply like the one below (usernames and details are changed from actual response):

Prompt

Show me Bronto employees, check if they have Bronto user accounts and summarise what you find

Claude's response

I'll retrieve the employee data and check their Bronto user accounts, then provide you with a summary.

Used 2 integrations

Summary of Bronto employees and user accounts

  • Employee Database: 4 employees total

  • Bronto User Accounts: 8 active user accounts

Account coverage analysis:

Employees WITH Bronto accounts (3 out of 4):

  • Paul McCartney — 2 accounts (@beatles.io, @wings.io) — Admin role

  • George Harrison — 2 accounts (@beatles.io, @wilburys.io) — Admin

  • John Lennon — 4 accounts (various domains) — Admin/ReadOnly roles

Employee WITHOUT Bronto account:

  • Ringo Starr — No user account found

Key findings:

  • 75% coverage — 3 out of 4 employees have Bronto accounts

  • Most employees have multiple accounts (likely for testing/different environments)

  • Predominantly Admin roles across the board

  • One main domain: @beatles.io

  • Team tags include "fabfour" and "scousers"

  • Additional users not in the employee list (George Martin) suggest either external contractors or the employee list isn't complete

Summary

As can be seen from the sample Claude response, the simple MCP Servers have enabled a much richer return of information very easily compared to the IT person having to use custom tools per data store. This benefit increases as the number of data stores available via agents grows.

This simple demo scenario also showed that there was no need to move any data to a new database or data lake to get access to all the data in a world of AI agents using MCP. In this case the data could stay in the most suitable data storage i.e. logs in the Bronto logging platform and tabular HR data in a SQL database, but both data sources could be accessed by using agents specific to where that data was stored.

Start a Free Trial of Bronto

Try Bronto for free for 14 days to centralize agent logs in one platform with sub-second search.

Start a Free Trial of Bronto →

Appendix 1 - Code Samples for Bronto REST API

Note: All code samples here are for demonstration purposes only as the code is not written for efficiency or with comprehensive error handling.

Code for Bronto REST API Client

The following code, bronto-user-get.py, calls the Bronto REST API /users endpoint to retrieve all users for a given organisation.

import json
import logging

from requests import Session
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger()
handler = logging.FileHandler('/path/to/test-mcp/bronto_client.log')
handler.setLevel(logging.DEBUG)
# Define the log message format
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
# Attach the handler to the logger
logger.addHandler(handler)

ADMIN_API_KEY = "SomeKey"
DATA_STORAGE_REGION = 'us'  # Swap for your region


def get_users(s: Session) -> None:
    response = s.get(
        f"https://api.{DATA_STORAGE_REGION}.brontobytes.io/users",
        headers={'X-BRONTO-API-KEY': ADMIN_API_KEY},
    )
    logger.warning('status=%s', response.status_code)
    logger.info('dump=%s', json.dumps(response.json()))
    print(json.dumps(response.json(), indent=4))


if __name__ == '__main__':
    session = Session()
    session.mount(
        f'https://api.{DATA_STORAGE_REGION}.brontobytes.io',
        HTTPAdapter(max_retries=(
            Retry(total=3, backoff_factor=1, status_forcelist=[500, 502, 503, 504])
        )),
    )
    get_users(session)

Code for Sample Bronto MCP Server and MCP Client to get users

Save the MCP server as mcp-bronto-user-get.py:

import json
import logging

from fastmcp import FastMCP
from requests import Session
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger()
handler = logging.FileHandler('/path/to/test-mcp/mcp-bronto-user-get.log')
handler.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)

# Initialize the MCP server with a friendly name
mcp = FastMCP("Bronto Users")

ADMIN_API_KEY = "SomeKey"
DATA_STORAGE_REGION = 'us'  # Swap for your region


@mcp.tool()
def get_bronto_users():
    session = Session()
    session.mount(
        f'https://api.{DATA_STORAGE_REGION}.brontobytes.io',
        HTTPAdapter(max_retries=(
            Retry(total=3, backoff_factor=1, status_forcelist=[500, 502, 503, 504])
        )),
    )
    response = session.get(
        f"https://api.{DATA_STORAGE_REGION}.brontobytes.io/users",
        headers={'X-BRONTO-API-KEY': ADMIN_API_KEY},
    )
    logger.warning('content=%s', response.json())
    return response.json()


# Run the MCP server locally
if __name__ == '__main__':
    mcp.run()

The source code for a simple MCP client, mcp-client.py, to call get_bronto_users() follows:

import asyncio

from fastmcp import Client


async def call_server():
    # Connect to a server run with:
    # fastmcp run mcp-bronto-user-get.py:mcp --transport sse --port 8080
    client = Client("http://localhost:8080/sse")
    try:
        async with client:
            await client.ping()  # Only included for demo to test connection
            print("Past ping")
            tools = await client.list_tools()
            print(f"Available tools: {tools}")
            if any(tool.name == "get_bronto_users" for tool in tools):
                print("Tool 'get_bronto_users' found. Calling now...")
                employees = await client.call_tool("get_bronto_users")
                print(f"Employees with Bronto Accounts: {employees}")
            else:
                print("Warning: 'get_bronto_users' tool is not available on this server.")
    except Exception as e:
        print(f"An error occurred: {e}")
    finally:
        print("--- Client Interaction Finished ---")


if __name__ == "__main__":
    asyncio.run(call_server())

Appendix 2 - Setup and Code Samples for SQLite

Note: All code samples here are for demonstration purposes only as the code is not written for efficiency or with comprehensive error handling.

Setup

Download the zip file holding the precompiled binaries from sqlite.org/download.html for your system or use brew install sqlite on a Mac.

Then create a simple Python script, like sqlite-simple-client.py below, which returns a list of employees, and run it with:

python sqlite-simple-client.py

Sample Client Source Code

Save the simple client as sqlite-simple-client.py:

import sqlite3

# From https://www.sqlitetutorial.net/sqlite-sample-database/
# Simple client to fetch employees from a SQLite database


def get_employees():
    conn = sqlite3.connect('bronto_employee.db')
    cursor = conn.cursor()
    cursor.execute("SELECT LastName, FirstName FROM Employee ORDER BY HireDate DESC")
    results = cursor.fetchall()
    conn.close()
    employees = [
        {"LastName": LastName, "FirstName": FirstName}
        for LastName, FirstName in results
    ]
    return employees


if __name__ == '__main__':
    employees = get_employees()
    print("List of Employees: ")
    print(employees)

MCP Code Samples for Employee Database

Sample Server Source Code

Save the MCP server as mcp-sqlite-server.py:

import sqlite3

from fastmcp import FastMCP

# Initialize the MCP server with a friendly name
mcp = FastMCP("Employee DB")


@mcp.tool()
def get_employees():
    conn = sqlite3.connect('/path/to/test-mcp/bronto_employee.db')
    cursor = conn.cursor()
    cursor.execute("SELECT LastName, FirstName FROM Employee ORDER BY HireDate DESC")
    results = cursor.fetchall()
    conn.close()
    employees = [
        {"LastName": LastName, "FirstName": FirstName}
        for LastName, FirstName in results
    ]
    return employees


# Run the MCP server locally
if __name__ == '__main__':
    mcp.run()

Sample Client Source Code

Save the MCP client as mcp-get-employees-client.py:

import asyncio

from fastmcp import Client


async def mcp_call_get_employees():
    # Connect to a server run with:
    # fastmcp run mcp-sqlite-server.py:mcp --transport sse --port 8081
    client = Client("http://localhost:8081/sse")
    try:
        async with client:
            print("--- Client Connected ---")
            await client.ping()
            tools = await client.list_tools()
            print(f"Available tools: {tools}")
            if any(tool.name == "get_employees" for tool in tools):
                print("Tool 'get_employees' found. Calling now...")
                employees = await client.call_tool("get_employees")
                print(f"Employees in Database: {employees}")
            else:
                print("Warning: 'get_employees' tool is not available on this server.")
    except Exception as e:
        print(f"An error occurred: {e}")
    finally:
        print("--- Client Interaction Finished ---")


if __name__ == "__main__":
    asyncio.run(mcp_call_get_employees())

Enjoyed this post?

Share it with your team or network.

Free trial

Try Bronto free for 14 days

Centralize your agent and infrastructure telemetry in one platform with sub-second search and 12-month hot retention.

  • 14-day free trial
  • No credit card
  • Set up in minutes