This week I wanted to stop speaking about Syndu MCP in abstractions and use it as an operator would use it.
So I picked a live target: the most recent security telemetry objects from the Access Admin dashboard on production.
The goal was simple:
- review the latest suspicious events,
- investigate them through Syndu MCP,
- store the outcomes back into Syndu memory,
- enforce the stronger decisions at the firewall boundary.
That turned out to be a very good test, because the product did not behave like a polished demo. It behaved like a real system. It gave me useful signal, it surfaced one real bug, and it let me close the loop from investigation to memory to action.
1. The telemetry cohort
I started with the latest twelve objects from the Security Telemetry smart panel in the Access Admin dashboard.
The cluster was not a dramatic breach narrative. It was the kind of messy edge traffic an internet-facing system actually sees:
- repeated
csrf_failedevents on/ - repeated
PROPFIND /probes - a few browser-like
POST /requests with no referer - a few benign-looking reactivation-email clicks
Most of the heat concentrated into four IPs:
45.205.1.846.151.178.1345.205.1.2078.153.140.43
That was enough to make the panel worth investigating, but not enough to justify blanket blocking on sight.
2. The MCP loop I used
I used the live Syndu MCP server at /mcp/, authenticated with a fresh production credential tied to the admin workspace, and ran the investigation as a tool loop rather than as direct Django ORM introspection.
The investigation path was:
resolve_indicator
-> get_report_snapshot
-> explain_entity_risk
-> find_related_entities
-> get_workspace_memory_policy
-> store_outcome_event
That matters because it is the actual product contract. If Syndu MCP is going to be useful for Codex, Claude Code, Cursor, Windsurf, or any other MCP-capable agent, it needs to work in this exact shape:
- resolve a suspicious identifier,
- explain why it matters,
- recover related context,
- preserve the result as reusable memory.
3. The first real bug
The first live run did not succeed cleanly.
The memory tools worked, but the report-facing tools failed with a serialization error. The cause was straightforward and important: our MCP report payloads were leaking internal report context objects across the transport boundary. In practice, that meant raw Django model objects like IPReportTotal could end up inside the result payload for resolve_indicator and get_report_snapshot.
So before I could trust the investigation surface, I fixed the bug:
- public MCP payloads now strip internal context objects instead of returning them,
- report payloads are JSON-safe again,
- the fix was tested locally and deployed before the investigation continued.
This was a useful outcome in itself. It proved that the MCP server is no longer a marketing concept. It is a live operator surface, and when it breaks, I can improve it on the same day the investigation demands it.
4. What Syndu MCP said about the suspicious IPs
45.205.1.8
This one was the clearest repeated scanner in the cohort.
Recent security telemetry showed repeated PROPFIND / requests with insecure referers and non-browser behavior. Through MCP, the stronger picture became visible:
- overall contextual score:
44 - resolved to
Cloud Innovation Ltd - subnet:
45.205.1.0/24 - city/region/country:
Johannesburg / Gauteng / South Africa - activity history:
261recent events - annotator pressure: strong
uaandmethodanomalies
This is exactly the sort of host that makes a dashboard panel look noisy if you only stare at the event cards. With MCP, I could see it as a sustained probing source rather than a random one-off CSRF failure.
78.153.140.43
This was the materially riskier host.
The security telemetry row itself was just a browser-like POST / with no referer. But the MCP report snapshot exposed the historical context:
- overall contextual score:
72 - resolved to
HOSTGLOBAL.PLUS LTD - subnet:
78.153.140.0/24 - city/region/country:
City of London / England / United Kingdom - annotator history included
sfppressure
In Syndu's vocabulary, sfp means Sensitive File Probing: requests for configuration files, backups, admin resources, and other commonly exposed artifacts. That changes the interpretation materially. The current telemetry row may look small, but the historical pattern is not.
45.205.1.20
This host produced a recent browser-like POST / with no referer.
MCP resolved it to:
- overall contextual score:
49 - resolved org:
Vpsvault.host LTD - subnet:
45.205.1.0/24 - recent report activity:
18events - no strong currently published annotator pressure
That is suspicious enough to remember, but not strong enough to promote as shared scanner intelligence or block immediately.
46.151.178.13
This was the weakest candidate.
MCP resolved it to:
- overall contextual score:
30 - resolved org:
Demenin B.V - subnet:
46.151.178.0/24 - recent report activity:
3events - mostly redirect-shaped history
So this one stayed in the "remember privately, but do not overstate it" bucket.
5. I used MCP memory the way we intend agents to use it
Before writing outcomes back, I asked the server for the workspace memory policy:
stored_outcomes = truehive_mind = true
That let me use the write path deliberately instead of guessing at visibility.
I then stored four outcome events through MCP:
- two
communityevents for the stronger public scanner findings - two
workspaceevents for the weaker observations
The split was intentional:
45.205.1.8became shared scanner memory withblock_recommended78.153.140.43became shared scanner memory withblock_recommended45.205.1.20stayed as workspace-onlyobserve_only46.151.178.13stayed as workspace-onlyobserve_only
That is a good example of what I want the product to become.
Not every result should become hive-mind memory. Not every suspicious row deserves a block. The power is in making that judgment inside one governed loop.
6. Then I enforced the stronger decisions
Once the investigation had been preserved in MCP memory, I applied the operational follow-through in the firewall layer.
I created live IP block rules for:
45.205.1.878.153.140.43
I did not block:
45.205.1.2046.151.178.13
That asymmetry is important. A serious product should not train agents to treat every suspicious object as equally actionable. Syndu MCP is more useful when it helps the operator preserve ambiguity where ambiguity is real.
7. Why this matters
This was a small investigation, but it demonstrated the shape of the product clearly.
Reports alone would have been good for human reading.
The Risk API alone would have been good for a narrow programmable score.
MCP was the right surface because the job was collaborative and stateful:
- read recent telemetry,
- inspect a suspect,
- explain the context,
- attach a disposition,
- decide what becomes shared memory,
- enforce the stronger result.
That is what I mean when I say Syndu MCP is not just another way to query the graph. It is a governed cyber investigation loop with memory.
8. The operator lesson from this run
The most interesting part of this exercise was not the hostile traffic itself. The internet is full of that.
The interesting part was that the product held up as a working operator surface:
- it exposed the suspicious cluster,
- it let me investigate the hosts through MCP,
- it forced me to confront a real MCP serialization bug,
- it accepted the corrected outcomes back into memory,
- it supported a real enforcement decision afterward.
That is the shape I want Syndu to keep moving toward.
Investigate. Explain. Remember. And when the evidence is strong enough, act.