From e335961d95eb9d39010ff3e4861c83638a202daa Mon Sep 17 00:00:00 2001 From: AE Date: Wed, 12 Aug 2026 11:29:15 -0700 Subject: [PATCH 1/4] docs: clarify ContextForge startup step is a separate repo/command The step didn't name a command, which read as if this repo had its own way to bring ContextForge up. Name make dev and its default port, and say explicitly it's a separate clone. Signed-off-by: Anna Effort --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3175a7f..1e318fc 100644 --- a/README.md +++ b/README.md @@ -41,10 +41,12 @@ The app is split into three pieces that all must run for local dev: Bring them up in this order: -1. **Start ContextForge** — the upstream `mcp-context-forge` repo. Follow - its own quick-start guide: +1. **Start ContextForge** (terminal A, a separate clone of the upstream + `mcp-context-forge` repo — it is not part of this repo). Follow its own + quick-start guide: https://github.com/IBM/mcp-context-forge/issues/2503 - Note whatever port it ends up listening on for the next step. + In that repo, `make dev` boots it on `:8000` by default. Note whatever + port it ends up listening on for the next step. 2. **Configure and start the BFF** (terminal B, this repo's `server/`): From 618d4d7aa499bfc3f032312f5cbc849f69771366 Mon Sep 17 00:00:00 2001 From: AE Date: Wed, 12 Aug 2026 11:56:52 -0700 Subject: [PATCH 2/4] docs: clarify FASTAPI_URL default vs make dev port .env.example's 4444 default matches ContextForge's production make serve default, not make dev's :8000 - following the doc literally against a make dev instance pointed the BFF at the wrong port. Signed-off-by: Anna Effort --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1e318fc..081ba37 100644 --- a/README.md +++ b/README.md @@ -57,8 +57,10 @@ Bring them up in this order: Edit `server/.env`: - `FASTAPI_URL` — point it at whatever host:port ContextForge is - listening on from step 1 (`.env.example`'s default is `4444`; confirm - against your ContextForge run rather than assuming). + listening on from step 1. `.env.example`'s default (`4444`) is + ContextForge's own **production** default (`make serve`); `make dev` + (the usual path for local dev) listens on `:8000` instead — confirm + against your actual run rather than assuming either. - `COOKIE_SECURE=false` — needed for local HTTP; the default (`true`) is for prod and silently drops the session cookie over plain HTTP. From 2ac7dd03602b3e361b6041433caac1541cba4b23 Mon Sep 17 00:00:00 2001 From: AE Date: Wed, 12 Aug 2026 12:07:57 -0700 Subject: [PATCH 3/4] docs: disambiguate mcp-context-forge from contextforge-web-ui The repo names are similar enough that shorthand like "ContextForge" and "this repo" was ambiguous about which project was meant. Spell out mcp-context-forge and contextforge-web-ui explicitly throughout. Signed-off-by: Anna Effort --- README.md | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 081ba37..878c4b6 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -# ContextForge UI Client +# ContextForge Web UI Client -React-based admin UI for ContextForge MCP Gateway. +React-based user interface for mcp-context-forge. -This UI targets **ContextForge API v1.0.7**, matching [`openapi.json`](./openapi.json) committed at repo root. +This UI targets **mcp-context-forge API v1.0.7**, matching [`openapi.json`](./openapi.json) committed at repo root. ## Tech Stack @@ -29,26 +29,26 @@ npm install The app is split into three pieces that all must run for local dev: -- **ContextForge** (`mcpgateway`) — the upstream FastAPI gateway. It owns +- **mcp-context-forge** — the upstream FastAPI gateway. It owns auth and all business data. - **BFF** (`server/`) — a Fastify app that sits between the browser and - ContextForge. It holds the session cookie/CSRF boundary and keeps the + mcp-context-forge. It holds the session cookie/CSRF boundary and keeps the API's JWT off the browser (`server/src/index.ts`). The browser only ever - talks to the BFF, never directly to ContextForge. + talks to the BFF, never directly to mcp-context-forge. - **Client** (`src/`) — this React SPA, served as static files by the BFF (same-origin — the API client always calls relative paths, see `src/api/client.ts`). Bring them up in this order: -1. **Start ContextForge** (terminal A, a separate clone of the upstream - `mcp-context-forge` repo — it is not part of this repo). Follow its own - quick-start guide: +1. **Start mcp-context-forge** (terminal A, a separate clone of the + `mcp-context-forge` repo — it is not part of contextforge-web-ui). Follow + its own quick-start guide: https://github.com/IBM/mcp-context-forge/issues/2503 In that repo, `make dev` boots it on `:8000` by default. Note whatever port it ends up listening on for the next step. -2. **Configure and start the BFF** (terminal B, this repo's `server/`): +2. **Configure and start the BFF** (terminal B, contextforge-web-ui's `server/`): ```bash cd server @@ -56,9 +56,9 @@ Bring them up in this order: ``` Edit `server/.env`: - - `FASTAPI_URL` — point it at whatever host:port ContextForge is + - `FASTAPI_URL` — point it at whatever host:port mcp-context-forge is listening on from step 1. `.env.example`'s default (`4444`) is - ContextForge's own **production** default (`make serve`); `make dev` + mcp-context-forge's own **production** default (`make serve`); `make dev` (the usual path for local dev) listens on `:8000` instead — confirm against your actual run rather than assuming either. - `COOKIE_SECURE=false` — needed for local HTTP; the default (`true`) is @@ -89,22 +89,22 @@ Bring them up in this order: 4. **Use it.** Visit `http://localhost:3000/` — redirects to `/app/login` (unauthed) or `/app/` (authed). The login form posts through the BFF, - which holds the ContextForge JWT server-side and hands the browser only + which holds the mcp-context-forge JWT server-side and hands the browser only an opaque session cookie. Default seeded admin: `admin@example.com` / `changeme` (first login forces a password change unless `PASSWORD_CHANGE_ENFORCEMENT_ENABLED=false` - is set in ContextForge's `.env`). + is set in mcp-context-forge's `.env`). > `npm run dev` (plain Vite dev server at `:5173`, no BFF in front) still > works for UI-only iteration, but `/api/*` calls need the BFF — it won't -> reach ContextForge on its own. +> reach mcp-context-forge on its own. #### Troubleshooting - **`EADDRINUSE` on `:3000`** — stale `tsx watch` process: `lsof -ti:3000 | xargs kill`, then restart `npm run dev` in `server/`. -- **401 mid-session** — expected; the ContextForge token hard-expires per +- **401 mid-session** — expected; the mcp-context-forge token hard-expires per `TOKEN_EXPIRY` (default 20 min). The BFF auto-revokes the session and redirects to login. @@ -330,12 +330,12 @@ client/ ├── tsconfig.app.json # TypeScript app config ├── vite.config.ts # Vite configuration (builds to server/public/) ├── package.json # Dependencies and scripts -└── server/ # BFF (Fastify): session/CSRF boundary in front of ContextForge +└── server/ # BFF (Fastify): session/CSRF boundary in front of mcp-context-forge ├── src/ │ ├── index.ts # Entrypoint │ ├── config.ts # Env-driven config │ ├── plugins/ # cookie, redis, session, csrf, static - │ └── routes/ # auth/, proxy/ (catch-all to ContextForge), sse/ + │ └── routes/ # auth/, proxy/ (catch-all to mcp-context-forge), sse/ ├── public/ # Built SPA (npm run build output), served by BFF ├── .env.example # Copy to .env and configure FASTAPI_URL etc. └── package.json From d3583aa7c51002d48691deecc10a561e9cadc6c2 Mon Sep 17 00:00:00 2001 From: AE Date: Wed, 12 Aug 2026 12:39:58 -0700 Subject: [PATCH 4/4] replaced em dashes Signed-off-by: AE Signed-off-by: Anna Effort --- README.md | 52 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 878c4b6..ea6f7a0 100644 --- a/README.md +++ b/README.md @@ -7,11 +7,11 @@ This UI targets **mcp-context-forge API v1.0.7**, matching [`openapi.json`](./op ## Tech Stack - **React 18** with TypeScript -- **Vite** - Build tool and dev server -- **React Router** - Client-side routing -- **React Intl** - Internationalization (i18n) -- **Tailwind CSS** - Utility-first styling -- **shadcn/ui** - Component library +- **Vite**: build tool and dev server +- **React Router**: client-side routing +- **React Intl**: internationalization (i18n) +- **Tailwind CSS**: utility-first styling +- **shadcn/ui**: component library ## Getting Started @@ -29,20 +29,20 @@ npm install The app is split into three pieces that all must run for local dev: -- **mcp-context-forge** — the upstream FastAPI gateway. It owns +- **mcp-context-forge**: the upstream FastAPI gateway. It owns auth and all business data. -- **BFF** (`server/`) — a Fastify app that sits between the browser and +- **BFF** (`server/`): a Fastify app that sits between the browser and mcp-context-forge. It holds the session cookie/CSRF boundary and keeps the API's JWT off the browser (`server/src/index.ts`). The browser only ever talks to the BFF, never directly to mcp-context-forge. -- **Client** (`src/`) — this React SPA, served as static files by the BFF - (same-origin — the API client always calls relative paths, see +- **Client** (`src/`): this React SPA, served as static files by the BFF + (same-origin: the API client always calls relative paths, see `src/api/client.ts`). Bring them up in this order: 1. **Start mcp-context-forge** (terminal A, a separate clone of the - `mcp-context-forge` repo — it is not part of contextforge-web-ui). Follow + `mcp-context-forge` repo: it is not part of contextforge-web-ui). Follow its own quick-start guide: https://github.com/IBM/mcp-context-forge/issues/2503 In that repo, `make dev` boots it on `:8000` by default. Note whatever @@ -56,18 +56,18 @@ Bring them up in this order: ``` Edit `server/.env`: - - `FASTAPI_URL` — point it at whatever host:port mcp-context-forge is + - `FASTAPI_URL`: point it at whatever host:port mcp-context-forge is listening on from step 1. `.env.example`'s default (`4444`) is mcp-context-forge's own **production** default (`make serve`); `make dev` - (the usual path for local dev) listens on `:8000` instead — confirm + (the usual path for local dev) listens on `:8000` instead: confirm against your actual run rather than assuming either. - - `COOKIE_SECURE=false` — needed for local HTTP; the default (`true`) is + - `COOKIE_SECURE=false`: needed for local HTTP; the default (`true`) is for prod and silently drops the session cookie over plain HTTP. Other values (`PORT`, `REDIS_URL`, `SESSION_TTL_SECONDS`, etc.) have - dev-safe defaults — see comments in `server/.env.example`. + dev-safe defaults; see comments in `server/.env.example`. `REDIS_URL=memory://` (the default) is an in-process store, no Redis - process needed for local dev — state resets on restart. + process needed for local dev; state resets on restart. ```bash npm install @@ -82,12 +82,12 @@ Bring them up in this order: ``` This builds the SPA into `server/public/`, which the already-running BFF - serves directly. Re-run `npm run build` after any frontend change — + serves directly. Re-run `npm run build` after any frontend change; there's no HMR dev server wired to the BFF, so this build step is the loop for local iteration against the real backend. (`npm run build:watch` reruns it automatically on file changes.) -4. **Use it.** Visit `http://localhost:3000/` — redirects to `/app/login` +4. **Use it.** Visit `http://localhost:3000/`: redirects to `/app/login` (unauthed) or `/app/` (authed). The login form posts through the BFF, which holds the mcp-context-forge JWT server-side and hands the browser only an opaque session cookie. @@ -102,7 +102,7 @@ Bring them up in this order: #### Troubleshooting -- **`EADDRINUSE` on `:3000`** — stale `tsx watch` process: +- **`EADDRINUSE` on `:3000`**: stale `tsx watch` process: `lsof -ti:3000 | xargs kill`, then restart `npm run dev` in `server/`. - **401 mid-session** — expected; the mcp-context-forge token hard-expires per `TOKEN_EXPIRY` (default 20 min). The BFF auto-revokes the session and @@ -124,7 +124,7 @@ npm run preview ## API Types -TypeScript types and fetch clients under `src/generated/` come from [`openapi.json`](./openapi.json) via [Orval](./orval.config.ts). That file is committed and pinned to API v1.0.7 — not re-fetched at build time. +TypeScript types and fetch clients under `src/generated/` come from [`openapi.json`](./openapi.json) via [Orval](./orval.config.ts). That file is committed and pinned to API v1.0.7, not re-fetched at build time. ```bash npm run generate # regenerate src/generated/ from ./openapi.json @@ -173,9 +173,9 @@ npm run format:check ### Test Framework -- **Vitest** - Fast unit test runner with jsdom environment -- **React Testing Library** - Component testing utilities -- **MSW (Mock Service Worker)** - API mocking +- **Vitest**: Fast unit test runner with jsdom environment +- **React Testing Library**: Component testing utilities +- **MSW (Mock Service Worker)**: API mocking ### Running Tests @@ -264,9 +264,9 @@ export const handlers = [ Test-specific TypeScript configuration: -- **[`tsconfig.app.json`](./tsconfig.app.json)** - Includes `vitest/globals` and `@testing-library/jest-dom` types -- **[`src/vitest.d.ts`](./src/vitest.d.ts)** - Global type declarations for test utilities -- **[`vitest.config.ts`](./vitest.config.ts)** - Vitest configuration with jsdom environment +- **[`tsconfig.app.json`](./tsconfig.app.json)**: includes `vitest/globals` and `@testing-library/jest-dom` types +- **[`src/vitest.d.ts`](./src/vitest.d.ts)**: global type declarations for test utilities +- **[`vitest.config.ts`](./vitest.config.ts)**: Vitest configuration with jsdom environment ## End-to-End Testing @@ -367,7 +367,7 @@ client/ The app supports multiple languages via React Intl: -- **English (en-US)** - Default +- **English (en-US)** (default) - **Spanish (es-ES)** - **Portuguese (pt-BR)**