Skip to content

Commit d93a9fa

Browse files
dschwarz26rgambee
andauthored
Update tool definitions (#153)
Annotate MCP tools and update their descriptions Co-authored-by: Robert Gambee <robert@futuresearch.ai>
1 parent 9b65c32 commit d93a9fa

1 file changed

Lines changed: 104 additions & 20 deletions

File tree

everyrow-mcp/src/everyrow_mcp/server.py

Lines changed: 104 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
)
3333
from everyrow.session import create_session, get_session_url
3434
from mcp.server.fastmcp import FastMCP
35-
from mcp.types import TextContent
35+
from mcp.types import TextContent, ToolAnnotations
3636
from pydantic import BaseModel, ConfigDict, Field, create_model, field_validator
3737

3838
from everyrow_mcp.utils import (
@@ -261,19 +261,33 @@ def validate_output(cls, v: str) -> str:
261261
return v
262262

263263

264-
@mcp.tool(name="everyrow_agent", structured_output=False)
264+
@mcp.tool(
265+
name="everyrow_agent",
266+
structured_output=False,
267+
annotations=ToolAnnotations(
268+
title="Run Web Research Agents",
269+
readOnlyHint=False,
270+
destructiveHint=False,
271+
idempotentHint=False,
272+
openWorldHint=True,
273+
),
274+
)
265275
async def everyrow_agent(params: AgentInput) -> list[TextContent]:
266-
"""Run web research agents on each row of a CSV.
276+
"""Run web research agents on each row of a CSV file.
267277
268-
Submit the task and return immediately with a task_id and session_url.
269-
After receiving a result from this tool, share the session_url with the user.
270-
Then immediately call everyrow_progress(task_id) to monitor.
271-
Once the task is completed, call everyrow_results to save the output.
278+
The dispatched agents will search the web, read pages, and return the
279+
requested research fields for each row. Agents run in parallel to save
280+
time and are optimized to find accurate answers at minimum cost.
272281
273282
Examples:
274283
- "Find this company's latest funding round and lead investors"
275284
- "Research the CEO's background and previous companies"
276285
- "Find pricing information for this product"
286+
287+
This function submits the task and returns immediately with a task_id and session_url.
288+
After receiving a result from this tool, share the session_url with the user.
289+
Then immediately call everyrow_progress(task_id) to monitor.
290+
Once the task is completed, call everyrow_results to save the output.
277291
"""
278292
if _client is None:
279293
return [TextContent(type="text", text="Error: MCP server not initialized.")]
@@ -316,9 +330,23 @@ async def everyrow_agent(params: AgentInput) -> list[TextContent]:
316330
]
317331

318332

319-
@mcp.tool(name="everyrow_rank", structured_output=False)
333+
@mcp.tool(
334+
name="everyrow_rank",
335+
structured_output=False,
336+
annotations=ToolAnnotations(
337+
title="Score and Rank Rows",
338+
readOnlyHint=False,
339+
destructiveHint=False,
340+
idempotentHint=False,
341+
openWorldHint=True,
342+
),
343+
)
320344
async def everyrow_rank(params: RankInput) -> list[TextContent]:
321-
"""Score and sort rows in a CSV based on qualitative criteria.
345+
"""Score and sort rows in a CSV file based on any criteria.
346+
347+
Dispatches web agents to research the criteria to rank the entities in the
348+
table. Conducts research, and can also apply judgment to the results if the
349+
criteria are qualitative.
322350
323351
Examples:
324352
- "Score this lead from 0 to 10 by likelihood to need data integration solutions"
@@ -383,9 +411,23 @@ async def everyrow_rank(params: RankInput) -> list[TextContent]:
383411
]
384412

385413

386-
@mcp.tool(name="everyrow_screen", structured_output=False)
414+
@mcp.tool(
415+
name="everyrow_screen",
416+
structured_output=False,
417+
annotations=ToolAnnotations(
418+
title="Filter Rows by Criteria",
419+
readOnlyHint=False,
420+
destructiveHint=False,
421+
idempotentHint=False,
422+
openWorldHint=True,
423+
),
424+
)
387425
async def everyrow_screen(params: ScreenInput) -> list[TextContent]:
388-
"""Filter rows in a CSV based on criteria that require judgment.
426+
"""Filter rows in a CSV file based on any criteria.
427+
428+
Dispatches web agents to research the criteria to filter the entities in the
429+
table. Conducts research, and can also apply judgment to the results if the
430+
criteria are qualitative.
389431
390432
Examples:
391433
- "Is this job posting remote-friendly AND senior-level AND salary disclosed?"
@@ -447,13 +489,24 @@ async def everyrow_screen(params: ScreenInput) -> list[TextContent]:
447489
]
448490

449491

450-
@mcp.tool(name="everyrow_dedupe", structured_output=False)
492+
@mcp.tool(
493+
name="everyrow_dedupe",
494+
structured_output=False,
495+
annotations=ToolAnnotations(
496+
title="Deduplicate Rows",
497+
readOnlyHint=False,
498+
destructiveHint=False,
499+
idempotentHint=False,
500+
openWorldHint=True,
501+
),
502+
)
451503
async def everyrow_dedupe(params: DedupeInput) -> list[TextContent]:
452-
"""Remove duplicate rows from a CSV using semantic equivalence.
504+
"""Remove duplicate rows from a CSV file using semantic equivalence.
453505
454506
Dedupe identifies rows that represent the same entity even when they
455-
don't match exactly. Useful for fuzzy deduplication where string
456-
matching fails.
507+
don't match exactly. The duplicate criterion is semantic and LLM-powered:
508+
agents reason over the data and, when needed, search the web for external
509+
information to establish equivalence.
457510
458511
Examples:
459512
- Dedupe contacts: "Same person even with name abbreviations or career changes"
@@ -510,12 +563,23 @@ async def everyrow_dedupe(params: DedupeInput) -> list[TextContent]:
510563
]
511564

512565

513-
@mcp.tool(name="everyrow_merge", structured_output=False)
566+
@mcp.tool(
567+
name="everyrow_merge",
568+
structured_output=False,
569+
annotations=ToolAnnotations(
570+
title="Merge Two Tables",
571+
readOnlyHint=False,
572+
destructiveHint=False,
573+
idempotentHint=False,
574+
openWorldHint=True,
575+
),
576+
)
514577
async def everyrow_merge(params: MergeInput) -> list[TextContent]:
515578
"""Join two CSV files using intelligent entity matching.
516579
517-
Merge combines two tables even when keys don't match exactly. The LLM
518-
performs research and reasoning to identify which rows should be joined.
580+
Merge combines two tables even when keys don't match exactly. Uses LLM web
581+
research and judgment to identify which rows from the first table should
582+
join those in the second.
519583
520584
Examples:
521585
- Match software products to parent companies (Photoshop -> Adobe)
@@ -578,7 +642,17 @@ async def everyrow_merge(params: MergeInput) -> list[TextContent]:
578642
]
579643

580644

581-
@mcp.tool(name="everyrow_progress", structured_output=False)
645+
@mcp.tool(
646+
name="everyrow_progress",
647+
structured_output=False,
648+
annotations=ToolAnnotations(
649+
title="Check Task Progress",
650+
readOnlyHint=True,
651+
destructiveHint=False,
652+
idempotentHint=True,
653+
openWorldHint=False,
654+
),
655+
)
582656
async def everyrow_progress(params: ProgressInput) -> list[TextContent]:
583657
"""Check progress of a running task. Blocks for a time to limit the polling rate.
584658
@@ -687,7 +761,17 @@ async def everyrow_progress(params: ProgressInput) -> list[TextContent]:
687761
]
688762

689763

690-
@mcp.tool(name="everyrow_results", structured_output=False)
764+
@mcp.tool(
765+
name="everyrow_results",
766+
structured_output=False,
767+
annotations=ToolAnnotations(
768+
title="Save Task Results",
769+
readOnlyHint=False,
770+
destructiveHint=False,
771+
idempotentHint=False,
772+
openWorldHint=False,
773+
),
774+
)
691775
async def everyrow_results(params: ResultsInput) -> list[TextContent]:
692776
"""Retrieve results from a completed everyrow task and save them to a CSV.
693777

0 commit comments

Comments
 (0)