Skip to main content
Glama
googleSandy

Google Threat Intelligence MCP Server

by googleSandy

get_collection_timeline_events

Retrieve curated timeline events for security campaigns and threat actors from Google Threat Intelligence collections to analyze threat activity chronologically.

Instructions

Retrieves timeline events from the given collection, when available.

This is super valuable curated information produced by security analysits at Google Threat Intelligence.

We should fetch this information for campaigns and threat actors always.

It's common to display the events grouped by the "event_category" field.

Args: id (required): Collection identifier Return: List of events related to the given collection.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
idYes
api_keyNo

Implementation Reference

  • The main handler function get_collection_timeline_events that retrieves timeline events from a collection via VirusTotal API. Decorated with @server.tool() for MCP registration.
    @server.tool()
    async def get_collection_timeline_events(id: str, ctx: Context, api_key: str = None):
      """Retrieves timeline events from the given collection, when available.
    
      This is super valuable curated information produced by security analysits at Google Threat Intelligence.
    
      We should fetch this information for campaigns and threat actors always.
    
      It's common to display the events grouped by the "event_category" field.
    
      Args:
        id (required): Collection identifier
      Return:
        List of events related to the given collection.
      """
      async with vt_client(ctx, api_key=api_key) as client:
        resp = await client.get_async(f"/collections/{id}/timeline/events")
        if resp.status != 200:
            error_json = await resp.json_async()
            error_info = error_json.get("error", {})
            return [{"error": f"API Error: {error_info.get('message', 'Unknown error')}"}]
        data = await resp.json_async()
      return utils.sanitize_response(data.get("data", []))
  • The @server.tool() decorator that registers get_collection_timeline_events as an MCP tool. The server instance is a FastMCP object from gti_mcp/server.py.
    @server.tool()
  • Helper function sanitize_response that recursively removes empty dictionaries and lists from API responses, used by get_collection_timeline_events to clean up returned data.
    def sanitize_response(data: typing.Any) -> typing.Any:
      """Removes empty dictionaries and lists recursively from a response."""
      if isinstance(data, dict):
        sanitized_dict = {}
        for key, value in data.items():
          sanitized_value = sanitize_response(value)
          if sanitized_value is not None:
            sanitized_dict[key] = sanitized_value
        return sanitized_dict
      elif isinstance(data, list):
        sanitized_list = []
        for item in data:
          sanitized_item = sanitize_response(item)
          if sanitized_item is not None:
            sanitized_list.append(sanitized_item)
        return sanitized_list
      elif isinstance(data, str):
        return data if data else None
      else:
        return data
  • Test case for get_collection_timeline_events that verifies error handling when the API returns a non-200 status code (e.g., 404 for non-existent collection).
    async def test_get_collection_timeline_events_api_error_handled():
        """Test get_collection_timeline_events returns error dict on API error (e.g. 404)."""
        mock_ctx = MagicMock(spec=Context)
    
        mock_response = MagicMock()
        mock_response.status = 404
        async def json_async():
            return {"error": {"message": "Collection not found"}}
        mock_response.json_async = json_async
    
        mock_client_instance = MagicMock()
        mock_client_instance.get_async = AsyncMock(return_value=mock_response)
    
        mock_vt_client = MagicMock()
        mock_vt_client.__aenter__ = AsyncMock(return_value=mock_client_instance)
        mock_vt_client.__aexit__ = AsyncMock(return_value=None)
    
        with patch("gti_mcp.tools.collections.vt_client", return_value=mock_vt_client):
            result = await collections.get_collection_timeline_events(id="non_existent_id", ctx=mock_ctx)
            assert isinstance(result, list)
            assert len(result) == 1
            assert "error" in result[0]
            assert "Collection not found" in result[0]["error"]
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries full burden. It mentions the data is 'super valuable curated information produced by security analysts at Google Threat Intelligence,' which adds context about data quality and source. However, it doesn't disclose critical behavioral traits like whether this is a read-only operation, authentication requirements (though 'api_key' parameter hints at this), rate limits, pagination, or what 'when available' means operationally (e.g., error conditions).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is moderately concise but not optimally structured. It starts with the core purpose, then includes promotional content ('super valuable...'), usage suggestions, and finally parameter details. The promotional sentences ('This is super valuable...', 'We should fetch...') don't add essential operational value and could be trimmed. However, the overall length is reasonable, and key information is present.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's moderate complexity (retrieving curated timeline events), no annotations, no output schema, and 0% schema coverage, the description is partially complete. It covers the purpose, some usage context, and basic parameter semantics, but lacks details on authentication, error handling, output structure beyond 'list of events', and behavioral constraints. For a security intelligence tool with sensitive data, more completeness would be beneficial.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the schema provides no parameter descriptions. The description adds minimal semantics: it notes 'id (required): Collection identifier' and mentions the return is a 'List of events related to the given collection.' However, it doesn't explain the 'api_key' parameter at all, and the parameter information is buried after promotional content rather than integrated clearly. With 2 parameters and 0% schema coverage, this partial compensation earns a baseline 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Retrieves timeline events from the given collection, when available.' It specifies the verb ('retrieves') and resource ('timeline events'), and distinguishes it from siblings by focusing on timeline events rather than reports, rules, or other collection features. However, it doesn't explicitly differentiate from 'get_threat_profile_associations_timeline' which might be a similar sibling tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides implied usage guidance: 'We should fetch this information for campaigns and threat actors always' and 'It's common to display the events grouped by the "event_category" field.' This suggests when to use it (for campaigns/threat actors) and how to handle output, but it doesn't explicitly state when NOT to use it or name alternatives among the many sibling tools for different data types.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/googleSandy/gti-mcp-standalone'

If you have feedback or need assistance with the MCP directory API, please join our Discord server