2424if str (_project_root ) not in sys .path :
2525 sys .path .insert (0 , str (_project_root ))
2626
27- from fastmcp import FastMCP
27+ from fastmcp import FastMCP , Context
2828from fastmcp .server .dependencies import get_access_token
29+ from fastmcp .server .elicitation import AcceptedElicitation , DeclinedElicitation , CancelledElicitation
2930
3031from src .tools .endpoint_index import get_endpoint_index
3132from src .tools .glossary_index import get_glossary_index
3233
3334from mcp_server_obp .lifespan import lifespan
3435from mcp_server_obp .auth import get_auth_provider
36+ from mcp_server_obp .elicitation import elicit_consent , ApprovalConsent
3537
3638logger = logging .getLogger (__name__ )
3739
3840# Initialize authentication provider based on environment configuration
3941# Supports: keycloak, obp-oidc, or none (disabled)
4042# See auth.py for configuration details
4143auth = get_auth_provider ()
42-
44+
45+
4346
4447mcp = FastMCP (
4548 "Open Bank Project" ,
@@ -142,12 +145,13 @@ def get_endpoint_schema(endpoint_id: str) -> str:
142145
143146
144147@mcp .tool ()
145- def call_obp_api (
148+ async def call_obp_api (
149+ ctx : Context ,
146150 endpoint_id : str ,
147151 path_params : dict = None ,
148152 query_params : dict = None ,
149153 body : dict = None ,
150- headers : dict = None
154+ headers : dict = None ,
151155) -> str :
152156 """
153157 Execute an OBP API request to a specific endpoint.
@@ -173,7 +177,7 @@ def call_obp_api(
173177 index = get_endpoint_index ()
174178
175179 # Get endpoint info from lightweight index
176- endpoint = index .get_endpoint_by_id (endpoint_id )
180+ endpoint = index .get_endpoint_schema (endpoint_id )
177181 if not endpoint :
178182 return json .dumps ({
179183 "error" : f"Endpoint '{ endpoint_id } ' not found" ,
@@ -205,6 +209,47 @@ def call_obp_api(
205209 method = endpoint .method .value # HttpMethod enum value
206210 request_headers = headers or {}
207211
212+ auth_method = os .getenv ("OBP_AUTHORIZATION_VIA" , "none" ).lower ()
213+ match auth_method :
214+ case "oauth" :
215+ logger .info ("Using OAuth authorization method for OBP API call" )
216+ access_token = get_access_token ()
217+ if not access_token :
218+ logger .error ("No access token available in context for OAuth authorization." )
219+ else :
220+ # TODO: Elicit a simple approval here to confirm tool use?
221+ request_headers ["Authorization" ] = f"Bearer { access_token } "
222+ case "consent" :
223+ # Elicit user consent
224+ logger .info ("Eliciting user consent for OBP API call" )
225+ from mcp_server_obp .elicitation import elicit_consent
226+
227+ response = await elicit_consent (ctx , endpoint )
228+ match response :
229+ case AcceptedElicitation (data = consent ):
230+ # For now just assume the consent is valid, but we might want to decode the JWT in the future
231+ logger .info ("User consent accepted for OBP API call" )
232+ request_headers ["Consent-JWT" ] = consent .consent_jwt
233+ case DeclinedElicitation ():
234+ logger .info ("User declined consent for OBP API call" )
235+ return json .dumps ({
236+ "error" : "User declined consent for this endpoint"
237+ }, indent = 2 )
238+ case CancelledElicitation ():
239+ logger .info ("User cancelled consent elicitation for OBP API call" )
240+ return json .dumps ({
241+ "error" : "User cancelled operation."
242+ }, indent = 2 )
243+ case "none" :
244+ # No authorization
245+ logger .info ("No authorization method used for OBP API call" )
246+ pass
247+ case _:
248+ logger .error (f"Invalid OBP_AUTHORIZATION_VIA value: { auth_method } " )
249+ return json .dumps ({
250+ "error" : f"Internal server error."
251+ }, indent = 2 )
252+
208253 # Make the request
209254 logger .info (f"Calling OBP API: { method } { url } " )
210255
0 commit comments