<!--
SPDX-FileCopyrightText: Amolith <amolith@secluded.site>

SPDX-License-Identifier: CC0-1.0
-->

# sb-mcp

SilverBullet MCP server, this repo uses jujutsu over git and imperative, kernel-style commits over Conventional Commits.

We also maintain the SilverBullet agent skill (`SKILL.md`). It and the MCP server are separate surfaces: do not make the skill reference the MCP server, and do not make MCP prose reference the skill. When changing prose in either surface, consider whether the underlying rule applies to both, and if so, update each independently.

## Commands

```sh
mise run fmt ::: lint ::: build # all three in parallel, run after every edit
mise run check # fmt, lint, build, AND vet, vuln, and test
```

## Landmines

- **`print()` is silently swallowed** in the Runtime API. Always use `return` to send results back from `execute_lua`. No error, no warning — just empty output.
- **Space Lua is camelCase**, not snake_case. All built-in functions (`space.readPage`, `space.writePage`) use camelCase. Writing `space.read_page` will fail.
- **Bearer auth and password auth coexist** — `SB_TOKEN` sets `Authorization: Bearer ...`, while `SB_USER`/`SB_PASS` logs in via `POST /.auth` and sends a session `Cookie`. They use different headers, no override. For proxy auth (e.g. Exe.dev), use SB password authentication with Exe Bearer auth or SB Bearer auth with Exe HTTP Basic credentials embedded in `SB_URL` (`https://user:pass@host`).
- **Timeout clamping**: Lua timeouts <1 are clamped to 1, >21600 clamped to 21600. No error raised; the value silently changes.
- **`DisableLocalhostProtection: true`** is set on the StreamableHTTP handler because nginx proxies with the external Host header. Removing it will cause 403s from the SDK's DNS rebinding protection.
