Skip to content

Commit c08477a

Browse files
committed
chore: create a utility to evaluate the mcp server implemenation, inspired by https://www.anthropic.com/engineering/writing-tools-for-agents
1 parent 5d9d16a commit c08477a

File tree

6 files changed

+2100
-7
lines changed

6 files changed

+2100
-7
lines changed

src/fenic/api/mcp/tool_generation.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,6 @@ def _auto_generate_read_tool(
224224
name_to_df: Dict[str, DataFrame] = {d.table_name: d.df for d in datasets}
225225

226226
async def _validate_columns(
227-
ctx: Context,
228227
available_columns: List[str],
229228
original_columns: List[str],
230229
filtered_columns: List[str],
@@ -233,10 +232,9 @@ async def _validate_columns(
233232
raise ValidationError(f"Column(s) {original_columns} not found. Available: {', '.join(available_columns)}")
234233
if len(filtered_columns) != len(original_columns):
235234
invalid_columns = [c for c in original_columns if c not in filtered_columns]
236-
await ctx.warning(f"Column(s) {invalid_columns} not found. Available: {', '.join(available_columns)}")
235+
raise ValidationError(f"Column(s) {invalid_columns} not found. Available: {', '.join(available_columns)}")
237236

238237
async def read_func(
239-
ctx: Context, # MCP server context allows us to log warnings back to the client.
240238
df_name: Annotated[str, "Dataset name to read rows from."],
241239
limit: Annotated[Optional[int], "Max rows to read within a page"] = result_limit,
242240
offset: Annotated[Optional[int], "Row offset to start from (requires order_by)"] = None,
@@ -258,11 +256,11 @@ async def read_func(
258256
exclude_columns = [c.strip() for c in exclude_columns.split(",") if c.strip()] if exclude_columns else None
259257
if include_columns:
260258
filtered_columns = [c for c in include_columns if c in available_columns]
261-
await _validate_columns(ctx, available_columns, include_columns, filtered_columns)
259+
await _validate_columns(available_columns, include_columns, filtered_columns)
262260
df = df.select(*filtered_columns)
263261
if exclude_columns:
264262
filtered_columns = [c for c in available_columns if c not in exclude_columns]
265-
await _validate_columns(ctx, available_columns, exclude_columns, filtered_columns)
263+
await _validate_columns(available_columns, exclude_columns, filtered_columns)
266264
df = df.select(*filtered_columns)
267265
# Apply paging (handles offset+order_by via SQL and optional limit)
268266
return _apply_paging(

src/fenic/core/mcp/types.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,15 @@ class ParameterizedToolDefinition:
8080
class DynamicToolDefinition:
8181
"""A tool implemented as a regular Python function with explicit parameters.
8282
83-
The function must be a `Callable[..., Coroutine[Any, Any, LogicalPlan]]`
83+
The function must be a `Callable[..., Coroutine[Any, Any, LogicalPlan]]`
8484
(a function defined with `async def`). Collection/formatting is handled by
8585
the MCP generator wrapper.
8686
"""
8787
name: str
8888
description: str
8989
max_result_limit: Optional[int]
9090
func: Callable[..., Coroutine[Any, Any, LogicalPlan]]
91-
add_limit_parameter: bool = True
91+
add_limit_parameter: bool = True
9292
default_table_format: TableFormat = "markdown"
9393
read_only: Annotated[bool, "A hint to provide to the client that the tool is read-only."] = True
9494
idempotent: Annotated[bool, "A hint to provide to the client that the tool is idempotent."] = True

0 commit comments

Comments
 (0)