Skip to content

Commit e429fb1

Browse files
Agw new token fetch (#136)
Co-authored-by: Max Heidinger <max.heidinger@sap.com>
1 parent 500b699 commit e429fb1

15 files changed

Lines changed: 823 additions & 240 deletions

File tree

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "sap-cloud-sdk"
3-
version = "0.19.3"
3+
version = "0.20.0"
44
description = "SAP Cloud SDK for Python"
55
readme = "README.md"
66
license = "Apache-2.0"

src/sap_cloud_sdk/agentgateway/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
]
5353
"""
5454

55-
from sap_cloud_sdk.agentgateway._models import MCPTool
55+
from sap_cloud_sdk.agentgateway._models import AuthResult, MCPTool
5656
from sap_cloud_sdk.agentgateway.config import ClientConfig
5757
from sap_cloud_sdk.agentgateway.agw_client import create_client, AgentGatewayClient
5858
from sap_cloud_sdk.agentgateway.exceptions import (
@@ -69,6 +69,7 @@
6969
# Configuration
7070
"ClientConfig",
7171
# Data models
72+
"AuthResult",
7273
"MCPTool",
7374
# Exceptions
7475
"AgentGatewaySDKError",

src/sap_cloud_sdk/agentgateway/_customer.py

Lines changed: 10 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
- Tool invocation: mTLS + jwt-bearer grant → user-scoped token (principal propagation)
99
"""
1010

11-
import asyncio
1211
import json
1312
import logging
1413
import os
@@ -432,17 +431,18 @@ async def _list_server_tools(
432431

433432
async def get_mcp_tools_customer(
434433
credentials: CustomerCredentials,
434+
system_token: str,
435435
timeout: float,
436-
app_tid: str | None = None,
437436
) -> list[MCPTool]:
438437
"""List all MCP tools from servers defined in credentials.
439438
440439
Iterates over all integrationDependencies in the credentials file and
441-
discovers tools from each MCP server using mTLS client credentials.
440+
discovers tools from each MCP server using a pre-fetched system token.
442441
443442
Args:
444443
credentials: Customer credentials with integrationDependencies.
445-
app_tid: BTP Application Tenant ID of subscriber (optional).
444+
system_token: Pre-fetched raw system token for authentication.
445+
timeout: HTTP timeout in seconds for MCP server calls.
446446
447447
Returns:
448448
List of MCPTool objects from all servers.
@@ -459,12 +459,6 @@ async def get_mcp_tools_customer(
459459

460460
logger.info("Discovering tools from %d MCP server(s)", len(dependencies))
461461

462-
# Get system token for discovery
463-
loop = asyncio.get_running_loop()
464-
system_token = await loop.run_in_executor(
465-
None, get_system_token_mtls, credentials, timeout, app_tid
466-
)
467-
468462
tools: list[MCPTool] = []
469463

470464
for dep in dependencies:
@@ -490,53 +484,30 @@ async def get_mcp_tools_customer(
490484

491485

492486
async def call_mcp_tool_customer(
493-
credentials: CustomerCredentials,
494487
tool: MCPTool,
495-
user_token: str | None,
488+
auth_token: str,
496489
timeout: float,
497-
app_tid: str | None = None,
498490
**kwargs,
499491
) -> str:
500492
"""Invoke an MCP tool using customer flow.
501493
502-
If user_token is provided, exchanges it for an AGW-scoped token to preserve
503-
user identity for principal propagation. Otherwise, falls back to system token.
494+
Uses a pre-fetched token (either user-scoped or system-scoped) for
495+
authentication against the MCP server.
504496
505497
Args:
506-
credentials: Customer credentials.
507498
tool: MCPTool to invoke.
508-
user_token: User's JWT token for principal propagation (optional).
509-
If None, system token is used instead (no principal propagation).
510-
app_tid: BTP Application Tenant ID of subscriber (optional).
499+
auth_token: Pre-fetched raw access token for authentication.
500+
timeout: HTTP timeout in seconds for the MCP server call.
511501
**kwargs: Tool input parameters.
512502
513503
Returns:
514504
Tool execution result as string.
515505
"""
516506
logger.info("Calling tool '%s' on server '%s'", tool.name, tool.server_name)
517507

518-
loop = asyncio.get_running_loop()
519-
520-
if user_token:
521-
# Exchange user token for AGW-scoped token (with principal propagation)
522-
agw_token = await loop.run_in_executor(
523-
None, exchange_user_token, credentials, user_token, timeout, app_tid
524-
)
525-
else:
526-
# TODO: IBD workaround - use system token when user_token is not available.
527-
# This bypasses principal propagation. Remove this fallback once IBD
528-
# supports proper user token flow.
529-
logger.warning(
530-
"No user_token provided - using system token for tool invocation. "
531-
"Principal propagation will NOT work."
532-
)
533-
agw_token = await loop.run_in_executor(
534-
None, get_system_token_mtls, credentials, timeout, app_tid
535-
)
536-
537508
async with httpx.AsyncClient(
538509
headers={
539-
"Authorization": f"Bearer {agw_token}",
510+
"Authorization": f"Bearer {auth_token}",
540511
"x-correlation-id": str(uuid.uuid4()),
541512
},
542513
timeout=timeout,

0 commit comments

Comments
 (0)