mcpField
P
pbx-mcp

pbx-mcp

本地服务
ictinnovations.com通信协作193 天前更新

关于 pbx-mcp

pbx-mcp 是通过 AMI 和 ESL 检查 Asterisk 与 FreeSWITCH PBX 系统的 MCP 服务,为 AI 助手提供统一的检查工具;呼叫控制和 Asterisk 配置需分别显式启用。

主要功能

  1. 01检查 Asterisk 状态、通道、端点和拨号计划
  2. 02检查 FreeSWITCH 状态、通道、注册和 SIP
  3. 03预览挂断操作影响的通道
  4. 04显式启用拨号和挂断工具
  5. 05选择启用 Asterisk 中继与分机配置

适用场景

  1. 01检查离线分机或活动通话
  2. 02排查 SIP 中继注册状态
  3. 03预览挂断操作会影响哪些通道
  4. 04启用配置功能后创建 Asterisk 中继或 SIP 分机

MCP 相关

向 MCP 客户端提供已配置的 Asterisk 和/或 FreeSWITCH 检查工具。呼叫控制和 Asterisk 配置工具仅在分别启用对应选项后注册。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"ictinnovations-pbx": {
"command": "npx",
"args": [
"-y",
"pbx-mcp"
],
"env": {
"ASTERISK_AMI_HOST": "<ASTERISK_AMI_HOST>",
"ASTERISK_AMI_PORT": "<ASTERISK_AMI_PORT>",
"ASTERISK_AMI_USERNAME": "<ASTERISK_AMI_USERNAME>",
"ASTERISK_AMI_PASSWORD": "<ASTERISK_AMI_PASSWORD>",
"ASTERISK_AMI_TLS": "<ASTERISK_AMI_TLS>",
"FREESWITCH_ESL_HOST": "<FREESWITCH_ESL_HOST>",
"FREESWITCH_ESL_PORT": "<FREESWITCH_ESL_PORT>",
"FREESWITCH_ESL_PASSWORD": "<FREESWITCH_ESL_PASSWORD>",
"PBX_MCP_ALLOW_WRITE": "<PBX_MCP_ALLOW_WRITE>",
"PBX_MCP_TIMEOUT_MS": "<PBX_MCP_TIMEOUT_MS>"
}
}
}
}
启动命令npx -y pbx-mcp
需要配置的环境变量
ASTERISK_AMI_HOSTHostname or IP of the Asterisk server. Set this to enable the Asterisk tools.
ASTERISK_AMI_PORTAsterisk Manager Interface port. Defaults to 5038.
ASTERISK_AMI_USERNAMEAMI username from manager.conf.
ASTERISK_AMI_PASSWORD密钥AMI secret from manager.conf.
ASTERISK_AMI_TLSConnect to AMI over TLS. Set true if tlsenable=yes in manager.conf.
FREESWITCH_ESL_HOSTHostname or IP of the FreeSWITCH server. Set this to enable the FreeSWITCH tools.
FREESWITCH_ESL_PORTFreeSWITCH inbound event socket port. Defaults to 8021.
FREESWITCH_ESL_PASSWORD密钥Event socket password from event_socket.conf.xml. Defaults to ClueCon, which you should change.
PBX_MCP_ALLOW_WRITEUnlocks call control. When false the server is read-only and the originate and hangup tools are not registered at all. Placing a call on a live trunk costs real money, so leave this off unless you mean it.
PBX_MCP_TIMEOUT_MSPer command timeout in milliseconds. Defaults to 10000.

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npmpbx-mcp0.1.4

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

pbx-mcp

pbx-mcp MCP server Documentation Status

一个 MCP 服务,可让 AI 助手检查和控制 Asterisk 与 FreeSWITCH。

询问“现在有哪些分机处于离线状态?”或“我的 SIP 中继为什么无法注册?”,即可从正在运行的交换机获得准确答案,而不是猜测。

由 ICT Innovations 的 Tahir Almas 开发。该团队也是 ICTCore、ICTContact、ICTDialer、ICTFax 和 ICTPBX 的开发者。本仓库中的 AMI 和 ESL 客户端采用的协议基础,也正是这些产品所使用的。

为什么要用

调试 PBX 意味着要记住两套截然不同的命令。Asterisk 使用 AMI 和拥有数百个命令的 CLI。FreeSWITCH 使用 ESL,也有自己的一套术语。如果你同时运行两者,就得整天在不同上下文之间切换。

pbx-mcp 在两者前提供一套统一、描述清晰的工具接口,让助手可以从“通话失败了”直接转到 sofia status gateway,而不必由你逐步说明每个操作。

初次使用?用户指南介绍了 PBX 设置、客户端配置、示例和故障排除。本 README 是快速参考。

助手能看到什么

十二个只读工具,每种引擎各六个,每个工具都描述得足够清楚,让模型无需额外指示就能选对。这是运行在 MCP Inspector 下的服务:

MCP Inspector 中列出的 pbx-mcp 工具

四个写入工具 asterisk_originate、asterisk_hangup、freeswitch_originate 和 freeswitch_hangup,只有在设置 PBX_MCP_ALLOW_WRITE=true 后才会显示。

安装

npm install -g pbx-mcp

或者直接通过 npx 运行,这是大多数 MCP 客户端配置采用的方式:

npx -y pbx-mcp

需要 Node 18 或更高版本。

Docker

如果你不想在连接 PBX 的机器上安装 Node,可以使用预构建镜像。

docker run -i --rm \
  -e ASTERISK_AMI_HOST=10.0.0.10 \
  -e ASTERISK_AMI_USERNAME=mcp \
  -e ASTERISK_AMI_PASSWORD=change-me \
  ghcr.io/ictinnovations/pbx-mcp

如果从 Docker Hub 拉取更方便,也可以使用同一镜像:ictinnovations/pbx-mcp。

需要了解以下三点:

  • -i 不能省略。该服务通过 stdio 使用 MCP 通信,因此如果没有连接 stdin,容器启动后就会一直沉默,看起来就像服务出故障了一样。
  • 无需发布端口,因为没有任何监听端口。
  • 必须能够从容器内部访问 PBX。如果 Asterisk 运行在 Docker 主机本身上,在 Mac 和 Windows 上请将上面的 IP 替换为 host.docker.internal,在 Linux 上则添加 --network host。

镜像以非 root 用户运行,并且与其他运行方式一样,默认以只读模式启动。

配置

所有配置都通过环境变量提供。可设置 Asterisk 配置块、FreeSWITCH 配置块,或同时设置两者。服务只会注册已配置的工具,因此仅使用 Asterisk 的环境中不会看到 FreeSWITCH 工具。

Asterisk
变量默认值说明
ASTERISK_AMI_HOST(启用所必需)Asterisk 主机的主机名或 IP
ASTERISK_AMI_PORT5038manager.conf 中的 AMI 端口
ASTERISK_AMI_USERNAMEAMI 用户名
ASTERISK_AMI_PASSWORDAMI 密钥
ASTERISK_AMI_TLSfalse若 tlsenable=yes,则设为 true

manager.conf 中的用户至少需要 read = system,call,command 和 write = command 权限。只有计划启用写入模式时才添加 originate。

[mcp]
secret = change-me
read = system,call,command
write = command
FreeSWITCH
变量默认值说明
FREESWITCH_ESL_HOST(必填才能启用)交换机的主机名或 IP
FREESWITCH_ESL_PORT8021入站 ESL 端口
FREESWITCH_ESL_PASSWORDClueCon来自 event_socket.conf.xml
共享
变量默认值说明
PBX_MCP_ALLOW_WRITEfalse解锁呼叫控制。请先阅读安全部分
PBX_MCP_TIMEOUT_MS10000每条命令的超时时间
配置(仅限 Asterisk,选择启用)
变量默认值说明
PBX_MCP_ALLOW_PROVISIONfalse注册六个中继和分机工具。与 PBX_MCP_ALLOW_WRITE 相互独立
PBX_MCP_TRUNK_ALLOW(未设置)中继可指向的 IPv4 CIDR 和主机名,以逗号分隔。未设置时将拒绝 asterisk_trunk_create
PBX_MCP_CONTEXT_ALLOW(未设置)新对象可使用的拨号计划上下文,以逗号分隔。未设置时将拒绝所有创建操作
PBX_MCP_PJSIP_FILEpjsip_mcp.conf配置写入的唯一包含文件。必须是独立的 pjsip_*.conf 文件名(绝不能是 pjsip.conf、manager.conf 或任何其他文件)

Claude Desktop

将以下内容添加到 claude_desktop_config.json:

{
  "mcpServers": {
    "pbx": {
      "command": "npx",
      "args": ["-y", "pbx-mcp"],
      "env": {
        "ASTERISK_AMI_HOST": "10.0.0.10",
        "ASTERISK_AMI_USERNAME": "mcp",
        "ASTERISK_AMI_PASSWORD": "change-me",
        "FREESWITCH_ESL_HOST": "10.0.0.11",
        "FREESWITCH_ESL_PASSWORD": "ClueCon"
      }
    }
  }
}

任何使用 stdio 的 MCP 客户端都可以采用相同的结构。副本位于 examples/claude_desktop_config.json。

若要使用 Docker 而非 npx 运行容器,请保留 env 块,并将 command 指向 Docker:

{
  "mcpServers": {
    "pbx": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "ASTERISK_AMI_HOST",
        "-e", "ASTERISK_AMI_USERNAME",
        "-e", "ASTERISK_AMI_PASSWORD",
        "ghcr.io/ictinnovations/pbx-mcp"
      ],
      "env": {
        "ASTERISK_AMI_HOST": "10.0.0.10",
        "ASTERISK_AMI_USERNAME": "mcp",
        "ASTERISK_AMI_PASSWORD": "change-me"
      }
    }
  }
}

每个不带值的 -e NAME 都会将 env 中对应的变量传递到容器中,从而避免机密出现在参数列表中。

工具

Asterisk
工具功能
asterisk_status版本、运行时间、活动呼叫数和已处理呼叫数
asterisk_channels所有实时通道,包含主叫号码、状态、桥接、持续时间和拨号计划位置。可选子字符串筛选
asterisk_endpointsPJSIP 端点的设备状态和联系人数量。在较旧的安装中会回退到 chan_sip 对等端
asterisk_dialplan转储一个上下文,或上下文中的一个分机
asterisk_cli执行任意 CLI 命令,但须遵守下方的安全策略
asterisk_hangup_preview显示挂断操作会断开的实时通道,但不会实际断开
asterisk_originate发起呼叫。仅写入模式可用
asterisk_hangup按名称终止通道。仅写入模式可用
FreeSWITCH
工具功能
freeswitch_status版本、运行时间、当前会话数和最大会话数
freeswitch_channelsshow channels 返回的所有实时呼叫腿。可选子字符串筛选,并保留标题行
freeswitch_registrationsSofia 配置文件上的已注册用户,包含联系人 URI、用户代理和有效期
freeswitch_sofia_status所有 SIP 配置文件和网关,包括中继是否已在上游注册
freeswitch_api执行任意 API 命令,但须遵守下方的安全策略
freeswitch_hangup_preview显示挂断操作会断开的实时呼叫腿,但不会实际断开
freeswitch_originate发起呼叫。仅写入模式可用
freeswitch_hangup对通道 UUID 执行 uuid_kill。仅写入模式可用

安全

PBX 不是随手试验的地方。重新加载配置文件会丢失注册信息,而发起呼叫会在真实线路上产生实际费用。因此,默认采取只读模式,并设置多层防护:

默认只读。 asterisk_cli 接受一组用于检查的前缀白名单(core show、pjsip show、dialplan show、queue show 等)。freeswitch_api 接受同类白名单(status、show、sofia status、db list 等),并按命令开头进行匹配,因此子命令也会被计入。

FreeSWITCH 白名单允许子命令,不是拒绝包含危险词的命令。 sofia status 是读取操作;sofia profile internal restart 不在白名单中,因此会被拒绝。过去采用的方式正好相反:将每个单词与会更改状态的动词列表逐一比对,但这种方法只能捕获有人想到的单词。conference 3001 kick all 就直接绕过了检查。此问题由 Electrical-Place-458 在 r/mcp 上报告。

只读模式下不会注册写入工具。 除非设置 PBX_MCP_ALLOW_WRITE=true,否则 asterisk_originate 和其他三个工具不会出现在 tools/list 中。模型无法调用它看不到的工具。

挂断预览工具始终可用。 asterisk_hangup_preview 和 freeswitch_hangup_preview 会显示挂断操作会断开哪些活动通道,但不会实际断开它们。这样,你可以在启用写入标志前了解影响范围,也可以在执行实际操作前发现通道名称中的拼写错误。根据设计,它们是只读工具,但会使用写入路径所用的相同匹配逻辑。

两种传输方式都会在发送命令前拒绝 shell 元字符。

AMI 标头注入会被拦截。 每个写入 AMI 操作的字段都会检查是否包含回车符和换行符,避免主叫号码字符串混入额外标头。

输出限制为 20,000 个字符。 繁忙的交换机上执行一次 show channels,也不会挤满上下文窗口。

即便有这些防护,也应仅授予 AMI 用户能够回答你问题的最小权限集,并将 PBX 部署在防火墙之后,而不是放在公共互联网中。

配置中继和分机(Asterisk,可选启用)

另外有六个工具可通过 AMI UpdateConfig 创建、列出和删除 PJSIP 中继与 SIP 分机。只有在设置 PBX_MCP_ALLOW_PROVISION=true 时才会注册;它们与写入模式相互独立:启用其中一种不会启用另一种。

工具功能
asterisk_trunk_createIP 身份验证中继:endpoint、aor 和 identify。字段:name、host、port(5060)、transport(udp、tcp、tls)、codecs、context、dry_run
asterisk_trunk_list / asterisk_trunk_delete列出或删除此服务创建的中继
asterisk_extension_createSIP endpoint,电话会向其注册(endpoint、aor、auth),不是拨号计划分机。字段:number、context、codecs、dry_run。生成的密码仅返回一次
asterisk_extension_list / asterisk_extension_delete列出或删除此服务创建的分机。不会列出密码

编解码器为 ulaw、alaw、g722、g729、opus。名称和号码须匹配 ^[A-Za-z0-9_-]{1,32}$。

一次性设置
  1. 在 pjsip.conf 旁创建空的托管文件(缺少 include 会导致错误),并允许 Asterisk 向其中写入:

    touch /etc/asterisk/pjsip_mcp.conf
    
  2. 在 pjsip.conf 末尾添加这一行。不会触碰 pjsip.conf 中的其他内容:

    #include pjsip_mcp.conf
    
  3. 为 AMI 用户授予配置所需的额外权限。config 用于 UpdateConfig/GetConfig,command 用于重新加载和验证步骤;仅当你也使用写入模式时才需要 originate:

    [mcp]
    secret = change-me
    deny = 0.0.0.0/0.0.0.0
    permit = 192.0.2.0/24
    read = system,call,command
    write = command,originate,config
    
  4. 中继引用名为 transport-udp、transport-tcp 或 transport-tls 的传输方式;请在 pjsip.conf 中定义你将使用的传输方式。

工作原理
  • 所有内容都会写入托管文件:使用 UpdateConfig(NewCat、Append、RenameCat、DelCat)更新,然后执行 module reload res_pjsip.so,再运行 pjsip show endpoint mcp-<name>。如果 Asterisk 未报告该端点,就会再次移除更改,并返回错误。
  • 每个对象的名称都是 mcp-<name>。列表和删除操作只会针对托管文件中的 mcp- 分区;不能将中继当作分机删除,反之亦然。
  • 创建操作会拒绝已存在的名称。dry_run=true 会返回完整的配置块,且不会调用 AMI;对于分机,密码会显示为占位符。
  • 所有配置调用都会在进程内串行执行,因为 UpdateConfig 采用读取-修改-写入方式。每个托管文件只运行一个 pbx-mcp 配置程序。
  • 分机会注册为 mcp-<number>,而不是不带前缀的号码。PJSIP 会根据注册用户名匹配端点及其 AOR,而且每个对象都必须带有 mcp- 前缀。创建响应会说明用户名。
  • 密码是由 crypto.randomBytes 生成的 24 个随机 URL 安全字符。它只会在创建响应中返回,也是唯一会显示或记录密码的地方;密码确实会保存在 PBX 上的托管文件中,这是 SIP 密码所必需的。
电话欺诈:启用前请阅读

SIP 中继允许呼叫离开 PBX;可注册且使用了可接通外呼路由的上下文的分机,也会让任何得知密码的人做到这一点。被盗的 SIP 凭据是产生高额电话账单的主要原因之一。

  • 将 PBX_MCP_CONTEXT_ALLOW 指向无法拨打 PSTN 的上下文,除非你确实有此意图。上下文是唯一决定已注册电话或中继可以呼叫哪些号码的因素。
  • 尽可能严格地限制 PBX_MCP_TRUNK_ALLOW。主机名会按字面值比较,且不会解析,因此 DNS 无法扩大列表范围。不支持 IPv6。
  • 允许列表为空时会拒绝所有内容:配置会默认失败关闭。
  • 请将持有这些工具的助手视为有权更改哪些对象可以访问 PBX。检查它创建的内容(先使用 *_list 或 dry_run),不要将 SIP(5060)或 AMI(5038)暴露到互联网。
  • 尝试使用时,优先选择实验室或预发布 PBX。
示例流程

仅使用文档专用地址(RFC 5737)。环境:

PBX_MCP_ALLOW_PROVISION=true
PBX_MCP_TRUNK_ALLOW=192.0.2.0/24,198.51.100.0/24
PBX_MCP_CONTEXT_ALLOW=from-trunk,from-internal
  1. 使用 asterisk_trunk_create 和 dry_run=true 预览中继:

    { "name": "carrier1", "host": "192.0.2.10", "port": 5060, "transport": "udp",
      "codecs": ["ulaw", "alaw"], "context": "from-trunk", "dry_run": true }
    

    返回内容如下:

    [mcp-carrier1]
    type=endpoint
    transport=transport-udp
    context=from-trunk
    disallow=all
    allow=ulaw,alaw
    aors=mcp-carrier1
    
    [mcp-carrier1]
    type=aor
    contact=sip:192.0.2.10:5060
    
    [mcp-carrier1]
    type=identify
    endpoint=mcp-carrier1
    match=192.0.2.10
    
  2. 不带 dry_run 再运行一次。不在允许列表中的主机(例如 203.0.113.5)会被拒绝。

  3. 创建分机:{ "number": "1001", "context": "from-internal" }。回复会提供 SIP 用户名 mcp-1001 和密码,密码仅显示这一次。

  4. 使用这些凭据将电话连接到 PBX,然后通过 asterisk_endpoints 检查。

  5. asterisk_extension_list 和 asterisk_trunk_list 会显示现有对象;使用 1001 调用 asterisk_extension_delete,以及使用 carrier1 调用 asterisk_trunk_delete,即可将其删除。

已针对 Asterisk 22(认证版本 22.8)进行测试。使用的 PJSIP 选项(identify、max_contacts、remove_existing、auth_type=userpass)和 UpdateConfig 功能(RenameCat、catfilter)都是标准功能,但在其他 Asterisk 版本上请重新确认。已生成 TCP 和 TLS 中继配置,但未对实时对端进行测试。

从源代码构建

git clone https://github.com/ictinnovations/pbx-mcp.git
cd pbx-mcp
npm install
npm run build
npm start

AMI 和 ESL 客户端没有第三方依赖。这两种协议都只是通过 TCP 传输带有帧结构的文本,手动实现它们可以让安装体积更小,行为也更可预测。仅有的运行时依赖是 MCP SDK 和 Zod。

独立使用协议客户端

如果你想在自己的 Node 代码中与 PBX 通信,而完全不需要 MCP,这个服务所用的两个客户端也单独发布了。协议功能相同,不依赖 MCP SDK、Zod 等任何组件:

  • asterisk-ami-node - Asterisk Manager Interface 客户端。npm install asterisk-ami-node
  • freeswitch-esl-node - FreeSWITCH Event Socket 客户端,采用入站模式。npm install freeswitch-esl-node

两者均零依赖,使用 TypeScript,支持 ESM 和 CommonJS,要求 Node 18 或更高版本,并经过模拟交换机测试,因此无需 PBX 即可运行测试套件。

目录结构

src/
  index.ts          entry point, config to transport wiring
  ami.ts            Asterisk Manager Interface client
  esl.ts            FreeSWITCH Event Socket Layer client
  config.ts         environment config and the command safety policy
  tools/
    asterisk.ts     Asterisk tool definitions
    freeswitch.ts   FreeSWITCH tool definitions
    format.ts       text table and truncation helpers

贡献

欢迎提交问题和拉取请求。如果你要添加工具,请像向从未接触过你的拨号计划的同事介绍那样描述它。模型会根据这些描述选择工具,所以描述含糊不清就等于工具无法正常工作。

关于

由 ICT Innovations 创始人 Tahir Almas 创建并维护。

ICT Innovations 自 2005 年以来一直推出开源和商业电话解决方案。如果 pbx-mcp 对你有用,其背后的完整技术栈或许也能帮到你:

有关商业产品的问题,请通过 ICT Innovations 支持门户联系。有关 pbx-mcp 本身的问题,请在 GitHub 上提交问题,以便所有人都能看到答复。

许可证

MIT。请参阅 LICENSE。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。