Cybersecurity Engineering · Homelab Portfolio · October 2026

Building an Agentic SOC Investigation Workflow

A proof of concept that connects Microsoft Sentinel, Azure MCP, a locally hosted language model and n8n to investigate Cowrie SSH honeypot incidents and deliver structured findings to Discord.

Microsoft SentinelAzure MCP Servern8nOllamaQwen3:14bKQLCowrieDiscord
3Successful MCP investigation calls in latest test
8,192Configured model context length (tokens)
~3m 52sObserved end-to-end test execution
01 / Project overview

From security alert to investigated narrative

Traditional alert handling often requires an analyst to open an incident, extract entities, formulate several queries, correlate the results and write a summary. This project tests whether a locally hosted LLM can perform a useful portion of that investigative work by calling real security tools—not simply summarising a preassembled log extract.

Problem

Repetitive incident triage

A Cowrie honeypot generates frequent Sentinel incidents. Investigating each source IP manually is useful for research, but time-consuming and repetitive.

Objective

Evidence-led AI investigation

Pass incident context into an agent, allow it to query Sentinel through MCP, and produce a readable SOC report delivered to Discord.

Current project status: The investigation-and-delivery workflow has been demonstrated successfully through manual execution. Five-minute scheduling, persistent incident deduplication and unattended processing are planned next steps—not implemented features of this version.
02 / Technical architecture

How the components fit together

Sentinel incidentIncident metadata, timestamps and IP entities
→
n8n orchestrationGet incidents, extract entities, pass parameters
→
Qwen3:14b agentPlan KQL queries and interpret evidence
↔
Azure MCPQuery Log Analytics using KQL
→
DiscordDeliver formatted SOC findings

The model runs locally through Ollama on a Windows host with an AMD Radeon RX 7600 XT (16 GB VRAM). n8n runs in Docker on an Ubuntu VM, while the Azure MCP Server provides access to Sentinel's Log Analytics workspace. The workflow's tool access is scoped to querying Cowrie telemetry.

ComponentRole
Microsoft SentinelGenerates and stores incidents; provides source entities and activity timestamps.
Cowrie SSH honeypotCaptures simulated SSH logins, session events and attacker-supplied commands.
n8nOrchestrates incident retrieval, conditional processing, agent execution, output formatting and Discord delivery.
Azure MCP ServerExposes the monitor_workspace_log_query tool for real Log Analytics queries.
Ollama + Qwen3:14bLocally hosted agent that generates queries, reviews results and writes the investigation.
DiscordReceives the final report through the existing messaging integration.
03 / Implementation

Investigation logic and tool use

STEP 01

Retrieve incident context

n8n retrieves Sentinel incidents, obtains associated entities and passes the source IP plus incident first/last activity times to the agent. The investigation window expands by one hour on each side.

STEP 02

Call a real security tool

The agent uses MCP_Client_monitor with monitor_workspace_log_query. MCP requires the physical table cowrie_JSON_CL, while the KQL itself uses the saved function Cowrie_Normalized.

STEP 03

Investigate based on findings

A baseline query counts events, sessions, successful and failed logins, and command events. The agent can follow up with authentication details, command analysis and session correlation when warranted.

STEP 04

Produce and deliver a report

Qwen assembles a SOC-style report with observed activity, interpretation, caveats and follow-up suggestions. n8n formats and sends the output to Discord.

Example baseline KQL

Cowrie_Normalized
| where TimeGenerated >= datetime(START_TIME)
| where TimeGenerated <= datetime(END_TIME)
| where SourceIp == "SOURCE_IP"
| summarize
    TotalEvents = count(),
    DistinctSessions = dcount(Session),
    FailedLogins = countif(EventID == "cowrie.login.failed"),
    SuccessfulLogins = countif(EventID == "cowrie.login.success"),
    Commands = countif(EventID == "cowrie.command.input")

The placeholders above are illustrative. At execution time, the agent substitutes the current incident's IP and expanded UTC timestamps.

Handling long attacker commands

Some captured Cowrie commands exceeded 10,000 characters. Sending complete command strings into a small model context reduced investigation quality. The revised KQL groups commands by their input string but returns only a preview, character length, SHA-256 hash and execution frequency.

| summarize CommandCount = count(),
            FirstSeen = min(TimeGenerated),
            LastSeen = max(TimeGenerated) by Input
| extend CommandLength = strlen(Input),
         CommandPreview = substring(Input, 0, 500),
         CommandHash = hash_sha256(Input)
| project CommandCount, FirstSeen, LastSeen,
          CommandLength, CommandPreview, CommandHash

This preserves useful investigative indicators while limiting the data sent to the LLM. The hash represents the command string, not a downloaded executable.

04 / Observed results

A working end-to-end investigation

In the latest demonstrated run, the n8n workflow completed successfully in approximately 3 minutes 52 seconds. The agent made three successful MCP calls, and the resulting SOC report was passed through the workflow's Discord delivery path.

23Events returned by the baseline MCP query
3Distinct sessions
2 / 1Successful / failed SSH logins

The verified baseline also showed two command input events. The agent's report described commands attempting to alter .ssh and write an SSH public key to authorized_keys, behaviour consistent with an attempted persistence mechanism in the simulated SSH environment.

Evidence qualification: The baseline counts were visible in the successful MCP response. Although the execution showed three successful tool calls, the detailed authentication and command responses were not independently inspected in the available screenshots. Accordingly, command content, session linkage and hashes should be treated as agent-reported findings pending tool-output verification—not independently validated facts.

The report also illustrates why analyst review remains important: one described command timestamp preceded the login timestamp of the session to which the report associated it. A future evidence-validation step should catch inconsistencies of this kind automatically.

05 / Engineering lessons

What made the PoC work

Tool calling is not the same as evidence integrity

Earlier tests produced plausible but unsupported usernames, Linux commands and hashes. Real tool access did not by itself prevent hallucinations. The report must be evaluated against the underlying MCP results.

Context length matters

The n8n Ollama Chat Model context setting was found at 2,048 tokens and increased to 8,192. The subsequent test showed three successful tool calls and a more coherent investigation. This is an observed improvement, not proof that context length was the only cause.

Compact queries beat raw log dumps

Aggregated statistics and bounded command previews reduce model load while preserving relevant telemetry. This was especially important for lengthy attacker-supplied shell commands.

Errors should be recoverable

One earlier run sent an invalid MCP command and workspace. The agent recovered by retrying with the correct monitor_workspace_log_query command and sentinel workspace, demonstrating useful—but not perfect—tool resilience.

Security and scope boundaries

06 / Next phase

From manual PoC to unattended triage

The investigation and Discord reporting path works. The next development milestone is reliable autonomous triggering and deduplication, without repeatedly processing the same Sentinel incident.

PLANNED 01

Five-minute schedule

Replace manual-only execution with an n8n Schedule Trigger that polls Sentinel for recent incidents.

PLANNED 02

Persistent deduplication

Use an n8n Data Table keyed by a stable Sentinel incident ID to track processing, completion and failure states.

PLANNED 03

Safe sequential processing

Queue or process incidents one at a time to avoid overlapping GPU-intensive investigations, especially during incident bursts.

PLANNED 04

Evidence validation

Capture intermediate MCP results and compare structured evidence against the generated report before Discord delivery.

At approximately 50 Sentinel incidents per day, the estimated inference workload is roughly 3–4 hours daily if each incident takes around four minutes. Actual capacity will depend on incident complexity, scheduling, retries and GPU performance.

07 / Outcome

What this project demonstrates

This PoC goes beyond prompting an LLM to summarise logs. It demonstrates an agent using a real MCP interface to query live security telemetry, adapt its investigation to the data returned, recover from at least some tool errors and communicate a useful SOC narrative through an existing messaging workflow.

The system is not production-ready, and its reports are not guaranteed to be fully accurate. As a homelab engineering project, however, it establishes a functioning integration across incident management, KQL, MCP, local inference, workflow automation and analyst-facing reporting—providing a practical foundation for unattended, evidence-checked incident triage.