Problem Statement
Currently, all tools across server/secops/secops_mcp/tools/ are registered using unadorned @server.tool() decorators without tool metadata annotations.
Model Context Protocol (MCP) clients, autonomous agents, and orchestrators (e.g. Gemini CLI, ADK, Claude, Cursor) rely on standard ToolAnnotations hints to evaluate tool safety prior to execution. In particular:
readOnlyHint (boolean): Signals whether a tool only queries data without altering the state of the system.
destructiveHint (boolean): When readOnlyHint is False, indicates whether the operation deletes, overwrites, or invalidates resources versus performing an additive mutation.
idempotentHint (boolean): Signals whether repeated execution with identical arguments produces the same state.
Without these annotations, clients cannot distinguish harmless read-only telemetry queries (e.g. udm_search, list_rules, get_security_alert) from destructive operations (e.g. delete_rule, delete_feed, delete_data_table_row, delete_watchlist, archive_rule). This forces clients to either prompt the user for interactive confirmation on every single safe read query, or execute mutating and destructive actions without confirmation.
Requested Pattern
FastMCP supports passing annotations dictionaries directly to the @server.tool() decorator:
from fastmcp import FastMCP
mcp = FastMCP("Database Manager")
@mcp.tool(
annotations={
"readOnlyHint": False,
"destructiveHint": True
}
)
def drop_table(table_name: str) -> str:
"""Permanently deletes a database table."""
# Your destructive logic here
return f"Table {table_name} has been dropped."
When registered, FastMCP validates and parses these dictionaries into mcp.types.ToolAnnotations(readOnlyHint=False, destructiveHint=True).
Proposed Tool Classification for secops-mcp
1. Destructive Operations (readOnlyHint: False, destructiveHint: True)
Tools that permanently delete, archive, or deactivate resources, or invalidate credentials:
security_rules.py: delete_rule, archive_rule
feed_management.py: delete_feed, disable_feed, generate_feed_secret
data_table_management.py: delete_data_table_row
rule_exclusions.py: delete_rule_exclusion
watchlist_management.py: delete_watchlist
curated_rules_management.py: disable_curated_rule
parser_management.py: deactivate_parser
- (If SOAR case tools are active):
execute_bulk_close_case, close_case
2. Mutating / Additive Operations (readOnlyHint: False, destructiveHint: False)
Tools that create, update, or append state without permanently deleting data:
security_rules.py: create_rule, update_rule
feed_management.py: create_feed, update_feed, enable_feed
data_table_management.py: create_data_table, add_rows_to_data_table
reference_list_management.py: create_reference_list, update_reference_list
rule_exclusions.py: create_rule_exclusion, update_rule_exclusion
watchlist_management.py: create_watchlist, update_watchlist
curated_rules_management.py: enable_curated_rule
parser_management.py: create_parser, activate_parser
log_ingestion.py: ingest_log, batch_ingest_logs
security_alerts.py: update_security_alert
investigation_management.py: trigger_investigation
3. Read-Only Operations (readOnlyHint: True)
Queries, searches, and validation tools that do not mutate server state:
- UDM & Events:
udm_search, search_security_events, get_security_event
- Rules & Detections:
list_rules, get_rule, validate_rule, test_rule (validating and testing YARA-L 2.0 / YL2 rules against historical data)
- Curated Rules:
list_curated_rules, get_curated_rule, list_curated_rule_detections
- Alerts:
list_security_alerts, get_security_alert
- Feeds:
list_feeds, get_feed
- Parsers:
list_parsers, get_parser, run_parser
- Data Tables & Reference Lists:
list_data_tables, get_reference_list
- Investigations:
list_investigations, get_investigation
- Threat Intel & Entities:
search_threat_intel, lookup_entity, get_ioc_matches
- Watchlists & Exclusions:
list_watchlists, get_watchlist, list_rule_exclusions, get_rule_exclusion
Deliverables & Acceptance Criteria
- Update
@server.tool() decorators across all tool modules in server/secops/secops_mcp/tools/ to include explicit annotations mappings (readOnlyHint, destructiveHint, and idempotentHint where applicable).
- Verify all tools exposed by
server.run() surface ToolAnnotations during MCP tools/list protocol negotiation.
- Update unit tests in
server/secops/tests/ to assert that all registered tools define annotations and verify expected hint values.
- Ensure all existing tests in
server/secops/tests/ continue to pass.
Problem Statement
Currently, all tools across
server/secops/secops_mcp/tools/are registered using unadorned@server.tool()decorators without tool metadata annotations.Model Context Protocol (MCP) clients, autonomous agents, and orchestrators (e.g. Gemini CLI, ADK, Claude, Cursor) rely on standard
ToolAnnotationshints to evaluate tool safety prior to execution. In particular:readOnlyHint(boolean): Signals whether a tool only queries data without altering the state of the system.destructiveHint(boolean): WhenreadOnlyHintisFalse, indicates whether the operation deletes, overwrites, or invalidates resources versus performing an additive mutation.idempotentHint(boolean): Signals whether repeated execution with identical arguments produces the same state.Without these annotations, clients cannot distinguish harmless read-only telemetry queries (e.g.
udm_search,list_rules,get_security_alert) from destructive operations (e.g.delete_rule,delete_feed,delete_data_table_row,delete_watchlist,archive_rule). This forces clients to either prompt the user for interactive confirmation on every single safe read query, or execute mutating and destructive actions without confirmation.Requested Pattern
FastMCP supports passing
annotationsdictionaries directly to the@server.tool()decorator:When registered, FastMCP validates and parses these dictionaries into
mcp.types.ToolAnnotations(readOnlyHint=False, destructiveHint=True).Proposed Tool Classification for
secops-mcp1. Destructive Operations (
readOnlyHint: False, destructiveHint: True)Tools that permanently delete, archive, or deactivate resources, or invalidate credentials:
security_rules.py:delete_rule,archive_rulefeed_management.py:delete_feed,disable_feed,generate_feed_secretdata_table_management.py:delete_data_table_rowrule_exclusions.py:delete_rule_exclusionwatchlist_management.py:delete_watchlistcurated_rules_management.py:disable_curated_ruleparser_management.py:deactivate_parserexecute_bulk_close_case,close_case2. Mutating / Additive Operations (
readOnlyHint: False, destructiveHint: False)Tools that create, update, or append state without permanently deleting data:
security_rules.py:create_rule,update_rulefeed_management.py:create_feed,update_feed,enable_feeddata_table_management.py:create_data_table,add_rows_to_data_tablereference_list_management.py:create_reference_list,update_reference_listrule_exclusions.py:create_rule_exclusion,update_rule_exclusionwatchlist_management.py:create_watchlist,update_watchlistcurated_rules_management.py:enable_curated_ruleparser_management.py:create_parser,activate_parserlog_ingestion.py:ingest_log,batch_ingest_logssecurity_alerts.py:update_security_alertinvestigation_management.py:trigger_investigation3. Read-Only Operations (
readOnlyHint: True)Queries, searches, and validation tools that do not mutate server state:
udm_search,search_security_events,get_security_eventlist_rules,get_rule,validate_rule,test_rule(validating and testing YARA-L 2.0 / YL2 rules against historical data)list_curated_rules,get_curated_rule,list_curated_rule_detectionslist_security_alerts,get_security_alertlist_feeds,get_feedlist_parsers,get_parser,run_parserlist_data_tables,get_reference_listlist_investigations,get_investigationsearch_threat_intel,lookup_entity,get_ioc_matcheslist_watchlists,get_watchlist,list_rule_exclusions,get_rule_exclusionDeliverables & Acceptance Criteria
@server.tool()decorators across all tool modules inserver/secops/secops_mcp/tools/to include explicitannotationsmappings (readOnlyHint,destructiveHint, andidempotentHintwhere applicable).server.run()surfaceToolAnnotationsduring MCPtools/listprotocol negotiation.server/secops/tests/to assert that all registered tools defineannotationsand verify expected hint values.server/secops/tests/continue to pass.