Skip to content

Commit bca7d8f

Browse files
straetergithub-actions[bot]
authored andcommitted
Remove screen sdk + sdk + api + docs (#4865)
- remove screen from api, sdk, mcp + docs Sourced from commit 20d57ae93603fd9741bd4af35d2efadb0fba3227
1 parent 7ff1b9c commit bca7d8f

26 files changed

Lines changed: 29 additions & 1628 deletions

everyrow-mcp/README.md

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
55
MCP (Model Context Protocol) server for [everyrow](https://everyrow.io): agent ops at spreadsheet scale.
66

7-
This server exposes everyrow's core operations as MCP tools, allowing LLM applications to classify, screen, rank, dedupe, merge, forecast, and run agents on CSV files.
7+
This server exposes everyrow's core operations as MCP tools, allowing LLM applications to classify, rank, dedupe, merge, forecast, and run agents on CSV files.
88

99
**All tools operate on local CSV files.** Provide absolute file paths as input, and transformed results are written to new CSV files at your specified output path.
1010

@@ -60,19 +60,6 @@ All operations follow an async pattern:
6060

6161
## Available Tools
6262

63-
### everyrow_screen
64-
65-
Filter CSV rows based on criteria that require judgment.
66-
67-
```
68-
Parameters:
69-
- task: Natural language description of screening criteria
70-
- input_csv: Absolute path to input CSV
71-
- response_schema: (optional) JSON schema for custom response fields
72-
```
73-
74-
Example: Filter job postings for "remote-friendly AND senior-level AND salary disclosed"
75-
7663
### everyrow_rank
7764

7865
Score and sort CSV rows based on qualitative criteria.

everyrow-mcp/manifest.json

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,6 @@
2929
}
3030
},
3131
"tools": [
32-
{
33-
"name": "everyrow_screen",
34-
"description": "Filter rows in a CSV file based on any criteria."
35-
},
3632
{
3733
"name": "everyrow_rank",
3834
"description": "Score and sort rows in a CSV file based on any criteria."
@@ -113,7 +109,7 @@
113109
"python": ">=3.12"
114110
}
115111
},
116-
"keywords": ["everyrow", "dataframe", "csv", "ai", "data-processing", "classify", "dedupe", "merge", "rank", "screen", "forecast"],
112+
"keywords": ["everyrow", "dataframe", "csv", "ai", "data-processing", "classify", "dedupe", "merge", "rank", "forecast"],
117113
"license": "MIT",
118114
"privacy_policies": ["https://futuresearch.ai/privacy/"]
119115
}

everyrow-mcp/src/everyrow_mcp/app.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ async def no_auth_http_lifespan(_server: FastMCP):
8282
## Workflow
8383
1. **Ingest data** — pass `data` (inline list of dicts) or an `artifact_id` \
8484
(from `everyrow_upload_data` or `everyrow_request_upload_url`) to any processing tool.
85-
2. **Submit** — call a processing tool (everyrow_agent, everyrow_screen, \
85+
2. **Submit** — call a processing tool (everyrow_agent, everyrow_classify, \
8686
everyrow_rank, everyrow_dedupe, everyrow_merge, everyrow_forecast). \
8787
It returns a task_id immediately.
8888
3. **Poll** — call `everyrow_progress(task_id)` repeatedly until the task completes. \

everyrow-mcp/src/everyrow_mcp/models.py

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -78,25 +78,6 @@ def _validate_response_schema(schema: dict[str, Any] | None) -> dict[str, Any] |
7878
return schema
7979

8080

81-
def _validate_screen_response_schema(
82-
schema: dict[str, Any] | None,
83-
) -> dict[str, Any] | None:
84-
"""Validate screen response_schema includes at least one boolean property."""
85-
validated_schema = _validate_response_schema(schema)
86-
if validated_schema is None:
87-
return None
88-
89-
properties = validated_schema["properties"]
90-
has_boolean_property = any(
91-
isinstance(field_def, dict) and field_def.get("type") == "boolean"
92-
for field_def in properties.values()
93-
)
94-
if not has_boolean_property:
95-
raise ValueError("response_schema must include at least one boolean property")
96-
97-
return validated_schema
98-
99-
10081
def _schema_to_model(name: str, schema: dict[str, Any]) -> type[BaseModel]:
10182
"""Convert a JSON schema dict to a dynamic Pydantic model.
10283
@@ -314,28 +295,6 @@ def validate_response_schema(
314295
return _validate_response_schema(v)
315296

316297

317-
class ScreenInput(_SingleSourceInput):
318-
"""Input for the screen operation."""
319-
320-
model_config = ConfigDict(str_strip_whitespace=True, extra="forbid")
321-
322-
task: str = Field(
323-
..., description="Natural language screening criteria.", min_length=1
324-
)
325-
response_schema: dict[str, Any] | None = Field(
326-
default=None,
327-
description="Optional JSON schema for the response model. "
328-
"Must include at least one boolean property — screen uses the boolean field to filter rows into pass/fail.",
329-
)
330-
331-
@field_validator("response_schema")
332-
@classmethod
333-
def validate_response_schema(
334-
cls, v: dict[str, Any] | None
335-
) -> dict[str, Any] | None:
336-
return _validate_screen_response_schema(v)
337-
338-
339298
class DedupeInput(_SingleSourceInput):
340299
"""Input for the dedupe operation."""
341300

everyrow-mcp/src/everyrow_mcp/tool_helpers.py

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ async def create_tool_response(
321321
return [main_content]
322322

323323

324-
_UI_EXCLUDE: set[str] = {"is_terminal", "is_screen", "task_type", "error", "started_at"}
324+
_UI_EXCLUDE: set[str] = {"is_terminal", "task_type", "error", "started_at"}
325325

326326

327327
class TaskState(BaseModel):
@@ -349,11 +349,6 @@ def is_terminal(self) -> bool:
349349
TaskStatus.REVOKED,
350350
)
351351

352-
@computed_field
353-
@property
354-
def is_screen(self) -> bool:
355-
return self._response.task_type == PublicTaskType.SCREEN
356-
357352
@computed_field
358353
@property
359354
def task_type(self) -> PublicTaskType:
@@ -441,10 +436,7 @@ def progress_message( # noqa: PLR0912
441436
if self.error:
442437
return f"Task {self.status.value}: {self.error}"
443438
if self.status == TaskStatus.COMPLETED:
444-
if self.is_screen:
445-
completed_msg = f"Screening complete ({self.elapsed_s}s)."
446-
else:
447-
completed_msg = f"Completed: {self.completed}/{self.total} ({self.failed} failed) in {self.elapsed_s}s."
439+
completed_msg = f"Completed: {self.completed}/{self.total} ({self.failed} failed) in {self.elapsed_s}s."
448440
if settings.is_http:
449441
if self.total <= settings.auto_page_size_threshold:
450442
next_call = dedent(f"""\
@@ -467,11 +459,6 @@ def progress_message( # noqa: PLR0912
467459
return f"{completed_msg}\n{next_call}"
468460
return f"Task {self.status.value}. Report the error to the user."
469461

470-
if self.is_screen:
471-
return dedent(f"""\
472-
Screen running ({self.elapsed_s}s elapsed).
473-
Immediately call everyrow_progress(task_id='{task_id}').""")
474-
475462
fail_part = f", {self.failed} failed" if self.failed else ""
476463
cursor_arg = f", cursor='{cursor}'" if cursor else ""
477464
msg = dedent(f"""\

everyrow-mcp/src/everyrow_mcp/tools.py

Lines changed: 2 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
forecast_async,
2424
merge_async,
2525
rank_async,
26-
screen_async,
2726
single_agent_async,
2827
)
2928
from everyrow.session import create_session, get_session_url, list_sessions
@@ -48,7 +47,6 @@
4847
MergeInput,
4948
ProgressInput,
5049
RankInput,
51-
ScreenInput,
5250
SingleAgentInput,
5351
StdioResultsInput,
5452
UploadDataInput,
@@ -509,88 +507,6 @@ async def everyrow_rank(params: RankInput, ctx: EveryRowContext) -> list[TextCon
509507
)
510508

511509

512-
@mcp.tool(
513-
name="everyrow_screen",
514-
structured_output=False,
515-
annotations=ToolAnnotations(
516-
title="Filter Rows by Criteria",
517-
readOnlyHint=False,
518-
destructiveHint=False,
519-
idempotentHint=False,
520-
openWorldHint=True,
521-
),
522-
)
523-
async def everyrow_screen(
524-
params: ScreenInput, ctx: EveryRowContext
525-
) -> list[TextContent]:
526-
"""Filter rows in a CSV file based on any criteria.
527-
528-
Dispatches web agents to research the criteria to filter the entities in the
529-
table. Conducts research, and can also apply judgment to the results if the
530-
criteria are qualitative.
531-
532-
Screen produces a boolean pass/fail verdict per row. If you provide a custom
533-
response_schema, it MUST include at least one boolean property (e.g.
534-
``{"passes": {"type": "boolean"}}``). If the screening criteria need more than
535-
a yes/no answer (e.g. a three-way classification), use everyrow_agent instead.
536-
537-
Examples:
538-
- "Is this job posting remote-friendly AND senior-level AND salary disclosed?"
539-
- "Is this vendor financially stable AND does it have good security practices?"
540-
- "Is this lead likely to need our product based on company description?"
541-
542-
This function submits the task and returns immediately with a task_id and session_url.
543-
544-
Then immediately call everyrow_progress(task_id) to monitor.
545-
Once the task is completed, call everyrow_results to save the output.
546-
547-
Args:
548-
params: ScreenInput
549-
550-
Returns:
551-
Success message containing task_id for monitoring progress
552-
"""
553-
logger.info(
554-
"everyrow_screen: task=%.80s rows=%s",
555-
params.task,
556-
len(params.data) if params.data else "artifact",
557-
)
558-
log_client_info(ctx, "everyrow_screen")
559-
client = _get_client(ctx)
560-
561-
input_data = params._aid_or_dataframe
562-
563-
response_model: type[BaseModel] | None = None
564-
if params.response_schema:
565-
response_model = _schema_to_model("ScreenResult", params.response_schema)
566-
567-
async with create_session(
568-
client=client, session_id=params.session_id, name=params.session_name
569-
) as session:
570-
session_url = session.get_url()
571-
session_id_str = str(session.session_id)
572-
cohort_task = await screen_async(
573-
task=params.task,
574-
session=session,
575-
input=input_data,
576-
response_model=response_model,
577-
)
578-
task_id = str(cohort_task.task_id)
579-
total = len(input_data) if isinstance(input_data, pd.DataFrame) else 0
580-
581-
return await create_tool_response(
582-
task_id=task_id,
583-
session_url=session_url,
584-
label=f"Submitted: {total} rows for screening."
585-
if total
586-
else "Submitted: artifact for screening.",
587-
token=client.token,
588-
total=total,
589-
mcp_server_url=ctx.request_context.lifespan_context.mcp_server_url,
590-
session_id=session_id_str,
591-
)
592-
593-
594510
@mcp.tool(
595511
name="everyrow_dedupe",
596512
structured_output=False,
@@ -922,7 +838,7 @@ async def everyrow_upload_data(
922838
) -> list[TextContent]:
923839
"""Upload data from a URL or local file. Returns an artifact_id for use in processing tools.
924840
925-
Use this tool to ingest data before calling everyrow_agent, everyrow_screen,
841+
Use this tool to ingest data before calling everyrow_agent,
926842
everyrow_rank, everyrow_dedupe, everyrow_merge, everyrow_classify, or everyrow_forecast.
927843
928844
Supported sources:
@@ -1090,7 +1006,7 @@ async def everyrow_progress(
10901006
summaries: list[dict[str, Any]] | None = None
10911007
cursor: str | None = params.cursor
10921008

1093-
if not ts.is_terminal and not ts.is_screen:
1009+
if not ts.is_terminal:
10941010
if ts.completed > 0:
10951011
(
10961012
(partial_rows, rows_cursor),

everyrow-mcp/src/everyrow_mcp/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ def resolve_output_path(output_path: str, input_path: str, prefix: str) -> Path:
433433
Args:
434434
output_path: The output path (directory or full file path)
435435
input_path: The input file path (used to generate output filename)
436-
prefix: Prefix to add to the generated filename (e.g., 'screened', 'ranked')
436+
prefix: Prefix to add to the generated filename (e.g., 'classified', 'ranked')
437437
438438
Returns:
439439
Full path to the output file

0 commit comments

Comments
 (0)