Source code for tavily_fastmcp.tools.research
"""Research tool registration.
Purpose:
Register the namespaced Tavily research MCP tool.
Design:
- Keep long-form research creation separate from retrieval.
- Convert flat MCP arguments into the canonical request model.
"""
from __future__ import annotations
from typing import Annotated, Any, cast
from pydantic import Field
from tavily_fastmcp._typing import ToolRegistrar
from tavily_fastmcp.models import ResearchRequest, ResearchResponse
from tavily_fastmcp.service import TavilyServiceProtocol
[docs]
def register_research_tool(mcp: Any, *, backend: TavilyServiceProtocol) -> None:
"""Register the ``tavily.research`` MCP tool.
Args:
mcp: FastMCP server instance.
backend: Tavily service backend.
Returns:
``None``.
"""
tool_server = cast(ToolRegistrar, mcp)
@tool_server.tool(
name="tavily.research",
title="Tavily Research",
description="Create a deep multi-source Tavily research task.",
tags={"research", "report", "readonly"},
annotations={
"title": "Tavily Research",
"readOnlyHint": True,
"openWorldHint": True,
"idempotentHint": False,
},
meta={"profile_hints": ["deep-research"]},
)
async def tavily_research(
input: Annotated[str, Field(description="Research task or question.")],
model: Annotated[str, Field(description="Research model.")] = "auto",
citation_format: Annotated[str, Field(description="Citation format.")] = "numbered",
stream: Annotated[bool, Field(description="Whether Tavily should stream results.")] = False,
output_schema: Annotated[
dict[str, Any] | None, Field(description="Optional JSON schema for structured output.")
] = None,
ctx: Any | None = None,
) -> ResearchResponse:
"""Create a Tavily research task.
Args:
input: Research task or question.
model: Tavily research model.
citation_format: Citation format.
stream: Whether Tavily should stream.
output_schema: Optional JSON schema for structured output.
ctx: Optional FastMCP context.
Returns:
A normalized Tavily research response.
"""
request = ResearchRequest.model_validate(
{
"input": input,
"model": model,
"citation_format": citation_format,
"stream": stream,
"output_schema": output_schema,
}
)
if ctx is not None:
await ctx.info(f"Starting research task with model={model}.")
return backend.research_from_model(request)