Agent frameworks
Give your own agent the M-Pesa tools and guardrails in LangChain, the OpenAI Agents SDK, Agno, Google ADK, CrewAI or the Vercel AI SDK.
Use this page when you are building your own agent in code, with LangChain, the OpenAI Agents SDK, Agno, Google ADK, CrewAI or the Vercel AI SDK, and want it to take M-Pesa payments. If you use Claude, Cursor or another MCP client, you don't need this page: connect the MCP server instead.
The library hands your agent the same M-Pesa tools as the MCP server, as ordinary functions in your own process. Nothing extra runs in the background. Every safety rule still applies: read-only mode, the production lock, the approval threshold, the recipient allowlist and idempotency keys.
1. Install
Pick the extra for your framework:
| Framework | Install |
|---|---|
| LangChain or LangGraph | pip install "mpesa-daraja-mcp[langchain]" |
| OpenAI Agents SDK | pip install "mpesa-daraja-mcp[openai-agents]" |
| Agno | pip install "mpesa-daraja-mcp[agno]" |
| Google ADK | pip install "mpesa-daraja-mcp[google-adk]" |
| CrewAI | pip install "mpesa-daraja-mcp[crewai]" |
| Several of them | pip install "mpesa-daraja-mcp[frameworks]" (all five) |
| Vercel AI SDK (Node) | npm install mpesa-daraja ai |
2. Add your keys
The tools read the same settings as the MCP server. Either run mpesa init once, or set the DARAJA_* variables yourself (see Sandbox setup). Start in the sandbox, with DARAJA_ENV=sandbox.
3. Choose which tools the agent gets
Give an agent only what its job needs. A checkout agent needs stk; it should never see payouts. Tools are grouped into toolsets, and core is always included:
| Toolset | Tools | Moves money? |
|---|---|---|
core | explain_code, normalize_phone, generate_stk_password, parse_callback, setup_status, check_credentials, get_result | No |
stk | stk_push, stk_push_and_wait, stk_query | Collects |
c2b | c2b_register_urls, c2b_simulate, pull_transactions | No |
payouts | b2c_payment, b2b_payment, b2b_express_checkout | Sends |
ops | transaction_status, account_balance, reverse_transaction | Reversal sends |
qr | generate_dynamic_qr | No |
ratiba | ratiba_create_standing_order | Collects |
billmanager | bill_manager_optin, bill_manager_send_invoice, bill_manager_cancel_invoice | No |
Every Python entry point takes the same four options:
toolsets: which groups to load, such as{"stk"}.include: keep only these tools, such as{"stk_push_and_wait", "get_result"}.read_only=True: leave out every tool that moves money or writes.approve: your function that approves large payouts (step 5).
4. Connect it to your framework
Put INSTRUCTIONS in the agent's system prompt in every case. It teaches the model that ACCEPTED does not mean paid, and that it must never retry a payout whose outcome is unknown.
LangChain or LangGraph
from mpesa_mcp.agent import INSTRUCTIONS
from mpesa_mcp.integrations.langchain import mpesa_langchain_tools
tools = mpesa_langchain_tools(toolsets={"stk"})
# pass `tools` to your agent, and INSTRUCTIONS as its system promptOpenAI Agents SDK
from agents import Agent
from mpesa_mcp.agent import INSTRUCTIONS
from mpesa_mcp.integrations.openai_agents import mpesa_openai_tools
agent = Agent(name="cashier", instructions=INSTRUCTIONS, tools=mpesa_openai_tools(toolsets={"stk"}))Agno
from agno.agent import Agent
from mpesa_mcp.agent import INSTRUCTIONS
from mpesa_mcp.integrations.agno import mpesa_agno_tools
agent = Agent(instructions=INSTRUCTIONS, tools=mpesa_agno_tools(toolsets={"stk"}))Google ADK
from google.adk.agents import Agent
from mpesa_mcp.agent import INSTRUCTIONS
from mpesa_mcp.integrations.google_adk import mpesa_adk_tools
agent = Agent(name="cashier", model="gemini-2.5-flash", instruction=INSTRUCTIONS,
tools=mpesa_adk_tools(toolsets={"stk"}))CrewAI
from crewai import Agent
from mpesa_mcp.agent import INSTRUCTIONS
from mpesa_mcp.integrations.crewai import mpesa_crewai_tools
agent = Agent(role="Cashier", goal="Collect payments", backstory=INSTRUCTIONS,
tools=mpesa_crewai_tools(toolsets={"stk"}))Any other Python framework
mpesa_tools() returns plain tools. Each has a name, a description and a JSON schema in parameters, which is what most frameworks ask for.
from mpesa_mcp.agent import INSTRUCTIONS, mpesa_tools
tools = mpesa_tools(toolsets={"stk"})
for t in tools.values():
print(t.name, t.parameters)
out = await tools["stk_push_and_wait"].call(phone="2547XXXXXXXX", amount=10, account_reference="order-1")
out["status"] # SUCCESS, FAILED, UNKNOWN or ACCEPTEDcall() returns a dict you can send straight back to the model as JSON. Errors come back as {"error": "..."} instead of being raised, so the agent can read them and explain. Use call_sync() in code that isn't async.
5. Approve large payouts
Payouts above DARAJA_APPROVAL_THRESHOLD must be approved by a person, never by the model. Over MCP, the approval is asked in the chat. In your own code, you pass an approve function. It receives a one-line summary of the payout and returns True to send it. It can be async, for example to post to Slack and wait for a reply.
tools = mpesa_tools(toolsets={"payouts"}, approve=lambda summary: input(f"{summary} [y/N] ") == "y")If you don't pass approve, any payout above the threshold is refused and nothing is sent.
Vercel AI SDK (Node)
The Node library mpesa-daraja works without Python or an MCP server.
import { generateText } from "ai";
import { Daraja } from "mpesa-daraja";
import { mpesaAiTools, INSTRUCTIONS } from "mpesa-daraja/ai";
const daraja = Daraja.fromEnv(process.env, { approve: async (summary) => askAHuman(summary) });
await generateText({
model,
system: INSTRUCTIONS,
tools: mpesaAiTools(daraja, { include: ["stk_push_and_wait", "get_result"] }),
prompt,
});It differs from the Python library in a few ways:
- It has 13 tools: the STK, B2C, B2B, status, balance and reversal tools, plus the helpers. It has no C2B, QR, Ratiba or Bill Manager tools yet.
- Choose tools with
includeandreadOnly. There are no toolsets. - In the AI SDK, tool names start with
mpesa_, such asmpesa_stk_push_and_wait. approvegoes in the client options, as above, not on the tools.
For another Node framework, mpesaTools(daraja) from mpesa-daraja returns plain tools, each with a JSON schema and an execute function.