Skip to content

RaulRC/spanish-grid-research-agent

Repository files navigation

spanish-grid-research-agent

A "deep research" agent for the Spanish electricity market. Ask it a question in plain language; it autonomously decides which Spanish grid data to fetch, calls the spanish-grid-mcp server over MCP, iterates as needed, and produces a written analysis with sources.

Streamlit UI

Two implementations live side by side in this repo:

  • agent.py — Hand-rolled Claude SDK loop (~150 lines). Deliberately framework-free, showing the raw tool-use pattern.
  • agent_pydantic.py — Built on Pydantic AI. Uses MCPToolset for MCP connectivity and stream_text for live output.
  • streamlit_app.py — Chat UI built on agent_pydantic.py. Renders tool calls, live text, and conversation history in the browser.

Examples of questions it's built for:

  • "Why were Spanish day-ahead prices high on 2026-05-20?"
  • "How did the wind generation collapse on 2025-11-12 affect prices?"
  • "Compare PVPC and wholesale prices for the last 30 days — when is PVPC most divergent?"

How it works

Your question
   │
   ├── agent.py (stdio MCP)
   │   └── spawns spanish-grid-mcp as subprocess → ESIOS / REE / AEMET
   │
   ├── agent_pydantic.py (stdio or HTTP MCP)
   │   ├── stdio: spawns spanish-grid-mcp as subprocess
   │   └── HTTP:  connects to spanish-grid-mcp at MCP_SERVER_URL
   │
   └── streamlit_app.py (chat UI → agent_pydantic.py)
       └── same transport options as agent_pydantic.py

The agentic part is the loop itself — Claude decides which tool to call next based on what it's learned so far. No hand-coded data-gathering pipeline.

All data comes from the spanish-grid-mcp server, which wraps ESIOS, REE apidatos, and AEMET OpenData behind an MCP interface.

Install

git clone https://github.com/raulrc/spanish-grid-research-agent.git
cd spanish-grid-research-agent
uv sync --extra ui     # Streamlit is optional — omit --extra ui for CLI-only

cp .env.example .env
# edit .env: add ANTHROPIC_API_KEY, ESIOS_TOKEN, AEMET_TOKEN

For the stdio path (agent.py or agent_pydantic.py without MCP_SERVER_URL), the spanish-grid-mcp package must be importable:

git clone https://github.com/raulrc/spanish-grid-mcp.git ../spanish-grid-mcp
uv pip install -e ../spanish-grid-mcp

For the HTTP path, you only need a running MCP server:

MCP_SERVER_URL=http://localhost:8000/mcp python agent_pydantic.py "..."

Run

# Hand-rolled loop (stdio only)
python agent.py "Why were Spanish day-ahead prices high on 2026-05-20?"

# Pydantic AI (stdio)
python agent_pydantic.py "Why were Spanish day-ahead prices high on 2026-05-20?"

# Pydantic AI (HTTP — MCP server running elsewhere)
MCP_SERVER_URL=http://spanish-grid-mcp:8000/mcp python agent_pydantic.py "..."

# Streamlit UI (stdio MCP — spawns subprocess automatically)
streamlit run streamlit_app.py

# Streamlit UI (HTTP MCP — server running elsewhere)
MCP_SERVER_URL=http://localhost:8000/mcp streamlit run streamlit_app.py

All three entry points stream tool calls live, then produce the analysis.

What's good about the code

agent.py — An explicit agent loop with no framework dependency (~150 lines). The while True + tool dispatch is the whole pattern. Uses prompt caching on the system prompt + tool definitions; after the first iteration each subsequent loop step reuses the cached prefix (~10% of full price). Uses adaptive thinking with summarized display — reasoning summaries stream live and each thinking step is cached individually.

agent_pydantic.py — A Pydantic AI implementation that demonstrates the framework's MCP integration, live event streaming, and usage tracking. Switches between stdio and Streamable HTTP based on the MCP_SERVER_URL env var. Uses MCPToolset (the recommended API replacing MCPServerStdio) and stream_text(delta=True) for live output.

streamlit_app.py — A chat UI that wraps run_agent() from agent_pydantic.py with conversation history, live text streaming, tool call log, and usage stats. Uses a background thread to bridge the async agent into Streamlit's sync event loop.

Configuration

Env var Default Notes
ANTHROPIC_API_KEY Required.
MCP_SERVER_URL HTTP endpoint for the MCP server (e.g. http://host:8000/mcp). If set, connects over Streamable HTTP instead of spawning a subprocess.
MCP_SERVER_CMD python -m spanish_grid_mcp.server Command that launches the MCP server subprocess (stdio mode only).
AGENT_MODEL claude-opus-4-7 Override to a cheaper model like claude-sonnet-4-6.
AGENT_MAX_STEPS 20 Hard ceiling on loop iterations (both agents).
AGENT_MAX_TOKENS 8192 Max output tokens per response (agent_pydantic.py only). Increase if using extended thinking with smaller models.
ESIOS_TOKEN, AEMET_TOKEN Forwarded to the MCP server subprocess.

The spanish-grid-mcp server also accepts --transport streamable-http to run as an HTTP server instead of stdio.

Status

The MCP server is wired to real data from ESIOS, REE apidatos, and AEMET OpenData. The agent can fetch actual prices, demand, generation mix, CO₂ intensity, and weather observations.

Known issues

  • get_cross_border_flows returns the demand envelope rather than actual interconnection flows — the REE per-border endpoint returns 500 errors.

Releases

No releases published

Packages

 
 
 

Contributors

Languages