AtlatestRepositoryfolio

folio / tree / docsshared-http.md

Read it rendered

1# Shared HTTP server
2
3Run one Folio process for multiple local MCP clients:
4
5```sh
6FOLIO_ROOT="$HOME/folio" folio serve --http 18765 \
7 --token-file "$HOME/.config/folio/http.token"
8```
9
10The listener binds only `127.0.0.1`. Clients use `/mcp` with an
11`Authorization: Bearer TOKEN` header. The token file must have no group or
12other permissions, contain one printable ASCII token of at least 32 characters,
13and stay outside client configuration files. Unauthenticated requests return 401
14before protocol dispatch. The five-minute HTTP timeout applies to request
15parsing and idle connections. Dispatched tool streams leave that timeout
16sweep: there is no server-side tool deadline, and a hung tool can hold its
17socket indefinitely. Clients should allow a six-minute tool timeout.
18`folio/rebuild-index` is refused immediately over HTTP; run explicit full
19rebuilds through a separate stdio maintenance session. An initial HTTP start
20with an empty or upgraded index can take several minutes before it listens.
21Wait for readiness before connecting clients.
23Stdio remains the default. `--http` and `--stdio` are mutually exclusive.
24`--web` and `--web-port PORT` are accepted with one stderr deprecation warning
25and ignored; the old local note viewer has been removed.
27## Storage and indexing
29Validated HTTP tool calls run in separate cooperative tasks. A writer waiting
30for another process's store lock leaves independent reads free to complete.
31CPU-bound calls still share one thread; they are not preempted. Mutating tool
32handlers are serialized through their index flush, including inbox reads that
33may backfill ids. Other read tools do not enter that writer queue.
34Tools taking over ten milliseconds allow socket polling before JSON encoding
35with a one-millisecond cooperative pause; faster tools can reply immediately.
36Cold file-cache fills and task-block parsing also pause between work units
37after about ten milliseconds, so a first status, inbox or task-notes call can
38populate its caches while independent reads proceed. Cache hits bypass these
39checkpoints; a fingerprint recheck after a pause prevents caching a value
40whose file changed meanwhile. Individual native operations still occupy the
41thread until they return, so this is not a hard response-time bound.
42Note listings skip unused full-text snippets, and
43updates locate existing full-text rows through their indexed names.
45Note and project mutations use the cross-process SQLite store lock. Index
46maintenance never takes that lock: each indexed document is replaced in its
47own transaction. A per-connection channel mutex keeps concurrent index tasks
48from sharing a transaction, and a fingerprint captured before reading lets a later census
49repair stale results after concurrent edits. Files are replaced atomically. Read-only
50tools retain their direct read path. A failed index refresh after a saved write
51is logged without turning that successful write into a failed tool call.
53HTTP index reads use a separate SQLite connection from census and writes, so
54they cannot see that connection's uncommitted rows. A read concurrent with a
55write may finish first and see the previous committed state. A read sent after
56the write reply sees its committed index update under the existing write-through
57and census-retry rules. SQLite consistency is per query and Markdown replacement
58is atomic per file; tools have no global snapshot across files and index queries.
59Stdio retains one connection and the same cross-process writer coordination.
61HTTP tool replies are ordinary JSON-RPC JSON documents sent with chunked
62framing and `Connection: close`, using one connection per tool call with no
63pipelining after a `tools/call`. Early validation retains its HTTP errors; an
64unexpected failure after response headers are sent becomes a JSON-RPC internal error carrying the same
65request id. Clients must consume the complete body before decoding it.
67A metadata census runs every 15 seconds, reading content only for changed files.
68Signatures include inode, size and nanosecond timestamps. Files that cannot be
69read or parsed are retried when their fingerprint changes; database failures
70remain retryable on the next census. The initial census populates a new index,
71and `folio/rebuild-index` explicitly rebuilds all documents in stdio mode.
73## Supervision and clients
75[The Shepherd example](../examples/folio.scm) returns a user-service definition
76and a log-rotation service. It creates a private random token on first start,
77respawns Folio, and uses the XDG configuration/state directories. Set the
78executable and data-root arguments for your installation. Reuse an existing
79Shepherd log-rotation service rather than registering a second one.
81For clients with an optional HTTP configuration, probe the unauthenticated MCP
82URL at launch and expect 401. If the probe fails or returns another status,
83warn and generate the usual stdio configuration. Read the token into the client
84process environment; keep only its variable name in generated configuration.
86## Development status
88The 0.3.4 lock uses published sigil-json 0.16.2 (less encoding CPU), sigil-mcp
890.18.4 (opt-in deferred tools) and sigil-http 0.18.8, retaining the pinned
900.22.15 runtime family. Release builds and qualification use that public lock
91without dependency overrides. `dev-redirects.sgl` is optional development
92configuration, active only when explicitly selected through the CLI or
93`SIGIL_REDIRECTS`; do not enable it for release qualification.