research_create
Initiate a research task by providing instructions and selecting a model. Optionally specify a JSON schema to structure the output.
Instructions
Create a new research request using Exa.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| instructions | Yes | The research instructions describing what to research. | |
| model | No | The model to use ('exa-research-fast', 'exa-research', 'exa-research-pro'). | |
| output_schema | No | JSON schema for structured output format. |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- src/mcp_exa/_server.py:389-426 (handler)The `research_create` tool handler function. Decorated with @mcp.tool(), it accepts `instructions`, optional `model` (ResearchModel), and optional `output_schema` (JSONSchemaInput). It builds a request dict and calls the remote MCP tool 'exa_research_create' via `_call_mcp_tool()`, running the async call synchronously with `asyncio.get_event_loop().run_until_complete()`.
@mcp.tool() def research_create( instructions: str, model: ResearchModel | None = None, output_schema: JSONSchemaInput | None = None, ) -> dict[str, Any]: """Create a new research request using Exa. Args: instructions: The research instructions describing what to research. model: The model to use ('exa-research-fast', 'exa-research', 'exa-research-pro'). output_schema: JSON schema for structured output format. Returns: Dict containing the research task ID and initial status. Example: >>> research_create(instructions="What is the latest valuation of SpaceX?") {"research_id": "abc-123", "status": "running"} """ import asyncio if not instructions: raise ValueError("Instructions cannot be empty") arguments: dict[str, Any] = {"instructions": instructions} if model is not None: arguments["model"] = model if output_schema is not None: arguments["output_schema"] = output_schema try: result = asyncio.get_event_loop().run_until_complete( _call_mcp_tool("exa_research_create", arguments) ) return result except Exception as e: return {"error": str(e)} - src/mcp_exa/_server.py:26-26 (schema)Type alias `ResearchModel` defining the allowed model values for research_create: 'exa-research-fast', 'exa-research', 'exa-research-pro'.
ResearchModel = Literal["exa-research-fast", "exa-research", "exa-research-pro"] - src/mcp_exa/_server.py:27-27 (schema)Type alias `JSONSchemaInput` for the structured output schema parameter (a dict of string to Any).
JSONSchemaInput = dict[str, Any] - src/mcp_exa/_server.py:389-389 (registration)The `@mcp.tool()` decorator registers `research_create` as an MCP tool via the FastMCP framework.
@mcp.tool() - src/mcp_exa/_server.py:30-69 (helper)The `_call_mcp_tool` helper function that executes the actual JSON-RPC call to the Exa MCP server. It sends a 'tools/call' request with the tool name and arguments to the remote endpoint.
async def _call_mcp_tool(tool_name: str, arguments: dict[str, Any]) -> dict[str, Any]: """Call a tool on the public Exa MCP server.""" request = { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": tool_name, "arguments": arguments, }, } async with httpx.AsyncClient(timeout=60.0) as client: response = await client.post( f"{BASE_URL}/mcp", json=request, headers={ "accept": "application/json, text/event-stream", "content-type": "application/json", }, ) response.raise_for_status() response_text = response.text lines = response_text.split("\n") for line in lines: if line.startswith("data: "): data = line[6:] result = {"jsonrpc": "2.0", "id": 1, "result": {}} try: parsed = eval(data) except Exception: pass else: if "result" in parsed and parsed["result"].get("content"): return { "results": parsed["result"]["content"][0].get("text", "") } return {"results": ""}