Skip to content

Commit 0f7d961

Browse files
committed
refactor(telemetry): remove prefixed tool name convention from extension tool calls
1 parent c2b0b6c commit 0f7d961

4 files changed

Lines changed: 62 additions & 72 deletions

File tree

src/sap_cloud_sdk/core/telemetry/extensions.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ def resolve_source_info(
252252
fields when the key is not found in the mapping.
253253
254254
Args:
255-
key: Lookup key in the source mapping (e.g. prefixed tool name or
255+
key: Lookup key in the source mapping (e.g. tool name or
256256
hook ID).
257257
source_mapping: Mapping of keys to source info objects or dicts.
258258
May be ``None``.
@@ -430,15 +430,22 @@ async def call_extension_tool(
430430
Args:
431431
mcp_client: The MCP client session connected to the tool's server.
432432
Must have an async ``call_tool(name, args)`` method.
433-
tool_name: The tool name used as the lookup key in *source_mapping*
434-
and passed to ``mcp_client.call_tool()``.
433+
tool_name: The raw MCP tool name (e.g. ``"create_ticket"``), used
434+
as the lookup key in *source_mapping* and passed directly to
435+
``mcp_client.call_tool()``.
435436
args: Dictionary of arguments to pass to the tool.
436437
capability: Extension capability ID (default: ``"default"``).
437-
source_mapping: Optional mapping of tool names to source info
438-
objects (from ``ext_impl.source.tools``).
438+
source_mapping: Optional mapping of tool names to
439+
:class:`~sap_cloud_sdk.extensibility.ExtensionSourceInfo`
440+
objects (from ``ext_impl.source.tools``). Keys must match the
441+
*tool_name* values passed to this function.
442+
See :class:`~sap_cloud_sdk.extensibility.ExtensionSourceMapping`.
439443
440444
Returns:
441445
The tool's response from the MCP server.
446+
447+
See Also:
448+
:func:`call_extension_hook` for hook-based extensions.
442449
"""
443450
resolved_name, resolved_id, resolved_version, resolved_url, resolved_solution_id = (
444451
resolve_source_info(tool_name, source_mapping, "unknown")

src/sap_cloud_sdk/extensibility/_models.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -489,15 +489,15 @@ class ExtensionSourceMapping:
489489
Returned by the extensibility backend when multiple extensions are merged
490490
into a single capability implementation response.
491491
492-
Tool keys are prefixed tool names
493-
(e.g., ``"sap_mcp_servicenow_v1_create_ticket"``).
492+
Tool keys are raw tool names
493+
(e.g., ``"create_ticket"``).
494494
Hook keys are hook IDs (UUIDs) (e.g.,
495495
``"3f5c8c8a-7b4d-4f9c-a4c0-7d5cb1a39f7e"``).
496496
Values are :class:`ExtensionSourceInfo` objects containing the extension's
497497
name, version, and unique identifier.
498498
499499
Attributes:
500-
tools: Mapping of prefixed tool name to extension source info.
500+
tools: Mapping of tool name to extension source info.
501501
hooks: Mapping of hook ID to extension source info.
502502
"""
503503

@@ -512,7 +512,7 @@ def from_dict(cls, obj: Dict[str, Any]) -> ExtensionSourceMapping:
512512
513513
{
514514
"tools": {
515-
"sap_mcp_taxvalidator_validate_validate_tax": {
515+
"validate_tax": {
516516
"extensionName": "ap-invoice-extension",
517517
"extensionVersion": "1",
518518
"extensionId": "a1b2c3d4-..."
@@ -679,7 +679,7 @@ def from_dict(cls, obj: Dict[str, Any]) -> ExtensionCapabilityImplementation:
679679
],
680680
"source": {
681681
"tools": {
682-
"sap_mcp_servicenow_v1_create_ticket": {
682+
"create_ticket": {
683683
"extensionName": "servicenow-ext",
684684
"extensionVersion": "1",
685685
"extensionId": "abc-123"
@@ -740,8 +740,8 @@ def get_extension_for_tool(self, tool_name: str) -> Optional[str]:
740740
"""Look up the extension name that contributed a specific tool.
741741
742742
Args:
743-
tool_name: The prefixed tool name (e.g.,
744-
``"sap_mcp_servicenow_v1_create_ticket"``).
743+
tool_name: The tool name (e.g.,
744+
``"create_ticket"``).
745745
746746
Returns:
747747
Extension name, or ``None`` if source mapping is not available
@@ -774,8 +774,8 @@ def get_source_info_for_tool(self, tool_name: str) -> Optional[ExtensionSourceIn
774774
``None`` when source mapping is not available or the tool is not found.
775775
776776
Args:
777-
tool_name: The prefixed tool name (e.g.,
778-
``"sap_mcp_servicenow_v1_create_ticket"``).
777+
tool_name: The tool name (e.g.,
778+
``"create_ticket"``).
779779
780780
Returns:
781781
:class:`ExtensionSourceInfo` for the tool, or ``None``.

tests/core/unit/telemetry/test_extensions.py

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -920,18 +920,32 @@ class FakeSourceInfo:
920920
extension_id: str
921921
extension_version: str
922922

923-
mapping = {"tool1": FakeSourceInfo("Mapped Ext", "uuid-m", "7")}
923+
mapping = {"create_ticket": FakeSourceInfo("Mapped Ext", "uuid-m", "7")}
924924
mock_client = AsyncMock()
925925
mock_client.call_tool.return_value = "ok"
926926

927927
reset_tool_call_metrics()
928-
result = await call_extension_tool(
929-
mcp_client=mock_client,
930-
tool_name="tool1",
931-
args={},
932-
source_mapping=mapping,
933-
)
934-
assert result == "ok"
928+
with patch(
929+
"sap_cloud_sdk.core.telemetry.extensions._tracer"
930+
) as mock_tracer:
931+
mock_tracer.start_as_current_span = MagicMock(
932+
return_value=MagicMock(
933+
__enter__=MagicMock(), __exit__=MagicMock(return_value=False)
934+
)
935+
)
936+
result = await call_extension_tool(
937+
mcp_client=mock_client,
938+
tool_name="create_ticket",
939+
args={},
940+
source_mapping=mapping,
941+
)
942+
assert result == "ok"
943+
call_args = mock_tracer.start_as_current_span.call_args
944+
attrs = call_args[1]["attributes"]
945+
assert attrs[ATTR_EXTENSION_NAME] == "Mapped Ext"
946+
assert attrs[ATTR_EXTENSION_ID] == "uuid-m"
947+
assert attrs[ATTR_EXTENSION_VERSION] == "7"
948+
assert attrs[ATTR_EXTENSION_ITEM_NAME] == "create_ticket"
935949

936950
asyncio.run(_run())
937951

tests/extensibility/unit/test_models.py

Lines changed: 19 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -740,12 +740,12 @@ def test_from_dict_full_new_format(self):
740740
"""Parse a complete source mapping from backend JSON (new format)."""
741741
data = {
742742
"tools": {
743-
"sap_mcp_servicenow_v1_create_ticket": {
743+
"create_ticket": {
744744
"extensionName": "servicenow-ext",
745745
"extensionVersion": "2",
746746
"extensionId": "uuid-sn",
747747
},
748-
"sap_mcp_jira_v1_create_issue": {
748+
"create_issue": {
749749
"extensionName": "jira-ext",
750750
"extensionVersion": "1",
751751
"extensionId": "uuid-jira",
@@ -765,21 +765,10 @@ def test_from_dict_full_new_format(self):
765765
},
766766
}
767767
mapping = ExtensionSourceMapping.from_dict(data)
768-
assert (
769-
mapping.tools["sap_mcp_servicenow_v1_create_ticket"].extension_name
770-
== "servicenow-ext"
771-
)
772-
assert (
773-
mapping.tools["sap_mcp_servicenow_v1_create_ticket"].extension_version
774-
== "2"
775-
)
776-
assert (
777-
mapping.tools["sap_mcp_servicenow_v1_create_ticket"].extension_id
778-
== "uuid-sn"
779-
)
780-
assert (
781-
mapping.tools["sap_mcp_jira_v1_create_issue"].extension_name == "jira-ext"
782-
)
768+
assert mapping.tools["create_ticket"].extension_name == "servicenow-ext"
769+
assert mapping.tools["create_ticket"].extension_version == "2"
770+
assert mapping.tools["create_ticket"].extension_id == "uuid-sn"
771+
assert mapping.tools["create_issue"].extension_name == "jira-ext"
783772
assert (
784773
mapping.hooks["3f5c8c8a-7b4d-4f9c-a4c0-7d5cb1a39f7e"].extension_name
785774
== "workflow-ext"
@@ -793,21 +782,16 @@ def test_from_dict_old_format_backward_compat(self):
793782
"""Parse old format where values are plain strings."""
794783
data = {
795784
"tools": {
796-
"sap_mcp_servicenow_v1_create_ticket": "servicenow-ext",
785+
"create_ticket": "servicenow-ext",
797786
},
798787
"hooks": {
799788
"3f5c8c8a-7b4d-4f9c-a4c0-7d5cb1a39f7e": "workflow-ext",
800789
},
801790
}
802791
mapping = ExtensionSourceMapping.from_dict(data)
803-
assert (
804-
mapping.tools["sap_mcp_servicenow_v1_create_ticket"].extension_name
805-
== "servicenow-ext"
806-
)
807-
assert (
808-
mapping.tools["sap_mcp_servicenow_v1_create_ticket"].extension_version == ""
809-
)
810-
assert mapping.tools["sap_mcp_servicenow_v1_create_ticket"].extension_id == ""
792+
assert mapping.tools["create_ticket"].extension_name == "servicenow-ext"
793+
assert mapping.tools["create_ticket"].extension_version == ""
794+
assert mapping.tools["create_ticket"].extension_id == ""
811795
assert (
812796
mapping.hooks["3f5c8c8a-7b4d-4f9c-a4c0-7d5cb1a39f7e"].extension_name
813797
== "workflow-ext"
@@ -823,15 +807,15 @@ def test_from_dict_only_tools(self):
823807
"""Parse with only tools key present."""
824808
data = {
825809
"tools": {
826-
"prefix_tool": {
810+
"my_tool": {
827811
"extensionName": "my-ext",
828812
"extensionVersion": "1",
829813
"extensionId": "id-1",
830814
}
831815
}
832816
}
833817
mapping = ExtensionSourceMapping.from_dict(data)
834-
assert mapping.tools["prefix_tool"].extension_name == "my-ext"
818+
assert mapping.tools["my_tool"].extension_name == "my-ext"
835819
assert mapping.hooks == {}
836820

837821
def test_from_dict_only_hooks(self):
@@ -902,7 +886,7 @@ def test_from_dict_with_source_new_format(self):
902886
],
903887
"source": {
904888
"tools": {
905-
"sap_mcp_servicenow_v1_create_ticket": {
889+
"create_ticket": {
906890
"extensionName": "servicenow-ext",
907891
"extensionVersion": "2",
908892
"extensionId": "uuid-sn",
@@ -919,18 +903,9 @@ def test_from_dict_with_source_new_format(self):
919903
}
920904
impl = ExtensionCapabilityImplementation.from_dict(data)
921905
assert impl.source is not None
922-
assert (
923-
impl.source.tools["sap_mcp_servicenow_v1_create_ticket"].extension_name
924-
== "servicenow-ext"
925-
)
926-
assert (
927-
impl.source.tools["sap_mcp_servicenow_v1_create_ticket"].extension_version
928-
== "2"
929-
)
930-
assert (
931-
impl.source.tools["sap_mcp_servicenow_v1_create_ticket"].extension_id
932-
== "uuid-sn"
933-
)
906+
assert impl.source.tools["create_ticket"].extension_name == "servicenow-ext"
907+
assert impl.source.tools["create_ticket"].extension_version == "2"
908+
assert impl.source.tools["create_ticket"].extension_id == "uuid-sn"
934909
assert (
935910
impl.source.hooks["3f5c8c8a-7b4d-4f9c-a4c0-7d5cb1a39f7e"].extension_name
936911
== "workflow-ext"
@@ -942,20 +917,14 @@ def test_from_dict_with_source_old_format(self):
942917
"capabilityId": "default",
943918
"mcpServers": [],
944919
"source": {
945-
"tools": {"sap_mcp_servicenow_v1_create_ticket": "servicenow-ext"},
920+
"tools": {"create_ticket": "servicenow-ext"},
946921
"hooks": {"3f5c8c8a-7b4d-4f9c-a4c0-7d5cb1a39f7e": "workflow-ext"},
947922
},
948923
}
949924
impl = ExtensionCapabilityImplementation.from_dict(data)
950925
assert impl.source is not None
951-
assert (
952-
impl.source.tools["sap_mcp_servicenow_v1_create_ticket"].extension_name
953-
== "servicenow-ext"
954-
)
955-
assert (
956-
impl.source.tools["sap_mcp_servicenow_v1_create_ticket"].extension_version
957-
== ""
958-
)
926+
assert impl.source.tools["create_ticket"].extension_name == "servicenow-ext"
927+
assert impl.source.tools["create_ticket"].extension_version == ""
959928
assert (
960929
impl.source.hooks["3f5c8c8a-7b4d-4f9c-a4c0-7d5cb1a39f7e"].extension_name
961930
== "workflow-ext"

0 commit comments

Comments
 (0)