Skip to content

Commit d51dc47

Browse files
committed
Rename tools and add titles search functionality
- Rename pia_search -> pia_search_content for clarity - Rename pia_search_facets -> pia_search_content_facets - Add new pia_search_titles tool for title-only searches - Add new pia_search_titles_facets tool for title search facets - Update tool schemas to match remote server implementation - Synchronize prompts with examples/prompts structure - Update all tests to reflect new tool names (14 tests passing) - Update README documentation to describe all four tools - Update imports and exports throughout codebase Now provides comprehensive search capabilities: - Content search: Full-text search in document content - Title search: Fast document discovery by title - Facets for both modes: Filter value discovery - All tools support OData filtering with proper field names
1 parent 1f21abb commit d51dc47

File tree

6 files changed

+335
-107
lines changed

6 files changed

+335
-107
lines changed

README.md

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -123,22 +123,57 @@ For Docker:
123123

124124
## 💡 Available Tools
125125

126-
The server provides two main tools:
126+
The server provides four main tools:
127127

128-
### 1. PIA Search
129-
Comprehensive search with OData filtering and faceting. The `filter` parameter uses standard [OData query syntax](https://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part2-url-conventions.html).
128+
### 1. `pia_search_content`
129+
130+
Comprehensive search tool for querying document content and recommendations in the PIA database.
130131

131-
**Tool Name:** `pia_search`
132+
**Tool Name:** `pia_search_content`
132133

133134
**Parameters:**
134135
- `query` (required): Search query text
135136
- `filter` (optional): OData filter expression
136137
- `page` (optional): Page number (default: 1)
137138
- `page_size` (optional): Results per page (default: 10)
138139
- `search_mode` (optional): Search mode (default: "content")
140+
141+
### 2. `pia_search_content_facets`
142+
143+
Tool for discovering available filter values before performing content searches.
144+
145+
**Parameters:**
146+
- `query` (optional): Query to get facets for (if empty, gets all facets)
147+
- `filter` (optional): OData filter expression
148+
149+
### 3. `pia_search_titles`
150+
151+
Search document titles only for faster discovery of available documents.
152+
153+
**Parameters:**
154+
- `query` (required): Search query text (searches document titles only)
155+
- `filter` (optional): OData filter expression
156+
- `page` (optional): Page number (default: 1)
157+
- `page_size` (optional): Results per page (default: 10)
158+
- `search_mode` (optional): Search mode (default: "titles")
139159
- `limit` (optional): Maximum results limit
140160
- `include_facets` (optional): Include facets in results (default: false)
141161

162+
### 4. `pia_search_titles_facets`
163+
164+
Tool for discovering available filter values before performing title searches.
165+
166+
**Parameters:**
167+
- `query` (optional): Query to get facets for (if empty, gets all facets)
168+
- `filter` (optional): OData filter expression
169+
170+
## Search Modes
171+
172+
Comprehensive search with OData filtering and faceting. The `filter` parameter uses standard [OData query syntax](https://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part2-url-conventions.html).
173+
174+
- **Content Search** (`pia_search_content`): Searches within document content and recommendations for comprehensive results
175+
- **Title Search** (`pia_search_titles`): Searches document titles only - faster and useful for document discovery
176+
142177
**Example Filter Expressions:**
143178
- Basic filter: `"SourceDocumentDataSource eq 'GAO'"`
144179
- Multiple conditions: `"SourceDocumentDataSource eq 'GAO' or SourceDocumentDataSource eq 'OIG'"`
@@ -183,7 +218,7 @@ Discover available field names and values for filtering.
183218
- Find possible field values (e.g., "OIG", "GAO", "audit_report")
184219
- Understand data types for each field (string, date, number)
185220

186-
This information helps you construct proper `filter` expressions for the `pia_search` tool.
221+
This information helps you construct proper `filter` expressions for the search tools.
187222

188223
## 🔍 Filter Discovery Workflow
189224

src/pia_mcp_server/prompts/handlers.py

Lines changed: 28 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,14 @@
99
# Available prompts for PIA MCP server
1010
AVAILABLE_PROMPTS = [
1111
{
12-
"name": "summary_prompt",
13-
"description": "Instructions for LLM to summarize information only from provided search results with proper citations",
14-
"arguments": [
15-
{
16-
"name": "search_results",
17-
"description": "The search results to summarize (will be inserted into <SEARCH_RESULTS> tags)",
18-
"required": True,
19-
},
20-
],
12+
"name": "summarization_guidance",
13+
"description": "Provides guidance on how to summarize information from PIA search results with proper citations",
14+
"arguments": [],
2115
},
2216
{
23-
"name": "search_prompt",
24-
"description": "Instructions for LLM on how to effectively use PIA search tools with proper filtering",
25-
"arguments": [
26-
{
27-
"name": "user_query",
28-
"description": "The user's search query to analyze for filter criteria",
29-
"required": True,
30-
},
31-
],
17+
"name": "search_guidance",
18+
"description": "Provides guidance on how to perform PIA searches with or without filters",
19+
"arguments": [],
3220
},
3321
]
3422

@@ -76,10 +64,10 @@ async def get_prompt(
7664
arguments = arguments or {}
7765

7866
# Generate prompt content based on the type
79-
if name == "summary_prompt":
80-
content = _generate_summary_prompt(arguments)
81-
elif name == "search_prompt":
82-
content = _generate_search_prompt(arguments)
67+
if name == "summarization_guidance":
68+
content = _generate_summarization_guidance()
69+
elif name == "search_guidance":
70+
content = _generate_search_guidance()
8371
else:
8472
content = f"Prompt template for {name} - implement specific logic based on arguments: {arguments}"
8573

@@ -93,11 +81,9 @@ async def get_prompt(
9381
)
9482

9583

96-
def _generate_summary_prompt(arguments: Dict[str, str]) -> str:
97-
"""Generate summary prompt for LLM."""
98-
search_results = arguments.get("search_results", "")
99-
100-
return f"""You are an assistant that summarizes information **only** from the provided search results.
84+
def _generate_summarization_guidance() -> str:
85+
"""Generate summarization guidance prompt."""
86+
return """You are an assistant that summarizes information **only** from the provided search results.
10187
10288
Your task:
10389
1. **Only include facts that appear in the provided search results.**
@@ -130,8 +116,6 @@ def _generate_summary_prompt(arguments: Dict[str, str]) -> str:
130116
131117
Input to use:
132118
<SEARCH_RESULTS>
133-
{search_results}
134-
</SEARCH_RESULTS>
135119
136120
Output template:
137121
---
@@ -151,33 +135,37 @@ def _generate_summary_prompt(arguments: Dict[str, str]) -> str:
151135
- If you can't find enough information for a point, omit it entirely."""
152136

153137

154-
def _generate_search_prompt(arguments: Dict[str, str]) -> str:
155-
"""Generate search prompt for LLM."""
156-
user_query = arguments.get("user_query", "")
157-
158-
return f"""You can perform searches using the PIA Search tools with or without filters.
138+
def _generate_search_guidance() -> str:
139+
"""Generate search guidance prompt."""
140+
return """You can perform searches using the PIA Search tools with or without filters.
159141
160142
General rules:
161143
- Run an **unfiltered search** by default if no filter criteria are mentioned in the user's request.
162144
- If the user's request includes any specific filter criteria (e.g., agency name, year, category):
163-
1. Call `pia_search_facets` once to discover the filterable field names and allowed values.
145+
1. Call `pia_search_content_facets` or `pia_search_titles_facets` once to discover the filterable field names and allowed values.
164146
2. Use these to build a valid OData filter expression.
165147
3. Call the search tool with the filter applied.
166148
149+
Available search tools:
150+
- `pia_search_content`: Search within document content and recommendations
151+
- `pia_search_content_facets`: Get available filter values for content search
152+
- `pia_search_titles`: Search document titles only (faster, good for discovery)
153+
- `pia_search_titles_facets`: Get available filter values for title search
154+
167155
Process for applying filters:
168156
169157
1. **Detect filter intent**:
170158
- Examine the user's query for references to agencies, dates, categories, or other filterable attributes.
171159
- If such references are present, treat the search as **filtered**.
172160
173161
2. **Discover filterable fields and values** (only if filtering):
174-
- Call the `pia_search_facets` tool (one time per session unless filters change).
162+
- Call the appropriate facets tool (one time per session unless filters change).
175163
- Review the output to see:
176164
- Field names that support filtering.
177165
- Possible values for each field.
178166
179167
3. **Build the filter expression**:
180-
- Use **only field names and values** returned by `pia_search_facets`.
168+
- Use **only field names and values** returned by the facets tools.
181169
- Construct the filter in **OData syntax**:
182170
- `SourceDocumentDataSource eq 'GAO'`
183171
- `(SourceDocumentDataSource eq 'GAO' or SourceDocumentDataSource eq 'OIG') and SourceDocumentPublishDate ge '2020-01-01'`
@@ -200,12 +188,12 @@ def _generate_search_prompt(arguments: Dict[str, str]) -> str:
200188
- Inform the user you are showing unfiltered results because no matches were found with the filter.
201189
202190
6. **Validation**:
203-
- Never use a field or value not provided by `pia_search_facets`.
204-
- If the user requests a filter that doesn't exist in `pia_search_facets`, explain it's not available and offer an unfiltered search instead.
191+
- Never use a field or value not provided by the facets tools.
192+
- If the user requests a filter that doesn't exist in facets, explain it's not available and offer an unfiltered search instead.
205193
206194
Goal:
207195
- Default to unfiltered search unless filter criteria are clearly present in the query.
208196
- Always validate filter fields/values before applying them.
209197
- Fall back to unfiltered if filtering produces zero results and it hasn't already been run.
210198
211-
User query to analyze: "{user_query}\""""
199+
"""

src/pia_mcp_server/server.py

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,16 @@
1414
from mcp.server.stdio import stdio_server
1515
from .config import Settings
1616
from .tools import (
17-
handle_pia_search,
18-
handle_pia_search_facets,
17+
handle_pia_search_content,
18+
handle_pia_search_content_facets,
19+
handle_pia_search_titles,
20+
handle_pia_search_titles_facets,
1921
)
2022
from .tools import (
21-
pia_search_tool,
22-
pia_search_facets_tool,
23+
pia_search_content_tool,
24+
pia_search_content_facets_tool,
25+
pia_search_titles_tool,
26+
pia_search_titles_facets_tool,
2327
)
2428
from .prompts.handlers import list_prompts as handler_list_prompts
2529
from .prompts.handlers import get_prompt as handler_get_prompt
@@ -48,8 +52,10 @@ async def get_prompt(
4852
async def list_tools() -> List[types.Tool]:
4953
"""List available PIA research tools."""
5054
return [
51-
pia_search_tool,
52-
pia_search_facets_tool,
55+
pia_search_content_tool,
56+
pia_search_content_facets_tool,
57+
pia_search_titles_tool,
58+
pia_search_titles_facets_tool,
5359
]
5460

5561

@@ -58,10 +64,14 @@ async def call_tool(name: str, arguments: Dict[str, Any]) -> List[types.TextCont
5864
"""Handle tool calls for PIA research functionality."""
5965
logger.debug(f"Calling tool {name} with arguments {arguments}")
6066
try:
61-
if name == "pia_search":
62-
return await handle_pia_search(arguments)
63-
elif name == "pia_search_facets":
64-
return await handle_pia_search_facets(arguments)
67+
if name == "pia_search_content":
68+
return await handle_pia_search_content(arguments)
69+
elif name == "pia_search_content_facets":
70+
return await handle_pia_search_content_facets(arguments)
71+
elif name == "pia_search_titles":
72+
return await handle_pia_search_titles(arguments)
73+
elif name == "pia_search_titles_facets":
74+
return await handle_pia_search_titles_facets(arguments)
6575
else:
6676
return [types.TextContent(type="text", text=f"Error: Unknown tool {name}")]
6777
except Exception as e:

src/pia_mcp_server/tools/__init__.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,23 @@
66
"""
77

88
from .search_tools import (
9-
handle_pia_search,
10-
pia_search_tool,
11-
handle_pia_search_facets,
12-
pia_search_facets_tool,
9+
handle_pia_search_content,
10+
pia_search_content_tool,
11+
handle_pia_search_content_facets,
12+
pia_search_content_facets_tool,
13+
handle_pia_search_titles,
14+
pia_search_titles_tool,
15+
handle_pia_search_titles_facets,
16+
pia_search_titles_facets_tool,
1317
)
1418

1519
__all__ = [
16-
"handle_pia_search",
17-
"pia_search_tool",
18-
"handle_pia_search_facets",
19-
"pia_search_facets_tool",
20+
"handle_pia_search_content",
21+
"pia_search_content_tool",
22+
"handle_pia_search_content_facets",
23+
"pia_search_content_facets_tool",
24+
"handle_pia_search_titles",
25+
"pia_search_titles_tool",
26+
"handle_pia_search_titles_facets",
27+
"pia_search_titles_facets_tool",
2028
]

0 commit comments

Comments
 (0)