Skip to main content
Glama
caioribeiro25

agro-market-agent

agro-market-agent

CI Python Ruff mypy License: MIT

Agente de IA multi-step que responde perguntas de inteligência de mercado agropecuário — "qual minha margem na soja hoje, com custo de R$95/saca?" — decidindo sozinho quais ferramentas chamar, em que ordem, e finalizando com um relatório. As ferramentas são expostas por um MCP server próprio (Model Context Protocol), reutilizável em qualquer cliente MCP.

Não é um wrapper de chatbot: é um agente instrumentado, testado e avaliado, construído com as preocupações de um sistema de produção.

O que este projeto demonstra

Área

Como

Agente sobre a API oficial

Loop de tool-use com o SDK da Anthropic — sem framework de orquestração, para deixar explícito o mecanismo.

MCP server próprio

5 tools tipadas (src/agro_market/server.py), reutilizáveis em qualquer cliente MCP (ex: Claude Desktop).

Avaliação rigorosa

tests/eval.py: precision/recall de seleção de tools + LLM-as-judge + detecção de regressão contra baseline.

Observabilidade

Tracing estruturado (spans JSON no stderr), contabilidade de tokens e custo por execução, RunTrace persistida em disco.

Type safety

Modelos Pydantic v2 em todas as fronteiras; mypy strict e ruff no CI.

Robustez

Guardrails de entrada, timeout global, limite de iterações; cliente HTTP com retry exponencial + cache TTL.

Testes sem custo

Anthropic e HTTP mockados (respx) — a suíte roda no CI sem API key e sem rede.

Fonte de dados plugável

Padrão adapter: mock (offline, default) ou yahoo (HTTP real), trocável por config.

Engenharia de projeto

pyproject.toml, layout src/, CI (GitHub Actions), pre-commit, Dockerfile, Makefile.

Related MCP server: leafengines-mcp-server

Arquitetura

  Usuário
    │  pergunta em linguagem natural
    ▼
  Agente (Claude + tool runner)  ── src/agro_market/agent.py
    │  guardrails · tracing · timeout · limite de iterações
    │  descobre e chama tools via MCP (stdio)
    ▼
  MCP Server  ── src/agro_market/server.py
    ├── list_commodities
    ├── get_commodity_price   → data_sources.py  (mock | yahoo, com retry+cache)
    ├── calculate_margin      → calculations.py   (lógica pura)
    ├── get_historical_trend  → db.py             (SQLite)
    └── generate_report       → markdown

Estrutura

src/agro_market/
├── agent.py          loop de orquestração (Claude + MCP)
├── server.py         MCP server (5 tools)
├── data_sources.py   adapter de preço: mock | Yahoo (httpx + tenacity + cache)
├── calculations.py   lógica de negócio pura
├── db.py             SQLite + histórico auto-semeado
├── domain.py         modelos Pydantic (contratos entre camadas)
├── observability.py  tracer, spans, custo, RunTrace
├── guardrails.py     validação de entrada
└── config.py         settings tipadas (pydantic-settings)
tests/
├── test_*.py         unit + integração (mockados, rodam no CI)
└── eval.py           avaliação end-to-end (LLM-as-judge, usa a API)

Quickstart

python -m venv .venv
.venv\Scripts\activate            # Windows (Linux/macOS: source .venv/bin/activate)
pip install -e ".[dev]"
copy .env.example .env             # e preencha ANTHROPIC_API_KEY

Rodar o agente:

python -m agro_market.agent "Qual minha margem na soja com custo de R$95/saca em 1000 sacas? Gere um relatório."

O agente busca o preço → calcula a margem → consulta a tendência → gera o relatório, e ao final reporta tools chamadas, tokens, custo e latência.

Qualidade (o que roda no CI, sem API key)

make check      # ruff + mypy strict + pytest (com cobertura)
# ou individualmente:
ruff check .
mypy
pytest          # 20 testes, ~86% de cobertura, sem rede

Avaliação (metodologia)

tests/eval.py roda cenários fixos e mede, por caso:

  • Seleção de tools — precision/recall contra o conjunto esperado.

  • Qualidade da resposta — LLM-as-judge dá nota 0..1 com justificativa (via structured output).

  • Custo e latência por execução.

Agrega as métricas e compara com um baseline (eval_baseline.json): se a nota média cair além do limiar, sinaliza regressão e falha. É o que separa "funcionou uma vez" de "não regrediu".

python tests/eval.py    # exige ANTHROPIC_API_KEY

Observabilidade

Cada execução emite spans estruturados (JSON no stderr, prontos para um coletor de logs) e persiste uma RunTrace completa em traces/ — pergunta, spans com duração, tools chamadas, tokens e custo estimado. Debugar uma run que deu errado é ler um JSON, não vasculhar prints.

Fontes de dados

  • AGRO_PRICE_SOURCE=mock (default) — determinística, offline.

  • AGRO_PRICE_SOURCE=yahoo — futuros via Yahoo Finance, com timeout, retry exponencial e cache TTL. Ponto de extensão para CEPEA/ESALQ isolado no adapter.

Configuração

Todas via ambiente (prefixo AGRO_) — ver .env.example. Principais: AGRO_MODEL, AGRO_PRICE_SOURCE, AGRO_MAX_TOOL_ITERATIONS, AGRO_AGENT_TIMEOUT_S.

MCP server em outro cliente

python -m agro_market.server        # processo stdio

Aponte a config MCP do cliente (ex: Claude Desktop) para esse comando.

Roadmap

  • Integração CEPEA/ESALQ real no adapter

  • Export de traces em formato OpenTelemetry

  • GIF de demonstração no README

Stack

Python · Anthropic API (tool use) · Model Context Protocol · Pydantic v2 · httpx · tenacity · SQLite · pytest · ruff · mypy · GitHub Actions

Available Tools

5 tools
calculate_marginA

Calcula receita, custo, lucro e margem de uma produção.

Args: price_per_unit: preço de venda por unidade (ex: R$/saca). cost_per_unit: custo de produção por unidade. quantity: quantidade de unidades produzidas.

ParametersJSON Schema
NameRequiredDescriptionDefault
quantityYes
cost_per_unitYes
price_per_unitYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, and the description does not disclose behavioral traits such as whether the tool is read-only or has side effects. As a calculation tool, it likely does not mutate state, but this is not stated.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise, with a clear main sentence followed by parameter explanations. Every sentence adds value, and the structure is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the presence of an output schema (not shown but indicated), the description adequately covers the tool's purpose and parameters. It is complete for a simple calculation tool, though it could mention return format or edge cases.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description includes a docstring explaining each parameter (price per unit, cost per unit, quantity) with examples (e.g., R$/saca), adding meaning beyond the schema's property titles. Since schema description coverage is 0%, this is valuable.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it calculates revenue, cost, profit, and margin for production, with a specific verb and resource. It distinguishes itself from sibling tools like list_commodities or get_commodity_price which are data retrieval, not calculation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for margin calculation but provides no explicit guidance on when to use this tool versus alternatives like generate_report. No exclusions or conditions are given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

generate_reportA

Monta um relatório em markdown a partir dos dados já apurados.

Use por último, depois de obter preço, margem e tendência.

ParametersJSON Schema
NameRequiredDescriptionDefault
unitYes
titleYes
profitYes
commodityYes
margin_pctYes
current_priceYes
trend_change_pctYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so description carries full burden. It implies a read-only aggregation tool with no side effects. Lacks explicit mention of output format but output schema exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short, front-loaded sentences with no wasted words. First sentence defines purpose, second gives usage guidance.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the number of required parameters and existence of output schema, the description provides sufficient context for the tool's role in a pipeline. Missing parameter descriptions are a minor gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema has 0% description coverage for 7 parameters. Description does not explain any parameter individually. Parameter names are somewhat self-explanatory but description should compensate given low coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it builds a markdown report from collected data, using the verb 'monta' and specifying the resource 'relatório em markdown'. It distinguishes from sibling tools which gather data.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says 'Use por último, depois de obter preço, margem e tendência', providing clear workflow ordering and when not to use the tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_commodity_priceA

Retorna o preço atual de uma commodity agrícola.

Args: commodity: nome da commodity (ex: "soja", "milho", "boi_gordo"). region: sigla/estado opcional (ex: "MT", "PR"). Vazio = média Brasil.

ParametersJSON Schema
NameRequiredDescriptionDefault
regionNo
commodityYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.7/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It only states the core behavior (returns current price) but does not disclose what happens on invalid parameters (e.g., unknown commodity, region), whether the price is real-time, or any side effects. Error behavior is unclear.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise, with two lines of purpose and an Args block. Every sentence serves a purpose. It could be slightly more structured (e.g., separate behavior from parameters), but it is not wasteful.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's low complexity (2 params, no nesting, output schema exists), the description covers the key aspects: what it does, parameter meanings, and optionality. It does not mention error handling or data freshness, but the output schema likely covers return format.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, but the description adds examples for commodity ('soja', 'milho', 'boi_gordo') and region ('MT', 'PR') and clarifies that empty region means national average. This adds significant meaning beyond the schema's type and default.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool returns the current price of an agricultural commodity. The verb 'Retorna' and resource 'preço atual de uma commodity agrícola' are specific. It distinguishes from siblings like list_commodities (listing) and calculate_margin (computation).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage when needing a current price, but does not explicitly state when to use it vs alternatives (e.g., for historical trends use get_historical_trend). No when-not-to-use guidance is provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_historical_trendB

Retorna a série histórica de preços e a variação percentual do período.

Args: commodity: nome da commodity. days: janela de dias a considerar (padrão 30).

ParametersJSON Schema
NameRequiredDescriptionDefault
daysNo
commodityYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

B3.3/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It only states the return type (historical series and percentage change) but does not mention whether the operation is read-only, any side effects, authentication requirements, rate limits, or data freshness. The description adds minimal behavioral context beyond the obvious.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise: one sentence stating the purpose, followed by a bullet-like listing of arguments. Every word earns its place; there is no filler. The main action is front-loaded, and the argument descriptions are compact.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 2 parameters, no annotations, and an output schema (unseen), the description covers the basic return but lacks details. It does not explain what 'historical series' entails (e.g., frequency, date range, format) or any constraints on 'days'. The description is adequate but leaves room for ambiguity about the exact output structure.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It explains 'commodity' as the name of the commodity and 'days' as the window of days with a default of 30. This adds value beyond the schema's type and default, but it does not specify valid commodity identifiers, allowed range for days, or format constraints. The description partially clarifies parameter meaning.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool returns historical price series and percentage change for a commodity. It uses a specific verb ('retorna') and resource ('série histórica de preços'), distinguishing it from sibling tools like get_commodity_price (current price) and list_commodities.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description does not provide any guidance on when to use this tool versus alternatives. It lacks explicit context like when to prefer historical data over current prices or how this tool differs from calculate_margin or generate_report. No exclusions or prerequisites are mentioned.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_commoditiesA

Lista as commodities suportadas e suas unidades de negociação.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It states the output (list of commodities and trading units) but does not detail behavior like idempotency or side effects. However, the read-only nature is obvious.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single sentence that is front-loaded and contains no unnecessary words. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is simple (no parameters, output schema exists). The description fully captures what the tool does, and given the context, no additional information is needed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

No parameters exist, so schema coverage is 100%. The description adds no parameter info, but none is needed. Baseline for 0 parameters is 4.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb ('Lista' = lists) and resource ('commodities suportadas e suas unidades de negociação'), and distinguishes from siblings like get_commodity_price or calculate_margin.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied: use this tool to get a list of supported commodities. No explicit when-to-use or when-not-to-use guidance, but the simplicity of the tool makes it straightforward.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

TDQS

A4/5.0
Disambiguation5/5

Each tool has a clearly distinct purpose: listing commodities, getting price, calculating margin, historical trend, and report generation. No overlap or ambiguity.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern in snake_case (e.g., list_commodities, get_commodity_price), making them predictable and easy to understand.

Tool Count5/5

With 5 tools, the server covers the entire agricultural market analysis workflow without being too sparse or overwhelming. Each tool earns its place.

Completeness5/5

The tool set provides a complete lifecycle: discovering commodities, fetching prices, calculating margins, viewing historical trends, and generating reports. No obvious gaps for the intended purpose.

Maintenance

ActivitySlowing
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    C
    maintenance
    An MCP server that provides real-time access to Brazilian agricultural data, including commodity prices, crop estimates, climate information, and deforestation rates. It integrates data from 19 public sources like CEPEA, CONAB, and IBGE to enable LLMs to analyze the Brazilian agribusiness sector.
    10
    26
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    EU Crop Intelligence MCP Server — Yield forecasts, weather analysis, and phenology models for 15 countries. AI agent-native, multi-source intelligence (NASA POWER, Eurostat, Open-Meteo).
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    An MCP server providing global soft-commodity data (cocoa, coffee, sugar, cotton, cashew) with per-call billing in USDC, offering tools for farmgate prices, ICE futures, CFTC COT positioning, and historical series.
    12
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/caioribeiro25/agro-market-agent'

If you have feedback or need assistance with the MCP directory API, please join our Discord server