Skip to content

secops_mcp_lookup_entity_formatter_bug #268

Description

@barnabys-drew

lookup_entity output drops related-entity names, prevalence data, and likely timeline/alert counts

secops_mcp 0.1.3. secops_mcp/tools/entity_lookup.py::lookup_entity only emits entity_type for each related entity, never the canonical Entity.name (or asset/domain detail in Entity.entity). The prevalence section is a string-only tease — "Prevalence Information Available" — with no actual data. Timeline event/alert totals and the Associated Alerts section also come back empty for entities with confirmed recent activity, but those may be SDK-call issues rather than formatter omissions (see below).

Smoke test against 10.6.20.143 (28 detections from Win_Repeat_Failed_Logins in the last 7d):

Entity Summary for 10.6.20.143:

Primary Entity:
Entity Type: ASSET
First Seen: 2026-04-09 ...
Last Seen: 2026-05-28 ...

Related Entities (2):
1. Type: IP_ADDRESS
2. Type: ASSET                  <-- which assets??

Timeline Summary:
Total Events: 0                 <-- 28 detections in 7d, this is wrong
Total Alerts: 0

Prevalence Information Available  <-- but no data emitted

SDK model (secops/chronicle/models.py):

  • Entity has name: str and entity: dict (asset/domain detail) — both ignored by the wrapper
  • PrevalenceData has prevalence_time, count — ignored
  • TimelineBucket has event_count: int = 0, alert_count: int = 0 (defaulted) — wrapper sums these correctly, so the zeros likely originate from the SDK call not populating buckets

Fix for the two clear formatter omissions:

 for i, entity in enumerate(related_entities[:5], 1):
     entity_type = 'Unknown'
     if hasattr(entity, 'metadata') and hasattr(entity.metadata, 'entity_type'):
         entity_type = entity.metadata.entity_type
-    result += f'{i}. Type: {entity_type}\n'
+    name = getattr(entity, 'name', 'Unknown')
+    extra = ''
+    if hasattr(entity, 'entity') and isinstance(entity.entity, dict):
+        if 'asset' in entity.entity and 'ip' in entity.entity['asset']:
+            extra = f" ip={','.join(entity.entity['asset']['ip'])}"
+        elif 'domain' in entity.entity and 'name' in entity.entity['domain']:
+            extra = f" domain={entity.entity['domain']['name']}"
+    result += f'{i}. {name} (Type: {entity_type}){extra}\n'
 if hasattr(entity_summary, 'prevalence') and entity_summary.prevalence:
-    result += 'Prevalence Information Available\n\n'
+    result += 'Prevalence:\n'
+    for p in entity_summary.prevalence[:10]:
+        result += f'  - {p.prevalence_time}: count={p.count}\n'
+    result += '\n'

Separately worth investigating: why chronicle.summarize_entity() returns empty timeline.buckets / empty alert_counts for entities with known activity. May need different SDK args.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions