diff --git a/README.md b/README.md index e9f478dc..1684d856 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,8 @@
- Your LLM doesn't know what the user is looking at. Fix that in two lines.
- One attribute. Real-time UI context. Works with every LLM SDK and MCP client.
+ Give your LLM eyes. One attribute for humans, one protocol for agents.
+ data-askable turns what the user is looking at into structured, real-time context — for every LLM SDK and every MCP client.
@@ -35,6 +35,7 @@
MCP ·
How it works ·
Capture modes ·
+ Protocol ·
Packages ·
Docs ·
Live Demo
@@ -129,38 +130,37 @@ React + Vite + CopilotKit, wired up and ready to go.
## MCP — Claude Desktop, Cursor, and any MCP client
-Expose your app's live UI context as an MCP server. Any agent that connects can ask what the user currently sees.
+**Give Claude eyes into your running app in one command.** If your app exposes its current context at an endpoint (one `GET` route returning `ctx.toContextPacket()`), the bundled `askable-mcp` binary serves it to any MCP client over stdio — no server framework, no extra dependencies:
-```bash
-npm install @askable-ui/mcp
+```json
+// claude_desktop_config.json
+{
+ "mcpServers": {
+ "my-app": {
+ "command": "npx",
+ "args": ["-y", "@askable-ui/mcp", "--url", "http://localhost:3001/context"]
+ }
+ }
+}
```
+Claude Desktop and Cursor can now call `get_current_context`, `format_context_for_prompt`, and `list_context_sources`, or read the live `askable://current` resource — they see exactly what your user sees, without screenshots or manual description. Add `--require-redacted` to refuse serving unredacted packets.
+
+Prefer embedding? The same server runs in-process:
+
```ts
import { createAskableMcpServer, createAskableMcpContextProvider } from '@askable-ui/mcp';
+import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
const server = createAskableMcpServer({
provider: createAskableMcpContextProvider(ctx),
});
-
-server.connect(transport);
-```
-
-Add to `claude_desktop_config.json`:
-
-```json
-{
- "mcpServers": {
- "my-app": {
- "command": "node",
- "args": ["path/to/your/mcp-server.js"]
- }
- }
-}
+await server.connect(new StdioServerTransport());
```
-Claude Desktop can now call `get_current_context` and `format_context_for_prompt` — it sees exactly what your user sees, without screenshots or manual description.
+There's also a fetch-compatible HTTP handler (`createAskableMcpWebHandler`) for remote WebMCP endpoints, and a browser-local page bridge for extensions.
-→ **[MCP integration guide](https://askable-ui.com/docs/api/mcp)**
+→ **[MCP integration guide](https://askable-ui.com/docs/guide/mcp)**
---
@@ -247,7 +247,7 @@ const { visibleItems, promptContext } = useAskableViewport({ threshold: 0.5 });
// promptContext → "Visible UI elements:\n- {"metric":"revenue","value":"$2.3M"} ..."
```
-Available in React, Vue, and Svelte (both Svelte 4 and 5).
+Available in React, Vue, Svelte (both 4 and 5), SolidJS, and Angular.
### Navigation history
@@ -260,7 +260,7 @@ const { history, promptContext } = useAskableHistory({ maxEntries: 5 });
// promptContext → "User navigation trail (most recent first):\n→ {"metric":"churn"}..."
```
-Deduplicates consecutive identical entries by default. Available in React, Vue, and Svelte.
+Deduplicates consecutive identical entries by default. Available in React, Vue, Svelte, SolidJS, Angular, and Qwik.
### Composing context streams
@@ -461,6 +461,27 @@ All sources are also available from the main entry point — the split is about
---
+## An open protocol, not just a library
+
+Everything above serializes to one versioned wire format: the **Context Packet** (`askable.context/0.1`). It's a small JSON envelope that carries what was captured, how, and — first-class — whether it was redacted and under what consent:
+
+```json
+{
+ "protocol": "askable.context",
+ "version": "0.1",
+ "capture": { "mode": "lasso", "intent": "explain the highlighted region" },
+ "target": { "text": "NRR 118%", "metadata": { "metric": "net revenue retention" } },
+ "privacy": { "redacted": true, "consent": "explicit" },
+ "provenance": { "producer": "askable-ui", "method": "app" }
+}
+```
+
+The format lives in [`@askable-ui/context`](https://www.npmjs.com/package/@askable-ui/context) — a dependency-free package with the types, the JSON Schema, and a runtime guard. askable-ui is the reference implementation; any producer (app, extension, native client) and any consumer (prompt builder, MCP client, agent runtime) can speak it.
+
+→ **[Read the spec](https://askable-ui.com/docs/guide/protocol)**
+
+---
+
## Works with
**LLM SDKs**
@@ -483,7 +504,7 @@ All sources are also available from the main entry point — the split is about
| Svelte 4 & 5 | `@askable-ui/svelte` | `createAskableStore()`, `useAskableAgent()`, `useAskableStream()`, `useAskableChat()`, `useAskableKeyboardShortcut()`, `useAskablePageSource()`, `useAskableFormSource()`, `useAskableTableSource()`, `useAskableErrorSource()`, `useAskableUserSource()`, `useAskableNavigationSource()`, `useAskableDOMSource()`, `useAskableStorageSource()`, `useAskableCartSource()`, `useAskableMultistepSource()`, `useAskableScrollSource()`, `useAskableThemeSource()`, `useAskableWindowSource()`, `useAskableLocaleSource()`, `useAskableNetworkSource()`, `useAskableTimeSource()`, `useAskableFocusSource()`, `useAskableTabSource()`, `useAskablePerformanceSource()`, `useAskableBatterySource()`, `useAskableGeolocationSource()`, `useAskableViewport()`, `useAskableHistory()`, `