mirror of
https://github.com/dnlbauer/cordra-mcp.git
synced 2026-09-12 06:35:30 +00:00
feat: replace CordraPy with http requests
This commit is contained in:
@@ -1,12 +1,15 @@
|
||||
"""Cordra client wrapper using CordraPy."""
|
||||
"""Cordra client wrapper using HTTP requests."""
|
||||
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
import cordra
|
||||
import requests
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from .config import CordraConfig
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DigitalObject(BaseModel):
|
||||
"""Model for a Cordra digital object."""
|
||||
@@ -30,7 +33,7 @@ class CordraNotFoundError(CordraClientError):
|
||||
|
||||
|
||||
class CordraClient:
|
||||
"""Client for interacting with Cordra repository."""
|
||||
"""Client for interacting with Cordra repository using HTTP requests."""
|
||||
|
||||
def __init__(self, config: CordraConfig) -> None:
|
||||
"""Initialize the Cordra client.
|
||||
@@ -39,6 +42,14 @@ class CordraClient:
|
||||
config: Configuration settings for the Cordra connection
|
||||
"""
|
||||
self.config = config
|
||||
self.session = requests.Session()
|
||||
self.session.verify = config.verify_ssl
|
||||
|
||||
# Set up authentication
|
||||
if config.username and config.password:
|
||||
self.session.auth = (config.username, config.password)
|
||||
elif config.username or config.password:
|
||||
logger.warning("Only username or password provided, not both. Authentication may fail.")
|
||||
|
||||
async def get_object(self, object_id: str) -> DigitalObject:
|
||||
"""Retrieve a digital object by its ID.
|
||||
@@ -54,28 +65,34 @@ class CordraClient:
|
||||
CordraClientError: For other API errors
|
||||
"""
|
||||
try:
|
||||
cordra_obj: dict[str, Any] = cordra.CordraObject.read(
|
||||
host=self.config.cordra_url, #type: ignore
|
||||
obj_id=object_id,
|
||||
username=self.config.username,
|
||||
password=self.config.password,
|
||||
verify=self.config.verify_ssl,
|
||||
full=True # Get full object details including metadata, paylods, etc.
|
||||
)
|
||||
# Build URL: cordra_base_url/objects/prefix/postfix
|
||||
url = f"{self.config.cordra_url}/objects/{object_id}"
|
||||
|
||||
# Add full=true parameter to get complete object details
|
||||
params = {"full": "true"}
|
||||
|
||||
response = self.session.get(url, params=params, timeout=self.config.timeout)
|
||||
|
||||
if response.status_code == 404:
|
||||
raise CordraNotFoundError(f"Object not found: {object_id}")
|
||||
|
||||
response.raise_for_status()
|
||||
cordra_obj = response.json()
|
||||
|
||||
return DigitalObject(
|
||||
id=object_id,
|
||||
type=cordra_obj['type'],
|
||||
content=cordra_obj['content'],
|
||||
type=cordra_obj.get('type', ''),
|
||||
content=cordra_obj.get('content', cordra_obj),
|
||||
metadata=cordra_obj.get('metadata'),
|
||||
acl=cordra_obj.get('acl'),
|
||||
payloads=cordra_obj.get('payloads'),
|
||||
)
|
||||
|
||||
except CordraNotFoundError:
|
||||
raise
|
||||
except requests.RequestException as e:
|
||||
raise CordraClientError(f"Failed to retrieve object {object_id}: {e}") from e
|
||||
except Exception as e:
|
||||
error_msg = str(e).lower()
|
||||
if 'not found' in error_msg or '404' in error_msg:
|
||||
raise CordraNotFoundError(f"Object not found: {object_id}") from e
|
||||
raise CordraClientError(f"Failed to retrieve object {object_id}: {e}") from e
|
||||
|
||||
async def find(self, query: str) -> list[dict[str, Any]]:
|
||||
@@ -91,19 +108,22 @@ class CordraClient:
|
||||
CordraClientError: If there's an API error
|
||||
"""
|
||||
try:
|
||||
# Use CordraPy to find objects
|
||||
# TODO - need to handle pagination, but the CordraPy API does not support it.
|
||||
response: dict[str, Any] = cordra.CordraObject.find(
|
||||
self.config.cordra_url, # type: ignore
|
||||
query
|
||||
)
|
||||
# Use HTTP GET request to search endpoint
|
||||
url = f"{self.config.cordra_url}/search"
|
||||
params = {"query": query}
|
||||
|
||||
response = self.session.get(url, params=params, timeout=self.config.timeout)
|
||||
response.raise_for_status()
|
||||
|
||||
search_result = response.json()
|
||||
|
||||
# Extract the results array from the response
|
||||
if isinstance(response, dict) and 'results' in response:
|
||||
return response['results']
|
||||
if isinstance(search_result, dict) and 'results' in search_result:
|
||||
return search_result['results']
|
||||
else:
|
||||
return []
|
||||
|
||||
except Exception as e:
|
||||
except requests.RequestException as e:
|
||||
raise CordraClientError(f"Failed to search with query '{query}': {e}") from e
|
||||
|
||||
except Exception as e:
|
||||
raise CordraClientError(f"Failed to search with query '{query}': {e}") from e
|
||||
@@ -59,8 +59,8 @@ async def list_cordra_schemas() -> str:
|
||||
# Extract the names from the schema objects
|
||||
schema_names = []
|
||||
for schema in schemas:
|
||||
if isinstance(schema, dict) and 'name' in schema:
|
||||
schema_names.append(schema['name'])
|
||||
if isinstance(schema, dict) and 'content' in schema and 'name' in schema['content']:
|
||||
schema_names.append(schema['content']['name'])
|
||||
|
||||
result = {
|
||||
"schemas": schema_names,
|
||||
|
||||
Reference in New Issue
Block a user