connectsecure-mcp
MCP server for ConnectSecure — a vulnerability management / IT securityassessment platform. Exposes ConnectSecure's read-only query API (companies,assets, vulnerabilities, Active Directory, firewall, compliance, credentials,and more) as MCP tools.
MSPbots Connector
The MCP Gateway built for MSPs: visible, controlled, and your data stays where it belongs.
MSPbots Connector gives your AI clients one MCP URL to reach your entire MSP stack (RMM, PSA, documentation, security, finance), and gives you control over who can call which tool and a record of everything that was called.
Hosted service: connect.mspbots.ai · Free to use.
Why Connector

| Visible | Every tool call is logged: who, which vendor, when. Usage dashboard, CSV export, SIEM streaming. |
| Controlled | Role-based, per-tool allowlist. Deny by default. |
| Protected | Credentials encrypted per record. AI clients never see your vendor passwords or tokens. |
| MSP-native | Built for the MSP stack only: RMM, PSA, documentation, security, finance. |
Quick start
- Sign up at connect.mspbots.ai.
- Connect your vendors. Pick from 150+ connectors and authorize each one on the vendor's own page, or bring your own API keys. No extra vendor accounts needed.
- Set access. Create roles and decide which tools each role may call. Nothing is allowed until you allow it.
- Add your MCP URL to your AI client. Copy the URL from your Connector dashboard into Claude, ChatGPT, Cursor, VS Code, Gemini, Codex, or any MCP-capable client.
- Ask your AI to do real work, and watch every call appear in the audit log.
Features
Unified gateway
- One MCP URL for all your AI clients
- 150+ connectors across the MSP stack
- Custom MCP servers supported, free
- Authorization happens on each vendor's own page; the AI never sees passwords or tokens
- Bring your own credentials: use the vendor API keys you already have
- Multiple accounts per app; connect once, reuse across AI clients
- Tool search: finds the right action for the task
- One sign-in; vendor credentials are injected behind the scenes and OAuth tokens refresh automatically
Visibility
- Audit log for every tool call (who, which vendor, when)
- Usage dashboard: call volume, top vendors, error rate, per-user activity
- Export audit logs to CSV, or stream to Loki, Graylog, or LogScale (SIEM)
- Optional recording of tool arguments and result summaries (off by default, enabled per organization)
Control
- Per-role, per-tool allowlist, deny by default
- owner / admin / member roles
- SCIM provisioning with Entra ID, Okta, JumpCloud, and Google Workspace
Security
- Credentials encrypted one record at a time (AES-256-GCM, per-record key)
- AI clients authenticate with OAuth 2.1 + PKCE
- Vendor responses are scanned for prompt-injection patterns and returned as structured data. This is one layer of defense, not a guarantee against every attack.
- Static egress IP for customer firewall and API allowlisting
Pricing
Free.
Links: connect.mspbots.ai · mspbots.ai
Overview
- Stateless HTTP service. No credentials are ever persisted — each requestsupplies its own credentials via headers, used only for the lifetime ofthat single request.
- Supports concurrent requests; per-request credential isolation is done viaPython
contextvars, not a global/shared client instance. - Entry points:
POST /mcp(MCP protocol) andGET /health(health check). - Default port:
8080(configurable viaMCP_HTTP_PORT).
Scope
19 read-only (GET) tools, trimmed twice: first from an initial285-tool full-API build down to 50 tools (to stay under Vertex AI/Gemini's512-function-declaration ceiling across all loaded MCP servers), thenagain on 2026-08-04 down to 19 tools per the "actual usage + minimalsame-category CRUD" scope decision applied across this program's MCPfleet.
The 2026-08-04 trim confirmed all 11 endpoints MSPbots' own productionintegration actually calls (via web/int/sys/integration/api/listagainst integration id 2008424422784020481):vulnerabilities_details, external_asset_vulnerabilities,remediate_records, asset_critical_vulnerabilities, asset_view,sw_problems_remediations_view (all asset); azure_secure_score,ad_users_view, ad_password_policies (all active_directory);companies/company (company); users (users). Every one of thoseis kept, plus a small amount of same-category padding for baselinevisibility:
asset(9 of the prior 18): the 6 actually-used tools above, plusassets(base list),asset_stats,risk_score.active_directory(6 of the prior 22): the 3 actually-used toolsabove, plusad_basic_info,ad_domain_details,ad_groups_view.company(3 of the prior 9):companies,companies_by_id,company_stats.users(1, unchanged):get_users.
Cut entirely on 2026-08-04 (available in the prior 50-tool build butnot exposed here): the other 16 asset tools (asset_software,asset_users, distinct_os, distinct_platform,total_asset_count, vulnerabilities_count, problems_summary,get_asset_remediation_plan, remediation_plan_global), the other 16active_directory tools (computers/GPOs/groups/OUs/roles detail views,Azure AD logs/licenses, user licenses/details), and the other 6 companytools (adaudit, asset_windows_compatibility, event_tickets,jobs_view + jobs_view_by_id).
Cut in the earlier 285→50 pass (still not exposed here — see KnownGaps for the full accounting): Asset Data (33, field-level machinedetail), Vulnerabilities category (22, overlapped with the vulnerabilitysummaries kept in Asset), Compliance (10), Reports (7), Firewall (12),Application Baseline (8), Integration (6), Ad Audit, Agent, AttackSurface, Tags, Credentials, Discovery Settings, Compliance Assessment,Backup Software, EDR, Event Set, External Scan, Jobs, Patch Management,PII, Scheduler, Settings, Ticket Template (2-4 each, mostlyadministrative/config endpoints). Write operations (POST/PATCH/DELETE, ~78 of them) were never in scope in either pass. If a removedtool is needed later, the vendor's Swagger spec (linked below) stilldocuments it and it can be re-added the same way the kept tools weregenerated.
Authentication
ConnectSecure is multi-tenant: every tenant is provisioned on its own podhostname (e.g. https://pod1.connectsecure.com), and auth is a JWT accesstoken obtained out-of-band via:
POST {base_url}/w/authorize
Client-Auth-Token: base64(tenant_name + "+" + client_id + ":" + client_secret)
(Note the literal + between tenant_name and client_id — confirmed againstboth ConnectSecure's own Swagger description and MSPbots' real implementationin autointegration's ConnectSecureAuth.java; easy to miss since theSwagger text renders it ambiguously as "tenant+client_id".)
which returns {"data": {"access_token": "...", "user_id": "..."}}. Thisserver does not perform that exchange itself — like the other OAuth2-basedvendor MCPs in this program (Acronis, ConnectWise Asio, Bloom Growth), it onlyreceives the already-obtained access token (plus the user id and podhostname) via request headers, and forwards them upstream asAuthorization: Bearer <token> and X-USER-ID: <user_id> on every call.
HEADER Authentication Parameters
| Header | Type | Required | Default | Allowed values | Description | Example |
|---|---|---|---|---|---|---|
X-ConnectSecure-Access-Token |
string | Yes | None | None | The JWT access_token returned by POST {base_url}/w/authorize, forwarded as-is as the upstream Authorization: Bearer <token> |
eyJhbGciOi... |
X-ConnectSecure-User-Id |
string | Yes | None | None | The user_id returned by the same /w/authorize call, forwarded as-is as the upstream X-USER-ID request header |
1234 |
X-ConnectSecure-Base-Url |
string | Yes | None | None | The tenant's ConnectSecure pod hostname (per tenant, not fixed) | https://pod1.connectsecure.com |
Missing any of the three headers returns 401:
{
"error": "Missing credentials",
"message": "This server requires the X-ConnectSecure-Access-Token, X-ConnectSecure-User-Id, and X-ConnectSecure-Base-Url headers",
"required_headers": ["X-ConnectSecure-Access-Token", "X-ConnectSecure-User-Id", "X-ConnectSecure-Base-Url"],
"optional_headers": []
}
Environment Variables
| Variable | Type | Required | Default | Description |
|---|---|---|---|---|
MCP_HTTP_PORT |
int | No | 8080 |
HTTP listen port |
MCP_HTTP_HOST |
string | No | 0.0.0.0 |
HTTP listen address |
(No *_BASE_URL env var — the pod hostname is per-tenant and always suppliedvia the X-ConnectSecure-Base-Url header, never a fixed default.)
MCP Endpoint
POST /mcp— MCP protocol (streamable HTTP transport)GET /health— health check, returns{"status": "ok", "service": "connectsecure-mcp", "transport": "http"}
Tool List
Every list-style tool shares the same optional pagination/filter params —condition (a ConnectSecure query-condition string), skip, limit,order_by — in addition to whatever's listed below. Get-by-id tools take asingle required id path parameter. Several report/detail tools additionallyrequire a company_id (get it from connectsecure_get_company_companies)and/or an object_guid/asset_id (get it from the corresponding list toolfirst).
| Category | Tool | Description | Params |
|---|---|---|---|
| active_directory | connectsecure_get_active_directory_ad_basic_info |
Retrieve ad basic info. | company_id, source, condition?, skip?, limit?, order_by? |
| active_directory | connectsecure_get_active_directory_ad_domain_details |
Retrieve ad domain details. | company_id, source, condition?, skip?, limit?, order_by? |
| active_directory | connectsecure_get_active_directory_ad_groups_view |
Retrieve ad groups view. | condition?, skip?, limit?, order_by? |
| active_directory | connectsecure_get_active_directory_ad_password_policies |
Retrieve ad password policies. | condition?, skip?, limit?, order_by? |
| active_directory | connectsecure_get_active_directory_ad_users_view |
AD user account inventory for a client company (not ConnectSecure's own platform users — see users_get_users). |
condition?, skip?, limit?, order_by? |
| active_directory | connectsecure_get_active_directory_azure_secure_score |
Retrieve azure secure score. | condition?, skip?, limit?, order_by? |
| asset | connectsecure_get_asset_asset_critical_vulnerabilities |
Vulnerability findings filtered to critical severity only (severity-scoped subset of vulnerabilities_details). |
condition?, skip?, limit?, order_by? |
| asset | connectsecure_get_asset_asset_stats |
Aggregate asset inventory counters, not individual asset records. | condition?, skip?, limit?, order_by? |
| asset | connectsecure_get_asset_asset_view |
Per-asset inventory view from the core asset resource (primary asset listing). | condition?, skip?, limit?, order_by? |
| asset | connectsecure_get_asset_assets |
Report-query asset list, same query group as asset_stats (alternative to asset_view). |
condition?, skip?, limit?, order_by? |
| asset | connectsecure_get_asset_external_asset_vulnerabilities |
Vulnerability findings scoped to externally-facing (internet-exposed) assets only. | condition?, skip?, limit?, order_by? |
| asset | connectsecure_get_asset_remediate_records |
Remediation action records (fixes applied/recommended per finding), not raw findings. | condition?, skip?, limit?, order_by? |
| asset | connectsecure_get_asset_risk_score |
Computed aggregate risk-score rating per asset/company. | condition?, skip?, limit?, order_by? |
| asset | connectsecure_get_asset_sw_problems_remediations_view |
Software-specific problems (missing/outdated software) paired with remediation status. | condition?, skip?, limit?, order_by? |
| asset | connectsecure_get_asset_vulnerabilities_details |
Full vulnerability findings across all assets/severities (base finding-level dataset). | condition?, skip?, limit?, order_by? |
| company | connectsecure_get_company_companies |
Retrieve companies. | condition?, skip?, limit?, order_by? |
| company | connectsecure_get_company_companies_by_id |
Retrieve company. | id |
| company | connectsecure_get_company_company_stats |
Retrieve company stats. | condition?, skip?, limit?, order_by? |
| users | connectsecure_get_users_get_users |
Retrieve Users. | condition?, skip?, limit?, order_by? |
Test Example
# Health check
curl -s http://localhost:8080/health
# Call a tool via the MCP protocol (streamable HTTP) — requires an
# initialize handshake first per the MCP spec; abbreviated example below
# shows the tool-call request body only:
curl -s -X POST http://localhost:8080/mcp -H "X-ConnectSecure-Access-Token: <jwt-access-token>" -H "X-ConnectSecure-User-Id: <user-id>" -H "X-ConnectSecure-Base-Url: https://pod1.connectsecure.com" -H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" -H "mcp-session-id: <session-id-from-initialize>" -d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "connectsecure_get_company_companies",
"arguments": {}
}
}'
Expected: 200 with the companies list on a valid token; 401/403(surfaced by the tool as Error: ConnectSecure API error 401/403: ...) on aninvalid or expired token.
Live self-test against a real account: passed. Using a realaccess_token/user_id/pod for tenant mspbots (pod pod107), calledthrough the running MCP server end-to-end:
connectsecure_get_users_get_users→ returned 11 real user records.connectsecure_get_company_companies→ returned the real company(id: 11939,mspbots.ai,internal_scan: false).connectsecure_get_active_directory_ad_basic_info,connectsecure_get_active_directory_ad_users_view,connectsecure_get_asset_assets,connectsecure_get_asset_vulnerabilities_details→ all returned{"status": true, "total": 0}(genuine empty result, notan error). Cross-checked against the two non-empty calls above: since thesame auth/parsing path returns real data for users/companies, the zerocounts for AD/asset/vulnerability endpoints reflect this test tenanthavinginternal_scan: false(no on-prem scan agent deployed) — nothinghas been scanned yet — not a broken pipeline or masked auth failure.Client-Auth-Tokenformat correction: the initial/w/authorizeattempt (base64 oftenant_name+client_id+:+client_secret,no separator betweentenant_nameandclient_id) got a real403fromConnectSecure. This was first (wrongly) suspected to mean the providedclient_secretwas still MSPbots-internal ciphertext (it base64-decodesto agAAAAA...-prefixed string, the signature of a Pythoncryptography.fernettoken). That hypothesis was disproved by checkingthe real implementation in MSPbots'autointegrationrepo(client/src/main/java/mspbots/integration/client/core/auth/impl/ConnectSecureAuth.java):the actual formula inserts a literal+betweentenant_nameandclient_id—base64(tenant_name + "+" + client_id + ":" + client_secret)— and usesclient_secretcompletely as-is, with no decryption stepanywhere in that codebase. Rebuilding the token with the literal+included, using the exact same (unmodified)client_secretvalue, got areal200from/w/authorizewith a validaccess_token. So theclient_secretwas fine all along; the bug was purely in the testscript's string concatenation, not in ConnectSecure, MSPbots' credentialstorage, or this MCP server (which never performs the/w/authorizeexchange itself — see Authentication).
API Reference
- Swagger UI: https://pod102.myconnectsecure.com/apidocs/ (spec:
https://pod102.myconnectsecure.com/apidocs/swagger.yaml) — public, nologin required. Each tenant's own pod hosts the identical spec. - Overview / auth docs: see
/w/authorize(tagAuth) in the spec above.
Known Gaps
- Trimmed twice. First from 285 to 50 tools, by explicit user decision,after the full 285-tool build tripped the platform's aggregate MCPfunction-declaration ceiling (Vertex AI/Gemini caps a single model call at512 function declarations across all loaded MCP servers) — see below forwhat that pass cut. Then again on 2026-08-04, from 50 to 19 tools, perthe "actual usage + minimal same-category CRUD" scope decision appliedacross this program's MCP fleet — kept the 11 endpoints MSPbots' ownproduction integration actually calls plus light same-category padding;cut the rest of what had been "full category" Active Directory/Companyand the broader 18-tool Asset set down further. See Scope for theexact breakdown of both passes. Any removed tool can be re-added onrequest if a real use case needs it — the vendor's Swagger spec (linkedbelow) still documents its exact shape.
- 285→50 pass cut entirely: Asset Data, the standaloneVulnerabilities category, Compliance, Reports, Firewall, ApplicationBaseline, Integration, and a long tail of small administrative/configcategories (Ad Audit, Agent, Attack Surface, Tags, Credentials, DiscoverySettings, Compliance Assessment, Backup Software, EDR, Event Set, ExternalScan, Jobs, Patch Management, PII, Scheduler, Settings, Ticket Template).
- Read-only scope, by explicit user decision (unchanged from theoriginal build): the ~78
POST/PATCH/DELETEwrite operations(create/update/delete company mappings, credentials, discovery settings,tags, scheduler jobs, etc.) were never implemented — can be added onrequest. company_id/object_guid/asset_idare not auto-resolved — manyActive Directory / Asset Data / Compliance tools require one of these IDsas input; call the corresponding list tool (e.g.connectsecure_get_company_companies,connectsecure_get_asset_asset_view)first to obtain it.- Response field shapes are whatever the vendor's Swagger spec documents —not independently re-verified per endpoint beyond the schema-validity check(no bare arrays without
items, confirmed with a script againsttools/listoutput).