JazzCash integration, inside your own AI client
Install one connector, give it an access token, and your AI client can look up the official JazzCash guidance, generate integration code, sign and verify payloads, and diagnose failed transactions. The tools that need your merchant credentials run on your own machine and send them nowhere.
What this is
Before the first command, what you are installing.
M-MCP is an MCP server for JazzCash payment-gateway integration. You register one connector with your AI client, and that client gains 17 tools that answer from the transcribed JazzCash merchant guides: listing the integration flows, generating integration code, building and verifying secure hashes, validating payloads, explaining response codes, and diagnosing failed transactions. The flows covered are hosted checkout for card and BNPL, MWallet REST, token payment, token inquiry and deletion, wallet linking, status inquiry and refunds.
It is not a payment gateway. It holds no money, opens no merchant account, and moves nothing on your behalf. It is the integration knowledge two engineers would otherwise walk you through, in a form your own AI client can call — which is also why the parts that need your merchant credentials stay on your machine rather than coming here. That split is section 5, and it is the part worth reading twice.
JazzCash is the provider this covers today. An access token can also name a DGPara scope, and it is important not to read more into that than it says: no DGPara flow has been transcribed, so a DGPara-scoped token receives the tools that can serve either provider, answering from the JazzCash flows the catalogue holds. There is no DGPara coverage to grant yet.
Get an access token
One thing has to arrive from somebody else before you start.
You cannot issue a token yourself
There is no sign-up on this site and nothing here mints a token. An operator issues one from the administration console and sends it to you.How to ask
Ask the operator who runs this deployment — in practice, whoever sent you here. Say which provider and which tool groups you need, because a token is scoped to both and a scope that is too narrow shows up as tools quietly missing from your client rather than as an error.
Providers
jazzcashdgparaTool groups
knowledgehashcodegengatewaydiagnosticsTwo further permissions can be granted alongside them: the documentation corpus as MCP resources, and the guided integration walkthrough as an MCP prompt. Both are withheld unless asked for.
What arrives, and what to do with it
A token reads mmcp_xxxxxxxx_… — the five characters mmcp_, eight lowercase base32 characters, an underscore, then 43 more characters. There is no 0, 1, 8 or 9 in the middle section, so nothing there can be misread.
It is shown exactly once, at the moment it is minted. Nothing stores the whole token — only a keyed digest of its second half — so a token that has been lost is replaced rather than recovered. Put it straight into your client's configuration or a password manager, and never into a file you commit.
Your token also carries a per-minute rate limit and a daily call quota, both fixed when it is minted. Ask for figures that suit the work you are doing rather than meeting them under load.
You do not have to wait for it
With no token the connector still runs. It serves the credential-requiring tools from your own machine, reports the hosted half as unavailable, and keeps trying in the background, so you can build and sign payloads before an account exists. Install first if you would rather not be blocked.
Install the connector
Node.js 24.18.0 or newer, and one build.
Not on npm yet
The connector depends on the package that ships the transcribed JazzCash documentation, so publishing it would redistribute that corpus — and permission to do so is not settled. Until it is, build the connector from a checkout. Nothing else about the setup changes when it is published.The build produces connector/dist/index.js, which is the path every configuration in the next section points at. Note it down as an absolute path; a relative one will not resolve, because your AI client spawns the connector with your own workspace as its working directory rather than with the checkout.
git clone <this repository>
cd m-mcp
npm ci && npm run build # the server the local half is served from
cd connector
npm ci && npm run build # produces connector/dist/index.jsOnce the corpus question is settled, the connector is published as @atbas/m-mcp-connector and the two lines below replace the command and args of every snippet in the next section. There is no clone, no build, and nothing else to change.
"command": "npx",
"args": ["-y", "@atbas/m-mcp-connector"]Configure your AI client
One file, one entry. Pick your client below.
Put the token in env, not in args
ps, and /proc/<pid>/cmdline — so a token passed as --token= is exposed for as long as the connector runs. The flags exist for clients that offer no env block. Where both are set the environment wins, so configuring both leaves you protected by the safer of the two.Every snippet does the same three things: run the connector, pass your access token in the env block, and pass your JazzCash credentials in the same block. Replace /absolute/path/to/m-mcp/connector/dist/index.js with your own path and mmcp_xxxxxxxx_… with the token you were given. The credential variables are section 5; the sandbox ones are shown here so the file is complete the first time you save it.
{
"mcpServers": {
"m-mcp": {
"command": "node",
"args": ["/absolute/path/to/m-mcp/connector/dist/index.js"],
"env": {
"M_MCP_TOKEN": "mmcp_xxxxxxxx_…",
"JAZZCASH_SANDBOX_MERCHANT_ID": "MC12345",
"JAZZCASH_SANDBOX_PASSWORD": "…",
"JAZZCASH_SANDBOX_INTEGRITY_SALT": "…",
"JAZZCASH_SANDBOX_RETURN_URL": "https://shop.example.pk/jazzcash/return"
}
}
}
}Restart Claude Code, or run /mcp to check the connection.
An AI client reads its MCP configuration when it starts, so save the file and then restart the client. Nothing takes effect until you do.
The split
Where each tool runs, and why your credentials never leave your machine.
Your password, Integrity Salt and MPIN never leave your machine
The 4 tools that need a merchant credential run inside the connector your AI client spawned, against the environment you gave it. They are not part of the hosted surface at all: the hosted server is built from an explicit environment that carries no JazzCash credential variable, the deployment refuses to start if one appears in it, and the tool filter it registers from contains only the credential-free half. All three would have to fail together, in the same direction, for a credential to reach this host — and there would still be nothing here to reach it with.Runs on your machine
Resolve a credential on every path, so they only ever run where your credentials are.
- jazzcash_build_transaction_parameters
- jazzcash_send_gateway_request
- jazzcash_run_sandbox_smoke_test
- jazzcash_build_checkout_form
They sign a payload with your Integrity Salt, send it to the gateway, or write a checkout page that embeds your merchant password. No token is involved and no network call reaches this deployment.
Runs on the hosted endpoint
Need no configured credential, so your token scopes and meters them instead.
- jazzcash_list_integration_flows
- jazzcash_get_integration_flow
- jazzcash_search_docs
- jazzcash_get_doc_section
- jazzcash_explain_response_code
- jazzcash_get_onboarding_checklist
- jazzcash_build_secure_hash
- jazzcash_verify_secure_hash
- jazzcash_validate_payload
- jazzcash_generate_integration_code
- jazzcash_generate_ipn_handler
- jazzcash_verify_ipn_notification
- jazzcash_diagnose_integration_issue
Which of them your client actually lists depends on the scopes your token was granted. The endpoint records the method, the tool name, the outcome and the duration — never a tool argument, never a result, and never the token itself.
Your AI client sees one tool list
The connector decides where each call goes by name, and the local half always wins. Nothing in your client distinguishes the two, so nothing you ask it to do has to.
The hash tools are on the hosted side because they take an Integrity Salt as a call argument, at your choice, which is what lets you debug a mismatched hash without configuring anything. If you would rather not send one at all, the local jazzcash_build_transaction_parameters hashes with your configured salt and the value never leaves the machine.
Configuring the local half
These go in the same env block as your token. The connector reads exactly what the standalone server reads, from exactly the same places. Sandbox and production are separate profiles: the two share identical gateway URLs in every JazzCash guide, so which environment is in play is a property of the credentials, never of the address.
| Variable | Meaning |
|---|---|
JAZZCASH_SANDBOX_MERCHANT_IDJAZZCASH_PRODUCTION_MERCHANT_ID | Merchant ID for that environment |
JAZZCASH_SANDBOX_PASSWORDJAZZCASH_PRODUCTION_PASSWORD | Merchant password |
JAZZCASH_SANDBOX_INTEGRITY_SALTJAZZCASH_PRODUCTION_INTEGRITY_SALT | Integrity Salt — the HMAC key |
JAZZCASH_SANDBOX_MERCHANT_MPINJAZZCASH_PRODUCTION_MERCHANT_MPIN | MPIN, needed only for refunds |
JAZZCASH_SANDBOX_RETURN_URLJAZZCASH_PRODUCTION_RETURN_URL | The Return URL registered against your profile |
JAZZCASH_SANDBOX_IPN_URLJAZZCASH_PRODUCTION_IPN_URL | Your IPN listener |
JAZZCASH_CREDENTIALS_FILE | Absolute path to a JSON file holding the above |
JAZZCASH_CREDENTIALS_FILE is preferable wherever the client configuration itself is committed — a project-level Cursor file, for instance. Point it at an absolute path outside the repository.
{
"sandbox": { "merchantId": "MC12345", "password": "…", "integritySalt": "…" },
"production": { "merchantId": "MC12345", "password": "…", "integritySalt": "…" }
}Two variables that change behaviour rather than identity
JAZZCASH_ENVIRONMENT is sandbox or production, and selects the profile used when a call names none. It defaults to sandbox.
JAZZCASH_ALLOW_LIVE is the first of two opt-ins for moving real money: it must be true, and the individual call must additionally pass confirmLiveEnvironment: true. Both apply on your machine and only there — the hosted half holds no credential and cannot move money at all.
The connector reads no .env file, deliberately. Your AI client spawns it with your own workspace as its working directory, so a dotenv loader would read your application's own .env — which for a live site very plausibly holds production credentials. Which environment is in play must always be a decision, never a side effect of where the process happened to start.
Initialise and confirm
What to set, in what order, and how to know it worked.
Set these, in this order
M_MCP_TOKEN, in theenvblock. Skip it if you do not have a token yet; the connector runs local-only without one.JAZZCASH_SANDBOX_MERCHANT_ID,JAZZCASH_SANDBOX_PASSWORDandJAZZCASH_SANDBOX_INTEGRITY_SALT— the three the local half needs at a minimum. Or setJAZZCASH_CREDENTIALS_FILEto an absolute path and put them there instead.JAZZCASH_SANDBOX_RETURN_URL, if the flow you are integrating redirects the customer back to you. Payload validation checks against the Return URL registered on your profile when it knows one.Nothing else. Leave
JAZZCASH_ENVIRONMENTunset so it stays on sandbox, and leaveJAZZCASH_ALLOW_LIVEunset until you are deliberately moving real money.Save the file and restart your AI client.
Then check both halves
Either half can be wrong on its own, so each is confirmed separately.
Is the server connected?
In Claude Code and in Codex, run /mcp. The entry named m-mcp should be listed and connected. In the other clients, look for it in the MCP panel. Diagnostics from the connector go to standard error, which is what your client's MCP log pane shows.
Does the hosted half answer?
Ask your client to make the first tool call. This one needs nothing of yours configured, so it isolates the token and the endpoint.
Use jazzcash_list_integration_flows to show me every JazzCash
integration flow you can see.A good answer lists the flows by id with the transport, the version, whether the flow moves money, when to use it and its endpoint — and closes by noting that sandbox and production share identical endpoints. An empty or very short list usually means the token's scope is narrower than you expected, not that anything is broken.
Does the local half have your credentials?
This one runs entirely inside the connector and sends nothing anywhere. It is the cheapest proof that your credentials are readable and your Integrity Salt signs.
Use jazzcash_build_transaction_parameters for flowId
"card-page-redirection-v1.1" with amount "100.00", and tell me which
fields it filled in for me.A good answer is a complete parameter map with a timestamp in Pakistan Standard Time, the amount converted to minor units, a generated transaction reference and pp_SecureHash computed last, with your password and salt masked in the output. If the credentials are not readable it says so in as many words — No usable sandbox credentials are configured — and names the variables to set.
When you are ready to send one
jazzcash_run_sandbox_smoke_test builds, validates, signs, sends and interprets a single sandbox transaction in one step, and refuses production outright. It needs the sandbox test mobile numbers and CNICs, which no JazzCash guide publishes — ask your JazzCash contact for them before you try.
When something is refused
Three refusals you may meet, and which of them you can fix.
The token was not accepted
The request carried no token, a token that does not match the required shape, or one that matches no issued token. It is not a statement that your token was revoked.
Check, in this order: the header is Authorization: Bearer mmcp_… with no quotes and no stray whitespace; the token is complete — mmcp_, eight lowercase base32 characters, an underscore, then 43 more, and a truncated copy-paste is by far the commonest cause; and you are sending it to the right deployment.
The token is finished
The token was recognised and is no longer usable: revoked, past its expiry, or belonging to a merchant that has been deactivated. The endpoint does not say which, by design.
Ask your administrator for a new token. Nothing you can change at your end will make the request succeed. Meanwhile the connector's local half keeps working, because it never depended on this endpoint in the first place.
Over an allowance
Back off for the number of seconds in the Retry-After header, which is always present on a 429 and is capped at one hour.
Sixty seconds or fewer means a per-minute rate limit, on your token or on your address — reduce concurrency, because a client retrying a failed call in a tight loop is the usual cause. Longer than that means a daily or monthly quota, which will not clear by retrying sooner. Never retry automatically without honouring Retry-After.
What the connector says on standard error
A missing token, an unreachable endpoint or an exhausted allowance does not stop the connector: it serves the local tools, reports the hosted half as unavailable and keeps trying in the background. A token the endpoint actively rejects is the exception — that is a configuration mistake only you can fix, so it refuses to start and says so.
| What you see | What to do |
|---|---|
| token rejected — check M_MCP_TOKEN | The token was not accepted. Check it was copied whole; remove it to run local-only. |
| token revoked or expired — ask your administrator for a new one | The token is finished. A new one has to be minted. |
| rate limit reached, retry after N seconds | An allowance was reached. The local tools are unaffected. |
| … could not be reached (ECONNREFUSED) | The endpoint named in the message did not answer. Check M_MCP_URL and your network. |
A tool you expected is missing
Two reasons, and they need different actions.
It is one of the credential-requiring tools. Those are not on the hosted endpoint under any scope and never will be. Run them from the connector, on your own machine, with your own credentials — which means checking that the credential variables in section 5 are set.
Its group or its provider is outside your scope. Ask your administrator to widen the token's scope, or to tell you what it was issued for.
The connector never prints your token, not even truncated, and never writes it to a file. If you find one in a log, that is a defect worth reporting.