3535
3636# MCP Server and Keycloak configuration
3737MCP_SERVER_URL = os .getenv (
38- "MCP_SERVER_URL" ,
39- "https://mcp-gps-key-n7pc5ej-ca.ashymeadow-ae27942e.eastus2.azurecontainerapps.io/mcp"
38+ "MCP_SERVER_URL" , "https://mcp-gps-key-n7pc5ej-ca.ashymeadow-ae27942e.eastus2.azurecontainerapps.io/mcp"
4039)
4140KEYCLOAK_REALM_URL = os .getenv (
42- "KEYCLOAK_REALM_URL" ,
43- "https://mcp-gps-key-n7pc5ej-kc.ashymeadow-ae27942e.eastus2.azurecontainerapps.io/realms/mcp"
41+ "KEYCLOAK_REALM_URL" , "https://mcp-gps-key-n7pc5ej-kc.ashymeadow-ae27942e.eastus2.azurecontainerapps.io/realms/mcp"
4442)
4543
4644# Configure language model based on API_HOST
7472async def register_client_via_dcr () -> tuple [str , str ]:
7573 """Register a new client dynamically using Keycloak's DCR endpoint."""
7674 dcr_url = f"{ KEYCLOAK_REALM_URL } /clients-registrations/openid-connect"
77-
75+
7876 logger .info ("📝 Registering client via DCR..." )
79-
77+
8078 async with httpx .AsyncClient () as client :
8179 response = await client .post (
8280 dcr_url ,
@@ -87,24 +85,24 @@ async def register_client_via_dcr() -> tuple[str, str]:
8785 },
8886 headers = {"Content-Type" : "application/json" },
8987 )
90-
88+
9189 if response .status_code not in (200 , 201 ):
9290 raise Exception (f"DCR failed: { response .status_code } - { response .text } " )
93-
91+
9492 data = response .json ()
9593 client_id = data ["client_id" ]
9694 client_secret = data ["client_secret" ]
97-
95+
9896 logger .info (f"✅ Registered client: { client_id [:20 ]} ..." )
9997 return client_id , client_secret
10098
10199
102100async def get_keycloak_token (client_id : str , client_secret : str ) -> str :
103101 """Get an access token from Keycloak using client_credentials grant."""
104102 token_url = f"{ KEYCLOAK_REALM_URL } /protocol/openid-connect/token"
105-
103+
106104 logger .info ("🔑 Getting access token from Keycloak..." )
107-
105+
108106 async with httpx .AsyncClient () as client :
109107 response = await client .post (
110108 token_url ,
@@ -115,14 +113,14 @@ async def get_keycloak_token(client_id: str, client_secret: str) -> str:
115113 },
116114 headers = {"Content-Type" : "application/x-www-form-urlencoded" },
117115 )
118-
116+
119117 if response .status_code != 200 :
120118 raise Exception (f"Failed to get token: { response .status_code } - { response .text } " )
121-
119+
122120 token_data = response .json ()
123121 access_token = token_data ["access_token" ]
124122 expires_in = token_data .get ("expires_in" , "unknown" )
125-
123+
126124 logger .info (f"✅ Got access token (expires in { expires_in } s)" )
127125 return access_token
128126
@@ -134,9 +132,9 @@ async def run_agent() -> None:
134132 # Register client via DCR and get token
135133 client_id , client_secret = await register_client_via_dcr ()
136134 access_token = await get_keycloak_token (client_id , client_secret )
137-
135+
138136 logger .info (f"📡 Connecting to MCP server: { MCP_SERVER_URL } " )
139-
137+
140138 # Initialize MCP client with Bearer token auth
141139 client = MultiServerMCPClient (
142140 {
@@ -154,7 +152,7 @@ async def run_agent() -> None:
154152 logger .info ("🔧 Getting available tools..." )
155153 tools = await client .get_tools ()
156154 logger .info (f"✅ Found { len (tools )} tools: { [t .name for t in tools ]} " )
157-
155+
158156 agent = create_agent (base_model , tools )
159157
160158 # Prepare query with context
@@ -172,7 +170,7 @@ async def run_agent() -> None:
172170 logger .info ("=" * 60 )
173171 logger .info ("📊 Agent Response:" )
174172 logger .info ("=" * 60 )
175-
173+
176174 final_message = response ["messages" ][- 1 ]
177175 print (final_message .content )
178176
@@ -187,7 +185,7 @@ async def main():
187185 print (f" LLM Host: { API_HOST } " )
188186 print (" Auth: Dynamic Client Registration (DCR)" )
189187 print ()
190-
188+
191189 await run_agent ()
192190
193191
0 commit comments