afro.tools
io.github.afrotools/afrotoolsafrotoolsstreamable-httpv1.0.0Scanned
Open-source API specs for African providers (payments, SMS, KYC, delivery) for AI agents.
5 tools: 2 change things and 3 only read.
- Reads private data · 0
- Reads text others write · 1
- Can send data out · 0
- 3 findings
Anlyon alternative
2 of these tools change something. Run those as governed actions.
Declare what an action changes, and Anlyon puts it under a shared limit, binds every approval to the exact request, and grades the outcome. It works on any HTTPS API you can describe as an action.
Anlyon does not run, proxy or govern this MCP server. A tool your own code calls directly is not routed through Anlyon and is not governed by it.
Import an OpenAPI spec →Tools
Grouped by what each tool does, most consequential first. Open one for its reasons and full description; descriptions are the publisher's own words.
5 tools
Changes things 2Claude Code: ask
report_integrationBuilds a pre-filled GitHub link to report how an integration went against a spec — it worked, or the spec is wrong.No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
Description, as the server wrote it Builds a pre-filled GitHub link to report how an integration went against a spec — it worked, or the spec is wrong. Call it when the user confirms an integration works against the real API (sandbox or production), or when you find the spec does not match the API. Reports are how specs get verified and fixed. Nothing is posted: the user reviews the text and submits it on GitHub. One report per provider, covering every capability of the flow (e.g. payment init, status, webhook): each one is verified on its own. Args: - provider (string): Provider slug e.g. "paycard" - capabilities (array): Every capability the integration used, each with its own result e.g. [{ "capability": "create_payment", "result": "worked" }, { "capability": "webhook", "result": "wrong: status is SUCCESSFUL, spec says succeeded" }] - summary (string): One line about the flow, e.g. "checkout flow works in sandbox" - details (string): What was called, what came back, what differed from the spec. NEVER include API keys, tokens, phone numbers or personal data. - tested_on (string?): Date of the test, YYYY-MM-DD Returns: { url, next_step } — give the url to the user and follow next_step. If a spec does not exist: isError, with { error, available_capabilities } when the provider exists.
Annotations the server declares
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
request_specLogs a request for a spec that doesn't exist yet and notifies maintainers.Reads text others writeNo findings
Why it is in this group
- The name "request_spec" says "request": a word for a change.
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it Logs a request for a spec that doesn't exist yet and notifies maintainers. Call this when a user asks for a provider or capability that has no spec in the registry (check list_providers first). This helps maintainers prioritize which specs to write next. Args: - provider (string): Provider slug e.g. "wave" - capability (string): Capability name e.g. "create_payment" Returns: { logged: true, count } if the request was recorded — count is the all-time number of requests for this exact provider+capability, including this one, so you can tell the user e.g. "you're the Nth person to ask for this". count is absent if it could not be reliably determined — in that case do NOT guess a number to the user, just confirm the request was logged. { logged: false, reason } if the spec already exists. isError if the request could not be stored: tell the user it was NOT recorded.
Annotations the server declares
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: false
- openWorldHint: true
Only reads 3Show 3 read-only tools
get_specReturns the full spec payload for a provider + capability, including canonical_example.ts source code.2 findings
Why it is in this group
- The name "get_spec" says "get": a word for reading.
Findings
- Info
The description mentions "credentials".
What this check looks forMatched text
description: "...nted — ask the user, never guess. "auth.credentials" / "signing" / "token_exchange" / "appl..."
- Info
The description is 2,917 characters long, over the 2,000 this check looks for.
What this check looks forMatched text
description ends: "...h_specs or list_providers first to discover available providers and capabilities."
Description, as the server wrote it Returns the full spec payload for a provider + capability, including canonical_example.ts source code. Use this to get the complete integration guide — auth pattern, endpoint, schemas, gotchas, and a TypeScript example — before writing API calls. The response includes a "status" field: - "verified": tested against the provider's API, in "sandbox" or "production" (verified_in / verification.environment) - "deprecated": the provider is retiring it — "deprecation" gives the reason, replaced_by (the capability to use instead) and removed_after - anything else (e.g. "ready", "unverified"): written from the provider's documentation, NOT tested against the live API "verification" says how and when it was tested; sandbox proves the request and response shapes, not production behaviour. "open_questions", when present, lists what the provider's docs do not answer: tell the user before relying on the spec. "environments", when present, gives each documented environment's base URL; a missing one is undocumented — ask the user, never guess. "auth.credentials" / "signing" / "token_exchange" / "apply" and "webhook.signature", when present, describe the auth and webhook signature steps exactly: follow them. "parameters", when present, lists the path, query and header parameters; "input_schema" is the request body only. A path parameter fills the {name} placeholder of endpoint.url. "success_condition", when present, names the response field (dotted path) that says the call succeeded: a 2xx response with another value is a failure. If status is not "verified", always warn the user before generating integration code: "This spec has not been tested against the live API yet and may contain errors." Args: - provider (string): Provider slug e.g. "paycard" - capability (string): Capability name e.g. "create_payment" - variant (string[]?): Discriminator values to keep, e.g. ["mobile_money_ghs"] or ["bank", "NGN"]. In every union (oneOf) of input_schema and response_schema, only the branches pinned to one of these values are kept; a union none of them matches is left whole. Without it, all branches are returned. The response lists every value under "variants" (discriminator property → values). A large spec also carries "_mcp_size_note": if your client cut the result, call again with the variant you need. Returns: Full Spec object with canonical_example string (plus _mcp_warning when status is not "verified"). If not found: isError, with { error, available_capabilities } when the provider exists — capability names are each provider's own, pick one from that list — and did_you_mean (closest provider slugs or capability names) when one is close. A capability removed from the registry after a provider deprecation answers isError with removed_in, reason and alternatives. Use search_specs or list_providers first to discover available providers and capabilities.
Annotations the server declares
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
list_providersLists all providers and their verification status.No findings
Why it is in this group
- The name "list_providers" says "list": a word for reading.
Description, as the server wrote it Lists all providers and their verification status. Every listed provider is AI Ready: its specs give you a structured description to integrate it from. They can still contain errors — that is what each capability's "status" reports. all_verified is true only when ALL its capabilities have status "verified". Providers with any capability not yet "verified" have all_verified false — call search_specs or get_spec and check each capability's "status": one that is not "verified" has not been tested against the provider's API. Returns: { providers: Array<{ slug, name, category, channels?, all_verified, verified_count, capabilities, country_code, docs_public, docs_url }> }
Annotations the server declares
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
search_specsSearches specs by words and filters by category, channel, provider, country, currency, status or capability type.1 finding
Why it is in this group
- The name "search_specs" says "search": a word for reading.
Findings
- Info
The description is 2,665 characters long, over the 2,000 this check looks for.
What this check looks forMatched text
description ends: "...abilities whose status is not "verified"; warning is present only when it is > 0."
Description, as the server wrote it Searches specs by words and filters by category, channel, provider, country, currency, status or capability type. Returns the matching providers, each with its countries, currencies, sandbox flag, docs URL and the matching capabilities (name, type, status, example_prompt) — no endpoints, schemas, gotchas or canonical_example source. Use get_spec with the exact capability name to retrieve the full payload. A capability with "variants" has several request/response shapes (e.g. one per payment method or corridor): pass the ones you need to get_spec "variant" to receive only those. Each result includes a "status" field: - "verified": tested against the provider's API, in "sandbox" or "production" (verified_in / verification.environment) - "deprecated": the provider is retiring it — get_spec says what replaces it - anything else (e.g. "ready", "unverified"): written from the provider's documentation, NOT tested against the live API — may contain errors Always check the status field. If status is not "verified", inform the user that the spec is experimental and may contain errors. Args: - query (string?): Words, e.g. "wave", "mobile money senegal", "send sms", "kyc", "XOF". Every word must match somewhere: provider name or slug, capability, description, example_prompt, countries (code or English/French name), currencies, channels (a few synonyms: momo, otp, kyc, payout…). Providers the query names come first. - category (string?): Filter by category, e.g. "payment", "communications" (SMS, WhatsApp, USSD, voice and email providers — "sms" is accepted as a legacy alias), "identity" (KYC, document verification, AML), "logistics" (delivery and courier providers). The registry adds categories over time: list_providers shows every category that exists - channel ("sms"|"whatsapp"|"ussd"|"voice"|"email"?): Only providers that offer this channel - provider (string?): Provider slug e.g. "paycard" - country_code (string?): ISO 3166-1 alpha-2 e.g. "GN" - currency (string?): ISO 4217 e.g. "XOF" - status ("verified"|"ready"|"unverified"?): e.g. "verified" for specs tested against the provider's API - capability_type ("synchronous"|"asynchronous"|"webhook"|"sdk"?): Filter by capability type Returns: { providers: ProviderMatch[], note?: string, hint?: string, unverified_count: number, warning?: string } note is present when example_prompt was left out to keep a wide result readable. hint is present when nothing matched: widen the search before telling the user a provider is unavailable. unverified_count counts matching capabilities whose status is not "verified"; warning is present only when it is > 0.
Annotations the server declares
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
This is not a safety rating, and no finding is not a safety guarantee. The groups and findings come from fixed checks of the tool definitions the server returned on the date shown, not from its code or what it does when called. How the checks work.
Exfil surface
Which tools read private data, which read text someone else can write, and which can send data out. One of each is a path a prompt injection can use.
No private-data, untrusted-input, outbound path in this server alone: no tool is tagged private-data or outbound.
- Reads private data0
- Reads files, mail, messages, databases, secrets, calendars or repositories.
- Reads text others write1
- Brings in text someone else can write: web pages, inbound email, messages, issues and comments.
- Can send data out0
- Can carry data to people or systems: it sends, posts or publishes, or takes a recipient, channel or URL.
Other servers in the same agent add their own tools to these paths. Audit your whole setup to see them together.
Findings
Matches of fixed checks, with the text they matched.
- Infosearch_specs
The description is 2,665 characters long, over the 2,000 this check looks for.
What this check looks forMatched text
description ends: "...abilities whose status is not "verified"; warning is present only when it is > 0."
- Infoget_spec
The description mentions "credentials".
What this check looks forMatched text
description: "...nted — ask the user, never guess. "auth.credentials" / "signing" / "token_exchange" / "appl..."
- Infoget_spec
The description is 2,917 characters long, over the 2,000 this check looks for.
What this check looks forMatched text
description ends: "...h_specs or list_providers first to discover available providers and capabilities."
History
Changes to its tool definitions and to its remote endpoint, newest first.
No change seen yet. Its tools are rescanned every day, and a remote endpoint is looked at once a week.
Install
Pinned to version 1.0.0. Values in angle brackets are yours to fill in.
claude mcp add --transport http afrotools https://mcp.afro.tools/mcpclaude mcp add --transport http afrotools https://mcp.afro.tools/mcpRun in a terminal.
Claude Code permissions
Allow the reads, ask before a change or a way out, deny the deletes. Paste into .claude/settings.json.
{
"permissions": {
"allow": [
"mcp__afrotools__list_providers",
"mcp__afrotools__search_specs",
"mcp__afrotools__get_spec"
],
"ask": [
"mcp__afrotools__request_spec",
"mcp__afrotools__report_integration"
],
"deny": []
}
}Tools that only read are allowed, tools that change things ask first, tools that delete or cancel are denied. A read that can send data out (it takes a URL, say) asks first too. It assumes the server is installed as afrotools. Review it before you use it.
Capability tags behind 1 rule
- mcp__afrotools__request_spec untrusted-input
Pin
Keep the decision: fail CI when the tools change, follow every change, or show a badge.
Pin in CI
Fail a build when the tools you reviewed are not the tools the server serves today.
curl -s "https://anlyon.dev/api/v1/servers/io.github.afrotools/afrotools/verify?hash=081dc4307212ec5f1d102e7b4213d3b85b7fcf533dea3bff1a2a34f259f87644" | jq -e '.changed == false'Pinned hash 081dc4307212, from Oct 31, 2026, 19:18 UTC.
Watch
Get told when its tools change: a new tool, a new description, a new class.
https://anlyon.dev/servers/io.github.afrotools/afrotools/changes.xmlAn Atom feed. Works in any feed reader or Slack's RSS app.
Badge
[](https://anlyon.dev/servers/io.github.afrotools/afrotools)Source: MCP Registry · repository. Synced Oct 31, 2026, 20:17 UTC.