Skip to main content
Glama
path_resolver.py6.97 kB
""" Shared path resolution utilities for RBT and general Markdown documents. This module provides simple helper functions that wrap the PathResolver class from rbt_mcp_server, making it easy to resolve paths and read documents without managing PathResolver instances. @REQ: REQ-graphiti-chunk-mcp @BP: BP-graphiti-chunk-mcp @TASK: TASK-001-PathResolver """ import os from pathlib import Path from typing import Optional from rbt_mcp_server.path_resolver import PathResolver as _PathResolver # Default root directory (can be overridden) _DEFAULT_ROOT = str(Path(__file__).parent.parent.absolute()) _resolver_cache: Optional[_PathResolver] = None def _get_resolver(root_dir: Optional[str] = None) -> _PathResolver: """ Get or create a PathResolver instance. Uses a cached instance when root_dir matches the default, creates a new instance otherwise. Args: root_dir: Root directory for documents (defaults to project root) Returns: PathResolver instance @REQ: REQ-graphiti-chunk-mcp @BP: BP-graphiti-chunk-mcp @TASK: TASK-001-PathResolver """ global _resolver_cache if root_dir is None: root_dir = _DEFAULT_ROOT # Use cached resolver if root matches default if root_dir == _DEFAULT_ROOT and _resolver_cache is not None: return _resolver_cache # Create new resolver resolver = _PathResolver(root_dir) # Cache it if it's the default if root_dir == _DEFAULT_ROOT: _resolver_cache = resolver return resolver def resolve_path( project_id: str, feature_id: Optional[str] = None, doc_type: Optional[str] = None, file_path: Optional[str] = None, root_dir: Optional[str] = None ) -> str: """ Resolve document path and return the absolute file system path. This function wraps the PathResolver class from rbt_mcp_server, providing a simple interface for path resolution. Supports: - RBT documents: Specify project_id, feature_id, and doc_type (REQ/BP/TASK) - General documents: Specify project_id and file_path (relative to docs/) - TASK documents: Supports partial matching (e.g., "001" matches "TASK-001-*.md") - .new.md priority: Prefers .new.md over .md when both exist Args: project_id: Project identifier (required) feature_id: Feature identifier (optional, required for RBT docs) doc_type: Document type ('REQ', 'BP', 'TASK') for RBT docs file_path: For RBT TASK docs: TASK identifier (e.g., "001") For general docs: Relative path from docs/ dir (e.g., "architecture/overview.md") root_dir: Root directory for documents (defaults to project root) Returns: Absolute file system path to the document Raises: ValueError: If invalid parameter combination FileNotFoundError: If resolved file doesn't exist Examples: # RBT Blueprint document >>> resolve_path("knowledge-smith", "graphiti-chunk-mcp", "BP") '/path/to/knowledge-smith/features/graphiti-chunk-mcp/BP-graphiti-chunk-mcp.md' # TASK document with partial matching >>> resolve_path("knowledge-smith", "graphiti-chunk-mcp", "TASK", "001") '/path/to/knowledge-smith/features/graphiti-chunk-mcp/tasks/TASK-001-PathResolver.md' # General document (file_path is relative to docs/ directory) >>> resolve_path("knowledge-smith", file_path="architecture/overview.md") '/path/to/knowledge-smith/docs/architecture/overview.md' @REQ: REQ-graphiti-chunk-mcp @BP: BP-graphiti-chunk-mcp @TASK: TASK-001-PathResolver """ resolver = _get_resolver(root_dir) # Use PathResolver.resolve() to get PathInfo path_info = resolver.resolve( project_id=project_id, feature_id=feature_id, doc_type=doc_type, file_path=file_path ) # Check if file exists (for backward compatibility) if not path_info.file_exists: raise FileNotFoundError( f"Document not found: {path_info.file_path}\n" f"Parameters: project_id={project_id}, feature_id={feature_id}, " f"doc_type={doc_type}, file_path={file_path}" ) # Return the resolved file path return path_info.file_path def read_document( project_id: str, feature_id: Optional[str] = None, doc_type: Optional[str] = None, file_path: Optional[str] = None, root_dir: Optional[str] = None ) -> str: """ Resolve document path and return its content as a string. This function first resolves the path using resolve_path(), then reads and returns the file content. Args: project_id: Project identifier (required) feature_id: Feature identifier (optional, required for RBT docs) doc_type: Document type ('REQ', 'BP', 'TASK') for RBT docs file_path: For RBT TASK docs: TASK identifier (e.g., "001") For general docs: Relative path from docs/ dir (e.g., "README.md") root_dir: Root directory for documents (defaults to project root) Returns: Document content as a UTF-8 string Raises: ValueError: If invalid parameter combination FileNotFoundError: If resolved file doesn't exist IOError: If file cannot be read Examples: # Read RBT Blueprint >>> content = read_document("knowledge-smith", "graphiti-chunk-mcp", "BP") >>> print(content[:50]) '---\nid: BP-graphiti-chunk-mcp\ngroup_id: knowledg...' # Read TASK document >>> content = read_document("knowledge-smith", "graphiti-chunk-mcp", "TASK", "001") >>> "PathResolver" in content True # Read general document (file_path relative to docs/) >>> content = read_document("knowledge-smith", file_path="README.md") @REQ: REQ-graphiti-chunk-mcp @BP: BP-graphiti-chunk-mcp @TASK: TASK-001-PathResolver """ # Resolve the path resolved_path = resolve_path( project_id=project_id, feature_id=feature_id, doc_type=doc_type, file_path=file_path, root_dir=root_dir ) # Read and return content try: with open(resolved_path, 'r', encoding='utf-8') as f: return f.read() except FileNotFoundError: raise FileNotFoundError(f"Document not found: {resolved_path}") except Exception as e: raise IOError(f"Failed to read document {resolved_path}: {str(e)}") def set_default_root(root_dir: str) -> None: """ Set the default root directory for path resolution. This is useful for testing or when working with multiple projects. Args: root_dir: New default root directory @REQ: REQ-graphiti-chunk-mcp @BP: BP-graphiti-chunk-mcp @TASK: TASK-001-PathResolver """ global _DEFAULT_ROOT, _resolver_cache _DEFAULT_ROOT = root_dir _resolver_cache = None # Clear cache to force recreation

Latest Blog Posts

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/leo7nel23/KnowkedgeSmith-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server