Two-Factor Authentication

mcp2p embeds two-factor authentication directly into the AI conversation. Every payment operation that moves funds requires a one-time password (OTP) delivered via SMS through Twilio Verify. The AI assistant handles the challenge-response flow automatically — no separate authentication screen or redirect is needed.

This design is called conversational 2FA. The MCP tool itself acts as the challenge gate: calling it without a verification code starts the SMS flow; calling it with the code completes the authorization.

How conversational 2FA works

The flow follows a two-turn pattern within the same conversation thread:

1

User requests a payment

The user tells the AI assistant to make a payment. For example: "Send 500 MXN to CLABE 014027000005555558". The AI identifies the correct MCP tool and calls it.

2

SDK triggers verification

The AI calls spei_send_payment (or the equivalent rail tool) without a verificationCode. The SDK detects the missing code, calls Twilio Verify's /start-verification endpoint, and returns { "status": "2fa_required" } to the AI.

3

AI prompts the user

The AI reads the 2fa_required status and asks the user for their verification code: "I've sent you an SMS with a 6-digit code. Please share it to authorize the payment."

4

User provides the code

The user replies with the code: "The code is 847291". The AI extracts the code and calls the tool again with the same parameters plus verificationCode: "847291".

5

SDK verifies and executes

The SDK calls Twilio Verify's /check endpoint. If the code is valid, the SDK proceeds to execute the payment via the bank connector and returns the transaction result. If the code is invalid, it returns an error and the user can try again.

Flow diagram

User            AI Client         mcp2p SDK         Twilio Verify   Bank Connector
 |                  |                  |                   |                |
 |-- "Send 500 MXN" -->               |                   |                |
 |                  |-- tool_call() -->|                   |                |
 |                  |   (no OTP)       |-- startVerify() ->|                |
 |                  |                  |                   |-- SMS -------> User
 |                  |<- 2fa_required --|                   |                |
 |<- "Enter code" --|                  |                   |                |
 |-- "847291" ------>                  |                   |                |
 |                  |-- tool_call() -->|                   |                |
 |                  |   (OTP: 847291)  |-- checkVerify() ->|                |
 |                  |                  |<- valid --------- |                |
 |                  |                  |-- executePayment() --------------->|
 |                  |                  |<- { success, txId } --------------|
 |                  |<- { success } ---|                   |                |
 |<- "Done! txId: ..|                  |                   |                |

Twilio Verify setup

mcp2p uses Twilio Verify for OTP delivery. Follow these steps to configure it:

  1. Create a Twilio account if you do not already have one.
  2. In the Twilio Console, go to Verify → Services and create a new Verify service. Note the Service SID (starts with VA).
  3. Copy your Account SID (starts with AC) and Auth Token from the Twilio Console home page.
  4. Add these three values to your environment variables (see below).
  5. Pass them to createMcp2pServer in the twoFactor config block.

Configuration options

createMcp2pServer({
  twoFactor: {
    provider: "twilio-verify",          // Required: only "twilio-verify" supported

    // Twilio credentials
    accountSid: process.env.TWILIO_ACCOUNT_SID!,
    authToken: process.env.TWILIO_AUTH_TOKEN!,
    verifyServiceSid: process.env.TWILIO_VERIFY_SERVICE_SID!,

    // The phone number that receives the OTP (in E.164 format)
    // This is the authorizer's phone — typically the bank operator
    phoneNumber: "+525512345678",

    // How long (seconds) a code is valid before expiry (default: 600)
    codeExpirySeconds: 600,

    // How many failed attempts before the session is locked (default: 3)
    // After lockout, a new SMS must be triggered by calling the tool again
    maxAttempts: 3,

    // Custom message template (optional — uses Twilio's default if omitted)
    // The {code} placeholder is replaced by Twilio with the actual OTP
    messageTemplate: "Your mcp2p authorization code is {code}. Valid for 10 minutes.",
  },
})

Handling verification codes

The AI client handles code extraction automatically. When the SDK returns 2fa_required, the AI prompts the user to share the code. The AI extracts the numeric code from the user's message (even if written naturally, e.g., “it's 847291” or “the code is 8-4-7-2-9-1”) and passes it as the verificationCode parameter in the next tool call.

The SDK strips non-digit characters from the verification code before checking it, so codes entered with spaces or hyphens work correctly.

What happens if the code is wrong

  • The tool returns { status: "2fa_invalid" } with a count of remaining attempts.
  • The AI will tell the user the code was wrong and ask them to try again.
  • After maxAttempts failures (default: 3), the session is locked and the tool returns { status: "2fa_locked" }.
  • A locked session can be reset by calling the payment tool again without a code — this triggers a new SMS.

What happens if the code expires

  • After codeExpirySeconds (default: 600 seconds / 10 minutes), the code becomes invalid.
  • The tool returns { status: "2fa_expired" }.
  • Calling the tool again without a code sends a fresh SMS with a new code.

Security considerations

  • Code expiry: Default 10 minutes. Reduce this for higher-security environments.
  • Attempt limiting: 3 failures lock the session and require a new SMS. This prevents brute-force attacks.
  • Audit trail: Every 2FA event — send, verify, fail, lock — is recorded in the mcp2p audit log visible in the dashboard.
  • No code logging: The SDK never logs the OTP value. Twilio Verify handles code generation and validation; the SDK only passes the user-provided code to Twilio for checking.
  • Phone number security: Never log or expose the configured phone number. Treat it as a secret.

Next steps