OM

openmf/mcp-mifosx-self-service

Developer tools
9 stars 17 forks Quality 82 Trend 37MPL-2.0

MCP Server for Mifos X - Self Service

Overview

MifosX Self Service MCP is a Model Context Protocol (MCP) server built using FastMCP (Python). It exposes a set of AI-callable tools that allow MCP-compatible clients (such as Claude Desktop or DeepChat) to securely interact with the Apache Fineract / MifosX Self-Service APIs. This project enables AI-driven banking workflows such as authentication, account access, beneficiary management, loans, savings, and transfers — while keeping all sensitive logic on the server side. * Register new self-service users. * Confirm user registration. * User login and authentication. * Manage client information. * Manage beneficiaries (add, list, update, delete). * View client accounts and transactions. * Manage loans (view products, applications, transactions, charges). * Manage savings accounts (products, applications, transactions, charges). * Manage guarantors for loans. * Manage share accounts and products.

README

MifosX Self Service MCP

MifosX Self Service MCP is a Model Context Protocol (MCP) server built using FastMCP (Python). It exposes a set of AI-callable tools that allow MCP-compatible clients (such as Claude Desktop or DeepChat) to securely interact with the Apache Fineract / MifosX Self-Service APIs.

This project enables AI-driven banking workflows such as authentication, account access, beneficiary management, loans, savings, and transfers — while keeping all sensitive logic on the server side.

Features

  • Register new self-service users.
  • Confirm user registration.
  • User login and authentication.
  • Manage client information.
  • Manage beneficiaries (add, list, update, delete).
  • View client accounts and transactions.
  • Manage loans (view products, applications, transactions, charges).
  • Manage savings accounts (products, applications, transactions, charges).
  • Manage guarantors for loans.
  • Manage share accounts and products.
  • Read account statements and spending insights (statement, summary, recurring payments).
  • Register for push notifications.
  • Perform third-party account transfers.

Architecture

The MCP server acts as a secure bridge between your AI client and the Mifos/Fineract backend.

graph LR
    A[AI Client] -- MCP Protocol --> B[FastMCP Server]
    B -- REST API --> C[MifosX / Fineract]
    C -- Data --> B
    B -- Context --> A

Project Structure

The codebase is organized into a modular, maintainable structure:

mcp-mifosx-self-service/
│
├── main.py              # MCP server entry point
├── mcp_app.py           # FastMCP app initialization
│
├── config/
│   └── config.py        # Environment-based configuration
│
├── routers/             # MCP tools grouped by domain
│   ├── auth_tools.py        # User registration & authentication
│   ├── client_tools.py      # Client information & accounts
│   ├── beneficiary_tools.py # Beneficiary management
│   ├── transfer_tools.py   # Third-party transfers
│   ├── loan_tools.py        # Loan products & accounts
│   ├── savings_tools.py     # Savings accounts & products
│   ├── statement_tools.py   # Statements, spending summary, recurring payments
│   ├── guarantor_tools.py  # Loan guarantor management
│   ├── shares_tools.py     # Share accounts & products
│   └── notification_tools.py # Push notification registration
│
├── schemas/             # Pydantic request/response models
│   ├── registration.py
│   ├── authentication.py
│   ├── confirm.py
│   ├── beneficiary.py
│   └── transfer.py
│
├── utils/               # Shared helpers
│   ├── http.py          # Centralized HTTP client
│   └── auth.py          # Auth helpers (Basic Auth)
│
├── resources/           # MCP resources (context & docs)
│   ├── overview.py
│   ├── endpoints.py
│   └── workflows.py
│
├── requirements.txt
├── Dockerfile
├── docker-compose.yml
└── README.md

Installation

  1. Clone the repository:

    git clone https://github.com/openMF/mcp-mifosx-self-service.git
    cd mcp-mifosx-self-service
    
  2. Create and activate a virtual environment (recommended):

    python3 -m venv venv
    source venv/bin/activate  # On Windows: venv\Scripts\activate
    
  3. Install the required dependencies:

    pip install -r requirements.txt
    

Configuration

The application connects to a Fineract API. Use environment variables (or a .env file) for customization:

Variable Description Default
MIFOS_BASE_URL Base URL of Fineract instance https://tt.mifos.community
MIFOS_TENANT Tenant identifier default

| MIFOS_USERNAME | Self-service username (optional, see below) | none | | MIFOS_PASSWORD | Self-service password (optional, see below) | none | | MIFOS_STEP_UP_CHANNEL | EMAIL, SMS or TOTP: how the verification code reaches the user (see below) | the authenticator app if the user paired one, otherwise the first channel the bank offers | | MIFOS_STEP_UP_ALLOW_CHAT_OTP | false to forbid typing the code in the chat (see below) | true | | MIFOS_TRANSFER_MAX_AMOUNT | Largest transfer the assistant may prepare; larger ones must be made in the bank’s app | no limit | | MIFOS_TRANSFER_CONFIRM_TTL_SECONDS | How long a prepared transfer can be confirmed | 300 | | MIFOS_TIMEZONE | The bank’s time zone (e.g. America/Mexico_City), used for the transfer date | server’s time zone |

Authentication

Tools do not take a username or password. The server keeps the login itself, so the AI never sees the password or the access token. There are two ways to log in:

  1. Recommended: set MIFOS_USERNAME and MIFOS_PASSWORD in the server environment (for example in the env block of the Claude Desktop config). Tools work right away, and the password never goes through the chat.
  2. Ask the assistant to call the login tool. The server keeps the access token from Fineract and returns the login details without the token. Use logout to end the session.

The session lives in the server process. This is safe for the default stdio transport (one server per user); do not share one server between several users.

Transfers: prepare, then confirm

The assistant cannot move money in one call. Every transfer takes two tools:

  1. prepare_transfer(from_account_id, to_account_id, amount, description, ...) moves no money. It checks that the source is one of your accounts and that the destination is one of your own accounts (for example a loan, for a repayment) or, with third_party: true, one of your saved beneficiaries. It checks the amount against MIFOS_TRANSFER_MAX_AMOUNT and the available balance, and returns a summary (accounts, amount, currency, fee) with a confirmation_id. The assistant shows you the summary and asks you to confirm.
  2. confirm_transfer(confirmation_id) sends exactly the request that was prepared. The server keeps it, so the AI cannot change the accounts or the amount in between. The id works once and expires after MIFOS_TRANSFER_CONFIRM_TTL_SECONDS (5 minutes by default; at most 5 prepared transfers are kept). If your client supports MCP elicitation, it also shows you a form (“Send this … ?”) and nothing is sent unless you confirm there (if the form cannot be shown, nothing is sent either). If the bank asks for a one-time code, the confirmation continues as described below.

cancel_transfer(confirmation_id) drops a prepared transfer.

Applying for shares works the same way: prepare_share_application (checks the product’s share limits and that the linked savings account is the client’s, active and in the product’s currency, and returns the total price), then confirm_share_application or cancel_share_application. A share confirmation id cannot confirm a transfer, and the other way round. The bank still has to approve the application.

Adding a beneficiary works the same way, because money can be sent to it later: prepare_beneficiary(name, account_number, office_name, account_type, transfer_limit) checks the account type (“savings” or “loan”) against the bank’s template and the office against the bank’s offices, takes the currency of your own accounts (or the currency you pass) and saves nothing. prepare_beneficiary_change(beneficiary_id, name, transfer_limit) shows the old and new values; the bank only lets the name and the transfer limit change. confirm_beneficiary saves either one, cancel_beneficiary drops it.

Human-in-the-loop confirmation for sensitive tools

When the bank has step-up authentication turned on (selfservice-plugin, MX-488), some operations need a one-time code that the account owner receives by e-mail or SMS: third-party transfers, transfers between your own accounts, and password changes (confirm_transfer, update_account_password). All other tools are unchanged.

The AI never sees the code or the one-time token the bank returns for it. The server asks for the code like this:

  1. The client supports MCP elicitation (a form shown by the client). The tool shows a form such as “A verification code was sent to a***@example.com. Enter it to confirm: third-party transfer of 100.5 from account 11 to account 22.” The person types the code there; it goes straight to this server and the tool finishes the transfer in the same call. A wrong code asks again (the form shows the attempts left); declining or cancelling the form stops the operation with cancelled: true and nothing is executed.
  2. The client does not support elicitation. The tool answers step_up_required with a challengeId, a summary of what the code approves and the masked destination, and executes nothing. The assistant must ask you for the code and call verify_step_up(challengeId, otp). Use resend_step_up(challengeId) if the code did not arrive (the bank limits how soon and how often). Typing the code in the chat means the code passes through the AI client and its logs: it is a one-time code that is tied to that one operation, but if you do not accept that, set MIFOS_STEP_UP_ALLOW_CHAT_OTP=false. Then, without elicitation, no code is sent at all and the tool tells the user to confirm in the bank’s own app or website.

The request that runs after the code is accepted is the one that was approved. The server keeps it (it is not read from the AI again), and the bank also ties the code to the accounts and the amount, so the AI cannot approve one operation and run another. A waiting operation is kept in memory for 10 minutes and for at most 5 operations.

Step-up needs a login session: call login. Credentials from MIFOS_USERNAME / MIFOS_PASSWORD alone are not enough for this step (the bank answers session.required and the tool says so). MIFOS_STEP_UP_CHANNEL picks SMS or e-mail when the user has both; if that channel is not available the first one the bank offers is used.

Authenticator app

If the bank also offers an authenticator app (Google Authenticator, Microsoft Authenticator…) and the user paired one, the verification uses it (channel TOTP): nothing is sent, the person types the 6-digit code the app shows now. By default the bank offers only the app to such a user (so an intercepted SMS is of no use), and this server then uses it without any setting.

  • With elicitation the form asks for “Code from your authenticator app” and, only for a lost phone, “Recovery code” (one of the codes the user saved when pairing; each works once). The form takes one of the two. A wrong code asks again, as before.
  • Without elicitation the chat fallback accepts only the 6-digit code of the app, which is valid for seconds and for this one operation. A recovery code is never accepted in the chat (it is a long-lived credential); the tool tells the user to use a client with elicitation or the bank’s own app. resend_step_up does not apply: an app code cannot be sent again.
  • Pairing, new recovery codes and removing the app are not tools. The secret and the recovery codes must not pass through an AI conversation, so the user does that in the bank’s own app or website.

Errors

When the bank refuses a request, tools answer with a short, readable error instead of the bank’s raw response:

{"error": true, "status_code": 400,
 "message": "The parameter `productId` is mandatory.",
 "errors": [{"message": "The parameter `productId` is mandatory.", "parameter": "productId"}],
 "code": "validation.msg.validation.errors.exist"}

errors lists the fields to fix and code is the bank’s error code. Developer messages, server paths and HTML error pages are never passed on.

Running with Docker

The project includes Docker support for easy deployment:

# Build and run with docker-compose
docker-compose up --build

Using with Claude Desktop (MCP)

  • In Claude Desktop → Settings → Developer → Local MCP servers → Edit Config, add:
{
  "mcpServers": {
    "mifos-banking": {
      "command": "/ABSOLUTE/PATH/TO/venv/bin/python",
      "args": [
        "/ABSOLUTE/PATH/TO/main.py"
      ],
      "env": {
        "MIFOS_BASE_URL": "https://tt.mifos.community",
        "MIFOS_TENANT": "default",
        "MIFOS_USERNAME": "your-username",
        "MIFOS_PASSWORD": "your-password"
      }
    }
  }
}

Restart Claude Desktop after saving.

Running the Server

To run the MCP server, execute the following command from the project’s root directory:

python3 main.py

Example Usage (Natural Language) on Claude

Once the MCP server is connected, Claude can invoke the available tools automatically. You can paste the following prompts in Claude Desktop to verify that your configuration is working correctly:

  • Log in (only needed if MIFOS_USERNAME / MIFOS_PASSWORD are not set)
  • Get my client information
  • Show my client accounts
  • List my beneficiaries
  • Get my loan accounts
  • Show my savings accounts

If these commands return valid responses, your MCP server is successfully connected and operational.

Available MCP Tools

The MCP server exposes the following AI-callable tools. Each tool internally maps to a Fineract self-service API call. These tools are invoked by MCP-compatible AI clients, not directly via HTTP.

Authentication

Method MCP Tool Name Description
POST register_self_service_existing_client Register a self-service user for an existing client
POST confirm_self_service_user_registration Confirm the registration with the request id and token
POST verify_user_registration Same as confirm_self_service_user_registration
GET confirm_self_service_user_registration_status Check the registration: lists the clients the user can see
POST login Log in and keep the session in the server
POST authenticate_user_self_service Same as login
POST logout End the session
PUT update_account_password Change the password (asks for a one-time code)

Client & Accounts

Method MCP Tool Name Description
GET get_clients_linked_to_user The clients linked to the logged-in user (gives the client id)
GET get_client_details Retrieve client information
GET get_client_accounts Retrieve client accounts
GET get_client_charges Retrieve client charges
GET get_client_images Retrieve client images
GET get_client_transactions Retrieve client transactions
GET get_client_transaction_detail Retrieve one client transaction

Beneficiaries

Method MCP Tool Name Description
GET get_beneficiary_list List all beneficiaries
GET get_beneficiary_template The account types a beneficiary can have
- prepare_beneficiary Step 1: check a new beneficiary (saves nothing)
- prepare_beneficiary_change Step 1: check a new name or transfer limit (saves nothing)
POST/PUT confirm_beneficiary Step 2: save the prepared beneficiary or change
- cancel_beneficiary Drop a prepared beneficiary or change
DELETE delete_beneficiary Delete a beneficiary

Loans

Method MCP Tool Name Description
GET get_loan_products Retrieve available loan products
GET get_loan_product_details Retrieve loan product details
GET get_loan_account_details Retrieve loan account details
GET get_loan_transaction_detail Retrieve loan transaction detail
GET get_loan_account_charges Retrieve loan charges
GET get_loan_template Products a client can apply for, or one product’s terms and loan purposes
POST calculate_loan_repayment_calendar Repayment schedule for an amount and number of repayments (submits nothing)
POST prepare_loan_application Step 1: check a new application (or a change to a pending one) and show its schedule
POST confirm_loan_application Step 2: submit the prepared application, once, after the user says yes
POST cancel_loan_application Drop a prepared application
POST withdraw_loan_application Withdraw loan application

Loan applications take typed fields (product, amount, number of repayments, loan purpose, expected disbursement date). Everything else (interest, repayment frequency, product charges) comes from the bank’s loan template, and the amount and number of repayments are checked against the product’s limits. A loan creates a debt, so prepare_loan_application returns the schedule the bank calculates and submits nothing; confirm_loan_application submits it only with the confirmation id, at most once, and asks the person in a form when the client can show one. Passing loan_id changes an application that is still waiting for approval the same way.

Loan simulation (no login needed)

Method MCP Tool Name Description
GET get_loan_simulation_products Loan products available for simulation, with their limits
POST simulate_loan Estimate interest, total and installments for an amount

Savings

Method MCP Tool Name Description
GET get_savings_products Get list of savings products
GET get_savings_product_details Get savings product details
GET get_savings_account_details Get savings account details
GET get_savings_account_transactions Get savings account transactions
GET get_savings_account_transaction_details Get transaction details
GET get_savings_account_charges Get savings account charges
GET get_savings_account_template_raw Get savings account template
- prepare_savings_application Step 1: check an application for a savings account and get a summary and a confirmation_id (submits nothing)
POST confirm_savings_application Step 2: submit the prepared application once, after the user confirmed
- cancel_savings_application Drop a prepared application
PUT update_savings_account_application Change the product, field officer or external id of an application waiting for approval

Statements & Insights

Read-only tools that reshape a savings account’s own transaction list into a statement and spending picture. Everything is computed by the MCP server from the bank’s rows — see the “Honest limits” line in each tool’s description.

Method MCP Tool Name Description
GET get_account_statement Date- and direction-filtered statement of one savings account (paged, newest first)
GET get_spending_summary Money in / money out totals, monthly buckets and per-type breakdown
GET find_recurring_payments Same-amount, evenly-spaced debits (subscriptions, instalments)

Guarantors

Method MCP Tool Name Description
GET get_guarantor_template Get template for creating guarantors
GET get_guarantor_list Get list of guarantors for a loan
POST create_guarantor Add a new guarantor for a loan
PUT update_guarantor Update an existing guarantor
DELETE delete_guarantor Delete a loan guarantor

Shares

Method MCP Tool Name Description
GET get_share_product_list Get list of share products
GET get_share_product_details Get share product details
GET get_share_account_template Share products a client can apply for; with product_id, price and share limits
GET get_share_account One share account or application
- prepare_share_application Step 1: check an application for shares and get a summary and a confirmation_id (submits nothing)
POST confirm_share_application Step 2: submit the prepared application once, after the user confirmed
- cancel_share_application Drop a prepared application

Notifications

Method MCP Tool Name Description
GET get_user_notification_details Get notification registration details
POST register_for_notifications Register device for push notifications
PUT update_notification_registration Update notification registration

Offices

Method MCP Tool Name Description
GET get_offices List the bank’s offices (branches)
GET get_office_details Details of one office
GET get_office_services Services an office offers, with working hours
GET get_office_address Street address of an office
GET get_office_geolocation Map location of an office

Profile and pockets

Method MCP Tool Name Description
GET get_user_details The logged-in user’s roles, permissions and clients (banks with OAuth login only; credentials are removed)
GET get_pockets The accounts saved as favourites (pockets)
POST add_accounts_to_pocket Save the user’s loan, savings or share accounts as favourites
POST remove_accounts_from_pocket Remove favourites by mapping id (from get_pockets)
GET get_security_activity Logins and sensitive actions (password, transfers, beneficiaries), newest first; filter by type

Transfers

Method MCP Tool Name Description
GET get_account_transfer_template Accounts you can transfer between
GET get_third_party_transfer_template Your accounts and saved beneficiaries for third-party transfers
GET get_transfer_fees List the bank’s transfer fee rules (filter by type and currency)
POST get_transfer_quote Ask the bank for the exact fee and total of a transfer (moves no money)
- prepare_transfer Step 1: check a transfer and get a summary and a confirmation_id (moves no money)
POST confirm_transfer Step 2: send the prepared transfer once, after the user confirmed (may ask for a one-time code)
- cancel_transfer Drop a prepared transfer
POST verify_step_up Give the code the user received to the operation that waits for it (clients without elicitation)
POST resend_step_up Send the code again

License

This project is licensed under the terms included in the LICENSE file.

View the full README on GitHub

Install

This server does not publish a one-line install command.

Open the repository installation guide New to MCP? Start with the mcpskill.org guide →

Configuration

{ "mcpServers": { "mifos-banking": { "command": "/ABSOLUTE/PATH/TO/venv/bin/python", "args": [ "/ABSOLUTE/PATH/TO/main.py" ], "env": { "MIFOS_BASE_URL": "https://tt.mifos.community", "MIFOS_TENANT": "default", "MIFOS_USERNAME": "your-username", "MIFOS_PASSWORD": "your-password" } } } }