Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
venv
.venv
.venv-*
node_modules
app/frontend/node_modules
.git
.gitignore
docs
data
tests
*.pyc
__pycache__
dist
build
*.log
80 changes: 43 additions & 37 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -1,51 +1,57 @@
# Adding new data

New files should be added to the `data` folder, and then either run scripts/prepdocs.sh or scripts/prepdocs.ps1 to ingest the data.
# Copilot & AI Agent Instructions for This Codebase

# Adding a new azd environment variable
This project is a RAG (Retrieval-Augmented Generation) chat app using Azure OpenAI and Azure AI Search, with a Python (Quart) backend and a React (Vite/TypeScript) frontend. It is designed for rapid iteration, Azure deployment, and extensibility. These instructions guide AI coding agents to be productive and follow project conventions.

An azd environment variable is stored by the azd CLI for each environment. It is passed to the "azd up" command and can configure both provisioning options and application settings.
When adding new azd environment variables, update:
## Architecture Overview

1. infra/main.parameters.json : Add the new parameter with a Bicep-friendly variable name and map to the new environment variable
1. infra/main.bicep: Add the new Bicep parameter at the top, and add it to the `appEnvVariables` object
1. azure.yaml: Add the new environment variable under pipeline config section
1. .azdo/pipelines/azure-dev.yml: Add the new environment variable under `env` section
1. .github/workflows/azure-dev.yml: Add the new environment variable under `env` section
- **Backend**: `app/backend` (Quart, Python)
- `approaches/`: Pluggable RAG strategies (e.g., `retrievethenread.py`, `chatreadretrieveread.py`)
- `app.py`: Main entry point
- **Frontend**: `app/frontend` (React, Vite, TypeScript)
- `src/api/`: API client
- `src/components/`: UI components
- `src/locales/`: i18n translations (edit all languages for new UI strings)
- **Infra**: `infra/` (Bicep templates, `azure.yaml`)
- **Data**: `data/` (documents for ingestion)
- **Tests**: `tests/` (pytest, Playwright e2e)

# Adding a new setting to "Developer Settings" in RAG app
See `docs/architecture.md` for diagrams and data flow.

When adding a new developer setting, update:
## Key Workflows

* frontend:
* app/frontend/src/api/models.ts : Add to ChatAppRequestOverrides
* app/frontend/src/components/Settings.tsx : Add a UI element for the setting
* app/frontend/src/locales/*/translations.json: Add a translation for the setting label/tooltip for all languages
* app/frontend/src/pages/chat/Chat.tsx: Add the setting to the component, pass it to Settings
* app/frontend/src/pages/ask/Ask.tsx: Add the setting to the component, pass it to Settings
- **Local Dev**: Use VS Code Dev Containers or Codespaces for pre-configured environments. See `docs/localdev.md` for hot reloading, debug, and task usage.
- Start dev servers: Use the VS Code "Development" task or run `app/start.sh` (runs both frontend and backend with hot reload).
- **Azure Deployment**: Use `azd up` to provision infra and deploy code. Use `azd deploy` to redeploy code only. See `README.md` and `docs/azd.md`.
- **Data Ingestion**: Add files to `data/`, then run `scripts/prepdocs.sh` to ingest.
- **Testing**: All tests in `tests/` (pytest). E2E tests in `e2e.py` (Playwright, mocks backend). Activate `.venv` before running tests.

* backend:
* app/backend/approaches/chatreadretrieveread.py : Retrieve from overrides parameter
* app/backend/approaches/retrievethenread.py : Retrieve from overrides parameter
* app/backend/app.py: Some settings may need to be sent down in the /config route.
## Project-Specific Conventions

# When adding tests for a new feature:
- **Adding azd env vars**: Update all of:
1. `infra/main.parameters.json` (add param)
2. `infra/main.bicep` (add param, wire to `appEnvVariables`)
3. `azure.yaml` (pipeline config)
4. `.azdo/pipelines/azure-dev.yml` and `.github/workflows/azure-dev.yml` (env section)
- **Adding Developer Settings**:
- Frontend: Update `src/api/models.ts`, `components/Settings.tsx`, all `locales/*/translation.json`, and pass through `pages/chat/Chat.tsx` and `pages/ask/Ask.tsx`.
- Backend: Update `approaches/chatreadretrieveread.py`, `approaches/retrievethenread.py`, and `app.py` as needed.
- **Tests**: Add e2e for UI, integration for API, unit for functions. Use `conftest.py` for mocks.
- **Pull Requests**: Follow `PULL_REQUEST_TEMPLATE.md`.

All tests are in the `tests` folder and use the pytest framework.
There are three styles of tests:
## Integration & Patterns

* e2e tests: These use playwright to run the app in a browser and test the UI end-to-end. They are in e2e.py and they mock the backend using the snapshots from the app tests.
* app integration tests: Mostly in test_app.py, these test the app's API endpoints and use mocks for services like Azure OpenAI and Azure Search.
* unit tests: The rest of the tests are unit tests that test individual functions and methods. They are in test_*.py files.
- **Backend/Frontend API**: REST endpoints defined in backend, consumed via `src/api/`.
- **RAG Approaches**: Add new strategies in `app/backend/approaches/` and register in `app.py`.
- **Internationalization**: All UI strings must be added to every language in `src/locales/`.
- **Infra**: All infra changes must be reflected in both Bicep and pipeline config files.

When adding a new feature, add tests for it in the appropriate file.
If the feature is a UI element, add an e2e test for it.
If it is an API endpoint, add an app integration test for it.
If it is a function or method, add a unit test for it.
Use mocks from conftest.py to mock external services.
## References

When you're running tests, make sure you activate the .venv virtual environment first:
- [README.md](../README.md) — Quickstart, deployment, and dev environment
- [docs/architecture.md](../docs/architecture.md) — Architecture diagrams and explanation
- [docs/localdev.md](../docs/localdev.md) — Local dev, debugging, and tasks

```bash
source .venv/bin/activate
```
> **Nota:** Mantenha os links de referência acima atualizados conforme a estrutura do projeto. Se mover arquivos como AGENTS.md, ajuste o caminho aqui.

Keep this file up to date with any changes to workflows or conventions.
3 changes: 2 additions & 1 deletion .vscode/extensions.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"ms-azuretools.vscode-bicep",
"ms-python.python",
"esbenp.prettier-vscode",
"DavidAnson.vscode-markdownlint"
"DavidAnson.vscode-markdownlint",
"github.copilot-chat"
]
}
105 changes: 54 additions & 51 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -1,53 +1,56 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Backend (Python)",
"type": "debugpy",
"request": "launch",
"module": "quart",
"cwd": "${workspaceFolder}/app/backend",
"python": "${workspaceFolder}/.venv/bin/python",
"env": {
"QUART_APP": "main:app",
"QUART_ENV": "development",
"QUART_DEBUG": "0",
// Set this to "no-override" if you want env vars here to override AZD env vars
"LOADING_MODE_FOR_AZD_ENV_VARS": "override"
},
"args": [
"run",
"--no-reload",
"-p 50505"
],
"console": "integratedTerminal",
"justMyCode": false
},
{
"name": "Frontend",
"type": "node-terminal",
"request": "launch",
"command": "npm run dev",
"cwd": "${workspaceFolder}/app/frontend",
},
{
"name": "Tests (Python)",
"type": "debugpy",
"request": "launch",
"program": "${file}",
"purpose": ["debug-test"],
"console": "integratedTerminal",
"justMyCode": false
}
],
"compounds": [
{
"name": "Frontend & Backend",
"configurations": ["Backend (Python)", "Frontend"],
"stopAll": true
}
]
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python Debugger: Current File",
"type": "debugpy",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal"
},
{
"name": "Backend (Python)",
"type": "debugpy",
"request": "launch",
"module": "quart",
"cwd": "${workspaceFolder}/app/backend",
"python": "${workspaceFolder}/.venv/bin/python",
"env": {
"QUART_APP": "main:app",
"QUART_ENV": "development",
"QUART_DEBUG": "0",
// Set this to "no-override" if you want env vars here to override AZD env vars
"LOADING_MODE_FOR_AZD_ENV_VARS": "override"
},
"args": ["run", "--no-reload", "-p 50505"],
"console": "integratedTerminal",
"justMyCode": false
},
{
"name": "Frontend",
"type": "node-terminal",
"request": "launch",
"command": "npm run dev",
"cwd": "${workspaceFolder}/app/frontend"
},
{
"name": "Tests (Python)",
"type": "debugpy",
"request": "launch",
"program": "${file}",
"purpose": ["debug-test"],
"console": "integratedTerminal",
"justMyCode": false
}
],
"compounds": [
{
"name": "Frontend & Backend",
"configurations": ["Backend (Python)", "Frontend"],
"stopAll": true
}
]
}
30 changes: 30 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
FROM python:3.11-slim

ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1

WORKDIR /app

# install system deps
RUN apt-get update \
&& apt-get install -y --no-install-recommends curl build-essential gcc libpq-dev \
&& rm -rf /var/lib/apt/lists/*

# copy only what's needed for the backend
COPY app/backend/ ./backend/
COPY pyproject.toml ./
COPY requirements-dev.txt ./

WORKDIR /app/backend

# install python deps
RUN python -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
RUN pip install --upgrade pip setuptools wheel
RUN if [ -f requirements.txt ]; then pip install --no-cache-dir -r requirements.txt; fi

EXPOSE 50505

ENV PORT=50505

CMD ["python", "-m", "quart", "--app", "main:app", "run", "--host", "0.0.0.0", "--port", "50505"]
65 changes: 65 additions & 0 deletions docs/run-mcp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Run the MCP (backend) server

This document explains how to run only the backend (MCP/SSE) server locally or inside Docker. The backend exposes the SSE endpoint `/chat/stream` which can be used by an external connector.

Prerequisites
- Python 3.10+ (for local run)
- Docker (optional)
- cloudflared (optional) to create a public tunnel

## Option A — Run locally (recommended)

From the repository root:

```bash
./run_mcp.sh 50505
```

This will:
- create `.venv` if not present
- install backend requirements from `app/backend/requirements.txt`
- start the Quart backend on `0.0.0.0:50505`

Test endpoints:

```bash
curl http://localhost:50505/config
```

SSE endpoint (use this for connectors):

```
http://localhost:50505/chat/stream
```

## Option B — Run with Docker

Build image:

```bash
docker build -t azure-search-mcp .
```

Run container:

```bash
docker run -d --name azure-search-mcp -p 50505:50505 azure-search-mcp
```

Then the same endpoints are available on the host.

## Expose a public HTTPS tunnel (Cloudflare Tunnel)

Install `cloudflared` and run:

```bash
cloudflared tunnel --url http://localhost:50505
```

The command prints a public URL like `https://xxxx.trycloudflare.com`. Use the SSE path when registering the connector:

```
https://xxxx.trycloudflare.com/chat/stream
```

Note: if your connector expects a different path (e.g., `/sse`), create a small proxy or add a redirect handler in `app/backend/app.py`.
25 changes: 25 additions & 0 deletions run_mcp.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/usr/bin/env bash
set -euo pipefail

# Lightweight runner for the MCP backend (Quart)
# Usage: ./run_mcp.sh [port]

ROOT_DIR="$(cd "$(dirname "$0")" && pwd)"
VENV_DIR="$ROOT_DIR/.venv"
PORT=${1:-50505}

if [ ! -d "$VENV_DIR" ]; then
echo "Creating virtualenv at $VENV_DIR"
python3 -m venv "$VENV_DIR"
fi

source "$VENV_DIR/bin/activate"
pip install --upgrade pip

if [ -f "$ROOT_DIR/app/backend/requirements.txt" ]; then
pip install -r "$ROOT_DIR/app/backend/requirements.txt"
fi

cd "$ROOT_DIR/app/backend"
echo "Starting Quart backend on 0.0.0.0:$PORT"
exec "$VENV_DIR/bin/python" -m quart --app main:app run --host 0.0.0.0 --port "$PORT" --reload