AMI.

AMI — documentación interactiva

AMI — interactive documentation

AMI es un protocolo abierto que permite a un agente AI obtener su propia identidad móvil — un número real con SMS y voz — de forma autónoma, programable y auditable.

AMI is an open protocol that lets an AI agent obtain its own mobile identity — a real number with SMS and voice — autonomously, programmatically, and auditably.

TL;DR

Tu agente llama tres tools MCP (o tres POST REST) y obtiene un número de teléfono real en menos de un segundo. Después puede enviar SMS y hacer llamadas usando un agent_token scoped a ese número. La voz se bridgea a tu propio motor Realtime — AMI es la pipa, tu agente es el cerebro.

Your agent calls three MCP tools (or three REST POSTs) and gets a real phone number in under a second. From there it can send SMS and place calls using an agent_token scoped to that number. Voice gets SIP-bridged to your own real-time engine — AMI is the pipe, your agent is the brain.

Mapa del documento

Document map

Otros recursos

Other resources

  • /specspec técnica completafull technical spec
  • /openapi.json — OpenAPI 3.1
  • /diagramanimación del ciclo de vidalifecycle animation
  • /llms.txtíndice para LLMsindex for LLMs
  • /partnerspara operadores telcofor telco operators

Quick start

Obtén un número de teléfono real y envía tu primer SMS con cinco líneas de código. Los SDKs oficiales hacen todo el flujo de contratación en una sola llamada.

Get a real phone number and send your first SMS in five lines of code. The official SDKs handle the entire contracting flow in a single call.

1. Instala el SDK

1. Install the SDK

pip install ami-protocol
npm install @ami-protocol/sdk
# no install needed

2. Provisiona un número + envía un SMS

2. Provision a number + send an SMS

from ami import AmiClient

client = AmiClient(api_key="amik_live_...",
                   base_url="https://api.protocolami.com")
creds = client.provision_number(country="ES", customer={
    "legal_name": "Acme S.L.", "tax_id": "B12345678",
    "billing_email": "billing@acme.test",
    "address": "Madrid, Spain",
    "representative_name": "Ada Lovelace",
})

agent = client.as_agent(creds.agent_token)
agent.send_sms(to="+34600...", body="Hello from my agent")
print(f"Number: {creds.phone_number}")
print(f"Token (save it!): {creds.agent_token[:20]}...")
import { AmiClient } from "@ami-protocol/sdk";

const client = new AmiClient({
  apiKey: process.env.AMI_API_KEY!,
  baseUrl: "https://api.protocolami.com",
});

const creds = await client.provisionNumber({
  country: "ES",
  customer: {
    legalName: "Acme S.L.", taxId: "B12345678",
    billingEmail: "billing@acme.test",
    address: "Madrid, Spain",
    representativeName: "Ada Lovelace",
  },
});

const agent = client.asAgent(creds.agentToken);
await agent.sendSms({ to: "+34600...", body: "Hello from my agent" });
# 1) request + offer
curl -X POST https://api.protocolami.com/v1/sim-requests \
  -H "Authorization: Bearer $AMI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"country":"ES"}'

# 2-5) accept offer / customer-data / contract / mock-sign
# 6) activate → returns agent_token ONCE
curl -X POST https://api.protocolami.com/v1/mobile-identities/activate \
  -H "Authorization: Bearer $AMI_API_KEY" \
  -d '{"contract_id":"contract_..."}'

# 7) send SMS using the agent_token
curl -X POST https://api.protocolami.com/v1/agent/sms/send \
  -H "Authorization: Bearer $AGENT_TOKEN" \
  -d '{"to":"+34600...","body":"Hello"}'

3. Pruébalo ahora

3. Try it now

El endpoint POST /v1/demo/quick es público (sin auth) y ejecuta el flujo entero contra el backend mock. Útil para ver el shape de las respuestas sin necesidad de API key.

The POST /v1/demo/quick endpoint is public (no auth) and runs the full flow against the mock backend. Useful to see the shape of responses without an API key.

POST /v1/demo/quick

Conceptos clave

Key concepts

MobileIdentity (MID)

Una MobileIdentity es la unidad central del protocolo: un número de teléfono activo con un conjunto de capacidades (sms, voice) asignado a un agente concreto bajo un contrato firmado con un customer. Su id tiene formato mid_<hex>.

A MobileIdentity is the protocol's central unit: an active phone number with a set of capabilities (sms, voice) assigned to a specific agent under a signed contract. Its id has format mid_<hex>.

agent_token vs API key

Hay dos niveles de auth: la API key del customer cubre la contratación y administración (provisión, límites, webhooks, rotación); el agent_token está scoped a una MID concreta y cubre la operación diaria (enviar SMS, hacer llamadas). Si el agent_token se filtra, el blast radius es esa MID y nada más.

There are two auth levels: the customer's API key covers contracting and admin (provisioning, limits, webhooks, rotation); the agent_token is scoped to one specific MID and covers daily operation (sending SMS, placing calls). If the agent_token leaks, the blast radius is that one MID and nothing else.

Bridge-by-API · voz

Bridge-by-API · voice

AMI es el operador / SIP provider, no ejecuta voz Realtime. Cuando tu agente origina una llamada, AMI marca al PSTN y bridgea la llamada por SIP al callback_sip_uri que tu agente proporciona (típicamente el endpoint SIP de tu motor de voz en tiempo real). El audio en sí pasa por la pipa de AMI; el "cerebro" del agente vive en tu endpoint.

AMI is the operator / SIP provider, it does not run real-time voice. When your agent places a call, AMI dials the PSTN and SIP-bridges the call to the callback_sip_uri your agent provides (typically your real-time voice engine's SIP endpoint). Audio flows through AMI's pipe; the agent "brain" lives at your endpoint.

Ver la animación →See the animation →

Multi-tenancy

Multi-tenancy

Cada empresa cliente es un customer_account con su propia API key. Cada recurso (sim_request, contract, MID, customer legal) lleva account_id, y AMI filtra cualquier acceso para que un customer NO pueda ver ni mutar recursos de otro. Los endpoints /v1/admin/* (gestión de customers) requieren un master key separado.

Each client company is a customer_account with its own API key. Every resource (sim_request, contract, MID, legal customer) carries account_id, and AMI filters all access so one customer cannot see or mutate another's resources. /v1/admin/* endpoints (customer management) require a separate master key.

Todo real menos el partner telco

All real except the telco partner

Contratos, firma, estados, audit, webhooks, rate-limits — todo el plano funcional es real y persiste en SQLite. La única pieza "mockeable" es el adaptador hacia el SMSC (Kannel) y el PBX (Asterisk): por defecto en modo mock, y conmutable a live via AMI_TELCO_MODE cuando el partner telco aporte credenciales SMPP y trunk SIP.

Contracts, signing, state machine, audit log, webhooks, rate-limits — the entire functional plane is real and persists to SQLite. The only "mockable" piece is the adapter towards the SMSC (Kannel) and the PBX (Asterisk): mock by default, switchable to live via AMI_TELCO_MODE once the telco partner supplies SMPP credentials and a SIP trunk.

Autenticación

Authentication

NivelLevel Header FormatoFormat CubreCovers
1 — customer Authorization: Bearer ... amik_live_<48hex> Contratación + admin del MID Contracting + MID admin
2 — agent Authorization: Bearer ... amiagt_live_<64hex> SMS y voz scoped a UN MID SMS and voice scoped to ONE MID
admin Authorization: Bearer ... AMI_ADMIN_KEY (env) CRUD de customer-accounts CRUD of customer-accounts
telco X-Telco-Key AMI_TELCO_INBOUND_KEY (env) Webhooks del partner (/v1/_telco/*) Partner webhooks (/v1/_telco/*)

Cómo se obtiene cada uno

How to get each one

  • API key del customercreada por el admin concreated by the admin with POST /v1/admin/customers. Devuelta una sola vez en plano.Returned in plaintext once.
  • agent_tokendevuelto al activar la MID conreturned when activating the MID with POST /v1/mobile-identities/activate. Una sola vez.One time only.
  • Admin master keyse setea en la variable de entornoset in the environment variable AMI_ADMIN_KEY. Nunca se devuelve por la API.Never returned by the API.
  • Telco inbound keyenvenv AMI_TELCO_INBOUND_KEY, compartida con Kannel/Asterisk en la VPS del partner.shared with Kannel/Asterisk on the partner VPS.

Rotación

Rotation

Si sospechas de filtración de un agent_token, hard-rota con:

If you suspect an agent_token leak, hard-rotate with:

curl -X POST https://api.protocolami.com/v1/mobile-identities/$MID/rotate-token \
  -H "Authorization: Bearer $AMI_API_KEY"
client.rotate_agent_token(mid)
await client.rotateAgentToken(mid);

El token anterior queda invalidado al instante. La respuesta trae el nuevo agent_token en plano (única vez).

The previous token is invalidated instantly. The response returns the new agent_token in plaintext (one time only).

Flujo de contratación

Contracting flow

Seis pasos: request → offer → customer-data → contract → sign → activate. Cada paso devuelve el estado de la SIMRequest que actúa como máquina de estados (ver §17.6 del spec).

Six steps: request → offer → customer-data → contract → sign → activate. Each step returns the SIMRequest state which acts as the state machine (see §17.6 of the spec).

1. SIMRequest + Offer

curl -X POST https://api.protocolami.com/v1/sim-requests \
  -H "Authorization: Bearer $AMI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"country":"ES","sim_type":"eSIM","capabilities":["sms","voice"]}'
sim = client.request_number(country="ES",
                              capabilities=["sms","voice"],
                              agent_name="agent01")
offer_id = sim.id  # OfferAccepted.id
const { simRequest, offer } = await client.requestNumber({
  country: "ES", capabilities: ["sms","voice"], agentName: "agent01",
});

2. Accept offer

curl -X POST https://api.protocolami.com/v1/offers/$OFFER_ID/accept \
  -H "Authorization: Bearer $AMI_API_KEY"
client.accept_offer(offer.id)
await client.acceptOffer(offer.id);

3. Customer data

curl -X POST https://api.protocolami.com/v1/sim-requests/$SIM_ID/customer-data \
  -H "Authorization: Bearer $AMI_API_KEY" \
  -d '{"customer":{"legal_name":"Acme S.L.","tax_id":"B12345678","billing_email":"billing@acme.test","address":"Madrid, Spain","representative_name":"Ada Lovelace"}}'
customer = client.submit_customer_data(
    sim_request_id=sim.sim_request_id,
    legal_name="Acme S.L.", tax_id="B12345678",
    billing_email="billing@acme.test",
    address="Madrid, Spain",
    representative_name="Ada Lovelace",
)

4. Contract → 5. Sign → 6. Activate

POST /v1/contracts crea el contrato y devuelve un signature_url con el signing_token de 128 bits. El firmante humano abre esa URL y hace clic; si automatizas el flujo, POST /v1/contracts/{id}/mock-sign es el atajo programático. Después, POST /v1/mobile-identities/activate devuelve la MID activa con el agent_token en plano.

POST /v1/contracts creates the contract and returns a signature_url with the 128-bit signing_token. A human signer opens that URL and clicks; if you automate the flow, POST /v1/contracts/{id}/mock-sign is the programmatic shortcut. Then POST /v1/mobile-identities/activate returns the active MID with the agent_token in plaintext.

contract = client.create_contract(offer_id=offer.id, customer_id=customer.id)
client.mock_sign(contract.id)  # o abrir contract.signature_url en navegador
identity = client.activate_identity(contract.id)
# identity.agent_token disponible AQUÍ — una sola vez
print(identity.phone_number, identity.agent_token)

Atajo todo-en-uno

One-shot helper

Los SDKs exponen provision_number() que hace los 6 pasos en una sola llamada y devuelve {mid, phone, agent_token}.

The SDKs expose provision_number() which runs all 6 steps in a single call and returns {mid, phone, agent_token}.

SMS

SMS

Enviar SMS saliente

Send outbound SMS

Auth: agent_token. El SMS sale en estado queued; el DLR del SMSC (o el simulador mock en dev) lo lleva a sent y luego delivered.

Auth: agent_token. SMS goes out in queued; the SMSC's DLR (or the mock simulator in dev) takes it through sent and then delivered.

agent.send_sms(to="+34611000000", body="Hello")
await agent.sendSms({ to: "+34611000000", body: "Hello" });
curl -X POST https://api.protocolami.com/v1/agent/sms/send \
  -H "Authorization: Bearer $AGENT_TOKEN" \
  -d '{"to":"+34611000000","body":"Hello"}'
ami.send_sms(to="+34611000000", body="Hello")

Listar SMS

List SMS

msgs = agent.list_sms(limit=20, direction="outbound")
for m in msgs:
    print(m.id, m.status, m.body)
curl "https://api.protocolami.com/v1/agent/sms?limit=20&direction=outbound" \
  -H "Authorization: Bearer $AGENT_TOKEN"

SMS entrante

Inbound SMS

Llega al backend vía el webhook del SMSC en POST /v1/_telco/sms/inbound. Se asocia automáticamente al MID correspondiente al número receptor. El agente lo ve en list_sms(direction="inbound") o (mejor) recibe un webhook saliente sms.inbound en su URL registrada.

Arrives at the backend via the SMSC webhook at POST /v1/_telco/sms/inbound. Auto-associates to the MID matching the destination number. The agent sees it in list_sms(direction="inbound") or (better) receives an outbound sms.inbound webhook at its registered URL.

Estados

Statuses

queuedaceptado, esperando saliraccepted, awaiting send
sentcursado al SMSC, en caminosent to SMSC, in flight
deliveredDLR final positivofinal positive DLR
failedDLR de fallo — retry automático hasta 3 vecesfailure DLR — auto-retried up to 3 times
receivedMO entranteinbound MO

Voz · bridge-by-API

Voice · bridge-by-API

Recordatorio: AMI NO ejecuta voz Realtime. AMI es la pipa SIP/RTP. El cerebro de la conversación vive en tu callback_sip_uri.
Reminder: AMI does NOT run real-time voice. AMI is the SIP/RTP pipe. The conversation brain lives at your callback_sip_uri.

Originar una llamada saliente

Place an outbound call

call = agent.place_call(
    to="+34600999888",
    callback_sip_uri="sip:proj@sip.api.example;transport=tls",
)
print(call.id, call.status)  # initiated
const call = await agent.placeCall({
  to: "+34600999888",
  callbackSipUri: "sip:proj@sip.api.example;transport=tls",
});
curl -X POST https://api.protocolami.com/v1/agent/calls/place \
  -H "Authorization: Bearer $AGENT_TOKEN" \
  -d '{"to":"+34600999888","callback_sip_uri":"sip:proj@sip.api.example;transport=tls"}'

Colgar una llamada

Hang up a call

agent.hangup_call(call.id)
await agent.hangupCall(call.id);
curl -X POST https://api.protocolami.com/v1/agent/calls/$CALL_ID/hangup \
  -H "Authorization: Bearer $AGENT_TOKEN"

Llamadas entrantes

Inbound calls

Configura un inbound_sip_uri por MID. Cuando entra una llamada al número, el PBX consulta a AMI a dónde reenviarla y la bridgea por SIP a tu URI configurada. Sin URI configurado, la llamada se rechaza limpiamente con 486 Busy Here.

Configure an inbound_sip_uri per MID. When a call comes in to the number, the PBX asks AMI where to forward and bridges it via SIP to your configured URI. Without a configured URI, the call is cleanly rejected with 486 Busy Here.

client.set_inbound_sip_uri(mid,
    "sip:agent@your-pbx.example;transport=tls")
curl -X POST https://api.protocolami.com/v1/mobile-identities/$MID/inbound-config \
  -H "Authorization: Bearer $AMI_API_KEY" \
  -d '{"inbound_sip_uri":"sip:agent@your-pbx.example;transport=tls"}'

Lifecycle de una llamada

Call lifecycle

initiated → ringing → in_progress → completedcamino felizhappy path
failederror técnico (retry automático si pre-answer)technical error (auto-retry if pre-answer)
no_answertimeout sin contestar (retry auto)timeout no answer (auto-retry)
busylínea ocupada (NO se reintenta)line busy (NOT retried)
cancelledhangup explícito antes de answerexplicit hangup before answer

Webhooks

AMI te hace POST a una URL tuya cuando ocurre un evento del MID. Firmamos con HMAC-SHA256 sobre timestamp.body para que puedas verificar autenticidad y rechazar replays.

AMI POSTs to a URL of yours when an event happens for a MID. We sign with HMAC-SHA256 over timestamp.body so you can verify authenticity and reject replays.

Registrar un webhook

Register a webhook

wh = client.create_webhook(mid,
    url="https://your-app.example/ami/hook",
    events=["sms.inbound","call.completed"])
# wh.secret está aquí UNA SOLA VEZ — guárdalo
print(wh.secret)
curl -X POST https://api.protocolami.com/v1/mobile-identities/$MID/webhooks \
  -H "Authorization: Bearer $AMI_API_KEY" \
  -d '{"url":"https://your-app.example/ami/hook","events":["sms.inbound","call.completed"]}'

Eventos disponibles

Available events

sms.inboundMO recibido en el MIDMO received at the MID
sms.deliveredDLR positivo de MT enviadopositive DLR for sent MT
sms.failedDLR de fallofailure DLR
call.inboundllamada entrante (antes de answer)inbound call (before answer)
call.completedllamada terminada con duracióncall ended with duration
call.failedllamada caída (failed/no_answer/busy/cancelled)call dropped (failed/no_answer/busy/cancelled)
*wildcard — todoswildcard — all

Verificar la firma en tu handler

Verify the signature in your handler

from ami.webhooks import verify_signature

def my_handler(request):
    body = request.body
    sig = request.headers["X-Ami-Signature"]
    ts  = request.headers["X-Ami-Timestamp"]
    if not verify_signature(secret="whsec_...",
                            body=body,
                            signature_header=sig,
                            timestamp_header=ts):
        return 401
    payload = json.loads(body)
    # payload = {"event": "sms.inbound", "mid": "mid_...", "data": {...}, "delivered_at": "..."}
    ...
import { verifySignature } from "@ami-protocol/sdk/webhooks";

export async function handler(req) {
  const body = await readRawBody(req);
  const sig  = req.headers["x-ami-signature"];
  const ts   = req.headers["x-ami-timestamp"];
  const ok = verifySignature({
    secret: process.env.AMI_WEBHOOK_SECRET,
    body, signatureHeader: sig, timestampHeader: ts,
  });
  if (!ok) return new Response(null, { status: 401 });
  const payload = JSON.parse(body);
  ...
}
# pseudocode — equivalente en cualquier lenguaje
ts = headers["X-Ami-Timestamp"]
sig_header = headers["X-Ami-Signature"]   # "sha256=<hex>"
if abs(now() - int(ts)) > 300: reject("stale")
expected = "sha256=" + hmac_sha256(secret, ts + "." + raw_body).hex()
if not constant_time_eq(expected, sig_header): reject("bad sig")

Política de reintentos

Retry policy

AMI reintenta hasta 4 veces con backoff [0.5s, 2s, 8s]. Tras 10 fallos consecutivos el webhook se auto-deshabilita (status disabled). Defensa contra SSRF: validamos la URL antes de cada delivery (no solo al registrar) y rechazamos redirects 3xx automáticos.

AMI retries up to 4 times with backoff [0.5s, 2s, 8s]. After 10 consecutive failures the webhook auto-disables (status disabled). SSRF defense: we validate the URL before each delivery (not only at register time) and reject automatic 3xx redirects.

Rate limits y spending

Rate limits and spending

Cada MID tiene topes configurables: SMS/hora, SMS/día, llamadas/hora, llamadas/día, budget mensual en EUR, y allowlist de prefijos de país. El backend hace enforcement antes de cursar al telco — si bloquea, devuelve 429 con la razón concreta.

Every MID has configurable caps: SMS/hour, SMS/day, calls/hour, calls/day, monthly EUR budget, and country-prefix allowlist. Backend enforces before cursing to telco — if blocked, returns 429 with the specific reason.

Defaults al activar

Defaults at activation

  • sms_per_hour: 60 · sms_per_day: 500
  • calls_per_hour: 20 · calls_per_day: 200
  • monthly_budget_eur: 100.00
  • allowed_country_prefixes: ["+34"] (España)(Spain)

Cambiar los límites

Change the limits

client.update_limits(mid,
    sms_per_day=1000,
    monthly_budget_eur=50,
    allowed_country_prefixes=["+34","+33","+1"])
curl -X POST https://api.protocolami.com/v1/mobile-identities/$MID/limits \
  -H "Authorization: Bearer $AMI_API_KEY" \
  -d '{"sms_per_day":1000,"monthly_budget_eur":50}'

Ver uso en tiempo real

Real-time usage

u = agent.usage()
print(f"SMS today: {u.sms_count_today} / {u.sms_per_day}")
print(f"Spend: €{u.spend_this_month_eur} / €{u.monthly_budget_eur}")
curl https://api.protocolami.com/v1/agent/usage \
  -H "Authorization: Bearer $AGENT_TOKEN"

Razones de bloqueo (429)

Block reasons (429)

  • country_not_allowed
  • sms_hourly_limit_exceeded · sms_daily_limit_exceeded
  • calls_hourly_limit_exceeded · calls_daily_limit_exceeded
  • monthly_budget_exceeded

Admin · multi-tenancy

Los endpoints /v1/admin/* gestionan customers (cuentas con su propia API key). Auth: master key AMI_ADMIN_KEY (env), separada de la API key del customer.

/v1/admin/* endpoints manage customers (accounts with their own API key). Auth: master key AMI_ADMIN_KEY (env), separate from any customer's API key.

Crear un customer-account

Create a customer-account

curl -X POST https://api.protocolami.com/v1/admin/customers \
  -H "Authorization: Bearer $AMI_ADMIN_KEY" \
  -d '{"name":"Acme Robotics","billing_email":"billing@acme.test"}'
# devuelve api_key UNA SOLA VEZ

Listar / rotar / suspender

List / rotate / suspend

# listar
curl https://api.protocolami.com/v1/admin/customers \
  -H "Authorization: Bearer $AMI_ADMIN_KEY"

# rotar API key (hard rotate)
curl -X POST https://api.protocolami.com/v1/admin/customers/$ID/rotate-key \
  -H "Authorization: Bearer $AMI_ADMIN_KEY"

# suspender / reactivar
curl -X POST https://api.protocolami.com/v1/admin/customers/$ID/suspend \
  -H "Authorization: Bearer $AMI_ADMIN_KEY" \
  -d '{"reason":"non_payment"}'
curl -X POST https://api.protocolami.com/v1/admin/customers/$ID/activate \
  -H "Authorization: Bearer $AMI_ADMIN_KEY"

Aislamiento entre customers

Isolation between customers

Cada recurso (sim_request, contract, MID, customer legal) lleva account_id desde su creación. El backend filtra todo acceso por este campo — un customer A no puede ver, mutar ni operar ningún recurso de B. El intento devuelve 404 (no 403) para no leakear la existencia del id.

Every resource (sim_request, contract, MID, legal customer) carries account_id from creation. The backend filters all access by this field — customer A cannot see, mutate or operate any resource of B. The attempt returns 404 (not 403) to avoid leaking the id's existence.

Códigos de error

Error codes

HTTPerror SignificadoMeaning
400invalid_*campo malformadomalformed field
400missing_fieldsfaltan campos requeridosmissing required fields
401unauthorizedAPI key inválida o faltanteinvalid or missing API key
401invalid_agent_tokenagent_token inválidoinvalid agent_token
401unauthorized_adminadmin master key inválidainvalid admin master key
404*_not_foundrecurso no existe o pertenece a otro accountresource not found or owned by another account
409invalid_state / *_not_activetransición no permitida o recurso suspendedtransition not allowed or suspended resource
409webhook_limit_reached10 webhooks por MID max10 webhooks per MID max
429sms_hourly_limit_exceededSMS/hora superadoSMS/hour exceeded
429monthly_budget_exceededpresupuesto mensual agotadomonthly budget depleted
429country_not_allowedprefijo de país no en la allowlistcountry prefix not in allowlist
503telco_inbound_disabledAMI_TELCO_INBOUND_KEY no configuradaAMI_TELCO_INBOUND_KEY not set

Reintentos

Retries

Los SDKs reintentan GET en 5xx con backoff exponencial. POST NO se reintenta automáticamente — duplicar un SMS o un contrato sobre un blip es peor que devolver el error.

The SDKs retry GETs on 5xx with exponential backoff. POSTs are NOT auto-retried — duplicating an SMS or a contract on a blip is worse than surfacing the error.

SDKs

SDKPackageRepoStatus
Python ≥ 3.9 ami-protocol sdk/python 0.1.0
TypeScript / Node ≥ 18 @ami-protocol/sdk sdk/typescript 0.1.0
MCP server ami_mcp.py ami_mcp.py 23 tools

Conectar tu cliente MCP

Connect your MCP client

Apunta tu cliente MCP (streamable-http) a:

Point your MCP client (streamable-http) to:

https://mcp.protocolami.com/mcp/

REST direct

Para clientes no-MCP, la API REST tiene 47 endpoints documentados en /openapi.json (OpenAPI 3.1) y /spec (markdown/HTML con ejemplos).

For non-MCP clients, the REST API has 47 endpoints documented at /openapi.json (OpenAPI 3.1) and /spec (markdown/HTML with examples).