Ailimu.

Reference

Everything on this page is generated from the code by pnpm docs, and CI fails if it drifts. If it says something, that is what the build does.

Environment variables

Only FM_USER and FM_PASS are required.

Variable What it is
FM_USER, FM_PASS REQUIRED. The FileMaker account the connector logs in as. Needs the fmodata extended privilege to read tables, plus fmrest to expose scripts. Without them discovery returns 401. Credentials are read from the environment only. They are never written to the config file, so they stay out of backups and out of the hosted tier.
FM_USER_<SLUG>, FM_PASS_<SLUG> Several FileMaker files on one connector? Each is a "profile" with its own slug, its own /mcp/<slug> endpoint and its own token. Give a profile its own account by suffixing the slug in upper snake case; anything unset falls back to FM_USER / FM_PASS above, so a single-file setup needs nothing here. profile "sales-live" -> FM_USER_SALES_LIVE / FM_PASS_SALES_LIVE
FM_HOST, FM_DATABASE Optional. Prefills the wizard's Connection step. The wizard's own values win, and the published config is what the MCP endpoint actually uses at runtime. Must include the scheme and no trailing slash: it is used as a URL prefix, <FM_HOST>/fmi/data/vLatest/databases/<FM_DATABASE>
ADMIN_TOKEN, MCP_TOKEN Optional. Guards /admin and /mcp. Leave blank and the connector generates them on first run, prints them, and persists them on the config volume so they survive a restart. Set them here to pin your own values.
PORT Optional. Defaults to 8081.
CONFIG_DIR Leave CONFIG_DIR unset. Local default is ./.ailimu-config and the Docker image sets /config itself. Setting it here would override the volume path.

Credentials for several files

With more than one profile, each may have its own FileMaker account, named after the profile's slug in upper snake case, falling back to the unsuffixed pair:

FM_USER_SALES_LIVE=...
FM_PASS_SALES_LIVE=...

Credentials are read from the environment only. They are never written to the config file and never handled by the wizard, which is why adding a profile with its own account means editing .env and restarting.

Endpoints

Method Path Auth What
GET /healthz none Liveness. Returns {ok:true} and nothing about your data.
GET /docs none This manual, for the version you are running.
GET /admin admin token The setup wizard. The token is in the URL the connector prints on boot.
POST /mcp mcp token MCP endpoint. Serves the only profile when the connector holds exactly one.
POST /mcp/:profile profile token MCP endpoint for one profile, with its own token.
GET /admin/api/status admin token Credential readiness, defaults and the profile list.
GET /admin/api/profiles admin token Every profile this connector serves.
GET /admin/api/profiles/:slug admin token One profile's published config.
GET /admin/api/profiles/:slug/schema admin token The cached schema, so opening a profile costs no FileMaker read.
DELETE /admin/api/profiles/:slug admin token Delete a profile. Its endpoint stops immediately; FileMaker is untouched.
POST /admin/api/databases admin token Files this FileMaker server exposes to the account.
POST /admin/api/test-connection admin token Check the host, file and privileges before discovering.
POST /admin/api/discover admin token Read the schema: tables, row counts, scripts and layouts.
POST /admin/api/sample admin token Read a bounded row sample for named tables, to find unused columns.
GET /admin/api/config admin token The current config and the tools it generates.
PUT /admin/api/config admin token Publish. Takes effect immediately, with no restart.

/healthz and /docs are deliberately unauthenticated: one is a liveness probe that reveals nothing, the other is this manual.

Tools

A table called invoices and a script exposed as recalculate_totals produce:

Tool What it does
get_invoices One record by its identifier. Every readable field.
find_invoices Search. Returns the identifier plus the searchable fields, and the total match count.
describe_invoices The fields a search cannot filter on, and how this table links to others.
update_invoices Change a record. Only exists when writes are enabled and read-only is off.
recalculate_totals One exposed FileMaker script. Only exists when read-only is off.

Limits

Limit Value Why
Rows sampled per table 50 Enough to tell an always-empty column from a sparse one.
Sample cell budget 5000 FileMaker's OData returns malformed JSON past roughly 280KB, so a wide table gets fewer rows. A 208-column table samples 24 rows.
Concurrent FileMaker requests 8 Discovery is one request per table; unbounded would hammer the server.
Tool result budget 200KB Whole rows are dropped to fit, and the tool says how many.
Tables per sample request 500 A malformed request cannot turn into an unbounded scan.

Config file

One JSON file per profile, under profiles/ on the config volume. You should not need to edit it by hand, but it is plain JSON so you can read it and keep it in version control if you want to.

Field Type Default
tenantId string required
slug string optional
displayName string required
connection object required
connection.host string required
connection.database string required
connection.apiVersion string "vLatest"
connection.backend dataapi | odata "dataapi"
connection.scriptDatabase string optional
readOnly boolean true
resources array []
scripts array []
audit object {}
audit.enabled boolean true
audit.logWrites boolean true
audit.logReads boolean false
updatedAt string optional
lastDiscovered string optional

Known FileMaker behaviour

Things the FileMaker APIs do that Ailimu works around. They are listed here because they look like Ailimu bugs and are not: