Skip to main content

mpesa-daraja-mcp: M-Pesa Daraja MCP server

An MCP server that exposes Safaricom's Daraja APIs as tools, so an agent (Claude Code, Claude Desktop, any MCP client) can test and operate M-Pesa integrations. It pairs with the skills in ../skills: skills teach how to integrate, this server lets the agent call Daraja.

Tools

Tool Daraja API Moves money
mpesa_explain_code — offline error/result code lookup
mpesa_normalize_phone — offline 07… → 2547…
mpesa_generate_stk_password — offline Password + EAT Timestamp
mpesa_parse_callback — offline parse of any callback payload
mpesa_setup_status — offline: what's configured and missing per toolset (no values)
mpesa_check_credentials OAuth token (never returned)
mpesa_get_result Final status by idempotency key or any Daraja ID (from captured callbacks; STK falls back to STK Query)
mpesa_stk_push_and_wait M-Pesa Express: push, then wait for callback / poll query; returns SUCCESS, FAILED or UNKNOWN ✅
mpesa_stk_push / mpesa_stk_query M-Pesa Express, fire-and-forget / status ✅ /
mpesa_c2b_register_urls / mpesa_c2b_simulate C2B v2 (simulate = sandbox only)
mpesa_pull_transactions Pull Transactions query
mpesa_b2c_payment B2C v3, B2Pochi ✅
mpesa_b2b_payment BusinessPayBill, BusinessBuyGoods, BusinessPayToBulk (B2C top-up), PayTaxToKRA ✅
mpesa_b2b_express_checkout B2B USSD push ✅
mpesa_transaction_status / mpesa_account_balance Status / Balance (async result)
mpesa_reverse_transaction Reversal ✅
mpesa_generate_dynamic_qr Dynamic QR, saved as a PNG file (path returned, not the image)
mpesa_ratiba_create_standing_order M-Pesa Ratiba ✅
mpesa_bill_manager_optin / mpesa_bill_manager_send_invoice / mpesa_bill_manager_cancel_invoice Bill Manager

Tool annotations mark money-moving tools as destructiveHint, so MCP clients ask for approval.

Safety

  • Defaults to the sandbox.
  • In production, money-moving tools refuse to run unless MPESA_ALLOW_LIVE_MONEY_MOVEMENT=true.
  • Callback URLs must be HTTPS; C2B URLs with mpesa/safaricom in them are rejected up front.
  • Tokens and secrets are never returned in tool output.
  • Responses with ResponseCode "0" are tagged _note: ACCEPTED for processing only, so the agent does not report them as completed payments.
  • Idempotent money tools. Each request is stored under an idempotency key. Repeating the key returns the stored request (duplicate: true) instead of paying again.
    • Only a definitively FAILED request is re-sent.
    • ACCEPTED or UNKNOWN requests (queue timeouts, network errors) are never re-sent until their result is known.
    • B2C, B2B and B2B Express require an explicit idempotency_key, e.g. refund-order-1042. Reversal, tax and Ratiba derive one from the transaction ID, the PRN and phone + name respectively. For STK the key is optional.

Configuration

Variable Required Notes
MPESA_ENV sandbox (default) or production
MPESA_CONSUMER_KEY, MPESA_CONSUMER_SECRET ✅ From your Daraja app
MPESA_SHORTCODE most tools Paybill / store number (174379 in sandbox)
MPESA_PASSKEY STK Lipa na M-Pesa passkey
MPESA_INITIATOR_NAME B2C/B2B/status/balance/reversal API operator username
MPESA_SECURITY_CREDENTIAL same Pre-encrypted credential, or set the next two
MPESA_INITIATOR_PASSWORD + MPESA_CERT_PATH Server encrypts the password with the cert at startup
MPESA_CALLBACK_BASE_URL e.g. https://abc.ngrok-free.app; tools append /mpesa/stk/callback, /mpesa/b2c/result, …
MPESA_ALLOW_LIVE_MONEY_MOVEMENT true to allow production charges/payouts
MPESA_CALLBACK_LISTEN e.g. 127.0.0.1:8787: starts the built-in callback receiver
MPESA_CALLBACK_TOKEN with receiver 16+ random characters. Callback URLs become <base>/cb/<token>/…
MPESA_STATE_DB SQLite file for requests and results (default ~/.mpesa-mcp/state.db)
MPESA_TOOLSETS Comma list of stk,c2b,payouts,ops,qr,ratiba,billmanager (core is always on). Default: all
MPESA_OUTPUT_DIR Where QR PNGs are saved (default ~/.mpesa-mcp/qr)

Install & run

uvx mpesa-daraja-mcp setup     # guided: keys (hidden input), live check, save, register with your agents
uvx mpesa-daraja-mcp status    # what's configured (masked) + a live key check
uvx mpesa-daraja-mcp           # the MCP server itself, on stdio: what your agent runs

Until the first PyPI release, run from GitHub instead: uvx --from "git+https://github.com/Mr-Macharia/mpesa-daraja-skills-and-mcp#subdirectory=mcp-server" mpesa-daraja-mcp.

The server needs no flags or environment variables in your agent's config. Settings are read in this order, highest first:

  1. Environment variables, e.g. from the client's env block.
  2. A project .env in the folder the agent starts the server in, or the file named by MPESA_DOTENV. Only MPESA_* lines are read.
  3. The user config file that setup writes: ~/.config/mpesa-daraja-mcp/config.env (Windows: %APPDATA%\mpesa-daraja-mcp\config.env; override the folder with MPESA_CONFIG_DIR). It is readable only by you.

The server starts even when unconfigured. Tools then explain what's missing, and mpesa_setup_status lists the gaps for each toolset without revealing any values.

To register by hand: claude mcp add --scope user mpesa -- uvx mpesa-daraja-mcp. Every other agent is covered in docs/clients.md. The older mpesa-mcp command still works.

Results and callbacks

Every money or async tool returns one shape:

{"status": "ACCEPTED | SUCCESS | FAILED | UNKNOWN", "message": "...", "idempotency_key": "...",
 "duplicate": false, "ids": {"checkout_request_id": "..."}, "receipt": "...", "result_code": "...",
 "explanation": "...", "raw": {}}

To let the agent see final results, enable the built-in receiver:

export MPESA_CALLBACK_LISTEN=127.0.0.1:8787
export MPESA_CALLBACK_TOKEN=$(python -c "import secrets; print(secrets.token_urlsafe(24))")
ngrok http 8787                        # sandbox; use a reverse proxy with TLS in production
export MPESA_CALLBACK_BASE_URL=https://<tunnel-host>

Callbacks are stored in MPESA_STATE_DB:

  • mpesa_get_result(id) reads them.
  • mpesa_stk_push_and_wait returns the final outcome in one call.
  • Queue-timeout callbacks are recorded as UNKNOWN.
  • C2B validation requests are always accepted. Use your own receiver if you need to reject payments.

Without the receiver, mpesa_stk_push_and_wait still works through STK Query. For other APIs, paste a received payload into mpesa_parse_callback.

Context cost

Toolsets Tools Schema tokens (approx.)
all (default) 23 ~6,300
stk 9 ~2,100
stk,c2b 12 ~2,600

Pick the smallest set you need with MPESA_TOOLSETS.

Development

pip install -e ".[dev]"
pytest

Tests use respx to mock Daraja. Nothing hits the network.

License

MIT. Not affiliated with or endorsed by Safaricom PLC; M-Pesa and Daraja are trademarks of Safaricom PLC.

Metadata

Release files for mpesa-daraja-mcp 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mpesa-daraja-mcp 0.1.0
File Size Uploaded Provenance
mpesa_daraja_mcp-0.1.0.tar.gz 50.7 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for mpesa-daraja-mcp 0.1.0
File Interpreter ABI Platform
mpesa_daraja_mcp-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 88.7 kB

Release files / mpesa_daraja_mcp-0.1.0.tar.gz

Download URL mpesa_daraja_mcp-0.1.0.tar.gz
Size 50.7 kB
Tags Source
SHA-256 checksum
How to use checksums
90407e6ede8b27ccfb1d2ef91dea370ed9af9a9b771c0bc6d82db8285c576c53
BLAKE2b-256 checksum
How to use checksums
8c5a2d28cc8d801eb43b761ca18e103a1f6c1b62bb1fd4b5af5400542da4e1de
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.

Transparency log

Release files / mpesa_daraja_mcp-0.1.0-py3-none-any.whl

Download URL mpesa_daraja_mcp-0.1.0-py3-none-any.whl
Size 38.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a85aea6a2198b8782349fd174b72f68662c10b1a32429a63e46edc6dfbc7c3e4
BLAKE2b-256 checksum
How to use checksums
ae310cd3137341982abb36edf6017191f832e5394099a03f0641cc92d765b48b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.

Transparency log

Security for mpesa-daraja-mcp 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for mpesa_daraja_mcp-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page