@@ -18,9 +18,24 @@ async def get_all_actions():
1818 )
1919
2020@router .get ("/agents" , operation_id = "get_agents_endpoint" )
21- async def get_agents ():
22- """Get all available agents with tags only"""
21+ async def get_agents (
22+ after : Optional [str ] = Query (None , description = "Cursor for pagination (use slug of last item from previous page)" ),
23+ limit : int = Query (30 , ge = 1 , le = 30 , description = "Maximum number of results (max 30)" )
24+ ):
25+ """Get available agents with tags only, limited to 30 items"""
2326 agents = actions_loader .get_agents ()
27+
28+ # Find starting position if 'after' is provided
29+ start_idx = 0
30+ if after :
31+ for idx , agent in enumerate (agents ):
32+ if agent .slug == after :
33+ start_idx = idx + 1
34+ break
35+
36+ # Apply limit
37+ paginated_agents = agents [start_idx :start_idx + limit ]
38+
2439 return [
2540 {
2641 "name" : agent .name ,
@@ -29,13 +44,28 @@ async def get_agents():
2944 "tags" : agent .tags ,
3045 "filename" : agent .filename
3146 }
32- for agent in agents
47+ for agent in paginated_agents
3348 ]
3449
3550@router .get ("/rules" , operation_id = "get_rules_endpoint" )
36- async def get_rules ():
37- """Get all available rules with tags only"""
51+ async def get_rules (
52+ after : Optional [str ] = Query (None , description = "Cursor for pagination (use slug of last item from previous page)" ),
53+ limit : int = Query (30 , ge = 1 , le = 30 , description = "Maximum number of results (max 30)" )
54+ ):
55+ """Get available rules with tags only, limited to 30 items"""
3856 rules = actions_loader .get_rules ()
57+
58+ # Find starting position if 'after' is provided
59+ start_idx = 0
60+ if after :
61+ for idx , rule in enumerate (rules ):
62+ if rule .slug == after :
63+ start_idx = idx + 1
64+ break
65+
66+ # Apply limit
67+ paginated_rules = rules [start_idx :start_idx + limit ]
68+
3969 return [
4070 {
4171 "name" : rule .name ,
@@ -44,19 +74,34 @@ async def get_rules():
4474 "tags" : rule .tags ,
4575 "filename" : rule .filename
4676 }
47- for rule in rules
77+ for rule in paginated_rules
4878 ]
4979
5080@router .get ("/mcps" , operation_id = "get_mcps_endpoint" )
51- async def get_mcps ():
52- """Get all available MCPs with tags only"""
81+ async def get_mcps (
82+ after : Optional [str ] = Query (None , description = "Cursor for pagination (use name of last item from previous page)" ),
83+ limit : int = Query (30 , ge = 1 , le = 30 , description = "Maximum number of results (max 30)" )
84+ ):
85+ """Get available MCPs with tags only, limited to 30 items"""
5386 mcps = actions_loader .get_mcps ()
87+
88+ # Find starting position if 'after' is provided
89+ start_idx = 0
90+ if after :
91+ for idx , mcp in enumerate (mcps ):
92+ if mcp .name == after :
93+ start_idx = idx + 1
94+ break
95+
96+ # Apply limit
97+ paginated_mcps = mcps [start_idx :start_idx + limit ]
98+
5499 return [
55100 {
56101 "name" : mcp .name ,
57102 "tags" : mcp .tags if hasattr (mcp , 'tags' ) else []
58103 }
59- for mcp in mcps
104+ for mcp in paginated_mcps
60105 ]
61106
62107
@@ -102,37 +147,37 @@ async def get_merged_actions_block():
102147
103148@router .get ("/search/agents" , tags = ["mcp" ], operation_id = "search_agents_endpoint" )
104149async def search_agents (
105- query : str = Query (..., description = "Search query" ),
150+ query : str = Query (..., description = "Search query. Supports wildcards: * (any characters) and ? (single character) " ),
106151 limit : int = Query (10 , ge = 1 , le = 100 , description = "Maximum number of results" )
107152):
108- """Search for agents by name, display_name, or content"""
153+ """Search for agents by name, display_name, or content. Supports wildcard patterns with * and ? """
109154 results = search_service .search_agents (query , limit )
110155 return {"results" : results }
111156
112157@router .get ("/search/rules" , tags = ["mcp" ], operation_id = "search_rules_endpoint" )
113158async def search_rules (
114- query : str = Query (..., description = "Search query" ),
159+ query : str = Query (..., description = "Search query. Supports wildcards: * (any characters) and ? (single character) " ),
115160 limit : int = Query (10 , ge = 1 , le = 100 , description = "Maximum number of results" )
116161):
117- """Search for rules by name, display_name, content, tags, or author"""
162+ """Search for rules by name, display_name, content, tags, or author. Supports wildcard patterns with * and ? """
118163 results = search_service .search_rules (query , limit )
119164 return {"results" : results }
120165
121166@router .get ("/search/mcps" , tags = ["mcp" ], operation_id = "search_mcps_endpoint" )
122167async def search_mcps (
123- query : str = Query (..., description = "Search query" ),
168+ query : str = Query (..., description = "Search query. Supports wildcards: * (any characters) and ? (single character) " ),
124169 limit : int = Query (10 , ge = 1 , le = 100 , description = "Maximum number of results" )
125170):
126- """Search for MCPs by name or config content"""
171+ """Search for MCPs by name or config content. Supports wildcard patterns with * and ? """
127172 results = search_service .search_mcps (query , limit )
128173 return {"results" : results }
129174
130175@router .get ("/search" , tags = ["mcp" ], operation_id = "search_all_endpoint" )
131176async def search_all (
132- query : str = Query (..., description = "Search query" ),
177+ query : str = Query (..., description = "Search query. Supports wildcards: * (any characters) and ? (single character) " ),
133178 limit : int = Query (10 , ge = 1 , le = 100 , description = "Maximum number of results per category" )
134179):
135- """Search across all types (agents, rules, MCPs)"""
180+ """Search across all types (agents, rules, MCPs). Supports wildcard patterns with * and ? """
136181 return search_service .search_all (query , limit )
137182
138183@router .get ("/rules/{rule_ids}" , tags = ["mcp" ], operation_id = "get_multiple_rules_content" )
@@ -201,7 +246,7 @@ async def get_multiple_agents_content(agent_ids: str):
201246
202247@router .get ("/mcps/{mcp_ids}" , tags = ["mcp" ], operation_id = "get_multiple_mcps_config" )
203248async def get_multiple_mcps_config (mcp_ids : str ):
204- """Get config for multiple MCPs by comma-separated names"""
249+ """Get config for multiple MCPs by comma-separated names. These MCPs will need to be installed on the client side (e.g. in `.mcp.json`) """
205250 ids = [id .strip () for id in mcp_ids .split (',' ) if id .strip ()]
206251
207252 if not ids :
0 commit comments