返回市场
Twilio代理支付MCP服务器

Twilio代理支付MCP服务器

作者:deshartman5 星标更新:2025-04-30

项目介绍

Twilio Agent Payments MCP Server

一个基于MCP(模型上下文协议)的服务器,通过Twilio API实现代理辅助支付功能,并具有增强的异步回调功能和通过上下文提示引导的工作流程。

功能

  • 在语音通话中通过Twilio处理安全支付
  • 捕获支付信息(卡号、安全码、过期日期)
  • 对支付信息进行标记化以符合PCI标准
  • 通过MCP资源进行异步回调
  • 使用MCP提示引导支付过程中的每一步
  • 支持重新输入支付信息
  • 与MCP客户端如Claude Desktop集成
  • 安全凭证处理
  • 使用Twilio API密钥提高安全性
  • 基于事件的日志架构

安装

你可以通过npx直接使用此服务器:

npx twilio-agent-payments-mcp-server <accountSid> <apiKey> <apiSecret>

或者全局安装:

npm install -g twilio-agent-payments-mcp-server
twilio-agent-payments-mcp-server <accountSid> <apiKey> <apiSecret>

环境参数

在安装服务器时,需要提供以下参数:

  1. 命令行参数(必需):

    • accountSid:你的Twilio账户SID
    • apiKey:你的Twilio API密钥
    • apiSecret:你的Twilio API密钥密码
  2. 环境变量(在运行服务器之前设置):

    • TOKEN_TYPE:用于支付的令牌类型(例如,'可重复使用的','一次性')
    • CURRENCY:支付货币(例如,'USD','EUR')
    • PAYMENT_CONNECTOR:与Twilio一起使用的支付连接器
    • NGROK_AUTH_TOKEN:你的Ngrok认证令牌(用于回调处理)
    • NGROK_CUSTOM_DOMAIN:Ngrok的可选自定义域名

示例环境变量:

TOKEN_TYPE=reusable CURRENCY=USD PAYMENT_CONNECTOR=your_connector NGROK_AUTH_TOKEN=your_token npx twilio-agent-payments-mcp-server <accountSid> <apiKey> <apiSecret>

有关这些参数的详细信息,请参阅下面的配置部分。

配置

服务器需要以下参数:

  • accountSid:你的Twilio账户SID(必须以'AC'开头,将被验证)
  • apiKey:你的Twilio API密钥(以'SK'开头)
  • apiSecret:你的Twilio API密钥密码

环境变量

以下环境变量用于配置:

  • TOKEN_TYPE:用于支付的令牌类型(例如,'可重复使用的','一次性')
  • CURRENCY:支付货币(例如,'USD','EUR')
  • PAYMENT_CONNECTOR:与Twilio一起使用的支付连接器
  • NGROK_AUTH_TOKEN:你的Ngrok认证令牌(用于回调处理)
  • NGROK_CUSTOM_DOMAIN:Ngrok的可选自定义域名

注意:Twilio凭证(accountSid,apiKey,apiSecret)作为命令行参数提供,而不是环境变量。

安全说明

此服务器使用API密钥和密码而不是认证令牌来提高安全性。这种方法提供了更好的访问控制,并且可以在需要时撤销凭证。更多信息,请参阅Twilio API密钥文档

与Claude Desktop的使用

本地开发

对于本地开发(当包尚未发布到npm时),在你的Claude Desktop配置文件中添加以下内容(macOS上的路径为~/Library/Application Support/Claude/claude_desktop_config.json或Windows上的%APPDATA%\Claude\claude_desktop_config.json):

{
  "mcpServers": {
    "twilio-agent-payments": {
      "command": "node",
      "args": [
        "/PATHTONODE/twilio-agent-payments-mcp-server/build/index.js",
        "your_account_sid_here",
        "your_api_key_here",
        "your_api_secret_here"
      ],
      "env": {
        "TOKEN_TYPE": "reusable",
        "CURRENCY": "USD",
        "PAYMENT_CONNECTOR": "your_connector_name",
        "NGROK_AUTH_TOKEN": "your_ngrok_auth_token_here",
        "NGROK_CUSTOM_DOMAIN": "your_custom_domain_here" // 可选
      }
    }
  }
}

用你的实际Twilio凭证和配置替换值。

发布到npm后

一旦包发布到npm,你可以使用以下配置:

{
  "mcpServers": {
    "twilio-agent-payments": {
      "command": "npx",
      "args": [
        "-y", 
        "twilio-agent-payments-mcp-server",
        "your_account_sid_here",
        "your_api_key_here",
        "your_api_secret_here"
      ],
      "env": {
        ...process.env,   // 包含现有的环境变量,以便子进程可以访问路径
        "TOKEN_TYPE": "reusable",
        "CURRENCY": "USD",
        "PAYMENT_CONNECTOR": "your_connector_name",
        "NGROK_AUTH_TOKEN": "your_ngrok_auth_token_here",
        "NGROK_CUSTOM_DOMAIN": "your_custom_domain_here" // 可选
      }
    }
  }
}

与主机应用程序的集成

MCP(模型上下文协议)的一个关键优势是它消除了对LLM上下文中大量手动配置的需求。MCP服务器会自动向LLM客户端提供所有必要的工具定义、资源模板和能力。

设置你的主机应用程序

要将此MCP服务器集成到自己的主机应用程序中:

  1. 实现MCP客户端:使用现有的MCP客户端库或在应用程序中实现MCP客户端协议。
  2. 连接到MCP服务器:配置应用程序以连接到Twilio Agent Payments MCP服务器。
  3. 让协议处理其余部分:MCP服务器将自动:
    • 将其工具和资源注册到客户端
    • 提供所有工具的输入模式
    • 提供上下文提示以指导LLM完成支付流程

无需在LLM上下文中手动定义工具或资源——MCP协议会自动处理这一发现过程。

示例集成代码

这里是一个简化了的例子,展示如何与MCP客户端集成:

// 初始化你的MCP客户端
const mcpClient = new McpClient();

// 连接到Twilio Agent Payments MCP服务器
await mcpClient.connectToServer({
  name: "twilio-agent-payments",
  // 连接详情取决于你的具体MCP客户端实现
  // 这可能是WebSocket URL、stdio连接或其他传输方式
});

// 客户端将自动发现可用的工具和资源

// 当LLM想要使用一个工具时,你的应用程序可以这样处理:
function handleLlmToolRequest(toolRequest) {
  // toolRequest包含:
  // - server_name: "twilio-agent-payments"
  // - tool_name: 例如,"startPaymentCapture"
  // - arguments: 例如,{ callSid: "CA1234567890abcdef" }
  
  return mcpClient.callTool(toolRequest);
}

// 同样适用于资源:
function handleLlmResourceRequest(resourceRequest) {
  // resourceRequest包含:
  // - server_name: "twilio-agent-payments"
  // - uri: 例如,"payment://CA1234567890abcdef/PA9876543210abcdef/status"
  
  return mcpClient.accessResource(resourceRequest);
}

最小的LLM上下文需求

LLM只需要知道它可以使用Twilio Agent Payments MCP服务器来处理支付。系统提示中的简单指令就足够了:

你有一个Twilio Agent Payments MCP服务器,可以帮助你在语音通话期间处理安全支付。
当客户想要付款时,你可以使用该服务器提供的工具来安全地捕获支付信息,同时保持PCI合规性。

服务器将在支付流程的每一步通过上下文提示引导你。

MCP服务器本身提供了所有详细的工具定义、输入模式和上下文提示,以引导LLM完成支付流程。

开发者实现说明

本节解释了MCP服务器实现是如何跨不同组件和文件组织的,重点在于所使用的架构模式。

组件组织

服务器实现分布在几个目录中:

  1. src/index.ts:主要入口点,负责:

    • 初始化MCP服务器
    • 初始化TwilioAgentPaymentServer单例
    • 通过自动发现机制发现并注册所有组件到MCP服务器
    • 设置日志事件监听器
    • 将服务器连接到传输层
  2. src/tools/:包含单独的工具实现

    • 每个工具都实现为一个工厂函数,返回一个具有名称、描述、形状和执行属性的对象
    • 工具处理特定的支付操作(例如,StartPaymentCaptureTool,CaptureCardNumberTool)
    • 每个工具使用Zod定义其输入模式,并实现execute方法
    • 工具通过getInstance()访问TwilioAgentPaymentServer单例
  3. src/prompts/:包含提示实现

    • 每个提示都实现为一个工厂函数,返回一个具有名称、描述和执行属性的对象
    • 提示为LLM在支付流程的每一步提供上下文指导
    • 一些提示接受参数,可用于定制提示内容
  4. src/resources/:包含资源实现

    • 资源提供数据访问(例如,PaymentStatusResource)
    • 每个资源都实现为一个工厂函数,返回一个具有名称、模板、描述和读取属性的对象
    • 资源通过getInstance()访问TwilioAgentPaymentServer单例
  5. src/api-servers/:包含Twilio API客户端的实现

    • 实现TwilioAgentPaymentServer作为单例
    • 处理与Twilio API的通信
    • 管理支付会话状态
    • 提供静态方法以访问单例实例
  6. src/utils/:包含实用函数

    • autoDiscovery.ts文件处理工具、提示和资源的自动发现和注册

TwilioAgentPaymentServer的单例模式

此代码库中的一个重要架构模式是TwilioAgentPaymentServer的单例模式:

class TwilioAgentPaymentServer extends EventEmitter {
    // 单例实例
    private static instance: TwilioAgentPaymentServer | null = null;

    /**
     * 获取实例的静态方法
     */
    public static getInstance(): TwilioAgentPaymentServer {
        if (!TwilioAgentPaymentServer.instance) {
            throw new Error('TwilioAgentPaymentServer未初始化。请先调用initialize()。');
        }
        return TwilioAgentPaymentServer.instance;
    }
    
    /**
     * 初始化实例的静态方法
     */
    public static initialize(accountSid: string, apiKey: string, apiSecret: string): TwilioAgentPaymentServer {
        if (!TwilioAgentPaymentServer.instance) {
            TwilioAgentPaymentServer.instance = new TwilioAgentPaymentServer(accountSid, apiKey, api_密钥);
        }
        return TwilioAgentPaymentServer.instance;
    }

    // 私有构造函数以防止直接实例化
    private constructor(accountSid: string, apiKey: string, apiSecret: string) {
        // 初始化代码...
    }
}

这种方法的好处:

  • 确保整个应用程序中只有一个TwilioAgentPaymentServer实例
  • 消除了需要通过多个函数传递实例的需求
  • 提供了一个更简洁的API,具有更简单的函数签名
  • 使从代码库的任何地方访问TwilioAgentPaymentServer变得更容易

工厂函数模式

工具、提示和资源使用工厂函数模式实现:

  1. 在工具中

    // 来自StartPaymentCaptureTool.ts的示例
    export function startPaymentCaptureTool() {
        // 获取TwilioAgentPaymentServer实例
        const twilioAgentPaymentServer = TwilioAgentPaymentServer.getInstance();
        
        // 创建用于日志记录的事件发射器
        const emitter = new EventEmitter();
        
        return {
            name: "startPaymentCapture",
            description: "开始新的支付捕获会话",
            shape: schema.shape,
            execute: async function execute(params: z.infer<typeof schema>, extra: any): Promise<ToolResult> {
                // 实现调用Twilio API并返回结果
            },
            emitter // 用于附加事件监听器
        }
    }
    
  2. 在资源中

    // 来自PaymentStatusResource.ts的示例
    export function paymentStatusResource() {
        // 获取TwilioAgentPaymentServer实例
        const twilioAgentPaymentServer = TwilioAgentPaymentServer.getInstance();
        
        // 创建用于日志记录的事件发射器
        const emitter = new EventEmitter();
        
        return {
            name: "PaymentStatus",
            template: new ResourceTemplate("payment://{callSid}/{paymentSid}/status", { list: undefined }),
            description: "获取支付会话的当前状态",
            read: async (uri: URL, variables: Record<string, string | string[]>, extra: any): Promise<ResourceReadResult> => {
                // 实现检索并格式化支付状态数据
            },
            emitter // 用于附加事件监听器
        };
    }
    
  3. 在提示中

    // 来自提示工厂函数的示例
    export function startCapturePrompt() {
        return {
            name: "StartCapture",
            description: "启动支付捕获过程的提示",
            execute: (args: { callSid: string }, extra: RequestHandlerExtra): GetPromptResult | Promise<GetPromptResult> => {
                // 返回提示内容
            }
        };
    }
    

自动发现和注册

服务器使用自动发现机制来查找和注册所有组件:

// 在src/utils/autoDiscovery.ts中
export async function discoverComponents(mcpServer: McpServer) {
    // 获取当前目录路径
    const basePath: string = path.dirname(fileURLToPath(import.meta.url));

    await Promise.all([
        discoverTools(mcpServer, path.join(basePath, '../tools')),
        discoverPrompts(mcpServer, path.join(basePath, '../prompts')),
        discoverResources(mcpServer, path.join(basePath, '../resources'))
    ]);
}

这种方法:

  • 自动查找工具、提示和资源各自目录中的所有组件
  • 动态导入并注册它们到MCP服务器
  • 使得添加新组件而无需修改主文件变得容易
  • 减少样板代码并提高可维护性

提示中的参数

某些提示接受参数,可用于定制提示内容。StartCapturePrompt是一个很好的例子:

  1. 参数定义

    // 在提示工厂函数中
    return {
        name: "StartCapture",
        description: "启动支付捕获过程的提示",
        schema: { callSid: z.string().describe("Twilio呼叫SID") }, // 参数模式
        execute: (args: { callSid: string }, extra: RequestHandlerExtra) => {
            // 实现
        }
    };
    
    • schema属性使用Zod定义参数模式
    • 在这种情况下,它需要一个类型为字符串的callSid参数
  2. 在提示中使用参数

    execute: (args: { callSid: string }, extra: RequestHandlerExtra): GetPromptResult | Promise<GetPromptResult> => {
      const { callSid } = args;
    
      if (!callSid) {
        throw new Error("需要提供callSid参数");
      }
      
      return {
        messages: [
          {
            role: "assistant",
            content: {
              type: "text",
              text: getStartCapturePromptText(callSid), // 在提示文本中使用参数
            }
          }
        ]
      };
    }
    
    • execute方法接受参数作为其第一个参数
    • 它可以验证参数并使用它们来定制提示内容
    • 在这种情况下,callSid用于提供上下文

这种模式允许提示动态和上下文化,根据支付流程的当前状态提供量身定制的指导。

可用工具

startPaymentCapture

启动活动呼叫的支付捕获过程。

参数:

  • callSid:活动呼叫的Twilio呼叫SID

重要:StartCapturePrompt.ts要求用户从MCP客户端侧输入一个呼叫SID。这是一个必需参数,如果未提供,提示将抛出错误。

注意:在处理Twilio呼叫时,你需要了解正在工作的呼叫腿的呼叫SID。Twilio支付需要附着到PSTN侧的呼叫腿。如果应用于Twilio客户端侧,DTMF数字将不会被捕获。因此,这个MCP服务器假设正在使用正确的呼叫腿。通常检查如下:

 // 呼叫方向的伪代码
  if (event.CallDirection === "toPSTN") {
    theCallSid = event.CallSid;
  }

  if (event.CallDirection == "toSIP") {
    theCallSid = event.ParentCallSid;
  }

返回:

  • paymentSid:新支付会话的Twilio支付SID

captureCardNumber

开始捕获支付卡号。

参数:

  • callSid:活动呼叫的Twilio呼叫SID
  • paymentSid:支付会话的Twilio支付SID
  • captureType:设置为'payment-card-number'

返回:

  • 卡号捕获操作的状态

captureSecurityCode

开始捕获卡片的安全码。

参数:

  • callSid:活动呼叫的Twilio呼叫SID
  • paymentSid:支付会话的Twilio支付SID
  • captureType:设置为'security-code'

返回:

  • 安全码捕获操作的状态

captureExpirationDate

开始捕获卡片的过期日期。

参数:

  • callSid:活动呼叫的Twilio呼叫SID
  • paymentSid:支付会话的Twilio支付SID
  • captureType:设置为'expiration-date'

返回:

  • 过期日期捕获操作的状态

completePaymentCapture

完成支付捕获会话。

参数:

  • callSid:活动呼叫的Twilio呼叫SID
  • paymentSid:支付会话的Twilio支付SID

返回:

  • 支付完成操作的状态

可用资源

payment://{callSid}/{paymentSid}/status

以JSON对象形式获取支付会话的当前状态。此资源提供了关于支付捕获过程当前状态的详细信息,包括:

  • 支付SID
  • 支付卡号(已屏蔽)
  • 支付卡类型