# Alkemata server architecture and project inventory _Production snapshot: 24 October 2026. This page describes the running Linux server, not a proposed architecture. Recheck service status and configuration before an operational change._ ## At a glance Alkemata is several applications behind one HTTPS reverse proxy. They share an identity service where needed, but keep their application data and deployments separate. | Public address | Purpose | Main runtime and source | | --- | --- | --- | | `https://alkemata.com` | Editorial website, published articles, WordPress APIs | WordPress in Docker; `/srv/alkemata/wordpress` | | `https://map.alkemata.com` | Interactive knowledge map and REST API | Static web and Python API as user systemd services; `/srv/alkemata/knowledge-map` | | `https://auth.alkemata.com` | Alkemata login and OAuth | Keycloak in Docker; `/srv/alkemata/auth/keycloak` | | `https://projects.alkemata.com` | Project collaboration and wiki | OpenProject Community in Docker; `/srv/alkemata/openproject` | | `https://exchange.alkemata.com` | Moderated opportunities, contributions, and agent participation | FastAPI, worker, and PostgreSQL in Docker; `/srv/alkemata/exchange` | Traefik receives ports 80 and 443, terminates TLS, and routes these hostnames. Its configuration is in `/srv/alkemata/traefik`, with the current application routes in `custom/*.yaml`. Do not infer a deployment method from a repository's README alone: the map's active API and web frontend are user systemd services, while WordPress, Keycloak, OpenProject, Exchange, and Traefik run in Docker. ## Applications and data ownership ### WordPress: the editorial site WordPress publishes the articles, pages, author profiles, and navigation at `alkemata.com`. The running stack is PHP 8.3/Apache with its own MySQL database. Its source/deployment files are under `/srv/alkemata/wordpress`; content and plugins are in the WordPress container and persistent storage. The `mcp-adapter` and `alkemata-participation` plugins support the public content and submission tools used by the Alkemata gateway. WordPress also runs an **independent Easy MCP administration endpoint** at `/wp-json/easy-mcp-ai/v1/mcp`. It has its own OAuth setup and WordPress-oriented tools. It is active and must not be removed as part of gateway cleanup. Its broad administration functions are not the OpenProject tools. ### Knowledge map and shared MCP gateway The map's frontend is served by `alkemata-map-web.service`; its FastAPI backend is served by `alkemata-map-api.service`. The map has its own PostgreSQL 17 data directory under `/srv/alkemata/knowledge-map/runtime`, reached on host loopback. The map stores topics, placements, categories, relationships, trails, and editor state. Published WordPress article text remains in WordPress; the gateway fetches it rather than copying it into the map database. The **canonical shared MCP endpoint** is: `https://alkemata.com/wp-json/mcp/alkemata-public` Traefik routes that path to the map API. The API exposes public WordPress and map read tools, proposal tools that queue submissions for review, and private tools with per-user authorization. For WordPress content tools, the API calls the WordPress MCP upstream through a specific internal gateway route. For `openproject_*` tools, it calls the private OpenProject bridge after validating an Alkemata OAuth token. These are different paths through one externally advertised gateway. `https://map.alkemata.com/mcp` is a retired address and returns 404. `https://alkemata.com/wp-json/alkemata-public` is also not the gateway: it omits `/mcp`. The path-specific OAuth resource metadata for the canonical gateway is at `/.well-known/oauth-protected-resource/wp-json/mcp/alkemata-public`. The root `/.well-known/oauth-protected-resource` belongs to WordPress Easy MCP; do not use it to infer the gateway's OAuth settings. ### Identity: Keycloak Keycloak 26.8 runs with a separate PostgreSQL database. The `alkemata` realm provides user login and OAuth for the map gateway, OpenProject browser SSO, and Exchange. Client configuration, redirect URLs, scopes, and token audiences live here. Do not put client secrets, application passwords, tokens, or `.env` contents in this wiki. Public article and map reads need no account. Private map writes require `knowledge:contribute` plus the person's map role. OpenProject reads and edits require `projects:read` and `projects:write` respectively, plus that person's OpenProject project permissions. An OAuth client must also be configured to request those optional scopes; newly dynamically registered clients may not have them automatically. ### OpenProject: project collaboration OpenProject 17 Community has its own PostgreSQL database, cache, worker, and collaboration containers. Browser sign-in passes from Traefik through OAuth2 Proxy and Keycloak. A private LDAP mirror supplies verified Keycloak user profiles to OpenProject; `openproject-ldap-sync.timer` refreshes it every five minutes. OpenProject's membership and roles remain the final authority for project access. The private MCP bridge is internal. It checks signed requests and the matching OpenProject user's permissions before reading or editing work packages and wiki pages. OpenProject's Enterprise MCP add-on is not used. Agents reach these tools through the canonical Alkemata gateway above, not through a separate public OpenProject MCP URL. The OpenProject deployment and bridge are under `/srv/alkemata/openproject`. There are currently three OpenProject project spaces: **Website alkemata**, **Demo project**, and **Scrum project**. These are collaboration spaces and should not be confused with the server's deployment directories. This architecture page belongs to **Website alkemata**. ### Exchange: moderated contribution pilot Exchange is a separate FastAPI application with its own PostgreSQL 17 database and background worker. It handles moderated opportunities, claims, versioned contributions, reviews, participant roles, and agent participation. It uses Keycloak identity but not the WordPress, map, or OpenProject database. Its REST and MCP interfaces are served on `exchange.alkemata.com`. Its present map-link adapter records intended provenance links; it does not automatically publish map content. Source and operating guides are under `/srv/alkemata/exchange`. ### Other directories `/srv/alkemata/ReasonReport` and `/srv/alkemata/migration` contain separate source or migration material. They were not among the running production containers or user services in this snapshot. `/srv/alkemata/mcp-registry` contains registry assets. Do not treat the presence of a directory as proof that it is a live service. ## Request and trust paths ```text Browser or agent -> Traefik / HTTPS -> WordPress / MySQL (editorial content) -> Map web + API / map PostgreSQL (knowledge map) -> Keycloak / identity PostgreSQL (login and OAuth) -> OpenProject / project PostgreSQL (project work and wiki) -> Exchange / exchange PostgreSQL (moderated participation) Agent -> canonical Alkemata MCP gateway (map API) -> WordPress MCP upstream for published content and proposals -> map database for topics and trails -> private OpenProject bridge for authorized project operations WordPress Easy MCP -> separate WordPress administration connection ``` The shared gateway can list tool names without exposing private project data. A project tool call must carry a valid OAuth token and pass both scope and OpenProject permission checks. WordPress Easy MCP is an independent service with different tools and authorization; keep it when changing the shared gateway. ## Operations and source of truth | Area | Where to inspect or change it | Deployment / recovery note | | --- | --- | --- | | HTTPS routes | `/srv/alkemata/traefik/custom/*.yaml` | Traefik watches these route files. Check which hostname and path a rule matches before changing it. | | Map API and web | `/srv/alkemata/knowledge-map`; `systemctl --user status alkemata-map-api.service alkemata-map-web.service` | Active deployment is user systemd, not the alternative Compose recipe in the repository. The map has its own backup and smoke-test scripts. | | WordPress | `/srv/alkemata/wordpress` and the `wordpress-blog-1` / `wordpress-database-1` containers | Preserve the active WordPress MCP plugins and persistent database/content volumes. | | Identity | `/srv/alkemata/auth/keycloak` and Keycloak containers | Back up the realm database before changing clients, scopes, audiences, or login policy. | | OpenProject | `/srv/alkemata/openproject`; `COMMUNITY_SSO_MCP.md` | Preserve its database and assets. The LDAP sync timer is part of sign-in. | | Exchange | `/srv/alkemata/exchange`; `docs/operations.md` | Its daily user systemd backup timer makes encrypted dumps and runs a restore verification. Off-host backup storage still needs an owner-selected destination. | Use `docker ps` for container status, `systemctl --user list-units --type=service` for the native map services, and `systemctl --user list-timers` for the backup and LDAP-sync timers. Check each project's own operations guide before migrations, upgrades, or restores. Do not place credentials or decrypted backups in this wiki or in a public repository. ## Documentation links - Public MCP guide: https://alkemata.com/alkemata-mcp/ - Knowledge map: https://map.alkemata.com/ - OpenProject: https://projects.alkemata.com/ - Exchange: https://exchange.alkemata.com/ - Server-side map guide: `/srv/alkemata/knowledge-map/README.md` (some legacy MCP addresses remain in that file; use the live route described above) - OpenProject SSO and MCP guide: `/srv/alkemata/openproject/COMMUNITY_SSO_MCP.md` - Exchange architecture and operations: `/srv/alkemata/exchange/docs/architecture.md` and `docs/operations.md`