AI agents and MCP
Any AI agent can use Xaalis: learn the API, open a sandbox account, collect Wave and Orange Money payments, refund, bill subscriptions and pay people out — with little or no human help, and without ever being able to move live money beyond what a human allowed.
| You want… | Use |
|---|---|
| an assistant (Claude, ChatGPT, Cursor, VS Code, Codex…) to operate Xaalis for you | the MCP server — connect your client |
| a coding agent to integrate Xaalis into your app | the Agent Skills (or the Claude Code plugin) + the MCP server for docs and test objects |
| your own agent (OpenAI, Anthropic, Vercel AI SDK, LangChain, Python) to call Xaalis | the tool catalog — frameworks |
LLM-readable docs: /llms.txt · /llms-full.txt.
What an agent can do — the credential decides
Section titled “What an agent can do — the credential decides”The MCP server only lists the tools the connected credential allows, so a model can’t call what it can’t see — the first defence against a prompt injection asking it to “just send a payout”. The API enforces the same limits again.
| Credential | Tools |
|---|---|
| none | xaalis_whoami, xaalis_search_docs, xaalis_sandbox_signup (creates a sandbox account; the session then uses it) |
sk_test_… sandbox |
everything, with fake money: payments + xaalis_simulate_payment, refunds, subscriptions + xaalis_advance_subscription, payouts, agent-wallet setup |
sk_live_… |
read everything; create payments and subscriptions (money in); cancel subscriptions; disable agent wallets. No payouts. Refunds only if a human turned them on |
rk_test_… / rk_live_… restricted key, or an OAuth sign-in |
the same, narrowed to the scopes a human granted in the dashboard (e.g. payments:read + payments:write only). Refunds appear only if refunds:write was granted |
ak_test_… / ak_live_… agent wallet |
its own policy and balance, and payouts within the per-payout cap, daily cap, recipient list and balance a human set |
Test credentials go to the sandbox API, live ones to production — automatically.
Least privilege: for an agent in production, prefer a restricted key (dashboard → API keys → restricted,
pick the scopes) or an OAuth sign-in over a full sk_live_ key. Scopes: payments:read, payments:write,
refunds:write, subscriptions:read, subscriptions:write, payouts:read, balance:read, webhooks:read,
agent_wallets:read, agent_wallets:write (and payouts:write, webhooks:write, which the MCP tools don’t use).
Live refunds with a full sk_live_ key are off unless the human who sets up the connection turns them on: header
X-Xaalis-Allow-Live-Refunds: true (hosted) or XAALIS_ALLOW_LIVE_REFUNDS=true (local). With a restricted key or
OAuth, granting refunds:write is that decision. The model can change neither.
Money out is done only by agent wallets: a separate balance (the agent’s total budget), a per-payout cap, an
optional daily cap and an allow-list of phone numbers, with a key that can do nothing else. Retrying the same
action_id never pays twice. In production, only a dashboard owner can create, fund and issue keys for a live
agent wallet — never an API key, so an agent can’t fund itself. See Agent wallets.
Rules every agent follows
Section titled “Rules every agent follows”The server sends these as MCP instructions; the skills repeat them.
- Amounts are whole XOF integers (
15000), never decimals. - Every write takes an
idempotency_keyderived from the business action; retries reuse it. - A payment is paid only when it reads
succeeded(or a signed webhook says so) — never because of a redirect. - Test keys are fake money. With a live key, confirm amount and purpose with the human before any write.
- Money goes out only through agent wallets.
outcome_unknown: true→ read the object or retry with the same key; never create a second one.- Secret keys stay in environment variables or a secret store — never in chat, code or logs.
Zero-human start (sandbox)
Section titled “Zero-human start (sandbox)”Connect without a key. The agent calls xaalis_sandbox_signup with an email and a business name and gets a
sandbox account (sk_test_… key + webhook secret). The same session switches to it, so the agent can go straight on:
create a payment, simulate the customer paying, refund it, set up a subscription.
- Local server: the session keeps the key until the process stops.
- Hosted server: connect to
https://mcp.xaalis.org/sandboxwith no credential. The session (Mcp-Session-Id) keeps the sandbox key in memory for up to 30 idle minutes. Clients set to “no authentication” (ChatGPT, claude.ai) use this; the sandbox tools are listed from the start and answersignup_requireduntil the signup. - To keep the account, store the returned
secret_keyasXAALIS_API_KEYand reconnect with it.
Going live always needs a human: identity checks (KYC), approval, then a live key.
Connect your client
Section titled “Connect your client”| Hosted endpoint | Credential |
|---|---|
https://mcp.xaalis.org/mcp |
Authorization: Bearer <key> (sk_, rk_, ak_), or OAuth: without a credential it answers 401 and OAuth-capable clients open the Xaalis sign-in, where you pick the account, test or live, and the scopes |
https://mcp.xaalis.org/sandbox |
none — the zero-human sandbox session |
Local: npx -y @xaalis/mcp (Node 20+) with the key in XAALIS_API_KEY. Omit the key for the zero-human start.
Claude Code
Section titled “Claude Code”claude mcp add --transport http xaalis https://mcp.xaalis.org/mcp --header "Authorization: Bearer $XAALIS_API_KEY"# or local:claude mcp add --env XAALIS_API_KEY=$XAALIS_API_KEY --transport stdio xaalis -- npx -y @xaalis/mcpOr install the plugin (MCP server + skills; the key is asked once and kept in your OS credential store):
/plugin marketplace add <path-or-repo-with-integrations/ai>/plugin install xaalis@xaalisProject .mcp.json (shared with your team — the key stays in each person’s environment):
{ "mcpServers": { "xaalis": { "type": "http", "url": "https://mcp.xaalis.org/mcp", "headers": { "Authorization": "Bearer ${XAALIS_API_KEY}" } } }}Claude Desktop and claude.ai
Section titled “Claude Desktop and claude.ai”Local server — claude_desktop_config.json (macOS ~/Library/Application Support/Claude/, Windows %APPDATA%\Claude\):
{ "mcpServers": { "xaalis": { "command": "npx", "args": ["-y", "@xaalis/mcp"], "env": { "XAALIS_API_KEY": "sk_test_…" } } } }Remote custom connector (Customize → Connectors → Add custom connector):
- your account: URL
https://mcp.xaalis.org/mcp— Claude opens the Xaalis sign-in (OAuth). You choose the account, test or live, and what the connector may do (scopes). Withdrawing that consent takes effect immediately. - no account yet: URL
https://mcp.xaalis.org/sandboxwith no sign-in — the zero-human sandbox session.
ChatGPT
Section titled “ChatGPT”Plugins → Add → Add custom MCP server (no developer mode needed any more):
- your account: URL
https://mcp.xaalis.org/mcp, authentication OAuth — ChatGPT discovers the Xaalis sign-in by itself; you choose the account, test or live, and the scopes. - no account yet: URL
https://mcp.xaalis.org/sandbox, No authentication — the agent searches the docs, opens a sandbox account and uses it in that conversation.
What the Xaalis sign-in asks (OAuth)
Section titled “What the Xaalis sign-in asks (OAuth)”Checked end to end with Claude.ai and ChatGPT on 2026-10-14:
- Only an owner of the business can authorize a connector; a teammate with another role sees “Autorisation non disponible”.
- You pick the business and test or live (live only once the business is activated), then untick any permission
you don’t want to give — e.g. keep
payments:read,balance:readandpayments:write, and leave refunds, payouts and agent-wallet writes off. The connector gets exactly what stays ticked. - Approve within 10 minutes of clicking Connect; after that the request expires (“Erreur de continuation OAuth”) and you start again from Connect.
- Access tokens last 5 minutes and are renewed in the background (
offline_access). Settings → Applications & IA → Révoquer l’accès cuts the connector off at once — its next call fails even with an unexpired token.
Cursor
Section titled “Cursor”.cursor/mcp.json (project) or ~/.cursor/mcp.json:
{ "mcpServers": { "xaalis": { "url": "https://mcp.xaalis.org/mcp", "headers": { "Authorization": "Bearer ${env:XAALIS_API_KEY}" } } }}Local instead: { "command": "npx", "args": ["-y", "@xaalis/mcp"], "env": { "XAALIS_API_KEY": "${env:XAALIS_API_KEY}" } }.
VS Code (GitHub Copilot)
Section titled “VS Code (GitHub Copilot)”.vscode/mcp.json — note the top-level key servers; VS Code asks for the key once and stores it:
{ "inputs": [{ "type": "promptString", "id": "xaalis-key", "description": "Xaalis API key", "password": true }], "servers": { "xaalis": { "type": "http", "url": "https://mcp.xaalis.org/mcp", "headers": { "Authorization": "Bearer ${input:xaalis-key}" } } }}OpenAI Codex CLI
Section titled “OpenAI Codex CLI”~/.codex/config.toml:
[mcp_servers.xaalis]url = "https://mcp.xaalis.org/mcp"bearer_token_env_var = "XAALIS_API_KEY"
# or local:# [mcp_servers.xaalis]# command = "npx"# args = ["-y", "@xaalis/mcp"]# env_vars = ["XAALIS_API_KEY"]Gemini CLI
Section titled “Gemini CLI”~/.gemini/settings.json or .gemini/settings.json:
{ "mcpServers": { "xaalis": { "httpUrl": "https://mcp.xaalis.org/mcp", "headers": { "Authorization": "Bearer $XAALIS_API_KEY" } } }}Windsurf / Devin Desktop
Section titled “Windsurf / Devin Desktop”~/.config/devin/mcp_config.json (older Windsurf: ~/.codeium/windsurf/mcp_config.json):
{ "mcpServers": { "xaalis": { "serverUrl": "https://mcp.xaalis.org/mcp", "headers": { "Authorization": "Bearer ${env:XAALIS_API_KEY}" } } }}settings.json:
{ "context_servers": { "xaalis": { "command": "npx", "args": ["-y", "@xaalis/mcp"], "env": { "XAALIS_API_KEY": "sk_test_…" } } }}OpenAI API and Agents SDK
Section titled “OpenAI API and Agents SDK”Responses API — OpenAI calls the tools itself:
await openai.responses.create({ model: "gpt-5", input: "Create a 15000 F CFA payment for 'Tissus wax' and give me the link.", tools: [{ type: "mcp", server_label: "xaalis", server_url: "https://mcp.xaalis.org/mcp", headers: { Authorization: `Bearer ${process.env.XAALIS_API_KEY}` }, require_approval: "always", // keep "always" with live keys }],});Agents SDK: new MCPServerStreamableHttp({ url: "https://mcp.xaalis.org/mcp", requestInit: { headers: { Authorization: … } } })
(TypeScript) or MCPServerStreamableHttp(params={"url": …, "headers": {…}}) (Python).
Anthropic API
Section titled “Anthropic API”MCP connector (beta header mcp-client-2025-11-20):
{ "mcp_servers": [{ "type": "url", "url": "https://mcp.xaalis.org/mcp", "name": "xaalis", "authorization_token": "sk_test_…" }], "tools": [{ "type": "mcp_toolset", "mcp_server_name": "xaalis" }]}Complete, runnable versions of these: integrations/ai/examples/ in the Xaalis repository.
Skills for coding agents
Section titled “Skills for coding agents”Two Agent Skills, in the Claude Code plugin and usable by any skills-aware agent:
- xaalis-integration — add Xaalis to an app: server-side payment creation, redirect, webhook verification (Node, Python, PHP, Go), fulfilment, sandbox tests, refunds, subscriptions, payouts, go-live.
- xaalis-operations — run a business through the MCP tools: collect and confirm, refund, subscriptions, balance, webhook debugging, agent-wallet payouts, error handling.
For agents that read AGENTS.md (Codex, Gemini CLI, Copilot, Jules…), paste the ready-made section
integrations/ai/AGENTS.xaalis.md into yours. Cursor: integrations/ai/cursor/xaalis.mdc → .cursor/rules/.
Your own agent (no MCP)
Section titled “Your own agent (no MCP)”The same tool catalog runs in-process: you pass the tool definitions to your model and execute its calls.
TypeScript — @xaalis/ai-tools:
import { AGENT_RULES, XaalisToolkit } from "@xaalis/ai-tools";import { openAITools, runOpenAIToolCall } from "@xaalis/ai-tools/openai"; // Responses / Chat Completionsimport { anthropicTools, runAnthropicToolUse } from "@xaalis/ai-tools/anthropic";import { vercelTools } from "@xaalis/ai-tools/vercel"; // AI SDK: tools: vercelTools(kit)import { langChainTools } from "@xaalis/ai-tools/langchain"; // needs @langchain/core
const kit = new XaalisToolkit({ apiKey: process.env.XAALIS_API_KEY }); // no key: docs + sandbox signup// restricted key (rk_) or OAuth token: const kit = await XaalisToolkit.connect({ apiKey }) — loads its scopesconst tools = openAITools(kit); // pass to the modelconst output = await runOpenAIToolCall(kit, call.name, call.arguments); // run what it callsPython — xaalis.ai (standard library only):
from xaalis.ai import AGENT_RULES, XaalisToolkit
kit = XaalisToolkit(os.environ.get("XAALIS_API_KEY"), allow_live_refunds=False)tools = kit.openai_tools() # or openai_chat_tools(), anthropic_tools(), langchain_tools()output = kit.run_for_model(call.name, call.arguments)Results are JSON; errors come back as {"error": {"code", "message", "hint", "outcome_unknown"}} so the model knows
the next step. After a sandbox signup, rebuild the tool list (kit.tools() changes).
Tool reference
Section titled “Tool reference”Keys column: sk = merchant keys (and restricted keys / OAuth with the matching scope), ak = agent-wallet keys.
| Tool | Keys | Does |
|---|---|---|
xaalis_whoami |
all | connected key, mode, account/wallet, available tools |
xaalis_search_docs |
all | search this documentation |
xaalis_sandbox_signup |
none | create a sandbox account (email, business name) |
xaalis_create_payment · _get_payment · _list_payments |
sk | payment + checkout_url; status |
xaalis_simulate_payment |
sk_test | make a test payment succeed or fail |
xaalis_refund_payment · _list_refunds |
sk (live: if allowed) | full refund of a Wave payment; check it |
xaalis_get_balance |
sk | available and reserved XOF |
xaalis_create_payout |
sk_test | payout from the merchant balance (sandbox) |
xaalis_get_payout · _list_payouts |
sk | payout status |
xaalis_list_webhook_deliveries |
sk | recent webhooks, attempts, last error |
xaalis_create_subscription · _get_subscription · _list_subscriptions · _cancel_subscription |
sk | subscriptions and instalment plans |
xaalis_advance_subscription |
sk_test | jump to the next billing event |
xaalis_get_invoice · _list_invoices |
sk | invoices and their stable payment link |
xaalis_create_agent_wallet · _fund_agent_wallet · _reclaim_agent_wallet · _issue_agent_key |
sk_test | set up an agent wallet (production: a human, in the dashboard) |
xaalis_disable_agent_wallet · _list_agent_wallets · _get_agent_wallet |
sk | stop and inspect agent wallets |
xaalis_agent_get_wallet · _agent_pay · _agent_get_payout · _agent_list_payouts |
ak | the agent’s own wallet and payouts |
Resources: xaalis://rules, xaalis://docs/llms.txt, xaalis://docs/llms-full.txt, xaalis://openapi.json.
Prompts: accept_payment, integrate_xaalis, sandbox_tour.
Security notes
Section titled “Security notes”- The hosted server keeps nothing: a request with a key or token is handled and forgotten; an anonymous
/sandboxsession holds only a sandbox key, in memory. Keys, tokens and request bodies are never logged. - OAuth tokens last five minutes (clients refresh them). The server checks their signature and audience, and the API re-checks consent, membership and scopes on every call — a withdrawn consent takes effect at once.
- A live key is only ever sent over HTTPS.
- Give an agent the least it needs: a sandbox key to build and test; for live, a live key (money in) and, if it must pay people, its own agent wallet with a small balance and cap. Disable the wallet to stop it instantly.
- Treat anything the agent reads (web pages, emails, documents) as untrusted: it can’t unlock tools its key doesn’t have, but review what it proposes before approving live actions.