-
Notifications
You must be signed in to change notification settings - Fork 1
Proposed README edits #18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
a-effort
wants to merge
4
commits into
main
Choose a base branch
from
readme/clarify-contextforge-dev-step
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,17 +1,17 @@ | |||||||||||
| # 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 | |||||||||||
|
|
|||||||||||
| - **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,41 +29,45 @@ 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 | |||||||||||
| - **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 ContextForge. | |||||||||||
| - **Client** (`src/`) — this React SPA, served as static files by the BFF | |||||||||||
| (same-origin — the API client always calls relative paths, see | |||||||||||
| 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** — the upstream `mcp-context-forge` repo. Follow | |||||||||||
| 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 | |||||||||||
| 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/`): | |||||||||||
| 2. **Configure and start the BFF** (terminal B, contextforge-web-ui's `server/`): | |||||||||||
|
|
|||||||||||
| ```bash | |||||||||||
| cd server | |||||||||||
| cp .env.example .env | |||||||||||
| ``` | |||||||||||
|
|
|||||||||||
| 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). | |||||||||||
| - `COOKIE_SECURE=false` — needed for local HTTP; the default (`true`) 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 | |||||||||||
| against your actual run rather than assuming either. | |||||||||||
|
Comment on lines
+59
to
+63
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it be good if we had a table here?
|
|||||||||||
| - `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 | |||||||||||
|
|
@@ -78,29 +82,29 @@ 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 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: | |||||||||||
| - **`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. | |||||||||||
|
|
|||||||||||
|
|
@@ -120,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 | |||||||||||
|
|
@@ -169,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 | |||||||||||
|
|
|||||||||||
|
|
@@ -260,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 | |||||||||||
|
|
|||||||||||
|
|
@@ -326,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 | |||||||||||
|
|
@@ -363,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)** | |||||||||||
|
|
|||||||||||
|
|
|||||||||||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can add something like