mcp-stock-notion-ai
README.md
# mcp-stock-notion-ai
An [MCP](https://modelcontextprotocol.io) server that fetches stock market data,
stores it in **PostgreSQL** as the system of record, and pushes selected results
to **Notion**. Uses the **Streamable HTTP** transport and ships as a container
for **AWS ECS Fargate**.
```
Finnhub → Postgres (durable history, queryable) → Notion (a view you push to)
```
## Tools
| Tool | Description |
| --- | --- |
| `get_stock_quote(symbol)` | Current price, change, %, day high/low/open, prev close (live, not stored) |
| `get_company_profile(symbol)` | Company name, exchange, industry, market cap |
| `record_quote(symbol)` | Fetch the quote and **store it in Postgres** (the system of record) |
| `push_to_notion(symbol)` | Push the latest stored quote for a symbol **from Postgres to Notion** |
| `get_quote_history(symbol, limit)` | List recently recorded quotes from Postgres, newest first |
The MCP endpoint is served at `POST /mcp`. A `GET /health` endpoint is provided
for load-balancer health checks.
## Prerequisites
1. **Finnhub API key** — free at <https://finnhub.io>.
2. **Notion integration** — create one at
<https://www.notion.so/my-integrations>, copy the token.
3. **Notion database** with these properties (exact names/types):
| Property | Type |
| --- | --- |
| `Symbol` | Title |
| `Price` | Number |
| `Change` | Number |
| `Percent Change` | Number |
| `As Of` | Date |
Then **share the database with your integration** (••• → Connections) and
copy its database id from the URL.
## Configure
```bash
cp .env.example .env
# then fill in FINNHUB_API_KEY, NOTION_TOKEN, NOTION_DATABASE_ID
```
## Run locally
```bash
docker compose up -d # start local Postgres (port 5432)
pip install -e ".[dev]"
mcp-stock-notion # serves http://0.0.0.0:8000/mcp
```
The `quotes` table is created automatically on first use — no migration step
needed for local dev.
Test the health endpoint:
```bash
curl localhost:8000/health # {"status":"ok"}
```
Point an MCP client (e.g. Claude Desktop / Claude Code) at the Streamable HTTP
URL `http://localhost:8000/mcp`.
## Run the tests
```bash
pytest
```
## Docker
```bash
docker build -t mcp-stock-notion .
docker run --rm -p 8000:8000 --env-file .env mcp-stock-notion
```
## Deploy to AWS ECS Fargate (outline)
1. **Push image to ECR**
```bash
aws ecr create-repository --repository-name mcp-stock-notion
docker tag mcp-stock-notion:latest <acct>.dkr.ecr.<region>.amazonaws.com/mcp-stock-notion:latest
docker push <acct>.dkr.ecr.<region>.amazonaws.com/mcp-stock-notion:latest
```
2. **Store secrets** in AWS Secrets Manager (or SSM Parameter Store):
`FINNHUB_API_KEY`, `NOTION_TOKEN`, `NOTION_DATABASE_ID`. Reference them from
the task definition's `secrets` block so they're never baked into the image.
3. **Task definition**: container port `8000`, Fargate, inject the secrets above.
4. **Service**: behind an Application Load Balancer; target group health check
path `/health` (HTTP 200). Since MCP Streamable HTTP can hold sessions open,
enable ALB stickiness and set generous idle timeouts.
5. **TLS**: terminate HTTPS at the ALB (ACM cert) so remote clients connect to
`https://<your-domain>/mcp`.
## Layout
```
src/mcp_stock_notion/
server.py # FastMCP app, tool definitions, /health route
config.py # env-based settings (pydantic-settings)
stock.py # Finnhub provider (swappable)
notion.py # async Notion client
```
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessSyncing