> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mcphub.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Architecture

> How MCPHub is laid out at runtime

This page describes the actual moving parts of MCPHub today. Anything not listed here is not implemented — there is no built-in Redis, no Prometheus exporter, no WebSocket server, no plugin loader.

## Process model

MCPHub runs as a single Node.js (Express) process. The entrypoint is `src/index.ts`, which delegates to `AppServer` in [src/server.ts](src/server.ts). `AppServer` is responsible for:

1. Initializing i18n (`src/utils/i18n.ts`).
2. Bootstrapping the default admin user (`src/models/User.ts:initializeDefaultUser`).
3. Initializing the optional **upstream-MCP OAuth client provider** (`src/services/oauthService.ts`) and the optional **MCPHub OAuth authorization server** (`src/services/oauthServerService.ts`).
4. Wiring middlewares (`src/middlewares/index.ts`) and HTTP routes (`src/routes/index.ts`).
5. Spawning / connecting all enabled upstream MCP servers via `initUpstreamServers()` in `src/services/mcpService.ts`.
6. Mounting the SSE / streamable-HTTP MCP routes (`/mcp/:group`, `/sse/:group`, and their user-scoped variants `/:user/mcp/...`, `/:user/sse/...`).
7. Serving the built frontend from `frontend/dist/` (unless `DISABLE_WEB=true`).

Shutdown is handled in `AppServer.shutdown()`: stop the HTTP server, close all upstream MCP clients, then close the database pool if database mode is on.

## Top-level directories

| Path                  | Purpose                                                                                                                                                                                 |
| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `src/server.ts`       | `AppServer` class — process lifecycle, MCP route registration.                                                                                                                          |
| `src/index.ts`        | CLI entrypoint that constructs and starts `AppServer`.                                                                                                                                  |
| `src/routes/index.ts` | All HTTP route definitions (single file).                                                                                                                                               |
| `src/middlewares/`    | Auth (`auth.ts`), user context (`userContext.ts`), i18n, common middleware.                                                                                                             |
| `src/controllers/`    | One controller per resource (servers, groups, users, tools, prompts, resources, logs, activities, OAuth, bearer keys, templates, market, cloud, registry, MCPB upload, health, config). |
| `src/services/`       | Long-lived domain services — see the table below.                                                                                                                                       |
| `src/dao/`            | Data access layer with a file backend (default) and a TypeORM-based DB backend (`*DaoDbImpl.ts`). The factory in `src/dao/DaoFactory.ts` selects the implementation.                    |
| `src/db/`             | TypeORM `DataSource`, entities (`src/db/entities/`), repositories, subscribers. Loaded only in database mode.                                                                           |
| `src/models/`         | Lightweight in-memory models (e.g. `User`, `OAuth`) that wrap the DAO layer for convenience.                                                                                            |
| `src/clients/`        | Upstream MCP client wrappers (stdio / SSE / streamable-http / OpenAPI).                                                                                                                 |
| `src/types/`          | Shared TypeScript types — start here when looking for config schemas.                                                                                                                   |
| `src/utils/`          | Helpers: rate limiting, JWT, vector helpers, file migration, bearer-token parsing, etc.                                                                                                 |
| `src/betterAuth.ts`   | Optional [Better Auth](https://better-auth.com/) integration (GitHub/Google OAuth).                                                                                                     |
| `frontend/`           | Vite + React dashboard. Talks to the API over `/api`. In dev, `frontend/vite.config.ts` proxies to `http://localhost:3000`.                                                             |

## Service layer

The services in `src/services/` are the core domain layer. Notable members:

| Service                                                | Responsibility                                                                                                      |
| ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
| `mcpService.ts`                                        | Lifecycle of all upstream MCP clients (connect, reconnect, capability cache, tool/prompt/resource registries).      |
| `sseService.ts`                                        | Handles HTTP requests on `/sse/*` and `/mcp/*` and proxies them to the right upstream client / group / smart route. |
| `smartRoutingService.ts`                               | Vector-search-based tool discovery. Requires Postgres + pgvector and an OpenAI-compatible embedding endpoint.       |
| `vectorSearchService.ts`                               | Embedding store and similarity search backing smart routing.                                                        |
| `oauthService.ts`                                      | Acts as an **OAuth client** to upstream MCP servers that require OAuth.                                             |
| `oauthServerService.ts`                                | Acts as an **OAuth authorization server** for downstream MCP clients (uses `@node-oauth/oauth2-server`).            |
| `betterAuthConfig.ts` + `src/betterAuth.ts`            | Optional social-login layer; mounted at `${basePath}${betterAuthConfig.basePath}` (default `/api/auth/better`).     |
| `activityLoggingService.ts`                            | Records request/response activities. Persists to the `mcphub_activity` table; only active in database mode.         |
| `logService.ts`                                        | In-process log buffer that powers `/api/logs` and the SSE stream at `/api/logs/stream`.                             |
| `templateService.ts`                                   | Export / import of `mcp_settings.json` snapshots and group templates.                                               |
| `marketService.ts` / `cloudService.ts` / `registry.ts` | Read-mostly catalogs surfaced by the dashboard.                                                                     |
| `keepAliveService.ts`                                  | Optional periodic ping for `sse` upstream servers.                                                                  |

## Data layer

MCPHub supports two storage backends. The choice is decided once at startup:

```
useDatabase = (USE_DB === 'true') OR (USE_DB unset AND DB_URL set)
```

### File mode (default)

All persistent state lives in `mcp_settings.json` (path configurable via `MCPHUB_SETTING_PATH`). Users, servers, groups, system config and OAuth state are read/written through `src/dao/*Dao.ts` file implementations. This is the simplest deployment mode and works for single-instance use.

### Database mode

When enabled, MCPHub uses TypeORM against PostgreSQL. The schema is defined by entities in `src/db/entities/`:

* `User`, `BearerKey`, `OAuthClient`, `OAuthToken`
* `Server`, `Group`, `SystemConfig`, `UserConfig`
* `BuiltinPrompt`, `BuiltinResource`
* `Activity` — request/response logging (only populated in DB mode).
* `VectorEmbedding` — pgvector-backed table used by smart routing.

The DAO factory in `src/dao/DaoFactory.ts` swaps in the `*DaoDbImpl.ts` variants when database mode is on. A one-time migration script `src/scripts/migrate-to-database.ts` copies an existing `mcp_settings.json` into the database; the helper in `src/utils/migration.ts` runs the same path on first start.

See [Database Configuration](/configuration/database-configuration) for setup details.

## Request paths

There are three classes of HTTP route, all defined in `src/routes/index.ts` and mounted by `AppServer`:

1. **Public endpoints** (no auth):
   * `GET /health`
   * `GET ${basePath}/config`, `GET ${basePath}/public-config`
   * All `/oauth/*` and `/.well-known/oauth-*` endpoints (the OAuth flow itself).
   * All `${basePath}/api/openapi*` and `${basePath}/api/tools/...` OpenAPI endpoints.
   * `POST /api/auth/login`, `POST /api/auth/register`.
2. **Authenticated dashboard / management API** under `${basePath}/api/*`. Authentication is enforced by `src/middlewares/auth.ts`, which accepts (in order):
   * A configured system-level bearer key (`/api/auth/keys`) whose `accessType` is `all`.
   * An OAuth access token issued by MCPHub's authorization server (when enabled).
   * A Better Auth session cookie (when enabled).
   * An `x-auth-token` JWT issued by `/api/auth/login`, or the same value as a `?token=` query.
   * If `systemConfig.routing.skipAuth` is `true`, unauthenticated dashboard API calls receive a synthetic `guest` user with admin privileges.
3. **MCP transport routes**: `${basePath}/mcp/:group?`, `${basePath}/sse/:group?`, plus their user-scoped variants `${basePath}/:user/mcp/...` and `${basePath}/:user/sse/...`. These are rate-limited via `mcpConnectionRateLimiter` and pass through `sseUserContextMiddleware` before being dispatched by `sseService.ts`. System-level key scopes are enforced inside `sseService.ts`; user-level keys restore their owner's live user context so server visibility filtering applies.

## Observability

What actually ships today:

* `GET /health` — process & database & MCP-server connection status.
* `GET /api/logs`, `DELETE /api/logs`, `GET /api/logs/stream` (Server-Sent Events of the in-memory log buffer).
* `GET /api/activities*` — query the `mcphub_activity` table. **Database mode only.**

There is no Prometheus exporter, no OpenTelemetry SDK initialization and no built-in distributed tracing. If you need those, scrape `/health`/`/api/logs/stream` or wrap the process at the infrastructure layer (sidecar, log shipper, etc.).

## Frontend

The dashboard is a Vite + React + Tailwind app under `frontend/`. After `pnpm build` it is emitted to `frontend/dist/` and served by the backend as static files at `${basePath}/`. In development (`pnpm dev`), Vite runs on `:5173` and proxies `/api`, `/mcp`, `/sse`, `/oauth`, `/health` to the backend on `:3000` — see `frontend/vite.config.ts`.

The frontend uses the same JWT / Bearer / Better Auth session that the management API expects; it does not have its own auth.
