Skip to content

Commit 4d8fd95

Browse files
author
razvan
committed
refactor: conditionally register update tools, fix documentation
- Register rag_check_update and rag_apply_update only when auto_update=false - Rewrite doc_updates.md: fix SHA256 'Future Hook' (already implemented), replace 'binary swap' with installer handoff, add daemon auto-update and adapter version upgrade sections - README: remove non-existent --update CLI flag, document auto-update as default, update tool count to 9 - engine: add workspace detection debug logging
1 parent 9a1c628 commit 4d8fd95

4 files changed

Lines changed: 73 additions & 25 deletions

File tree

README.md

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
RagCode is a **Model Context Protocol (MCP) server** that instantly makes your project **AI-ready**. It enables AI assistants like **GitHub Copilot**, **Cursor**, **Windsurf**, and **Claude** to understand your entire codebase through **semantic vector search**, bridging the gap between your code and Large Language Models (LLMs).
2323

24-
Built with the official [Model Context Protocol Go SDK](https://github.com/modelcontextprotocol/go-sdk), RagCode provides **11 powerful tools** to index, search, and analyze code — including **Markdown documentation search** — making it the ultimate solution for **AI-ready software development**.
24+
Built with the official [Model Context Protocol Go SDK](https://github.com/modelcontextprotocol/go-sdk), RagCode provides **9 powerful MCP tools** to index, search, and analyze code — including **Markdown documentation search** — making it the ultimate solution for **AI-ready software development**.
2525

2626
## ⚡ One-Command Installation
2727

@@ -55,23 +55,20 @@ Invoke-WebRequest -Uri "https://github.com/doITmagic/rag-code-mcp/releases/lates
5555

5656
### 🔄 Keep Updated
5757

58-
The auto-update feature is available starting with **v1.1.18**.
58+
**Auto-update is enabled by default.** The daemon checks for new versions on startup and applies them automatically. No action needed.
5959

6060
**How to Upgrade:**
6161

6262
1. **If you are on an older version (< v1.1.18):**
63-
Your version **does not know** the update command.
6463
You must **re-run the installation command** (the curl command above) one last time.
65-
*(Don't worry, your indexes and configuration will be preserved).*
64+
*(Don't worry, your indexes and configuration will be preserved.)*
6665

6766
2. **If you are on v1.1.18 or newer:**
68-
Simply run:
69-
```bash
70-
rag-code-mcp --update
71-
```
67+
Updates happen automatically. You can also trigger a manual update:
68+
- Ask your AI assistant to run `rag_check_update` (check) or `rag_apply_update` (install)
69+
- Or re-run the installer: `rag-code-install --upgrade -y`
7270

73-
**For new installations:**
74-
The update system is built-in. Use the installer once, then simply run `rag-code-mcp --update` anytime to get the latest features.
71+
**To disable auto-update:** Set `auto_update: false` in `~/.ragcode/bin/config.yaml`.
7572

7673
📖 **[Full Installation Guide →](./QUICKSTART.md)** | **[Windows WSL Setup →](./QUICKSTART.md#windows-with-wsl-alternative)**
7774

@@ -161,7 +158,7 @@ First query triggers background indexing. Subsequent queries are instant.
161158

162159
---
163160

164-
## 🛠️ 11 Powerful MCP Tools
161+
## 🛠️ MCP Tools
165162

166163
### 🔍 Search & Navigation (Core)
167164

@@ -186,8 +183,11 @@ First query triggers background indexing. Subsequent queries are instant.
186183
| Tool | Description | Use When |
187184
|------|-------------|----------|
188185
| `rag_evaluate` | AI-to-Developer feedback on RagCode performance | Provide feedback |
189-
| `rag_check_update` | Check for available RagCode updates | Staying current |
190-
| `rag_apply_update` | Download and install latest RagCode version | Upgrading |
186+
| `rag_check_update` | Check for available RagCode updates | Only when `auto_update: false` |
187+
| `rag_apply_update` | Download and install latest RagCode version | Only when `auto_update: false` |
188+
189+
> [!NOTE]
190+
> Update tools are only registered when `auto_update: false` in config. By default, the daemon auto-updates on startup, so these tools are hidden to keep the AI context lean.
191191
192192
> [!TIP]
193193
> **`rag_search` is all you need for most queries.** It automatically combines semantic and exact search, adapts output format based on confidence, and with `include_docs: true` also searches project documentation (README, guides, Markdown files).

internal/daemon/run.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,11 @@ func Run(rcfg RunConfig) error {
161161
tools.NewListSkillsTool(eng, cfg.Skills).Register(mcpServer)
162162
tools.NewInstallSkillTool(eng, cfg.Skills).Register(mcpServer)
163163
tools.NewEvaluateRagCodeTool(eng, cfg).Register(mcpServer)
164-
tools.NewCheckUpdateTool(rcfg.Version, cfg).Register(mcpServer)
165-
tools.NewApplyUpdateTool(rcfg.Version).Register(mcpServer)
164+
if !cfg.AutoUpdate {
165+
tools.NewCheckUpdateTool(rcfg.Version, cfg).Register(mcpServer)
166+
tools.NewApplyUpdateTool(rcfg.Version).Register(mcpServer)
167+
logger.Instance.Info("Update tools registered (auto_update=false)")
168+
}
166169

167170
logger.Instance.Info("MCP RagCode Daemon initialized (version=%s)", rcfg.Version)
168171

@@ -209,8 +212,12 @@ func Run(rcfg RunConfig) error {
209212
// Middleware: extract X-Workspace-Hint header from adapter and inject into request context.
210213
// This makes the IDE's CWD available to all tools via transport.GetWorkspaceHint(ctx).
211214
mcpHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
212-
if hint := r.Header.Get("X-Workspace-Hint"); hint != "" {
215+
hint := r.Header.Get("X-Workspace-Hint")
216+
if hint != "" {
217+
logger.Instance.Debug("[DAEMON] Request received with X-Workspace-Hint=%s", hint)
213218
r = r.WithContext(transport.WithWorkspaceHint(r.Context(), hint))
219+
} else {
220+
logger.Instance.Debug("[DAEMON] Request received WITHOUT X-Workspace-Hint header")
214221
}
215222
mcpMux.ServeHTTP(w, r)
216223
})

internal/service/engine/engine.go

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,13 +180,18 @@ func (e *Engine) DetectFromParams(ctx context.Context, params map[string]interfa
180180
// If path is empty, it falls back to the last active workspace from the registry.
181181
// Results are cached with a 5s TTL to avoid redundant resolver invocations.
182182
func (e *Engine) DetectContext(ctx context.Context, path string) (*WorkspaceContext, error) {
183+
// Log incoming detection request for debugging workspace resolution
184+
hintFromCtx := transport.GetWorkspaceHint(ctx)
185+
logger.Instance.Info("[WS-DETECT] ▶ DetectContext called: path=%q, X-Workspace-Hint=%q", path, hintFromCtx)
186+
183187
// Normalize cache key
184188
cacheKey := strings.TrimSpace(path)
185189
if entry, ok := e.detectionCache.LoadAndDelete(cacheKey); ok {
186190
ce := entry.(*detectionCacheEntry)
187191
if time.Now().Before(ce.expiry) {
188192
// Re-store valid entry atomically before returning
189193
e.detectionCache.Store(cacheKey, ce)
194+
logger.Instance.Debug("[WS-DETECT] ◀ Cache hit: root=%s, source=%s", ce.wctx.Root, ce.wctx.DetectionSource)
190195
return ce.wctx, nil
191196
}
192197
}
@@ -195,8 +200,10 @@ func (e *Engine) DetectContext(ctx context.Context, path string) (*WorkspaceCont
195200
source := "explicit_file_path"
196201

197202
if strings.TrimSpace(path) == "" {
203+
logger.Instance.Info("[WS-DETECT] Tier 1 skipped: no explicit path in request params")
204+
198205
// Tier 2: Try workspace hint from adapter (IDE's CWD injected via X-Workspace-Hint header)
199-
if hint := strings.TrimSpace(transport.GetWorkspaceHint(ctx)); hint != "" {
206+
if hint := strings.TrimSpace(hintFromCtx); hint != "" {
200207
abs, err := filepath.Abs(hint)
201208
if err == nil {
202209
// Validate the path actually exists on disk before using it
@@ -205,25 +212,35 @@ func (e *Engine) DetectContext(ctx context.Context, path string) (*WorkspaceCont
205212
source = "hint_fallback"
206213
// Use hint as cache key so different IDEs don't share the same empty-string entry
207214
cacheKey = abs
215+
logger.Instance.Info("[WS-DETECT] ✅ Tier 2 matched: using X-Workspace-Hint=%s", abs)
216+
} else {
217+
logger.Instance.Warn("[WS-DETECT] Tier 2 skipped: hint path does not exist on disk: %s (err: %v)", abs, statErr)
208218
}
219+
} else {
220+
logger.Instance.Warn("[WS-DETECT] Tier 2 skipped: could not resolve hint to abs path: %v", err)
209221
}
222+
} else {
223+
logger.Instance.Info("[WS-DETECT] Tier 2 skipped: no X-Workspace-Hint header in request")
210224
}
211225

212226
// Tier 3: Fall back to last active workspace from registry
213227
if req.FilePath == "" {
214228
active, err := e.GetActiveWorkspace()
215229
if err != nil || active == "" {
230+
logger.Instance.Warn("[WS-DETECT] ❌ All tiers exhausted — no workspace detected")
216231
return nil, fmt.Errorf("❌ No workspace detected. Please provide the 'file_path' of the file you are currently working on to help detect the project context.")
217232
}
218233
req.WorkspaceRoot = active
219234
source = "registry_fallback"
235+
logger.Instance.Info("[WS-DETECT] ✅ Tier 3 matched: using registry fallback=%s", active)
220236
}
221237
} else {
222238
abs, err := filepath.Abs(path)
223239
if err != nil {
224240
return nil, fmt.Errorf("failed to resolve path: %w", err)
225241
}
226242
req.FilePath = abs
243+
logger.Instance.Info("[WS-DETECT] ✅ Tier 1 matched: using explicit path=%s", abs)
227244
}
228245

229246
resp, wsErr := e.resolver.Resolve(ctx, req)
@@ -242,6 +259,9 @@ func (e *Engine) DetectContext(ctx context.Context, path string) (*WorkspaceCont
242259
HeadSHA: resp.HeadSHA,
243260
}
244261

262+
logger.Instance.Info("[WS-DETECT] ◀ Resolved: root=%s, id=%s, branch=%s, source=%s, risk=%s",
263+
wctx.Root, wctx.ID, wctx.Branch, source, wctx.MismatchRisk)
264+
245265
// Don't cache entries that require reindex or are high-risk — let next call re-evaluate
246266
if !wctx.ReindexRequired && wctx.MismatchRisk != "high" {
247267
e.detectionCache.Store(cacheKey, &detectionCacheEntry{

internal/service/tools/doc_updates.md

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,47 @@
22

33
**Source File**: `updates.go`
44

5-
These two companion tools provide self-maintaining capabilities to the RagCode MCP server, allowing the AI assistant to detect when a newer version exists on GitHub and gracefully trigger an in-place upgrade.
5+
These two companion tools provide self-maintaining capabilities to the RagCode MCP server, allowing the AI assistant to detect when a newer version exists on GitHub and gracefully trigger an upgrade.
6+
7+
> **Note:** These tools are only registered when `auto_update: false` in config. By default, the daemon handles updates automatically on startup, so these tools are hidden to reduce AI context overhead.
68
79
## 1. `rag_check_update`
810

911
### Query Mechanisms
1012
- **External API Query**: Hooks into the public GitHub Releases API (`api.github.com/repos/doITmagic/rag-code-mcp/releases/latest`) to check the newest tagged version.
11-
- **Cache Mechanism**: By default, checks are cached to avoid API rate limiting. This can be overridden by passing `"force": true`.
12-
- **Version Comparison**: Compares the natively injected build version (`t.version` passed via `LDFLAGS`) against the Semantic Version tag discovered remotely.
13+
- **Cache Mechanism**: Results are cached for 24 hours in `~/.ragcode/update_cache.json` (written atomically via temp-file + rename, permissions `0600`). Pass `"force": true` to bypass the cache.
14+
- **Version Comparison**: Compares the natively injected build version (`t.version` passed via `LDFLAGS`) against the Semantic Version tag discovered remotely using `Masterminds/semver`.
15+
- **Remote Stable Model Check**: Fetches `config.yaml` from the `main` branch on GitHub to detect if the recommended embedding model has changed. Displays a warning if the local model differs from the remote stable model.
1316

1417
### Features
15-
- **Deterministic**: Provides the exact changelog and download URLs in the structured `ToolResponse.Data` response so the AI can summarize new features for the user.
18+
- **Deterministic**: Provides the exact download URLs, tag, and version details in the structured `ToolResponse.Data` response so the AI can summarize what's new for the user.
19+
- **Structured Response**: Returns a `ToolResponse` JSON with `status`, `message`, `error`, `context` (current version), and `data` (full `UpdateInfo` object) fields.
1620

1721
---
1822

1923
## 2. `rag_apply_update`
2024

2125
### Query Mechanisms
22-
- **Artifact Download**: Performs an HTTP streaming download of the release artifact (ZIP or TAR.GZ) aligned with the host's operating system and architecture (`GOOS`/`GOARCH`).
23-
- **Cryptographic Verification**: *(Future Hook)* Validates the BLAKE3/SHA256 checksum associated with the release to ensure binary integrity before executing a swap.
26+
- **Artifact Download**: Performs an HTTP streaming download of the release artifact (`.tar.gz` or `.zip`) aligned with the host's operating system and architecture (`GOOS`/`GOARCH`).
27+
- **SHA256 Verification**: Downloads `checksums.txt` from the release, locates the hash for the platform-specific archive, computes the SHA256 of the downloaded file, and compares them. Fails if the hashes don't match.
2428

2529
### Features
26-
- **In-place Binary Swap**: Downloads the artifact to a securely generated `os.CreateTemp` path. Unpacks the new `rag-code-mcp` executable and aggressively swaps it with the current running binary (using standard POSIX rename/replace syscalls depending on OS).
27-
- **Graceful Handoff**: Once the new binary is placed on disk, it prompts the AI to notify the user to restart their IDE or MCP client so the new process takes over.
30+
- **Installer Handoff**: Downloads the artifact to a securely generated `os.CreateTemp` path, extracts it to a temp directory, then spawns `rag-code-install --upgrade -y` from the extracted directory. The current process exits via `os.Exit(0)` to hand control to the installer. The installer handles process stopping (via PID file) and file copying to `~/.ragcode/bin/`.
31+
- **Cleanup**: On error paths, the temp directory is automatically cleaned up. On successful handoff, the installer takes ownership.
32+
- **Graceful Restart**: Once the installer completes, the AI prompts the user to restart their IDE or MCP client so the new version takes over.
33+
34+
---
35+
36+
## 3. Daemon Auto-Update
37+
38+
### Mechanism
39+
- **Automatic by Default**: The `auto_update: true` setting in `config.yaml` (default) enables automatic update checking on daemon startup.
40+
- **Background Worker**: 10 seconds after the daemon starts, a background goroutine calls `updater.CheckForUpdates()` (using the 24h cache), and if a new version is found, calls `updater.DownloadVerifyAndApply()` — which downloads, verifies SHA256, and spawns the installer.
41+
- **Shared Helper**: `DownloadVerifyAndApply()` is the unified code path used by both the daemon auto-update worker and the `rag_apply_update` MCP tool.
42+
- **Disable**: Set `auto_update: false` in `~/.ragcode/bin/config.yaml` to disable automatic updates.
43+
44+
---
45+
46+
## 4. Adapter Version Upgrade
47+
48+
When the adapter (stdio bridge) starts, it checks if the running daemon is on an older version. If so, it stops the old daemon and restarts with the current binary version. This ensures that after a manual update, the daemon is always running the latest installed version.

0 commit comments

Comments
 (0)