Skip to content

Commit a96569d

Browse files
authored
Merge pull request #35 from meilisearch/fix/issue-17-default-limit-offset
Fix issue #17: Add default limit and offset to get-documents tool
2 parents f338139 + 1ef03b7 commit a96569d

File tree

5 files changed

+311
-144
lines changed

5 files changed

+311
-144
lines changed

src/meilisearch_mcp/client.py

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ async def search(
5252
offset: Optional[int] = 0,
5353
filter: Optional[str] = None,
5454
sort: Optional[List[str]] = None,
55-
**kwargs
55+
**kwargs,
5656
) -> Dict[str, Any]:
5757
"""
5858
Search through Meilisearch indices.
@@ -65,12 +65,12 @@ async def search(
6565
"limit": limit if limit is not None else 20,
6666
"offset": offset if offset is not None else 0,
6767
}
68-
68+
6969
if filter is not None:
7070
search_params["filter"] = filter
7171
if sort is not None:
7272
search_params["sort"] = sort
73-
73+
7474
# Add any additional parameters
7575
search_params.update({k: v for k, v in kwargs.items() if v is not None})
7676

@@ -82,7 +82,7 @@ async def search(
8282
# Search across all indices
8383
results = {}
8484
indexes = self.client.get_indexes()
85-
85+
8686
for index in indexes["results"]:
8787
try:
8888
search_result = index.search(query, search_params)
@@ -91,13 +91,9 @@ async def search(
9191
except Exception as e:
9292
logger.warning(f"Failed to search index {index.uid}: {str(e)}")
9393
continue
94-
95-
return {
96-
"multi_index": True,
97-
"query": query,
98-
"results": results
99-
}
100-
94+
95+
return {"multi_index": True, "query": query, "results": results}
96+
10197
except Exception as e:
10298
raise Exception(f"Search failed: {str(e)}")
10399

src/meilisearch_mcp/documents.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ async def get_documents(
5454
return result_dict
5555
else:
5656
return result
57-
5857
except Exception as e:
5958
raise Exception(f"Failed to get documents: {str(e)}")
6059

src/meilisearch_mcp/server.py

Lines changed: 79 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ def json_serializer(obj: Any) -> str:
2424
return str(obj)
2525

2626

27-
def create_server(url: str = "http://localhost:7700", api_key: Optional[str] = None) -> "MeilisearchMCPServer":
27+
def create_server(
28+
url: str = "http://localhost:7700", api_key: Optional[str] = None
29+
) -> "MeilisearchMCPServer":
2830
"""Create and return a configured MeilisearchMCPServer instance"""
2931
return MeilisearchMCPServer(url, api_key)
3032

@@ -48,13 +50,15 @@ def __init__(
4850
self.server = Server("meilisearch")
4951
self._setup_handlers()
5052

51-
async def update_connection(self, url: Optional[str] = None, api_key: Optional[str] = None):
53+
async def update_connection(
54+
self, url: Optional[str] = None, api_key: Optional[str] = None
55+
):
5256
"""Update connection settings and reinitialize client if needed"""
5357
if url:
5458
self.url = url
5559
if api_key:
5660
self.api_key = api_key
57-
61+
5862
self.meili_client = MeilisearchClient(self.url, self.api_key)
5963
self.logger.info("Updated Meilisearch connection settings", url=self.url)
6064

@@ -171,7 +175,11 @@ async def handle_list_tools() -> list[types.Tool]:
171175
"limit": {"type": "integer", "optional": True},
172176
"offset": {"type": "integer", "optional": True},
173177
"filter": {"type": "string", "optional": True},
174-
"sort": {"type": "array", "items": {"type": "string"}, "optional": True},
178+
"sort": {
179+
"type": "array",
180+
"items": {"type": "string"},
181+
"optional": True,
182+
},
175183
},
176184
"required": ["query"],
177185
},
@@ -194,20 +202,44 @@ async def handle_list_tools() -> list[types.Tool]:
194202
"limit": {"type": "integer", "optional": True},
195203
"from": {"type": "integer", "optional": True},
196204
"reverse": {"type": "boolean", "optional": True},
197-
"batchUids": {"type": "array", "items": {"type": "string"}, "optional": True},
198-
"uids": {"type": "array", "items": {"type": "integer"}, "optional": True},
199-
"canceledBy": {"type": "array", "items": {"type": "string"}, "optional": True},
200-
"types": {"type": "array", "items": {"type": "string"}, "optional": True},
201-
"statuses": {"type": "array", "items": {"type": "string"}, "optional": True},
202-
"indexUids": {"type": "array", "items": {"type": "string"}, "optional": True},
205+
"batchUids": {
206+
"type": "array",
207+
"items": {"type": "string"},
208+
"optional": True,
209+
},
210+
"uids": {
211+
"type": "array",
212+
"items": {"type": "integer"},
213+
"optional": True,
214+
},
215+
"canceledBy": {
216+
"type": "array",
217+
"items": {"type": "string"},
218+
"optional": True,
219+
},
220+
"types": {
221+
"type": "array",
222+
"items": {"type": "string"},
223+
"optional": True,
224+
},
225+
"statuses": {
226+
"type": "array",
227+
"items": {"type": "string"},
228+
"optional": True,
229+
},
230+
"indexUids": {
231+
"type": "array",
232+
"items": {"type": "string"},
233+
"optional": True,
234+
},
203235
"afterEnqueuedAt": {"type": "string", "optional": True},
204236
"beforeEnqueuedAt": {"type": "string", "optional": True},
205237
"afterStartedAt": {"type": "string", "optional": True},
206238
"beforeStartedAt": {"type": "string", "optional": True},
207239
"afterFinishedAt": {"type": "string", "optional": True},
208-
"beforeFinishedAt": {"type": "string", "optional": True}
209-
}
210-
}
240+
"beforeFinishedAt": {"type": "string", "optional": True},
241+
},
242+
},
211243
),
212244
types.Tool(
213245
name="cancel-tasks",
@@ -293,8 +325,7 @@ async def handle_call_tool(
293325

294326
elif name == "update-connection-settings":
295327
await self.update_connection(
296-
arguments.get("url"),
297-
arguments.get("api_key")
328+
arguments.get("url"), arguments.get("api_key")
298329
)
299330
return [
300331
types.TextContent(
@@ -313,7 +344,9 @@ async def handle_call_tool(
313344

314345
elif name == "list-indexes":
315346
indexes = await self.meili_client.get_indexes()
316-
formatted_json = json.dumps(indexes, indent=2, default=json_serializer)
347+
formatted_json = json.dumps(
348+
indexes, indent=2, default=json_serializer
349+
)
317350
return [
318351
types.TextContent(
319352
type="text", text=f"Indexes:\n{formatted_json}"
@@ -397,13 +430,15 @@ async def handle_call_tool(
397430
filter=arguments.get("filter"),
398431
sort=arguments.get("sort"),
399432
)
400-
433+
401434
# Format the results for better readability
402-
formatted_results = json.dumps(search_results, indent=2, default=json_serializer)
435+
formatted_results = json.dumps(
436+
search_results, indent=2, default=json_serializer
437+
)
403438
return [
404439
types.TextContent(
405440
type="text",
406-
text=f"Search results for '{arguments['query']}':\n{formatted_results}"
441+
text=f"Search results for '{arguments['query']}':\n{formatted_results}",
407442
)
408443
]
409444

@@ -416,11 +451,27 @@ async def handle_call_tool(
416451
elif name == "get-tasks":
417452
# Filter out any invalid parameters
418453
valid_params = {
419-
"limit", "from", "reverse", "batchUids", "uids", "canceledBy",
420-
"types", "statuses", "indexUids", "afterEnqueuedAt", "beforeEnqueuedAt",
421-
"afterStartedAt", "beforeStartedAt", "afterFinishedAt", "beforeFinishedAt"
454+
"limit",
455+
"from",
456+
"reverse",
457+
"batchUids",
458+
"uids",
459+
"canceledBy",
460+
"types",
461+
"statuses",
462+
"indexUids",
463+
"afterEnqueuedAt",
464+
"beforeEnqueuedAt",
465+
"afterStartedAt",
466+
"beforeStartedAt",
467+
"afterFinishedAt",
468+
"beforeFinishedAt",
422469
}
423-
filtered_args = {k: v for k, v in arguments.items() if k in valid_params} if arguments else {}
470+
filtered_args = (
471+
{k: v for k, v in arguments.items() if k in valid_params}
472+
if arguments
473+
else {}
474+
)
424475
tasks = await self.meili_client.tasks.get_tasks(filtered_args)
425476
return [types.TextContent(type="text", text=f"Tasks: {tasks}")]
426477

@@ -479,7 +530,8 @@ async def handle_call_tool(
479530
)
480531
return [
481532
types.TextContent(
482-
type="text", text=f"Index metrics: {json.dumps(metrics.__dict__, default=json_serializer)}"
533+
type="text",
534+
text=f"Index metrics: {json.dumps(metrics.__dict__, default=json_serializer)}",
483535
)
484536
]
485537

@@ -526,13 +578,15 @@ async def cleanup(self):
526578
self.logger.info("Shutting down MCP server")
527579
self.logger.shutdown()
528580

581+
529582
def main():
530583
"""Main entry point"""
531584
url = os.getenv("MEILI_HTTP_ADDR", "http://localhost:7700")
532585
api_key = os.getenv("MEILI_MASTER_KEY")
533-
586+
534587
server = create_server(url, api_key)
535588
asyncio.run(server.run())
536589

590+
537591
if __name__ == "__main__":
538592
main()

src/meilisearch_mcp/tasks.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
def serialize_task_results(obj: Any) -> Any:
77
"""Serialize task results into JSON-compatible format"""
8-
if hasattr(obj, '__dict__'):
8+
if hasattr(obj, "__dict__"):
99
return {k: serialize_task_results(v) for k, v in obj.__dict__.items()}
1010
elif isinstance(obj, (list, tuple)):
1111
return [serialize_task_results(item) for item in obj]

0 commit comments

Comments
 (0)