# Getting Started
> **Local development and demo only:** The Docker Compose instructions in this guide are intended exclusively for isolated local development and demonstrations. Do not use this setup unchanged for production or test systems; those systems require a separate, non-public and appropriately secured deployment procedure.
- Install uv:
- [Using UV during development](./DEVELOPMENT.md)
- Install [Node.js 22+](https://nodejs.org/en/download/package-manager)
## ⚙️ Configure the environment
Configuration is done via **YAML configuration files** (primary) with optional **environment variable overrides**.
Each service reads a `config.yaml` mounted into the container. Environment variables can override any YAML setting using a service-specific prefix and `__` (double underscore) as the nested delimiter.
| Service | YAML file (in `stack/`) | Env Prefix |
| -------------------- | ----------------------- | ------------------- |
| core-service | `core.config.yaml` | `MUCGPT_CORE_` |
| assistant-service | `assistant.config.yaml` | `MUCGPT_ASSISTANT_` |
| assistant-migrations | `assistant.config.yaml` | `MUCGPT_ASSISTANT_` |
### Initial Setup
```bash
cd stack
cp .env.example .env
cp core.config.yaml.example core.config.yaml
cp assistant.config.yaml.example assistant.config.yaml
```
### Models Configuration (YAML)
Configure your LLM models in `core.config.yaml`. The placeholder values in this example, as well as any local demo values, must not be used unchanged in production or test environments:
```yaml
MODELS:
- type: "OPENAI"
llm_name: ""
endpoint: ""
api_key: ""
model_info:
auto_enrich_from_model_info_endpoint: true
max_output_tokens: 16384
max_input_tokens: 128000
description: ""
input_cost_per_token: 0.00000009
output_cost_per_token: 0.00000036
supports_function_calling: true
supports_reasoning: false
supports_vision: true
litellm_provider: ""
inference_location: ""
knowledge_cut_off: "2024-07-01"
```
See `mucgpt-core-service/config.yaml.example` and `mucgpt-assistant-service/config.yaml.example` for complete examples.
### Prompt Configuration
See the [AI governance and compliance checks guide](AI_GOVERNANCE.md) for the
end-to-end screening flow, version lifecycle, review queue, and operational
responsibilities.
The optional `PROMPTS` section maps prompt names used by the core service to prompts stored in [langfuse](https://langfuse.com/docs/prompt-management/overview). Configure each prompt under its Langfuse folder with the label to use; folder and prompt names must match Langfuse exactly. See `mucgpt-core-service/config.yaml.example` for the complete YAML structure.
- `defaults/default_instructions`: general system instructions for regular chat.
- `generation_prompts/chat_title`: generates concise chat titles.
- `generation_prompts/assistant_name`: generates assistant names from prompt seeds.
- `generation_prompts/assistant_description`: generates assistant descriptions from prompt seeds.
- `generation_prompts/assistant_systemprompt`: generates assistant system prompts from prompt seeds.
- `compliance_prompts/*`: screens assistant prompts for high-risk use cases (eu-ai-act) in migration/asylum/border control, public services, employment, and education.
### Document Parsing Configuration (YAML)
The core service supports extracting text and structure from uploaded documents using an optional parser. Configure the document parser in `core.config.yaml`. By default, document parsing is disabled (`PARSER_BACKEND: "none"`).
Currently, Xberg is the only supported parser backend. To enable it, set the parser backend to `"xberg"` and configure the URL and timeout:
```yaml
PARSER_BACKEND: "xberg" # Default is "none"
XBERG_URL: "http://xberg-full:8000"
XBERG_TIMEOUT: 120.0
```
Where:
- `PARSER_BACKEND`: Defines the parser used (`none` to disable, or `xberg`).
- `XBERG_URL`: Points to your Xberg parsing service.
- `XBERG_TIMEOUT`: Execution timeout in seconds.
### Transcription Configuration (YAML)
MUCGPT offers browser-based speech-to-text (beta): users can dictate into the chat input, and the audio is transcribed entirely inside their browser. The backend only gates the feature — no audio ever leaves the user's browser; the resulting transcript is placed in the chat input and can be submitted through the normal chat request. It is disabled by default (`TRANSCRIPTION_ENABLED: false`).
To enable it, set the flag in `core.config.yaml`:
```yaml
TRANSCRIPTION_ENABLED: true # Default is false
```
Or via environment variable: `MUCGPT_CORE_TRANSCRIPTION_ENABLED=true`
Optionally, preselect a default model for first-time users:
```yaml
TRANSCRIPTION_DEFAULT_MODEL: "onnx-community/whisper-small" # Default is null (frontend built-in default)
```
The id must match an entry of the frontend's model list (`mucgpt-frontend/src/config/transcriptionModels.ts`); unknown ids are ignored. The choice applies once — as soon as a user picks a model themselves, it is stored in their browser and later changes to the default do not affect them.
Notes for operators:
- All transcription models (Whisper, NVIDIA Canary/Parakeet) run client-side on WebGPU or WASM; the browser downloads them directly from their model registry (Hugging Face) and caches them locally.
- Model choice, language support, and hardware requirements are managed in the frontend (`mucgpt-frontend/src/config/transcriptionModels.ts`); the backend cannot define the model inventory or runtime, but it can preselect the default model ID through `TRANSCRIPTION_DEFAULT_MODEL` (applied on first use before the user picks a model).
- Users on hardware without WebGPU see a reduced model selection (CPU-based WASM models).
### Models Configuration (Environment Variable)
Alternatively, models can be configured via the `MUCGPT_CORE_MODELS` environment variable as a JSON array:
```env
MUCGPT_CORE_MODELS='[
{
"type": "OPENAI",
"llm_name": "",
"endpoint": "",
"api_key": "",
"model_info": {
"auto_enrich_from_model_info_endpoint": true,
"max_output_tokens": "",
"max_input_tokens": "",
"description": ""
}
}
]'
```
### Configuration Priority
Settings are loaded in this order (highest priority wins):
1. **Init values** – constructor kwargs / `init_settings`
2. **Environment variables** – `MUCGPT_CORE_*` / `MUCGPT_ASSISTANT_*`, using `__` for nested sections
3. **YAML config file** – `config.yaml` mounted into each container
4. **`.env` file** – lowest priority; values here will **not** override anything set in `config.yaml` or environment variables
This means environment variables always override YAML values, which is useful for injecting secrets in CI/CD.
### Data storage overview
MUCGPT stores data in two layers:
- PostgreSQL (persistent):
- Assistants and their versions
- Assistant subscriptions
- Redis/Valkey (temporary cache):
- MCP tool metadata cache (core service, key prefix: `mcp_tools_raw:`)
- LDAP/Active Directory data cache (assistant service, key: `mucgpt:directory-tree:v1`)
- Assistant compliance verification cache (key prefix: `mucgpt:assistant-compliance:v1:`)
Notes:
- PostgreSQL is the source of truth for assistant and subscription data.
- Redis/Valkey entries are TTL-based and can expire:
- MCP tools: configured via `MCP.CACHE_TTL` (default: 12h)
- LDAP directory cache: configured via `LDAP.CACHE_TTL` (default: 14d)
- Compliance verification cache: configured via `COMPLIANCE_CACHE_TTL_SECONDS` (default: 30m)
### Browser storage (frontend)
In addition to backend storage, the frontend uses browser storage for UX state and local history:
- IndexedDB:
- `MUCGPT-ASSISTANTS` (assistant data)
- `MUCGPT-CHAT` (chat data)
- `MUCGPT-COMMUNITY-ASSISTANTS` (community assistant data)
- localStorage:
- UI/user preferences (for example language, theme, selected tools, selected model)
- Parsed document history/content cache (`MUCGPT_PARSED_DOCUMENTS_V1`)
- Transcription settings: enabled flag, selected model, downloaded model list (`SETTINGS_TRANSCRIPTION_*`)
- Cache API (browser):
- NeMo transcription model files (Canary/Parakeet encoder/decoder/vocab, cache name `mucgpt-nemo-models-v1`)
- Whisper transcription model files (cached by transformers.js)
- sessionStorage:
- Route-local draft text in the question input
- Cookies:
- `XSRF-TOKEN` is read by the frontend and sent as `X-XSRF-TOKEN` request header
Note: Browser storage is client-local and can be cleared by the user/browser.
### Environment Variable Override Examples
Any YAML setting can be overridden. Nested sections use `__` (double underscore):
```bash
# Top-level field
MUCGPT_CORE_VERSION=1.0.0 # → VERSION: "1.0.0"
MUCGPT_CORE_AI_ACT_COMPLIANCE_CHECK_ENABLED=false # → AI_ACT_COMPLIANCE_CHECK_ENABLED: false
# Nested field (DB section in assistant service)
MUCGPT_ASSISTANT_DB__HOST=postgres # → DB: { HOST: "postgres" }
MUCGPT_ASSISTANT_DB__PASSWORD=secret # → DB: { PASSWORD: "secret" }
# Nested field (Redis section in core service)
MUCGPT_CORE_REDIS__HOST=valkey # → REDIS: { HOST: "valkey" }
# Nested field (Langfuse section)
MUCGPT_CORE_LANGFUSE__SECRET_KEY=sk-... # → LANGFUSE: { SECRET_KEY: "sk-..." }
```
**Top-level fields:**
- `type`: The provider type (e.g., `OPENAI`).
- `llm_name`: The name or identifier of your LLM model.
- `endpoint`: The API endpoint URL for the model.
- `api_key`: The API key or secret for authentication.
**`model_info` fields:**
- `auto_enrich_from_model_info_endpoint`: If `true` (default), missing metadata is fetched from `/model/info` (as it is available in litellm). Set to `false` to require manual values.
- `max_output_tokens`: Maximum number of tokens the model can generate in a response.
- `max_input_tokens`: Maximum number of tokens accepted as input.
- `description`: A human-readable description of the model.
- `knowledge_cut_off`: Optional ISO date string describing the model's latest training data cutoff.
- `input_cost_per_token` / `output_cost_per_token`: Optional pricing hints per token.
- `supports_function_calling`, `supports_reasoning`, `supports_vision`: Capability flags advertised to the UI.
- `litellm_provider`: Provider identifier reported by LiteLLM.
- `inference_location`: Region or deployment location for the model.
- `creativity_{low,medium,high}_temperature`: Map abstract creativity levels to specific `temperature` values (0.0 - 1.0 or higher depending on model). Defaults are low=0.0, medium=0.5, high=1.0.
Replace the placeholder values with your actual model configuration.
### LDAP integration
Assistants can be published to specific departments. MUCGPT reads the organization’s department tree from the configured LDAP directory, so published assistants are scoped according to that hierarchy. Configure LDAP in `assistant.config.yaml` under the `LDAP` section:
```yaml
LDAP:
ENABLED: true
HOST: "ldaps://ldap.example.org"
PORT: 636
USE_SSL: true
START_TLS: false
VERIFY_SSL: true
CA_CERT_FILE: "/path/to/ca-bundle.pem"
BIND_DN: "cn=mucgpt,ou=service-accounts,dc=example,dc=org"
BIND_PASSWORD: ""
SEARCH_BASE: "dc=example,dc=org"
SEARCH_FILTER: "(objectClass=organizationalUnit)"
DISPLAY_ATTRIBUTE: "ou"
SHORTNAME_ATTRIBUTE: "departmentCode"
PARENT_ATTRIBUTE: "parentDepartment" # optional
ADDITIONAL_ATTRIBUTES: ["departmentName", "departmentCode"]
REQUIRED_ATTRIBUTES: ["departmentName", "departmentCode"]
IGNORED_OU_PREFIXES: ["_"]
IGNORED_OU_SUFFIXES: ["-xxx"]
IGNORED_OU_SHORTNAME_EXCEPTIONS: ["DEPT-EXAMPLE"]
PAGE_SIZE: 500
CONNECT_TIMEOUT: 5.0
READ_TIMEOUT: 10.0
```
Individual fields can be overridden via environment variables using the `MUCGPT_ASSISTANT_LDAP__` prefix:
```bash
MUCGPT_ASSISTANT_LDAP__ENABLED=true
MUCGPT_ASSISTANT_LDAP__BIND_PASSWORD=
MUCGPT_ASSISTANT_LDAP__IGNORED_OU_SHORTNAME_EXCEPTIONS=["DEPT-EXAMPLE"]
```
- `SEARCH_BASE` defines the root of the organization tree.
- Toggle `USE_SSL` / `START_TLS` / `VERIFY_SSL` depending on your directory security requirements; set `CA_CERT_FILE` if your LDAP server uses a custom CA.
- `DISPLAY_ATTRIBUTE` (default `ou`) controls the label shown for each organizational unit; `SHORTNAME_ATTRIBUTE` selects its stable identifier; `PARENT_ATTRIBUTE` can be set if your LDAP schema exposes a parent reference.
- `ADDITIONAL_ATTRIBUTES` fetches extra attributes for display; `REQUIRED_ATTRIBUTES` are enforced during loading. Adapt all attribute names to your LDAP schema.
- `IGNORED_OU_PREFIXES` / `_SUFFIXES` let you skip placeholder OUs (by default everything starting with `_` or ending with `-xxx`).
- `IGNORED_OU_SHORTNAME_EXCEPTIONS` allows specific OUs to bypass ignore rules when their configured short-name attribute matches one of the listed values (case-insensitive).
- Typical use case: keep a business-relevant OU like `_Hidden` by adding its shortname (for example `DEPT-EXAMPLE`) to `IGNORED_OU_SHORTNAME_EXCEPTIONS`.
- Pagination and robustness: `PAGE_SIZE` (default 500), `CONNECT_TIMEOUT` (default 5s), and `READ_TIMEOUT` (default 10s).
### Demo credentials
The local Docker demo stack includes a standard user and an admin user for testing role-based access:
- `demo-user` / `mucgpt`
- `demo-admin` / `mucgpt`
These credentials are only for the isolated local development stack and must not be reused in production or test environments.
### SSO integration
Authentication is performed in front of the services through an OpenID Connect-compatible API gateway. MUCGPT only accepts access tokens that contain a configured authorization role and uses a configurable organization claim for authorization checks.
The SSO role is configured in each service's `config.yaml` under the `SSO` section:
```yaml
SSO:
ROLE: "mucgpt-user"
ADMIN_ROLE: "mucgpt-admin"
USER_ID_CLAIM: "user_id"
ORGANIZATION_UNIT_CLAIM: "organization_unit"
```
Or via environment variable:
```bash
# Core service
MUCGPT_CORE_SSO__ROLE=mucgpt-user
# Assistant service
MUCGPT_ASSISTANT_SSO__ROLE=mucgpt-user
```
- Configure a role that is emitted by your identity provider, such as `mucgpt-user`.
- The API Gateway handles OpenID Connect login, token issuance, and validation; services receive a validated access token.
- The access token includes a configured user-ID claim and a configurable organization claim. The latter is combined with the LDAP organization tree to scope assistant publishing and access.
### MCP (optional)
Besides static tools, MUCGPT allows configuration of MCP sources, for which tools are fetched and can be called.
Configure MCP in `core.config.yaml` under the `MCP` section:
```yaml
MCP:
SOURCES:
"":
url: "http://mcpdoc-server:8088/sse"
forward_token: true
transport: "sse"
CACHE_TTL: 43200 # seconds, default: 12h
```
Or via environment variable:
```bash
MUCGPT_CORE_MCP__SOURCES='{"": {"url": "...", "forward_token": true, "transport": "sse"}}'
MUCGPT_CORE_MCP__CACHE_TTL=43200
```
- `SOURCES`: Map of MCP source configurations.
- ``: Unique id of one MCP source.
- `url`: URL of the MCP endpoint.
- `forward_token`: If the OAuth 2.0 JWT token used for authentication should be forwarded to the MCP endpoint.
- `transport`: Transport protocol (`"sse"` or `"streamable_http"`), see
- `CACHE_TTL`: Time-to-live of cached MCP tools in seconds (default: 12h).
## 🐋 Run with Docker
The Docker Compose setup is for isolated local development and demos only. Do not expose it as a production or test deployment and do not reuse its demo credentials or other local defaults. Production and test systems must use a separate, non-public and appropriately secured deployment procedure.
See the [stack README](../stack/README.md) for the local Docker Compose setup instructions, including:
- Quick start guide
- Service architecture and ports
- Local Compose and local development modes
- Common commands and troubleshooting