feat(3cx): add 3CX PBX plugin — native MCP server skills, commands - #225
Merged
Conversation
3CX shipped a native MCP server built into the PBX in V20 Update 10 (Alpha, July 30 2026). Every PBX exposes its own OAuth-protected endpoint at its own FQDN, so it doesn't fit Conduit's single-shared-endpoint vendor catalog — this plugin documents both the direct standalone connection and Conduit's generic BYO MCP path (/connect/byo) instead of shipping a .mcp.json. Adds 4 skills (api-patterns, directory, calls-queues, pbx-admin), 3 commands (find-contact, pbx-health-check, queue-status), and a GOVERNANCE.md grounded in the real BYO tool-tiering heuristic (src/byo/byo-tool-classifier.ts) rather than the standard VENDOR_TOOL_CONFIG story, since 3CX has no catalog entry. Registers under the "productivity" category (no telephony/UC category exists; mirrors Slack's placement).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a plugin for 3CX's native PBX MCP server, introduced in 3CX V20 Update 10 (announced July 30, 2026 as an Alpha release — 3CX's own release notes describe it as "intended for testing and evaluation only"). This is a first-party server built into the PBX itself, distinct from the older third-party
SSIG-IT/3cx-mcp-servercommunity project on GitHub — the two are not conflated anywhere in this plugin, and no claim from the community project (including its "Enterprise/Enterprise Plus license required" note) is carried over, since it isn't confirmed for 3CX's native offering.Why this is a plugin now, and why it looks different from other plugins here: every 3CX PBX exposes its own MCP endpoint at its own FQDN (
https://yourpbx.3cx.eu/mcppattern) with its own OAuth authorization server — there's no sharedmcp.3cx.com. That means it doesn't fit Conduit's single-shared-endpoint vendor catalog (src/credentials/vendor-config.tshas no3cxentry, and structurally can't in the normal sense). So this plugin documents two real connection paths instead of shipping a.mcp.json:claude mcp add --transport httpstraight at a PBX's own URL, OAuth done directly against that PBX./connect/byo) — generic, vendor-agnostic code (src/byo/*) that auto-discovers the PBX's OAuth flow (RFC 9728 → RFC 8414 → RFC 7591 DCR, RFC 9207 issuer validation) and auto-classifies each tool's permission tier from its name/description (src/byo/byo-tool-classifier.ts), since there's no hand-curatedVENDOR_TOOL_CONFIGentry to read from.GOVERNANCE.mdworks through what that BYO classifier heuristic actually does to 3CX's documented tool groups (verified directly against the real source inwyre-technology/conduit, not assumed) — including a genuine, non-obvious gap: theQuerytool is enforcedSELECT-only inside the PBX regardless of role, but Conduit's classifier tiers on the tool's name. If that name doesn't lead with a recognized read verb, it tierswritedespite the PBX-side restriction — a usability gap, not a safety one, but worth knowing before assuming aread-tier grant reaches it.3CX has not published exact MCP tool-name strings anywhere I could access — only human-readable capability labels in its own "MCP Tools and Permissions Reference." Every skill here describes tools by capability rather than inventing snake_case identifiers, and points at calling
tools/listagainst the live PBX as the authoritative source.What was added
Category:
productivity— no telephony/UC/voip category exists in this repo's taxonomy (checked: accounting, bcdr, crm, documentation, email-security, incident-management, infrastructure, knowledge, legal, marketplace, monitoring, network, psa, psa-rmm, rmm, sales, security, workflow-pack).networkis specifically network-device monitoring (Auvik/Domotz/Meraki), not a fit for a phone system.productivityalready houses Slack — another communications/collaboration platform — so 3CX mirrors that placement rather than forcing a new category.Directory:
msp-claude-plugins/3cx/3cx/skills/api-patterns— connection setup (direct + Conduit BYO), the inherited permission model, and how to discover the live tool surfaceskills/directory— contact/extension lookups (email, exact extension, phonebook, CRM-synced)skills/calls-queues— active calls, recordings, voicemail, queue/department/profile visibility, plus the write actions that change live routing (with explicit caution language)skills/pbx-admin— system diagnostics, PBX inventory/database, the read-onlyQuerytool, call flow apps, and blocklist/blacklist/DID write actions (with explicit caution language)commands/find-contact.md,commands/pbx-health-check.md,commands/queue-status.mdGOVERNANCE.md,README.mdNo subagent — checked the closest analogues in this repo (vendors running their own hosted/native MCP server rather than a WYRE-built one:
pax8,rootly,runzero;connectwise-cpqis WYRE-built, not a vendor-hosted analogue, so it wasn't used as a pattern source). None of those three ship a populatedagents/directory — matching that precedent, this plugin ships skills + commands only.No
.env.exampleand no.mcp.json— every connection is OAuth against a PBX-specific URL with no static token or shared endpoint to template, matching thewyre-gatewayplugin's precedent (pure OAuth, no headers/secrets) rather than the API-key.env.examplepattern used by token-based vendors.plugin.jsonstarts at0.1.0, matching the actual starting-version convention of the three most recently added vendor-hosted-MCP plugins (axcient,rootly,runzeroall shipped0.1.0initially, not1.0.0).Also touched:
docs/scripts/generate-plugins.ts(added a3cx→3CXdisplay-name mapping so the docs site doesn't title-case it as "3cx"),docs/src/data/plugins.ts(regenerated),scripts/unanchored-docs.json(one new inventoried entry — see verification below).Verification
All commands run from the repo root in a clean worktree off
origin/main, after committing.1. Docs-site regen + build (
docs/, using--ignore-scriptslocally becausesharp's native build fails on this machine regardless of Node version 22/26 — pre-existing, unrelated to this change, and self-heals via thedeploy-docs.ymlworkflow'snpm cion Node 20):Plugin count moved 80 → 81 in the generated data (confirmed by diffing against
git show HEAD~1). The new entry:Full
npx astro build+npx pagefind --site dist(site build + search index, the parts ofnpm run buildthat don't needsharp) also completed clean: 159 pages including/plugins/3cx/, homepage hero shows "81 Plugins" / "365 skills" (was 80/361 before).2. Marketplace drift + bump gate:
3. Doc-reference resolution:
(Caught and fixed one real issue along the way: an early draft backtick-referenced
`3cx-mcp-server`inside an Anti-triggers bullet, which this check correctly flagged as a dangling skill-id-shaped reference. Reworded to italics since it's naming an external GitHub project, not a sibling skill.)4. Tool anchoring:
One new unit is in the inventory:
3cx:skills/api-patterns, flagged for theclaude mcp add --scope project --transport http ...setup command (a real CLI invocation, not a 3CX API operation — there's no MCP tool to anchor it to). This is the same class of exception the script's own design accounts for (seepax8:commands/search-products.md, already inventoried for the same reason — hyphenated tool names the script's snake_case regex can't see). Added vianode scripts/check-tool-anchoring.mjs --update, which produced a clean, purely-additive one-line diff toscripts/unanchored-docs.json.5. Plugin validation:
Also ran
claude plugin validateacross all 82 registered plugins (mirroring the CI loop invalidate.yml) to confirm thegenerate-plugins.tsdisplay-name edit didn't regress anything else: 0 failed out of 82.6. Sanity checks:
.mcp.jsonanywhere undermsp-claude-plugins/3cx/(confirmed viafind).triggers:field in anySKILL.mdfrontmatter (confirmed viagrep).versionfield on the new marketplace entry (onlyplugin.jsoncarries version).Not merging — leaving this for review.
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is enabled.