Query Details

Agent MCP Server Endpoints Matching Threat Intel

Query

let TI =
    ThreatIntelIndicators
    | where TimeGenerated > ago(30d)
    | summarize arg_max(TimeGenerated, *)
        by WorkspaceId, Id, ObservableKey, ObservableValue
    | where IsActive == true and IsDeleted == false
    | where coalesce(Revoked, false) == false
    | where isnull(ValidFrom) or ValidFrom <= now()
    | where isnull(ValidUntil) or ValidUntil > now()
    | where ObservableKey in ('url:value', 'domain-name:value')
    | extend LookupType = ObservableKey,
             LookupValue = iff(
                 ObservableKey == 'domain-name:value',
                 tolower(ObservableValue),
                 ObservableValue)
    | summarize IndicatorCount = count(),
                MaxConfidence = max(Confidence)
        by LookupType, LookupValue;
AgentsInfo
| where TimeGenerated > ago(30d)
| summarize arg_max(TimeGenerated, *) by AgentId
| mv-expand McpServer = McpServers
| extend McpServer = parse_json(tostring(McpServer))
| extend McpServerName = tostring(McpServer.name),
         McpServerType = tostring(McpServer.type),
         McpServerEndpoint = tostring(McpServer.endpoint)
| where McpServerEndpoint matches regex @'^https?://'
| distinct McpServerName, McpServerType, McpServerEndpoint, AgentId
| summarize AgentCount = count()
    by McpServerName, McpServerType, McpServerEndpoint
| extend McpHost = tolower(tostring(parse_url(McpServerEndpoint).Host))
| mv-expand LookupType = dynamic(['url:value', 'domain-name:value'])
    to typeof(string)
| extend LookupValue = iff(
    LookupType == 'url:value', McpServerEndpoint, McpHost)
| join kind=leftouter TI on LookupType, LookupValue
| summarize TIHits = sum(coalesce(IndicatorCount, 0)),
            MatchTypes = make_set_if(LookupType, isnotnull(IndicatorCount)),
            MaxConfidence = max(MaxConfidence)
    by McpServerName, McpServerType, McpServerEndpoint, AgentCount
| extend TIStatus = iff(
    TIHits > 0, 'TI-hit – check', 'No TI-hit')
| order by TIHits desc, AgentCount desc

About this query

Explanation

This query is designed to identify potential security threats by comparing the MCP (Model Context Protocol) servers used by AI agents in a network against known threat intelligence indicators. Here's a simplified breakdown of what the query does:

  1. Threat Intelligence Preparation:

    • It creates a list of threat indicators (URLs and domain names) from the last 30 days that are active, not deleted, and valid.
    • It summarizes these indicators by type and value, counting how many times each appears and noting the highest confidence score.
  2. Agent Information Processing:

    • It gathers information about AI agents and their configured MCP servers from the last 30 days.
    • For each agent, it examines the latest configuration and expands the list of MCP servers to evaluate each one individually.
    • It focuses only on servers with HTTP or HTTPS endpoints.
  3. Matching Against Threat Intelligence:

    • For each MCP server, it extracts the host name from the endpoint and checks both the full endpoint and the host name against the threat intelligence list.
    • It uses a left outer join to ensure all MCP servers are included in the results, even if there's no match with the threat intelligence.
  4. Results Compilation:

    • The query counts how many threat intelligence hits each server has and lists the types of matches and the highest confidence score.
    • It orders the results by the number of threat intelligence hits and the number of agents using each server, prioritizing servers that are widely used or clearly flagged.
  5. Output:

    • Each server is marked as either having a threat intelligence hit (requiring manual review) or not.
    • The results help prioritize which servers to investigate further based on their threat intelligence hits and usage.

Overall, this query helps security analysts identify and prioritize potential threats by correlating AI agent server configurations with known threat indicators.