Kusto and Log Analytics MCP server help you execute a KQL (Kusto Query Language) query within an AI prompt, analyze, and visualize the data.
SaferSkills independently audited Mcp Kql Server (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
mcp-name: io.github.4R9UN/mcp-kql-server
AI-Powered KQL Query Execution with Natural Language to KQL (NL2KQL) Conversion and Execution
A Model Context Protocol (MCP) server that transforms natural language questions into optimized KQL queries with intelligent schema discovery, AI-powered caching, and seamless Azure Data Explorer integration. Simply ask questions in plain English and get instant, accurate KQL queries with context-aware results.
Latest Version: v2.1.4 - Canonical schema type normalization for sharper NL2KQL accuracy, credential redaction in logs, leaner dependencies, and a single-source package version.
<!-- Badges Section -->
Watch a quick demo of the MCP KQL Server in action:
graph TD
A[👤 User Submits KQL Query] --> B{🔍 Query Validation}
B -->|❌ Invalid| C[📝 Syntax Error Response]
B -->|✅ Valid| D[🧠 Load Schema Context]
D --> E{💾 Schema Cache Available?}
E -->|✅ Yes| F[⚡ Load from Memory]
E -->|❌ No| G[🔍 Discover Schema]
F --> H[🎯 Execute Query]
G --> I[💾 Cache Schema + AI Context]
I --> H
H --> J{🎯 Query Success?}
J -->|❌ Error| K[🚨 Enhanced Error Message]
J -->|✅ Success| L[📊 Process Results]
L --> M[🎨 Generate Visualization]
M --> N[📤 Return Results + Context]
K --> O[💡 AI Suggestions]
O --> N
style A fill:#4a90e2,stroke:#2c5282,stroke-width:2px,color:#ffffff
style B fill:#7c7c7c,stroke:#4a4a4a,stroke-width:2px,color:#ffffff
style C fill:#e74c3c,stroke:#c0392b,stroke-width:2px,color:#ffffff
style D fill:#8e44ad,stroke:#6a1b99,stroke-width:2px,color:#ffffff
style E fill:#7c7c7c,stroke:#4a4a4a,stroke-width:2px,color:#ffffff
style F fill:#27ae60,stroke:#1e8449,stroke-width:2px,color:#ffffff
style G fill:#f39c12,stroke:#d68910,stroke-width:2px,color:#ffffff
style H fill:#2980b9,stroke:#1f618d,stroke-width:2px,color:#ffffff
style I fill:#f39c12,stroke:#d68910,stroke-width:2px,color:#ffffff
style J fill:#7c7c7c,stroke:#4a4a4a,stroke-width:2px,color:#ffffff
style K fill:#e74c3c,stroke:#c0392b,stroke-width:2px,color:#ffffff
style L fill:#27ae60,stroke:#1e8449,stroke-width:2px,color:#ffffff
style M fill:#8e44ad,stroke:#6a1b99,stroke-width:2px,color:#ffffff
style N fill:#27ae60,stroke:#1e8449,stroke-width:2px,color:#ffffff
style O fill:#f39c12,stroke:#d68910,stroke-width:2px,color:#ffffffThe schema memory flow is integrated into query execution, but it now reuses existing cached schema before attempting live discovery. If a table schema is already available in CAG/schema memory, the server will use that cached schema instead of re-indexing it.
graph TD
A[👤 User Requests Schema Discovery] --> B[🔗 Connect to Cluster]
B --> C[📂 Enumerate Databases]
C --> D[📋 Discover Tables]
D --> E[🔍 Get Table Schemas]
E --> F[🤖 AI Analysis]
F --> G[📝 Generate Descriptions]
G --> H[💾 Store in Memory]
H --> I[📊 Update Statistics]
I --> J[✅ Return Summary]
style A fill:#4a90e2,stroke:#2c5282,stroke-width:2px,color:#ffffff
style B fill:#8e44ad,stroke:#6a1b99,stroke-width:2px,color:#ffffff
style C fill:#f39c12,stroke:#d68910,stroke-width:2px,color:#ffffff
style D fill:#2980b9,stroke:#1f618d,stroke-width:2px,color:#ffffff
style E fill:#7c7c7c,stroke:#4a4a4a,stroke-width:2px,color:#ffffff
style F fill:#e67e22,stroke:#bf6516,stroke-width:2px,color:#ffffff
style G fill:#8e44ad,stroke:#6a1b99,stroke-width:2px,color:#ffffff
style H fill:#f39c12,stroke:#d68910,stroke-width:2px,color:#ffffff
style I fill:#2980b9,stroke:#1f618d,stroke-width:2px,color:#ffffff
style J fill:#27ae60,stroke:#1e8449,stroke-width:2px,color:#ffffffaz login)#### From Source
git clone https://github.com/4R9UN/mcp-kql-server.git && cd mcp-kql-server && pip install -e .pip install mcp-kql-serverThat's it! The server automatically:
%APPDATA%\KQL_MCP (Windows) or ~/.local/share/KQL_MCP (Linux/Mac)One-time install (any platform): ``bash pip install --upgrade mcp-kql-server`After install, configure your MCP client to launch the server via the Python module entry point:python -m mcp_kql_server. This works on every platform where Python is onPATHand does not depend on the location of themcp-kql-serverconsole script. (The console script is still installed bypip` and remains supported for backward compatibility — see the alternative snippets below.)
Add to your Claude Desktop MCP settings file (mcp_settings.json):
Location:
%APPDATA%\Claude\mcp_settings.json~/Library/Application Support/Claude/mcp_settings.json~/.config/Claude/mcp_settings.json{
"mcpServers": {
"mcpKqlServer": {
"type": "stdio",
"command": "python",
"args": ["-m", "mcp_kql_server"]
}
}
}<details> <summary>Alternatives: platform-stable launchers or the installed console script</summary>
Windows (the py launcher is commonly available as py; use Get-Command py if you need its full path):
{
"mcpServers": {
"mcpKqlServer": {
"type": "stdio",
"command": "py",
"args": ["-3", "-m", "mcp_kql_server"]
}
}
}On macOS / Linux replace "py" with "python3" and drop the "-3" arg.
</details>
Add to your VSCode MCP configuration:
Settings.json location:
%APPDATA%\Code\User\mcp.json~/Library/Application Support/Code/User/mcp.json~/.config/Code/User/mcp.json{
"servers": {
"mcpKqlServer": {
"type": "stdio",
"command": "py",
"args": ["-3", "-m", "mcp_kql_server", "--transport", "stdio"],
"timeout": 300000,
"env": {
"FASTMCP_TRANSPORT": "stdio",
"MCP_KQL_AUTH_ON_STARTUP": "false",
"MCP_KQL_CHECK_FOR_UPDATES": "false",
"MCP_KQL_DEFER_AUTH": "1",
"MCP_KQL_SKIP_STARTUP_VERSION_CHECK": "1",
"MCP_KQL_AUTH_CHECK_TIMEOUT_SECONDS": "10",
"MCP_KQL_AUTH_LOGIN_TIMEOUT_SECONDS": "120",
"MCP_KQL_SQLITE_BUSY_TIMEOUT_MS": "30000"
}
}
}
}If VS Code logs `spawn ...PythonNNN/python.exe ENOENT`, the Python extension is substituting a cached interpreter path for"python". Switch to"py"(Windows) /"python3"(macOS/Linux), or to the"mcp-kql-server"console script thatpip installdrops onPATH. See docs/troubleshooting.md for full details.
Windows tip: usepy -3 -m mcp_kql_serverso VS Code does not need a user-specific Python path. If you must use a full path locally, keep it in your privatemcp.json, not in shared documentation.
If the server starts but VS Code still shows no tools, runMCP: Reset Cached Tools, thenMCP: Reset Trust, and restart the server fromMCP: List Servers. VS Code stores trust and cached tools separately frommcp.json, so a previous failed launch can keep the old empty state until you reset it.
Use shared HTTP when VS Code, GitHub Copilot CLI, agents, or other MCP clients should connect to one persistent MCP KQL server process.
Start the server:
python -m mcp_kql_server --transport http --host 127.0.0.1 --port 8000 --http-path /mcp --stateless-httpClient configuration:
{
"servers": {
"mcpKqlServer": {
"type": "http",
"url": "http://127.0.0.1:8000/mcp"
}
}
}| Option or environment variable | Purpose | Default |
|---|---|---|
--transport, FASTMCP_TRANSPORT | stdio, http, streamable-http, or sse | stdio |
--host, FASTMCP_HOST | HTTP bind host | 127.0.0.1 |
--port, FASTMCP_PORT | HTTP bind port | 8000 |
--http-path, FASTMCP_STREAMABLE_HTTP_PATH | Streamable HTTP endpoint path | /mcp |
--stateless-http, FASTMCP_STATELESS_HTTP | Stateless HTTP mode for shared deployments | false |
--auth-on-startup, MCP_KQL_AUTH_ON_STARTUP | Check Azure CLI auth before startup | false |
--check-updates, MCP_KQL_CHECK_FOR_UPDATES | Check PyPI for package updates before startup | false |
MCP_KQL_AUTH_CHECK_TIMEOUT_SECONDS | Azure CLI auth check timeout | 10 |
MCP_KQL_AUTH_LOGIN_TIMEOUT_SECONDS | Interactive Azure login timeout | 120 |
MCP_KQL_SQLITE_BUSY_TIMEOUT_MS | SQLite busy timeout for concurrent local MCP instances | 30000 |
Ask or Add to your Roo-code Or Cline MCP settings:
MCP Settings location:
mcp_settings.json{
"mcp-kql-server": {
"type": "stdio",
"command": "python",
"args": ["-m", "mcp_kql_server"],
"alwaysAllow": []
}
}For any MCP-compatible application:
# Preferred: invoke as a Python module (cross-platform)
python -m mcp_kql_server
# Platform-stable launchers (recommended if `python` is ambiguous on PATH)
py -3 -m mcp_kql_server # Windows
python3 -m mcp_kql_server # macOS / Linux
# Equivalent console script installed by pip
mcp-kql-server
# Shared HTTP mode for multiple clients
python -m mcp_kql_server --transport http --host 127.0.0.1 --port 8000 --http-path /mcp --stateless-http
# Server provides these tools:
# - execute_kql_query: Execute KQL or generate KQL from natural language
# - kql_schema_memory: Discover, cache, and inspect cluster schemasaz loginpython -m mcp_kql_serverTo inspect the installed server version and runtime defaults:
python -m mcp_kql_server --info --jsonThe server starts immediately with:
%APPDATA%\KQL_MCP\cluster_memoryThe server provides two main tools:
####execute_kql_query- Execute KQL queries or generate KQL from natural language ####kql_schema_memory- Discover, refresh, and inspect cached cluster schemas
Ask your MCP client (like Claude):
"Execute this KQL query against the help cluster: cluster('help.kusto.windows.net').database('Samples').StormEvents | take 10 and summarize the result and give me high level insights "Ask your MCP client:
"Query the Samples database in the help cluster to show me the top 10 states by storm event count, include visualization"
Ask your MCP client:
"Discover and cache the schema for the help.kusto.windows.net cluster, then tell me what databases and tables are available"
Ask your MCP client:
"Using the StormEvents table in the Samples database on help cluster, show me all tornado events from 2007 with damage estimates over $1M"
Ask your MCP client:
"Analyze storm events by month for the year 2007 in the StormEvents table, group by event type and show as a visualization"
%%{init: {'theme':'dark', 'themeVariables': {
'primaryColor':'#1a1a2e',
'primaryTextColor':'#00d9ff',
'primaryBorderColor':'#00d9ff',
'secondaryColor':'#16213e',
'secondaryTextColor':'#c77dff',
'secondaryBorderColor':'#c77dff',
'tertiaryColor':'#0f3460',
'tertiaryTextColor':'#ffaa00',
'tertiaryBorderColor':'#ffaa00',
'lineColor':'#00d9ff',
'textColor':'#ffffff',
'mainBkg':'#0a0e27',
'nodeBorder':'#00d9ff',
'clusterBkg':'#16213e',
'clusterBorder':'#9d4edd',
'titleColor':'#00ffff',
'edgeLabelBackground':'#1a1a2e',
'fontFamily':'Inter, Segoe UI, sans-serif',
'fontSize':'16px',
'flowchart':{'nodeSpacing':60, 'rankSpacing':80, 'curve':'basis', 'padding':20}
}}}%%
graph LR
Client["🖥️ MCP Client<br/><b>Claude / AI / Custom</b><br/>─────────<br/>Natural Language<br/>Interface"]
subgraph Server["🚀 MCP KQL Server"]
direction TB
FastMCP["⚡ FastMCP<br/>Framework<br/>─────────<br/>MCP Protocol<br/>Handler"]
NL2KQL["🧠 NL2KQL<br/>Engine<br/>─────────<br/>AI Query<br/>Generation"]
Executor["⚙️ Query<br/>Executor<br/>─────────<br/>Validation &<br/>Execution"]
Memory["💾 Schema<br/>Memory<br/>─────────<br/>AI Cache"]
FastMCP --> NL2KQL
NL2KQL --> Executor
Executor --> Memory
Memory --> Executor
end
subgraph Azure["☁️ Azure Services"]
direction TB
ADX["📊 Azure Data<br/>Explorer<br/>─────────<br/><b>Kusto Cluster</b><br/>KQL Engine"]
Auth["🔐 Azure<br/>Identity<br/>─────────<br/>Device Code<br/>CLI Auth"]
end
%% Client to Server
Client ==>|"📡 MCP Protocol<br/>stdio or streamable HTTP"| FastMCP
%% Server to Azure
Executor ==>|"🔍 Execute KQL<br/>Query & Analyze"| ADX
Executor -->|"🔐 Authenticate"| Auth
Memory -.->|"📥 Fetch Schema<br/>On Demand"| ADX
%% Styling - Using cyberpunk palette
style Client fill:#1a1a2e,stroke:#00d9ff,stroke-width:4px,color:#00ffff
style FastMCP fill:#16213e,stroke:#c77dff,stroke-width:3px,color:#c77dff
style NL2KQL fill:#1a1a40,stroke:#ffaa00,stroke-width:3px,color:#ffaa00
style Executor fill:#16213e,stroke:#9d4edd,stroke-width:3px,color:#9d4edd
style Memory fill:#0f3460,stroke:#00d9ff,stroke-width:3px,color:#00d9ff
style ADX fill:#1a1a2e,stroke:#ff6600,stroke-width:4px,color:#ff6600
style Auth fill:#16213e,stroke:#00ffff,stroke-width:2px,color:#00ffff
style Server fill:#0a0e27,stroke:#9d4edd,stroke-width:3px,stroke-dasharray: 5 5
style Azure fill:#0a0e27,stroke:#ff6600,stroke-width:3px,stroke-dasharray: 5 5Report Generated by MCP-KQL-Server | ⭐ Star this repo on GitHub
Ready to deploy MCP KQL Server to Azure for production use? We provide comprehensive deployment automation for Azure Container Apps with enterprise-grade security and scalability.
For complete deployment instructions, architecture details, and troubleshooting:
👉 [View Production Deployment Guide](./deployment/README.md)
The guide includes:
# PowerShell (Windows)
cd deployment
.\deploy.ps1 -SubscriptionId "YOUR_SUB_ID" -ResourceGroupName "mcp-kql-prod-rg" -ClusterUrl "https://yourcluster.region.kusto.windows.net"
# Bash (Linux/Mac/WSL)
cd deployment
./deploy.sh --subscription "YOUR_SUB_ID" --resource-group "mcp-kql-prod-rg" --cluster-url "https://yourcluster.region.kusto.windows.net"mcp-kql-server/
├── mcp_kql_server/
│ ├── __init__.py # Package initialization
│ ├── mcp_server.py # Main MCP server implementation
│ ├── execute_kql.py # KQL query execution logic
│ ├── memory.py # Advanced memory management
│ ├── kql_auth.py # Azure authentication
│ ├── utils.py # Utility functions
│ └── constants.py # Configuration constants
├── docs/ # Documentation
├── Example/ # Usage examples
├── pyproject.toml # Project configuration
└── README.md # This file # Re-authenticate with Azure CLI
az login --tenant your-tenant-id # The memory cache is now managed automatically. If you suspect issues,
# you can clear the cache directory, and it will be rebuilt on the next query.
# Windows:
rmdir /s /q "%APPDATA%\KQL_MCP\unified_memory.json"
# macOS/Linux:
rm -rf ~/.local/share/KQL_MCP/cluster_memoryWe welcome contributions! Please do.
mcp-name: io.github.4R9UN/mcp-kql-server
Happy Querying! 🎉
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.