Compare commits

...
4 Commits
5 changed files with 129 additions and 28 deletions

No files matched your search

+9 -9
View File
@@ -24,12 +24,13 @@ Copy-Item target\release\mcp-memory-stub.exe C:\Users\reazul.ashraf\.local\bin\m
if (-not (Get-Process mcp-memory-server -ErrorAction SilentlyContinue)) { Start-Process -FilePath "C:\Users\reazul.ashraf\.local\bin\mcp-memory-server.exe" -WindowStyle Hidden -ErrorAction SilentlyContinue } if (-not (Get-Process mcp-memory-server -ErrorAction SilentlyContinue)) { Start-Process -FilePath "C:\Users\reazul.ashraf\.local\bin\mcp-memory-server.exe" -WindowStyle Hidden -ErrorAction SilentlyContinue }
``` ```
**Shutting Down:** If you need to stop or restart the background daemon (e.g., to replace the executable after a recompile), you MUST NEVER use brute-force OS kill commands (e.g., Stop-Process, pkill, or kill). Instead, you MUST ALWAYS use the server's built-in graceful shutdown mechanisms: **Shutting Down & Managing:** If you need to stop, start, or restart the background daemon (e.g., to replace the executable after a recompile), you MUST NEVER use brute-force OS kill commands (e.g., Stop-Process, pkill, or kill). Instead, you MUST ALWAYS use the built-in graceful shutdown mechanisms, which are wrapped neatly in the `justfile`:
1. The CLI flag: `--exit` (or `--restart`)
```powershell ```powershell
mcp-memory-server.exe --exit just start
just stop
just restart
``` ```
2. The HTTP endpoint: `POST http://127.0.0.1:3000/shutdown` Alternatively, you can gracefully shut down the server by invoking the executable with the `--exit` flag (`mcp-memory-server.exe --exit`) or hitting the HTTP endpoint (`POST http://127.0.0.1:3000/shutdown`).
` `
**Step 2:** Update your Windows ~/.gemini/config/mcp_config.json to point the CLI to the ultra-lightweight stub (since the server is already running in the background): **Step 2:** Update your Windows ~/.gemini/config/mcp_config.json to point the CLI to the ultra-lightweight stub (since the server is already running in the background):
`json `json
@@ -44,11 +45,10 @@ mcp-memory-server.exe --exit
` `
` `
### 2. WSL / Linux Installation (The Stub) ### 2. WSL / Linux Installation (The Stub)
Compile the ultra-lightweight stub as a static Linux binary (from the Windows host): Compile the ultra-lightweight stub as a native Linux binary directly from WSL (we do not use zigbuild):
`powershell ```powershell
cargo zigbuild --target x86_64-unknown-linux-musl --release -p mcp-memory-stub just deploy-stub-wsl
wsl.exe -d Ubuntu -e bash -c "cp /mnt/c/Users/reazul.ashraf/workspace/rust/mcp-memory/target/x86_64-unknown-linux-musl/release/mcp-memory-stub ~/.local/bin/mcp-memory-stub && chmod +x ~/.local/bin/mcp-memory-stub" ```
`
` `
Update your WSL ~/.gemini/config/mcp_config.json: Update your WSL ~/.gemini/config/mcp_config.json:
`json `json
+66 -12
View File
@@ -20,30 +20,68 @@ shutdown-server:
-$token = Get-Content "$env:USERPROFILE\.gemini\mcp_memory\admin.token" -ErrorAction SilentlyContinue; if ($token) { Invoke-RestMethod -Uri "http://127.0.0.1:3000/shutdown" -Method Post -Headers @{ Authorization = "Bearer $token" } -ErrorAction SilentlyContinue } else { Invoke-RestMethod -Uri "http://127.0.0.1:3000/shutdown" -Method Post -ErrorAction SilentlyContinue } -$token = Get-Content "$env:USERPROFILE\.gemini\mcp_memory\admin.token" -ErrorAction SilentlyContinue; if ($token) { Invoke-RestMethod -Uri "http://127.0.0.1:3000/shutdown" -Method Post -Headers @{ Authorization = "Bearer $token" } -ErrorAction SilentlyContinue } else { Invoke-RestMethod -Uri "http://127.0.0.1:3000/shutdown" -Method Post -ErrorAction SilentlyContinue }
Start-Sleep -Seconds 1 Start-Sleep -Seconds 1
-if (Get-Process mcp-memory-server, mcp-memory-stub, mcp-memory-win-nvim -ErrorAction SilentlyContinue) { Stop-Process -Name mcp-memory-server, mcp-memory-stub, mcp-memory-win-nvim -Force -ErrorAction SilentlyContinue } -if (Get-Process mcp-memory-server, mcp-memory-stub, mcp-memory-win-nvim -ErrorAction SilentlyContinue) { Stop-Process -Name mcp-memory-server, mcp-memory-stub, mcp-memory-win-nvim -Force -ErrorAction SilentlyContinue }
Start-Sleep -Seconds 2
# Build Windows-native binaries # Build Windows-native binaries
build-win: build-win: build-server build-stub-win build-nvim-win
Write-Host "Building Windows binaries..." -ForegroundColor Cyan
cargo build --release -p mcp-memory-server -p mcp-memory-stub -p mcp-memory-win-nvim
# Deploy Windows-native binaries # Deploy Windows-native binaries
deploy-win: shutdown-server deploy-win: deploy-server deploy-stub-win deploy-nvim-win deploy-rules-win
Write-Host "Deploying Windows binaries..." -ForegroundColor Cyan
Copy-Item -Force target\release\mcp-memory-stub.exe "C:\Users\reazul.ashraf\.local\bin\"; Copy-Item -Force target\release\mcp-memory-win-nvim.exe "C:\Users\reazul.ashraf\.local\bin\" build-server:
Write-Host "Building Windows Server..." -ForegroundColor Cyan
cargo build --release -p mcp-memory-server
deploy-server: shutdown-server
Write-Host "Deploying Windows Server..." -ForegroundColor Cyan
Copy-Item -Force target\release\mcp-memory-server.exe "C:\Users\reazul.ashraf\.local\bin\" Copy-Item -Force target\release\mcp-memory-server.exe "C:\Users\reazul.ashraf\.local\bin\"
build-stub-win:
Write-Host "Building Windows Stub..." -ForegroundColor Cyan
cargo build --release -p mcp-memory-stub
deploy-stub-win:
Write-Host "Deploying Windows Stub..." -ForegroundColor Cyan
-Stop-Process -Name mcp-memory-stub -Force -ErrorAction SilentlyContinue
Copy-Item -Force target\release\mcp-memory-stub.exe "C:\Users\reazul.ashraf\.local\bin\"
build-nvim-win:
Write-Host "Building Windows Nvim..." -ForegroundColor Cyan
cargo build --release -p mcp-memory-win-nvim
deploy-nvim-win:
Write-Host "Deploying Windows Nvim..." -ForegroundColor Cyan
-Stop-Process -Name mcp-memory-win-nvim -Force -ErrorAction SilentlyContinue
Copy-Item -Force target\release\mcp-memory-win-nvim.exe "C:\Users\reazul.ashraf\.local\bin\"
deploy-rules-win:
Write-Host "Deploying global Agent rules (Windows)..." -ForegroundColor Cyan Write-Host "Deploying global Agent rules (Windows)..." -ForegroundColor Cyan
if (!(Test-Path "C:\Users\reazul.ashraf\.gemini\config\rules")) { New-Item -ItemType Directory -Force -Path "C:\Users\reazul.ashraf\.gemini\config\rules" | Out-Null } if (!(Test-Path "C:\Users\reazul.ashraf\.gemini\config\rules")) { New-Item -ItemType Directory -Force -Path "C:\Users\reazul.ashraf\.gemini\config\rules" | Out-Null }
Copy-Item -Force -Recurse agent-rules\* "C:\Users\reazul.ashraf\.gemini\config\rules\" Copy-Item -Force -Recurse agent-rules\* "C:\Users\reazul.ashraf\.gemini\config\rules\"
# Build WSL-native binaries # Build WSL-native binaries
build-wsl: build-wsl: build-stub-wsl build-nvim-wsl
Write-Host "Building WSL binaries natively..." -ForegroundColor Cyan
wsl.exe -d Ubuntu -e bash -c 'export PATH="$PATH:/home/riz/.cargo/bin" && cd /mnt/c/Users/reazul.ashraf/workspace/rust/mcp-memory && cargo build --release -p mcp-memory-stub -p mcp-memory-linux-nvim'
# Deploy WSL-native binaries # Deploy WSL-native binaries
deploy-wsl: deploy-wsl: deploy-stub-wsl deploy-nvim-wsl deploy-rules-wsl
Write-Host "Deploying WSL binaries natively..." -ForegroundColor Cyan
wsl.exe -d Ubuntu -e bash -c 'export PATH="$PATH:/home/riz/.cargo/bin" && cd /mnt/c/Users/reazul.ashraf/workspace/rust/mcp-memory && cp target/release/mcp-memory-stub /home/riz/.local/bin/ && cp target/release/mcp-memory-linux-nvim /home/riz/.local/bin/' build-stub-wsl:
Write-Host "Building WSL Stub natively..." -ForegroundColor Cyan
wsl.exe -d Ubuntu -e bash -c 'export PATH="$PATH:/home/riz/.cargo/bin" && cd /mnt/c/Users/reazul.ashraf/workspace/rust/mcp-memory && cargo build --release -p mcp-memory-stub'
deploy-stub-wsl:
Write-Host "Deploying WSL Stub natively..." -ForegroundColor Cyan
wsl.exe -d Ubuntu -e bash -c 'export PATH="$PATH:/home/riz/.cargo/bin" && cd /mnt/c/Users/reazul.ashraf/workspace/rust/mcp-memory && cp target/release/mcp-memory-stub /home/riz/.local/bin/'
build-nvim-wsl:
Write-Host "Building WSL Nvim natively..." -ForegroundColor Cyan
wsl.exe -d Ubuntu -e bash -c 'export PATH="$PATH:/home/riz/.cargo/bin" && cd /mnt/c/Users/reazul.ashraf/workspace/rust/mcp-memory && cargo build --release -p mcp-memory-linux-nvim'
deploy-nvim-wsl:
Write-Host "Deploying WSL Nvim natively..." -ForegroundColor Cyan
wsl.exe -d Ubuntu -e bash -c 'export PATH="$PATH:/home/riz/.cargo/bin" && cd /mnt/c/Users/reazul.ashraf/workspace/rust/mcp-memory && cp target/release/mcp-memory-linux-nvim /home/riz/.local/bin/'
deploy-rules-wsl:
Write-Host "Deploying global Agent rules (WSL)..." -ForegroundColor Cyan Write-Host "Deploying global Agent rules (WSL)..." -ForegroundColor Cyan
wsl.exe -d Ubuntu -e bash -c 'mkdir -p /home/riz/.gemini/config/rules && cp -r /mnt/c/Users/reazul.ashraf/workspace/rust/mcp-memory/agent-rules/* /home/riz/.gemini/config/rules/' wsl.exe -d Ubuntu -e bash -c 'mkdir -p /home/riz/.gemini/config/rules && cp -r /mnt/c/Users/reazul.ashraf/workspace/rust/mcp-memory/agent-rules/* /home/riz/.gemini/config/rules/'
@@ -59,3 +97,19 @@ test-coverage:
# Start the server directly # Start the server directly
startup-server: startup-server:
cargo run -p mcp-memory-server cargo run -p mcp-memory-server
# Stop the background server
stop: shutdown-server
# Start the server in the background (nohup equivalent)
start:
Write-Host "Starting MCP server in background..." -ForegroundColor Cyan
Start-Process -WindowStyle Hidden -FilePath mcp-memory-server
# Verify the deployment is healthy and serving correct content
verify:
pwsh.exe -NoProfile -File verify_deployment.ps1
# Restart the server and verify
restart: stop start verify
+11 -5
View File
@@ -21,9 +21,12 @@
--btn-border: #dcdde1; --btn-border: #dcdde1;
--btn-hover: #f8f9fa; --btn-hover: #f8f9fa;
--search-hover: #f0f2f5; --search-hover: #f0f2f5;
--input-bg: white;
--input-text: #2c3e50; --input-text: #2c3e50;
--inspector-bg: rgba(255,255,255,0.98); --inspector-bg: rgba(255,255,255,0.98);
--success-color: #27ae60;
--warning-color: #f39c12;
--error-color: #e74c3c;
--open-color: #e67e22;
} }
[data-theme="dark"] { [data-theme="dark"] {
@@ -42,9 +45,12 @@
--btn-border: #3d4a57; --btn-border: #3d4a57;
--btn-hover: #3d4a57; --btn-hover: #3d4a57;
--search-hover: #2c3643; --search-hover: #2c3643;
--input-bg: #171b21;
--input-text: #d1d8e0; --input-text: #d1d8e0;
--inspector-bg: rgba(30, 36, 43, 0.98); --inspector-bg: rgba(30, 36, 43, 0.98);
--success-color: #2ecc71;
--warning-color: #f1c40f;
--error-color: #e74c3c;
--open-color: #e67e22;
} }
body { body {
@@ -1133,7 +1139,7 @@
`); `);
loadGenericList('/api/tech_debts', 'techdebt-container', item => ` loadGenericList('/api/tech_debts', 'techdebt-container', item => `
<strong>${item.id}</strong> ${item.is_resolved ? '<span style="color:var(--success-color);">(Resolved)</span>' : '<span style="color:var(--error-color);">(Open)</span>'} <strong>${item.id}</strong> ${item.is_resolved ? '<span style="color:var(--success-color); font-weight:bold; background: rgba(46, 204, 113, 0.1); padding: 2px 6px; border-radius: 4px; border: 1px solid var(--success-color); margin-left: 8px;">(Resolved)</span>' : '<span style="color:var(--open-color); font-weight:bold; background: rgba(230, 126, 34, 0.1); padding: 2px 6px; border-radius: 4px; border: 1px solid var(--open-color); margin-left: 8px;">(Open)</span>'}
<div style="margin-top:5px;"><strong>Description:</strong> ${item.description}</div> <div style="margin-top:5px;"><strong>Description:</strong> ${item.description}</div>
<div style="margin-top:5px;"><strong>Ideal Solution:</strong> ${item.ideal_solution}</div> <div style="margin-top:5px;"><strong>Ideal Solution:</strong> ${item.ideal_solution}</div>
<div style="margin-top:10px;"> <div style="margin-top:10px;">
@@ -1143,8 +1149,8 @@
`); `);
loadGenericList('/api/error_fixes', 'errorfixes-container', item => ` loadGenericList('/api/error_fixes', 'errorfixes-container', item => `
<strong>${item.signature || 'Error'}</strong> <strong>${item.signature || 'Error'}</strong> <span style="color:var(--success-color); font-weight:bold; background: rgba(46, 204, 113, 0.1); padding: 2px 6px; border-radius: 4px; border: 1px solid var(--success-color); margin-left: 8px;">(Resolved)</span>
<div style="font-size:0.9em; margin-bottom:8px;"><em>Solution:</em> ${item.solution || ''}</div> <div style="font-size:0.9em; margin-bottom:8px; margin-top:5px;"><em>Solution:</em> ${item.solution || ''}</div>
<div style="font-family:monospace; font-size:0.85em; color:#e74c3c;">Commit: ${item.git_commit || 'None'}</div> <div style="font-family:monospace; font-size:0.85em; color:#e74c3c;">Commit: ${item.git_commit || 'None'}</div>
`); `);
+19 -2
View File
@@ -56,6 +56,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
.replace("https://", "wss://"); .replace("https://", "wss://");
let ws_url = format!("{ws_url}/ws?client=proxy"); let ws_url = format!("{ws_url}/ws?client=proxy");
let mut retry_count = 0;
loop { loop {
if shutdown_rx.try_recv().is_ok() { if shutdown_rx.try_recv().is_ok() {
tracing::info!("Stub shutdown requested"); tracing::info!("Stub shutdown requested");
@@ -87,6 +88,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
match connect_result { match connect_result {
Ok(Ok((ws_stream, _))) => { Ok(Ok((ws_stream, _))) => {
retry_count = 0;
tracing::info!("Successfully connected to target server"); tracing::info!("Successfully connected to target server");
let (mut write, mut read) = ws_stream.split(); let (mut write, mut read) = ws_stream.split();
@@ -125,8 +127,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
); );
use tokio::io::AsyncWriteExt; use tokio::io::AsyncWriteExt;
let mut stdout = tokio::io::stdout(); let mut stdout = tokio::io::stdout();
let _ = stdout.write_all(text.as_bytes()).await; let response = format!("{}\n", text);
let _ = stdout.write_all(b"\n").await; let _ = stdout.write_all(response.as_bytes()).await;
let _ = stdout.flush().await; let _ = stdout.flush().await;
} }
} }
@@ -153,14 +155,29 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
} }
Ok(Err(e)) => { Ok(Err(e)) => {
tracing::error!("Failed to connect via WSS: {}", e); tracing::error!("Failed to connect via WSS: {}", e);
retry_count += 1;
if retry_count >= 5 {
tracing::error!("Max connection retries reached. Exiting proxy.");
break;
}
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
} }
Err(_) => { Err(_) => {
tracing::error!("Connection attempt timed out"); tracing::error!("Connection attempt timed out");
retry_count += 1;
if retry_count >= 5 {
tracing::error!("Max connection retries reached. Exiting proxy.");
break;
}
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
} }
} }
} }
if retry_count >= 5 {
return Err("Failed to connect to the MCP memory server after multiple attempts. Is it running?".into());
}
Ok(()) Ok(())
}) })
} }
+24
View File
@@ -0,0 +1,24 @@
$Url = "http://127.0.0.1:3000/"
$ExpectedContent = "open-color" # Basic sanity check that we are serving the updated UI
Write-Host "Verifying server at $Url..." -ForegroundColor Cyan
for ($i = 1; $i -le 10; $i++) {
try {
$response = Invoke-WebRequest -Uri $Url -UseBasicParsing -ErrorAction Stop
if ($response.StatusCode -eq 200) {
if ($response.Content -match $ExpectedContent) {
Write-Host "✅ Server is UP and serving the correct payload! (Attempt $i)" -ForegroundColor Green
exit 0
} else {
Write-Host "⚠️ Server is up but serving old cached content. Retrying... (Attempt $i)" -ForegroundColor Yellow
}
}
} catch {
Write-Host "⏳ Server not responding yet... (Attempt $i)" -ForegroundColor Yellow
}
Start-Sleep -Seconds 1
}
Write-Error "❌ Deployment verification failed! Server did not come up or did not serve correct content after 10 seconds."
exit 1