Skip to main content
Glama

marm-mcp

documentation.py10.4 kB
"""Documentation loading service for MARM MCP Server.""" from pathlib import Path from datetime import datetime, timezone import sqlite3 from typing import Dict, List # Import core components from core.memory import memory def guess_context_type(filename): """Smart context classification based on filename""" filename_lower = filename.lower() if "protocol" in filename_lower: return "protocol" elif "handbook" in filename_lower: return "handbook" elif "faq" in filename_lower: return "support" elif "readme" in filename_lower: return "general" elif "description" in filename_lower: return "general" elif "tool" in filename_lower or "reference" in filename_lower: return "reference" elif "workflow" in filename_lower or "pattern" in filename_lower: return "workflow" elif "troubleshoot" in filename_lower or "debug" in filename_lower: return "support" elif "integration" in filename_lower or "setup" in filename_lower: return "integration" elif "api" in filename_lower: return "api" elif "security" in filename_lower or "auth" in filename_lower: return "security" elif "config" in filename_lower or "setting" in filename_lower: return "config" elif "install" in filename_lower or "deploy" in filename_lower: return "installation" else: return "general" def get_docs_to_load(): """Auto-discover essential .md files only to avoid token overload""" # Try local development path first docs_dir = Path(__file__).parent.parent / "marm-docs" # If not found, try Docker path if not docs_dir.exists(): docs_dir = Path("/app/marm-docs") # Essential files only - keep startup lean essential_files = { "PROTOCOL.md", # Core commands - always needed "README.md" # Tool usage and getting started info } docs_to_load = [] seen_notebook_names = set() if docs_dir.exists(): for md_file in sorted(docs_dir.glob("*.md")): # Skip non-essential files to reduce token dump if md_file.name not in essential_files: continue filename = md_file.stem.lower() # "PROTOCOL.md" → "protocol" notebook_name = f"marm_{filename}" # Check for duplicate notebook names (same stem) if notebook_name in seen_notebook_names: print(f"WARNING: Duplicate notebook name detected: {notebook_name} (from {md_file.name})") # Add timestamp to make unique import time timestamp = str(int(time.time()))[-4:] # last 4 digits notebook_name = f"marm_{filename}_{timestamp}" print(f" Renamed to: {notebook_name}") seen_notebook_names.add(notebook_name) context_type = guess_context_type(filename) # Auto-generate config based on filename docs_to_load.append({ "file_path": f"marm-docs/{md_file.name}", "notebook_name": notebook_name, "context_type": context_type, "description": f"Essential: {md_file.name}" }) # Print visual QA table of loaded docs if docs_to_load: print(f"\n[DOCS] Loading essential documentation ({len(docs_to_load)} files):") print("+---------------------------------+--------------+-------------------------+") print("| File | Type | Notebook Name |") print("+---------------------------------+--------------+-------------------------+") for doc in docs_to_load: filename = doc["file_path"].split("/")[-1] print(f"| {filename:<31} | {doc['context_type']:<12} | {doc['notebook_name']:<23} |") print("+---------------------------------+--------------+-------------------------+") # Show what's available but not loaded all_files = set(f.name for f in docs_dir.glob("*.md")) skipped_files = all_files - essential_files if skipped_files: print(f"Available via marm_smart_recall: {', '.join(sorted(skipped_files))}") else: print("No essential documentation files found") else: print(f"WARNING: Documentation directory not found: {docs_dir}") return docs_to_load async def load_marm_documentation(): """Pre-populate the MCP server with core MARM documentation""" # Auto-discover all documentation files docs_to_load = get_docs_to_load() print("Loading MARM documentation into memory system...") for doc in docs_to_load: try: # Try to read the documentation file - works in both local and Docker # First try relative to current file location (local development) doc_path = Path(__file__).parent.parent / doc["file_path"] # If not found, try Docker app directory if not doc_path.exists(): doc_path = Path("/app") / doc["file_path"] if doc_path.exists(): with open(doc_path, 'r', encoding='utf-8') as f: content = f.read() # Store in memory system for semantic search await memory.store_memory( content=content, session="marm_system", context_type=doc["context_type"], metadata={ "doc_type": "documentation", "source_file": doc["file_path"], "description": doc["description"] } ) # Also store in notebook for easy reference embedding_bytes = None if memory.encoder: try: embedding = memory.encoder.encode(content) embedding_bytes = embedding.tobytes() except Exception as e: print(f"Failed to generate embedding for {doc['notebook_name']}: {e}") with sqlite3.connect(memory.db_path) as conn: conn.execute(''' INSERT OR REPLACE INTO notebook_entries (name, data, embedding, updated_at) VALUES (?, ?, ?, ?) ''', (doc["notebook_name"], content, embedding_bytes, datetime.now(timezone.utc).isoformat())) conn.commit() print(f"OK: Loaded {doc['notebook_name']} ({len(content)} chars)") else: print(f"WARNING: Documentation file not found: {doc_path}") except Exception as e: # Safe error printing - avoid unicode issues try: print(f"ERROR: Failed to load {doc['notebook_name']}: {str(e)}") except UnicodeEncodeError: print(f"ERROR: Failed to load {doc['notebook_name']}: {type(e).__name__}") # Add some core knowledge entries core_knowledge = [ { "name": "marm_commands_summary", "content": """MARM Core Commands Quick Reference: SESSION COMMANDS: - /start marm - Activates MARM memory and accuracy layers - /refresh marm - Refreshes active session state LOGGING COMMANDS: - /log session: [name] - Create or switch to named session - /log entry: [YYYY-MM-DD-topic-summary] - Add structured log entry - /log show: [session] - Display all entries and sessions - /log delete: [session/entry] - Delete specified session or entry REASONING COMMANDS: - /summary: [session] - Generate paste-ready context block - /context_bridge: [new topic] - Intelligent workflow transitions NOTEBOOK COMMANDS: - /notebook add: [name] [data] - Add new entry - /notebook use: [name1,name2] - Activate entries as instructions - /notebook show: - Display all saved entries - /notebook delete: [name] - Delete specific entry - /notebook clear: - Clear active list - /notebook status: - Show current active list""" }, { "name": "mcp_integration_guide", "content": """MARM MCP Server Integration Guide: This MCP server provides all MARM protocol functionality to Claude Desktop through these endpoints: MEMORY SYSTEM: - marm_smart_recall - Semantic search across all memories - marm_contextual_log - Auto-classifying memory storage PROTOCOL COMMANDS: - marm_start / marm_refresh - Session management - marm_log_session / marm_log_entry / marm_log_show / marm_log_delete - Logging - marm_summary / marm_context_bridge - Reasoning and workflow transitions - marm_notebook_* - All 6 notebook management functions SYSTEM: - marm_current_context - Current date/time and system status The MCP server uses semantic search with sentence transformers, SQLite storage, and event-driven automation for intelligent memory management.""" } ] for knowledge in core_knowledge: try: embedding_bytes = None if memory.encoder: try: embedding = memory.encoder.encode(knowledge["content"]) embedding_bytes = embedding.tobytes() except Exception as e: print(f"Failed to generate embedding for {knowledge['name']}: {e}") with sqlite3.connect(memory.db_path) as conn: conn.execute(''' INSERT OR REPLACE INTO notebook_entries (name, data, embedding, updated_at) VALUES (?, ?, ?, ?) ''', (knowledge["name"], knowledge["content"], embedding_bytes, datetime.now(timezone.utc).isoformat())) conn.commit() print(f"OK: Added core knowledge: {knowledge['name']}") except Exception as e: # Safe error printing - avoid unicode issues try: print(f"ERROR: Failed to add {knowledge['name']}: {str(e)}") except UnicodeEncodeError: print(f"ERROR: Failed to add {knowledge['name']}: {type(e).__name__}") print("MARM documentation database ready!")

MCP directory API

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