Skip to main content
Glama

Persistent-Code MCP Server

by sparshdrolia
persistent_code_cli.py9.04 kB
#!/usr/bin/env python3 """ Persistent-Code Command Line Interface A command-line utility for managing the Persistent-Code MCP server. """ import os import sys import json import argparse import subprocess from pathlib import Path import textwrap import platform def parse_args(): """Parse command line arguments.""" parser = argparse.ArgumentParser( description="Persistent-Code CLI - Manage your Persistent-Code MCP server" ) # Add subparsers for different commands subparsers = parser.add_subparsers(dest="command", help="Command to run") # Init command init_parser = subparsers.add_parser("init", help="Initialize a new project") init_parser.add_argument( "--project-name", "-p", default="default", help="Name of the project" ) init_parser.add_argument( "--storage-dir", "-s", default=None, help="Directory to store persistent data" ) # Start command start_parser = subparsers.add_parser("start", help="Start the MCP server") start_parser.add_argument( "--project-name", "-p", default="default", help="Name of the project" ) start_parser.add_argument( "--storage-dir", "-s", default=None, help="Directory to store persistent data" ) # Status command status_parser = subparsers.add_parser("status", help="Show server status") # Configure command config_parser = subparsers.add_parser("config", help="Configure Claude for Desktop") config_parser.add_argument( "--project-name", "-p", default="default", help="Name of the project" ) # List command list_parser = subparsers.add_parser("list", help="List available projects") # Analyze command analyze_parser = subparsers.add_parser("analyze", help="Analyze code files") analyze_parser.add_argument( "--project-name", "-p", default="default", help="Name of the project" ) analyze_parser.add_argument( "--file", "-f", required=True, help="File to analyze" ) # Parse arguments args = parser.parse_args() # If no command specified, show help if not args.command: parser.print_help() sys.exit(1) return args def get_claude_config_path(): """Get the path to the Claude for Desktop config file.""" if platform.system() == "Darwin": # macOS return os.path.expanduser("~/Library/Application Support/Claude/claude_desktop_config.json") elif platform.system() == "Windows": return os.path.join(os.environ.get("APPDATA", ""), "Claude", "claude_desktop_config.json") else: return os.path.expanduser("~/.config/Claude/claude_desktop_config.json") def init_project(args): """Initialize a new project.""" cmd = [sys.executable, "-m", "persistent_code", "init", "--project-name", args.project_name] if args.storage_dir: cmd.extend(["--storage-dir", args.storage_dir]) print(f"Initializing project '{args.project_name}'...") subprocess.run(cmd) print(f"Project '{args.project_name}' initialized successfully.") print("\nTo start the server:") print(f" {sys.executable} -m persistent_code serve --project-name {args.project_name}") # Suggest configuring Claude print("\nTo configure Claude for Desktop:") print(f" {sys.executable} {__file__} config --project-name {args.project_name}") def start_server(args): """Start the MCP server.""" cmd = [sys.executable, "-m", "persistent_code", "serve", "--project-name", args.project_name] if args.storage_dir: cmd.extend(["--storage-dir", args.storage_dir]) print(f"Starting server for project '{args.project_name}'...") print("Press Ctrl+C to stop the server.") print("") try: subprocess.run(cmd) except KeyboardInterrupt: print("\nServer stopped.") def show_status(): """Show the server status.""" # Check if server is running (very basic) try: with open("/tmp/persistent_code_pid", "r") as f: pid = f.read().strip() # Check if process is running os.kill(int(pid), 0) print(f"Server is running (PID: {pid})") except (FileNotFoundError, ProcessLookupError, PermissionError): print("Server is not running") def configure_claude(args): """Configure Claude for Desktop.""" config_path = get_claude_config_path() config_dir = os.path.dirname(config_path) # Ensure config directory exists os.makedirs(config_dir, exist_ok=True) # Get absolute path to Python executable python_path = os.path.abspath(sys.executable) # Get absolute path to project directory project_dir = os.path.abspath(os.path.dirname(__file__)) # Load existing config if it exists config = {"mcpServers": {}} if os.path.exists(config_path): try: with open(config_path, "r") as f: config = json.load(f) if "mcpServers" not in config: config["mcpServers"] = {} except json.JSONDecodeError: print(f"Warning: Invalid JSON in {config_path}. Creating a new config.") # Add Persistent-Code configuration config["mcpServers"]["persistent-code"] = { "command": python_path, "args": [ "-m", "persistent_code", "serve", "--project-name", args.project_name ], "cwd": project_dir } # Write the config with open(config_path, "w") as f: json.dump(config, f, indent=2) print(f"Claude for Desktop configured to use project '{args.project_name}'") print(f"Configuration written to: {config_path}") print("\nPlease restart Claude for Desktop for the changes to take effect.") def list_projects(): """List available projects.""" # Check storage directory for projects storage_dir = os.path.join(os.path.dirname(__file__), "storage") if not os.path.exists(storage_dir): print("No projects found. Storage directory doesn't exist.") return projects = [] # Find all project directories with graph files for item in os.listdir(storage_dir): item_path = os.path.join(storage_dir, item) if os.path.isdir(item_path): # Check if project has a graph file graph_file = os.path.join(item_path, f"{item}_graph.json") config_file = os.path.join(item_path, "config.json") if os.path.exists(graph_file) or os.path.exists(config_file): projects.append(item) if not projects: print("No projects found.") return print("Available projects:") for project in sorted(projects): print(f" - {project}") print("\nTo start a server for a project:") print(f" {sys.executable} {__file__} start --project-name <project-name>") def analyze_file(args): """Analyze a code file.""" if not os.path.exists(args.file): print(f"Error: File not found: {args.file}") return # Read the file with open(args.file, "r") as f: code = f.read() # Get file path file_path = os.path.abspath(args.file) # Run the analyzer from persistent_code.knowledge_graph import KnowledgeGraph from persistent_code.code_analyzer import CodeAnalyzer # Create a knowledge graph graph = KnowledgeGraph(args.project_name) # Create a code analyzer analyzer = CodeAnalyzer(graph) # Analyze the code print(f"Analyzing {file_path}...") component_id = analyzer.analyze_code( code_text=code, file_path=file_path ) # Print summary of what was found component = graph.get_component(component_id) print(f"\nFile analyzed: {component['name']}") print(f"Component ID: {component_id}") # Count nodes in the graph node_count = len(graph.graph.nodes) print(f"Total components in graph: {node_count}") # Print types of components found component_types = {} for _, data in graph.graph.nodes(data=True): comp_type = data.get("type", "unknown") component_types[comp_type] = component_types.get(comp_type, 0) + 1 print("\nComponents by type:") for comp_type, count in component_types.items(): print(f" - {comp_type}: {count}") def main(): """Main entry point.""" args = parse_args() if args.command == "init": init_project(args) elif args.command == "start": start_server(args) elif args.command == "status": show_status() elif args.command == "config": configure_claude(args) elif args.command == "list": list_projects() elif args.command == "analyze": analyze_file(args) if __name__ == "__main__": main()

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/sparshdrolia/Persistent-code-mcp'

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