{"slug":"3cx-api-patterns","title":"3CX API Patterns","summary":"3CX's native PBX MCP server: the per-PBX endpoint shape (every PBX is its own FQDN and its own OAuth authorization server — there is no shared mcp.3cx.com), the Admin Console + client setup flow, the permission model (fully inherited from the 3CX account that approved the connect","platform":"Claude","tags":[],"authorName":"LLM Mart","authorSlug":"llm-mart","score":0,"source":"github","price":null,"verified":false,"createdAt":"2026-09-21T18:26:31.598673Z","repo":{"url":"https://github.com/WYRE-AI/msp-claude-plugins","stars":46,"forks":26,"license":"Apache-2.0","updatedAt":"2026-09-21T16:51:26Z"},"bodyHtml":"<hr>\n<h2>name: \"3CX API Patterns\"\ndescription: &gt;\n3CX's native PBX MCP server: the per-PBX endpoint shape (every PBX is its\nown FQDN and its own OAuth authorization server — there is no shared\nmcp.3cx.com), the Admin Console + client setup flow, the permission model\n(fully inherited from the 3CX account that approved the connection), and\nhow to discover the live tool surface since 3CX has not published exact\ntool-name strings.\nwhen_to_use: &gt;-\nWhen connecting Claude to a 3CX PBX for the first time, troubleshooting a\n3CX MCP connection or authorization failure, or figuring out which 3CX MCP\ntools are actually available before calling one. Use when: 3cx connect,\n3cx mcp, 3cx setup, 3cx oauth, 3cx authenticate, 3cx admin console, 3cx\nmcp client, 3cx byo, or 3cx pbx url.</h2>\n<h1>3CX API Patterns</h1>\n<h2>Overview</h2>\n<p>3CX added a native MCP server built directly into the PBX, introduced in\n<strong>3CX V20 Update 10</strong> (announced July 30, 2026 as an <strong>Alpha</strong> release — 3CX's\nown release notes describe Update 10 Alpha as \"intended for testing and\nevaluation only\"). Treat everything in this plugin as based on that Alpha:\nexact tool names, the permissions reference, and behavior may all shift\nbefore 3CX ships Update 10 GA.</p>\n<p>This is a different project from the older third-party <em>SSIG-IT/3cx-mcp-server</em>\non GitHub, a community-built MCP server that talks to 3CX's REST API rather\nthan shipping inside the PBX. Do not mix the two up, and do not carry\nclaims from the community project into this one — in particular, its\n\"Enterprise/Enterprise Plus license required\" claim is specific to that\nproject and is <strong>not</strong> confirmed for 3CX's native MCP server.</p>\n<h2>Anti-triggers</h2>\n<ul>\n<li><strong>The community <em>3cx-mcp-server</em> project</strong> — different codebase, different\ntool surface, different auth model (its own API-key setup rather than\nper-PBX OAuth). Nothing in this plugin describes it, and nothing about it\nshould be assumed here.</li>\n<li><strong>A customer's \"the phones are down\" ticket</strong> — that's ticket handling in\nthe PSA, not a 3CX MCP call. Use <code>halopsa-tickets</code>, <code>connectwise-psa-tickets</code>,\nor <code>autotask-tickets</code> to work the ticket itself; come back to this plugin\nonce you need the PBX-side facts.</li>\n<li><strong>WYRE's Conduit vendor catalog</strong> — 3CX has no catalog entry there and,\nstructurally, cannot: Conduit's catalog vendors share one fixed endpoint\nper vendor, and every 3CX PBX is its own origin with its own authorization\nserver. See <em>Connection &amp; Authentication</em> below for the two ways this\nplugin actually reaches a PBX.</li>\n</ul>\n<h2>Connection &amp; Authentication</h2>\n<h3>Every PBX is its own endpoint</h3>\n<p>Unlike a hosted SaaS MCP server, there is no single 3CX MCP URL. Each PBX\nexposes its own endpoint at its own FQDN, following the pattern:</p>\n<pre><code>https://yourpbx.3cx.eu/mcp\n</code></pre>\n<p>(or whatever FQDN that customer's PBX actually uses). Transport is\nStreamable HTTP. A skill, command, or agent in this plugin that needs to\ncall a tool always does so against whichever PBX endpoint the current\nsession is already connected to — nothing here can assume a fixed URL\nacross customers.</p>\n<h3>Admin-side setup (on the PBX)</h3>\n<p>An admin enables the connection from inside that PBX's own console:</p>\n<ol>\n<li>Sign into the 3CX Admin Console for the target PBX.</li>\n<li><strong>Admin → Integrations → MCP Clients → Add MCP Client</strong>.</li>\n<li>3CX displays the MCP Server URL for that PBX — copy it for the client-side\nstep below.</li>\n</ol>\n<h3>Client-side setup — direct connection (no gateway)</h3>\n<p>For a technician working standalone in Claude Code, with no MSP gateway in\nfront of it:</p>\n<pre><code>claude mcp add --scope project --transport http 3CX \"https://yourpbx.3cx.eu/mcp\"\nclaude\n</code></pre>\n<p>Then inside Claude:</p>\n<ol>\n<li>Run <code>/mcp</code> and select the <code>3CX</code> server.</li>\n<li>Choose <strong>Authenticate</strong>. Claude opens the 3CX authorization page in the\nbrowser.</li>\n<li>Sign in, review the requested access, and select <strong>Allow</strong>.</li>\n<li>Claude confirms the connection succeeded.</li>\n</ol>\n<p>The new connection also then shows up in that PBX's own\n<strong>Admin → Integrations → MCP Clients</strong> list — the authorization is visible\nand revocable from both sides.</p>\n<h3>Client-side setup — through Conduit's BYO MCP feature</h3>\n<p>An MSP already using WYRE's Conduit gateway for other vendors does not need\na separate direct connection per PBX. Conduit has a generic\n<strong>\"Bring Your Own (BYO) MCP server\"</strong> feature (<code>/connect/byo</code>) built for\nexactly this shape — a vendor with no fixed shared endpoint. Paste the\nPBX's MCP URL from the admin step above into that form; Conduit then:</p>\n<ol>\n<li>Discovers the PBX's own OAuth authorization server at runtime —\nRFC 9728 protected-resource metadata, then RFC 8414 authorization-server\nmetadata.</li>\n<li>Registers a client dynamically against that authorization server\n(RFC 7591 DCR).</li>\n<li>Runs the normal authorization-code + PKCE flow, validating the callback's\n<code>iss</code> against the discovered issuer (RFC 9207) before persisting tokens.</li>\n</ol>\n<p>No 3CX-specific code exists in Conduit for this — the same generic BYO path\nhandles any MCP server shaped this way. See <em>Tool permission tiers under\nConduit BYO</em> below for how Conduit decides what an operator may call once\nconnected, and this plugin's <code>GOVERNANCE.md</code> for the full picture.</p>\n<h2>Permission Model</h2>\n<p>Tool access is entirely inherited from the 3CX user account that approved\nthe OAuth connection. Claude can do exactly what that account's 3CX role\nalready permits inside 3CX — nothing more. There is no separate\nClaude-specific permission layer on the PBX side.</p>\n<p>One tool is restricted regardless of role: the <code>Query</code> tool (see the\n<code>pbx-admin</code> skill) is hard-restricted server-side to read-only SQL\n<code>SELECT</code> statements, no matter what the connecting account is otherwise\nallowed to do in 3CX.</p>\n<h2>Discovering the Live Tool Surface</h2>\n<p>3CX's own \"MCP Tools and Permissions Reference\" documents these tools by\nhuman-readable label — find a contact by email, list active calls, drop a\ncall, and so on — but does not publish the literal machine tool-name\nstrings anywhere publicly accessible. The skills in this plugin describe\nthe tool surface by capability for that reason, deliberately without\ninventing exact snake_case identifiers that cannot be verified against a\nreal PBX.</p>\n<p><strong>Before calling a tool, confirm its real name and schema</strong> by calling the\nstandard MCP <code>tools/list</code> method against the connected PBX. This is also the\nonly reliable way to know what changed between the Update 10 Alpha and any\nlater release — the tool surface described here is a snapshot, not a\nguarantee.</p>\n<h2>Tool Permission Tiers Under Conduit BYO</h2>\n<p>If a PBX is reached through Conduit's BYO path rather than a direct\nconnection, Conduit still has to decide a permission tier for each tool it\nhas never seen before — there is no hand-curated <code>VENDOR_TOOL_CONFIG</code> entry\nfor 3CX to draw from. It does this with a name-and-description heuristic\nthat is deliberately conservative:</p>\n<ul>\n<li>A leading verb from a fixed read-shaped set (<code>get</code>, <code>list</code>, <code>search</code>,\n<code>find</code>, <code>query</code>, and similar) tiers the tool <code>read</code>.</li>\n<li>Any other leading verb — including one the heuristic has simply never\nseen before — tiers the tool <code>write</code>. Unrecognized verbs are never\nsilently treated as read.</li>\n<li>A secret/credential noun anywhere in the name or description escalates\nto <code>admin</code>, and a mutating verb on a privileged-account noun (roles,\nmembers, billing, API keys, org settings) does too.</li>\n</ul>\n<p>This matters concretely for one 3CX tool: the read-only <code>Query</code> tool is\nenforced <code>SELECT</code>-only <em>inside the PBX</em>, but Conduit's heuristic tiers\npurely on the tool's name. If that tool's real name is built around a\ngeneric \"run\" or \"execute\" action rather than a <code>get</code>/<code>list</code>/<code>query</code>-style\nread verb, Conduit will tier it <code>write</code> despite the PBX-side restriction.\nDon't assume <code>read</code> for it; check the tool's actual granted tier after\nconnecting.</p>\n<h2>Gotchas</h2>\n<ul>\n<li><strong>This is Alpha software.</strong> Exact tool names, the permissions reference,\nand behavior can all change before 3CX ships Update 10 GA. Re-verify\nagainst <code>tools/list</code> rather than trusting a cached mental model, especially\nmonths after this was written.</li>\n<li><strong>No shared URL.</strong> Every other skill and command in this plugin assumes an\nalready-connected PBX; there is nothing to hardcode across customers.</li>\n<li><strong>Don't borrow tool names from the community <em>3cx-mcp-server</em> project</strong> —\nit is a different codebase talking to a different API surface.</li>\n</ul>\n<h2>Related Skills</h2>\n<ul>\n<li><a href=\"../directory/SKILL.md\">Directory &amp; Contacts</a> — contact and extension lookups</li>\n<li><a href=\"../calls-queues/SKILL.md\">Calls, Queues &amp; Profiles</a> — live call/queue state and the write actions that change it</li>\n<li><a href=\"../pbx-admin/SKILL.md\">PBX Admin &amp; Diagnostics</a> — system diagnostics, PBX inventory, and configuration writes</li>\n</ul>\n","files":[{"path":"SKILL.md","sizeBytes":8719,"isText":true}],"reviewScore":null,"reviewSummary":null,"trust":{"provenance":"trusted-source-unreviewed","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow.","bodySource":null},"bodyLocked":false,"purchaseUrl":null,"sourceUrl":null,"report":{"provenance":"trusted-source-unreviewed","screen":{"ran":true,"outcome":"clean","suspicious":0,"notes":0,"hiddenCharacters":false},"virusScan":{"engine":"clamav","status":"clean","scannedAt":"2026-09-21T18:26:40.323767Z","sha256":"5959B3C97E92EDFBCBF2509ABFC2A9D71F8C21A5FEFA6B24E3A2D478B8C77ACE","sizeBytes":4022},"review":null,"source":{"repositoryUrl":"https://github.com/WYRE-AI/msp-claude-plugins","path":"msp-claude-plugins/3cx/3cx/skills/api-patterns","license":"Apache-2.0","commit":"147da75a83127bb77f9551efdbf66adf62823c05","subtreeSha":"105522B8F368B751512BBBD8F5E0CA5257D86C0871A1B5286C4D2D7210F7415B","lastSyncedAt":"2026-09-21T18:26:31.557491Z"},"reviewedAt":"2026-09-21T18:26:49.950135Z","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow."},"install":[{"target":"skills-cli","command":"npx skills add https://github.com/WYRE-AI/msp-claude-plugins/tree/main/msp-claude-plugins/3cx/3cx/skills/api-patterns"},{"target":"claude-code","command":"claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install wyre-ai-msp-claude-plugins@llmmart"},{"target":"git","command":"git clone https://github.com/WYRE-AI/msp-claude-plugins.git"}]}