Security
Security model: RLS, RBAC, audit logging, and rate limiting
Security
ATOMS MCP Server is designed for regulated industries where security and auditability are non-negotiable.
Row Level Security (RLS)
All database queries execute through the user's JWT : never a service role key. Supabase RLS policies ensure:
- Users can only access projects belonging to their organization
- No cross-tenant data leakage is possible at the database level
- Even if the MCP server code had a bug, RLS would prevent unauthorized access
Role-Based Access Control (RBAC)
Access is controlled at the organization level:
| Role | Read | Write | Admin |
|---|---|---|---|
| Viewer | All read tools | Rejected with clear error | No |
| Editor | All read tools | All write tools | No |
| Admin | All read tools | All write tools | Yes |
Write operations (atoms_create_item, atoms_update_item, atoms_delete_item, atoms_link_items, atoms_bulk_import, atoms_record_test_result) check the user's role before executing.
Audit logging
Every MCP tool call is logged to the mcp_audit_log table:
| Field | Description |
|---|---|
tool_name | Which tool was called |
params | Sanitized input parameters |
status | Success or error |
duration_ms | Response time |
user_id | Who made the call |
project_id | Which project was accessed |
session_id | Groups related calls in a session |
client_name | Which AI assistant (Claude, Cursor, etc.) |
Actor attribution
Change history entries include an actor field:
"user": Change made through the ATOMS web app"mcp_claude": Change made through the MCP server
This lets teams distinguish human edits from AI-generated changes in compliance reviews.
Audit logging is fire-and-forget : it never blocks or slows down tool responses.
Rate limiting
A sliding window rate limiter protects the API:
- Default: 60 requests per minute per user
- Algorithm: Sliding window (60-second window)
- Override: Set
ATOMS_RATE_LIMIT_RPMenvironment variable - Response: Returns
retryAfterSecondswhen limit is exceeded
Token security
- OAuth 2.1 with PKCE : no client secrets transmitted
- Credentials stored at
~/.atoms/credentials.jsonwith0600permissions - Automatic token refresh (60-second buffer before expiry)
- No secrets embedded in the npm package
- The published anon key only grants API gateway access : zero data access without a valid JWT
Input validation
All inputs from AI assistants are validated before processing:
- UUIDs : Strict format check for project IDs
- Item IDs : Must match
[A-Z]+-\d{3}pattern (e.g.,REQ-001) - Text fields : Sanitized to prevent injection (`< > & ; ' " ``)
- Limits : Bounded ranges prevent resource exhaustion
- Zod schemas : Every tool input is validated against a Zod schema
Soft deletes
Items are never physically removed from the database. atoms_delete_item sets a deleted_at timestamp, preserving the full audit trail for compliance.