docs: add react-auth, react-openapi, vet sites; update standards registry and MCP setup

This commit is contained in:
2026-10-19 13:47:00 +05:30
parent a4f428b451
commit bd6fca43aa
258 changed files with 28653 additions and 51 deletions

View File

@@ -25,6 +25,8 @@ can read a library's full API by connecting to its MCP and reading
| Py JWT | `jwtlib` | JWT auth primitives (register/login/introspect) | password hashing + token code | `:8005` |
| Doc Forge | `docforge` | Docstring compiler → MkDocs + MCP docs | custom doc generators | `:8001` |
| Doc Weaver | `doc-weaver` | JSDoc compiler → TypeDoc + MCP docs (React/TS) | custom TypeScript doc generators | `:8010` |
| React Auth | `react-auth` | JWT-backed React auth UI: provider, login page, profile screens, bearer axios client | hand-rolled auth contexts and token handling in React apps | `:8011` |
| React OpenAPI | `react-openapi` | Spec-driven React admin UI (CRUD, tables, forms, SSE) derived from an OpenAPI document | per-resource hand-written admin screens | `:8012` |
| Auth Server | *(service)* | Central identity service (register/login/me/logout/introspect) | building auth endpoints yourself | spec: `docs://spec` |
## How to choose
@@ -40,6 +42,8 @@ can read a library's full API by connecting to its MCP and reading
| authenticate users / verify tokens | Py JWT (+ Auth Server) |
| generate documentation | Doc Forge |
| generate React/TypeScript documentation | Doc Weaver |
| authenticate a React front-end | React Auth (+ Auth Server) |
| build a React admin UI from an OpenAPI spec | React OpenAPI |
## Discovery
@@ -64,5 +68,9 @@ any infrastructure.
JSDoc comments and emits a TypeDoc site plus the same doc-forge-shaped MCP
bundle for React packages. Its convention is **RDFC** (the React Doc-forge
Convention), the JSDoc parallel to GSDFC.
- **React Auth** and **React OpenAPI** are front-end libraries (TypeScript,
React 18 + MUI + React Router peers), not Python services — they consume the
**Auth Server** and an OpenAPI document rather than serving one. Each ships
a wiki, a TypeDoc site and an MCP bundle like every other library above.
- Library MCP servers expose **documentation resources** (not executable tools):
they tell an agent the available API surface so it does not invent code.

View File

@@ -69,8 +69,9 @@ nav:
- Home: index.md
- Overview: 01_overview.md
- App Components: 02_components.md
- Start an App: 03_start_an_app.md
- MCP:
- Start an App: 03_start_an_app.md
- UI + API Reference: 06_ui_api_reference.md
- MCP:
- Setup: 05_mcp_setup.md
- Testing & Quality: 04_development/01_testing.md
- Releasing & Versioning: 04_development/02_releasing.md

View File

@@ -40,10 +40,14 @@ From the `docs` checkout:
| `mongo-ops` | `mongo_ops` | 8007 | `http://localhost:8007/mcp` | `https://mcp.aetoskia.com/mongo-ops/mcp` |
| `hexa` | `hexa` | 8008 | `http://localhost:8008/mcp` | `https://mcp.aetoskia.com/hexa/mcp` |
| `doc-weaver` | `doc-weaver` | 8010 | `http://localhost:8010/mcp` | `https://mcp.aetoskia.com/doc-weaver/mcp` |
| `react-auth` | `react-auth` | 8011 | `http://localhost:8011/mcp` | `https://mcp.aetoskia.com/react-auth/mcp` |
| `react-openapi` | `react-openapi` | 8012 | `http://localhost:8012/mcp` | `https://mcp.aetoskia.com/react-openapi/mcp` |
| `vet` | `vet` | 8013 | `http://localhost:8013/mcp` | `https://mcp.aetoskia.com/vet/mcp` |
The hosted endpoints are served over HTTPS at `https://mcp.aetoskia.com/<slug>/mcp`.
The tabs below are linked (`content.tabs.link`): switching one switches all of
them. Every snippet registers **all ten** servers, so a single paste is enough.
them. Every snippet registers **all thirteen** servers, so a single paste is
enough.
---
@@ -66,7 +70,10 @@ entry with a `url` but no `type` is read as a stdio server and skipped.
"dagpipe": { "type": "http", "url": "http://localhost:8006/mcp" },
"mongo-ops": { "type": "http", "url": "http://localhost:8007/mcp" },
"hexa": { "type": "http", "url": "http://localhost:8008/mcp" },
"doc-weaver": { "type": "http", "url": "http://localhost:8010/mcp" }
"doc-weaver": { "type": "http", "url": "http://localhost:8010/mcp" },
"react-auth": { "type": "http", "url": "http://localhost:8011/mcp" },
"react-openapi": { "type": "http", "url": "http://localhost:8012/mcp" },
"vet": { "type": "http", "url": "http://localhost:8013/mcp" }
}
}
```
@@ -85,7 +92,10 @@ entry with a `url` but no `type` is read as a stdio server and skipped.
"dagpipe": { "type": "http", "url": "https://mcp.aetoskia.com/dagpipe/mcp" },
"mongo-ops": { "type": "http", "url": "https://mcp.aetoskia.com/mongo-ops/mcp" },
"hexa": { "type": "http", "url": "https://mcp.aetoskia.com/hexa/mcp" },
"doc-weaver": { "type": "http", "url": "https://mcp.aetoskia.com/doc-weaver/mcp" }
"doc-weaver": { "type": "http", "url": "https://mcp.aetoskia.com/doc-weaver/mcp" },
"react-auth": { "type": "http", "url": "https://mcp.aetoskia.com/react-auth/mcp" },
"react-openapi": { "type": "http", "url": "https://mcp.aetoskia.com/react-openapi/mcp" },
"vet": { "type": "http", "url": "https://mcp.aetoskia.com/vet/mcp" }
}
}
```
@@ -131,6 +141,15 @@ Or add them with the CLI:
[mcp_servers.doc-weaver]
url = "http://localhost:8010/mcp"
[mcp_servers.react-auth]
url = "http://localhost:8011/mcp"
[mcp_servers.react-openapi]
url = "http://localhost:8012/mcp"
[mcp_servers.vet]
url = "http://localhost:8013/mcp"
```
=== "mcp.aetoskia.com"
@@ -165,6 +184,15 @@ Or add them with the CLI:
[mcp_servers.doc-weaver]
url = "https://mcp.aetoskia.com/doc-weaver/mcp"
[mcp_servers.react-auth]
url = "https://mcp.aetoskia.com/react-auth/mcp"
[mcp_servers.react-openapi]
url = "https://mcp.aetoskia.com/react-openapi/mcp"
[mcp_servers.vet]
url = "https://mcp.aetoskia.com/vet/mcp"
```
Or add them with the CLI:
@@ -192,7 +220,10 @@ Or add them with the CLI:
"dagpipe": { "serverUrl": "http://localhost:8006/mcp" },
"mongo-ops": { "serverUrl": "http://localhost:8007/mcp" },
"hexa": { "serverUrl": "http://localhost:8008/mcp" },
"doc-weaver": { "serverUrl": "http://localhost:8010/mcp" }
"doc-weaver": { "serverUrl": "http://localhost:8010/mcp" },
"react-auth": { "serverUrl": "http://localhost:8011/mcp" },
"react-openapi": { "serverUrl": "http://localhost:8012/mcp" },
"vet": { "serverUrl": "http://localhost:8013/mcp" }
}
}
```
@@ -211,7 +242,10 @@ Or add them with the CLI:
"dagpipe": { "serverUrl": "https://mcp.aetoskia.com/dagpipe/mcp" },
"mongo-ops": { "serverUrl": "https://mcp.aetoskia.com/mongo-ops/mcp" },
"hexa": { "serverUrl": "https://mcp.aetoskia.com/hexa/mcp" },
"doc-weaver": { "serverUrl": "https://mcp.aetoskia.com/doc-weaver/mcp" }
"doc-weaver": { "serverUrl": "https://mcp.aetoskia.com/doc-weaver/mcp" },
"react-auth": { "serverUrl": "https://mcp.aetoskia.com/react-auth/mcp" },
"react-openapi": { "serverUrl": "https://mcp.aetoskia.com/react-openapi/mcp" },
"vet": { "serverUrl": "https://mcp.aetoskia.com/vet/mcp" }
}
}
```
@@ -237,7 +271,10 @@ Or add them with the CLI:
"dagpipe": { "type": "remote", "url": "http://localhost:8006/mcp", "enabled": true },
"mongo-ops": { "type": "remote", "url": "http://localhost:8007/mcp", "enabled": true },
"hexa": { "type": "remote", "url": "http://localhost:8008/mcp", "enabled": true },
"doc-weaver": { "type": "remote", "url": "http://localhost:8010/mcp", "enabled": true }
"doc-weaver": { "type": "remote", "url": "http://localhost:8010/mcp", "enabled": true },
"react-auth": { "type": "remote", "url": "http://localhost:8011/mcp", "enabled": true },
"react-openapi": { "type": "remote", "url": "http://localhost:8012/mcp", "enabled": true },
"vet": { "type": "remote", "url": "http://localhost:8013/mcp", "enabled": true }
}
}
```
@@ -257,7 +294,10 @@ Or add them with the CLI:
"dagpipe": { "type": "remote", "url": "https://mcp.aetoskia.com/dagpipe/mcp", "enabled": true },
"mongo-ops": { "type": "remote", "url": "https://mcp.aetoskia.com/mongo-ops/mcp", "enabled": true },
"hexa": { "type": "remote", "url": "https://mcp.aetoskia.com/hexa/mcp", "enabled": true },
"doc-weaver": { "type": "remote", "url": "https://mcp.aetoskia.com/doc-weaver/mcp", "enabled": true }
"doc-weaver": { "type": "remote", "url": "https://mcp.aetoskia.com/doc-weaver/mcp", "enabled": true },
"react-auth": { "type": "remote", "url": "https://mcp.aetoskia.com/react-auth/mcp", "enabled": true },
"react-openapi": { "type": "remote", "url": "https://mcp.aetoskia.com/react-openapi/mcp", "enabled": true },
"vet": { "type": "remote", "url": "https://mcp.aetoskia.com/vet/mcp", "enabled": true }
}
}
```
@@ -287,7 +327,10 @@ Client Configuration → Copy HTTP Stream Config**.
"dagpipe": { "url": "http://localhost:8006/mcp" },
"mongo-ops": { "url": "http://localhost:8007/mcp" },
"hexa": { "url": "http://localhost:8008/mcp" },
"doc-weaver": { "url": "http://localhost:8010/mcp" }
"doc-weaver": { "url": "http://localhost:8010/mcp" },
"react-auth": { "url": "http://localhost:8011/mcp" },
"react-openapi": { "url": "http://localhost:8012/mcp" },
"vet": { "url": "http://localhost:8013/mcp" }
}
}
```
@@ -306,7 +349,10 @@ Client Configuration → Copy HTTP Stream Config**.
"dagpipe": { "url": "https://mcp.aetoskia.com/dagpipe/mcp" },
"mongo-ops": { "url": "https://mcp.aetoskia.com/mongo-ops/mcp" },
"hexa": { "url": "https://mcp.aetoskia.com/hexa/mcp" },
"doc-weaver": { "url": "https://mcp.aetoskia.com/doc-weaver/mcp" }
"doc-weaver": { "url": "https://mcp.aetoskia.com/doc-weaver/mcp" },
"react-auth": { "url": "https://mcp.aetoskia.com/react-auth/mcp" },
"react-openapi": { "url": "https://mcp.aetoskia.com/react-openapi/mcp" },
"vet": { "url": "https://mcp.aetoskia.com/vet/mcp" }
}
}
```

View File

@@ -0,0 +1,115 @@
# UI + API Reference
The vet application is the reference implementation of the **UI + API
pattern**: a spec-first backend (`react/vet/server`) paired with a
react-openapi frontend (`react/vet`) that renders itself directly from the
backend's OpenAPI document. Everything about the pairing — auth, persistence,
uploads, SSE — is driven from `openapi.yaml`.
---
## Architecture
```
react/vet/ # frontend (vite, react-openapi, react-auth)
src/
openapi-config.ts # reads VITE_API_BASE_URL + VITE_AUTH_BASE_URL
.env # VITE_API_BASE_URL=http://localhost:8020
react/vet/server/ # backend (OpenAPIFirstApp, port 8020)
openapi.yaml # single source of truth (24 operations)
domain/ # parents, vets, treatments, pets, appointments
infra/db/repos/ # IntIdMemoryRepository / IntIdMongoRepository
interfaces/ # one route module per resource + system (health)
```
The frontend's `specConfiguration` passes `specUrl` and `baseApiUrl` derived
from `VITE_API_BASE_URL`; `react-openapi` fetches `${base}/openapi.json` and
builds the admin UI from the `x-` extensions in the spec.
---
## Auth (bearer JWT)
`openapi.yaml` declares a single `bearerAuth` security scheme
(`type: http`, `bearerFormat: JWT`) with `x-server-url: "{AUTH_SERVER}"` and
`x-introspect-path: "/introspect"`. `openapi_first` resolves `{AUTH_SERVER}`
from the environment at app build time and generates a `Depends` that calls
the auth-server's `/introspect` endpoint per request. No hand-written auth
code exists in the backend.
The frontend uses `react-auth`'s `AuthProvider` and `AuthPage` gate; the API
client attaches `Authorization: Bearer <token>` via
`specConfiguration.getToken = () => tokenStore.get()`.
---
## Persistence (dual backend)
`REPO_BACKEND` selects the repository flavor:
| Value | Adapter | Notes |
| ------ | ---------------------------- | ------------------------------------------ |
| `memory` (default) | `IntIdMemoryRepository` | Process-local dict + counter; zero deps |
| `mongo` | `IntIdMongoRepository` | Motor via `MongoConnectionManager`; counter via `_counters` collection |
Both adapters expose the same duck-type (`create`, `get_by_id`, `get_many`,
`update`, `patch`, `delete`) consumed by the hexa-wired
`CrudsServiceAdaptor` services, so domain code and route handlers are
backend-agnostic. **Integer ids** are used end-to-end (the wire contract
declares `type: integer` primary keys); this is a documented deviation from
mongo-ops' default `ObjectId` allocation.
---
## Resource modelling
Every resource follows the same slice:
- `domain/<resource>/models.py` — plain pydantic models (`extra: "ignore"`)
- `domain/<resource>/ports/db.py` — `XDocument(X, BaseDocument)` + `create_x_repo()`
- `domain/<resource>/ports/service.py` — `XCrudsService(CrudsServiceAdaptor)` + `get_x_service(repo)`
- `interfaces/<resource>/routes.py` — handlers named after operationIds
Foreign keys are embedded objects on the wire (e.g. `Appointment.pet` is a
full `Pet`). Create/update handlers accept either a bare id or an expanded
object and normalize through `expand_ref` / `expand_ref_list` before
persisting. Unresolvable references return `422`.
---
## Non-CRUD surface
- **File upload** — `POST /pets/{id}/photo` (multipart) writes to
`UPLOADS_DIR` and stores the path on the pet document.
- **SSE** — `GET /pets/{id}/actions` returns `text/event-stream` with random
species-scoped behaviors (see `infra/adapters/actions_stream.py`).
- **Health** — `GET /health` is public (`security: []`) and used by the
Docker healthcheck.
---
## Running
```bash
cd react/vet/server
python -m venv .venv && .venv\Scripts\pip install -e .[dev]
AUTH_SERVER=https://auth.aetoskia.com REPO_BACKEND=memory .venv\Scripts\uvicorn main:app --port 8020
```
The frontend (`react/vet`) reads `VITE_API_BASE_URL` from `.env` and proxies
nothing — CORS is open (`allow_origins=["*"]`) in `main.py`.
---
## What the standards say
The backend follows the [Start an App](03_start_an_app.md) blueprint
(composition root, hexa wiring, `CrudsServiceAdaptor` services, spec-first
routing via `openapi_first`). The deviations are intentional and documented:
- **No worker/pipelines** — no background jobs for this app.
- **Integer-id repositories** — required by the wire contract; replaces the
ObjectId-based `mongo_ops.BaseRepository`.
- **Both persistence flavors** — memory (default, zero-dep) and Mongo
(production) selected via `REPO_BACKEND`.