lailaelkoussy commited on
Commit
d874b77
·
1 Parent(s): 8942d03

add pagination to list nodes by type

Browse files
Files changed (1) hide show
  1. gradio_mcp_space.py +33 -10
gradio_mcp_space.py CHANGED
@@ -982,7 +982,7 @@ def entity_relationships(node_id: str) -> str:
982
 
983
 
984
  @observe(as_type="tool")
985
- def search_by_type_and_name(node_type: str, name_query: str, limit: int = 10, fuzzy: bool = True) -> str:
986
  """
987
  Search for nodes/entities by type and name substring with fuzzy matching support.
988
 
@@ -1005,19 +1005,27 @@ def search_by_type_and_name(node_type: str, name_query: str, limit: int = 10, fu
1005
  return "Error: Knowledge graph not initialized"
1006
 
1007
  try:
1008
- # Convert limit to int if it's a string (MCP may pass strings)
1009
  if isinstance(limit, str):
1010
  try:
1011
  limit = int(limit)
1012
  except ValueError:
1013
  return f"Error: 'limit' must be an integer, got '{limit}'"
1014
-
 
 
 
 
 
 
1015
  # Convert fuzzy to bool if it's a string
1016
  if isinstance(fuzzy, str):
1017
  fuzzy = fuzzy.lower() in ('true', '1', 'yes')
1018
-
1019
  if limit <= 0:
1020
  return "Error: limit must be a positive integer"
 
 
1021
 
1022
  g = knowledge_graph.graph
1023
  matches = []
@@ -1084,21 +1092,33 @@ def search_by_type_and_name(node_type: str, name_query: str, limit: int = 10, fu
1084
  "score": score
1085
  })
1086
 
1087
- # Sort by match score (best matches first) and limit results
1088
  matches.sort(key=lambda x: (x['score'], x['name'].lower()))
1089
- matches = matches[:limit]
1090
 
1091
- if not matches:
 
1092
  return f"No matches for type '{node_type}' and name containing '{name_query}'."
1093
 
1094
- result = f"Matches for type '{node_type}' and name '{name_query}' ({len(matches)} results):\n"
 
 
 
 
 
 
 
 
 
1095
  result += "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
1096
 
1097
- for i, match in enumerate(matches, 1):
1098
  result += f"{i}. {match['name']}\n"
1099
  result += f" ID: {match['id']}\n"
1100
  result += f" Type: {match['type']}\n\n"
1101
 
 
 
 
1102
  return result
1103
  except Exception as e:
1104
  return f"Error: {str(e)}"
@@ -1910,10 +1930,13 @@ def create_gradio_app():
1910
  label="Node Type"
1911
  )
1912
  search_name = gr.Textbox(label="Name Contains", placeholder="Enter partial name...")
 
 
 
1913
  search_type_btn = gr.Button("Search", variant="primary")
1914
  with gr.Column():
1915
  search_type_output = gr.Textbox(label="Results", lines=20, max_lines=30)
1916
- search_type_btn.click(fn=search_by_type_and_name, inputs=[search_type, search_name], outputs=search_type_output)
1917
  gr.Markdown(_tool_doc_md(search_by_type_and_name))
1918
 
1919
  with gr.Tab("🔗 Relationships"):
 
982
 
983
 
984
  @observe(as_type="tool")
985
+ def search_by_type_and_name(node_type: str, name_query: str, limit: int = 10, page: int = 1, fuzzy: bool = True) -> str:
986
  """
987
  Search for nodes/entities by type and name substring with fuzzy matching support.
988
 
 
1005
  return "Error: Knowledge graph not initialized"
1006
 
1007
  try:
1008
+ # Convert limit/page to int if they're strings (MCP/Gradio may pass strings)
1009
  if isinstance(limit, str):
1010
  try:
1011
  limit = int(limit)
1012
  except ValueError:
1013
  return f"Error: 'limit' must be an integer, got '{limit}'"
1014
+
1015
+ if isinstance(page, str):
1016
+ try:
1017
+ page = int(page)
1018
+ except ValueError:
1019
+ return f"Error: 'page' must be an integer, got '{page}'"
1020
+
1021
  # Convert fuzzy to bool if it's a string
1022
  if isinstance(fuzzy, str):
1023
  fuzzy = fuzzy.lower() in ('true', '1', 'yes')
1024
+
1025
  if limit <= 0:
1026
  return "Error: limit must be a positive integer"
1027
+ if page < 1:
1028
+ return "Error: 'page' must be a positive integer (1 or greater)"
1029
 
1030
  g = knowledge_graph.graph
1031
  matches = []
 
1092
  "score": score
1093
  })
1094
 
1095
+ # Sort by match score (best matches first)
1096
  matches.sort(key=lambda x: (x['score'], x['name'].lower()))
 
1097
 
1098
+ total = len(matches)
1099
+ if total == 0:
1100
  return f"No matches for type '{node_type}' and name containing '{name_query}'."
1101
 
1102
+ # Pagination
1103
+ total_pages = (total + limit - 1) // limit
1104
+ if page > total_pages:
1105
+ return f"Error: Page {page} does not exist. Total pages: {total_pages} (with {total} results at {limit} per page)"
1106
+
1107
+ start_idx = (page - 1) * limit
1108
+ end_idx = start_idx + limit
1109
+ page_slice = matches[start_idx:end_idx]
1110
+
1111
+ result = f"Matches for type '{node_type}' and name '{name_query}' (Page {page}/{total_pages}, {total} total):\n"
1112
  result += "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
1113
 
1114
+ for i, match in enumerate(page_slice, start=start_idx + 1):
1115
  result += f"{i}. {match['name']}\n"
1116
  result += f" ID: {match['id']}\n"
1117
  result += f" Type: {match['type']}\n\n"
1118
 
1119
+ if page < total_pages:
1120
+ result += f"Use page={page + 1} to see the next page\n"
1121
+
1122
  return result
1123
  except Exception as e:
1124
  return f"Error: {str(e)}"
 
1930
  label="Node Type"
1931
  )
1932
  search_name = gr.Textbox(label="Name Contains", placeholder="Enter partial name...")
1933
+ search_limit = gr.Slider(1, 100, value=10, step=1, label="Max Results")
1934
+ search_page = gr.Slider(1, 100, value=1, step=1, label="Page")
1935
+ search_fuzzy = gr.Checkbox(label="Fuzzy Match", value=True)
1936
  search_type_btn = gr.Button("Search", variant="primary")
1937
  with gr.Column():
1938
  search_type_output = gr.Textbox(label="Results", lines=20, max_lines=30)
1939
+ search_type_btn.click(fn=search_by_type_and_name, inputs=[search_type, search_name, search_limit, search_page, search_fuzzy], outputs=search_type_output)
1940
  gr.Markdown(_tool_doc_md(search_by_type_and_name))
1941
 
1942
  with gr.Tab("🔗 Relationships"):