Skip to content

Commit 205f225

Browse files
committed
added audit_history tool
1 parent ab997ac commit 205f225

File tree

4 files changed

+368
-2
lines changed

4 files changed

+368
-2
lines changed

modelcontextprotocol/server.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
UpdatableAttribute,
1515
CertificateStatus,
1616
UpdatableAsset,
17+
get_asset_history,
1718
)
1819
from pyatlan.model.lineage import LineageDirection
1920
from utils.parameters import (
@@ -508,6 +509,65 @@ def update_assets_tool(
508509
}
509510

510511

512+
@mcp.tool()
513+
def get_asset_history_tool(
514+
guid=None,
515+
qualified_name=None,
516+
type_name=None,
517+
size=10,
518+
sort_order="DESC",
519+
include_attributes=None,
520+
):
521+
"""
522+
Get the audit history of an asset by GUID or qualified name.
523+
524+
Args:
525+
guid (str, optional): GUID of the asset to get history for.
526+
Either guid or qualified_name must be provided.
527+
qualified_name (str, optional): Qualified name of the asset to get history for.
528+
Either guid or qualified_name must be provided.
529+
type_name (str, optional): Type name of the asset (required when using qualified_name).
530+
Examples: "Table", "Column", "DbtModel", "AtlasGlossary"
531+
size (int): Number of history entries to return. Defaults to 10.
532+
sort_order (str): Sort order for results. "ASC" for oldest first, "DESC" for newest first.
533+
Defaults to "DESC".
534+
include_attributes (List[Union[str, AtlanField]], optional): List of additional attributes to include in results.
535+
Can be string attribute names or AtlanField objects. These will be added to the default set.
536+
537+
Returns:
538+
Dict[str, Any]: Dictionary containing:
539+
- entityAudits: List of audit entries with details about each change
540+
- count: Number of audit entries returned
541+
- totalCount: Total number of audit entries available
542+
- errors: List of any errors encountered
543+
544+
Examples:
545+
# Get history by GUID
546+
history = get_asset_history_tool(
547+
guid="6fc01478-1263-42ae-b8ca-c4a57da51392",
548+
size=20,
549+
sort_order="DESC",
550+
include_attributes=["owner_users", "description"]
551+
)
552+
553+
# Get history by qualified name
554+
history = get_asset_history_tool(
555+
qualified_name="default/dbt/1755018137/account/258239/project/376530/model.simple_column_lineage.order_maths",
556+
type_name="DbtModel",
557+
size=15,
558+
sort_order="ASC"
559+
)
560+
"""
561+
return get_asset_history(
562+
guid=guid,
563+
qualified_name=qualified_name,
564+
type_name=type_name,
565+
size=size,
566+
sort_order=sort_order,
567+
include_attributes=include_attributes,
568+
)
569+
570+
511571
@mcp.tool()
512572
def create_glossaries(glossaries) -> List[Dict[str, Any]]:
513573
"""

modelcontextprotocol/tools/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from .search import search_assets
22
from .dsl import get_assets_by_dsl
33
from .lineage import traverse_lineage
4-
from .assets import update_assets
4+
from .assets import update_assets, get_asset_history
55
from .glossary import (
66
create_glossary_category_assets,
77
create_glossary_assets,
@@ -21,6 +21,7 @@
2121
"get_assets_by_dsl",
2222
"traverse_lineage",
2323
"update_assets",
24+
"get_asset_history",
2425
"create_glossary_category_assets",
2526
"create_glossary_assets",
2627
"create_glossary_term_assets",

modelcontextprotocol/tools/assets.py

Lines changed: 102 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
import logging
2-
from typing import List, Union, Dict, Any
2+
from typing import List, Union, Dict, Any, Optional
33
from client import get_atlan_client
44
from .models import UpdatableAsset, UpdatableAttribute, CertificateStatus
55
from pyatlan.model.assets import Readme
66
from pyatlan.model.fluent_search import CompoundQuery, FluentSearch
7+
from pyatlan.model.fields.atlan_fields import AtlanField
8+
from utils.asset_history import (
9+
validate_asset_history_params,
10+
create_audit_search_request,
11+
process_audit_result,
12+
create_sort_item,
13+
convert_attributes_to_camel_case,
14+
)
715

816
# Initialize logging
917
logger = logging.getLogger(__name__)
@@ -128,3 +136,96 @@ def update_assets(
128136
error_msg = f"Error updating assets: {str(e)}"
129137
logger.error(error_msg)
130138
return {"updated_count": 0, "errors": [error_msg]}
139+
140+
141+
def get_asset_history(
142+
guid: Optional[str] = None,
143+
qualified_name: Optional[str] = None,
144+
type_name: Optional[str] = None,
145+
size: int = 10,
146+
sort_order: str = "DESC",
147+
include_attributes: Optional[List[Union[str, AtlanField]]] = None,
148+
) -> Dict[str, Any]:
149+
"""
150+
Get the audit history of an asset by GUID or qualified name.
151+
152+
Args:
153+
guid (Optional[str]): GUID of the asset to get history for.
154+
Either guid or qualified_name must be provided.
155+
qualified_name (Optional[str]): Qualified name of the asset to get history for.
156+
Either guid or qualified_name must be provided.
157+
type_name (Optional[str]): Type name of the asset (required when using qualified_name).
158+
Examples: "Table", "Column", "DbtModel", "AtlasGlossary"
159+
size (int): Number of history entries to return. Defaults to 10.
160+
sort_order (str): Sort order for results. "ASC" for oldest first, "DESC" for newest first.
161+
Defaults to "DESC".
162+
include_attributes (List[Union[str, AtlanField]], optional): List of additional attributes to include in results.
163+
Can be string attribute names or AtlanField objects. These will be added to the default set.
164+
165+
Returns:
166+
Dict[str, Any]: Dictionary containing:
167+
- entityAudits: List of audit entries
168+
- count: Number of audit entries returned
169+
- totalCount: Total number of audit entries available
170+
- errors: List of any errors encountered
171+
172+
Raises:
173+
Exception: If there's an error retrieving the asset history
174+
"""
175+
try:
176+
# Validate input parameters
177+
validation_error = validate_asset_history_params(
178+
guid, qualified_name, type_name, sort_order
179+
)
180+
if validation_error:
181+
logger.error(validation_error)
182+
return {
183+
"errors": [validation_error],
184+
"entityAudits": [],
185+
"count": 0,
186+
"totalCount": 0,
187+
}
188+
189+
logger.info(
190+
f"Retrieving asset history with parameters: guid={guid}, qualified_name={qualified_name}, size={size}"
191+
)
192+
193+
# Get Atlan client
194+
client = get_atlan_client()
195+
196+
# Create sort item
197+
sort_item = create_sort_item(sort_order)
198+
199+
# Convert include_attributes from snake_case to camelCase if needed
200+
if include_attributes:
201+
include_attributes = convert_attributes_to_camel_case(include_attributes)
202+
203+
# Create and execute audit search request
204+
request = create_audit_search_request(
205+
guid, qualified_name, type_name, size, sort_item, include_attributes
206+
)
207+
response = client.audit.search(criteria=request, bulk=False)
208+
209+
# Process audit results - use current_page() to respect size parameter
210+
entity_audits = [
211+
process_audit_result(result, include_attributes)
212+
for result in response.current_page()
213+
]
214+
215+
result_data = {
216+
"entityAudits": entity_audits,
217+
"count": len(entity_audits),
218+
"totalCount": response.total_count,
219+
"errors": [],
220+
}
221+
222+
logger.info(
223+
f"Successfully retrieved {len(entity_audits)} audit entries for asset"
224+
)
225+
return result_data
226+
227+
except Exception as e:
228+
error_msg = f"Error retrieving asset history: {str(e)}"
229+
logger.error(error_msg)
230+
logger.exception("Exception details:")
231+
return {"errors": [error_msg], "entityAudits": [], "count": 0, "totalCount": 0}

0 commit comments

Comments
 (0)