Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions internal/daemon/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import (
"github.com/doITmagic/rag-code-mcp/internal/healthcheck"
"github.com/doITmagic/rag-code-mcp/internal/logger"
"github.com/doITmagic/rag-code-mcp/internal/service/engine"
"github.com/doITmagic/rag-code-mcp/internal/service/prompts"
"github.com/doITmagic/rag-code-mcp/internal/service/resources"
"github.com/doITmagic/rag-code-mcp/internal/service/search"
"github.com/doITmagic/rag-code-mcp/internal/service/tools"
"github.com/doITmagic/rag-code-mcp/internal/transport"
Expand Down Expand Up @@ -173,6 +175,10 @@ func Run(rcfg RunConfig) error {
logger.Instance.Info("Update tools registered (auto_update=false)")
}

// Register Extra Features (Resources & Prompts MVP)
resources.Register(mcpServer, eng)
prompts.Register(mcpServer, eng)

Comment on lines +178 to +181
logger.Instance.Info("MCP RagCode Daemon initialized (version=%s)", rcfg.Version)

if cfg.AutoUpdate {
Expand Down
41 changes: 41 additions & 0 deletions internal/service/prompts/prompts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package prompts

import (
"context"
"fmt"

"github.com/doITmagic/rag-code-mcp/internal/service/engine"
"github.com/modelcontextprotocol/go-sdk/mcp"
)

// Register registers all MCP prompts provided by this package on the given mcp.Server.
func Register(mcpServer *mcp.Server, eng *engine.Engine) {
mcpServer.AddPrompt(&mcp.Prompt{
Name: "System Diagnostics",
Description: "Analyze the current indexing status and troubleshoot common issues based on the workspace resources.",
Title: "Analyze RagCode Indexing System",
}, func(ctx context.Context, request *mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
// Detect workspace to contextualize the prompt
wctx, err := eng.DetectContext(ctx, "")
if err != nil {
return nil, fmt.Errorf("failed to detect workspace: %w", err)
}

promptText := fmt.Sprintf(`Please analyze the current indexing status of the RagCode MCP server for the workspace located at: %s

You can inspect the indexing status by reading the resource directly via URI: "ragcode://status/indexing" or using your available tools.
Then, inform me if there are any issues such as stuck processes or parsing errors.`, wctx.Root)

return &mcp.GetPromptResult{
Description: "Prompt to diagnose indexing and execution issues automatically.",
Messages: []*mcp.PromptMessage{
{
Role: mcp.Role("user"),
Content: &mcp.TextContent{
Text: promptText,
},
},
},
}, nil
})
}
46 changes: 46 additions & 0 deletions internal/service/resources/resources.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package resources

import (
"context"
"encoding/json"
"fmt"

"github.com/doITmagic/rag-code-mcp/internal/service/engine"
"github.com/modelcontextprotocol/go-sdk/mcp"
)

// Register registers all MCP resources provided by this package on the given mcp.Server.
func Register(mcpServer *mcp.Server, eng *engine.Engine) {
mcpServer.AddResource(&mcp.Resource{
URI: "ragcode://status/indexing",
Name: "Indexing Status",
Description: "Returns the current indexing status and progress for the workspace.",
MIMEType: "application/json",
}, func(ctx context.Context, request *mcp.ReadResourceRequest) (*mcp.ReadResourceResult, error) {
// Attempt to resolve context
wctx, err := eng.DetectContext(ctx, "")
if err != nil {
return nil, fmt.Errorf("failed to detect workspace: %w", err)
}

status := eng.GetIndexStatus(wctx.Root)
if status == nil {
return nil, fmt.Errorf("index status not found for workspace %s", wctx.Root)
}

blob, err := json.MarshalIndent(status, "", " ")
if err != nil {
return nil, fmt.Errorf("failed to marshal index status: %w", err)
}
Comment on lines +26 to +34

return &mcp.ReadResourceResult{
Contents: []*mcp.ResourceContents{
{
URI: request.Params.URI,
Text: string(blob),
MIMEType: "application/json",
},
},
}, nil
})
}
3 changes: 1 addition & 2 deletions internal/service/tools/call_hierarchy.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ func (t *CallHierarchyTool) Execute(ctx context.Context, args map[string]interfa
resp := ToolResponse{
Status: "indexing_required",
Message: fmt.Sprintf("⏳ Workspace '%s' is not indexed yet. Indexing is required for complete call hierarchy results.", wctx.Root),
Context: ContextFromWorkspaceWithStatus(wctx, t.engine),
Context: ContextFromWorkspace(wctx),
}
if idx != nil {
resp.Status = "indexing_in_progress"
Expand Down Expand Up @@ -168,7 +168,6 @@ func (t *CallHierarchyTool) Execute(ctx context.Context, args map[string]interfa
WorkspaceRoot: wctx.Root,
DetectionSource: wctx.DetectionSource,
Telemetry: telemetry.CalculateSavings(baselineBytes, actualBytes),
IndexingStatus: idx,
},
}
return resp.JSON()
Expand Down
2 changes: 1 addition & 1 deletion internal/service/tools/evaluate_ragcode.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ func (t *EvaluateRagCodeTool) Execute(ctx context.Context, args map[string]inter
Status: "success",
Message: b.String(),
Data: data,
Context: ContextFromWorkspaceWithStatus(wctx, t.engine),
Context: ContextFromWorkspace(wctx),
}

return response.JSON()
Expand Down
7 changes: 3 additions & 4 deletions internal/service/tools/find_usages.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ func (t *FindUsagesTool) Execute(ctx context.Context, args map[string]interface{
resp := ToolResponse{
Status: "indexing_required",
Message: fmt.Sprintf("⏳ Workspace '%s' is not indexed yet. Indexing is required for complete results.", wctx.Root),
Context: ContextFromWorkspaceWithStatus(wctx, t.engine),
Context: ContextFromWorkspace(wctx),
}
if idx != nil {
resp.Status = "indexing_in_progress"
Expand All @@ -113,7 +113,7 @@ func (t *FindUsagesTool) Execute(ctx context.Context, args map[string]interface{
resp := ToolResponse{
Status: "success",
Message: fmt.Sprintf("No usages found for symbol '%s' based on Code Graph relations.", symbolName),
Context: ContextFromWorkspaceWithStatus(wctx, t.engine),
Context: ContextFromWorkspace(wctx),
}
return resp.JSON()
}
Expand Down Expand Up @@ -198,7 +198,7 @@ func (t *FindUsagesTool) Execute(ctx context.Context, args map[string]interface{
resp := ToolResponse{
Status: "success",
Message: fmt.Sprintf("No explicit usages found for symbol '%s'", symbolName),
Context: ContextFromWorkspaceWithStatus(wctx, t.engine),
Context: ContextFromWorkspace(wctx),
}
return resp.JSON()
}
Expand Down Expand Up @@ -256,7 +256,6 @@ func (t *FindUsagesTool) Execute(ctx context.Context, args map[string]interface{
WorkspaceRoot: wctx.Root,
DetectionSource: wctx.DetectionSource,
Telemetry: telemetry.CalculateSavings(baselineBytes, actualBytes),
IndexingStatus: idx,
},
}
return resp.JSON()
Expand Down
7 changes: 3 additions & 4 deletions internal/service/tools/list_package_exports.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ func (t *ListPackageExportsTool) Execute(ctx context.Context, args map[string]in
resp := ToolResponse{
Status: "indexing_required",
Message: fmt.Sprintf("⏳ Workspace '%s' is not indexed yet. Indexing is required for complete results.", wctx.Root),
Context: ContextFromWorkspaceWithStatus(wctx, t.engine),
Context: ContextFromWorkspace(wctx),
}
return resp.JSON()
}
Expand All @@ -126,7 +126,7 @@ func (t *ListPackageExportsTool) Execute(ctx context.Context, args map[string]in
resp := ToolResponse{
Status: "success",
Message: fmt.Sprintf("No exported symbols found in package '%s'", packageName),
Context: ContextFromWorkspaceWithStatus(wctx, t.engine),
Context: ContextFromWorkspace(wctx),
}
return resp.JSON()
}
Expand Down Expand Up @@ -206,7 +206,7 @@ func (t *ListPackageExportsTool) Execute(ctx context.Context, args map[string]in
resp := ToolResponse{
Status: "success",
Message: fmt.Sprintf("No exported symbols found in package '%s' (after filtering)", packageName),
Context: ContextFromWorkspaceWithStatus(wctx, t.engine),
Context: ContextFromWorkspace(wctx),
}
return resp.JSON()
}
Expand Down Expand Up @@ -258,7 +258,6 @@ func (t *ListPackageExportsTool) Execute(ctx context.Context, args map[string]in
WorkspaceRoot: wctx.Root,
DetectionSource: wctx.DetectionSource,
Telemetry: telemetry.CalculateSavings(baselineBytes, actualBytes),
IndexingStatus: t.engine.GetIndexStatus(wctx.Root),
},
}

Expand Down
2 changes: 1 addition & 1 deletion internal/service/tools/read_file_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ func (t *ReadFileContextTool) buildResponse(wctx *engine.WorkspaceContext, res C
Message: fmt.Sprintf("Extracted %s context for lines %d-%d from %s", res.ContextType, res.StartLine, res.EndLine, res.FilePath),
}
if wctx != nil {
resp.Context = ContextFromWorkspaceWithStatus(wctx, t.engine)
resp.Context = ContextFromWorkspace(wctx)
}

baselineBytes := int64(0)
Expand Down
10 changes: 0 additions & 10 deletions internal/service/tools/response.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"fmt"

"github.com/doITmagic/rag-code-mcp/internal/service/engine"
"github.com/doITmagic/rag-code-mcp/pkg/indexer"
"github.com/doITmagic/rag-code-mcp/pkg/telemetry"
)

Expand All @@ -26,7 +25,6 @@ type ContextMetadata struct {
Language string `json:"language,omitempty"`
Collection string `json:"collection,omitempty"`
Telemetry *telemetry.Savings `json:"telemetry,omitempty"`
IndexingStatus *indexer.IndexStatus `json:"indexing_progress,omitempty"` // JSON tag kept as "indexing_progress" for backward compatibility; present when indexing is in progress or just completed
SessionMetrics *telemetry.AggregatedMetrics `json:"session_metrics,omitempty"` // cumulative search stats from .ragcode/search_metrics.jsonl
}

Expand Down Expand Up @@ -57,11 +55,3 @@ func ContextFromWorkspace(wctx *engine.WorkspaceContext) ContextMetadata {
}
}

// ContextFromWorkspaceWithStatus builds ContextMetadata and attaches indexing status from disk.
func ContextFromWorkspaceWithStatus(wctx *engine.WorkspaceContext, eng *engine.Engine) ContextMetadata {
ctx := ContextFromWorkspace(wctx)
if eng != nil && wctx != nil {
ctx.IndexingStatus = eng.GetIndexStatus(wctx.Root)
}
return ctx
}
4 changes: 2 additions & 2 deletions internal/service/tools/skills.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func (t *ListSkillsTool) Execute(ctx context.Context, args map[string]interface{

response := ToolResponse{
Status: "success",
Context: ContextFromWorkspaceWithStatus(wctx, t.engine),
Context: ContextFromWorkspace(wctx),
}
response.SetFallbackWarning(source == "registry_fallback")

Expand Down Expand Up @@ -208,7 +208,7 @@ func (t *InstallSkillTool) Execute(ctx context.Context, args map[string]interfac

response := ToolResponse{
Status: "success",
Context: ContextFromWorkspaceWithStatus(wctx, t.engine),
Context: ContextFromWorkspace(wctx),
}
response.SetFallbackWarning(source != "explicit_file_path")

Expand Down
2 changes: 0 additions & 2 deletions internal/service/tools/smart_search.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,15 +267,13 @@ func (t *SmartSearchTool) handleSearchError(err error, workspaceRoot, workspaceI
if errors.As(err, &indexingStarted) {
response.Status = "indexing_started"
response.Context.WorkspaceRoot = indexingStarted.WorkspaceRoot
response.Context.IndexingStatus = t.engine.GetIndexStatus(indexingStarted.WorkspaceRoot)
response.Message = fmt.Sprintf("🚀 Indexing started for workspace '%s'. Results will appear as indexing progresses.", indexingStarted.WorkspaceRoot)
return response.JSON()
}

if errors.As(err, &indexingInProgress) {
response.Status = "indexing_in_progress"
response.Context.WorkspaceRoot = indexingInProgress.WorkspaceRoot
response.Context.IndexingStatus = t.engine.GetIndexStatus(indexingInProgress.WorkspaceRoot)
response.Message = fmt.Sprintf("⏳ Indexing in progress for workspace '%s'. Results will improve as indexing completes.", indexingInProgress.WorkspaceRoot)
return response.JSON()
}
Expand Down
7 changes: 0 additions & 7 deletions internal/service/tools/smart_search_pipeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (

"github.com/doITmagic/rag-code-mcp/internal/logger"
"github.com/doITmagic/rag-code-mcp/internal/service/engine"
"github.com/doITmagic/rag-code-mcp/pkg/indexer"
"github.com/doITmagic/rag-code-mcp/pkg/scoring"
"github.com/doITmagic/rag-code-mcp/pkg/telemetry"
)
Expand Down Expand Up @@ -203,19 +202,13 @@ func applyScoreFilter(merged []mergedResult, minScore float32) []mergedResult {
func (t *SmartSearchTool) buildResponseMeta(meta searchMetadata) ToolResponse {
isFallback := meta.collection == "fallback"

var idxStatus *indexer.IndexStatus
if meta.workspaceRoot != "" {
idxStatus = indexer.LoadIndexStatus(meta.workspaceRoot)
}

response := ToolResponse{
Status: "success",
Context: ContextMetadata{
WorkspaceRoot: meta.workspaceRoot,
DetectionSource: meta.detectionSource,
Language: meta.language,
Collection: meta.collection,
IndexingStatus: idxStatus,
SessionMetrics: telemetry.ReadAggregatedMetrics(meta.workspaceRoot),
},
}
Expand Down
Loading