Deploy AI Integration
AI Integration
Overview
The AI integration ships as two independent binaries built from one Go module, communicating over MCP Streamable HTTP:
- mcp-server - a single-tenant, read-only MCP server. It exposes 69 read-only tools over Archibus/WebCentral data (space, maintenance/work requests, assets, people, move management, leases) and proxies every tool call to WebCentral's typed REST endpoints (
/api/v1/mcp/...) using an OAuth2 client-credentials service account. It has no database and calls no LLM. - orchestrator - the AI host. It serves
POST /api/v1/ai/queryandPOST /api/v1/ai/chat, which WebCentral's "Ask AI" drawer and work-request AI-summary feature call. It drives an agent loop against a configured LLM provider (Anthropic or Azure OpenAI) and is itself an MCP client of mcp-server - it never talks to WebCentral directly.
Neither service uses a database. Configuration is entirely environment variables; each service authenticates its single caller with one static bearer token.
These two services can run on the same host or two different hosts and the only requirement is that orchestrator can reach mcp-server over HTTP, and that WebCentral can reach orchestrator over HTTP.

Contents
- Prerequisites
- Obtain and verify the release archives
- Verify the checksum before installing
- Environment configuration
- mcp-server
- orchestrator
- Generating token values for MCP_INBOUND_TOKEN / ORCH_INBOUND_TOKEN
- Install as an unattended background service
- Linux — system
- macOS — launchd
- Windows — WinSW
- Logging configuration
- WebCentral integration
- Set the ai.properties values
- Verify the deployment
- Troubleshooting
- Service won't start
- 401 / authentication errors between the two services
- mcp-server can't reach WebCentral
- orchestrator / LLM provider errors
- WebCentral integration issues
- General diagnostic steps
Prerequisites
Ensure the following are in place before starting:
- A target host (or two) running Linux, macOS, or Windows, with network access to the WebCentral instance and outbound access to your chosen LLM provider (Anthropic or Azure OpenAI)
- An Archibus/WebCentral OAuth2 service account (client ID + client secret) with a token endpoint, scoped for the webcentral-platform-mcp REST module (
/api/v1/mcp/...). The token must include thearchibus.mcp.readscope. - An LLM provider API key, such as Anthropic, or an Azure OpenAI endpoint + deployment
- Administrative/elevated access on the target host, to install a systemd unit (Linux), a launchd daemon (macOS), or a Windows service via WinSW (Windows)
No Go toolchain, CGO, or external system libraries are required to run the services, and you only need Go/GoReleaser if you intend to build the release archives yourself rather than using a pre-built release.
Obtain and verify the release archives
Each tagged release produces, per binary, one archive per platform plus a single checksum manifest.
| OS | Arch | Archive format |
|---|---|---|
| Linux | amd64, arm64 | .tar.gz (one archive per arch) |
| macOS | universal (amd64 + arm64 in one binary) | .tar.gz (single archive covers both Mac architectures) |
|
Windows |
amd64 | .zip |
That is 4 archives per binary (8 total), named like mcp-server_VERSION_OS_ARCH.tar.gz / orchestrator_VERSION_OS_ARCH.tar.gz, plus one checksums.txt covering all of them.
Each archive already bundles the README.md, .env.example, the deployment docs, and the full service-template tree for all 3 Operating Systems (OS) therefore you only need to pick out the template relevant to your platform.
Verify the checksum before installing
Verify every archive against checksums.txt before extracting or running it as this confirms the download completed correctly and wasn't tampered with in transit. Both files must be in the same directory.
| Platform | Command |
|---|---|
|
Linux |
sha256sum -c checksums.txt --ignore-missing |
| macOS | shasum -a 256 -c checksums.txt --ignore-missing |
| Windows (PowerShell) |
compared against the matching line in checksums.txt |
| Windows (cmd) |
compared against the matching line in checksums.txt |
If a hash doesn't match: don't run the binary then re-download both files from the original source and check again.
Environment configuration
Both binaries are configured entirely from environment variables there is no config file and no database. Copy .env.example from the archive as a starting point for each service's env file.
mcp-server
| Variable | Required | Default | Description |
|---|---|---|---|
|
|
No |
|
HTTP listen address |
|
|
Yes | — | Static bearer the orchestrator must present on /mcp |
|
|
Yes | — | WebCentral base URL |
|
|
Yes | — | OAuth2 token endpoint |
|
|
Yes | — | Service-account client ID |
|
|
Yes | — | Service-account client secret |
|
|
No | — | Optional OAuth2 audience parameter |
|
|
No | OS-specific, see section 6 | Rotating log file path |
|
|
No | 100 |
Rotate once the active log file reaches this size (MB) |
|
|
No | 5 |
Number of rotated log files to retain |
|
|
No | 30 |
Delete rotated log files older than this |
|
|
No | false | gzip rotated log files |
orchestrator
| Variable | Required | Default | Description |
|---|---|---|---|
|
|
No | :8090 |
HTTP listen address |
|
|
Yes | — | Static bearer WebCentral must present on the AI endpoints |
|
|
Yes | — |
Base URL of mcp-server e.g.
|
|
|
Yes | — | Bearer sent to mcp-server must equal its MCP_INBOUND_TOKEN |
|
|
Yes | — | anthropic or azure_openai |
|
|
Yes | — | Provider API key |
|
|
Only for Azure | — | Azure OpenAI endpoint (required when LLM_PROVIDER=azure_openai) |
|
|
Only for Azure | — | Azure deployment name (required when LLM_PROVIDER=azure_openai) |
|
|
No | claude-sonnet-4-6 |
Model name |
|
|
No | 8 |
Max agent-loop round-trips |
|
|
No | OS-specific, see section 6 | Rotating log file path |
|
|
No | 100 |
Rotate when the active log file reaches this size (MB) |
|
|
No | 5 |
Number of rotated log files to retain |
|
|
No | 30 |
Delete rotated log files older than this |
|
|
No | false |
gzip rotated log files |
MCP_INBOUND_TOKEN (mcp-server) and MCP_OUTBOUND_TOKEN (orchestrator) must hold the same shared secret. Make sure to set both env files to one generated value. A binary started with required variables missing logs the full list of missing vars and exits non-zero, so a misconfiguration fails fast and visibly rather than starting in a broken state.
Generating token values for MCP_INBOUND_TOKEN / ORCH_INBOUND_TOKEN
MCP_INBOUND_TOKEN and ORCH_INBOUND_TOKEN are not issued by Archibus; they are opaque static bearer secrets the customer generates and assigns themselves, purely to authenticate calls between these two services and from Web Central. Any sufficiently long random string works; there is no token-issuing endpoint or format requirement to satisfy.
Two distinct secrets are needed:
- One shared value for
MCP_INBOUND_TOKEN(mcp-server) andMCP_OUTBOUND_TOKEN(orchestrator) - These two must be set to the exact same string. - A separate value for
ORCH_INBOUND_TOKEN(orchestrator) - This is also what you set as WebCentral's ai.properties archibus.ai.apiKey (see Web Central Integration below).
Generate each one as a long random string (32 bytes / 256 bits of randomness is a reasonable minimum) using whatever tool is available on your platform:
| Platform | Command |
|---|---|
|
Linux / macOS |
openssl rand -hex 32 |
| Windows (PowerShell) | -join ((1..32 | ForEach-Object { "{0:x2}" -f (Get-Random -Maximum 256) })) |
|
Any platform with Python 3 |
python3 -c "import secrets; print(secrets.token_hex(32))" |
Paste the generated value straight into the relevant env file(s) with no surrounding whitespace or quotes. Treat these like any other credential: don't commit them to source control, and restrict read access on whichever env file, systemd EnvironmentFile=, launchd wrapper script, or WinSW service XML holds them to the service account and administrators only.
Install as an unattended background service
Both binaries are plain console executables with no built-in service/daemon code. Each platform's native service manager supervises the process (auto-start on boot, restart on crash). Service unit/plist/XML templates ship inside every release archive under service-templates/.
Linux — system
Templates: service-templates/linux/archibus-mcp-server.service, archibus-orchestrator.service.
- Extract the archive, for example.
/opt/archibus-mcp-server/ - Create the service account referenced by the unit's User= (or edit it to an existing one), for example
useradd --system --no-create-home archibus-mcp - Write the
envfile the unit expects, for example,/etc/archibus-mcp-server/mcp-server.env(plain KEY=value lines, same variable names as.env.example). Repeat for the orchestrator's env file. - Ensure the service account can write the log directory, either create
/var/log/mcp-serverandchownit to the service account, or setLOG_FILEin theenvfile to a path it already owns. - Copy the unit files to
/etc/systemd/system/, then reload the daemon and enable both units:
sudo systemctl daemon-reload sudo systemctl enable --now archibus-mcp-server sudo systemctl enable --now archibus-orchestrator
systemctlgives boot-start and restart-on-failure (Restart=on-failure in the unit) for free.systemctl status archibus-mcp-serverandjournalctl -u archibus-mcp-serverremain available even though the app also keeps its own file log.
Update: stop the service, replace the binary, start the service.
Uninstall: disable the service, remove the unit file, reload the daemon.
macOS — launchd
Templates:
service-templates/macos/- 2 plists (
com.eptura.archibus-mcp-server.plist,com.eptura.archibus-orchestrator.plist) - 2 wrapper-script templates
The launchd plists have no equivalent of systemd's EnvironmentFile=, so each plist's ProgramArguments points at a small wrapper script that sources the env file and execs the real binary.
- Extract the archive, for example,
/opt/archibus-mcp-server/ - Copy
launch-mcp-server.sh.templateto/opt/archibus-mcp-server/launch-mcp-server.sh(and the orchestrator counterpart), and mark both executable. - Write the
envfiles the wrapper scripts source (mcp-server.env, orchestrator.env). - Choose daemon vs. agent:
/Library/LaunchDaemons/(system-wide, runs at boot with no user logged in, requires elevated access) is the right choice for an unattended server;~/Library/LaunchAgents/(per-user, no elevated access needed) only runs while that user is logged in. - Copy the plist(s) into the chosen directory, then load both:
sudo launchctl load /Library/LaunchDaemons/com.eptura.archibus-mcp-server.plist sudo launchctl load /Library/LaunchDaemons/com.eptura.archibus-orchestrator.plist
Note, drop the elevated-access prefix and use the LaunchAgents path for the per-user variant.
Update: unload, replace the binary, load again.
Uninstall: unload, then remove the plist.
Windows — WinSW
Templates:
service-templates/windows/mcp-server-service.xml, orchestrator-service.xml
Windows has no built-in systemd/launchd equivalent, so this uses WinSW which is a small, well-established wrapper for running an existing executable as a Windows Service. No in-binary Windows service code is required.
- Extract the archive to
C:\archibus-mcp-server\ - Download WinSW's latest executable and rename it to
archibus-mcp-server.exe(WinSW pairs aname.exewith a matchingname.xml), placed next tomcp-server.exe. Repeat with archibus-orchestrator.exe next to orchestrator.exe. - Copy
mcp-server-service.xmltoarchibus-mcp-server.xmlalongside the renamed WinSW exe (and the orchestrator counterpart), and fill in the env values in the XML. - From an elevated prompt, install and start both services:
archibus-mcp-server.exe install archibus-mcp-server.exe start archibus-orchestrator.exe install archibus-orchestrator.exe start
- Both services are now visible in
services.msc, with onfailure-triggered restart configured in the XML. The XML deliberately disables WinSW's own log capture and the app writes its own rotating file log (see Logging configuration below); don't double-log.
Update: stop the service, replace the binary, start the service.
Uninstall: stop the service, then uninstall it.
Logging configuration
Both binaries share one logging implementation. They always write a rotating JSON log file, and additionally echo the same lines to stdout whenever the process has an interactive terminal attached. Running a binary by hand shows live output; running it as a service writes only to the file.
| OS | Default log path (when LOG_FILE is unset) |
|---|---|
|
Linux |
/var/log/<binary-name>/<binary-name>.log |
|
macOS |
Falls back to |
| Windows | %ProgramData%\<binary-name>\logs\<binary-name>.log |
Where:
<binary-name> is mcp-server or orchestrator and each logs to its own file even when both run on the same host.
Permissions:
Any account the service runs as (systemd User=, the launchd daemon/agent's owner, or the Windows service account) must be able to create/write that directory. If it cannot set the LOG_FILE explicitly to a path that the account owns, then for an explicit override, there is no silent fallback: an unwritable explicit path fails fast at startup with a clear error, so a misconfigured override is never masked. Note that macOS is the only platform with an automatic fallback, and only for the OS default path, never for an explicit override.
Verify logging is working by tailing the log path where it writes structured JSON lines; a JSON pretty-printer helps readability.
WebCentral integration
WebCentral's "Ask AI" drawer and WR-summary FAB call the orchestrator, proxied through /core/api/v1/ai/
When the orchestrator is running and reachable from the WebCentral host:
- In Web Central's
ai.propertiesset thearchibus.ai.baseUrlto the orchestrator's URL e.g.http://orchestrator-host:8090. - Set the
archibus.ai.apiKeyto the orchestrator'sORCH_INBOUND_TOKENvalue.
This is an operational configuration change only and no WebCentral code change is required.
Set the ai.properties values
Both properties live in a single file in the WebCentral project: WEB-INF/config/ai.properties. It ships with both keys present but empty:
# Base URL of the AI orchestrator service. # Example: archibus.ai.baseUrl=http://localhost:8090 archibus.ai.baseUrl= # Bearer token presented to the orchestrator on each request. # Example: archibus.ai.apiKey=your-base64-token-here
Where:
| Property | Required | Description |
|---|---|---|
|
|
Yes |
Base URL of the running orchestrator instance, for example:
Must be reachable from the WebCentral application server. |
|
|
Yes | Must equal the orchestrator's own ORCH_INBOUND_TOKEN value exactly (see Generate token values, above) and this is the bearer WebCentral presents on every call to /api/v1/ai/query and /api/v1/ai/chat |
Verify the deployment
Each service exposes an unauthenticated liveness probe at /health on its listen port (mcp-server defaults to 8085, orchestrator to 8090); a healthy response is a JSON object with status ok.
Then confirm the 2 services can actually talk to each other and to Web Central by exercising the orchestrator's AI endpoint directly with an authenticated POST to /api/v1/ai/query, sending a simple free-form question in the request body and the ORCH_INBOUND_TOKEN as a bearer credential. A successful response looks like an answer field plus an iterations count.
Finally, confirm the version actually running matches what you deployed where both binaries log their version on startup and tail each service's log file per section 6 to confirm structured JSON lines are being written.
Troubleshooting
Below details common configuration issues.
Note that both binaries fail fast and log clearly on startup misconfiguration rather than starting in a half-working state. The log file (or console, if run interactively) is the first place to look for any of these.
Service won't start
|
Symptom |
Likely cause |
Fix |
|---|---|---|
|
Process exits immediately; log shows a list of missing environment variables |
One or more required vars weren't set in the env file the service reads |
Check the exact var names logged against the tables in Environment configuration above. Cross-check the |
|
|
Another process (often a leftover manual run) already holds the configured LISTEN_ADDR port |
Find and stop the other process, or set LISTEN_ADDR to a free port on both this service and whatever calls it (MCP_SERVER_URL / WebCentral's ai.properties) |
|
Fails at startup with a log-directory permission error, even though |
The account the service runs as can't create the OS-default log directory (common for a non-root systemd User=, or a Windows service account without %ProgramData% write access) |
Set macOS is the only OS with an automatic fallback for the default path, and only when |
|
Fails at startup with a log-directory permission error, and |
The explicit path (or a parent directory) isn't writable by the service account and this never falls back silently, by design. | Grant the service account write access to that path, or point LOG_FILE at a directory it already owns. |
|
|
The binary is crashing on every start. Usually a config error being masked by how fast |
To see the actual startup error run:
Or run the binary by hand with the same |
401 / authentication errors between the two services
|
Symptom |
Likely cause |
Fix |
|---|---|---|
|
orchestrator logs 401s when calling mcp-server; tool calls in |
|
Compare both values byte-for-byte (watch for trailing whitespace/newlines picked up from copy-paste into an env file); restart both services after fixing. |
|
WebCentral's "Ask AI" drawer / WR-summary FAB gets a 401 or doesn't respond. |
The bearer WebCentral sends doesn't match the orchestrator's ORCH_INBOUND_TOKEN |
Confirm WebCentral's |
mcp-server can't reach WebCentral
|
Symptom |
Likely cause |
Fix |
|---|---|---|
|
mcp-server logs OAuth2 token-fetch failures on startup or on each tool call. |
ARCHIBUS_TOKEN_URL, ARCHIBUS_CLIENT_ID, or ARCHIBUS_CLIENT_SECRET is wrong, or the service account was disabled/rotated on the WebCentral side |
Re-verify the service account credentials directly against the token endpoint (e.g. with a manual OAuth2 client-credentials request) before assuming the binary's config is at fault. |
|
Tool calls return 403/permission errors even though the OAuth2 token is obtained successfully. |
The service account lacks the WebCentral role/permission needed for the webcentral-platform-mcp REST module (/api/v1/mcp/...) |
Have a WebCentral admin confirm the service account is scoped for that module |
|
Tool calls hang or time out. |
|
Confirm network reachability from the mcp-server host to ARCHIBUS_BASE_URL independently (e.g. a simple HTTP request to a known WebCentral endpoint) before looking further into the binary's config. |
orchestrator / LLM provider errors
|
Symptom |
Likely cause |
Fix |
|---|---|---|
/api/v1/ai/query or /api/v1/ai/chat returns HTTP 502 |
The configured LLM provider call itself failed. Invalid/expired Wrong |
Check the orchestrator's log for the underlying provider error (it's included in the log line even though the HTTP response body is generic); verify the key/endpoint/deployment directly against the provider's own tooling. |
|
Startup fails citing missing Azure-specific configuration. |
|
Set both, or switch |
|
Answers are generic, ignore Archibus data, or the loop seems to give up early. |
Usually not a config problem. Check |
WebCentral integration issues
|
Symptom |
Likely cause |
Fix |
|---|---|---|
|
"Ask AI" drawer or WR-summary FAB doesn't appear or errors immediately. |
|
From the WebCentral host, confirm you can reach |
|
Feature works intermittently or times out under load. |
Network path between WebCentral and the orchestrator (or orchestrator and mcp-server) has latency/instability, or the LLM provider is rate-limiting. |
Check each hop's own logs for timeouts; consider colocating the two services with WebCentral to remove a network hop. |
General diagnostic steps
- Confirm both binaries are running the version you deployed and check the version line each logs on startup.
- Check each service's
/healthendpoint directly (see Verify the deployment above) to isolate whether a failure is in the service itself or in something calling it. - Tail the rotating log file (see Logging configuration above) rather than relying on the service manager's own log capture. The app's own JSON log line provides more details than a generic "service failed" message from
systemd/launchd/WinSW. - Change one variable at a time and restart. The token mismatches, wrong URLs, and missing Azure-only variables account for the large majority of configuration issues seen in practice.
