Heatmap Visualization
by SCStelz
Use this skill when asked to create heatmaps, visualize patterns over time, show activity grids, or display aggregated data in a matrix format. Triggers on keywords like "heatmap", "show heatmap", "visualize patterns", "activity grid", "time-based visualization", or when analyzing attack patterns, sign-in activity, or event distributions by time period.
Skill Details
Repository Files
1 file in this skill directory
name: heatmap-visualization description: Use this skill when asked to create heatmaps, visualize patterns over time, show activity grids, or display aggregated data in a matrix format. Triggers on keywords like "heatmap", "show heatmap", "visualize patterns", "activity grid", "time-based visualization", or when analyzing attack patterns, sign-in activity, or event distributions by time period.
Heatmap Visualization Skill
Purpose
Generate interactive heatmap visualizations from Microsoft Sentinel data using the Sentinel Heatmap MCP App. Heatmaps display aggregated data in a row/column grid with color-coded intensity, ideal for identifying patterns across time periods, comparing entities, or spotting anomalies.
π TABLE OF CONTENTS
- Quick Start - Minimal example to get started
- MCP Tool Reference - Parameters and schemas
- KQL Query Patterns - Ready-to-use queries by scenario
- Enrichment Integration - Adding threat intel drill-down
- Color Scale Guide - Choosing the right colors
- Examples - End-to-end workflows
Quick Start
Minimal Heatmap (3 Steps)
# 1. Query Sentinel for aggregated data
mcp_sentinel-data_query_lake({
"query": "SigninLogs | where TimeGenerated > ago(24h) | summarize value = count() by row = AppDisplayName, column = format_datetime(bin(TimeGenerated, 1h), 'HH:mm') | project row, column, value"
})
# 2. Display heatmap
mcp_sentinel-heat_show-signin-heatmap({
"data": [<query results>],
"title": "Sign-Ins by Application (Last 24h)",
"rowLabel": "Application",
"colLabel": "Hour (UTC)",
"valueLabel": "Sign-ins",
"colorScale": "green-red"
})
MCP Tool Reference
Tool: mcp_sentinel-heat_show-signin-heatmap
| Parameter | Required | Type | Description |
|---|---|---|---|
data |
β | array | Array of {row, column, value} objects |
title |
β | string | Title displayed above heatmap |
rowLabel |
β | string | Label for row axis (e.g., "IP Address") |
colLabel |
β | string | Label for column axis (e.g., "Hour") |
valueLabel |
β | string | Label for cell values (e.g., "Events") |
colorScale |
β | string | green-red, blue-red, or blue-yellow |
enrichment |
β | array | IP enrichment data for click-to-expand panels |
Data Schema
{
"data": [
{"row": "192.168.1.1", "column": "10:00", "value": 45},
{"row": "192.168.1.1", "column": "11:00", "value": 62},
{"row": "10.0.0.5", "column": "10:00", "value": 128}
]
}
Enrichment Schema (Optional)
{
"enrichment": [
{
"ip": "80.94.95.83",
"city": "TimiΘoara",
"country": "RO",
"org": "AS204428 SS-Net",
"is_vpn": false,
"abuse_confidence_score": 100,
"total_reports": 975,
"last_reported": "2026-01-29",
"threat_categories": ["RDP Brute-Force", "Hacking", "Port Scan"]
}
]
}
KQL Query Patterns
All queries must return row, column, value columns.
Pattern 1: Activity by Entity and Hour
<Table>
| where TimeGenerated between (datetime(<start>) .. datetime(<end>))
| summarize value = count()
by row = <entity_field>,
column = format_datetime(bin(TimeGenerated, 1h), "HH:mm")
| project row, column, value
| order by column asc
Pattern 2: Activity by Entity and Day
<Table>
| where TimeGenerated > ago(30d)
| summarize value = count()
by row = <entity_field>,
column = format_datetime(bin(TimeGenerated, 1d), "yyyy-MM-dd")
| project row, column, value
| order by column asc
Pattern 3: Cross-Tabulation (Two Dimensions)
<Table>
| where TimeGenerated > ago(7d)
| summarize value = count()
by row = <dimension1>,
column = <dimension2>
| project row, column, value
| order by value desc
Scenario-Specific KQL Queries
Scenario: Sign-In Activity by Application and Hour
SigninLogs
| where TimeGenerated > ago(24h)
| where ResultType == 0 // Successful sign-ins
| summarize value = count()
by row = AppDisplayName,
column = format_datetime(bin(TimeGenerated, 1h), "HH:mm")
| project row, column, value
| order by column asc
Recommended: colorScale: "green-red" (activity = good)
Scenario: Failed Sign-Ins by IP and Hour
SigninLogs
| where TimeGenerated > ago(24h)
| where ResultType != 0 // Failed sign-ins
| summarize value = count()
by row = IPAddress,
column = format_datetime(bin(TimeGenerated, 1h), "HH:mm")
| project row, column, value
| order by column asc, value desc
| take 500 // Limit to top patterns
Recommended: colorScale: "blue-red" (failures = threat)
Scenario: Honeypot Attack Patterns (SecurityEvent)
let start = datetime(<StartDate>);
let end = datetime(<EndDate>);
let honeypot = '<HONEYPOT_NAME>';
SecurityEvent
| where TimeGenerated between (start .. end)
| where Computer contains honeypot
| where EventID in (4625, 4771, 4776) // Failed auth events
| where isnotempty(IpAddress) and IpAddress != "-" and IpAddress != "127.0.0.1"
| summarize value = count()
by row = IpAddress,
column = format_datetime(bin(TimeGenerated, 1h), "HH:mm")
| project row, column, value
| order by column asc, value desc
Recommended: colorScale: "blue-red" (attacks = threat)
Scenario: Web Attack Patterns (W3CIISLog)
let start = datetime(<StartDate>);
let end = datetime(<EndDate>);
W3CIISLog
| where TimeGenerated between (start .. end)
| where tolong(scStatus) >= 400 // HTTP errors
| where cIP != "127.0.0.1"
| summarize value = count()
by row = cIP,
column = format_datetime(bin(TimeGenerated, 1h), "HH:mm")
| project row, column, value
| order by column asc, value desc
| take 300
Recommended: colorScale: "blue-red"
Scenario: Defender Alerts by Severity and Day
SecurityAlert
| where TimeGenerated > ago(30d)
| summarize value = count()
by row = AlertSeverity,
column = format_datetime(bin(TimeGenerated, 1d), "yyyy-MM-dd")
| project row, column, value
| order by column asc
Recommended: colorScale: "blue-yellow" (neutral overview)
Scenario: User Activity by Application
SigninLogs
| where TimeGenerated > ago(7d)
| where UserPrincipalName =~ '<UPN>'
| summarize value = count()
by row = AppDisplayName,
column = format_datetime(bin(TimeGenerated, 1d), "MM-dd")
| project row, column, value
| order by column asc
Recommended: colorScale: "green-red"
Scenario: Multi-Source Combined Heatmap
let start = datetime(<StartDate>);
let end = datetime(<EndDate>);
let honeypot = '<HONEYPOT_NAME>';
union
(SecurityEvent
| where TimeGenerated between (start .. end)
| where Computer contains honeypot
| where EventID in (4625, 4771, 4776)
| where isnotempty(IpAddress) and IpAddress != "-"
| extend Source = "RDP/SMB", IP = IpAddress),
(W3CIISLog
| where TimeGenerated between (start .. end)
| where Computer contains honeypot
| where tolong(scStatus) >= 400
| extend Source = "IIS", IP = cIP),
(DeviceNetworkEvents
| where TimeGenerated between (start .. end)
| where DeviceName contains honeypot
| where ActionType in ("ConnectionSuccess", "InboundConnectionAccepted")
| extend Source = "Network", IP = RemoteIP)
| where IP != "127.0.0.1" and IP != "::1"
| summarize value = count()
by row = strcat(IP, " (", Source, ")"),
column = format_datetime(bin(TimeGenerated, 1h), "HH:mm")
| project row, column, value
| order by column asc, value desc
Enrichment Integration
Adding Threat Intel Drill-Down
When displaying IP-based heatmaps, add enrichment data for click-to-expand threat panels:
Step 1: Extract unique IPs from your query results
Step 2: Enrich IPs using the enrichment script:
python enrich_ips.py 80.94.95.83 193.142.147.209 101.36.107.228
Step 3: Transform enrichment output to heatmap format:
enrichment_out = []
for e in enrichment_data:
threat_cats = []
for c in e.get('recent_comments', [])[:5]:
threat_cats.extend(c.get('categories', []))
enrichment_out.append({
'ip': e['ip'],
'city': e.get('city', 'Unknown'),
'country': e.get('country', '??'),
'org': e.get('org', 'Unknown'),
'is_vpn': e.get('is_vpn') or e.get('vpnapi_security_vpn', False),
'abuse_confidence_score': e.get('abuse_confidence_score', 0),
'total_reports': e.get('total_reports', 0),
'last_reported': e.get('recent_comments', [{}])[0].get('date', '')[:10],
'threat_categories': list(set(threat_cats))[:5]
})
Step 4: Include in heatmap call:
mcp_sentinel-heat_show-signin-heatmap({
"data": [...],
"enrichment": [<enrichment_out>],
...
})
Interactive Features with Enrichment
When enrichment is provided:
- Click any IP row β Opens threat intel panel showing:
- π Location (city, country)
- π’ Organization/ISP
- π·οΈ VPN/Proxy/Tor badges
- π AbuseIPDB confidence meter (0-100)
- π Total reports count
- π΄ Threat category tags
- Hover any cell β Tooltip with row, column, exact value
Color Scale Guide
| Scale | Low Value | High Value | Best For |
|---|---|---|---|
green-red |
Teal/Blue | Green | Positive activity (sign-ins, successful ops) |
blue-red |
Blue | Red | Threats/failures (attacks, errors, risks) |
blue-yellow |
Blue | Yellow | Neutral data (general distributions) |
Decision Tree
Is the data about threats/failures/attacks?
β YES: Use "blue-red" (red = danger)
β NO: Is high volume a positive indicator?
β YES: Use "green-red" (green = success)
β NO: Use "blue-yellow" (neutral)
Complete Examples
Example 1: Honeypot Attack Heatmap with Enrichment
# Query attack data
mcp_sentinel-data_query_lake({
"query": "SecurityEvent | where TimeGenerated between (datetime(<START_DATE>) .. datetime(<END_DATE>)) | where Computer contains '<HONEYPOT_SERVER>' | where EventID == 4625 | where IpAddress != '127.0.0.1' | summarize value = count() by row = IpAddress, column = format_datetime(bin(TimeGenerated, 1h), 'HH:mm') | project row, column, value | order by column asc, value desc | take 200"
})
# Enrich top IPs
python enrich_ips.py 80.94.95.83 193.142.147.209 101.36.107.228
# Display heatmap
mcp_sentinel-heat_show-signin-heatmap({
"data": [
{"row": "80.94.95.83", "column": "19:00", "value": 636},
{"row": "193.142.147.209", "column": "20:00", "value": 245},
...
],
"title": "Honeypot Attack Analysis - Click IP for Threat Intel",
"rowLabel": "Attacker IP",
"colLabel": "Hour (UTC)",
"valueLabel": "Failed Auth Attempts",
"colorScale": "blue-red",
"enrichment": [
{"ip": "80.94.95.83", "city": "TimiΘoara", "country": "RO", "org": "AS204428 SS-Net", "is_vpn": false, "abuse_confidence_score": 100, "total_reports": 975, "threat_categories": ["RDP Brute-Force", "Hacking"]},
{"ip": "193.142.147.209", "city": "Amsterdam", "country": "NL", "org": "AS213438 ColocaTel Inc.", "is_vpn": true, "abuse_confidence_score": 100, "total_reports": 30972, "threat_categories": ["SSH Brute-Force", "Port Scan"]}
]
})
Example 2: Sign-In Activity Overview
# Query sign-in data
mcp_sentinel-data_query_lake({
"query": "SigninLogs | where TimeGenerated > ago(24h) | where ResultType == 0 | summarize value = count() by row = AppDisplayName, column = format_datetime(bin(TimeGenerated, 1h), 'HH:mm') | project row, column, value | order by column asc"
})
# Display heatmap (no enrichment needed - not IP-based)
mcp_sentinel-heat_show-signin-heatmap({
"data": [
{"row": "Microsoft Teams", "column": "09:00", "value": 145},
{"row": "Outlook", "column": "09:00", "value": 312},
...
],
"title": "Sign-In Activity by Application (Last 24h)",
"rowLabel": "Application",
"colLabel": "Hour (UTC)",
"valueLabel": "Sign-ins",
"colorScale": "green-red"
})
When to Use Heatmaps
β Good Use Cases:
- Attack patterns over time (by hour/day)
- Comparing activity across entities (IPs, apps, users)
- Identifying peak activity periods
- Spotting anomalies in regular patterns
- Executive-friendly threat visualization
β Skip Heatmaps When:
- Fewer than 5 unique rows or columns (too sparse)
- Single-dimension data (use bar chart instead)
- Geographic data (use geomap skill instead)
- Real-time streaming data (heatmaps are for aggregated snapshots)
Last Updated: January 29, 2026
Related Skills
Xlsx
Comprehensive spreadsheet creation, editing, and analysis with support for formulas, formatting, data analysis, and visualization. When Claude needs to work with spreadsheets (.xlsx, .xlsm, .csv, .tsv, etc) for: (1) Creating new spreadsheets with formulas and formatting, (2) Reading or analyzing data, (3) Modify existing spreadsheets while preserving formulas, (4) Data analysis and visualization in spreadsheets, or (5) Recalculating formulas
Clickhouse Io
ClickHouse database patterns, query optimization, analytics, and data engineering best practices for high-performance analytical workloads.
Clickhouse Io
ClickHouse database patterns, query optimization, analytics, and data engineering best practices for high-performance analytical workloads.
Analyzing Financial Statements
This skill calculates key financial ratios and metrics from financial statement data for investment analysis
Data Storytelling
Transform data into compelling narratives using visualization, context, and persuasive structure. Use when presenting analytics to stakeholders, creating data reports, or building executive presentations.
Kpi Dashboard Design
Design effective KPI dashboards with metrics selection, visualization best practices, and real-time monitoring patterns. Use when building business dashboards, selecting metrics, or designing data visualization layouts.
Dbt Transformation Patterns
Master dbt (data build tool) for analytics engineering with model organization, testing, documentation, and incremental strategies. Use when building data transformations, creating data models, or implementing analytics engineering best practices.
Sql Optimization Patterns
Master SQL query optimization, indexing strategies, and EXPLAIN analysis to dramatically improve database performance and eliminate slow queries. Use when debugging slow queries, designing database schemas, or optimizing application performance.
Anndata
This skill should be used when working with annotated data matrices in Python, particularly for single-cell genomics analysis, managing experimental measurements with metadata, or handling large-scale biological datasets. Use when tasks involve AnnData objects, h5ad files, single-cell RNA-seq data, or integration with scanpy/scverse tools.
Xlsx
Spreadsheet toolkit (.xlsx/.csv). Create/edit with formulas/formatting, analyze data, visualization, recalculate formulas, for spreadsheet processing and analysis.
