jami-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@jami-mcpCreate a 1,237 birr Telebirr checkout for order #1042 and wait."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
jami-mcp
The official Model Context Protocol server for JamiDev — Jami's payments API for Ethiopia. Connect it to Claude, Cursor, VS Code, Codex or any MCP client and your agent can create ETB checkouts, watch them settle, reconcile orders, preview and send payouts, debug webhooks, and read the Jami docs while it writes your integration.
Built on the official jami-sdk, so every tool
behaves exactly like the SDK and the REST API.
npx -y jami-mcpQuick start
Get a token: Jami dashboard → JamiDev → Developer → API Tokens. Start with a sandbox org — its
jamidev_test_…token moves no real money.Add the server to your client (below), with the token as
JAMI_TOKEN.Ask: "Charge buyer@example.com 1,237 birr for order #1042 on Telebirr, phone 251900000001, and wait for it."
No token yet? The server still runs. The docs, withdrawal-quote and webhook tools work without one, so you can start building right away.
Claude Code
claude mcp add jami -e JAMI_TOKEN=jamidev_test_xxx -- npx -y jami-mcpClaude Desktop · Cursor · Windsurf
Add to claude_desktop_config.json, ~/.cursor/mcp.json or ~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"jami": {
"command": "npx",
"args": ["-y", "jami-mcp"],
"env": { "JAMI_TOKEN": "jamidev_test_xxx" }
}
}
}VS Code
.vscode/mcp.json — VS Code prompts for the token and stores it securely:
{
"inputs": [
{ "type": "promptString", "id": "jami-token", "description": "JamiDev API token", "password": true }
],
"servers": {
"jami": {
"type": "stdio",
"command": "npx",
"args": ["-y", "jami-mcp"],
"env": { "JAMI_TOKEN": "${input:jami-token}" }
}
}
}Codex
~/.codex/config.toml:
[mcp_servers.jami]
command = "npx"
args = ["-y", "jami-mcp"]
env = { JAMI_TOKEN = "jamidev_test_xxx" }Related MCP server: mcp-jazzcash
Tools
Tool | What it does | Needs token |
| Charge a product ( | ✓ |
| Create or edit products; each comes back with its public page and | ✓ |
| Read the catalog. | ✓ |
| Check a session once, with the failure reason when it expired. | ✓ |
| Wait for the buyer to finish, with progress updates. Never hangs: returns | ✓ |
| Orders, newest first, paginated and filterable by status. | ✓ |
| Withdrawable earnings and whether the org can withdraw. | ✓ |
| Fee, tax and net for an amount, plus auto-pay and cap checks. Offline. | — |
| Pay out to Telebirr, M-Pesa or CBE Birr. Opt-in (see Safety). | ✓ |
| Track payouts. | ✓ |
| Check a captured delivery's signature, and why it fails. | — |
| Build a correctly signed test event, and optionally POST it to your local handler. | — |
| Search and read the live docs at dev.jami.bio. | — |
Every tool returns a readable markdown summary plus typed structuredContent. Pass
response_format: "json" for the raw payload. Money is always integer santim, and
every parameter that takes money ends in _minor: amount_minor: 15000 = 150.00 ETB.
Prompts: integrate_jami (build a full integration in your stack), go_live_checklist,
debug_payment. Resource: jami://reference — fees, limits, sandbox numbers, failure
codes and webhook rules in one page.
Safety
The defaults are set so an agent can't move money by accident.
Withdrawals are off until you start the server with
--enable-withdrawals(orJAMI_ENABLE_WITHDRAWALS=true). When they're on, clients that support elicitation ask you to confirm each payout, and every payout needs anidempotency_key, so a retry can never pay twice. Sandbox tokens are refused before any request is made.--read-onlyregisters only the tools that read data. Use it for reporting agents.Live mode is announced. With a
jamidev_live_token, the server tells the agent that checkouts charge real buyers and to confirm first.Tokens stay in the environment. They never appear in tool output.
Options
--http Streamable HTTP on POST /mcp instead of stdio
--port <n> HTTP port (default 3333)
--host <addr> HTTP bind address (default 127.0.0.1)
--read-only Only read tools
--enable-withdrawals Register jami_create_withdrawal
--base-url <url> Override the API base (default https://jami.bio/api/jamidev)
--docs-url <url> Override the docs origin (default https://dev.jami.bio)Env | Purpose |
|
|
| Default secret for the webhook tools |
| Same as the flags |
Remote (HTTP) mode
npx -y jami-mcp --http --port 3333
# → http://127.0.0.1:3333/mcp (health check: /healthz)The HTTP server is stateless, so any number of clients can share one process. Without
JAMI_TOKEN, each request authenticates with its own Authorization: Bearer jamidev_…
header, which makes one deployment safe to share across teams. On loopback it rejects
foreign Host headers (DNS-rebinding protection). In HTTP mode, jami_create_test_webhook
never sends requests; it only returns the signed payload and a curl command.
Embedding
import { createJamiServer } from 'jami-mcp';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
const server = createJamiServer({ token: process.env.JAMI_TOKEN, docsUrl: 'https://dev.jami.bio', readOnly: true, withdrawals: false });
await server.connect(new StdioServerTransport());Development
npm install
npm test # in-memory MCP client against a mocked API
npm run build
npm run inspect # opens the MCP Inspector on dist/index.jsFull guide: dev.jami.bio/docs/mcp · Support: support@jami.bio
MIT © Jami
Available Tools
16 toolsjami_create_checkoutCreate checkoutA
Start a checkout and get back how the buyer pays — either for one of the organization's published products, or for ANY amount with no product ("charge this buyer 1,237 ETB for order #1042").
Buyers pay in ETB via Telebirr, M-Pesa or CBE Birr; nothing is added on top. In LIVE mode a "direct" checkout pushes a real payment prompt to the buyer's phone, so only call this when the user actually wants to charge someone.
What to charge:
Product: product_id (p_… token or 24-char id, must be published). amount_minor only for flexible-price (pwyw) products.
Custom amount: omit product_id, pass amount_minor (≥ 100 = 1.00 ETB) and description (what the buyer sees, ≤ 120 chars).
How to collect it:
Direct push: pass gateway + customer_email + customer_phone. The prompt goes straight to the buyer's phone (kind 'direct').
Payment link: omit gateway. You get a Jami link in checkout_url (kind 'redirect') to send the buyer by SMS/Telegram/email; they pick the method and enter their details there, and can retry a failed attempt until the link expires (30 min). customer_* is optional.
Args:
customer_email / customer_phone: required for a direct push; optional for a link. Phone like "251911223344" or "0911223344". Sandbox magic numbers: 251900000001 = instant success, 251900000002 = instant failure.
gateway: 'telebirr' | 'mpesa' | 'cbe'. Omit for a payment link.
amount_minor: integer santim. 123700 = 1,237.00 ETB.
metadata: optional string map (e.g. { "orderId": "1042" }) stored on the order and sent back on order webhooks.
Returns: { session_id, kind: 'free' | 'redirect' | 'direct', checkout_url, order_id }.
free: completed instantly; order_id is set.
redirect: send the buyer to checkout_url.
direct: the buyer confirms on their phone; call jami_wait_for_checkout next.
| Name | Required | Description | Default |
|---|---|---|---|
| gateway | No | Payment method for paid products | |
| metadata | No | Your own key/values, returned on order webhooks (max 20 keys) | |
| product_id | No | Product token (p_…) or id. Omit for a custom-amount checkout. | |
| description | No | Custom amount only: what the buyer is paying for, e.g. "Order #1042" | |
| success_url | No | Where to send the buyer after paying | |
| amount_minor | No | Integer santim. Required for custom amounts (≥ 100) and pay-what-you-want products; ignored for fixed prices | |
| checkout_link | No | Checkout link token (cl_…) to attribute this session to | |
| customer_name | No | ||
| customer_email | No | Buyer email for the receipt. Required with gateway; optional for a payment link | |
| customer_phone | No | Buyer phone, e.g. "251911223344" | |
| collected_fields | No | Answers to the product's checkout fields, keyed by field id | |
| customer_external_id | No | Your own user id, stored on the customer record |
Output Schema
| Name | Required | Description |
|---|---|---|
| kind | Yes | |
| order_id | Yes | |
| session_id | Yes | |
| checkout_url | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare mutation/non-idempotent/open-world, but the description adds substantial context they don't carry: LIVE mode pushes a real payment prompt to a phone, link expiry is 30 minutes, failed attempts can be retried, ETB-only payment with nothing added on top, and sandbox magic numbers for instant success/failure. This is unusually rich operational disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well front-loaded with the core outcome first, then structured 'What to charge' / 'How to collect it' / Args / Returns sections that are easy to scan. It is somewhat long and a few lines (phone format, amount_minor units) duplicate schema text, but the structure justifies the length.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers modes, gateway selection, when-to-call caution, error/retry behavior, expiry, and next-step routing; an output schema exists yet the description still summarizes the return shape (session_id/kind/checkout_url/order_id) and how to act on each kind. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is already 92%, so the schema carries most parameter detail. The description nonetheless adds cross-parameter semantics the schema cannot express: product_id vs. amount_minor mutual exclusion, gateway-driven kind selection, and required/optional status of customer_email/customer_phone per mode. It omits explanation of secondary params (success_url, checkout_link, collected_fields, customer_external_id), keeping it from a 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Start a checkout and get back how the buyer pays') and immediately distinguishes the two modes it serves: a published product vs. an arbitrary custom amount. It also names the sibling workflow it feeds into (jami_wait_for_checkout), so an agent can place it in the toolset without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when NOT to call it ('only call this when the user actually wants to charge someone') and lays out the decision between direct push vs. payment link with the exact parameter conditions (pass gateway vs. omit gateway). It routes the agent to jami_wait_for_checkout for the direct case, which is explicit alternative guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
jami_create_productCreate productA
Create a product the organization sells, and get its public Jami page (url) and p_… token. Published by default, so the page and checkouts work immediately.
Pricing (can't be changed after creation; the amounts can):
fixed: amount_minor is the price, e.g. 250000 = 2,500.00 ETB.
pwyw (flexible): minimum_amount_minor; each checkout then sends its own amount.
free: no price.
Args: title (1–120 chars), pricing_model, amount_minor / minimum_amount_minor, description?, status? ('published' | 'draft').
Returns: { product_id, token, url, title, status, pricing_model, price }. To charge for it, call jami_create_checkout with product_id = token (omit gateway for a payment link).
| Name | Required | Description | Default |
|---|---|---|---|
| title | Yes | ||
| status | No | published | |
| description | No | ||
| amount_minor | No | Fixed price in santim | |
| pricing_model | Yes | ||
| response_format | No | 'markdown' (default) for a readable summary, 'json' for the full structured payload | markdown |
| minimum_amount_minor | No | Flexible price floor in santim |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | Yes | Public Jami page where anyone can buy it (published only) |
| price | Yes | |
| title | Yes | |
| token | Yes | Use as product_id in jami_create_checkout |
| status | Yes | |
| product_id | Yes | |
| amount_minor | Yes | |
| pricing_model | Yes | |
| minimum_amount_minor | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare this is a non-read-only, non-idempotent, non-destructive write, so the bar is lower. The description adds the crucial immutability constraint ('Pricing can't be changed after creation; the amounts can') and the default publication behavior, which are not visible in the structured fields. It does not cover auth/permission requirements or reversal.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads purpose, then a compact pricing block, then args, then return shape and next step. Every section earns its place, though the Args/Returns lines partially restate schema and output-schema data.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers the full lifecycle an agent needs: what is created, defaults, immutable vs mutable fields, the returned fields, and the follow-up call. An output schema exists, yet the description's summary of returns is coherent with it rather than missing anything critical.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 43%, so the description must carry weight, and it does: it explains all three pricing_model modes and their corresponding amount fields (amount_minor with the 250000 = 2,500.00 ETB example, minimum_amount_minor, free) plus the status values. It omits the response_format parameter entirely, leaving one gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Create a product the organization sells') and immediately scopes the outcome (public Jami page url + p_… token). It is clearly distinguished from siblings jami_update_product and jami_get_product without needing to open their schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear operative context ('Published by default, so the page and checkouts work immediately') and routes the agent onward ('To charge for it, call jami_create_checkout with product_id = token'). It lacks an explicit when-not-to-use statement (e.g. vs update_product for existing products), so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
jami_create_test_webhookCreate test webhookA
Build a correctly signed JamiDev webhook delivery for testing a handler locally — no real event needed.
Args:
type: 'order.created' | 'order.completed' | 'benefit.granted' | 'checkout.session.expired' | 'withdrawal.paid' | 'withdrawal.failed'.
secret: signing secret (defaults to JAMI_WEBHOOK_SECRET; any string works for a local test).
data: optional fields to merge over the realistic sample payload.
livemode: default false (sandbox).
target_url: optional. When set, the delivery is POSTed there (e.g. "http://localhost:3000/webhooks/jami") and the response status is reported.
Returns: { payload, signature, headers, curl } — the exact body and X-JamiDev-Signature to send, plus delivery_status when target_url is set. Handlers must verify the RAW body and reply 2xx within 10 seconds.
| Name | Required | Description | Default |
|---|---|---|---|
| data | No | ||
| type | Yes | ||
| secret | No | ||
| livemode | No | ||
| target_url | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| curl | Yes | |
| headers | Yes | |
| payload | Yes | |
| signature | Yes | |
| delivery_error | No | |
| delivery_status | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare the safety profile (readOnlyHint=false, openWorldHint=true), and the description adds substantial context beyond them: default secret from JAMI_WEBHOOK_SECRET, livemode defaults to sandbox, target_url triggers an actual POST with reported status, and handlers must verify the RAW body and reply 2xx within 10 seconds. These are genuine operational traits not derivable from annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded purpose followed by clean Args/Returns sections; every element is useful. Minor redundancy in re-listing the enum values already present in the schema, but overall tight and well-structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 5 params, an object-typed field, and an existing output schema, the description still supplies the merge semantics, signing/verification requirements, and timeout constraint an agent needs to use the tool correctly. Nothing material is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full param burden and does so: it documents all five params (type enum, secret default source, data merge-over-sample semantics, livemode sandbox default, optional target_url POST semantics). This fully compensates for the missing schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb+resource with scope: 'Build a correctly signed JamiDev webhook delivery for testing a handler locally — no real event needed.' The phrase 'no real event needed' distinguishes it from a real webhook flow and from the sibling jami_verify_webhook. An agent can tell what it does without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Clearly states the use case (testing a handler locally) and the condition for the POST behavior (target_url set, response status reported). It does not explicitly name an alternative like jami_verify_webhook or when-not to use it, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
jami_get_balanceGet balanceARead-onlyIdempotent
Get the organization's withdrawable JamiDev earnings — the ceiling on what jami_create_withdrawal can pay out.
Returns: { balance_minor, balance, eligible, currency }. eligible is false (and balance 0) when the org can't withdraw yet: it's a sandbox org, Developer Mode is off, or KYC isn't approved. The money itself sits in the owner's unified Jami wallet, so a withdrawal can still fail with 402 if that wallet was spent elsewhere.
| Name | Required | Description | Default |
|---|---|---|---|
| response_format | No | 'markdown' (default) for a readable summary, 'json' for the full structured payload | markdown |
Output Schema
| Name | Required | Description |
|---|---|---|
| balance | Yes | |
| currency | Yes | |
| eligible | Yes | |
| balance_minor | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only cover the read-only/idempotent safety profile, so the description usefully adds behavior: what 'eligible=false' means, why balance can be 0, and that a withdrawal can still fail with 402 because funds live in the owner's unified wallet. That last point is non-obvious operational context not derivable from the schema. It stops short of discussing caching, rate limits, or staleness of the balance.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tightly-packed sentences: purpose first, return shape second, failure semantics third. No repetition, no filler, and nothing is buried.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema and read-only annotations already present, the description only needs to supply the non-structured context, and it does: eligibility gating and the 402 wallet-spend edge case. Slightly thin on the relationship to the other withdrawal siblings (quote/get/list), but complete enough to call correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Only one parameter (response_format) with 100% schema description coverage including its enum values, so the schema fully documents it. The description adds nothing about parameter semantics, which is acceptable at this coverage level but earns only the baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb and resource ('Get the organization's withdrawable JamiDev earnings') with an explicit framing as a ceiling relative to the payout sibling jami_create_withdrawal. An agent can distinguish this read tool from the withdrawal/quote siblings without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It ties the tool to jami_create_withdrawal ('the ceiling on what ... can pay out') and explains the conditions under which the tool is useless (sandbox org, Developer Mode off, KYC not approved). Clear context for use, but it never says explicitly when to prefer it over jami_quote_withdrawal or state a precondition/pre-check step.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
jami_get_checkout_statusGet checkout statusARead-onlyIdempotent
Check a checkout session once. The server reconciles with the payment provider on every call, so this resolves even when webhooks are late.
Args:
session_id: from jami_create_checkout.
Returns: { session_id, status: 'open' | 'completed' | 'expired', order_id, order_status, amount_minor, amount, expires_at, failure }. When status is 'expired', failure.code explains why: payment_rejected · payment_failed · payment_canceled · payment_timed_out · initiate_failed · session_expired.
Use jami_wait_for_checkout instead if you want to block until the buyer finishes.
| Name | Required | Description | Default |
|---|---|---|---|
| session_id | Yes | Checkout session id returned by jami_create_checkout, e.g. "6710c2e8b1a2f0012ab34cd9" | |
| response_format | No | 'markdown' (default) for a readable summary, 'json' for the full structured payload | markdown |
Output Schema
| Name | Required | Description |
|---|---|---|
| amount | Yes | Human-readable amount, e.g. "150.00 ETB" |
| status | Yes | |
| failure | Yes | Why the session ended without an order; null unless status is "expired" |
| order_id | Yes | |
| expires_at | Yes | |
| session_id | Yes | |
| amount_minor | Yes | Integer santim (100 = 1.00 ETB) |
| order_status | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations (readOnlyHint/idempotentHint/openWorldHint) by disclosing server-side reconciliation on every call and enumerating the failure.code values that explain an expired session. It does duplicate the return-value enumeration that the output schema already carries, which caps this slightly below a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded purpose sentence, then clearly labeled Args/Returns blocks, then the alternative-tool line. Nearly every sentence earns its place; the only drag is the return-value enumeration repeating what the output schema provides.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only polling tool it covers semantics, error decoding, and the sibling choice. Since an output schema exists, the description is not required to describe return values, so the remaining 'gap' is minor rather than material.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the schema already documents both parameters, including that session_id comes from jami_create_checkout, so the Args line is largely redundant. response_format is not mentioned in the description at all. Baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Check a checkout session once') and immediately names the sibling it is not ('Use jami_wait_for_checkout instead if you want to block'). An agent can pick between the two checkout tools without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit routing rule with the selecting condition: poll with this tool, block with jami_wait_for_checkout. It also gives the operational reason to prefer it ('server reconciles with the payment provider on every call, so this resolves even when webhooks are late'), which is exactly the when-to-use context needed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
jami_get_productGet productARead-onlyIdempotent
Fetch one product by its p_… token or id: price, status, and its public page url.
| Name | Required | Description | Default |
|---|---|---|---|
| product_id | Yes | Product p_… token or id | |
| response_format | No | 'markdown' (default) for a readable summary, 'json' for the full structured payload | markdown |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | Yes | Public Jami page where anyone can buy it (published only) |
| price | Yes | |
| title | Yes | |
| token | Yes | Use as product_id in jami_create_checkout |
| status | Yes | |
| product_id | Yes | |
| amount_minor | Yes | |
| pricing_model | Yes | |
| minimum_amount_minor | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint, so the safety profile is covered. The description adds only the returned-field summary, which the output schema already carries; it discloses nothing extra about cache behavior, errors on unknown ids, or cross-workspace access.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single tight sentence that front-loads the action and resource and then names the output fields. There is no filler, hedging, or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present and rich annotations covering safety and idempotency, the description needn't explain return values, and it does briefly note what comes back. The only gap is the absence of routing guidance against the many sibling product/checkout tools, which is minor here.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and both parameters (product_id, response_format) are documented in the schema, so the baseline is 3. The description echoes the token/id form of product_id but adds no semantics, such as what happens if the id belongs to another workspace, beyond what the schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
'Fetch one product by its p_… token or id' names a specific verb (fetch), resource (product), and the lookup key, and it enumerates the salient returned fields (price, status, public page url). It clearly reads as a single-item retrieval, implicitly contrasting with jami_list_products, but no sibling is named explicitly, so it stops short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'by its p_… token or id' implies the caller must already hold a product identifier, which hints at usage after a list/search. However, there is no explicit when-to-use statement, no mention of alternatives such as jami_list_products for browsing, and no exclusions, so guidance is only implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
jami_get_withdrawalGet withdrawalARead-onlyIdempotent
Fetch one withdrawal by id to track it from pending → processing → completed (or rejected).
Args:
withdrawal_id: from jami_create_withdrawal or jami_list_withdrawals.
| Name | Required | Description | Default |
|---|---|---|---|
| withdrawal_id | Yes | ||
| response_format | No | 'markdown' (default) for a readable summary, 'json' for the full structured payload | markdown |
Output Schema
| Name | Required | Description |
|---|---|---|
| net | Yes | |
| note | No | |
| amount | Yes | |
| status | Yes | |
| account | Yes | |
| gateway | Yes | |
| fee_minor | Yes | |
| net_minor | Yes | Santim that reaches the destination |
| tax_minor | Yes | |
| created_at | Yes | |
| amount_minor | Yes | Gross santim debited |
| withdrawal_id | Yes | |
| idempotency_key | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, openWorldHint and destructiveHint=false, so the safety profile is covered structurally. The description adds genuine value by naming the state progression the caller should expect (pending → processing → completed/rejected), but says nothing about auth, polling cadence, or eventual-consistency behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose sentence first, then a compact Args block. Every line earns its place with no restated or decorative text.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be described, and the description covers purpose, lifecycle, and parameter sourcing. It stops short of the operational details (auth scope, behavior while the withdrawal is still pending) that would make it fully self-sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 50%, so the description must carry some weight for withdrawal_id, and it does by documenting provenance (which sibling tool produces the id). The response_format enum is already fully documented inside the schema, so nothing is lost there.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Starts with a specific verb+resource ('Fetch one withdrawal by id') and adds the lifecycle it exists to observe (pending → processing → completed/rejected). The scope word 'one' plus the required id clearly separates it from jami_list_withdrawals and it is distinct from jami_quote_withdrawal.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states the practical context (tracking a withdrawal's status) and tells the agent where the id comes from ('jami_create_withdrawal or jami_list_withdrawals'). It does not, however, say when to prefer this over jami_list_withdrawals or a wait/poll alternative, so no explicit exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
jami_list_ordersList ordersARead-onlyIdempotent
List the organization's orders, newest first, one page at a time.
Args:
status: 'paid' | 'pending' | 'failed' (optional filter).
page: 1-based page (default 1).
limit: 1–100 per page (default 20).
Returns: { orders: [{ order_id, status, amount_minor, amount, product: { id, title }, customer: { id, email, name }, paid_at, created_at, metadata }], total, page, limit, count, has_more, next_page }.
To total revenue or find a specific buyer, page through with next_page until has_more is false. Amounts are integer santim (100 = 1.00 ETB); this is what buyers paid, before any withdrawal fee.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | ||
| limit | No | ||
| status | No | ||
| response_format | No | 'markdown' (default) for a readable summary, 'json' for the full structured payload | markdown |
Output Schema
| Name | Required | Description |
|---|---|---|
| page | Yes | |
| count | Yes | Records in this page |
| limit | Yes | |
| total | Yes | Total matching records |
| orders | Yes | |
| has_more | Yes | |
| next_page | No | Pass as `page` to fetch the next page |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, so the safety profile is covered; the description adds genuinely new behavioral context: newest-first ordering, page-at-a-time retrieval with defaults, and the unit/semantics of amounts ('integer santim, 100 = 1.00 ETB ... before any withdrawal fee'). No rate limits or auth requirements are mentioned, keeping it out of 5 territory.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded purpose sentence followed by tightly formatted Args/Returns/Notes blocks; each line carries information. The Returns block restates a payload that an output schema already defines, which is mild redundancy, though the accompanying santim/fee note justifies its presence.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Beyond pagination mechanics, it supplies the amount unit convention and the 'before withdrawal fee' caveat, which cannot be inferred from the schema or output schema. Combined with the documented filters and paging contract, an agent has everything needed to call and interpret this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 25%, so the description carries the load and does so for three of four params: status filter values, page being 1-based with default 1, and limit range 1–100 with default 20. It silently omits response_format (markdown vs json), which is the one parameter the schema documents and which materially changes what the agent receives.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List the organization's orders') plus scope and ordering ('newest first, one page at a time'). It is clearly distinguishable from sibling list tools on other resources (withdrawals, products), but it never names a sibling or an alternative to route against, so it stops short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a concrete usage path: 'To total revenue or find a specific buyer, page through with next_page until has_more is false.' That tells the agent how to satisfy a goal, which is real guidance. It does not state when *not* to use this tool or name a preferred alternative, so no exclusions are covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
jami_list_productsList productsARead-onlyIdempotent
List the organization's products, newest first.
Args: status ('published' | 'draft' | 'archived', optional), page (default 1), limit 1–100 (default 20).
Returns: { products: [{ product_id, token, url, title, status, pricing_model, price }], total, page, limit, count, has_more, next_page }.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | ||
| limit | No | ||
| status | No | ||
| response_format | No | 'markdown' (default) for a readable summary, 'json' for the full structured payload | markdown |
Output Schema
| Name | Required | Description |
|---|---|---|
| page | Yes | |
| count | Yes | Records in this page |
| limit | Yes | |
| total | Yes | Total matching records |
| has_more | Yes | |
| products | Yes | |
| next_page | No | Pass as `page` to fetch the next page |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive). The description adds genuinely new behavioral context beyond them: the 'newest first' ordering and pagination behavior (has_more, next_page). It stops short of noting auth requirements or how an omitted status filter behaves.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the purpose, then a compact Args block and a Returns block with no filler. The Returns enumeration is somewhat redundant since an output schema exists, but it is short and does not bloat the definition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values are already covered, and the description adds the small amount of context an agent needs (ordering, defaults, filters) to invoke it correctly. It lacks only auth/permission notes and filter-combination semantics, which are minor for a read-only list tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 25%, so the description must compensate, and it documents status enum values, page default, and the limit range (1–100, default 20). The one param it omits, response_format, is the sole param already documented in the schema, so combined coverage is effectively complete.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource with scope and ordering: 'List the organization's products, newest first.' It is clearly distinguishable from jami_get_product and jami_create_product by the list/get/create verb, though no sibling is named explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the tool name and the status filter, but there is no explicit statement of when to use this versus jami_get_product or jami_list_orders, and no prerequisites or exclusions are given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
jami_list_withdrawalsList withdrawalsARead-onlyIdempotent
List the organization's withdrawals, newest first.
Args:
status: 'pending' | 'reviewing' | 'approved' | 'rejected' | 'processing' | 'completed' (optional).
page (default 1), limit 1–100 (default 20).
Returns: { withdrawals: [...], total, page, limit, count, has_more, next_page }.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | ||
| limit | No | ||
| status | No | ||
| response_format | No | 'markdown' (default) for a readable summary, 'json' for the full structured payload | markdown |
Output Schema
| Name | Required | Description |
|---|---|---|
| page | Yes | |
| count | Yes | Records in this page |
| limit | Yes | |
| total | Yes | Total matching records |
| has_more | Yes | |
| next_page | No | Pass as `page` to fetch the next page |
| withdrawals | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, so safety is covered. The description adds genuinely non-derivable behavior: result ordering (newest first) and that the result set is org-scoped and pageable with has_more/next_page. It stops short of auth requirements or rate-limit/consistency caveats.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core behavior, then a tidy Args block and a Returns line — well sized and easy to scan. The Returns line is largely redundant given a full output schema exists, which is the only wasted content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description does not need to explain the payload, yet it still restates the envelope; the more valuable coverage (ordering, filters, pagination limits) is there. What's missing — auth scope, what qualifies as a withdrawal record, and why response_format matters — is minor given the structured fields.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 25% (just response_format), so the description must carry the other three parameters — and it does enumerate status values, page default, and the 1–100 limit range. Much of that restates the schema's own enums/defaults, and response_format is never mentioned in the Args block, so it is not fully compensating.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb and resource ('List the organization's withdrawals') plus the ordering ('newest first'), so the agent knows exactly what comes back. It does not, however, contrast itself against the close sibling jami_get_withdrawal, leaving the singular-vs-list distinction to be inferred from names alone.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the optional status filter and pagination defaults — an agent can infer this is for browsing/filtering the org's withdrawal queue. There is no explicit statement of when to use this instead of jami_get_withdrawal or jami_quote_withdrawal, and no stated prerequisites or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
jami_quote_withdrawalQuote withdrawalARead-onlyIdempotent
Preview what reaches the destination for a withdrawal — offline, no API call, works without a token.
The JamiDev usage fee (7% unless Jami set a custom rate on the account) and any government tax are cut FROM the amount: you withdraw amount, the account receives net. Rounding is round-half-up per component. The server is authoritative; the real breakdown comes back on the withdrawal.
Args:
amount_minor: gross santim (min 10000 = 100.00 ETB).
fee_rate / tax_rate: optional overrides (0–1) if you know the account's real rates.
Returns the breakdown plus whether the amount auto-pays (≤ 10,000 ETB) or goes to manual review, and the per-org 100,000 ETB rolling-24h cap.
| Name | Required | Description | Default |
|---|---|---|---|
| fee_rate | No | ||
| tax_rate | No | ||
| amount_minor | Yes | Gross amount in integer santim — the fee is cut from this. 10000 = 100.00 ETB (the minimum). | |
| response_format | No | 'markdown' (default) for a readable summary, 'json' for the full structured payload | markdown |
Output Schema
| Name | Required | Description |
|---|---|---|
| fee_rate | Yes | |
| tax_rate | Yes | |
| fee_minor | Yes | |
| net_minor | Yes | |
| tax_minor | Yes | |
| auto_payout | Yes | true when ≤ 10,000 ETB — paid out without manual review |
| amount_minor | Yes | |
| meets_minimum | Yes | |
| within_daily_cap | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, so safety is carried structurally. The description adds non-obvious behavior: 7% default fee unless a custom rate is set, government tax cut from the gross, round-half-up per component, server is authoritative, and the 10,000 ETB auto-pay threshold and 100,000 ETB rolling-24h cap. This is real behavioral context beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the one-line purpose, then the fee/tax mechanics and the return summary, then args. Every sentence carries information; mildly dense but nothing extraneous.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values needn't be fully enumerated, and the description still summarizes what comes back (breakdown, auto-pay vs. manual, cap). With annotations covering safety, params and mechanics covered, and boundaries stated, an agent has everything needed to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 50%; the description documents amount_minor's meaning (gross santim, minimum 10000), that fee/tax are optional 0–1 overrides representing the account's real rates, and that the fee is cut FROM the gross so the account receives net. It does not describe response_format, leaving that to the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb+resource ('preview what reaches the destination for a withdrawal') and immediately distinguishes from the mutation siblings jami_get_withdrawal/jami_list_withdrawals by stating it's offline and needs no token. An agent can route to it or away from it without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use (preview, no API call, no token) and when not (the authoritative breakdown comes from the real withdrawal). Also fills the critical decision boundary: which amounts auto-pay vs. go to manual review.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
jami_read_docRead Jami doc pageARead-onlyIdempotent
Read one JamiDev docs page as markdown, with every code sample intact.
Args:
path: a docs path from jami_search_docs, e.g. "/docs/webhooks", "api/checkout", or a full URL. Use "/docs" for the overview.
offset: character offset for long pages (default 0); the result says where to continue.
Returns: { title, url, markdown, offset, next_offset? }.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| offset | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | Yes | |
| title | Yes | |
| offset | Yes | |
| markdown | Yes | |
| next_offset | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, openWorld and non-destructive, so the safety profile is covered. The description adds genuinely new behavior: output is markdown with code samples intact, and long pages are paginated via offset with the result indicating where to continue.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action, then cleanly separated Args and Returns blocks with no filler sentences. Every line either defines a parameter or the return shape.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, and the description still summarizes the return shape ({ title, url, markdown, offset, next_offset? }) and explains pagination, so an agent knows both how to call it and how to handle long pages. Nothing material is missing for a two-argument read tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must carry parameter meaning, and it does: it gives example path forms ("/docs/webhooks", "api/checkout", full URL), a special value for the overview, and explains offset as a continuation cursor with a default of 0 and a next_offset hint in the result.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("Read one JamiDev docs page as markdown") and adds the format detail that code samples are preserved. It implicitly separates itself from the sibling jami_search_docs by framing itself as reading a single page whose path comes from search.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It tells the agent where the path argument comes from (jami_search_docs) and gives a concrete fallback ("Use '/docs' for the overview"), which establishes the intended workflow. It stops short of explicit when-not guidance, but the context for selecting this tool versus search is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
jami_search_docsSearch Jami docsARead-onlyIdempotent
Search the official JamiDev developer docs (https://dev.jami.bio/docs) — the source of truth for integrating Jami payments. Works without an API token.
Use this before writing integration code: SDK usage, REST endpoints, webhooks and signature checks, sandbox magic numbers, Sign in with Jami (OAuth/OIDC), the wallet API, the browser storefront, fees and limits.
Args:
query: what you need, e.g. "verify webhook signature express", "pay what you want amount", "withdrawal fee".
limit: 1–10 results (default 5).
Returns: { results: [{ title, path, url, snippet }] }. Read a full page with jami_read_doc(path).
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| results | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, and open-world behavior, so the safety profile is covered. The description adds genuinely useful context beyond that: it works without an API token, and it discloses the return shape and the search-then-read workflow. It doesn't state ranking or pagination behavior, keeping it below a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded purpose sentence, then a scoping paragraph, then Args and Returns blocks. Every line carries information; nothing is padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, yet the description still sketches the result fields and points to jami_read_doc for full pages, covering the search-then-read loop end to end. Nothing an agent needs to invoke this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate, and it does: it gives concrete query examples ('verify webhook signature express', 'withdrawal fee') and restates the limit default and 1–10 range. It omits the query length constraints (2–200 chars) present in the schema, so not a full 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Search the official JamiDev developer docs') and scopes it as the source of truth for Jami payments. The topic list (SDK, REST, webhooks, OAuth, wallet API) makes it clearly distinct from siblings like jami_read_doc and jami_get_checkout_status.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Use this before writing integration code' states the when explicitly, and it names the follow-up alternative ('Read a full page with jami_read_doc(path)'), drawing the search-vs-read boundary. No inference required.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
jami_update_productUpdate productAIdempotent
Change a product's title, description, status or price amount. The pricing model itself is locked.
Args: product_id (p_… token or id), and any of: title, description, status ('published' | 'draft' | 'archived' — archived stops new sales), amount_minor (fixed price), minimum_amount_minor (flexible floor).
| Name | Required | Description | Default |
|---|---|---|---|
| title | No | ||
| status | No | ||
| product_id | Yes | Product p_… token or id | |
| description | No | ||
| amount_minor | No | ||
| response_format | No | 'markdown' (default) for a readable summary, 'json' for the full structured payload | markdown |
| minimum_amount_minor | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | Yes | Public Jami page where anyone can buy it (published only) |
| price | Yes | |
| title | Yes | |
| token | Yes | Use as product_id in jami_create_checkout |
| status | Yes | |
| product_id | Yes | |
| amount_minor | Yes | |
| pricing_model | Yes | |
| minimum_amount_minor | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover safety (readOnlyHint=false, idempotentHint=true, destructiveHint=false), but the description adds real behavioral context beyond them: pricing model is locked, 'archived' stops new sales, and updates are partial ('any of'). It is silent on auth requirements, error behavior, and what happens if both amount_minor and minimum_amount_minor are sent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the purpose, then a compact args list; every sentence is doing work. The terse 'Args:' pseudo-syntax is dense but readable, with only minor redundancy between the first sentence and the field list.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists (and response_format is documented in the schema), so return values need no explanation here. For a partial-update tool with annotations present, the description covers the fields and key constraints well; the main gap is how the two price parameters interact when supplied together.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With only 29% schema description coverage, the description carries most of the burden and largely succeeds: it explains product_id's token form, the status enum values with the semantic effect of 'archived', and — critically — that amount_minor is a fixed price while minimum_amount_minor is a flexible floor. It omits response_format and the length bounds, which the schema handles.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Change a product's title, description, status or price amount') and enumerates the mutable fields. It clearly is the mutation counterpart to jami_create_product and jami_get_product, but it never explicitly names or contrasts those siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by 'Change...' and 'any of' (partial update), but there is no explicit when-to-use/when-not-to-use guidance, no prerequisite or permission notes, and no pointer to alternatives such as create vs update. The 'pricing model itself is locked' line hints at a constraint but does not guide tool selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
jami_verify_webhookVerify webhookARead-onlyIdempotent
Check whether a webhook delivery is genuine — the same timing-safe HMAC check and replay guard the SDK runs. Use it to debug "signature mismatch" errors in a handler.
Args:
payload: the RAW request body exactly as received (not re-serialized JSON — whitespace matters).
signature: the X-JamiDev-Signature header, "t=,v1=".
secret: the subscription's webhook secret (defaults to JAMI_WEBHOOK_SECRET).
tolerance_seconds: max age of the timestamp (default 300). Raise it to check an old captured delivery.
Returns: { valid, reason, event_type, event_id, livemode }. An invalid signature is a normal result (valid: false), not an error.
| Name | Required | Description | Default |
|---|---|---|---|
| secret | No | ||
| payload | Yes | Raw request body | |
| signature | Yes | X-JamiDev-Signature header value | |
| tolerance_seconds | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| valid | Yes | |
| reason | Yes | |
| event_id | Yes | |
| livemode | Yes | |
| event_type | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover safety (readOnly/idempotent/non-destructive), and the description adds real behavioral context beyond them: it discloses the timing-safe HMAC + replay-guard semantics and, crucially, that 'an invalid signature is a normal result (valid: false), not an error' — a key invocation expectation an agent would otherwise get wrong.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded purpose sentence, then clearly labeled Args and Returns sections. No filler; each line (raw-body caveat, signature format, default source, invalid-is-normal) earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite the 50% schema coverage gap, the description documents all four parameters, the return shape, and the non-error semantics of a failed check. Nothing an agent needs to invoke or interpret this tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 50% (payload/signature documented; secret/tolerance_seconds not), but the Args block fully compensates: it explains payload must be the RAW body ('whitespace matters'), the exact signature format 't=<unix>,v1=<hex>', that secret defaults to JAMI_WEBHOOK_SECRET, and the tolerance rationale for old deliveries.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (check/verify) and resource (webhook delivery), and immediately qualifies what 'genuine' means — 'the same timing-safe HMAC check and replay guard the SDK runs'. An agent can tell this apart from sibling jami_create_test_webhook, which creates rather than verifies.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a concrete when-to-use scenario: 'Use it to debug "signature mismatch" errors in a handler.' That is clear context, but it names no alternatives or exclusions (e.g. when to generate a test webhook instead), so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
jami_wait_for_checkoutWait for checkoutARead-onlyIdempotent
Poll a checkout session until it's paid or ends, up to timeout_seconds. Reports progress while it waits.
If the buyer hasn't finished when the timeout hits, this returns status 'open' (not an error) — call it again to keep waiting. Sessions expire 30 minutes after creation.
Args:
session_id: from jami_create_checkout.
timeout_seconds: 5–300 (default 90).
interval_seconds: 2–30 between polls (default 3).
Returns the same shape as jami_get_checkout_status.
| Name | Required | Description | Default |
|---|---|---|---|
| session_id | Yes | Checkout session id returned by jami_create_checkout, e.g. "6710c2e8b1a2f0012ab34cd9" | |
| response_format | No | 'markdown' (default) for a readable summary, 'json' for the full structured payload | markdown |
| timeout_seconds | No | ||
| interval_seconds | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| amount | Yes | Human-readable amount, e.g. "150.00 ETB" |
| status | Yes | |
| failure | Yes | Why the session ended without an order; null unless status is "expired" |
| order_id | Yes | |
| expires_at | Yes | |
| session_id | Yes | |
| amount_minor | Yes | Integer santim (100 = 1.00 ETB) |
| order_status | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent and non-destructive, but the description adds genuinely new behavior: a timeout returns status 'open' rather than an error, progress is reported while waiting, and sessions expire after 30 minutes. These operational details go meaningfully beyond the annotation set.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core behavior, then edge case, then a structured Args block. The Args section partially duplicates the schema, but given the missing schema descriptions for two parameters it earns its place rather than being pure repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists and the description correctly defers to it by pointing at jami_get_checkout_status for the return shape. The timeout-as-status behavior, retry loop, and expiration window give an agent everything needed to drive it correctly; only the get-vs-wait tradeoff is left implicit.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With only 50% schema coverage, the description carries weight: it supplies the 5–300 range and default 90 for timeout_seconds and 2–30/default 3 for interval_seconds, which the schema declares only as min/max. It omits response_format, which the schema documents, so compensation is partial but effective for the two undocumented parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Poll a checkout session until it's paid or ends, up to timeout_seconds') with scope and stopping conditions front-loaded. It distinguishes itself from jami_get_checkout_status by framing itself as a persistent poller rather than a one-shot read, though it never says so explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear context: call it again after a timeout returns 'open', and notes sessions expire 30 minutes after creation. It stops short of an explicit when-not clause naming jami_get_checkout_status as the single-check alternative, so the routing guidance is contextual rather than exhaustive.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
16 tool updates
v0.2.0- First observed
jami_create_checkout - First observed
jami_create_product - First observed
jami_create_test_webhook - First observed
jami_get_balance - First observed
jami_get_checkout_status - First observed
jami_get_product - First observed
jami_get_withdrawal - First observed
jami_list_orders - First observed
jami_list_products - First observed
jami_list_withdrawals - First observed
jami_quote_withdrawal - First observed
jami_read_doc - First observed
jami_search_docs - First observed
jami_update_product - First observed
jami_verify_webhook - First observed
jami_wait_for_checkout
TDQS
Scored across 16 tools
Each tool targets a distinct resource+action, and the trio of checkout tools (create/get_status/wait) is explicitly differentiated in the descriptions ("use jami_wait_for_checkout instead if you want to block"). Product, order, withdrawal, webhook, and docs tools occupy clearly separate niches with no real overlap.
Every tool uses the jami_ prefix followed by a consistent verb_noun pattern (create_checkout, get_product, list_products, verify_webhook, read_doc). No mixed conventions or vague verbs anywhere in the set.
16 tools is well-scoped for a payments platform spanning checkout, products, orders, withdrawals, webhooks, and docs. Each tool earns its place; nothing is redundant padding.
The withdrawal lifecycle is notably incomplete: descriptions reference jami_create_withdrawal ("from jami_create_withdrawal or jami_list_withdrawals") but no such tool is exposed, so agents can quote/get/list withdrawals but never initiate one. Orders also lack a single-get or refund operation, though the core checkout and product CRUD flows are covered.
Maintenance
Related MCP Connectors
Directory of APIs, merchants, and tools AI agents can actually use.
Discover, inspect and run 63,000+ agent tools from one balance. Pay per call, no subscriptions.
Verified, pay-per-use API tools for AI agents through one authenticated connection.
70+ pay-per-call tools for AI agents: web search, email verify, KYC, stocks, crypto, news, data
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceEnables AI agents to interact with commercetools APIs to manage products, categories, orders, carts, and customer data. It provides a comprehensive set of tools for both read-only and full-access operations through secure authentication methods.4MIT
- AlicenseAqualityFmaintenanceEnables AI agents to create hosted checkouts, charge mobile wallets, query transactions, and process refunds via the JazzCash payment API.573MIT

Ultraner MCP Serverofficial
AlicenseNot gradedqualityBmaintenanceEnables AI agents to interact with the Ultraner API for creating payments, refunds, checkout sessions, managing escrow, and inspecting transactions across Africa.43 npmMIT- AlicenseNot gradedqualityBmaintenanceLets AI agents accept US payments (cards, Apple Pay, Google Pay) via Stripe hosted checkout. Includes tools to create payment links and query payment status.MIT