Skip to content

Configuration Reference

All configuration is environment variables, validated with zod at boot. An invalid or missing required value throws before the server listens, listing every problem at once — there is no partially-configured start.

Copy .env.example and fill it in:

bash
cp .env.example .env

Server

VariableRequiredDefaultNotes
PORTno5173One port for every mode: the Vite dev server, the built server and the Docker image all listen here.
APP_URLnohttp://localhost:5173Public base URL. The OAuth issuer, and the base of the Google redirect URI. Must match the URL you actually open.
NODE_ENVnodevelopmentproduction in the image.

APP_URL is the single most consequential value. It is what MCP clients discover the authorization server from, and {APP_URL}/auth/google/callback is what Google matches as an exact string. A trailing slash is stripped; a mismatch produces redirect_uri_mismatch.

Database

VariableRequiredDefaultNotes
DATABASE_URLyesPostgres connection string. docker compose ignores this and builds its own URL from the bundled db service.
POSTGRES_PASSWORDcompose onlyfinance_mcpPassword for the bundled compose database.

Sessions and access

VariableRequiredDefaultNotes
SESSION_SECRETyes32+ bytes. openssl rand -base64 32. Rotating it signs everyone out.
GOOGLE_CLIENT_IDyesSee Google OAuth Setup.
GOOGLE_CLIENT_SECRETyes
ADMIN_EMAILSyes on a fresh DBComma-separated emails seeded as active admins at boot.

Access is invitation-only: an email that is neither in ADMIN_EMAILS nor invited by an admin cannot sign in, even with a valid Google account.

Upstream data sources

VariableRequiredNotes
SEC_EDGAR_CONTACT_EMAILrecommendedEDGAR requires a descriptive User-Agent with a contact address on every request, or it starts rejecting them. A maintainer address is compiled in as the default — set your own for any real deployment.
COINGECKO_API_KEYnocryptoTickers uses CoinGecko's public tier, which needs no key. A demo key only raises the rate limit.
ISHARES_PROXY_BASEnoOrigin of a relay for the two iShares endpoints, no trailing slash. Set only when this host is blocked at Akamai's edge — see When iShares Is Blocked. Unset, iShares is fetched direct.
ISHARES_PROXY_TOKENwith ISHARES_PROXY_BASEBearer token for that relay. Both halves are required; one without the other stays direct.

Yahoo Finance needs no credentials: the data is read through the unofficial yahoo-finance2 integration and may be delayed, unavailable or removed for delisted symbols.

Precedence

The server loads .env via process.loadEnvFile() and falls back to the real environment when no file exists, so container environments (which set real variables and ship no .env) work unchanged.

Market data is delayed and provided as-is. Not investment advice.