Restrict which source addresses may call /mcp with a list of IPs/CIDRs
(IPv4 and IPv6). The check runs before token authentication, so a source
that is not listed is refused with 403 even when it holds a valid token.
An empty list keeps the previous behaviour (any source).
Behind a reverse proxy the TCP peer is always the proxy, so proxies can be
registered as trusted: for requests from them the client is the rightmost
X-Forwarded-For hop that is not itself a trusted proxy. Without a trusted
proxy the header is ignored, so a caller cannot claim an allowed address.
- A stored configuration that cannot be read or parsed refuses requests
instead of falling back to no restriction.
- The audit log records the resolved client address.
- The settings API reports the address the server sees for the caller.
- The allowlist applies to /mcp only; the web UI and admin API are
unaffected.
Refs RuoJi6/ARTEX#144
Add a stateless Streamable HTTP endpoint at /mcp that lets external agents
list tasks and findings, create tasks, pause/resume them and add hints.
- Access tokens (api_tokens): scopes (read, task:create, task:control),
optional company restriction, task quotas, expiry, revocation. Only the
SHA-256 is stored; the plaintext is returned once.
- /mcp authenticates with access tokens only. It sits outside the HTTP Basic
Auth gate and rejects Basic credentials and the admin JWT.
- Whitelisted tools only; nothing that edits tools, skills, MCP servers,
workspace files or settings is exposed.
- Every tools/call is audited (mcp_audit_log), refusals included.
- POST /api/tasks and the MCP spawn_task tool now share one creation path.
- Settings card for the switch, token management and the call audit.
- Off by default.
Refs RuoJi6/ARTEX#144
tool_input rules were only matched against the raw JSON of the tool call.
JSON escapes newlines and tabs, so a multi-line command reaches the rules as
`cd /tmp\nrm -rf /var/www`. There is no word boundary between the `n` of `\n`
and `rm`, so the built-in `\brm\b` / `\bmkfs\b` / `\bDROP ...` rules never
fire on a dangerous command that starts a new line (heredocs, small scripts).
Quotes (`\"`) and, for Go-encoded input, & < > (`&` etc.) have the same
problem.
Decode the input once per Match and also try each string value. The raw
JSON is still checked first, so existing rules written against the JSON
form keep matching; the change can only add matches.