get_file_behavior_report
Get a detailed behavior report for a file by using its behavior identifier, which includes the file hash and sandbox name.
Instructions
Retrieve the file behaviour report of the given file behaviour identifier.
You can get all the file behaviour of a given a file by calling get_entities_related_to_a_file as the file hash and the behaviours as relationship name.
The file behaviour ID is composed using the following pattern: "{file hash}_{sandbox name}".
Args: file_behaviour_id (required): File behaviour ID. Returns: The file behaviour report.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| file_behaviour_id | Yes | ||
| api_key | No |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| result | Yes |
Implementation Reference
- gti_mcp/tools/files.py:193-225 (handler)The `get_file_behavior_report` tool handler function. It uses the `@server.tool()` decorator for registration, fetches a file behaviour report from VirusTotal/GTI API using `utils.fetch_object` with multiple relationships (contacted_domains, contacted_ips, contacted_urls, dropped_files, embedded_domains, embedded_ips, embedded_urls, associations), and sanitizes the response.
@server.tool() async def get_file_behavior_report( file_behaviour_id: str, ctx: Context, api_key: str = None ) -> typing.Dict[str, typing.Any]: """Retrieve the file behaviour report of the given file behaviour identifier. You can get all the file behaviour of a given a file by calling `get_entities_related_to_a_file` as the file hash and the `behaviours` as relationship name. The file behaviour ID is composed using the following pattern: "{file hash}_{sandbox name}". Args: file_behaviour_id (required): File behaviour ID. Returns: The file behaviour report. """ async with vt_client(ctx, api_key=api_key) as client: res = await utils.fetch_object( client, "file_behaviours", "file_behaviour", file_behaviour_id, relationships=[ "contacted_domains", "contacted_ips", "contacted_urls", "dropped_files", "embedded_domains", "embedded_ips", "embedded_urls", "associations", ], ) return utils.sanitize_response(res) - gti_mcp/tools/files.py:194-196 (schema)Function signature acts as the input schema: `file_behaviour_id: str` (required), `ctx: Context`, and optional `api_key: str`. Return type is `Dict[str, Any]`.
async def get_file_behavior_report( file_behaviour_id: str, ctx: Context, api_key: str = None ) -> typing.Dict[str, typing.Any]: - gti_mcp/tools/files.py:193-193 (registration)The tool is registered via the `@server.tool()` decorator from `gti_mcp/server.py` (FastMCP instance). The `server` variable is imported at line 23, and all tools in `files.py` are loaded via `from gti_mcp.tools import *` at line 73 of server.py, which triggers `from .files import *` in gti_mcp/tools/__init__.py.
@server.tool() - gti_mcp/utils.py:29-84 (helper)The `fetch_object` helper function, called by the handler to fetch the file behaviour report from the GTI API. It handles the API call, error handling, and response formatting.
async def fetch_object( vt_client: vt.Client, resource_collection_type: str, resource_type: str, resource_id: str, attributes: list[str] | None = None, relationships: list[str] | None = None, params: dict[str, typing.Any] | None = None): """Fetches objects from Google Threat Intelligence API.""" logging.info( f"Fetching comprehensive {resource_collection_type} " f"report for id: {resource_id}") params = {k: v for k, v in params.items()} if params else {} # Retrieve a selection of object attributes and/or relationships. if attributes: params["attributes"] = ",".join(attributes) if relationships: params["relationships"] = ",".join(relationships) try: obj = await vt_client.get_object_async( f"/{resource_collection_type}/{resource_id}", params=params) if obj.error: logging.error( f"Error fetching main {resource_type} report for {resource_id}: {obj.error}" ) return { "error": f"Failed to get main {resource_type} report: {obj.error}", # "details": report.get("details"), } except vt.error.APIError as e: logging.warning( f"VirusTotal API Error fetching {resource_type} {resource_id}: {e.code} - {e.message}" ) return { "error": f"VirusTotal API Error: {e.code} - {e.message}", "details": f"The requested {resource_type} '{resource_id}' could not be found or there was an issue with the API request." } except Exception as e: logging.exception( f"Unexpected error fetching {resource_type} {resource_id}: {e}" ) return {"error": "An unexpected internal error occurred."} # Build response. obj_dict = obj.to_dict() obj_dict['id'] = obj.id if 'aggregations' in obj_dict['attributes']: del obj_dict['attributes']['aggregations'] logging.info( f"Successfully generated concise threat summary for id: {resource_id}") return obj_dict - gti_mcp/utils.py:119-138 (helper)The `sanitize_response` helper function, called by the handler to clean up the response by removing empty dicts/lists recursively.
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