DEX_MCP
OfficialClick on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@DEX_MCP Show me devices that haven't checked in for 7 days"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
1E Platform Consumer API — MCP Server
An MCP (Model Context Protocol) server that exposes the 1E Platform Consumer API as 92 callable tools for any MCP-compatible LLM client (Claude Desktop, Cursor, etc.).
Covered endpoints
Controller | Tools |
ApplicableOperations | Get by type ID, Get by type name, Add, Delete |
Approvals | Approve instruction/scheduled/persistent (×3), CanApprove checks (×3), Pending notifications (×4) |
AuditLogs | Search, Add entries |
Authentication | 2FA token for instruction, 2FA token for scheduled instruction |
CachedUserGroupMemberships | Get, Add, Delete, Get groups for user, Add groups for user, Remove groups for user, Get users in group |
CachedUsers | List, Get by ID, Add, Update, Delete |
Certificates | List IdP certs, Download cert, Set active cert, Verify cert |
Consumers | List, Get by ID, Get by name, Search, Add, Update, Delete, Delete many, Refresh cache |
CustomProperties | Get by type ID/name, Get by ID, Search, Add, Update, Delete, Delete many |
CustomPropertyTypes | List, Add |
Devices | List, Search, Get by FQDN, Get by Tachyon GUID, Get management groups by FQDN, Summary |
ManagementGroups (device groups) | List, Get by ID, Get by name, Search, Get contents, Get all devices |
InstructionDefinitions | List, Get by ID, Get by name, Search |
Instructions | Send, Send to device, Get by ID, Search, Get statistics (×2), Get responses (×2), Get responding devices, Get target list, Cancel, Rerun |
ScheduledInstructions | Create, Get by ID, Search, Update, Cancel, Delete |
PersistentInstructions | Create, Get by ID, Search, Cancel, Delete |
Related MCP server: Halo ITSM MCP Server
Project structure
src/
├── index.ts # MCP server entry point (stdio + Streamable HTTP transports)
├── client.ts # HTTP client — auth (OAuth/JWT, bearer, API key), token cache, retries
└── tools.ts # All 92 tool definitions
package.json
tsconfig.jsonQuick start
1. Install
npm install2. Set environment variables
ONE_E_BASE_URL is always required, e.g. https://your-tenant.1e.com/consumer. Pick one auth mode:
Mode | Variables | Notes |
1. OAuth / JWT Certificate Assertion (preferred, auto-rotating) |
| Signs a client-assertion JWT (RS256), exchanges it for a Tachyon token, caches it (5 min safety buffer before expiry) |
2. Static bearer token |
| Manual rotation |
3. API key |
| Sent as |
export ONE_E_BASE_URL=https://your-tenant.1e.com/consumer
export ONE_E_PRIVATE_KEY_FILE=/path/to/key.pem
export ONE_E_CERTIFICATE_FILE=/path/to/cert.pem
export ONE_E_APPLICATION_ID=<azure-ad-app-id>
export ONE_E_CONSUMER_NAME=<tachyon-consumer-name>3. Run
# Development (stdio)
npm run dev
# Development (Streamable HTTP)
npm run dev:http
# Production
npm run build && npm startTransports
Controlled by the TRANSPORT env var:
stdio(default) — for Claude Desktop / local MCP clientshttp— Streamable HTTP onPORT(default3000), endpoint/mcp, health check/health
HTTP-only env vars:
Variable | Description |
| HTTP port (default |
| Required. All |
| Allowed CORS origin (default |
| Set to |
Hosting for multiple MCP clients (Claude, Copilot Studio, etc.)
Run in http mode to let several MCP clients connect to one running server instance. Two independent credential models:
Shared identity (default, ONE_E_CLIENT_SUPPLIED_KEY unset) — the server holds one 1E credential (any of the 3 auth modes above) and every connecting client uses it. MCP_AUTH_TOKEN gates access to your hosted server and is required in this mode.
Per-client identity (ONE_E_CLIENT_SUPPLIED_KEY=true) — each client supplies its own 1E credential on the request that opens its session, via an X-API-Key header (or an api_key/apiKey query parameter, for clients like Microsoft Copilot Studio whose "API key" auth option only supports query strings). The server builds a fresh, isolated 1E client for that session and uses it for every tool call the session makes — nobody's calls run under anyone else's 1E identity. Despite the header's name, the value is forwarded to 1E as a bearer token (X-Tachyon-Authenticate), not literally as X-API-Key — that's what worked empirically against a live tenant for Tachyon-issued session tokens (1E rejected the same token via X-API-Key with "No authentication token found," but accepted it via X-Tachyon-Authenticate). OAuth/JWT pass-through isn't supported — sending a private key per request is not something clients should do.
MCP_AUTH_TOKEN becomes optional in this mode: a valid X-API-Key satisfies the access gate on its own, since MCP clients that can only configure one credential (Copilot Studio included) can't also send a separate Authorization: Bearer header. If you do set MCP_AUTH_TOKEN, it's still accepted as an alternate path for clients that support two headers.
export ONE_E_BASE_URL=https://your-tenant.1e.com/consumer
export ONE_E_CLIENT_SUPPLIED_KEY=true
TRANSPORT=http npm startPer-client tenant selection
By default every session hits the one tenant configured in ONE_E_BASE_URL. Set ONE_E_CLIENT_SUPPLIED_TENANT=true (requires ONE_E_CLIENT_SUPPLIED_KEY=true) to let each session pick its own tenant instead, via an X-1E-Base-URL header (or base_url/baseUrl query parameter):
export ONE_E_CLIENT_SUPPLIED_TENANT=trueArbitrary caller-supplied URLs are a real SSRF vector, so every one is validated before use: HTTPS-only, localhost rejected, and the hostname is DNS-resolved and rejected if it lands on a private, loopback, or link-local address (link-local — 169.254.0.0/16 — is where AWS/GCP/Azure serve instance credentials from, so this specifically blocks the classic cloud-metadata SSRF). This is a startup-configured, deliberate opt-in — it's refused to start if enabled without ONE_E_CLIENT_SUPPLIED_KEY, since arbitrary tenant selection must never be paired with the server's own shared credential (a caller could otherwise exfiltrate it by pointing "tenant" at a server they control).
Known limitation: the SSRF check resolves DNS once at session-creation time, not on every subsequent request — a sufficiently sophisticated DNS-rebinding attack could still slip through between the check and the actual request. Fine for testing/internal use; a production-grade multi-tenant deployment should additionally pin the resolved IP via a custom fetch dispatcher.
Header | Purpose | Required when |
| Alternate gate credential | Only if |
| Determines which 1E identity a session's calls run as, and satisfies the gate on its own |
|
| Determines which 1E tenant a session's calls hit | Optional even when |
Check your MCP client's docs for how it lets you set custom headers (or query parameters) on an HTTP connection.
Restricting the tool catalog
By default all 92 tools are available. Set ONE_E_TOOL_ALLOWLIST to a comma-separated list of tool names to expose only a subset — everything else disappears from tools/list and is rejected if called anyway. Applies to both transports. Useful because an LLM pays a real token cost just to reason over the tool catalog on every turn, so a narrowly-scoped deployment should ship a narrow tool list, not all 92.
.env.example ships with a recommended scope for device health identification and remediation — find devices → find the right health-check/remediation instruction → run it → track it to completion:
ONE_E_TOOL_ALLOWLIST=devices_list,devices_search,devices_get_by_fqdn,devices_summary,management_groups_list,management_groups_get_contents,instruction_definitions_search,instruction_definitions_get_by_name,instructions_send,instructions_send_to_device,instructions_get_by_id,instructions_get_statistics,instructions_get_statistics_detail,instructions_get_responses,instructions_get_responses_aggregate,instructions_rerun,instructions_cancelThat's 17 tools instead of 92. It deliberately excludes approvals, persistent/scheduled instructions, and custom properties — add those back in if your remediation workflow needs an approval step, continuous (not just on-demand) monitoring, or health state tracked via custom properties rather than instruction responses.
Comment the line out (or unset the variable) to expose the full 92-tool catalog instead. An unknown tool name in the list fails the server at startup with a clear error, rather than silently having no effect.
Running with Docker
Dockerfile + docker-compose.yml give you a two-stage build (compiles, then a slim runtime image running as a non-root user) with a health check.
1. Configure
cp .env.example .envEdit .env: set ONE_E_BASE_URL, pick one auth mode (see the table above), and set MCP_AUTH_TOKEN (unless you're using ONE_E_CLIENT_SUPPLIED_KEY=true, per Hosting for multiple MCP clients).
2. Run
docker compose up -dThe server listens on PORT (default 3000) over plain HTTP — it doesn't terminate TLS itself. For anything beyond local use, put it behind whatever reverse proxy or tunnel you already use for TLS (nginx, Caddy, your cloud provider's load balancer, Tailscale Funnel, etc.), forwarding to that port.
3. Verify
curl http://localhost:3000/health
# {"status":"ok","sessions":0,"uptime":...}Operating it
docker compose logs -f mcp # tail server logs
docker compose restart mcp # pick up new env vars (in-memory sessions are lost — see note below)
docker compose down # stop everything
docker compose up -d --build # rebuild after a code change and restartSessions live in memory and don't survive a restart — any MCP client with an open session will need to reconnect after one (it'll get a "session not found" until it does). Fine for a single instance; don't run multiple replicas of this service without externalizing session state first.
Connect to Claude Desktop
Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"1e-consumer": {
"command": "node",
"args": ["/absolute/path/to/1e-consumer-mcp/dist/index.js"],
"env": {
"ONE_E_BASE_URL": "https://your-tenant.1e.com/consumer",
"ONE_E_PRIVATE_KEY_FILE": "/absolute/path/to/key.pem",
"ONE_E_CERTIFICATE_FILE": "/absolute/path/to/cert.pem",
"ONE_E_APPLICATION_ID": "<azure-ad-app-id>",
"ONE_E_CONSUMER_NAME": "<tachyon-consumer-name>"
}
}
}
}Restart Claude Desktop and the tools appear automatically.
Adding more tools
Copy this pattern into src/tools.ts:
{
name: "my_new_tool",
description: "What it does and what permissions it requires.",
inputSchema: {
type: "object",
properties: {
someParam: { type: "string", description: "..." },
},
required: ["someParam"],
},
async handler(args, client) {
const res = await client.get(`/MyEndpoint/${args.someParam}`);
return [{ type: "text", text: JSON.stringify(res.data, null, 2) }];
},
},Available Tools
92 toolsapplicable_operations_addA
Add a new Applicable Operation. Provide securableTypeId OR securableTypeName (not both). Names must be unique per type. Requires 'Security' permission on 'Security'.
Inputs: name (required), securableTypeId, securableTypeName.
applicable_operations_deleteA
Delete an Applicable Operation by ID. Fails if it has permissions attached. Requires 'Write' on 'Security'.
Inputs: id (required).
applicable_operations_get_by_type_idA
Returns all operations applicable to a securable type (by numeric ID). Requires 'Read' on 'Security'.
Inputs: securableTypeId (required).
applicable_operations_get_by_type_nameA
Returns all operations applicable to a securable type (by name). Requires 'Read' on 'Security'.
Inputs: securableTypeName (required).
approvals_approve_instructionB
Approve or reject an Instruction. Users cannot approve their own instructions. Requires 'Approve' on the Instruction Definition.
Inputs: approved (required), instructionId (required), comment.
approvals_approve_persistent_instructionB
Approve or reject a Persistent Instruction (API v26.2+). Requires 'Approve' on the Instruction Definition.
Inputs: approved (required), persistentInstructionId (required), comment.
approvals_approve_scheduled_instructionB
Approve or reject a Scheduled Instruction. Requires 'Approve' on the Instruction Definition.
Inputs: approved (required), scheduledInstructionId (required), comment.
approvals_can_approve_instructionB
Check whether the calling user can approve the given Instruction.
Inputs: instructionId (required).
approvals_can_approve_persistent_instructionA
Check whether the calling user can approve the given Persistent Instruction (API v26.2+).
Inputs: id (required).
approvals_can_approve_scheduled_instructionA
Check whether the calling user can approve the given Scheduled Instruction.
Inputs: id (required).
approvals_get_all_pendingA
Returns all pending approval requests (Instructions, Scheduled Instructions, Device Authorizations) the calling user can action.
Inputs: no named parameters.
approvals_get_pending_instructionsB
Returns all Instructions pending approval that the calling user can approve.
Inputs: no named parameters.
approvals_get_pending_persistent_instructionsA
Returns all Persistent Instructions pending approval that the calling user can approve (API v26.2+).
Inputs: no named parameters.
approvals_get_pending_scheduled_instructionsA
Returns all Scheduled Instructions pending approval that the calling user can approve.
Inputs: no named parameters.
audit_logs_addB
Add one or more audit log entries (API v24.9+).
Inputs: entries (required).
audit_logs_searchA
Search audit logs. Filterable/sortable by: Component, Comment, CreatedTime, Message, UserName, DetailMessage. Requires 'Read' on 'Security'.
Inputs: skip, take, filter, sortBy, +1 more.
authentication_authenticate_instructionA
Submit a one-time token for Instruction Two-Factor Authentication. Only the instruction creator can call this.
Inputs: token (required), instructionId (required).
authentication_authenticate_scheduled_instructionA
Submit a one-time token for Scheduled Instruction Two-Factor Authentication. Only the creator can call this.
Inputs: token (required), scheduledInstructionId (required).
cached_user_group_memberships_addB
Create a new user–group membership. Requires 'Write' on 'Security'.
Inputs: userId (required), groupId (required).
cached_user_group_memberships_add_groups_for_userA
Batch-add a user to multiple groups (skips existing memberships). Requires 'Write' on 'Security'.
Inputs: userId (required), groupIds (required).
cached_user_group_memberships_deleteA
Remove the membership between a user and a group. Requires 'Delete' on 'Security'.
Inputs: userId (required), groupId (required).
cached_user_group_memberships_getA
Get the membership record for a specific user+group pair. Requires 'Read' on 'Security'.
Inputs: userId (required), groupId (required).
cached_user_group_memberships_get_groups_for_userB
Get all group IDs a user belongs to. Requires 'Read' on 'Security'.
Inputs: userId (required).
cached_user_group_memberships_get_users_in_groupA
Get all user IDs that are members of a specific group. Requires 'Read' on 'Security'.
Inputs: groupId (required).
cached_user_group_memberships_remove_groups_for_userA
Batch-remove a user from multiple groups (skips non-existent memberships). Requires 'Delete' on 'Security'.
Inputs: userId (required), groupIds (required).
cached_users_addC
Create a new cached user.
Inputs: username (required), email, displayName.
cached_users_deleteB
Delete a cached user by their integer ID.
Inputs: id (required).
cached_users_get_by_idA
Get a cached user by their integer ID.
Inputs: id (required).
cached_users_listA
List all cached users with optional skip/take pagination.
Inputs: skip, take.
cached_users_updateC
Update a cached user. The body must include the user's ID.
Inputs: id (required), email, username, displayName.
certificates_download_idpA
Download a PEM-formatted IdP certificate by its thumbprint. Requires 'Read' on 'Infrastructure'.
Inputs: thumbprint (required).
certificates_list_idpA
List all available IdP certificates. Requires 'Read' on 'Infrastructure'.
Inputs: no named parameters.
certificates_set_active_idpB
Set the active IdP certificate by thumbprint. Requires 'Write' on 'Infrastructure'.
Inputs: thumbprint (required).
certificates_verify_idpA
Verify whether a certificate (by thumbprint) can be used for IdP communication. Requires 'Write' on 'Infrastructure'.
Inputs: thumbprint (required).
consumers_addA
Create a Consumer. Name must be alphanumeric+underscore only, unique. System consumers cannot be created. Requires 'Write' on 'Consumer'.
Inputs: name (required), maximumSimultaneousInFlightInstructions (required), isEnabled, applicationUrl, +4 more.
consumers_deleteA
Delete a Consumer by ID. System consumers and those used by scheduled instructions cannot be deleted. Requires 'Write' on 'Consumer'.
Inputs: id (required).
consumers_delete_manyA
Delete multiple Consumers by their IDs in one request. Requires 'Write' on 'Consumer'.
Inputs: ids (required).
consumers_get_by_idA
Return a single Consumer by integer ID. Requires 'Read' on 'Consumer'.
Inputs: id (required).
consumers_get_by_nameA
Return a single Consumer by name (Base64-encoded automatically). Requires 'Read' on 'Consumer'.
Inputs: name (required).
consumers_listA
Return all Consumers. Requires 'Read' on 'Consumer'.
Inputs: no named parameters.
consumers_refresh_cacheB
Force a refresh of the internal Consumers cache.
Inputs: no named parameters.
consumers_searchA
Search Consumers. Filterable/sortable by: Name, Enabled, MaximumSimultaneousInstructions, OffloadTargetUrl, SystemConsumer. Requires 'Read' on 'Consumer'.
Inputs: skip, take, filter, sortBy, +1 more.
consumers_updateB
Update an existing Consumer. System consumers cannot be renamed or disabled. Requires 'Write' on 'Consumer'.
Inputs: id (required), name, isEnabled, applicationUrl, +5 more.
custom_properties_addA
Create a Custom Property with optional values. Provide typeId OR typeName. Name: unique, ≤16 chars, no spaces. Values: unique, ≤32 chars each. Requires 'Write' on 'CustomProperty'.
Inputs: name (required), typeId, values, typeName.
custom_properties_deleteA
Delete a single Custom Property by ID. Requires 'Write' on 'CustomProperty'.
Inputs: id (required).
custom_properties_delete_manyB
Delete multiple Custom Properties by their IDs. Requires 'Write' on 'CustomProperty'.
Inputs: ids (required).
custom_properties_get_by_idA
Return a single Custom Property by its ID.
Inputs: id (required).
custom_properties_get_by_type_idC
Return all Custom Properties for a given type ID.
Inputs: typeId (required).
custom_properties_get_by_type_nameA
Return all Custom Properties for a given type name.
Inputs: typeName (required).
custom_properties_searchA
Search Custom Properties. Filterable/sortable by: Name, TypeName.
Inputs: skip, take, filter, sortBy, +1 more.
custom_properties_updateA
Update a Custom Property. values=null → unchanged; values=[] → removes all values. Requires 'Write' on 'CustomProperty'.
Inputs: id (required), name, typeId, values, +1 more.
custom_property_types_addA
Create a new Custom Property Type. Name: unique, ≤32 chars. System types cannot be created. Requires 'Write' on 'CustomProperty'.
Inputs: name (required), description.
custom_property_types_listA
Return all available Custom Property Types.
Inputs: no named parameters.
devices_get_by_fqdnA
Get a single device by its fully-qualified domain name (FQDN), e.g. 'hostname.domain.com'.
Inputs: fqdn (required).
devices_get_by_tachyon_guidA
Get a single device by its Tachyon GUID (the unique identifier assigned by the 1E agent).
Inputs: guid (required).
devices_get_management_groups_by_fqdnA
Get the Management Groups that a device (identified by FQDN) belongs to.
Inputs: fqdn (required).
devices_listA
List all registered devices/agents known to the 1E platform.
Inputs: no named parameters.
devices_searchB
Search devices with filter/sort/pagination. Body is a SearchPostModel: start (integer offset), pageSize, sort array. includeInherited=true includes devices from child management groups.
Inputs: sort, start, pageSize, includeInherited.
devices_summaryC
Get a summary count/status of devices matching an optional filter.
Inputs: start, pageSize.
instruction_definitions_get_by_idA
Get a single Instruction Definition by its integer ID. Returns full schema including parameters needed.
Inputs: id (required).
instruction_definitions_get_by_nameA
Get an Instruction Definition by its exact name. Use this to find the definitionId and parameter schema before sending an instruction.
Inputs: name (required).
instruction_definitions_listB
List all available Instruction Definitions (the templates that describe what instructions can be sent to devices).
Inputs: instructionType.
instruction_definitions_searchC
Search Instruction Definitions with filter/sort/pagination.
Inputs: sort, start, pageSize.
instructions_cancelA
Cancel a running instruction. keepData=true retains any responses already collected; keepData=false deletes them.
Inputs: id (required), keepData.
instructions_get_by_idA
Get an Instruction by its integer ID. Returns status, target info, parameters, and approval state.
Inputs: id (required).
instructions_get_responding_devicesB
Get the list of unique device FQDNs that have responded to an instruction.
Inputs: instructionId (required), local.
instructions_get_responsesA
Get the actual responses/results from devices for an instruction. local=true returns data stored locally. Supports pagination via start/pageSize.
Inputs: instructionId (required), local, start, pageSize.
instructions_get_responses_aggregateA
Get aggregated (grouped/counted) responses for an instruction — useful for survey-style instructions that return the same values from many devices.
Inputs: instructionId (required), local, pageSize.
instructions_get_statisticsA
Get execution statistics for an instruction: total devices targeted, how many responded, pending, errors.
Inputs: id (required).
instructions_get_statistics_detailB
Get detailed per-state statistics for an instruction.
Inputs: id (required).
instructions_get_target_listB
Get the list of devices that were targeted by an instruction.
Inputs: instructionId (required).
instructions_rerunA
Re-run a previously completed instruction with the same parameters and scope.
Inputs: instructionId (required).
instructions_searchC
Search Instructions with filter/sort/pagination.
Inputs: sort, start, pageSize.
instructions_sendB
Send an instruction to devices. Use definitionId or definitionName to identify the instruction template. Target devices via 'devices' (array of FQDNs like ['host.domain.com']) OR via 'scope' (management group expression). Parameters are passed as [{name, value}] pairs matching the definition's schema.
Inputs: devices, keepRaw, comments, parameters, +4 more.
instructions_send_to_deviceA
Send an instruction directly to a single device identified by its Tachyon GUID. Simpler than instructions_send when you already know the device GUID.
Inputs: guid (required), comments, parameters, definitionId, +3 more.
management_groups_get_all_devicesA
Get all devices across all Management Groups.
Inputs: no named parameters.
management_groups_get_by_idA
Get a Management Group by integer ID.
Inputs: id (required).
management_groups_get_by_nameC
Get a Management Group by name.
Inputs: name (required).
management_groups_get_contentsB
Get the devices that are members of a Management Group by its integer ID.
Inputs: id (required).
management_groups_listA
List all Management Groups (device groups). These are used to scope instructions to sets of devices.
Inputs: includeSystemGroups.
management_groups_searchC
Search Management Groups with filter/sort/pagination.
Inputs: sort, start, pageSize.
persistent_instructions_cancelB
Cancel a Persistent Instruction by integer ID.
Inputs: id (required).
persistent_instructions_createC
Create a Persistent Instruction that continuously applies to all current and future devices matching a scope.
Inputs: devices, comments, parameters, definitionId, +3 more.
persistent_instructions_deleteB
Delete a Persistent Instruction by integer ID.
Inputs: id (required).
persistent_instructions_get_by_idA
Get a Persistent Instruction by integer ID.
Inputs: id (required).
persistent_instructions_searchC
Search Persistent Instructions with filter/sort/pagination.
Inputs: sort, start, pageSize.
scheduled_instructions_cancelB
Cancel a Scheduled Instruction by integer ID.
Inputs: id (required).
scheduled_instructions_createC
Schedule an instruction to run on a recurring schedule. Uses SQL Server Agent-style schedule fields: scheduleFreqType (1=once,4=daily,8=weekly,16=monthly), scheduleFreqInterval, scheduleActiveStartDate, scheduleActiveStartTime (HHMMSS as integer, e.g. 90000 = 09:00:00).
Inputs: devices, comments, parameters, definitionId, +12 more.
scheduled_instructions_deleteB
Delete a Scheduled Instruction by integer ID.
Inputs: id (required).
scheduled_instructions_get_by_idA
Get a Scheduled Instruction by integer ID.
Inputs: id (required).
scheduled_instructions_searchC
Search Scheduled Instructions with filter/sort/pagination.
Inputs: sort, start, pageSize.
scheduled_instructions_updateC
Update an existing Scheduled Instruction by ID.
Inputs: id (required), comments, parameters, scheduleEnabled, +4 more.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 92 tools
Tools are grouped under clear resource prefixes and mostly target distinct actions, so an agent can usually tell them apart. A few near-duplicates exist (list vs search, send vs send_to_device, get_by_id vs get_by_name) that could cause minor selection confusion, especially at this scale.
All tool names use the same lowercase snake_case resource_prefix + action pattern, such as consumers_add, scheduled_instructions_cancel, and management_groups_get_contents. The convention is highly predictable across all 92 tools.
92 tools is an extreme count for a single MCP server and will overwhelm an agent's tool-selection context, even though the underlying platform is broad. This falls squarely in the 50+ extreme mismatch range.
The surface covers core workflows well: send and retrieve instructions, schedule/persistent instructions, approvals, consumers, users, devices, management groups, custom properties, and audit logs. Minor gaps exist, such as no update for persistent instructions or custom property types and read-only management group operations, but agents can generally work around them.
Related MCP Connectors
Discover, plan and run tools across your connected business systems through one OAuth MCP endpoint
Every Canopy public API operation as a tool, run as you after a browser sign-in or on an API key.
Single-connection MCP gateway discovering and executing 490+ verified MCP & A2A tools.
Related MCP Servers
- AlicenseBqualityDmaintenanceAn MCP server that wraps the TeamDynamix (TDX) REST API, enabling AI-assisted IT service management through natural language. It exposes 41 tools for managing tickets, assets, CMDB, knowledge base articles, and other core TDX domains.4185 npm1MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI-driven IT service management by exposing the full Halo ITSM REST API through 172 tools across 43 resource domains to any MCP-compatible client.4MIT
- FlicenseAqualityDmaintenanceExposes two MCP tools (discover and execute) that enable agents to query an OpenAPI schema via natural language and execute matched API operations.2-
- AlicenseNot gradedqualityCmaintenanceAn MCP server that exposes Nexthink Digital Employee Experience (DEX) telemetry and automation to LLM agents, enabling execution of saved NQL queries, bulk async data exports, remote actions, and workflow triggers against Nexthink Infinity via secure OAuth2/bearer/basic authentication.9 npm1MIT