|
6 | 6 | from fastmcp import Context |
7 | 7 |
|
8 | 8 | from basic_memory.config import ConfigManager |
9 | | -from basic_memory.mcp.async_client import client |
| 9 | +from basic_memory.mcp.async_client import get_client |
10 | 10 | from basic_memory.mcp.server import mcp |
11 | 11 | from basic_memory.mcp.project_context import get_active_project |
12 | 12 | from basic_memory.services.sync_status_service import sync_status_tracker |
@@ -95,162 +95,163 @@ async def sync_status(project: Optional[str] = None, context: Context | None = N |
95 | 95 | """ |
96 | 96 | logger.info("MCP tool call tool=sync_status") |
97 | 97 |
|
98 | | - status_lines = [] |
| 98 | + async with get_client() as client: |
| 99 | + status_lines = [] |
99 | 100 |
|
100 | | - try: |
101 | | - from basic_memory.services.sync_status_service import sync_status_tracker |
102 | | - |
103 | | - # Get overall summary |
104 | | - summary = sync_status_tracker.get_summary() |
105 | | - is_ready = sync_status_tracker.is_ready |
106 | | - |
107 | | - # Header |
108 | | - status_lines.extend( |
109 | | - [ |
110 | | - "# Basic Memory Sync Status", |
111 | | - "", |
112 | | - f"**Current Status**: {summary}", |
113 | | - f"**System Ready**: {'✅ Yes' if is_ready else '🔄 Processing'}", |
114 | | - "", |
115 | | - ] |
116 | | - ) |
117 | | - |
118 | | - if is_ready: |
| 101 | + try: |
| 102 | + from basic_memory.services.sync_status_service import sync_status_tracker |
| 103 | + |
| 104 | + # Get overall summary |
| 105 | + summary = sync_status_tracker.get_summary() |
| 106 | + is_ready = sync_status_tracker.is_ready |
| 107 | + |
| 108 | + # Header |
119 | 109 | status_lines.extend( |
120 | 110 | [ |
121 | | - "✅ **All sync operations completed**", |
| 111 | + "# Basic Memory Sync Status", |
122 | 112 | "", |
123 | | - "- File indexing is complete", |
124 | | - "- Knowledge graphs are up to date", |
125 | | - "- All Basic Memory tools are fully operational", |
| 113 | + f"**Current Status**: {summary}", |
| 114 | + f"**System Ready**: {'✅ Yes' if is_ready else '🔄 Processing'}", |
126 | 115 | "", |
127 | | - "Your knowledge base is ready for use!", |
128 | 116 | ] |
129 | 117 | ) |
130 | 118 |
|
131 | | - # Show all projects status even when ready |
132 | | - status_lines.extend(_get_all_projects_status()) |
133 | | - else: |
134 | | - # System is still processing - show both active and all projects |
135 | | - all_sync_projects = sync_status_tracker.get_all_projects() |
136 | | - |
137 | | - active_projects = [ |
138 | | - p for p in all_sync_projects.values() if p.status.value in ["scanning", "syncing"] |
139 | | - ] |
140 | | - failed_projects = [p for p in all_sync_projects.values() if p.status.value == "failed"] |
141 | | - |
142 | | - if active_projects: |
| 119 | + if is_ready: |
143 | 120 | status_lines.extend( |
144 | 121 | [ |
145 | | - "🔄 **File synchronization in progress**", |
| 122 | + "✅ **All sync operations completed**", |
146 | 123 | "", |
147 | | - "Basic Memory is automatically processing all configured projects and building knowledge graphs.", |
148 | | - "This typically takes 1-3 minutes depending on the amount of content.", |
| 124 | + "- File indexing is complete", |
| 125 | + "- Knowledge graphs are up to date", |
| 126 | + "- All Basic Memory tools are fully operational", |
149 | 127 | "", |
150 | | - "**Currently Processing:**", |
| 128 | + "Your knowledge base is ready for use!", |
151 | 129 | ] |
152 | 130 | ) |
153 | 131 |
|
154 | | - for project_status in active_projects: |
155 | | - progress = "" |
156 | | - if project_status.files_total > 0: |
157 | | - progress_pct = ( |
158 | | - project_status.files_processed / project_status.files_total |
159 | | - ) * 100 |
160 | | - progress = f" ({project_status.files_processed}/{project_status.files_total}, {progress_pct:.0f}%)" |
| 132 | + # Show all projects status even when ready |
| 133 | + status_lines.extend(_get_all_projects_status()) |
| 134 | + else: |
| 135 | + # System is still processing - show both active and all projects |
| 136 | + all_sync_projects = sync_status_tracker.get_all_projects() |
161 | 137 |
|
162 | | - status_lines.append( |
163 | | - f"- **{project_status.project_name}**: {project_status.message}{progress}" |
| 138 | + active_projects = [ |
| 139 | + p for p in all_sync_projects.values() if p.status.value in ["scanning", "syncing"] |
| 140 | + ] |
| 141 | + failed_projects = [p for p in all_sync_projects.values() if p.status.value == "failed"] |
| 142 | + |
| 143 | + if active_projects: |
| 144 | + status_lines.extend( |
| 145 | + [ |
| 146 | + "🔄 **File synchronization in progress**", |
| 147 | + "", |
| 148 | + "Basic Memory is automatically processing all configured projects and building knowledge graphs.", |
| 149 | + "This typically takes 1-3 minutes depending on the amount of content.", |
| 150 | + "", |
| 151 | + "**Currently Processing:**", |
| 152 | + ] |
164 | 153 | ) |
165 | 154 |
|
166 | | - status_lines.extend( |
167 | | - [ |
168 | | - "", |
169 | | - "**What's happening:**", |
170 | | - "- Scanning and indexing markdown files", |
171 | | - "- Building entity and relationship graphs", |
172 | | - "- Setting up full-text search indexes", |
173 | | - "- Processing file changes and updates", |
174 | | - "", |
175 | | - "**What you can do:**", |
176 | | - "- Wait for automatic processing to complete - no action needed", |
177 | | - "- Use this tool again to check progress", |
178 | | - "- Simple operations may work already", |
179 | | - "- All projects will be available once sync finishes", |
180 | | - ] |
181 | | - ) |
182 | | - |
183 | | - # Handle failed projects (independent of active projects) |
184 | | - if failed_projects: |
185 | | - status_lines.extend(["", "❌ **Some projects failed to sync:**", ""]) |
186 | | - |
187 | | - for project_status in failed_projects: |
188 | | - status_lines.append( |
189 | | - f"- **{project_status.project_name}**: {project_status.error or 'Unknown error'}" |
| 155 | + for project_status in active_projects: |
| 156 | + progress = "" |
| 157 | + if project_status.files_total > 0: |
| 158 | + progress_pct = ( |
| 159 | + project_status.files_processed / project_status.files_total |
| 160 | + ) * 100 |
| 161 | + progress = f" ({project_status.files_processed}/{project_status.files_total}, {progress_pct:.0f}%)" |
| 162 | + |
| 163 | + status_lines.append( |
| 164 | + f"- **{project_status.project_name}**: {project_status.message}{progress}" |
| 165 | + ) |
| 166 | + |
| 167 | + status_lines.extend( |
| 168 | + [ |
| 169 | + "", |
| 170 | + "**What's happening:**", |
| 171 | + "- Scanning and indexing markdown files", |
| 172 | + "- Building entity and relationship graphs", |
| 173 | + "- Settings up full-text search indexes", |
| 174 | + "- Processing file changes and updates", |
| 175 | + "", |
| 176 | + "**What you can do:**", |
| 177 | + "- Wait for automatic processing to complete - no action needed", |
| 178 | + "- Use this tool again to check progress", |
| 179 | + "- Simple operations may work already", |
| 180 | + "- All projects will be available once sync finishes", |
| 181 | + ] |
190 | 182 | ) |
191 | 183 |
|
192 | | - status_lines.extend( |
193 | | - [ |
194 | | - "", |
195 | | - "**Next steps:**", |
196 | | - "1. Check the logs for detailed error information", |
197 | | - "2. Ensure file permissions allow read/write access", |
198 | | - "3. Try restarting the MCP server", |
199 | | - "4. If issues persist, consider filing a support issue", |
200 | | - ] |
201 | | - ) |
202 | | - elif not active_projects: |
203 | | - # No active or failed projects - must be pending |
204 | | - status_lines.extend( |
205 | | - [ |
206 | | - "⏳ **Sync operations pending**", |
207 | | - "", |
208 | | - "File synchronization has been queued but hasn't started yet.", |
209 | | - "This usually resolves automatically within a few seconds.", |
210 | | - ] |
211 | | - ) |
212 | | - |
213 | | - # Add comprehensive project status for all configured projects |
214 | | - all_projects_status = _get_all_projects_status() |
215 | | - if all_projects_status: |
216 | | - status_lines.extend(all_projects_status) |
| 184 | + # Handle failed projects (independent of active projects) |
| 185 | + if failed_projects: |
| 186 | + status_lines.extend(["", "❌ **Some projects failed to sync:**", ""]) |
| 187 | + |
| 188 | + for project_status in failed_projects: |
| 189 | + status_lines.append( |
| 190 | + f"- **{project_status.project_name}**: {project_status.error or 'Unknown error'}" |
| 191 | + ) |
| 192 | + |
| 193 | + status_lines.extend( |
| 194 | + [ |
| 195 | + "", |
| 196 | + "**Next steps:**", |
| 197 | + "1. Check the logs for detailed error information", |
| 198 | + "2. Ensure file permissions allow read/write access", |
| 199 | + "3. Try restarting the MCP server", |
| 200 | + "4. If issues persist, consider filing a support issue", |
| 201 | + ] |
| 202 | + ) |
| 203 | + elif not active_projects: |
| 204 | + # No active or failed projects - must be pending |
| 205 | + status_lines.extend( |
| 206 | + [ |
| 207 | + "⏳ **Sync operations pending**", |
| 208 | + "", |
| 209 | + "File synchronization has been queued but hasn't started yet.", |
| 210 | + "This usually resolves automatically within a few seconds.", |
| 211 | + ] |
| 212 | + ) |
217 | 213 |
|
218 | | - # Add explanation about automatic syncing if there are unsynced projects |
219 | | - unsynced_count = sum(1 for line in all_projects_status if "⏳" in line) |
220 | | - if unsynced_count > 0 and not is_ready: |
221 | | - status_lines.extend( |
222 | | - [ |
223 | | - "", |
224 | | - "**Note**: All configured projects will be automatically synced during startup.", |
225 | | - ] |
226 | | - ) |
| 214 | + # Add comprehensive project status for all configured projects |
| 215 | + all_projects_status = _get_all_projects_status() |
| 216 | + if all_projects_status: |
| 217 | + status_lines.extend(all_projects_status) |
| 218 | + |
| 219 | + # Add explanation about automatic syncing if there are unsynced projects |
| 220 | + unsynced_count = sum(1 for line in all_projects_status if "⏳" in line) |
| 221 | + if unsynced_count > 0 and not is_ready: |
| 222 | + status_lines.extend( |
| 223 | + [ |
| 224 | + "", |
| 225 | + "**Note**: All configured projects will be automatically synced during startup.", |
| 226 | + ] |
| 227 | + ) |
227 | 228 |
|
228 | | - # Add project context if provided |
229 | | - if project: |
230 | | - try: |
231 | | - active_project = await get_active_project(client, project, context) |
232 | | - status_lines.extend( |
233 | | - [ |
234 | | - "", |
235 | | - "---", |
236 | | - "", |
237 | | - f"**Active Project**: {active_project.name}", |
238 | | - f"**Project Path**: {active_project.home}", |
239 | | - ] |
240 | | - ) |
241 | | - except Exception as e: |
242 | | - logger.debug(f"Could not get project info: {e}") |
| 229 | + # Add project context if provided |
| 230 | + if project: |
| 231 | + try: |
| 232 | + active_project = await get_active_project(client, project, context) |
| 233 | + status_lines.extend( |
| 234 | + [ |
| 235 | + "", |
| 236 | + "---", |
| 237 | + "", |
| 238 | + f"**Active Project**: {active_project.name}", |
| 239 | + f"**Project Path**: {active_project.home}", |
| 240 | + ] |
| 241 | + ) |
| 242 | + except Exception as e: |
| 243 | + logger.debug(f"Could not get project info: {e}") |
243 | 244 |
|
244 | | - return "\n".join(status_lines) |
| 245 | + return "\n".join(status_lines) |
245 | 246 |
|
246 | | - except Exception as e: |
247 | | - return f"""# Sync Status - Error |
| 247 | + except Exception as e: |
| 248 | + return f"""# Sync Status - Error |
248 | 249 |
|
249 | 250 | ❌ **Unable to check sync status**: {str(e)} |
250 | 251 |
|
251 | 252 | **Troubleshooting:** |
252 | 253 | - The system may still be starting up |
253 | | -- Try waiting a few seconds and checking again |
| 254 | +- Try waiting a few seconds and checking again |
254 | 255 | - Check logs for detailed error information |
255 | 256 | - Consider restarting if the issue persists |
256 | 257 | """ |
0 commit comments