This document describes the new hybrid tag-based approach for endpoint discovery in the OBP-MCP server. This approach is designed to be more cost-effective and efficient than the previous RAG (Retrieval Augmented Generation) based system.
The hybrid approach follows a three-step process:
┌─────────────────────────────────────────────────────────────┐
│ User Query (e.g., "I need account endpoints") │
└─────────────────────┬───────────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────┐
│ 1. Tag Classification │
│ → Identify relevant tags (Account, Bank, etc.) │
└─────────────────────┬───────────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────┐
│ 2. list_endpoints_by_tag(tags) │
│ → Returns lightweight endpoint summaries │
│ → Only: id, name, method, path, summary, tags │
│ → ~20-50 endpoints, minimal tokens │
└─────────────────────┬───────────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────┐
│ 3. Main LLM selects specific endpoint(s) │
└─────────────────────┬───────────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────┐
│ 4. get_endpoint_schema(endpoint_id) │
│ → Fetch full schema ONLY for selected endpoint(s) │
└─────────────────────┬───────────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────┐
│ 5. call_obp_api(endpoint_id, params) │
│ → LLM constructs and executes request │
└─────────────────────────────────────────────────────────────┘
- No RAG infrastructure: Eliminates vector database overhead
- Minimal token usage: Lightweight index (~50-100 tokens per endpoint)
- On-demand schema loading: Full schemas loaded only when needed
- No grader/reformulator: Simpler processing pipeline
- Fast tag-based filtering: Quick endpoint discovery
- Lazy schema loading: Reduces initial load time
- Caching support: Schemas cached after first load
- Handles 600+ endpoints: Designed for large API surfaces
- Tag-based organization: Natural categorization
- Extensible: Easy to add new endpoints
Get available OBP API endpoints filtered by tags.
Parameters:
tags(List[str]): List of tag names to filter endpoints- Examples:
["Account", "Transaction"],["Bank"],[](all endpoints)
- Examples:
Returns:
- JSON object with:
count: Number of matching endpointsendpoints: Array of endpoint summaries
Example:
list_endpoints_by_tag(["Account", "Bank"])Response:
{
"count": 4,
"endpoints": [
{
"id": "vVERSION-privateAccountsAtOneBank",
"method": "GET",
"path": "/obp/vVERSION/banks/{BANK_ID}/accounts",
"operation_id": "vVERSION-privateAccountsAtOneBank",
"summary": "Get Accounts at Bank (Private)",
"tags": ["Account", "Bank"]
},
...
]
}Get the full OpenAPI schema for a specific endpoint.
Parameters:
endpoint_id(str): The unique identifier (operationId) of the endpoint- Example:
"vVERSION-getBanks"
- Example:
Returns:
- JSON object with full OpenAPI schema including:
- Parameters (path, query, body)
- Request/response schemas
- Descriptions and examples
Example:
get_endpoint_schema("vVERSION-getBanks")Execute an OBP API request to a specific endpoint.
Parameters:
endpoint_id(str): The unique identifier of the endpointpath_params(dict, optional): Path parameters (e.g.,{"BANK_ID": "123"})query_params(dict, optional): Query parameters (e.g.,{"limit": 10})body(dict, optional): Request body for POST/PUT requestsheaders(dict, optional): Additional HTTP headers
Returns:
- JSON object with:
status_code: HTTP status codeendpoint_id: The endpoint calledmethod: HTTP method usedurl: Full URL calledresponse: API response data
Example:
call_obp_api(
"vVERSION-getBanks",
query_params={"limit": 5}
)# Get all Account-related endpoints
result = list_endpoints_by_tag(["Account"])Review the summaries and identify the endpoint you need based on:
- Method (GET, POST, PUT, DELETE)
- Path (the URL pattern)
- Summary (brief description)
# Get detailed schema for the selected endpoint
schema = get_endpoint_schema("vVERSION-accountById")# Execute the API request
response = call_obp_api(
"vVERSION-accountById",
path_params={
"BANK_ID": "my-bank-id",
"ACCOUNT_ID": "my-account-id"
},
headers={
"Authorization": "DirectLogin token=..."
}
)The endpoint index is stored in database/endpoint_index.json and contains:
{
"endpoints": {
"vVERSION-getBanks": {
"id": "vVERSION-getBanks",
"method": "GET",
"path": "/obp/vVERSION/banks",
"operation_id": "vVERSION-getBanks",
"summary": "Get Banks",
"tags": ["Bank"]
},
...
}
}To regenerate the endpoint index from the OBP API:
# Generate index for static endpoints (default)
python scripts/generate_endpoint_index.py
# Generate index for dynamic endpoints
python scripts/generate_endpoint_index.py --endpoints dynamic
# Generate index for all endpoints
python scripts/generate_endpoint_index.py --endpoints all
# Specify custom output file
python scripts/generate_endpoint_index.py --output /path/to/custom_index.jsonRequirements:
OBP_BASE_URLenvironment variable (e.g.,https://apisandbox.openbankproject.com)OBP_VERSION_TO_CALLenvironment variable — version of the OBP meta-endpoint to call (e.g.,v7.0.0)API_VERSION_OF_INTERESTenvironment variable —requestedApiVersionfor the endpoint catalog (e.g.,v7.0.0)
The following tools are now deprecated but remain available for backward compatibility:
Status: DEPRECATED
Replacement: Use list_endpoints_by_tag() → get_endpoint_schema() → call_obp_api()
Why deprecated:
- More expensive (uses vector database + LLM grading)
- Higher token usage
- Slower response time
- Complex RAG pipeline
If you're currently using retrieve_endpoints():
Old approach:
# Single step with RAG
endpoints = retrieve_endpoints("I need to get bank accounts")
# Returns: Full schemas for multiple endpoints (expensive)New approach:
# Step 1: Get lightweight summaries
endpoints = list_endpoints_by_tag(["Account", "Bank"])
# Step 2: Select the right endpoint (LLM can help here)
# Let's say we want "vVERSION-privateAccountsAtOneBank"
# Step 3: Get full schema only if needed
schema = get_endpoint_schema("vVERSION-privateAccountsAtOneBank")
# Step 4: Make the API call
response = call_obp_api(
"vVERSION-privateAccountsAtOneBank",
path_params={"BANK_ID": "gh.29.uk"}
)| Aspect | Old RAG Approach | New Hybrid Approach |
|---|---|---|
| Initial Load | All schemas loaded | Lightweight index only |
| Token Usage | High (full schemas) | Low (summaries first) |
| Response Time | Slower (vector search + grading) | Faster (tag filtering) |
| Infrastructure | Vector DB required | Simple JSON file |
| Accuracy | Good | Better (explicit selection) |
| Cost | Higher | Lower |
| Maintenance | Complex | Simple |
The EndpointIndex class (src/tools/endpoint_index.py) provides:
- Lazy loading: Schemas loaded on first access
- Caching: Loaded schemas cached in memory
- Tag filtering: Fast tag-based search
- Reusability: Leverages existing database loader code
- Use operationId as endpoint ID: Ensures unique, stable identifiers
- Reuse existing fetch functions: Avoids code duplication with
populate_vector_db.py - Separate index from schemas: Keeps index lightweight
- Tag-based discovery: Natural categorization for banking APIs
Potential improvements for the future:
- Smart tag classifier: Use a small LLM or rules engine to suggest tags from natural language queries
- Schema caching: Persist loaded schemas to disk for faster subsequent loads
- Index versioning: Track API version changes
- Advanced filtering: Support for filtering by method, path patterns, etc.
- Batch operations: Support multiple endpoint calls in a single request
For questions or issues with the hybrid routing system:
- Check the logs for detailed error messages
- Verify environment variables are set correctly
- Ensure the endpoint index is up to date
- Review endpoint summaries before requesting full schemas