# BridgeAble

**Turns any confusing website into an accessible one — an AI agent fills forms and navigates for
people with disabilities, while they see and approve every step.**

BridgeAble is a drop-in accessibility layer built on [WebMCP](https://github.com/webmachinelearning/webmcp),
the proposed web standard that lets a page expose structured, callable **tools** to AI agents instead
of forcing them to guess by scraping the DOM and simulating clicks. A site owner adds a small
JavaScript config object and one `<script>` tag; BridgeAble handles the rest — registering WebMCP
tools, running an accessible chat/voice interface, and keeping a human in the loop for every action.

> *The agent does the fine-motor work of clicking and typing. The human makes every decision.*

---

## What's in this repo

| File | Purpose |
|---|---|
| `portal.php` | The demo "host" site: a deliberately messy, realistic **Metro City Housing & Assistance Portal** (multi-step, unlabeled fields, tiny buttons) — representing *any* complex web app BridgeAble could be retrofitted onto. |
| `assets/portal.css` | Intentionally dated/low-contrast styling for the demo host site. |
| `assets/bridgeable-widget.js` | **The product.** Registers WebMCP tools (`document.modelContext.registerTool`) and renders the accessible chat/voice panel that drives them. |
| `agent_api.php` | JSON endpoint: forwards the chat conversation + tool schema + live form state to an LLM with function/tool calling enabled, returns the assistant's next message or tool calls. |
| `llm.php` | Thin cURL wrapper around any OpenAI-compatible Chat Completions API. |
| `config.example.php` / `.env.example` | Configuration templates. |
| `index.php` | Marketing/landing page linking to the demo. |

## How it works

1. **Adapter config.** `portal.php` declares `window.BridgeableConfig`, mapping semantic keys
   (`first_name`, `monthly_income`, `id_proof`, …) to real CSS selectors, labels, and step numbers
   on the page. This is the only site-specific integration work required.
2. **Tool registration.** `bridgeable-widget.js` defines a small set of tools — `fill_field`,
   `go_to_step`, `upload_document`, `explain_field`, `read_field_aloud`, `review_summary`,
   `request_submit`, `undo_last_change`, `get_application_state` — and registers each one with
   `document.modelContext.registerTool()` per the [WebMCP Imperative API](https://developer.chrome.com/docs/ai/webmcp/imperative-api),
   *and* mirrors them into a local registry.
3. **Accessible panel.** A floating launcher opens a high-contrast, large-text, keyboard- and
   voice-operable chat panel. Typed or spoken requests ("My name is Maria Gomez, I have two
   dependents...") are sent to `agent_api.php`, which asks an LLM (with the same tool schema) what
   to do.
4. **Local execution + live sync.** The browser — not the server — actually executes any tool
   calls the model returns, directly against the real page DOM. Fields visibly light up as they're
   filled, so the change is never a black box.
5. **Human-gated submission.** The `request_submit` tool never submits anything — it only opens a
   plain-language confirmation card. The actual submit action is wired **only** to a direct human
   click on "Confirm & Submit" inside the panel, not to anything the LLM can trigger on its own.
6. **Undo.** Every field edit and document upload is pushed onto an undo stack, reversible with one
   tap or voice command.

See **[DEPLOYMENT.md](DEPLOYMENT.md)** for full setup and testing instructions, including how to
test real browser-native WebMCP tool discovery (Chrome flag / origin trial + the Model Context Tool
Inspector extension) in addition to the built-in demo agent.

## Tech stack

| Layer | Technology |
|---|---|
| Host site & backend | Vanilla PHP 8.1+ (no frameworks), consistent with other projects in this repo |
| Accessibility layer | Vanilla JavaScript, [WebMCP](https://github.com/webmachinelearning/webmcp) (`document.modelContext`) |
| Voice | Web Speech API (`SpeechRecognition`, `speechSynthesis`) |
| LLM | Any OpenAI-compatible Chat Completions API with tool/function calling |

## Quick start

```bash
cp .env.example .env
cp config.example.php config.php
# edit .env and set LLM_API_KEY (and LLM_API_URL / LLM_MODEL if not using OpenAI)
php -S localhost:8080
```

Open `http://localhost:8080/portal.php`, click the round assistant button, and try:

> "I want to apply for housing assistance. My name is Maria Gomez, I have two dependents, and my
> income is $2,400 a month."

Without an `.env`/API key configured, the demo host page, WebMCP tool registration, and the manual
"Undo" / "Read back my info" quick-action buttons all still work — only natural-language chat
requires an LLM key.

## License

MIT.
