Skip to main content
Glama
threatlocker-mcp

threatlocker-mcp

by Space-C0wboy

ThreatLocker MCP

PyPI version PyPI - Python Version License: MIT CI

threatlocker-mcp is a Model Context Protocol server that connects AI assistants such as Claude Desktop and Claude Code with the ThreatLocker Portal API. 57 tools — 44 generated directly from the official OpenAPI 3.0 spec plus 13 hand-written application / policy / audit-log management tools built from ThreatLocker's published API documentation — give your AI assistant programmatic access to computers, approvals, applications, policies, action logs, tags, maintenance mode, reports, and more, across single-org and parent/child tenant setups.

IMPORTANT

Unofficial project. This is an independent, community-built MCP server developed against ThreatLocker's published API documentation. It is not an official ThreatLocker product and is not affiliated with, endorsed by, or supported by ThreatLocker, Inc. "ThreatLocker" is a trademark of ThreatLocker, Inc. For official support of the ThreatLocker platform itself, contact ThreatLocker directly.

WARNING

Beta software — not yet recommended for production environments. This project is under active development. The tool surface and individual tool body shapes may still change between minor versions, and not every endpoint has been exhaustively exercised against every tenant configuration. Use against a lab or non-production tenant until you're confident in the behavior for your use case.

This server can also perform destructive actions against your ThreatLocker environment. Tools can enable/disable endpoint protection, approve security requests, modify tag membership, end active maintenance windows, approve storage devices, move computers between organizations, and (as of 0.3) create, change, delete and deploy Allowlisting applications and policies. A hallucinated tool argument from your AI assistant could alter your ThreatLocker configuration in ways that affect endpoint security.

Recommended posture:

  • Try the server against a non-production or lab tenant first.

  • Use a ThreatLocker API key scoped to the minimum permissions your use case requires.

  • Review every destructive tool call before allowing execution. Claude Desktop requires tool-call approval by default — keep that enabled.

  • Treat the API key with the same care as portal admin credentials, because functionally it is one.

  • The HTTP transport binds to 127.0.0.1 by default. Do not expose it to the public internet without adding authentication.

Tools

Area

Count

Capabilities

Computers

9

Search, get/edit details, enable/disable protection, update maintenance mode, baseline rescan, move between orgs, finish active maintenance

Approval Requests

11

Search, get by ID, count pending, get permit details, approve, reject, ignore, take ownership, storage approval read/permit, file download details

Application

11

Get by ID, get matching list, list available apps for permit-into, list apps for maintenance mode, research details; list apps (application_list), list file rules paged with hash-only / custom filters (application_files_list), create (application_insert), update name/description and add/remove file rules (application_update), bulk-add SHA256 rules (application_add_sha256_bulk), delete (application_delete)

Action Log

5

Search by parameters, get by ID, file history, file download details; action_log_search with explicit paging, fields projection and aggregate_by counts (server-side groupBys or client-side folder roll-up)

Maintenance Mode

4

Get schedule by computer, insert, end by ID, reschedule end time

Tag

3

Get by ID, dropdown options by org, update

System Audit

2

Search by parameters, health center

Computer Groups

2

Get groups with computers, dropdown by org

Policy

7

Get by ID; list/filter by applies-to, application, name, inactive (policy_list), create (policy_insert), update name/description/enabled/applies-to/applications/action (policy_update), set order (policy_set_order), delete (policy_delete), Deploy Policies (policies_deploy)

Online Devices

1

Get by parameters

Reports

1

Get by organization

Organization

1

list_organizations — discover org GUIDs this API key can target

All request bodies are typed Pydantic models (63 generated from the spec), so the AI assistant receives full schema validation and autocomplete. The wire format preserves the original camelCase field names expected by the API.

The application / policy management tools wrap endpoints that ThreatLocker documents in its PortalAPI knowledge-base articles rather than in the public Swagger document (Application/ApplicationInsert, ApplicationFile/*, Policy/PolicyInsert, Policy/PolicyUpdateById, Policy/PolicyGetByParameters, DeployPolicyQueue/DeployPolicies, ...). Field names are taken from those articles verbatim.

Write safety (application / policy tools)

Every tool that changes applications or policies follows the same rules:

Rule

Behaviour

dry_run defaults to true

The tool returns the exact request(s) it would send (method, path, body) plus the target org, and sends nothing. Pass dry_run=false to execute.

Explicit org for anything but the default

Writes go to THREATLOCKER_ORG_ID unless organization_id is given. Write tools do not accept override_organization_id; there is no silent fallback to another org.

confirm=true for destructive calls

policies_deploy, policy_delete, application_delete, and any application_update that removes rules refuse to run with dry_run=false unless confirm=true is also passed.

Read-modify-write

policy_update / policy_set_order read the policy first and resend every existing setting (the API resets omitted fields); application_update reads the app so an omitted description is preserved. The dry run shows exactly what was carried over.

Local audit log

Each executed write appends a JSON line (timestamp, tool, org, target id, method, path, outcome) to THREATLOCKER_AUDIT_LOG (default ~/.threatlocker-mcp/audit.jsonl). API keys, headers and request bodies are never written.

A rule for application_insert / application_update is a list of conditions, mirroring the portal: full_path, process_path, created_by and cert can be combined; hash (ThreatLocker hash) and sha256 are standalone. Exercise new write tools against a throwaway application in a non-production org first.

Related MCP server: GHL MCP Server

Quick Start

Install

uv tool install threatlocker-mcp

Using pip

pip install threatlocker-mcp

Configure

Set the required environment variables (or place them in a .env file in the directory where you launch the server):

export THREATLOCKER_API_KEY="your-api-key"
export THREATLOCKER_ORG_ID="your-default-org-guid"
export THREATLOCKER_BASE_URL="https://portalapi.h.threatlocker.com"

Variable

Required

Default

Description

THREATLOCKER_API_KEY

✅

—

API key from ThreatLocker Portal → Modules → API

THREATLOCKER_ORG_ID

✅

—

Default organization GUID. Find it in the portal URL after switching into the target org.

THREATLOCKER_BASE_URL

✅

—

Portal API base URL. Use the same subdomain letter shown in your portal (.h., .g., .e., etc.) — e.g. https://portalapi.h.threatlocker.com

THREATLOCKER_TIMEOUT

—

30

Per-request timeout in seconds

THREATLOCKER_AUDIT_LOG

—

~/.threatlocker-mcp/audit.jsonl

JSON-lines audit file for every executed application / policy write

LOG_LEVEL

—

INFO

Logging verbosity: DEBUG / INFO / WARNING / ERROR

MCP_HTTP_HOST

—

127.0.0.1

Bind host for the HTTP transport

MCP_HTTP_PORT

—

8765

Bind port for the HTTP transport

Run

threatlocker-mcp

By default the server runs in stdio mode (the transport MCP clients like Claude Desktop expect). For HTTP transport:

threatlocker-mcp --transport http --port 8765

Editor Integration

Claude Desktop with uvx (recommended)

Add the following block to your Claude Desktop configuration file:

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

{
  "mcpServers": {
    "threatlocker": {
      "command": "uvx",
      "args": [
        "threatlocker-mcp"
      ],
      "env": {
        "THREATLOCKER_API_KEY": "your-api-key",
        "THREATLOCKER_ORG_ID": "your-default-org-guid",
        "THREATLOCKER_BASE_URL": "https://portalapi.h.threatlocker.com"
      }
    }
  }
}

Fully quit Claude Desktop (tray icon → Quit on Windows; ⌘Q on macOS), then reopen it. uvx resolves and caches the package on first launch; subsequent launches are nearly instant.

Pinning to a specific version

"args": ["threatlocker-mcp@0.2.1"]

Forcing a refresh

"args": ["--refresh", "threatlocker-mcp"]

Multi-Organization Usage

Every tool accepts two optional parameters for targeting specific organizations in a parent/child tenant hierarchy:

  • organization_id — overrides the ManagedOrganizationId request header. When omitted, THREATLOCKER_ORG_ID is used.

  • override_organization_id — sets the OverrideManagedOrganizationId header for scenarios that require both headers simultaneously.

Finding child org GUIDs: Call list_organizations first — optionally with search_text to filter by display name — to enumerate every org this API key can target. Org GUIDs can also be read from the portal URL while switched into each child org.

Example Prompts

Investigate denied activity:

"Search the action log for any denied executions on hostname SRV-DB-01 in the last 24 hours."

→ Calls action_log_get_by_parameters_v2 with an ActionLogParamsDto.

Review pending approvals:

"Show me all pending approval requests for the Cloud Services org."

→ Calls approval_request_get_by_parameters with organization_id=<cloud-svc-guid>.

Approve a request:

"Approve request abc-123 at computer scope with the note 'verified vendor'."

→ Calls approval_request_permit_application with a PermitApplicationDto.

Schedule maintenance:

"Put workstation WS-FINANCE-04 into maintenance mode for the next two hours."

→ Calls maintenance_mode_insert with a MaintenanceModeInsertDto.

Manage tags:

"Add corporate-vpn.example.com to the existing 'Corporate VPN' network tag."

→ Calls tag_get_dropdown_options_by_organization_id and tag_update.

Add launcher hashes to an application:

"Add these 940 SHA256s to the 'Launcher' app in our lab org — show me the plan first."

→ Calls application_list to find the app, then application_add_sha256_bulk (dry run), then again with dry_run=false.

Create and order a policy:

"Create a disabled permit policy for app X on the Workstations group, put it above the default deny, then deploy."

→ Calls policy_insert, policy_set_order, and policies_deploy (each dry-run first; deploy needs confirm=true).

Summarise a week of denies without a 1 MB dump:

"Which policies produced the most denies last week, and which folders?"

→ Calls action_log_search with aggregate_by=["policyName"] and aggregate_by=["fullPathFolder"].

License

MIT — see LICENSE.

Available Tools

44 tools
action_log_get_all_for_file_history_v2A

Get All File History by hostname and fullpath NOTE: spec marks every parameter optional, but the API returns 417 'Missing Parameters. Unable to load details.' unless fullPath plus one of (hostname, computerId) is supplied.

Inputs: source_table_id, hostname, full_path, computer_id, +4 more.

action_log_get_by_id_v2D

Action Log: Get By Id V2

Inputs: e_action_log_id, source_table_id, add_to_application, get_all_parents, +3 more.

action_log_get_by_parameters_v2A

Get Action Logs By Parameters. NOTE: this endpoint runs in two modes depending on the usenewsearch header. The MCP defaults to usenewsearch=true (the new search path the portal SPA uses), which is the only mode that returns data. Required: sourceTableId (1=ActionLog, 2=DenyActionLog, 3=BaselineActionLog, 4=EventLogActionLog), startDate, endDate, and paramsFieldsDto (the MCP defaults this to []; the server returns HTTP 500 when the field is absent under the new search path). Omitting sourceTableId returns HTTP 500; omitting both date forms returns 417 'Invalid Date Range'. Pass usenewsearch=null to opt out into the legacy path -- but note the legacy path returns an empty body even when data exists, so this is only useful for back-compat probing.

Inputs: body (required), usenewsearch, organization_id, override_organization_id.

action_log_get_file_download_details_by_idD

Action Log: Get File Download Details By Id

Inputs: e_action_log_id, source_table_id, organization_id, override_organization_id.

application_get_by_idC

Get Application by Id.

Inputs: application_id, organization_id, override_organization_id.

application_get_for_application_optionsA

Load Application List custom + built-in applications available to permit a file into. Use this when the permit_application flow needs useExistingApplication: true -- i.e., adding the requested file to an app discovered through means other than application_get_matching_list. Filter by osType (1=Windows, 2=MAC, 3=Linux, 5=Windows XP), optional searchText to narrow by name, and includeBuiltIn to include master-org BUILT-IN apps. (Renamed from the KB's ApplicationGetListForAddToApplication.)

Inputs: body (required), organization_id, override_organization_id.

application_get_for_maintenance_modeA

Get Application Options for Maintenance Scheduling List applications eligible for use with a Maintenance Mode when processing an approval request. Filter by osType (1=Windows, 2=MAC, 3=Linux, 5=Windows XP). Maintenance Modes (Installation/Learning/Monitor) are selected on the permit_application body via policyConditions.ruleId (1/2/3 respectively).

Inputs: os_type, organization_id, override_organization_id.

application_get_matching_listD

Get Matching Applications

Inputs: body (required), organization_id, override_organization_id.

application_get_research_details_by_idA

Get Application Research Details by Id. Optional. Get ThreatLocker's research data (description, risks, mitigations) for an application before permitting it. Useful for decision support when the chosen matchingApplication or existingApplication is a sensitive built-in or unknown app.

Inputs: application_id, organization_id, override_organization_id.

approval_request_get_by_idA

Get Approval Request By ID NOTE: requestorReason is base64-encoded -- decode before display. approval_request_get_permit_application_by_id returns the same request with the reason already decoded under fileDetails.requestorReason, plus file/policy/ringfencing context.

Inputs: approval_request_id, organization_id, override_organization_id.

approval_request_get_by_parametersA

Approval Request: Get By Parameters NOTE: statusId is required (e.g. 1 for Pending). Calls without it return HTTP 500. Each result's requestorReason is base64-encoded -- decode before display. For the decoded reason plus richer file/policy context, follow up with approval_request_get_permit_application_by_id.

Inputs: body (required), organization_id, override_organization_id.

approval_request_get_countC

Get Approval Request Pending Count

Inputs: include_child_organizations, organization_id, override_organization_id.

approval_request_get_file_download_details_by_idC

Get File Download Details By Approval Request Id

Inputs: approval_request_id, organization_id, override_organization_id.

approval_request_get_permit_application_by_idC

Get Permit Application Details By Approval Request Id

Inputs: approval_request_id, organization_id, override_organization_id.

approval_request_get_storage_approval_by_idC

Get Storage Approval Request By Id

Inputs: approval_request_id, organization_id, override_organization_id.

approval_request_permit_applicationA

Approve Permit Application Request WORKFLOW: take_ownership -> get_permit_application_by_id -> application_get_matching_list -> permit_application. Start from the DTO returned by get_permit_application_by_id and modify the choices below. REQUIRED FIELDS (KB-documented, all must be present): approvalRequest.approvalRequestId; approvalRequest.json -- copy verbatim from get_permit_application_by_id (server uses it to reconstruct file/action context, omitting it causes silent failures); userinstance -- the portal shard ('h', 'g', etc.), parsed from the request's portalApiUrl subdomain; isFromApproval: true; hasOriginApprovalCenter: true; actionType (copy from request: 'elevate'/'execute'/'install'); osType (1=Windows, 2=Mac, 3=Linux, 5=WinXP); organizationId, computerId (copy from request); organizationIds -- list of parent org IDs above the request's org ([] for top-level); fileDetails.fullPath. APP SELECTION (set exactly ONE mode on matchingApplications): (a) PREFERRED -- use application_get_matching_list result. Prefer tenant-owned match (its organizationId equals the call's organizationId) over master-org/BUILT-IN (organizationName: "master"). Set useMatchingApplication: true, populate matchingApplication with the chosen result; set others false and their objects to null. The DTO's hasMatchingApplication flag is UNRELIABLE -- trust application_get_matching_list.hasMatching instead. *** CRITICAL -- BUILT-IN match REQUIRES entire-org scope. When the chosen match has organizationName: "master", you MUST set policyLevel.toEntireOrganization: true. Pairing a BUILT-IN with computer-scope returns HTTP 401 "Missing the '' permission" (misleading -- it's actually a body-shape error). Verified 2026-05-21. Tenant-owned matches and new apps use the default all-flags-false scope. (b) FALLBACK -- add to existing custom app (discover via application_get_for_application_options). Set useExistingApplication: true, populate existingApplication; others null. (c) LAST RESORT -- create new app. Set useNewApplication: true and newApplicationName to a non-null derived name (e.g. file stem title-cased: vlc.exe -> "VLC"). Null returns HTTP 417 'Must enter a name for a new application'. POLICY (policyConditions.ruleId): 0=manual rules, 1=Install Mode 1hr, 2=Learning Mode 1hr, 3=Monitor Mode 1hr. Set useExistingPolicy: true to reuse an existing policy (manualOptions then carries the rule criteria). SCOPE (policyLevel): default 'this computer' = ALL THREE flags false (toEntireOrganization/toComputerGroup/toComputer); scope is inferred from top-level computerId. Setting toComputer: true returns HTTP 417 'Provided applies to ID does not associate with a known OS type'. For computer group, set toComputerGroup: true and populate selectedComputerGroup (discover via computer_group_get_dropdown_by_organization_id). For entire-org, set toEntireOrganization: true. ACTION TYPE: for elevate set isElevationRequest: true and isExecutionRequest: false; for execute reverse. Both are spec-readOnly but MUST be sent matching the action. SHAPE: send null (not omit) for unused sub-objects -- matchingApplication, existingApplication, selectedComputerGroup, policyExpirationDate, elevationExpirationDate. Wrong shape = opaque HTTP 500. PERMISSIONS: API key user needs one of 'Approve for Entire Organization', 'Approve for Group', 'Approve for Single Computer', or 'Approve for Single Computer Application Only' in Administrators.

Inputs: body (required), organization_id, override_organization_id.

approval_request_permit_storage_approvalA

Approve Storage Request NOT YET LIVE-TESTED -- expect shape sensitivity similar to approval_request_permit_application. WORKFLOW: take_ownership -> get_storage_approval_by_id -> permit_storage_approval. Start from the DTO returned by approval_request_get_storage_approval_by_id and modify the choices below. LIKELY REQUIRED (by analogy with the application-permit flow): approvalRequest -- copy verbatim from get_storage_approval_by_id; json -- verbatim copy from the same response, used by the server to reconstruct the storage-request context. DEVICE / SCOPE FLAGS (set exactly one mode): addDeviceToExisting -- add the storage device to an existing storage policy (populate existingStoragePolicy); deviceExists -- the device is already known to ThreatLocker; allStorageDevices -- apply to all storage devices in scope; allFilePaths -- apply to all paths rather than just selectedPath; allUserGroups -- apply to all users/groups rather than the populated usersList/userGroups. Set unused companion objects (existingStoragePolicy, newStorageDevice) to null, not omitted. EXPIRATION: expirationDate is ISO 8601 UTC; null = permanent. RESPONSE: responseSubject and responseReason are shown to the requester; notifyOnResponse controls whether they're emailed. If the server returns HTTP 401 "Missing the '' permission" (empty interpolation), suspect body-shape rather than permissions -- same root cause as the application-permit flow.

Inputs: body (required), organization_id, override_organization_id.

approval_request_update_for_ignoreC

Ignore Approval Request

Inputs: body (required), organization_id, override_organization_id.

approval_request_update_for_rejectC

Reject Approval Request

Inputs: body (required), organization_id, override_organization_id.

approval_request_update_for_take_ownershipC

Take Ownership of Approval Request

Inputs: body (required), organization_id, override_organization_id.

computer_disable_protectionC

Disable Computer Protection

Inputs: body (required), organization_id, override_organization_id.

computer_enable_protectionD

Computer Enable Protection

Inputs: body (required), organization_id, override_organization_id.

computer_get_by_all_parametersC

Load Computers By All Parameters

Inputs: body (required), organization_id, override_organization_id.

computer_get_for_edit_by_idC

Get Computer Information By Id.

Inputs: computer_id, organization_id, override_organization_id.

computer_group_get_dropdown_by_organization_idC

Get Computer Groups by OrganizationId

Inputs: computer_group_o_s_type_id, computer_o_s_type, hide_globals, organization_id, +1 more.

computer_group_get_group_and_computerA

Get Groups and Computer NOTE: this endpoint can return very large payloads (>100KB for a single populated group) when called without scoping. Pass a specific computerGroupId and set only the include_* flags you actually need; unscoped calls may exceed downstream output limits.

Inputs: computer_group_id, o_s_type, include_global, include_all_policies, +11 more.

computer_move_to_other_organizationD

Move Computer

Inputs: body (required), organization_id, override_organization_id.

computer_update_baseline_rescanD

Update Baseline Rescan Computer

Inputs: body (required), organization_id, override_organization_id.

computer_update_for_editC

Update Computer

Inputs: body (required), organization_id, override_organization_id.

computer_update_maintenance_modeC

Updates a device's maintenance mode settings.

Inputs: body (required), organization_id, override_organization_id.

computer_update_to_finish_maintenance_modeA

End Maintenance Mode Ends ACTIVE maintenance mode on a specific computer immediately. Distinct from maintenance_mode_end_by_id, which ends a SCHEDULED maintenance window (in progress or not) identified by maintenanceModeId. Use this when you have a computerId and want enforcement re-enabled now. WARNING: may break in-progress installs.

Inputs: body (required), organization_id, override_organization_id.

list_organizationsA

Get Organizations For Move Computers Returns the organizations the current API key can target. Use this FIRST to discover org GUIDs to pass as organization_id to other tools. Despite the path name (the endpoint also feeds the portal's 'move computers' org picker), the result is the canonical list of accessible orgs for this key. searchText filters by display name; pass an empty string for the full list.

Inputs: search_text, organization_id, override_organization_id.

maintenance_mode_end_by_idC

End Maintenance Schedule

Inputs: body (required), organization_id, override_organization_id.

maintenance_mode_get_by_computer_idC

Get Maintenance Schedule By Computer Id

Inputs: computer_id, organization_id, override_organization_id.

maintenance_mode_insertC

Add to Maintenance Schedule

Inputs: body (required), organization_id, override_organization_id.

maintenance_mode_update_end_date_time_for_specific_dateA

Updated Maintenance Mode End Date Time. Reschedules the end time of an existing maintenance window for a specific computer without terminating it. Pass the new maintenanceEndDate (ISO 8601 UTC). To END maintenance immediately use computer_update_to_finish_maintenance_mode (by computer) or maintenance_mode_end_by_id (by maintenance schedule).

Inputs: body (required), organization_id, override_organization_id.

online_devices_get_by_parametersC

View Online Devices

Inputs: page_number, page_size, organization_id, override_organization_id.

policy_get_by_idC

Get Policy by Id.

Inputs: policy_id, organization_id, override_organization_id.

report_get_by_organization_idB

Get report(s) by organization id.

Inputs: organization_id, override_organization_id.

system_audit_get_by_parametersC

Retrieves System Audit records based on specified parameters.

Inputs: body (required), organization_id, override_organization_id.

system_audit_get_for_health_centerB

Retrieves System Audit data for the Health Center, specifically focused on login attempts.

Inputs: body (required), organization_id, override_organization_id.

tag_get_by_idC

Get Tag by Id.

Inputs: tag_id, organization_id, override_organization_id.

tag_get_dropdown_options_by_organization_idC

Get Tag Dropdown Options.

Inputs: include_built_ins (required), tag_type (required), include_network_tag_in_master (required), organization_id, +1 more.

tag_updateA

Update Tag. Updates an existing tag. tagId (spec-nullable) must be a valid existing tag GUID; passing an empty or omitted tagId may cause the server to interpret the request as a new-tag creation. Use tag_get_dropdown_options_by_organization_id to discover existing tag GUIDs first. tagType enum (verify against tenant): 1=Computer tag, 2=Application tag, 3=Network tag. Sending one of tagItemsText / tagItemsIPv4 / tagItemsIPv6 replaces (not merges) that list for the tag. NOT YET LIVE-TESTED -- verify behaviour against the dev tenant before relying on it.

Inputs: body (required), organization_id, override_organization_id.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    C2.5/5.0

    Scored across 44 tools

    Disambiguation4/5

    Most tools target distinct resources and actions, though a few overlap (e.g., two maintenance-ending tools). Descriptions generally clarify differences.

    Naming Consistency4/5

    Tool names follow a consistent verb_noun snake_case pattern with occasional version suffixes. Minor deviations in length but pattern is predictable.

    Tool Count3/5

    44 tools is on the high side, likely justified by the breadth of ThreatLocker's features, but still borders on overwhelming without clear organization.

    Completeness3/5

    Covers many domains (logs, approvals, computers, maintenance) but lacks CRUD operations for policies, organizations, or deletions, leaving notable gaps.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • F
      license
      A
      quality
      C
      maintenance
      An MCP server that connects AI assistants to the NinjaOne remote monitoring and management platform via the REST API v2. It provides tools for device inventory, organization management, alert handling, maintenance scheduling, and automated job execution.
      22
      1
      -
    • A
      license
      B
      quality
      D
      maintenance
      A comprehensive MCP server that connects AI assistants to GoHighLevel CRM, enabling management of contacts, conversations, calendars, pipelines, payments, and more through 60+ tools.
      64
      40 npm
      1
      MIT
    • A
      license
      A
      quality
      B
      maintenance
      MCP server for interacting with the ThreatLocker Portal API, enabling querying of computers, applications, policies, audit logs, and more through AI assistants.
      18
      3
      GPL 3.0