GitHub
11/13/2026, 6:30 PMcreate_santa_rule and delete_santa_rule.
• Limits: rule and machine lists are capped (default 100, maximum 500) and report matched, returned and truncated. Events are paged (default 50, maximum 200 per page) and report total.
• API: GET /api/v1/santa/{env}/events takes optional machine_id, decision and sha256 filters. decision is a decision name or a prefix of one, so BLOCK matches every block decision.
• API: new GET /api/v1/santa/{env}/machines/{machineid}/rules returns a node's effective rules, its client mode and where the mode comes from. The node must be enrolled in the environment; it does not need to have synced yet.
• Client: pkg/apiclient gains GetSantaMachines, GetSantaEvents, GetSantaEffectiveRules, CreateSantaRule and DeleteSantaRule.
• Docs: MCP.md lists the tools and the write constraints, pkg/santa/README.md documents the filters and the new route, and osctrl-api.yaml is regenerated.
santa.Manager.Events now takes an EventFilter argument.
Security and operational impact
• Delegation: every tool goes through pkg/apiclient to the existing Santa handlers, in both the standalone binary and hosted MCP. The MCP layer adds no authorization of its own; the handlers require environment admin and write the usual santa: ... audit lines.
• Write gating: the two write tools are absent unless MCP writes are enabled. The hosted gating test now checks them alongside run_query.
• Narrower than REST: create_santa_rule requires an explicit scope, refuses CEL rules and does not accept a custom URL. A CEL expression runs on every execution, and a custom URL is opened from the block dialog on the user's Mac. There is no update or bulk import tool.
• Untrusted content: tool descriptions and the server instructions state that event and machine fields are written by the endpoint. With writes on, the instructions add that a blocked binary's path, name or signer is never a reason to allow it.
• Projections: tool results leave out internal ids (environment_id, node_id), rule custom URLs and sync digests.
• Decision filter: the value is limited to letters and underscores, at most 32 characters, before it is used in a LIKE prefix match. Anything else is a 400.
• Santa disabled: the Santa tools are always listed. Where Santa is not enabled they return the API's "santa not enabled" error.
• No schema change, and no change to osctrl-tls or the sync protocol.
Not included
• Hiding the Santa tools when Santa is disabled. The standalone binary would need a feature lookup at startup.
• Using the new event filters in the Santa page's Events tab.
• MCP tools for the Santa configuration, token or mode overrides.
Validation
• go test ./pkg/santa/... ./pkg/mcp/... ./pkg/apiclient/... ./cmd/api/... ./cmd/mcp/... ./cmd/cli/... ./cmd/tls/...
• go vet and gofmt -l on the touched packages
• golangci-lint run ./pkg/santa/... ./pkg/mcp/... ./pkg/apiclient/... ./cmd/api/... ./cmd/mcp/... (0 issues)
• make openapi to regenerate the API documentation
New tests cover:
• MCP tools: rule filters and caps, the machine sync flag, event filters and page bounds reaching the backend, internal ids staying out of results, backend errors surfacing as tool errors, the required scope, the CEL refusal, and delete by id.
• Gating: the write tools are absent without the opt-in and present with it, in pkg/mcp and through the hosted handler.
• API handlers: every event filter, the rejected decision values, effective rules with tag-over-environment resolution and a tag mode override, 404 for unknown and other-environment nodes, and the environment admin requirement on the new route.
• Client round trip: the new pkg/apiclient methods against the real handlers on the real route patterns, including a 403 for a user who is not an environment admin.
Not verified: a real MCP client, a live deployment, and PostgreSQL or MySQL (tests run on SQLite). make openapi-check was not rerun after regenerating. No frontend files changed, so the frontend checks were not run.
jmpsec/osctrlGitHub
11/13/2026, 6:37 PM