feat(mcp): add offset/limit params and show file metadata in declarations

- Add offset and limit parameters to get_file tool schema
- Default limit is 250 lines, offset is 0
- Show "Showing lines X-Y of Z total" header when range is applied
- Update handleGetOption to use GetDeclarationsWithMetadata
- Display file size metadata (bytes, lines) in declarations output

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-04 01:30:45 +01:00
parent d9aab773c6
commit b188ca5088
2 changed files with 42 additions and 9 deletions

View File

@@ -103,8 +103,8 @@ func (s *Server) handleGetOption(ctx context.Context, args map[string]interface{
return ErrorContent(fmt.Errorf("option '%s' not found", name)), nil
}
// Get declarations
declarations, err := s.store.GetDeclarations(ctx, option.ID)
// Get declarations with file metadata
declarations, err := s.store.GetDeclarationsWithMetadata(ctx, rev.ID, option.ID)
if err != nil {
s.logger.Printf("Failed to get declarations: %v", err)
}
@@ -134,10 +134,15 @@ func (s *Server) handleGetOption(ctx context.Context, args map[string]interface{
sb.WriteString("\n**Declared in:**\n")
for _, decl := range declarations {
if decl.Line > 0 {
sb.WriteString(fmt.Sprintf("- %s:%d\n", decl.FilePath, decl.Line))
sb.WriteString(fmt.Sprintf("- %s:%d", decl.FilePath, decl.Line))
} else {
sb.WriteString(fmt.Sprintf("- %s\n", decl.FilePath))
sb.WriteString(fmt.Sprintf("- %s", decl.FilePath))
}
// Add file metadata if available
if decl.HasFile && decl.ByteSize > 0 {
sb.WriteString(fmt.Sprintf(" (%d bytes, %d lines)", decl.ByteSize, decl.LineCount))
}
sb.WriteString("\n")
}
}
@@ -199,16 +204,34 @@ func (s *Server) handleGetFile(ctx context.Context, args map[string]interface{})
return ErrorContent(fmt.Errorf("no indexed revision available")), nil
}
file, err := s.store.GetFile(ctx, rev.ID, path)
// Parse range parameters
var offset, limit int
if o, ok := args["offset"].(float64); ok {
offset = int(o)
}
if l, ok := args["limit"].(float64); ok {
limit = int(l)
}
// Use GetFileWithRange
fileRange := database.FileRange{Offset: offset, Limit: limit}
result, err := s.store.GetFileWithRange(ctx, rev.ID, path, fileRange)
if err != nil {
return ErrorContent(fmt.Errorf("failed to get file: %w", err)), nil
}
if file == nil {
if result == nil {
return ErrorContent(fmt.Errorf("file '%s' not found (files may not be indexed for this revision)", path)), nil
}
// Format output with range metadata
var sb strings.Builder
if result.TotalLines > 0 && (result.StartLine > 1 || result.EndLine < result.TotalLines) {
sb.WriteString(fmt.Sprintf("Showing lines %d-%d of %d total\n\n", result.StartLine, result.EndLine, result.TotalLines))
}
sb.WriteString(fmt.Sprintf("```%s\n%s\n```", strings.TrimPrefix(result.Extension, "."), result.Content))
return CallToolResult{
Content: []Content{TextContent(fmt.Sprintf("```%s\n%s\n```", strings.TrimPrefix(file.Extension, "."), file.Content))},
Content: []Content{TextContent(sb.String())},
}, nil
}