AtlatestRenderedmarkdown

folio / tree / docsshared-http.md

Read the source

Readme

Shared HTTP server

Run one Folio process for multiple local MCP clients:

FOLIO_ROOT="$HOME/folio" folio serve --http 18765 \
  --token-file "$HOME/.config/folio/http.token"

The listener binds only 127.0.0.1. Clients use /mcp with an Authorization: Bearer TOKEN header. The token file must have no group or other permissions, contain one printable ASCII token of at least 32 characters, and stay outside client configuration files. Unauthenticated requests return 401 before protocol dispatch. The five-minute HTTP timeout applies to request parsing and idle connections. Dispatched tool streams leave that timeout sweep: there is no server-side tool deadline, and a hung tool can hold its socket indefinitely. Clients should allow a six-minute tool timeout. folio/rebuild-index is refused immediately over HTTP; run explicit full rebuilds through a separate stdio maintenance session. An initial HTTP start with an empty or upgraded index can take several minutes before it listens. Wait for readiness before connecting clients.

Stdio remains the default. --http and --stdio are mutually exclusive. --web and --web-port PORT are accepted with one stderr deprecation warning and ignored; the old local note viewer has been removed.

Storage and indexing

Validated HTTP tool calls run in separate cooperative tasks. A writer waiting for another process's store lock leaves independent reads free to complete. CPU-bound calls still share one thread; they are not preempted. Mutating tool handlers are serialized through their index flush, including inbox reads that may backfill ids. Other read tools do not enter that writer queue. Tools taking over ten milliseconds allow socket polling before JSON encoding with a one-millisecond cooperative pause; faster tools can reply immediately. Cold file-cache fills and task-block parsing also pause between work units after about ten milliseconds, so a first status, inbox or task-notes call can populate its caches while independent reads proceed. Cache hits bypass these checkpoints; a fingerprint recheck after a pause prevents caching a value whose file changed meanwhile. Individual native operations still occupy the thread until they return, so this is not a hard response-time bound. Note listings skip unused full-text snippets, and updates locate existing full-text rows through their indexed names.

Note and project mutations use the cross-process SQLite store lock. Index maintenance never takes that lock: each indexed document is replaced in its own transaction. A per-connection channel mutex keeps concurrent index tasks from sharing a transaction, and a fingerprint captured before reading lets a later census repair stale results after concurrent edits. Files are replaced atomically. Read-only tools retain their direct read path. A failed index refresh after a saved write is logged without turning that successful write into a failed tool call.

HTTP index reads use a separate SQLite connection from census and writes, so they cannot see that connection's uncommitted rows. A read concurrent with a write may finish first and see the previous committed state. A read sent after the write reply sees its committed index update under the existing write-through and census-retry rules. SQLite consistency is per query and Markdown replacement is atomic per file; tools have no global snapshot across files and index queries. Stdio retains one connection and the same cross-process writer coordination.

HTTP tool replies are ordinary JSON-RPC JSON documents sent with chunked framing and Connection: close, using one connection per tool call with no pipelining after a tools/call. Early validation retains its HTTP errors; an unexpected failure after response headers are sent becomes a JSON-RPC internal error carrying the same request id. Clients must consume the complete body before decoding it.

A metadata census runs every 15 seconds, reading content only for changed files. Signatures include inode, size and nanosecond timestamps. Files that cannot be read or parsed are retried when their fingerprint changes; database failures remain retryable on the next census. The initial census populates a new index, and folio/rebuild-index explicitly rebuilds all documents in stdio mode.

Supervision and clients

The Shepherd example returns a user-service definition and a log-rotation service. It creates a private random token on first start, respawns Folio, and uses the XDG configuration/state directories. Set the executable and data-root arguments for your installation. Reuse an existing Shepherd log-rotation service rather than registering a second one.

For clients with an optional HTTP configuration, probe the unauthenticated MCP URL at launch and expect 401. If the probe fails or returns another status, warn and generate the usual stdio configuration. Read the token into the client process environment; keep only its variable name in generated configuration.

Development status

The 0.3.4 lock uses published sigil-json 0.16.2 (less encoding CPU), sigil-mcp 0.18.4 (opt-in deferred tools) and sigil-http 0.18.8, retaining the pinned 0.22.15 runtime family. Release builds and qualification use that public lock without dependency overrides. dev-redirects.sgl is optional development configuration, active only when explicitly selected through the CLI or SIGIL_REDIRECTS; do not enable it for release qualification.