Coverage for session_mgmt_mcp/tools/session_tools.py: 0.00%
153 statements
« prev ^ index » next coverage.py v7.10.6, created at 2025-09-01 05:22 -0700
« prev ^ index » next coverage.py v7.10.6, created at 2025-09-01 05:22 -0700
1#!/usr/bin/env python3
2"""Session management MCP tools.
4This module provides tools for managing Claude session lifecycle including
5initialization, checkpoints, and cleanup.
6"""
8import shutil
9import subprocess
10from pathlib import Path
12from session_mgmt_mcp.core import SessionLifecycleManager
13from session_mgmt_mcp.utils.logging import get_session_logger
15# Global session manager
16session_manager = SessionLifecycleManager()
17logger = get_session_logger()
20# Tool implementations
21async def _init_impl(working_directory: str | None = None) -> str:
22 """Implementation for init tool."""
23 output = []
24 output.append("🚀 Claude Session Initialization via MCP Server")
25 output.append("=" * 60)
27 try:
28 # Use the session manager for initialization
29 result = await session_manager.initialize_session(working_directory)
31 if result["success"]:
32 output.append(f"📁 Current project: {result['project']}")
33 output.append(f"📂 Working directory: {result['working_directory']}")
34 output.append(f"🏠 Claude directory: {result['claude_directory']}")
35 output.append(f"📊 Initial quality score: {result['quality_score']}/100")
37 # Add project context info
38 context = result["project_context"]
39 context_items = sum(1 for detected in context.values() if detected)
40 output.append(
41 f"🎯 Project context: {context_items}/{len(context)} indicators detected",
42 )
44 # Add UV setup
45 output.extend(_setup_uv_dependencies(Path(result["working_directory"])))
47 # Add recommendations
48 recommendations = result["quality_data"].get("recommendations", [])
49 if recommendations:
50 output.append("\n💡 Setup recommendations:")
51 for rec in recommendations[:3]:
52 output.append(f" • {rec}")
54 output.append("\n✅ Session initialization completed successfully!")
56 else:
57 output.append(f"❌ Session initialization failed: {result['error']}")
59 except Exception as e:
60 logger.exception("Session initialization error", error=str(e))
61 output.append(f"❌ Unexpected error during initialization: {e}")
63 return "\n".join(output)
66async def _checkpoint_impl() -> str:
67 """Implementation for checkpoint tool."""
68 output = []
69 output.append(
70 f"🔍 Claude Session Checkpoint - {session_manager.current_project or 'Current Project'}",
71 )
72 output.append("=" * 50)
74 try:
75 result = await session_manager.checkpoint_session()
77 if result["success"]:
78 # Add quality assessment output
79 output.extend(result["quality_output"])
81 # Add git checkpoint output
82 output.extend(result["git_output"])
84 output.append(f"\n⏰ Checkpoint completed at: {result['timestamp']}")
85 output.append(
86 "\n💡 Use this checkpoint data to track session progress and identify optimization opportunities.",
87 )
89 else:
90 output.append(f"❌ Checkpoint failed: {result['error']}")
92 except Exception as e:
93 logger.exception("Checkpoint error", error=str(e))
94 output.append(f"❌ Unexpected checkpoint error: {e}")
96 return "\n".join(output)
99async def _end_impl() -> str:
100 """Implementation for end tool."""
101 output = []
102 output.append("🏁 Claude Session End - Cleanup and Handoff")
103 output.append("=" * 50)
105 try:
106 result = await session_manager.end_session()
108 if result["success"]:
109 summary = result["summary"]
110 output.append(f"📁 Project: {summary['project']}")
111 output.append(
112 f"📊 Final quality score: {summary['final_quality_score']}/100",
113 )
114 output.append(f"⏰ Session ended: {summary['session_end_time']}")
116 # Add final recommendations
117 recommendations = summary.get("recommendations", [])
118 if recommendations:
119 output.append("\n🎯 Final recommendations for future sessions:")
120 for rec in recommendations[:5]:
121 output.append(f" • {rec}")
123 output.append("\n📝 Session Summary:")
124 output.append(f" • Working directory: {summary['working_directory']}")
125 output.append(" • Session data has been logged for future reference")
126 output.append(" • All temporary resources have been cleaned up")
128 output.append("\n✅ Session ended successfully!")
129 output.append(
130 "💡 Use the session data to improve future development workflows.",
131 )
133 else:
134 output.append(f"❌ Session end failed: {result['error']}")
136 except Exception as e:
137 logger.exception("Session end error", error=str(e))
138 output.append(f"❌ Unexpected error during session end: {e}")
140 return "\n".join(output)
143async def _status_impl(working_directory: str | None = None) -> str:
144 """Implementation for status tool."""
145 output = []
146 output.append("📊 Claude Session Status Report")
147 output.append("=" * 40)
149 try:
150 result = await session_manager.get_session_status(working_directory)
152 if result["success"]:
153 output.append(f"📁 Project: {result['project']}")
154 output.append(f"📂 Working directory: {result['working_directory']}")
155 output.append(f"📊 Quality score: {result['quality_score']}/100")
157 # Quality breakdown
158 breakdown = result["quality_breakdown"]
159 output.append("\n📈 Quality breakdown:")
160 output.append(f" • Project health: {breakdown['project_health']:.1f}/40")
161 output.append(f" • Permissions: {breakdown['permissions']:.1f}/20")
162 output.append(
163 f" • Session tools: {breakdown['session_management']:.1f}/20",
164 )
165 output.append(f" • Tool availability: {breakdown['tools']:.1f}/20")
167 # System health
168 health = result["system_health"]
169 output.append("\n🏥 System health:")
170 output.append(
171 f" • UV package manager: {'✅' if health['uv_available'] else '❌'}",
172 )
173 output.append(
174 f" • Git repository: {'✅' if health['git_repository'] else '❌'}",
175 )
176 output.append(
177 f" • Claude directory: {'✅' if health['claude_directory'] else '❌'}",
178 )
180 # Project context
181 context = result["project_context"]
182 context_items = sum(1 for detected in context.values() if detected)
183 output.append(
184 f"\n🎯 Project context: {context_items}/{len(context)} indicators",
185 )
187 # Key indicators
188 key_indicators = [
189 ("pyproject.toml", context.get("has_pyproject_toml", False)),
190 ("Git repository", context.get("has_git_repo", False)),
191 ("Test suite", context.get("has_tests", False)),
192 ("Documentation", context.get("has_docs", False)),
193 ]
195 for name, detected in key_indicators:
196 status_icon = "✅" if detected else "❌"
197 output.append(f" • {name}: {status_icon}")
199 # Recommendations
200 recommendations = result["recommendations"]
201 if recommendations:
202 output.append("\n💡 Recommendations:")
203 for rec in recommendations[:3]:
204 output.append(f" • {rec}")
206 output.append(f"\n⏰ Status generated: {result['timestamp']}")
208 else:
209 output.append(f"❌ Status check failed: {result['error']}")
211 except Exception as e:
212 logger.exception("Status check error", error=str(e))
213 output.append(f"❌ Unexpected error during status check: {e}")
215 return "\n".join(output)
218def _setup_uv_dependencies(current_dir: Path) -> list[str]:
219 """Set up UV dependencies and requirements.txt generation."""
220 output = []
221 output.append("\n" + "=" * 50)
222 output.append("📦 UV Package Management Setup")
223 output.append("=" * 50)
225 # Check if uv is available
226 uv_available = shutil.which("uv") is not None
227 if not uv_available:
228 output.append("⚠️ UV not found in PATH")
229 output.append("💡 Install UV: curl -LsSf https://astral.sh/uv/install.sh | sh")
230 return output
232 # Check for pyproject.toml
233 pyproject_path = current_dir / "pyproject.toml"
234 if pyproject_path.exists():
235 output.append("✅ Found pyproject.toml - UV project detected")
237 # Run uv sync if dependencies need updating
238 try:
239 sync_result = subprocess.run(
240 ["uv", "sync"],
241 check=False,
242 cwd=current_dir,
243 capture_output=True,
244 text=True,
245 timeout=60,
246 )
248 if sync_result.returncode == 0:
249 output.append("✅ UV dependencies synchronized")
250 else:
251 output.append(f"⚠️ UV sync had issues: {sync_result.stderr}")
252 except subprocess.TimeoutExpired:
253 output.append(
254 "⚠️ UV sync timed out - dependencies may need manual attention",
255 )
256 except Exception as e:
257 output.append(f"⚠️ UV sync error: {e}")
258 else:
259 output.append("ℹ️ No pyproject.toml found")
260 output.append("💡 Consider running 'uv init' to create a new UV project")
262 return output
265def register_session_tools(mcp_server) -> None:
266 """Register all session management tools with the MCP server."""
268 @mcp_server.tool()
269 async def init(working_directory: str | None = None) -> str:
270 """Initialize Claude session with comprehensive setup including UV dependencies and automation tools.
272 Args:
273 working_directory: Optional working directory override (defaults to PWD environment variable or current directory)
275 """
276 return await _init_impl(working_directory)
278 @mcp_server.tool()
279 async def checkpoint() -> str:
280 """Perform mid-session quality checkpoint with workflow analysis and optimization recommendations."""
281 return await _checkpoint_impl()
283 @mcp_server.tool()
284 async def end() -> str:
285 """End Claude session with cleanup, learning capture, and handoff file creation."""
286 return await _end_impl()
288 @mcp_server.tool()
289 async def status(working_directory: str | None = None) -> str:
290 """Get current session status and project context information with health checks.
292 Args:
293 working_directory: Optional working directory override (defaults to PWD environment variable or current directory)
295 """
296 return await _status_impl(working_directory)