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 Agent Skills in this repository: 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 DARAJA_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
DARAJA_ENV sandbox (default) or production
DARAJA_CONSUMER_KEY, DARAJA_CONSUMER_SECRET ✅ From your Daraja app
DARAJA_SHORTCODE most tools Paybill / store number (174379 in sandbox)
DARAJA_PASSKEY STK Lipa na M-Pesa passkey
DARAJA_INITIATOR_NAME B2C/B2B/status/balance/reversal API operator username
DARAJA_SECURITY_CREDENTIAL same Pre-encrypted credential, or set the next two
DARAJA_INITIATOR_PASSWORD + DARAJA_CERT_PATH Server encrypts the password with the cert at startup
DARAJA_CALLBACK_BASE_URL e.g. https://abc.ngrok-free.app; tools append /mpesa/stk/callback, /mpesa/b2c/result, …
DARAJA_ALLOW_LIVE_MONEY_MOVEMENT true to allow production charges/payouts
DARAJA_CALLBACK_LISTEN e.g. 127.0.0.1:8787: starts the built-in callback receiver
DARAJA_CALLBACK_TOKEN with receiver 16+ random characters. Callback URLs become <base>/cb/<token>/…
DARAJA_STATE_DB SQLite file for requests and results (default ~/.mpesa-mcp/state.db)
DARAJA_TOOLSETS Comma list of stk,c2b,payouts,ops,qr,ratiba,billmanager (core is always on). Default: all
DARAJA_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

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 DARAJA_DOTENV. Only DARAJA_* 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 DARAJA_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 DARAJA_CALLBACK_LISTEN=127.0.0.1:8787
export DARAJA_CALLBACK_TOKEN=$(python -c "import secrets; print(secrets.token_urlsafe(24))")
ngrok http 8787                        # sandbox; use a reverse proxy with TLS in production
export DARAJA_CALLBACK_BASE_URL=https://<tunnel-host>

Callbacks are stored in DARAJA_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) 24 ~6,300
stk 9 ~2,100
stk,c2b 12 ~2,600

Pick the smallest set you need with DARAJA_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.2

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.2
File Size Uploaded Provenance
mpesa_daraja_mcp-0.1.2.tar.gz 50.6 kB With provenance Details

Built distribution (wheel)

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

Total release size: 88.6 kB

Release files / mpesa_daraja_mcp-0.1.2.tar.gz

Download URL mpesa_daraja_mcp-0.1.2.tar.gz
Size 50.6 kB
Tags Source
SHA-256 checksum
How to use checksums
b7bbdc7b5c77c6dd38938570140dc38e32a14e33cfb34fe26688e6cf0630a764
BLAKE2b-256 checksum
How to use checksums
2c29a4ab184f85918106a9de1ab3b8892b2e4e7e01fe31c9024ebeceec7ea74a
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 21, 2026.

Transparency log

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

Download URL mpesa_daraja_mcp-0.1.2-py3-none-any.whl
Size 38.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
cf7eae7f371fde0083217a3e66f1279fe46ad84256227b0022be9c936ae241ea
BLAKE2b-256 checksum
How to use checksums
f8f63b77126071039b65daefb9236f68155e7837c04a734918ebd2a9bd21ce2f
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 21, 2026.

Transparency log

Security for mpesa-daraja-mcp 0.1.2

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.2.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 21, 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