Skip to main content
Glama
pintu544
by pintu544
README.md
# MarketPulse โ€” a Market Research skill for Alexa+

## ๐Ÿงญ 90-second judge tour

1. Open the live demo: https://web-production-331d9.up.railway.app/ โ€” tap the ring and say **"compare health beauty versus electronics"** โ†’ spoken answer + comparison card, tool call shown.
2. Say **"growth trends for watches gifts"** โ†’ live revenue chart rendered from the MCP tool's monthly data.
3. Say **"browse products"** โ†’ fictional catalog; **"add MP-001 to cart"** โ†’ cart card; **"checkout"** โ†’ simulated order confirmed with order ID. This is the agentic purchasing workflow, not Q&A.
4. Every answer shows which MCP tool served it (`/api/health` lists all 12 tools live on the Streamable HTTP endpoint).
5. See [FRICTION_LOG.md](FRICTION_LOG.md) for build friction and [docs/product-feedback.md](docs/product-feedback.md) for per-tool feedback.

## Track alignment (Devpost โ†’ implementation โ†’ evidence)

| Devpost requirement | How MarketPulse meets it | Evidence |
|---|---|---|
| Alexa+ track: MCP server or simulated Alexa+ experience | Self-hosted MCP server (spec 2025-11-25, Streamable HTTP) + simulated Alexa+ device host (voice in/out, display cards) | `src/marketpulse/server.py`, `web/` |
| Agentic, not a Q&A wrapper | Multi-turn purchasing workflow: browse โ†’ add to cart โ†’ checkout, with persistent cart state | `src/marketpulse/cart.py`, tools `browse_products`/`add_to_cart`/`view_cart`/`checkout` |
| Amazon developer tools | Amazon Bedrock (Nova Micro narration) + DynamoDB (cart state, SQLite fallback) | `src/marketpulse/llm_client.py`, `src/marketpulse/cart.py` |
| Public repo + license | MIT, public on GitHub | `LICENSE` |
| Demo video < 3 min | 48s, YouTube | Devpost submission |
| Product feedback | Per tool/API/SDK | `docs/product-feedback.md` |
| Friction log | Build friction, honest | `FRICTION_LOG.md` |

Built for the **Build, Ship, Shape: Amazon Developer Hackathon** (Alexa+ track + AWS Builder mini-challenge).

MarketPulse is a self-hosted **MCP server** (spec 2025-11-25, Streamable HTTP) that turns Alexa+ into a market research analyst. Ask it about e-commerce markets by voice โ€” *"Alexa, which categories are growing fastest?"* โ€” and it queries 100k+ real Brazilian e-commerce orders, reasons over them with an LLM, and answers in spoken-friendly language.

## How it works

```
Voice question โ†’ Alexa+ host โ†’ MCP tool (Streamable HTTP) โ†’ Olist data (SQLite)
                                                    โ†“
                                              LLM insight (Bedrock primary,
                                              OpenAI-compatible fallback)
```

**8 MCP tools:** `category_revenue` ยท `growth_trends` ยท `delivery_impact` ยท `review_insights` ยท `top_products` ยท `compare_categories` ยท `ask_analyst` ยท `generate_brief`

Every data tool returns live figures **plus a 1โ€“2 sentence spoken insight** generated by the LLM. `ask_analyst` answers free-form questions grounded in retrieved data; `generate_brief` writes a full market intelligence brief.

**AWS integration (AWS Builder mini-challenge):** all LLM reasoning goes through **Amazon Bedrock** first (Nova Micro on `us-east-1` via the Converse API), with an OpenAI-compatible fallback for resilience. Bedrock usage is documented in `docs/product-feedback.md`.

**Simulated Alexa+ experience:** the Alexa+ MCP Toolkit is partner-gated, so `web/` provides a simulated host โ€” a voice-style chat UI that calls the MCP server exactly like Alexa+ would, showing which tool served each answer.

## Quickstart

```bash
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt   # or: pip install -e .

# 1. Build the dataset (needs the public Olist CSVs from Kaggle: olistbr/brazilian-ecommerce)
python -m marketpulse.etl --dataset-dir /path/to/olist/csvs
# (a pre-built data/marketpulse.db is included, so this step is optional)

# 2. Configure
cp .env.example .env   # add AWS Bedrock creds and/or FastRouter key

# 3. Run the MCP server (Streamable HTTP on :8765/mcp)
python -m marketpulse.server

# 4. Run the simulated Alexa+ host (:8766)
uvicorn web.app:app --host 127.0.0.1 --port 8766
```

Test the MCP server directly:

```python
import asyncio
from mcp import Client

async def main():
    async with Client("http://127.0.0.1:8765/mcp") as client:
        print([t.name for t in (await client.list_tools()).tools])
        r = await client.call_tool("compare_categories",
            {"category_a": "health_beauty", "category_b": "electronics"})
        print(r.content[0].text[:500])

asyncio.run(main())
```

## Project layout

```
src/marketpulse/
  server.py         MCP server (MCPServer, Streamable HTTP, stateless)
  tools.py          8 tool implementations
  data.py           SQLite query layer over aggregated Olist data
  llm_client.py     Bedrock-primary / OpenAI-compatible-fallback LLM chain
  bedrock_client.py Bedrock Converse API wrapper
  etl.py            CSV โ†’ SQLite aggregation (raw CSVs not shipped)
web/
  app.py            simulated Alexa+ host (Starlette)
  index.html        voice-style chat UI
data/
  marketpulse.db    pre-aggregated Olist data (0.1 MB)
docs/
  friction-log.md   build friction log
  product-feedback.md  feedback on Amazon/AWS tools used
```

## Data

Olist Brazilian E-Commerce public dataset (Kaggle: `olistbr/brazilian-ecommerce`, CC-BY). Only aggregated tables are shipped (`data/marketpulse.db`); regenerate from raw CSVs with `python -m marketpulse.etl`.

## License

MIT โ€” see [LICENSE](LICENSE).