From 33f888b78a6236be98062bd2e1a6876085512720 Mon Sep 17 00:00:00 2001 From: Sam Bonifacio Date: Wed, 6 Aug 2025 23:13:19 +1000 Subject: [PATCH 1/2] feat(mcp-fd-server): add limit parameter to search_files and filter_files - Add limit parameter to both search_files and filter_files functions - Support limiting results with 0 meaning no limit (return all matches) - Update function signatures and documentation --- README.md | 2 ++ mcp_fd_server.py | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/README.md b/README.md index a44772f..83e37c2 100644 --- a/README.md +++ b/README.md @@ -682,6 +682,7 @@ Find files by NAME using fd with regex or glob patterns. **Parameters:** - `pattern` (required): Regex or glob pattern to match file names - `path` (optional): Directory to search in (defaults to current directory) +- `limit` (optional): Maximum number of results to return (default: 0 = no limit) - `flags` (optional): Additional flags to pass to fd **Example:** @@ -703,6 +704,7 @@ Fuzzy search for files by NAME using fzf's fuzzy matching. - `pattern` (optional): Initial pattern for fd to pre-filter - `path` (optional): Directory to search in - `first` (optional): Return only the best match +- `limit` (optional): Maximum number of results to return (default: 0 = no limit) - `fd_flags` (optional): Extra flags for fd - `fzf_flags` (optional): Extra flags for fzf - `multiline` (optional): When true, searches file CONTENTS instead of names (default: false) diff --git a/mcp_fd_server.py b/mcp_fd_server.py index 4a192fa..0e37f0f 100755 --- a/mcp_fd_server.py +++ b/mcp_fd_server.py @@ -199,6 +199,7 @@ def _suggest_fuzzy_terms(regex_pattern: str) -> str: "Args:\n" " pattern (str): Regex or glob pattern to match filenames. Required.\n" " path (str, optional): Directory to search in. Defaults to current dir.\n" + " limit (int, optional): Maximum number of results to return. Default 0 (no limit).\n" " flags (str, optional): Extra flags for fd (e.g., '--hidden' for hidden files).\n\n" "Examples:\n" " pattern='\\.py$' - Find all Python files\n" @@ -210,6 +211,7 @@ def _suggest_fuzzy_terms(regex_pattern: str) -> str: def search_files( pattern: str, path: str = ".", + limit: int = 0, flags: str = "", ) -> dict[str, Any]: """Return every file or directory matching *pattern* according to fd.""" @@ -226,6 +228,8 @@ def search_files( try: out = subprocess.check_output(cmd, text=True, stderr=subprocess.STDOUT) matches = [_normalize_path(p) for p in out.splitlines() if p] + if limit > 0: + matches = matches[:limit] return {"matches": matches} except subprocess.CalledProcessError as exc: return {"error": exc.output.strip() or str(exc)} @@ -247,6 +251,7 @@ def search_files( " pattern (str, optional): Pre-filter with fd pattern (empty = all files).\n" " path (str, optional): Directory to search. Defaults to current dir.\n" " first (bool, optional): Return only the best match. Default false.\n" + " limit (int, optional): Maximum number of results to return. Default 0 (no limit).\n" " fd_flags (str, optional): Extra flags for fd.\n" " fzf_flags (str, optional): Extra flags for fzf.\n" " multiline (bool, optional): Search file CONTENTS (not just names). Default false.\n\n" @@ -283,6 +288,7 @@ def filter_files( pattern: str = "", path: str = ".", first: bool = False, + limit: int = 0, fd_flags: str = "", fzf_flags: str = "", multiline: bool = False, @@ -381,6 +387,8 @@ def filter_files( if first and matches: matches = matches[:1] + elif limit > 0 and matches: + matches = matches[:limit] result = {"matches": matches} if warnings: From c212d0dae8f17896a10cb7543e3ebf7543a06653 Mon Sep 17 00:00:00 2001 From: Sam Bonifacio Date: Wed, 6 Aug 2025 23:27:25 +1000 Subject: [PATCH 2/2] feat(cli): add --limit parameter support to CLI commands - Add --limit argument to search and filter CLI subcommands - Update function calls to pass limit parameter correctly - Fix test assertion for multiline parameter position after adding limit --- mcp_fd_server.py | 5 ++++- tests/test_fd_server.py | 8 ++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/mcp_fd_server.py b/mcp_fd_server.py index 0e37f0f..91a5c7b 100755 --- a/mcp_fd_server.py +++ b/mcp_fd_server.py @@ -413,6 +413,7 @@ def _cli() -> None: p_search = sub.add_parser("search", help="fd search") p_search.add_argument("pattern") p_search.add_argument("path", nargs="?", default=".") + p_search.add_argument("--limit", type=int, default=0, help="Maximum results") p_search.add_argument("--flags", default="") # filter_files sub‑command @@ -423,6 +424,7 @@ def _cli() -> None: p_filter.add_argument("pattern", nargs="?", default="") p_filter.add_argument("path", nargs="?", default=".") p_filter.add_argument("--first", action="store_true") + p_filter.add_argument("--limit", type=int, default=0, help="Maximum results") p_filter.add_argument("--fd-flags", default="") p_filter.add_argument("--fzf-flags", default="") p_filter.add_argument( @@ -432,13 +434,14 @@ def _cli() -> None: ns = parser.parse_args() if ns.cmd == "search": - res = search_files(ns.pattern, ns.path, ns.flags) + res = search_files(ns.pattern, ns.path, ns.limit, ns.flags) else: res = filter_files( ns.filter, ns.pattern, ns.path, ns.first, + ns.limit, ns.fd_flags, ns.fzf_flags, ns.multiline, diff --git a/tests/test_fd_server.py b/tests/test_fd_server.py index 76b136b..9632953 100644 --- a/tests/test_fd_server.py +++ b/tests/test_fd_server.py @@ -609,10 +609,10 @@ def test_multiline_cli_support(): # Verify multiline=True was passed as a positional argument mock_filter.assert_called_once() call_args = mock_filter.call_args - # The function signature is filter_files(filter, pattern, path, first, fd_flags, fzf_flags, multiline) - # So multiline should be the 7th argument (index 6) - if len(call_args[0]) > 6: - assert call_args[0][6] is True # positional argument + # The function signature is filter_files(filter, pattern, path, first, limit, fd_flags, fzf_flags, multiline) + # So multiline should be the 8th argument (index 7) + if len(call_args[0]) > 7: + assert call_args[0][7] is True # positional argument else: # Check if it was passed as keyword argument assert call_args[1].get("multiline") is True