We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Lyellr88/marm-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
"""System endpoints for MARM MCP Server."""
from fastapi import HTTPException, APIRouter
import sqlite3
import logging
from datetime import datetime, timezone
from typing import List, Dict, Optional
# Setup logging for security error tracking
logger = logging.getLogger(__name__)
# Import core components
from core.memory import memory
from core.events import events
from config.settings import SEMANTIC_SEARCH_AVAILABLE, SCHEDULER_AVAILABLE, SERVER_VERSION
from core.response_limiter import MCPResponseLimiter
from core.rate_limiter import rate_limiter
# Import the documentation loader function
# This will need to be imported from the services module when it's created
# from services.documentation import load_marm_documentation
# Create router for system endpoints
router = APIRouter(prefix="", tags=["System"])
@router.get("/health", include_in_schema=False)
async def health_check():
"""Health check endpoint for Docker and monitoring"""
try:
# Test database connection
with memory.get_connection() as conn:
conn.execute("SELECT 1").fetchone()
return {
"status": "healthy",
"service": "MARM MCP Server",
"version": SERVER_VERSION,
"timestamp": datetime.now(timezone.utc).isoformat(),
"database": "connected",
"semantic_search": "available" if SEMANTIC_SEARCH_AVAILABLE else "text_only"
}
except Exception as e:
# Log detailed error server-side for debugging (secure)
logger.error(f"Health check failed: {str(e)}", exc_info=True)
# Return generic error message to external users (secure)
return {
"status": "unhealthy",
"service": "MARM MCP Server",
"version": SERVER_VERSION,
"timestamp": datetime.now(timezone.utc).isoformat(),
"error": "Service temporarily unavailable"
}
@router.get("/ready", include_in_schema=False)
async def readiness_check():
"""Readiness check endpoint - service ready to handle requests"""
try:
# Test database connection and basic functionality
with memory.get_connection() as conn:
conn.execute("SELECT COUNT(*) FROM memories").fetchone()
conn.execute("SELECT COUNT(*) FROM sessions").fetchone()
return {
"status": "ready",
"service": "MARM MCP Server",
"version": SERVER_VERSION,
"timestamp": datetime.now(timezone.utc).isoformat(),
"endpoints": {
"mcp": "http://localhost:8001/mcp",
"websocket": "ws://localhost:8001/mcp/ws",
"docs": "http://localhost:8001/docs"
}
}
except Exception as e:
# Log detailed error server-side for debugging (secure)
logger.error(f"Readiness check failed: {str(e)}", exc_info=True)
# Return generic error message to external users (secure)
return {
"status": "not_ready",
"service": "MARM MCP Server",
"version": SERVER_VERSION,
"timestamp": datetime.now(timezone.utc).isoformat(),
"error": "Service not ready"
}
@router.get("/marm_current_context", operation_id="marm_current_context", include_in_schema=False)
async def marm_current_context():
"""
๐ Get current date and system context
Provides current date/time to prevent AI date confusion
"""
now = datetime.now(timezone.utc)
return {
"current_date": now.strftime("%Y-%m-%d"),
"current_time": now.strftime("%H:%M:%S UTC"),
"formatted_date": now.strftime("%A, %B %d, %Y"),
"context": f"Today is {now.strftime('%A, %B %d, %Y')} at {now.strftime('%H:%M UTC')}",
"system_status": "operational",
"semantic_search": "available" if SEMANTIC_SEARCH_AVAILABLE else "text_only",
"scheduler": "available" if SCHEDULER_AVAILABLE else "disabled"
}
@router.post("/marm_reload_docs", operation_id="marm_reload_docs")
async def marm_reload_docs():
"""
๐ Reload MARM documentation into memory system
Refreshes all documentation files and core knowledge in the database
"""
try:
# This will be implemented when we create the services module
# await load_marm_documentation()
return {
"status": "success",
"message": "๐ MARM documentation reloaded successfully",
"timestamp": datetime.now(timezone.utc).isoformat()
}
except Exception as e:
raise HTTPException(status_code=500, detail=f"Failed to reload documentation: {str(e)}")
@router.get("/marm_system_info", operation_id="marm_system_info")
async def marm_system_info():
"""
โน๏ธ Get comprehensive system information and loaded documentation
Shows what documentation is available and system capabilities
"""
try:
# Get notebook entries (documentation)
with memory.get_connection() as conn:
cursor = conn.execute('''
SELECT name, LENGTH(data) as size, created_at, updated_at
FROM notebook_entries
WHERE name LIKE 'marm_%'
ORDER BY updated_at DESC
''')
docs = [{"name": r[0], "size_chars": r[1], "created": r[2], "updated": r[3]}
for r in cursor.fetchall()]
# Get memory count
cursor = conn.execute('SELECT COUNT(*) FROM memories')
memory_count = cursor.fetchone()[0]
# Get session count
cursor = conn.execute('SELECT COUNT(*) FROM sessions')
session_count = cursor.fetchone()[0]
# Build response with health status and size monitoring
current_time = datetime.now(timezone.utc)
response = {
"status": "operational",
"version": SERVER_VERSION,
"service": "MARM MCP Server",
"timestamp": current_time.isoformat(),
"health": {
"status": "healthy",
"service": "MARM MCP Server",
"version": SERVER_VERSION,
"timestamp": current_time.isoformat(),
"docker_health_endpoint": "/health"
},
"capabilities": {
"semantic_search": SEMANTIC_SEARCH_AVAILABLE,
"scheduler": SCHEDULER_AVAILABLE,
"documentation_loaded": len(docs) > 0
},
"database_stats": {
"notebook_entries": len(docs),
"memories": memory_count,
"sessions": session_count
},
"loaded_documentation": docs,
"mcp_endpoint": "http://localhost:8001/mcp",
"api_docs": "http://localhost:8001/docs"
}
# Check response size and truncate documentation list if needed
response_size = MCPResponseLimiter.estimate_response_size(response)
if response_size > MCPResponseLimiter.CONTENT_LIMIT:
# Truncate documentation list to fit
original_doc_count = len(docs)
# Keep removing docs until response fits
while response_size > MCPResponseLimiter.CONTENT_LIMIT and docs:
docs.pop()
response["loaded_documentation"] = docs
response_size = MCPResponseLimiter.estimate_response_size(response)
# Add truncation notice
if len(docs) < original_doc_count:
response["_mcp_truncated"] = True
response["_truncation_reason"] = "Documentation list truncated for MCP size compliance"
response["_total_docs_available"] = original_doc_count
response["_docs_shown"] = len(docs)
return response
except Exception as e:
raise HTTPException(status_code=500, detail=f"Failed to get system info: {str(e)}")