11"""Tests for external token passing to MCP tools via ADK session."""
22
3- import uuid
4- from typing import Any
5-
6- import pytest
7- from agenticlayer .agent import AgentFactory
8- from agenticlayer .agent_to_a2a import _EXTERNAL_TOKEN_SESSION_KEY , to_a2a
9- from agenticlayer .config import McpTool
10- from asgi_lifespan import LifespanManager
11- from google .adk .agents .llm_agent import LlmAgent
12- from google .adk .models .lite_llm import LiteLlm
13- from httpx_retries import Retry
14- from pydantic import AnyHttpUrl
15- from starlette .testclient import TestClient
16-
17-
18- def create_send_message_request (
19- message_text : str = "Hello, agent!" ,
20- ) -> dict [str , Any ]:
21- """Helper function to create a valid A2A send message request."""
22- message_id = str (uuid .uuid4 ())
23- context_id = str (uuid .uuid4 ())
24- return {
25- "jsonrpc" : "2.0" ,
26- "id" : 1 ,
27- "method" : "message/send" ,
28- "params" : {
29- "message" : {
30- "role" : "user" ,
31- "parts" : [{"kind" : "text" , "text" : message_text }],
32- "messageId" : message_id ,
33- "contextId" : context_id ,
34- },
35- "metadata" : {},
36- },
37- }
38-
39-
40- def create_agent (
41- name : str = "test_agent" ,
42- ) -> LlmAgent :
43- return LlmAgent (
44- name = name ,
45- model = LiteLlm (model = "gemini/gemini-2.5-flash" ),
46- description = "Test agent" ,
47- instruction = "You are a test agent." ,
48- )
49-
50-
51- @pytest .mark .asyncio
52- async def test_external_token_stored_in_session () -> None :
53- """Test that X-External-Token header is captured and stored in ADK session state."""
54- # Given: An agent with a tool
55- agent = create_agent ()
56- tools = [McpTool (name = "test_tool" , url = AnyHttpUrl ("http://tool-1.local/mcp" ))]
57- test_token = "test-bearer-token-12345"
58-
59- # When: Creating an app and sending a request with X-External-Token header
60- rpc_url = "http://localhost:80/"
61- app = to_a2a (
62- agent = agent ,
63- rpc_url = rpc_url ,
64- tools = tools ,
65- agent_factory = AgentFactory (retry = Retry (total = 2 )),
66- )
67-
68- async with LifespanManager (app ) as manager :
69- client = TestClient (manager .app )
70-
71- # Send a request with the X-External-Token header
72- response = client .post (
73- "" ,
74- json = create_send_message_request (),
75- headers = {"X-External-Token" : test_token },
76- )
3+ from agenticlayer .agent import _get_mcp_headers_from_session
4+ from agenticlayer .constants import EXTERNAL_TOKEN_SESSION_KEY
5+ from google .adk .sessions .session import Session
776
78- # Then: The request should succeed
79- assert response .status_code == 200
807
81- # Note: We cannot directly verify the session state from the test client
82- # because the session is internal to the ADK executor. However, we can
83- # verify that the app starts correctly and processes the request, which
84- # means our custom executor is working.
85-
86-
87- @pytest .mark .asyncio
88- async def test_header_provider_retrieves_token_from_session () -> None :
8+ def test_header_provider_retrieves_token_from_session () -> None :
899 """Test that the header provider function can retrieve token from session state."""
90- from agenticlayer .agent import _get_mcp_headers_from_session
91- from google .adk .sessions .session import Session
92-
9310 # Given: A session with an external token stored
9411 test_token = "test-api-token-xyz"
9512 session = Session (
9613 id = "test-session" ,
9714 app_name = "test-app" ,
9815 user_id = "test-user" ,
99- state = {_EXTERNAL_TOKEN_SESSION_KEY : test_token },
16+ state = {EXTERNAL_TOKEN_SESSION_KEY : test_token },
10017 events = [],
10118 last_update_time = 0.0 ,
10219 )
@@ -115,12 +32,8 @@ def __init__(self, session):
11532 assert headers == {"X-External-Token" : test_token }
11633
11734
118- @pytest .mark .asyncio
119- async def test_header_provider_returns_empty_when_no_token () -> None :
35+ def test_header_provider_returns_empty_when_no_token () -> None :
12036 """Test that the header provider returns empty dict when no token is present."""
121- from agenticlayer .agent import _get_mcp_headers_from_session
122- from google .adk .sessions .session import Session
123-
12437 # Given: A session without an external token
12538 session = Session (
12639 id = "test-session" ,
@@ -145,13 +58,11 @@ def __init__(self, session):
14558 assert headers == {}
14659
14760
148- @pytest .mark .asyncio
149- async def test_header_provider_handles_none_context () -> None :
61+ def test_header_provider_handles_none_context () -> None :
15062 """Test that the header provider safely handles None context."""
151- from agenticlayer .agent import _get_mcp_headers_from_session
152-
15363 # When: Calling the header provider with None
15464 headers = _get_mcp_headers_from_session (None )
15565
15666 # Then: The headers should be empty (no exception)
15767 assert headers == {}
68+
0 commit comments