Skip to content
Conduit

mcp server

forseti

A self-service UI and OAuth2 login/consent/logout bridge for Ory Kratos + Ory Hydra

franzos/forseticommunitylistedunreviewed

Set up

Runs on your computer. Pick your agent and operating system.

This project does not publish an install method we can turn into a config. Follow the README instead.

README

synced Oct 21, 2026

Forseti

The web UI Ory doesn't ship. Every self-service identity flow for Ory Kratos and Ory Hydra — login, registration, recovery, MFA, OAuth2 consent — plus an admin console, in a single server-rendered binary.

CI Release OpenSSF Scorecard License: AGPL v3 Container

Ory's engines are excellent, but headless — you get APIs, your users need pages. Forseti is the missing frontend: one binary that talks to Kratos (identity) and Hydra (OAuth2/OIDC) and gives your users real screens for every flow, plus an admin surface for operators.

Why Forseti

Because it's backed by software the giants scale with — OpenAI self-hosts Ory Hydra to issue tokens for ChatGPT — so your auth load rides on the most battle-tested engine in this space, not on Forseti itself. And it doesn't lock you in: Ory is the contract, Forseti is just the face. You can move to Ory Network (their cloud) later, or build your own frontend against the same Kratos and Hydra APIs and swap it in. That makes Forseti a low-risk stepping stone — and, since it's fully themeable, a fine permanent answer if it's all you ever need.

What you get

🔐 Every Kratos flow, server-renderedLogin, registration, recovery, verification, and the full settings hub — profile, password, MFA/TOTP, passkeys, social logins, active sessions.
🪪 OAuth2 / OIDC bridgeLogin, consent, and logout screens for Hydra's authorization-code flow — turn Forseti into a drop-in OIDC provider for your own apps.
🤖 MCP authorizationAuthorize your Model Context Protocol servers off the same stack. Claude Code, Claude Desktop and claude.ai onboard themselves over CIMD — no registration endpoint, nothing to set up per connection — and one registry row decides which audiences consent can mint. How it works ↓
🧩 40+ app templatesOne-click, pre-filled OAuth2 client setup for popular self-hosted apps (GitLab, Nextcloud, Vaultwarden, Grafana, Immich, …) — redirect URIs and per-app OIDC quirks already filled in. Full list →
🛠️ Admin consoleManage identities, sessions, and OAuth2 clients; a resource registry for the audiences consent may grant; append-only audit log; live status dashboard.
🏢 OrganizationsMulti-tenant orgs with members, invites, per-org theming (brand colours, a preset, and an uploaded logo — the authenticated app is white-labelled by the active org), and per-org OIDC claims. Each org runs internal (invite-only) or external — a public self-serve signup page at /o/{slug} — plus optional email-domain auto-join for workforce orgs.
📊 Observability (licensed)Prometheus /metrics on the internal listener, token-gated: HTTP request counts and latency plus a couple of bridged operational gauges. Setup →
🐧 Linux host auth (preview)Back your Linux logins off the identity store: NSS passwd/group + per-user SSH-key distribution, interactive ssh/console login via the OAuth Device Authorization Grant (RFC 8628), and offline passphrase login when the server's unreachable. Setup →
🌍 Nine languagesUI translated into English, German, French, Spanish, Italian, Portuguese, Russian, Thai, and Arabic (RTL-aware), including Kratos's own error messages. A footer switcher sets the language; otherwise it follows the browser's Accept-Language.
🌗 Light & darkA built-in theme toggle (light / dark / follow-system) across every page.
🛡️ Production-mindedCSRF on every form, signed cookies, rate-limited public endpoints, and an account-deletion webhook saga with retries.

Authorizing MCP servers

The MCP 2025-06-18 spec is OAuth 2.1 + OIDC, so Hydra fits. What it's missing is CIMD (ory/hydra#4061) and RFC 8707 resource=, which it ignores entirely. Forseti fills both gaps:

  • Clients onboard themselves. Under CIMD the client_id is an HTTPS URL pointing at a metadata document the client's vendor hosts. Forseti's /oauth2/authorize shim fetches it (https only, public IPs, no redirects, 5 s timeout, 64 KiB cap), validates it, upserts the Hydra client and forwards into Hydra. Someone runs claude mcp add yourapp https://mcp.yourapp.com/mcp --transport http, signs in, and it works. RFC 7591 Dynamic Client Registration is retired: no registration_endpoint anywhere.
  • You decide which audiences exist. One row at /admin/resources naming your canonical resource URI lets consent bind it into an access token's aud. Default deny: an unregistered resource comes back aud: [], and a CIMD document can't mint itself an audience. Effective on the next consent, no restart.
  • Discovery says so. Forseti serves the RFC 8414 path-insertion documents with client_id_metadata_document_supported: true and the shim's authorization_endpoint, cross-origin, because claude.ai reads them from the browser.

A CIMD client's consent screen leads with the host of its metadata URL (claude.ai) — the part whoever runs it provably controls — with the self-asserted name on a second line. No verified badge, no auto-grant; the screen renders every time.

Your side is two endpoints and a header: an RFC 9728 metadata document, WWW-Authenticate on the 401, and local JWT validation against Hydra's JWKS.

Two limits: tokens are bearer-only, no DPoP yet, and clients that speak only DCR — Cursor, as of mid-2026 — won't connect until they ship CIMD. Details in the integration guide; the operator checklist is in the operator guide.

Organization claims over OIDC

Forseti can fold the caller's org membership into the ID token and userinfo, so a connected app does tenant-aware access control without a second API call. Three opt-in scopes cover different needs; grant a client any combination (each still needs the user's consent, and only shows up when requested):

ScopeClaim shapeCoversStandardized?Reach for it when
groupsFlat array of team slugsThe active org's teamsDe-facto (widely implemented)Wiring a third-party app (ArgoCD, Grafana, Harbor, Proxmox, …) that maps a groups claim to its own roles
orgOne object: active org + your roleThe active orgForseti-specificAn app that only cares about the currently-selected tenant
orgsArray of {id, slug, role, name}Every org you belong toForseti-specificA multi-tenant app (e.g. Stackpit) that renders an org switcher and enforces per-org roles

groups is the portable path: it's in no RFC, but enough apps read a groups claim that it's become the lingua franca for role mapping, which is why the app templates use it. org/orgs are richer and self-describing (they carry the role explicitly) but only an app written against Forseti's shape can consume them. No off-the-shelf IdP emits orgs, and no generic app reads it.

One thing to keep in mind: groups reflects the active org only, while orgs spans all memberships, so for a multi-tenant app the two can look like they disagree. That's by design, not a bug.

OSS vs commercial

OSS (unlicensed)Commercial (licensed)
Identity portalFull self-service portal, single default orgSame, plus named orgs beyond Default
Enterprise SAML SSOUnavailablePer-org connections at /sso/{org-slug}
Linux (POSIX) auth accountsUp to the free seat capHigher seat cap
ObservabilityUnavailablePrometheus /metrics on the internal listener, token-gated
Health checks, JSON logsFullFull

See Commercial features for the licensing model, the grace period on expiry, and full detail on each feature.

How Forseti compares

Here's the thing: Forseti isn't another from-scratch identity engine. Rauthy, Kanidm, Keycloak and FreeIPA each implement their own protocol stack and their own datastore — they are the engine. Forseti is the part Ory never shipped: a server-rendered UI, an admin console, multi-tenant orgs, and governance, sitting in front of Ory Kratos and Ory Hydra — engines that are already OpenID-certified and battle-tested in production. So the comparison below is a little apples-to-oranges, and that's rather the point.

Legend: ✓ built-in · ◐ partial / via add-on / consumes-not-serves · ✗ no · † commercial license

ForsetiRauthyKanidmKeycloakFreeIPA
What it isUI + governance layer on OryStandalone OIDC providerPasskey-first IdMFull IAM serverLinux/Unix domain IdM
LanguageRust (Axum)RustRustJava / Quarkus (JVM)C + Python
OIDC / OAuth2 provider✓ (Hydra)✓✓✓◐ inbound only
SAML 2.0✓ †✗✗✓◐ via Keycloak
TOTP + passkeys/WebAuthn✓ (AAL2-enforced)◐ passkey-first✓ (passkey attestation)✓✓ (+ smartcard)
Multi-org / tenancy✓ †✗✗✓ realms + orgs✗
Upstream IdP brokering / social login✓ (Kratos)✓✗ by design✓◐ device-grant
LDAP / RADIUS / Unix (POSIX) hosts◐ POSIX/PAM ²◐ PAM/NSS✓◐ federation✓ (core)
Admin console (web)✓✓◐ CLI-first✓✓
End-user self-service UI✓ (the whole point)✓✓✓◐ limited
DatastoreSQLite / Postgres¹Embedded (Hiqlite) / PostgresOwn embedded DBExternal RDBMS389 DS (LDAP)
FootprintBinary + Ory servicesSingle binary (~50 MB)Single binaryJVM, ~0.75–2 GB RAMHeavy, Linux/RPM only
LicenseAGPL-3.0 + commercial gateApache-2.0MPL-2.0Apache-2.0GPLv3
MaturityYoung; built on mature OryPre-1.0, auditedStable 1.xVery mature (CNCF/Red Hat)Very mature (Red Hat)

¹ Forseti's own data. Kratos and Hydra each bring their own Postgres, so a full deployment runs several services — more moving parts than a single-binary Rauthy or Kanidm. † Organizations, SAML SSO, and the Prometheus /metrics endpoint are commercial features; the AGPL core runs as a fully working single tenant. SCIM, SIEM streaming and bulk-admin are on the roadmap, not shipped. ² Linux host auth (POSIX accounts, NSS, SSH-key distribution, PAM device-auth + offline login) ships as a preview — it backs POSIX hosts, but it's not an LDAP/RADIUS/Kerberos directory.

Where Forseti wins. If you've already bet on Ory — or you want a certified OAuth2/OIDC engine rather than a bespoke one — nothing else gives Kratos and Hydra real screens and an admin console and first-class multi-tenant organizations (members, invites, per-org branding, org/orgs OIDC claims). Rauthy, Kanidm and FreeIPA have no organizations model at all; only Keycloak does, and it costs you a JVM and a couple of gigs of RAM. You also get governance the others don't bundle: an append-only audit log, CIMD client onboarding for MCP with a default-deny audience registry, and an account-deletion webhook saga that emits signed RISC events.

Where it doesn't. Forseti is not a full directory. It now can back Linux logins — POSIX accounts, SSH-key distribution, and interactive PAM login for a fleet of hosts (a preview feature) — but if you need an LDAP server, RADIUS, or Kerberos, that's still Kanidm or FreeIPA territory, not this. If you want the absolute smallest footprint and a single self-contained binary with no Ory alongside, Rauthy or Kanidm will be lighter to run. And if you need the full enterprise kitchen sink — UMA, fine-grained authz, every protocol under one roof — Keycloak still does more, at the cost of operating Keycloak. Do take the table with a grain of salt: these projects move, and the facts here are current as of mid-2026.

Quickstart

Every release carries tarballs for x86_64 and aarch64 Linux (glibc), .deb and .rpm packages for x86_64, and a container image.

curl -L -o forseti.tar.gz https://github.com/franzos/forseti/releases/latest/download/forseti-x86_64-unknown-linux-gnu.tar.gz
tar -xzf forseti.tar.gz
cd forseti-x86_64-unknown-linux-gnu
cp config.example.toml config.toml   # then edit it
./forseti

Debian, Ubuntu and the RPM distros install the same binary to /usr/bin/forseti, with the example config at /usr/share/doc/forseti/config.example.toml. Grab the file for the version you want from the release page, then:

sudo apt install ./forseti_0.2.7-1_amd64.deb      # Debian, Ubuntu
sudo dnf install ./forseti-0.2.7-1.x86_64.rpm     # Fedora, RHEL, openSUSE

sudo mkdir -p /etc/forseti
sudo cp /usr/share/doc/forseti/config.example.toml /etc/forseti/config.toml   # then edit it
FORSETI_CONFIG_PATH=/etc/forseti/config.toml forseti

Or pull the container image from the GitHub Container Registry:

podman pull ghcr.io/franzos/forseti:latest
podman run --rm -p 3000:3000 \
  -v ./config.toml:/app/config.toml:ro \
  ghcr.io/franzos/forseti:latest

All of them need a reachable Kratos and Hydra — see the operator guide. The binary reads ./config.toml (override with FORSETI_CONFIG_PATH); web assets, translations and database migrations are compiled into it, so there is nothing else to deploy alongside.

Runtime note: the binary links dynamically against libpq (the Postgres client). On a bare host install libpq5 (Debian/Ubuntu) or libpq (most other distros); the container image already includes it. SQLite is bundled, so it needs nothing extra.

Verify the download

Every tarball and package ships a .sha256 next to it, and each release carries SLSA build provenance (multiple.intoto.jsonl) signed keylessly through Sigstore covering all of them. Download both alongside the artifact, then:

sha256sum -c forseti-x86_64-unknown-linux-gnu.tar.gz.sha256

# needs slsa-verifier: https://github.com/slsa-framework/slsa-verifier
slsa-verifier verify-artifact forseti-x86_64-unknown-linux-gnu.tar.gz \
  --provenance-path multiple.intoto.jsonl \
  --source-uri github.com/franzos/forseti

That proves the artifact came out of this repository's release workflow at that tag, not off someone's laptop. The same command works on a .deb or .rpm — swap the filename.

Status

Pre-release / active development. Core flows work end-to-end against the Ory playground; APIs, config, and schema are still moving. Pin a commit if you build on it.

Build from source

# 1. Bring up the playground (Kratos, Hydra, Mailcrab, Postgres)
make stack-up

# 2. Seed a deterministic admin (password + TOTP)
make seed-admin

# 3. Run Forseti (debug build) at :3000
make run

Open http://localhost:3000. Register at /registration, grab the verification email from Mailcrab at http://127.0.0.1:4436, and you're in.

For the full OAuth2 dance — register a Hydra client, run an auth-code flow, exchange a token — see the integration guide.

How it fits together

      Browser
         |
         v
+------------------+        admin (server-only)
|     Forseti      | --------------------------------+
|   Rust / Axum    |                                 |
|       :3000      | --+                             |
+------------------+   |                             |
         |             |                             |
         | browser     | browser                     |
         |             |                             v
   +------------+ +------------+             | Kratos admin   |
   |  Kratos    | |   Hydra    |             | Hydra admin    |
   |  public    | |  public    |             | (internal only)|
   +------------+ +------------+             +-----------------+
         |             |
         +------+------+
                |
                v
         +--------------+
         |  Database    |
         | Postgres /   |
         |   SQLite     |
         +--------------+

Documentation

Full documentation is published at https://franzos.github.io/forseti/.

License

Forseti is dual-licensed:

  • AGPL-3.0 for the open-source core (everything outside src/commercial/)
  • Commercial license for paid features in src/commercial/

Built on Ory Kratos and Ory Hydra.


Forseti — named for the Norse god of justice and reconciliation.

↑↓ navigate openesc close