mirror of
https://github.com/dnlbauer/cordra-mcp.git
synced 2026-09-10 21:55:30 +00:00
feat: init resources
This commit is contained in:
@@ -5,6 +5,7 @@ import json
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from mcp.server.fastmcp import FastMCP
|
from mcp.server.fastmcp import FastMCP
|
||||||
|
from mcp.server.fastmcp.resources import FunctionResource
|
||||||
|
|
||||||
from .client import (
|
from .client import (
|
||||||
CordraClient,
|
CordraClient,
|
||||||
@@ -24,21 +25,25 @@ cordra_client = CordraClient(config)
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@mcp.resource("cordra://objects/{prefix}/{suffix}", name="cordra-object", description="Retrieve a Cordra digital object by ID")
|
@mcp.resource(
|
||||||
|
"cordra://objects/{prefix}/{suffix}",
|
||||||
|
name="cordra-object",
|
||||||
|
description="Retrieve a Cordra digital object by ID",
|
||||||
|
)
|
||||||
async def get_cordra_object(prefix: str, suffix: str) -> str:
|
async def get_cordra_object(prefix: str, suffix: str) -> str:
|
||||||
"""Retrieve a Cordra digital object by its ID.
|
"""Retrieve a Cordra digital object by its ID.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
prefix: The prefix part of the object ID (e.g., 'wildlive')
|
prefix: The prefix part of the object ID (e.g., 'wildlive')
|
||||||
suffix: The suffix part of the object ID (e.g., '7a4b7b65f8bb155ad36d')
|
suffix: The suffix part of the object ID (e.g., '7a4b7b65f8bb155ad36d')
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
JSON representation of the digital object
|
JSON representation of the digital object
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RuntimeError: If the object is not found or there's an API error
|
RuntimeError: If the object is not found or there's an API error
|
||||||
"""
|
"""
|
||||||
|
|
||||||
object_id = f"{prefix}/{suffix}"
|
object_id = f"{prefix}/{suffix}"
|
||||||
try:
|
try:
|
||||||
digital_object = await cordra_client.get_object(object_id)
|
digital_object = await cordra_client.get_object(object_id)
|
||||||
@@ -69,33 +74,32 @@ async def create_schema_resource(schema_name: str) -> str:
|
|||||||
raise RuntimeError(f"Failed to retrieve schema {schema_name}: {e}") from e
|
raise RuntimeError(f"Failed to retrieve schema {schema_name}: {e}") from e
|
||||||
|
|
||||||
|
|
||||||
async def register_schema_resources():
|
async def register_schema_resources() -> None:
|
||||||
"""Register individual schema resources dynamically."""
|
"""Register individual schema resources dynamically."""
|
||||||
try:
|
try:
|
||||||
# Get all available schemas
|
# Get all available schemas
|
||||||
schemas = await cordra_client.find("type:Schema")
|
schemas = await cordra_client.find("type:Schema")
|
||||||
|
|
||||||
# Add individual schema resources
|
|
||||||
for schema in schemas:
|
for schema in schemas:
|
||||||
if isinstance(schema, dict) and 'content' in schema and 'name' in schema['content']:
|
schema_name = schema.get("content", {}).get("name")
|
||||||
schema_name = schema['content']['name']
|
if not schema_name:
|
||||||
|
logger.warning("Schema without a name found, skipping.")
|
||||||
# Create an async resource handler for this specific schema
|
continue
|
||||||
# Use a closure to capture the schema_name properly
|
|
||||||
def make_schema_handler(captured_name):
|
logger.info(f"Registering schema resource for cordra type {schema_name}")
|
||||||
async def schema_handler():
|
async def schema_fn(name: str = schema_name) -> str:
|
||||||
return await create_schema_resource(captured_name)
|
return await create_schema_resource(name)
|
||||||
return schema_handler
|
mcp.add_resource(
|
||||||
|
FunctionResource.from_function(
|
||||||
# Register using the decorator approach
|
uri=f"cordra://schemas/{schema_name}",
|
||||||
mcp.resource(
|
fn=schema_fn,
|
||||||
f"cordra://schemas/{schema_name}",
|
name=f"cordra-type-schema-{schema_name}",
|
||||||
name=f"cordra-schema-{schema_name}",
|
description=f"JSON schema for Cordra type {schema_name}",
|
||||||
description=f"Cordra schema definition for {schema_name}"
|
)
|
||||||
)(make_schema_handler(schema_name))
|
)
|
||||||
|
|
||||||
logger.info(f"Registered {len(schemas)} schema resources")
|
logger.info(f"Registered {len(schemas)} schema resources")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"Failed to register schema resources: {e}")
|
logger.warning(f"Failed to register schema resources: {e}")
|
||||||
|
|
||||||
@@ -106,13 +110,16 @@ async def ping() -> str:
|
|||||||
return "pong"
|
return "pong"
|
||||||
|
|
||||||
|
|
||||||
|
async def initialize_server() -> None:
|
||||||
|
"""Initialize server resources before starting."""
|
||||||
|
logger.info("Initializing Cordra MCP server...")
|
||||||
|
await register_schema_resources()
|
||||||
|
logger.info("Server initialization complete")
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
"""Main entry point for the MCP server."""
|
"""Main entry point for the MCP server."""
|
||||||
async def startup():
|
asyncio.run(initialize_server())
|
||||||
await register_schema_resources()
|
|
||||||
|
|
||||||
# Run startup tasks, then start the server
|
|
||||||
asyncio.run(startup())
|
|
||||||
mcp.run()
|
mcp.run()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user