Skip to content

ATSS Standard

Afro Tools Spec Standard — the machine-readable format powering the registry.

GitHub
# specs/ — CLAUDE.md (ATSS Specification v1.0) ## What is ATSS ATSS (Afro.tools Spec Specification) defines the structure, required fields, and rules for every spec in this registry. A spec is a structured, machine-readable description of one API capability. It is not a wrapper. It is not an SDK. It is a declarative description. > **Terminology note:** In this repo, "spec" refers to an ATSS API description > (`schema.json` + `canonical_example.ts`). > This is distinct from Claude Code "skills" (SKILL.md files in `plugin/skills/`), > which are instruction files for AI agents. --- ## Folder structure ``` specs/{category}/{provider_slug}/ ├── provider.json ← provider-level metadata └── {capability}/ ├── schema.json ← capability spec └── canonical_example.ts ← working TypeScript example ``` **category** — `payment` or `sms` (extensible to other categories) **provider_slug** — lowercase, no spaces, no dashes (e.g. `paycard`, `wave`, `nimbasms`) **capability** — snake_case verb (e.g. `create_payment`, `verify_payment`, `send_otp`) Every capability folder must contain exactly these two files. Nothing else. --- ## provider.json — required fields One `provider.json` per provider directory. Carries provider-level metadata migrated from `schema.json`. ```json { "slug": "paycard", "name": "Paycard", "category": "payment", "country_code": ["GN"], "description": "Paycard is a Guinean mobile money payment gateway that lets you accept payments via MTN, Orange, and Cellcom mobile wallets.", "example_prompt": "Integrate Paycard to accept mobile money payments in Guinea. Create a payment, extract the operation_reference, and verify the transaction server-side before fulfilling the order." } ``` | Field | Type | Rule | |---|---|---| | slug | string | Lowercase, no spaces, no dashes — matches the directory name | | name | string | Display name of the provider | | category | string | `"payment"` or `"sms"` | | country_code | string[] | ISO 3166-1 alpha-2 codes — non-empty array | | description | string | One-sentence description of the provider for display and MCP context | | example_prompt | string | Full-flow usage prompt for AI agents — describes a complete integration scenario | --- ## schema.json — required fields ```json { "spec_version": "1.0", "provider_api_version": "2024-01-01", "capability": "create_payment", "capability_type": "synchronous", "status": "ready", "currency": ["GNF"], "sandbox": false, "docs_url": "https://paycard.com/docs/create-payment", "docs_public": false, "auth": { "type": "api_key", "location": "body", "field": "c", "format": "{token}", "env_var": "PAYCARD_API_KEY" }, "endpoint": { "method": "POST", "url": "https://mapaycard.com/epay/create/" }, "example_prompt": "Initiate a Paycard mobile money payment for a given amount in GNF, extract the operation_reference from the response, and store it immediately before redirecting the user.", "input_schema": {}, "response_schema": {}, "error_schema": {}, "gotchas": [ "Always verify payment status server-side before fulfilling an order." ] } ``` ### Field rules | Field | Type | Rule | |---|---|---| | spec_version | string | Always "1.0" | | provider_api_version | string | YYYY-MM-DD if provider has no version string | | capability | string | snake_case — matches the directory name | | capability_type | enum | `synchronous`, `asynchronous`, `webhook`, or `sdk` | | status | enum | `unverified`, `draft`, `ready`, `verified`, `deprecated`, `archived` | | currency | string[] | ISO 4217 codes | | sandbox | boolean | true if provider has a sandbox environment | | docs_url | string | Can be `""` — provider has no public docs URL | | docs_public | boolean | false if provider does not publish API docs publicly | | auth | object | Auth descriptor — see auth variants below | | endpoint | object | `{ method, url }` | | example_prompt | string | Required for `ready`/`verified` — describes this specific capability usage for AI agents | | input_schema | object | JSON Schema describing the request body | | response_schema | object | JSON Schema describing the success response | | error_schema | object | JSON Schema describing the error response | | gotchas | string[] | MANDATORY — minimum 1 entry, no exceptions | **Fields NOT in schema.json** (migrated to provider.json): `provider_slug`, `provider_name`, `category`, `country_code`. ### `evidence` — required only when `status` is `"unverified"` ```jsonc "evidence": { "source_url": "https://provider.com/docs/create-payment", "source_reference": "Section 'Create a payment'", "extracted_at": "2026-09-15T10:00:00Z", "snapshot_hash": "a1b2c3…", "spans": ["POST /v1/payments", "Authorization: Bearer {api_key}"] } ``` Every entry in `spans[]` must appear literally (whitespace/case-normalized) in the source document at `source_url`. This is what lets a reviewer verify an `unverified` spec wasn't hallucinated without re-reading the provider's docs from scratch. ### capability_type definitions - `synchronous` — request/response, result available immediately in the HTTP response - `asynchronous` — provider processes in background, poll a separate endpoint for result - `webhook` — provider sends an HTTP POST to your endpoint when an event occurs - `sdk` — capability delivered through a client-side SDK script (no direct HTTP endpoint). `endpoint.url` holds the CDN URL of the SDK script; `endpoint.method` is `null`. The `canonical_example.ts` exports a server-side configuration helper; the actual SDK invocation is shown in the usage comment block. Auth credential goes in `auth.location: "sdk_param"` (the SDK's config object). --- ## canonical_example.ts — rules ### Mandatory rules 1. TypeScript strict — must compile with `tsc --noEmit`, zero errors 2. Native fetch only — no axios, no node-fetch, no external HTTP libraries 3. All credentials via `process.env` — checked at the top, throw if missing 4. Explicit TypeScript interfaces for input, response, and error types 5. Export the main function 6. Include a usage example in a comment block at the bottom 7. JSDoc header: provider, capability, ATSS version, capability_type ### Template ```typescript /** * @provider Paycard * @capability create_payment * @atss 1.0 * @capability_type synchronous */ const PAYCARD_API_KEY = process.env.PAYCARD_API_KEY; if (!PAYCARD_API_KEY) throw new Error("Missing env: PAYCARD_API_KEY"); interface CreatePaymentInput { amount: number; currency: string; reference: string; callback_url: string; } interface CreatePaymentResponse { id: string; payment_url: string; status: string; } interface PaycardError { code: string; message: string; } export async function createPayment( input: CreatePaymentInput ): Promise<CreatePaymentResponse> { const response = await fetch("https://mapaycard.com/epay/create/", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ ...input, c: PAYCARD_API_KEY }), }); if (!response.ok) { const error: PaycardError = await response.json(); throw new Error(`Paycard error ${response.status}: ${error.message}`); } return response.json() as Promise<CreatePaymentResponse>; } /* Usage example: const payment = await createPayment({ amount: 100000, currency: "GNF", reference: "order_123", callback_url: "https://myapp.com/callback", }); // Store payment.operation_reference immediately // Always verify payment status server-side before fulfilling the order */ ``` ### What must never appear in canonical_example.ts - Any npm import (`axios`, `node-fetch`, etc.) — native fetch only - `require()` — ES modules only - Hardcoded API keys or secrets - `any` type without a comment explaining why --- ## Status lifecycle ``` unverified → draft → ready → verified → deprecated → archived ``` ### unverified — criteria - [ ] `schema.json` passes `npm run validate` (structure + evidence block) - [ ] `evidence` block present with `source_url`, `source_reference`, `extracted_at`, `snapshot_hash`, and at least one grounded `spans[]` entry - [ ] Generated automatically by the discovery pipeline (`core/tools/discovery`) — contributors do not hand-write `unverified` specs - [ ] Not yet human-reviewed for correctness beyond the automated gates — a maintainer reviewing the PR promotes it to `draft` (needs more work) or `ready` (looks correct) by editing `status` and removing or keeping `evidence` as documentation ### ready — criteria - [ ] `schema.json` passes `npm run validate` - [ ] `canonical_example.ts` compiles with `tsc --noEmit` - [ ] `gotchas[]` has at least 1 specific, actionable entry - [ ] `example_prompt` is non-empty - [ ] `provider.json` exists in the parent provider directory - [ ] `status` field set to `ready` A `ready` spec is visible in the MCP server. ### verified — criteria - [ ] All `ready` criteria met - [ ] **One of:** - Working example exists in `afrotools/examples`, **or** - The provider has a sandbox (`provider.json.sandbox: true`) and `npm run test:live -- --provider <slug>` passes (exit 0) against it — link the GitHub Actions run in the PR/commit as evidence - [ ] Maintainer has set status to `verified` `test:live` only ever targets a sandbox — it refuses to run against a provider with no sandbox (real production traffic, no automated safety net). Providers without a sandbox are verified through `afrotools/examples` only; see `CONTRIBUTING.md` § Live verification. A `verified` spec contributes to the provider's "AI Ready" badge. ### AI Ready badge rule A provider is AI Ready only when ALL its capabilities are `verified`. --- ## Gotchas — writing guide **Good:** ``` "Always verify payment status server-side before fulfilling an order. The callback URL alone is not sufficient — it can be forged." ``` **Bad:** ``` "Read the docs carefully." ``` Gotchas must be: specific, actionable, based on real integration experience. --- ## Provider index See the auto-generated table in [README.md](./README.md) — it is regenerated by CI (`scripts/generate-readme.js`) on every merge to `main` and is never out of sync. This file used to keep a second, hand-maintained copy of that table; it drifted from reality within weeks and is not worth re-introducing here.