|
32 | 32 | ) |
33 | 33 | from everyrow.session import create_session, get_session_url |
34 | 34 | from mcp.server.fastmcp import FastMCP |
35 | | -from mcp.types import TextContent |
| 35 | +from mcp.types import TextContent, ToolAnnotations |
36 | 36 | from pydantic import BaseModel, ConfigDict, Field, create_model, field_validator |
37 | 37 |
|
38 | 38 | from everyrow_mcp.utils import ( |
@@ -261,19 +261,33 @@ def validate_output(cls, v: str) -> str: |
261 | 261 | return v |
262 | 262 |
|
263 | 263 |
|
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 | +) |
265 | 275 | 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. |
267 | 277 |
|
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. |
272 | 281 |
|
273 | 282 | Examples: |
274 | 283 | - "Find this company's latest funding round and lead investors" |
275 | 284 | - "Research the CEO's background and previous companies" |
276 | 285 | - "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. |
277 | 291 | """ |
278 | 292 | if _client is None: |
279 | 293 | return [TextContent(type="text", text="Error: MCP server not initialized.")] |
@@ -316,9 +330,23 @@ async def everyrow_agent(params: AgentInput) -> list[TextContent]: |
316 | 330 | ] |
317 | 331 |
|
318 | 332 |
|
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 | +) |
320 | 344 | 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. |
322 | 350 |
|
323 | 351 | Examples: |
324 | 352 | - "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]: |
383 | 411 | ] |
384 | 412 |
|
385 | 413 |
|
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 | +) |
387 | 425 | 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. |
389 | 431 |
|
390 | 432 | Examples: |
391 | 433 | - "Is this job posting remote-friendly AND senior-level AND salary disclosed?" |
@@ -447,13 +489,24 @@ async def everyrow_screen(params: ScreenInput) -> list[TextContent]: |
447 | 489 | ] |
448 | 490 |
|
449 | 491 |
|
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 | +) |
451 | 503 | 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. |
453 | 505 |
|
454 | 506 | 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. |
457 | 510 |
|
458 | 511 | Examples: |
459 | 512 | - Dedupe contacts: "Same person even with name abbreviations or career changes" |
@@ -510,12 +563,23 @@ async def everyrow_dedupe(params: DedupeInput) -> list[TextContent]: |
510 | 563 | ] |
511 | 564 |
|
512 | 565 |
|
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 | +) |
514 | 577 | async def everyrow_merge(params: MergeInput) -> list[TextContent]: |
515 | 578 | """Join two CSV files using intelligent entity matching. |
516 | 579 |
|
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. |
519 | 583 |
|
520 | 584 | Examples: |
521 | 585 | - Match software products to parent companies (Photoshop -> Adobe) |
@@ -578,7 +642,17 @@ async def everyrow_merge(params: MergeInput) -> list[TextContent]: |
578 | 642 | ] |
579 | 643 |
|
580 | 644 |
|
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 | +) |
582 | 656 | async def everyrow_progress(params: ProgressInput) -> list[TextContent]: |
583 | 657 | """Check progress of a running task. Blocks for a time to limit the polling rate. |
584 | 658 |
|
@@ -687,7 +761,17 @@ async def everyrow_progress(params: ProgressInput) -> list[TextContent]: |
687 | 761 | ] |
688 | 762 |
|
689 | 763 |
|
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 | +) |
691 | 775 | async def everyrow_results(params: ResultsInput) -> list[TextContent]: |
692 | 776 | """Retrieve results from a completed everyrow task and save them to a CSV. |
693 | 777 |
|
|
0 commit comments