DEV Community

Cover image for Bridging Fintech and Agentic AI: Building a Paystack MCP Server in Python
Akinshola Samuel AKINDE
Akinshola Samuel AKINDE

Posted on

Bridging Fintech and Agentic AI: Building a Paystack MCP Server in Python

If you’ve been following the AI space lately, you’ve probably heard of the Model Context Protocol (MCP). It is rapidly becoming the gold standard for connecting Large Language Models (LLMs) to external tools and databases.

We are seeing a massive surge in MCP servers for developer tools like GitHub, Postgres, and SQLite. But what about the Fintech space? It has remained largely untapped—until now.

I’m excited to share a project I had published over 6months ago on GitHub: the Paystack MCP Server. It’s a Python-based server that bridges the gap between Paystack (Africa’s premier payment gateway) and agentic AI interfaces like Claude Desktop.

Instead of writing manual cURL requests or digging through your Paystack dashboard, you can now just ask your AI agent to verify transactions, fetch customer details, or process refunds. Let's dive into how it works and how you can run it locally!

Core Capabilities

The Paystack MCP Server wraps the Paystack API into "Tools" that LLMs can naturally understand and execute. Currently, the server exposes the following critical endpoints:

  • verify_transaction: Confirms the status of a payment using a reference code.
  • fetch_transaction: Retrieves detailed metadata about a specific transaction ID.
  • create_customer: Registers a new customer on your Paystack integration.
  • fetch_customer: Retrieves customer details via email or ID.
  • list_transactions: Fetches a history of recent transactions (with pagination support).
  • initiate_refund: Processes refunds for disputes or errors.

Technical Deep Dive: How the Logic Works

I built this project using Python and the official mcp SDK. Right now, it leverages a synchronous architecture (using the good old requests library) for solid reliability.

At its core, the server uses the FastMCP pattern to strip away unnecessary boilerplate. Here is how the flow works when you prompt your AI:

  1. You ask: "Check if transaction T12345 was successful."
  2. Claude (MCP Client): Sees that the verify_transaction tool perfectly matches your intent.
  3. MCP Server: Receives the tool call and routes it directly to our Python function.
  4. Paystack API: The function fires a GET request to https://api.paystack.co/transaction/verify/T12345.
  5. Response: The JSON data is cleaned up, formatted, and sent back to the LLM so it can reply to you in natural language.

Code Sample: Transaction Verification

Here is a quick look under the hood at how the verification logic is implemented (simplified for readability):

from mcp.server.fastmcp import FastMCP
import requests
import os

# Initialize the MCP Server
mcp = FastMCP("paystack")

BASE_URL = "https://api.paystack.co"
HEADERS = {
    "Authorization": f"Bearer {os.getenv('PAYSTACK_SECRET_KEY')}",
    "Content-Type": "application/json"
}

@mcp.tool()
def verify_transaction(reference: str) -> str:
    """
    Verifies the status of a transaction using its reference.

    Args:
        reference: The unique transaction reference code.
    """
    url = f"{BASE_URL}/transaction/verify/{reference}"
    response = requests.get(url, headers=HEADERS)

    if response.status_code == 200:
        data = response.json().get('data', {})
        status = data.get('status')
        amount = data.get('amount') / 100  # Convert kobo to major unit
        return f"Transaction {reference} is {status}. Amount: {amount}."
    else:
        return f"Error verifying transaction: {response.text}"
Enter fullscreen mode Exit fullscreen mode

Installation & Setup

Ready to try it out? You can run this server locally or spin it up via Docker.

Prerequisites:

  • Python 3.10+
  • A Paystack Account (and your Secret Key)
  • uv (highly recommended) or pip

Option 1: Local Development (via UV)

  1. Clone the repo:
   git clone https://github.com/thisishaykins/paystack-python-mcp
   cd paystack-python-mcp
Enter fullscreen mode Exit fullscreen mode
  1. Set up your environment variables: Create a .env file or export your key directly in the terminal:
   export PAYSTACK_SECRET_KEY="sk_test_..."
Enter fullscreen mode Exit fullscreen mode
  1. Run the Server:
   uv run paystack_mcp.py
Enter fullscreen mode Exit fullscreen mode

Option 2: Docker Deployment

If you prefer isolated environments, Docker is the way to go.

Dockerfile Example:

FROM python:3.10-slim

WORKDIR /app

# Install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy source code
COPY . .

# Set entrypoint
ENTRYPOINT ["python", "paystack_mcp.py"]
Enter fullscreen mode Exit fullscreen mode

Run it:

docker build -t paystack-mcp .
docker run -e PAYSTACK_SECRET_KEY="sk_test_..." -i paystack-mcp
Enter fullscreen mode Exit fullscreen mode

(Note: That -i flag is super important because MCP communicates over Stdio!)

Integrating with Claude Desktop

To get this working inside your Claude Desktop app, you just need to update your claude_desktop_config.json file.

Where to find it:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json

Add this configuration:

{
  "mcpServers": {
    "paystack": {
      "command": "uv",
      "args": [
        "run",
        "--with",
        "requests",
        "/absolute/path/to/paystack-python-mcp/paystack_mcp.py"
      ],
      "env": {
        "PAYSTACK_SECRET_KEY": "sk_test_YOUR_KEY_HERE"
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Real-World Scenarios in Action

Once you are hooked up, it feels like magic. Here is what you can do:

Scenario 1: Quick Support Investigation

You: "I have a customer, john@example.com, claiming he paid for the Premium Plan but it's not showing. Can you check his last 3 transactions?"

Claude's Actions:

  1. Triggers fetch_customer(email="john@example.com") to grab the Customer ID.
  2. Triggers list_transactions(customer_id=123, per_page=3).
  3. Response: "I found John. His last 3 transactions were all 'Failed'. He attempted to pay 5000 NGN but the bank declined."

Scenario 2: Processing Instant Refunds

You: "Transaction REF-998877 was a duplicate charge. Please refund it immediately."

Claude's Actions:

  1. Triggers verify_transaction(reference="REF-998877") to check the status.
  2. Triggers initiate_refund(transaction="REF-998877").
  3. Response: "Refund initiated successfully for transaction REF-998877."

🔮 What's Next? Going Async

This current version is robust, but I'm already working on a v2 release to handle high-throughput workflows (imagine asking Claude to audit 50 transactions at once). Here's a tested branch: https://github.com/thisishaykins/paystack-python-mcp/tree/feature/v2-async-refactor

Here is what is on the immediate roadmap:

  • Async/Await: Swapping requests for httpx and asyncio for non-blocking API calls.
  • Webhooks: Allowing Paystack to push live updates back to the MCP server.
  • Bulk Operations: Dedicated tools for managing bulk transfers.

I’d love for you to try it out, break it, and contribute!

Check out the repo here: github.com/thisishaykins/paystack-python-mcp

Please drop a star ⭐ if you find it useful, and let me know in the comments what Fintech tools you'd like to see integrated next!

Top comments (0)