MCP server for M-Pesa payment integration, enabling STK Push transactions, QR code generation, and C2B payment instructions
The server defines 4 M-Pesa payment tools with reasonable descriptions and complete input schemas. However, there are significant gaps in output schema documentation, missing parameter constraints (enums for transaction types and codes), and no error recovery guidance. Tool naming is clear and verb-based, but the lack of documented return types and limited error handling place this in the fair-to-poor range. The schemas are present but incomplete, parameter descriptions exist but lack constraints like valid enum values for transaction_type and trx_code.
Generates M-Pesa C2B payment instructions for manual user payment via Paybill.
Generates a Dynamic M-PESA QR Code for LIPA NA M-PESA (LNM) merchant payments using Safaricom's QR API. This MCP tool enables Safaricom M-PESA customers using the MySafaricom App or M-PESA App to scan a QR Code and pay directly to a merchant's till or business number. It captures key metadata such as amount, reference number, and credit party identifier (CPI) — and returns a base64-encoded QR image.
Initiates an M-Pesa STK Push (Sim Tool Kit) transaction, which allows a merchant to request a customer to authorize a payment through M-Pesa. This tool triggers the M-Pesa Lipa na M-Pesa Online API (STK Push), which sends a payment request to the customer's M-Pesa registered phone number. The customer receives a prompt on their phone to enter their M-Pesa PIN to authorize and complete the payment.
Queries the status of an M-Pesa STK Push transaction using the CheckoutRequestID. This tool checks whether a previously initiated Lipa na M-Pesa Online transaction was successful, failed, or is still pending.
Missing output schemas: No tools document their return type structure. stk_push, stk_push_status, generate_qr_code, and c2b_payment all return dicts but the field names, types, and required fields are not documented. This forces LLMs to infer structure from examples and invites parsing errors.
Missing enum constraints: transaction_type (stk_push) and trx_code (generate_qr_code) accept a known set of values but are defined as free-form strings. The descriptions provide examples but not constraints. LLMs will hallucinate invalid values outside the hint examples.
No error handling or recovery guidance: All tools wrap exceptions in a generic {'error': str(e)} dict. There is no categorization (retryable vs user-fixable), no suggestion for what the LLM should do next, and no example recovery workflows. Raw exception messages leak implementation details without actionable remedies.
Inferred effective spec: 2026-07-28+.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | F | 49 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 49 | - | v1 |
Unbounded numeric parameter (size in generate_qr_code): Has a default of '300' but no min/max bounds. LLMs could pass extreme values (1, 10000) that break the QR generator. Should constrain to e.g. 100 - 1000.
Vague description (c2b_payment): 'Generates M-Pesa C2B payment instructions' is too generic. What are the 'instructions'? What should the user do with them? Is this a visual reference, a display string, or a lookup? This ambiguity makes it hard for LLMs to decide when to call this vs stk_push.
Missing parameter constraints: amount and phone_number parameters lack format/range descriptions. Should specify: phone_number must be E.164 format; amount must be > 0 and <= max_transaction_value (e.g., KES 500000).