iso27001-mcp 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +1084 -0
- package/dist/index.js +36386 -0
- package/dist/seed/policy-templates/policy-templates/acceptable_use.md +97 -0
- package/dist/seed/policy-templates/policy-templates/access_control.md +92 -0
- package/dist/seed/policy-templates/policy-templates/asset_management.md +88 -0
- package/dist/seed/policy-templates/policy-templates/business_continuity.md +82 -0
- package/dist/seed/policy-templates/policy-templates/cryptography.md +90 -0
- package/dist/seed/policy-templates/policy-templates/data_classification.md +106 -0
- package/dist/seed/policy-templates/policy-templates/incident_response.md +87 -0
- package/dist/seed/policy-templates/policy-templates/information_security.md +94 -0
- package/dist/seed/policy-templates/policy-templates/physical_security.md +94 -0
- package/dist/seed/policy-templates/policy-templates/risk_management.md +98 -0
- package/dist/seed/policy-templates/policy-templates/secure_development.md +100 -0
- package/dist/seed/policy-templates/policy-templates/supplier_security.md +87 -0
- package/package.json +79 -0
package/README.md
ADDED
|
@@ -0,0 +1,1084 @@
|
|
|
1
|
+
# iso27001-mcp
|
|
2
|
+
|
|
3
|
+
A stateful [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server that gives Claude a complete ISO 27001:2022 Information Security Management System (ISMS). Ask Claude to run gap assessments, manage risks, generate policies, track evidence, and run audits — all backed by an encrypted SQLite database on your own machine.
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
Claude ──MCP──► iso27001-mcp ──► encrypted SQLite (isms.db)
|
|
7
|
+
│
|
|
8
|
+
├── 93 ISO 27001:2022 controls (seeded)
|
|
9
|
+
├── 114 ISO 27001:2013 controls (seeded)
|
|
10
|
+
├── Gap assessments & remediation roadmaps
|
|
11
|
+
├── Risk register & treatment plans
|
|
12
|
+
├── Policy documents (Mustache templates)
|
|
13
|
+
├── Statement of Applicability
|
|
14
|
+
├── Audit findings & corrective actions
|
|
15
|
+
└── Evidence tracking (+ Jira / GitHub)
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Table of Contents
|
|
21
|
+
|
|
22
|
+
- [Quick Start](#quick-start)
|
|
23
|
+
- [Use Cases](#use-cases)
|
|
24
|
+
- [Installation](#installation)
|
|
25
|
+
- [Configuration](#configuration)
|
|
26
|
+
- [Connecting to Claude](#connecting-to-claude)
|
|
27
|
+
- [Tools Reference](#tools-reference)
|
|
28
|
+
- [Architecture](#architecture)
|
|
29
|
+
- [Modes](#modes)
|
|
30
|
+
- [Integrations](#integrations)
|
|
31
|
+
- [Development](#development)
|
|
32
|
+
- [Security](#security)
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Quick Start
|
|
37
|
+
|
|
38
|
+
Get the server connected to Claude Desktop in five minutes.
|
|
39
|
+
|
|
40
|
+
### Prerequisites
|
|
41
|
+
|
|
42
|
+
- **Node.js ≥ 20.11.0** — use [nvm](https://github.com/nvm-sh/nvm) or [Volta](https://volta.sh)
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
node --version # should print v20.x or higher (not v22 — use v20 LTS)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
- **Build tools** — needed by the encrypted SQLite native module:
|
|
49
|
+
- **macOS:** `xcode-select --install`
|
|
50
|
+
- **Ubuntu/Debian:** `sudo apt-get install build-essential python3`
|
|
51
|
+
- **Windows:** `npm install --global windows-build-tools` (run as Administrator)
|
|
52
|
+
|
|
53
|
+
### Step 1 — Install from npm
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npm install -g iso27001-mcp
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
This installs the `iso27001-mcp` command globally. The native SQLite module downloads a prebuilt binary automatically on macOS and Linux x64; it compiles from source on other platforms.
|
|
60
|
+
|
|
61
|
+
### Step 2 — Generate secrets
|
|
62
|
+
|
|
63
|
+
Generate two random 32-byte secrets — these encrypt your database and sign your API keys:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
openssl rand -hex 32 # → copy as HMAC_SECRET
|
|
67
|
+
openssl rand -hex 32 # → copy as DB_ENCRYPTION_KEY
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Step 3 — Generate an API key
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
iso27001-mcp keygen --label "Me" --role admin \
|
|
74
|
+
HMAC_SECRET=<your_hmac_secret> \
|
|
75
|
+
DB_ENCRYPTION_KEY=<your_db_key> \
|
|
76
|
+
DB_PATH=$HOME/.iso27001/isms.db
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Or set the env vars in your shell first:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
export HMAC_SECRET=your_hmac_secret
|
|
83
|
+
export DB_ENCRYPTION_KEY=your_db_encryption_key
|
|
84
|
+
export DB_PATH=$HOME/.iso27001/isms.db
|
|
85
|
+
|
|
86
|
+
iso27001-mcp keygen --label "Me" --role admin
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The raw key (`iso27001_...`) is printed **once** — copy it immediately, it cannot be retrieved again.
|
|
90
|
+
|
|
91
|
+
### Step 4 — Add to Claude Desktop
|
|
92
|
+
|
|
93
|
+
Open your Claude Desktop config file:
|
|
94
|
+
|
|
95
|
+
- **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
96
|
+
- **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
|
|
97
|
+
|
|
98
|
+
```json
|
|
99
|
+
{
|
|
100
|
+
"mcpServers": {
|
|
101
|
+
"iso27001": {
|
|
102
|
+
"command": "iso27001-mcp",
|
|
103
|
+
"env": {
|
|
104
|
+
"HMAC_SECRET": "your_hmac_secret",
|
|
105
|
+
"DB_ENCRYPTION_KEY": "your_db_encryption_key",
|
|
106
|
+
"MCP_API_KEY": "iso27001_your_key_here",
|
|
107
|
+
"DB_PATH": "/Users/you/.iso27001/isms.db"
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Step 5 — Restart Claude Desktop and verify
|
|
115
|
+
|
|
116
|
+
Fully quit and reopen Claude Desktop. Then ask:
|
|
117
|
+
|
|
118
|
+
> *"Use get_server_info to check the server is running."*
|
|
119
|
+
|
|
120
|
+
You should get back version, uptime, and database stats confirming all 93 + 114 controls are seeded.
|
|
121
|
+
|
|
122
|
+
### First things to try
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
"Create a gap assessment for Acme Ltd covering all ISO 27001:2022 controls."
|
|
126
|
+
"Show me the gap summary for that assessment."
|
|
127
|
+
"Generate a remediation roadmap with a 26-week timeline."
|
|
128
|
+
"Create an information security policy for Acme Ltd. Owner: CISO. Effective from today."
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Use Cases
|
|
134
|
+
|
|
135
|
+
### 1 — Run a Gap Assessment
|
|
136
|
+
|
|
137
|
+
Ask Claude to assess your organisation against ISO 27001:2022, track the status of each control, and generate a prioritised remediation roadmap.
|
|
138
|
+
|
|
139
|
+
> *"Create a gap assessment for Acme Ltd covering all 2022 controls. Our scope is cloud infrastructure and development. Exclude physical security controls."*
|
|
140
|
+
|
|
141
|
+
Claude will create the assessment, pre-populate all 93 controls as `not_started`, and let you work through them one by one or in bulk. When you're done:
|
|
142
|
+
|
|
143
|
+
> *"Generate a remediation roadmap grouped by risk level. Give us 26 weeks to get to certification."*
|
|
144
|
+
|
|
145
|
+
The roadmap groups work by theme (Technological first), links controls to open risks, and assigns recommended due dates.
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
### 2 — Manage the Risk Register
|
|
150
|
+
|
|
151
|
+
Track information security risks end-to-end from identification through treatment.
|
|
152
|
+
|
|
153
|
+
> *"Register a new risk: our customer database is at risk from SQL injection due to unparameterised queries. Likelihood 4, impact 5."*
|
|
154
|
+
|
|
155
|
+
> *"Create a treatment plan to mitigate this risk. Link it to controls 8.26 and 8.28. Owner: head of engineering. Due: end of Q3."*
|
|
156
|
+
|
|
157
|
+
> *"Show me all critical and high risks that still have open treatment plans."*
|
|
158
|
+
|
|
159
|
+
Risk scores are computed automatically (likelihood × impact) and reflected in summaries and heatmaps without any manual input.
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
### 3 — Generate ISMS Policies
|
|
164
|
+
|
|
165
|
+
Generate a full suite of ISO 27001-aligned policy documents in seconds.
|
|
166
|
+
|
|
167
|
+
> *"Generate an information security policy for Acme Ltd. Scope: all cloud-hosted systems and remote employees. Owner: CISO. Effective from 1 June 2026."*
|
|
168
|
+
|
|
169
|
+
Policies are rendered from Mustache templates with automatic ISO clause and control mappings. Twelve policy types are included out of the box:
|
|
170
|
+
|
|
171
|
+
`information_security` · `access_control` · `risk_management` · `asset_management` · `incident_response` · `business_continuity` · `supplier_security` · `cryptography` · `physical_security` · `acceptable_use` · `data_classification` · `secure_development`
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
### 4 — Produce a Statement of Applicability
|
|
176
|
+
|
|
177
|
+
Generate an SoA directly from your gap assessment, pre-populated with inclusion/exclusion decisions and justifications.
|
|
178
|
+
|
|
179
|
+
> *"Generate a Statement of Applicability from assessment A-001. Export it as a CSV for the auditors."*
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
### 5 — Run Internal Audits
|
|
184
|
+
|
|
185
|
+
Plan audits, record findings (NCs, observations, OFIs), raise corrective action requests, and track effectiveness.
|
|
186
|
+
|
|
187
|
+
> *"Create an audit of our access control and cryptography controls. Auditor: Jane Smith. Planned for 15 June 2026."*
|
|
188
|
+
|
|
189
|
+
> *"Record a major non-conformity against clause 9.1: no evidence of ongoing monitoring of security objectives."*
|
|
190
|
+
|
|
191
|
+
> *"Raise a CAR for this finding. Owner: compliance manager. Due in 30 days."*
|
|
192
|
+
|
|
193
|
+
The server enforces ISO 27001:2022 Clause 10.1 — a corrective action cannot be closed unless `effectiveness_verified` is `true`.
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
### 6 — Track Evidence
|
|
198
|
+
|
|
199
|
+
Register evidence artefacts for each control, spot gaps, and link them directly to Jira tickets or GitHub issues.
|
|
200
|
+
|
|
201
|
+
> *"Show me all controls marked as implemented or partial that have no current evidence."*
|
|
202
|
+
|
|
203
|
+
> *"Register a screenshot of our firewall config as evidence for control 8.20. Collector: ops team. Expires in 12 months."*
|
|
204
|
+
|
|
205
|
+
> *"Link this evidence to a new Jira ticket in the SEC project: 'Firewall config screenshot — annual review'."*
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
### 7 — Query the Audit Log
|
|
210
|
+
|
|
211
|
+
Every tool call is logged in a tamper-evident audit trail. Admins can query it at any time.
|
|
212
|
+
|
|
213
|
+
> *"Show me all tool calls made in the last 7 days that resulted in an error."*
|
|
214
|
+
|
|
215
|
+
> *"List all API keys and when they were last used."*
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Installation
|
|
220
|
+
|
|
221
|
+
### Prerequisites
|
|
222
|
+
|
|
223
|
+
- **Node.js ≥ 20.11.0** — use [nvm](https://github.com/nvm-sh/nvm) or [Volta](https://volta.sh)
|
|
224
|
+
- **npm ≥ 10**
|
|
225
|
+
- **Build tools** for the native SQLite module:
|
|
226
|
+
- macOS: `xcode-select --install`
|
|
227
|
+
- Ubuntu/Debian: `sudo apt-get install build-essential python3`
|
|
228
|
+
- Windows: `npm install --global windows-build-tools` (run as Administrator)
|
|
229
|
+
|
|
230
|
+
### Step 1 — Install
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
npm install -g iso27001-mcp
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
The `iso27001-mcp` command is now available globally. The encrypted SQLite module (`better-sqlite3-multiple-ciphers`) downloads a prebuilt binary on supported platforms; it compiles from source if none is available.
|
|
237
|
+
|
|
238
|
+
**Run from source** (for development or to get the latest unreleased changes):
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
git clone https://github.com/Sushegaad/MCP-Server-for-ISO27001
|
|
242
|
+
cd iso27001-mcp
|
|
243
|
+
npm install
|
|
244
|
+
npm run build
|
|
245
|
+
# Use `node dist/index.js` instead of `iso27001-mcp` in all commands below
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Step 2 — Set Up Environment Variables
|
|
249
|
+
|
|
250
|
+
```bash
|
|
251
|
+
cp .env.example .env
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
Edit `.env` and fill in the two required secrets:
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
# Generate a 32-byte HMAC signing secret
|
|
258
|
+
openssl rand -hex 32 # → paste into HMAC_SECRET
|
|
259
|
+
|
|
260
|
+
# Generate a 32-byte AES-256 database encryption key
|
|
261
|
+
openssl rand -hex 32 # → paste into DB_ENCRYPTION_KEY
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
Full variable reference:
|
|
265
|
+
|
|
266
|
+
| Variable | Required | Default | Description |
|
|
267
|
+
|----------|----------|---------|-------------|
|
|
268
|
+
| `HMAC_SECRET` | ✅ | — | 32-byte hex secret for HMAC-signing API keys |
|
|
269
|
+
| `DB_ENCRYPTION_KEY` | ✅ | — | 32-byte hex key for AES-256 SQLite encryption |
|
|
270
|
+
| `DB_PATH` | | `./isms.db` | Path to the encrypted database file |
|
|
271
|
+
| `AUDIT_LOG_PATH` | | `./audit.log` | Path for the append-only JSON-L audit log |
|
|
272
|
+
| `RATE_LIMIT_RPM` | | `500` | Tool calls per minute per API key |
|
|
273
|
+
| `SESSION_TTL_HOURS` | | `4` | SSE session TTL (hosted/team modes) |
|
|
274
|
+
| `SSE_PORT` | | `3000` | Port for the SSE server (hosted/team modes) |
|
|
275
|
+
| `BEHIND_TLS_PROXY` | | `false` | Set `true` when behind nginx/Caddy in production |
|
|
276
|
+
| `JIRA_BASE_URL` | | — | e.g. `https://your-org.atlassian.net` |
|
|
277
|
+
| `JIRA_API_TOKEN` | | — | Jira API token for the integration |
|
|
278
|
+
| `JIRA_PROJECT_KEY` | | — | e.g. `SEC` |
|
|
279
|
+
| `JIRA_USER_EMAIL` | | — | Email address associated with the Jira API token |
|
|
280
|
+
| `GITHUB_TOKEN` | | — | GitHub personal access token (scope: `issues:write`) |
|
|
281
|
+
| `GITHUB_REPO` | | — | e.g. `your-org/your-repo` |
|
|
282
|
+
|
|
283
|
+
### Step 3 — Generate an API Key
|
|
284
|
+
|
|
285
|
+
The server requires an API key on every tool call. Generate one for yourself:
|
|
286
|
+
|
|
287
|
+
```bash
|
|
288
|
+
# Viewer — read-only access to 22 tools
|
|
289
|
+
iso27001-mcp keygen --label "Alice" --role viewer
|
|
290
|
+
|
|
291
|
+
# Analyst — read + write for gap/risk/policy/evidence tools (35 tools)
|
|
292
|
+
iso27001-mcp keygen --label "Bob" --role analyst --expires 90d
|
|
293
|
+
|
|
294
|
+
# Admin — all 43 tools including audit log and key management
|
|
295
|
+
iso27001-mcp keygen --label "CISO" --role admin --expires 1y
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
The raw key is printed **once** and never stored in plaintext. Save it immediately.
|
|
299
|
+
|
|
300
|
+
```bash
|
|
301
|
+
# List all keys
|
|
302
|
+
iso27001-mcp keys list
|
|
303
|
+
|
|
304
|
+
# Revoke a key immediately
|
|
305
|
+
iso27001-mcp keys revoke --label "Alice"
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
## Connecting to Claude
|
|
311
|
+
|
|
312
|
+
### Claude Desktop
|
|
313
|
+
|
|
314
|
+
Add the server to your Claude Desktop MCP configuration file:
|
|
315
|
+
|
|
316
|
+
**macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
317
|
+
**Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
|
|
318
|
+
|
|
319
|
+
```json
|
|
320
|
+
{
|
|
321
|
+
"mcpServers": {
|
|
322
|
+
"iso27001": {
|
|
323
|
+
"command": "iso27001-mcp",
|
|
324
|
+
"env": {
|
|
325
|
+
"HMAC_SECRET": "your_hmac_secret",
|
|
326
|
+
"DB_ENCRYPTION_KEY": "your_db_encryption_key",
|
|
327
|
+
"MCP_API_KEY": "iso27001_your_api_key_here",
|
|
328
|
+
"DB_PATH": "/Users/you/.iso27001/isms.db"
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
Restart Claude Desktop. The ISO 27001 tools will appear in the tools panel.
|
|
336
|
+
|
|
337
|
+
> **Tip:** Store your `isms.db` in a stable location like `~/.iso27001/isms.db` so it persists across upgrades.
|
|
338
|
+
|
|
339
|
+
### Claude Code
|
|
340
|
+
|
|
341
|
+
```bash
|
|
342
|
+
# Add to your project's MCP config
|
|
343
|
+
claude mcp add iso27001 iso27001-mcp
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
Then set the required env vars in your shell or `.env`:
|
|
347
|
+
|
|
348
|
+
```bash
|
|
349
|
+
export HMAC_SECRET=your_hmac_secret
|
|
350
|
+
export DB_ENCRYPTION_KEY=your_db_encryption_key
|
|
351
|
+
export MCP_API_KEY=iso27001_your_key_here
|
|
352
|
+
export DB_PATH=$HOME/.iso27001/isms.db
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
---
|
|
356
|
+
|
|
357
|
+
## Tools Reference
|
|
358
|
+
|
|
359
|
+
The server exposes **43 tools** across 9 groups. All tools require a valid API key. The minimum role required is noted per group; `✅` marks required parameters, `—` marks optional ones.
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
### Group 1 — Control Registry *(minimum role: viewer)*
|
|
364
|
+
|
|
365
|
+
#### `get_control`
|
|
366
|
+
Fetch a single control by ID and version.
|
|
367
|
+
|
|
368
|
+
| Parameter | Req | Type | Values / Notes |
|
|
369
|
+
|-----------|-----|------|----------------|
|
|
370
|
+
| `control_id` | ✅ | string | e.g. `5.1`, `A.8.1` |
|
|
371
|
+
| `version` | — | enum | `2022` \| `2013` |
|
|
372
|
+
|
|
373
|
+
#### `list_controls`
|
|
374
|
+
List controls with optional filters.
|
|
375
|
+
|
|
376
|
+
| Parameter | Req | Type | Values / Notes |
|
|
377
|
+
|-----------|-----|------|----------------|
|
|
378
|
+
| `version` | — | enum | `2022` \| `2013` |
|
|
379
|
+
| `theme` | — | string | e.g. `Technological` |
|
|
380
|
+
| `control_type` | — | enum | `Preventive` \| `Detective` \| `Corrective` |
|
|
381
|
+
| `new_in_2022` | — | boolean | Filter to controls added in the 2022 revision |
|
|
382
|
+
| `cybersecurity_concept` | — | enum | `Identify` \| `Protect` \| `Detect` \| `Respond` \| `Recover` |
|
|
383
|
+
| `include_guidance` | — | boolean | Default: `false` |
|
|
384
|
+
| `limit` | — | integer | Default: `50`, max `100` |
|
|
385
|
+
| `offset` | — | integer | Default: `0` |
|
|
386
|
+
|
|
387
|
+
#### `search_controls`
|
|
388
|
+
Full-text search across control names, descriptions, and guidance (FTS5).
|
|
389
|
+
|
|
390
|
+
| Parameter | Req | Type | Values / Notes |
|
|
391
|
+
|-----------|-----|------|----------------|
|
|
392
|
+
| `query` | ✅ | string | Search terms |
|
|
393
|
+
| `version` | — | enum | `2022` \| `2013` |
|
|
394
|
+
| `limit` | — | integer | Default: `10`, max `50` |
|
|
395
|
+
| `offset` | — | integer | Default: `0` |
|
|
396
|
+
|
|
397
|
+
#### `get_control_attributes`
|
|
398
|
+
Retrieve 2022 attribute taxonomy (cybersecurity concepts, operational capabilities) for a control.
|
|
399
|
+
|
|
400
|
+
| Parameter | Req | Type | Values / Notes |
|
|
401
|
+
|-----------|-----|------|----------------|
|
|
402
|
+
| `control_id` | ✅ | string | 2022 control ID |
|
|
403
|
+
|
|
404
|
+
#### `compare_versions`
|
|
405
|
+
Show the mapping between a 2013 control and its 2022 equivalent. Provide at least one ID.
|
|
406
|
+
|
|
407
|
+
| Parameter | Req | Type | Values / Notes |
|
|
408
|
+
|-----------|-----|------|----------------|
|
|
409
|
+
| `v2013_id` | — | string | ISO 27001:2013 control ID |
|
|
410
|
+
| `v2022_id` | — | string | ISO 27001:2022 control ID |
|
|
411
|
+
|
|
412
|
+
#### `get_clause_requirement`
|
|
413
|
+
Fetch a clause requirement (clauses 4–10) with optional sub-clauses.
|
|
414
|
+
|
|
415
|
+
| Parameter | Req | Type | Values / Notes |
|
|
416
|
+
|-----------|-----|------|----------------|
|
|
417
|
+
| `clause_id` | ✅ | string | e.g. `4.1`, `9.2` |
|
|
418
|
+
| `include_sub_clauses` | — | boolean | Default: `false` |
|
|
419
|
+
|
|
420
|
+
#### `list_clause_requirements`
|
|
421
|
+
List all clause requirements, optionally filtered by parent.
|
|
422
|
+
|
|
423
|
+
| Parameter | Req | Type | Values / Notes |
|
|
424
|
+
|-----------|-----|------|----------------|
|
|
425
|
+
| `parent_id` | — | string | e.g. `9` to list all sub-clauses of clause 9 |
|
|
426
|
+
|
|
427
|
+
---
|
|
428
|
+
|
|
429
|
+
### Group 2 — Gap Analysis *(reads: viewer+, writes: analyst+)*
|
|
430
|
+
|
|
431
|
+
#### `create_gap_assessment`
|
|
432
|
+
Create a new gap assessment. Pre-populates all in-scope controls as `not_started`.
|
|
433
|
+
|
|
434
|
+
| Parameter | Req | Type | Values / Notes |
|
|
435
|
+
|-----------|-----|------|----------------|
|
|
436
|
+
| `name` | ✅ | string | Assessment name |
|
|
437
|
+
| `scope` | — | string | ISMS scope description |
|
|
438
|
+
| `isms_version` | — | enum | `2022` \| `2013` — default: `2022` |
|
|
439
|
+
| `themes_in_scope` | — | array | e.g. `["Organizational","Technological"]` |
|
|
440
|
+
| `exclude_controls` | — | array | Control IDs to exclude |
|
|
441
|
+
| `exclude_justification` | — | string | Reason for exclusions |
|
|
442
|
+
|
|
443
|
+
#### `update_control_status`
|
|
444
|
+
Set a control's implementation status within an assessment.
|
|
445
|
+
|
|
446
|
+
| Parameter | Req | Type | Values / Notes |
|
|
447
|
+
|-----------|-----|------|----------------|
|
|
448
|
+
| `assessment_id` | ✅ | string (UUID) | |
|
|
449
|
+
| `control_id` | ✅ | string | |
|
|
450
|
+
| `status` | ✅ | enum | `implemented` \| `partial` \| `not_implemented` \| `na` \| `not_started` |
|
|
451
|
+
| `evidence_refs` | — | array | Evidence UUIDs |
|
|
452
|
+
| `notes` | — | string | Implementation notes |
|
|
453
|
+
| `na_justification` | — | string | Required when `status=na` |
|
|
454
|
+
| `assessed_by` | — | string | Assessor name |
|
|
455
|
+
|
|
456
|
+
#### `get_gap_summary`
|
|
457
|
+
Return compliance %, counts by status, and a top-10 remediation priority list.
|
|
458
|
+
|
|
459
|
+
| Parameter | Req | Type | Values / Notes |
|
|
460
|
+
|-----------|-----|------|----------------|
|
|
461
|
+
| `assessment_id` | ✅ | string (UUID) | |
|
|
462
|
+
| `breakdown_by` | — | enum | `theme` \| `control_type` \| `cybersecurity_concept` |
|
|
463
|
+
|
|
464
|
+
#### `list_gap_assessments`
|
|
465
|
+
List assessments with a status filter.
|
|
466
|
+
|
|
467
|
+
| Parameter | Req | Type | Values / Notes |
|
|
468
|
+
|-----------|-----|------|----------------|
|
|
469
|
+
| `filter` | — | enum | `active` \| `archived` \| `all` — default: `active` |
|
|
470
|
+
|
|
471
|
+
#### `export_gap_report`
|
|
472
|
+
Export a full gap report.
|
|
473
|
+
|
|
474
|
+
| Parameter | Req | Type | Values / Notes |
|
|
475
|
+
|-----------|-----|------|----------------|
|
|
476
|
+
| `assessment_id` | ✅ | string (UUID) | |
|
|
477
|
+
| `format` | ✅ | enum | `markdown` \| `csv` \| `json` |
|
|
478
|
+
|
|
479
|
+
#### `generate_remediation_roadmap`
|
|
480
|
+
Generate a prioritised remediation roadmap with phases, risk linkage, and due dates.
|
|
481
|
+
|
|
482
|
+
| Parameter | Req | Type | Values / Notes |
|
|
483
|
+
|-----------|-----|------|----------------|
|
|
484
|
+
| `assessment_id` | ✅ | string (UUID) | |
|
|
485
|
+
| `timeline_weeks` | — | integer | 1–52, default: `12` |
|
|
486
|
+
|
|
487
|
+
#### `archive_gap_assessment`
|
|
488
|
+
Archive a completed assessment.
|
|
489
|
+
|
|
490
|
+
| Parameter | Req | Type | Values / Notes |
|
|
491
|
+
|-----------|-----|------|----------------|
|
|
492
|
+
| `assessment_id` | ✅ | string (UUID) | |
|
|
493
|
+
| `reason` | — | string | Archival reason |
|
|
494
|
+
|
|
495
|
+
---
|
|
496
|
+
|
|
497
|
+
### Group 3 — Risk Management *(reads: viewer+, writes: analyst+)*
|
|
498
|
+
|
|
499
|
+
#### `create_risk`
|
|
500
|
+
Register a new risk. `risk_score` is computed automatically as `likelihood × impact`.
|
|
501
|
+
|
|
502
|
+
| Parameter | Req | Type | Values / Notes |
|
|
503
|
+
|-----------|-----|------|----------------|
|
|
504
|
+
| `asset` | ✅ | string | Asset at risk |
|
|
505
|
+
| `threat` | ✅ | string | Threat description |
|
|
506
|
+
| `vulnerability` | ✅ | string | Vulnerability description |
|
|
507
|
+
| `likelihood` | ✅ | integer | 1–5 |
|
|
508
|
+
| `impact` | ✅ | integer | 1–5 |
|
|
509
|
+
| `owner` | — | string | Risk owner |
|
|
510
|
+
| `related_controls` | — | array | Control IDs |
|
|
511
|
+
| `status` | — | enum | `open` \| `accepted` \| `mitigated` \| `transferred` \| `closed` — default: `open` |
|
|
512
|
+
|
|
513
|
+
#### `get_risk`
|
|
514
|
+
Fetch a risk record with optional treatment plans.
|
|
515
|
+
|
|
516
|
+
| Parameter | Req | Type | Values / Notes |
|
|
517
|
+
|-----------|-----|------|----------------|
|
|
518
|
+
| `risk_id` | ✅ | string (UUID) | |
|
|
519
|
+
| `include_treatments` | — | boolean | Default: `false` |
|
|
520
|
+
|
|
521
|
+
#### `update_risk`
|
|
522
|
+
Update any mutable field; `risk_score` recomputes automatically.
|
|
523
|
+
|
|
524
|
+
| Parameter | Req | Type | Values / Notes |
|
|
525
|
+
|-----------|-----|------|----------------|
|
|
526
|
+
| `risk_id` | ✅ | string (UUID) | |
|
|
527
|
+
| `asset` | — | string | |
|
|
528
|
+
| `threat` | — | string | |
|
|
529
|
+
| `vulnerability` | — | string | |
|
|
530
|
+
| `likelihood` | — | integer | 1–5 |
|
|
531
|
+
| `impact` | — | integer | 1–5 |
|
|
532
|
+
| `owner` | — | string | |
|
|
533
|
+
| `status` | — | enum | `open` \| `accepted` \| `mitigated` \| `transferred` \| `closed` |
|
|
534
|
+
| `related_controls` | — | array | Control IDs |
|
|
535
|
+
|
|
536
|
+
#### `list_risks`
|
|
537
|
+
List risks with optional filters.
|
|
538
|
+
|
|
539
|
+
| Parameter | Req | Type | Values / Notes |
|
|
540
|
+
|-----------|-----|------|----------------|
|
|
541
|
+
| `risk_level` | — | enum | `Low` \| `Medium` \| `High` \| `Critical` |
|
|
542
|
+
| `status` | — | enum | `open` \| `accepted` \| `mitigated` \| `transferred` \| `closed` |
|
|
543
|
+
| `owner` | — | string | |
|
|
544
|
+
| `limit` | — | integer | Default: `50`, max `100` |
|
|
545
|
+
| `offset` | — | integer | Default: `0` |
|
|
546
|
+
|
|
547
|
+
#### `get_risk_summary`
|
|
548
|
+
Return aggregated stats: counts by level, 5×5 heatmap matrix, top 10 by score. No parameters.
|
|
549
|
+
|
|
550
|
+
#### `create_treatment_plan`
|
|
551
|
+
Create a risk treatment plan. `mitigate` type requires at least one control reference.
|
|
552
|
+
|
|
553
|
+
| Parameter | Req | Type | Values / Notes |
|
|
554
|
+
|-----------|-----|------|----------------|
|
|
555
|
+
| `risk_id` | ✅ | string (UUID) | |
|
|
556
|
+
| `treatment_type` | ✅ | enum | `mitigate` \| `accept` \| `avoid` \| `transfer` |
|
|
557
|
+
| `description` | ✅ | string | |
|
|
558
|
+
| `owner` | ✅ | string | |
|
|
559
|
+
| `due_date` | ✅ | string | `YYYY-MM-DD` |
|
|
560
|
+
| `controls` | — | array | Required for `mitigate` type |
|
|
561
|
+
| `residual_likelihood` | — | integer | 1–5 |
|
|
562
|
+
| `residual_impact` | — | integer | 1–5 |
|
|
563
|
+
| `evidence_ref` | — | string | |
|
|
564
|
+
|
|
565
|
+
#### `update_treatment_status`
|
|
566
|
+
Update a treatment plan's status and link evidence.
|
|
567
|
+
|
|
568
|
+
| Parameter | Req | Type | Values / Notes |
|
|
569
|
+
|-----------|-----|------|----------------|
|
|
570
|
+
| `treatment_id` | ✅ | string (UUID) | |
|
|
571
|
+
| `status` | ✅ | enum | `planned` \| `in_progress` \| `implemented` \| `verified` \| `cancelled` |
|
|
572
|
+
| `evidence_ref` | — | string | |
|
|
573
|
+
| `residual_likelihood` | — | integer | 1–5 |
|
|
574
|
+
| `residual_impact` | — | integer | 1–5 |
|
|
575
|
+
|
|
576
|
+
#### `generate_risk_register`
|
|
577
|
+
Export the full risk register.
|
|
578
|
+
|
|
579
|
+
| Parameter | Req | Type | Values / Notes |
|
|
580
|
+
|-----------|-----|------|----------------|
|
|
581
|
+
| `format` | ✅ | enum | `markdown` \| `csv` \| `json` |
|
|
582
|
+
| `risk_level_filter` | — | enum | `Low` \| `Medium` \| `High` \| `Critical` |
|
|
583
|
+
| `status_filter` | — | enum | `open` \| `accepted` \| `mitigated` \| `transferred` \| `closed` |
|
|
584
|
+
|
|
585
|
+
---
|
|
586
|
+
|
|
587
|
+
### Group 4 — Policy Management *(reads: viewer+, create: analyst+, update: admin)*
|
|
588
|
+
|
|
589
|
+
#### `create_policy`
|
|
590
|
+
Render a policy from a Mustache template with org-specific variables.
|
|
591
|
+
|
|
592
|
+
| Parameter | Req | Type | Values / Notes |
|
|
593
|
+
|-----------|-----|------|----------------|
|
|
594
|
+
| `type` | ✅ | enum | `information_security` \| `access_control` \| `risk_management` \| `asset_management` \| `incident_response` \| `business_continuity` \| `supplier_security` \| `cryptography` \| `physical_security` \| `acceptable_use` \| `data_classification` \| `secure_development` |
|
|
595
|
+
| `organisation_name` | ✅ | string | |
|
|
596
|
+
| `scope` | ✅ | string | |
|
|
597
|
+
| `owner` | ✅ | string | |
|
|
598
|
+
| `approver` | — | string | |
|
|
599
|
+
| `review_cycle_months` | — | integer | 1–36, default: `12` |
|
|
600
|
+
| `effective_date` | ✅ | string | `YYYY-MM-DD` |
|
|
601
|
+
|
|
602
|
+
#### `get_policy`
|
|
603
|
+
Fetch a policy with optional version history.
|
|
604
|
+
|
|
605
|
+
| Parameter | Req | Type | Values / Notes |
|
|
606
|
+
|-----------|-----|------|----------------|
|
|
607
|
+
| `policy_id` | ✅ | string (UUID) | |
|
|
608
|
+
| `include_versions` | — | boolean | Default: `false` |
|
|
609
|
+
|
|
610
|
+
#### `update_policy`
|
|
611
|
+
Archive the current version and create a new one. Admin only.
|
|
612
|
+
|
|
613
|
+
| Parameter | Req | Type | Values / Notes |
|
|
614
|
+
|-----------|-----|------|----------------|
|
|
615
|
+
| `policy_id` | ✅ | string (UUID) | |
|
|
616
|
+
| `scope` | — | string | |
|
|
617
|
+
| `owner` | — | string | |
|
|
618
|
+
| `approver` | — | string | |
|
|
619
|
+
| `reviewed_by` | ✅ | string | |
|
|
620
|
+
| `change_summary` | ✅ | string | |
|
|
621
|
+
|
|
622
|
+
#### `list_policies`
|
|
623
|
+
List policies with optional filters.
|
|
624
|
+
|
|
625
|
+
| Parameter | Req | Type | Values / Notes |
|
|
626
|
+
|-----------|-----|------|----------------|
|
|
627
|
+
| `status` | — | enum | `draft` \| `active` \| `archived` |
|
|
628
|
+
| `type` | — | enum | Any of the 12 policy types above |
|
|
629
|
+
| `owner` | — | string | |
|
|
630
|
+
| `overdue_only` | — | boolean | Filter to policies past their review date — default: `false` |
|
|
631
|
+
| `limit` | — | integer | Default: `50`, max `100` |
|
|
632
|
+
| `offset` | — | integer | Default: `0` |
|
|
633
|
+
|
|
634
|
+
---
|
|
635
|
+
|
|
636
|
+
### Group 5 — Statement of Applicability *(minimum role: analyst)*
|
|
637
|
+
|
|
638
|
+
#### `generate_soa`
|
|
639
|
+
Create an SoA from an assessment, pre-populating all 93 (2022) or 114 (2013) entries.
|
|
640
|
+
|
|
641
|
+
| Parameter | Req | Type | Values / Notes |
|
|
642
|
+
|-----------|-----|------|----------------|
|
|
643
|
+
| `assessment_id` | ✅ | string (UUID) | |
|
|
644
|
+
| `isms_version` | — | enum | `2022` \| `2013` — default: `2022` |
|
|
645
|
+
|
|
646
|
+
#### `update_soa_entry`
|
|
647
|
+
Update a single SoA entry's inclusion, justification, status, and responsible party.
|
|
648
|
+
|
|
649
|
+
| Parameter | Req | Type | Values / Notes |
|
|
650
|
+
|-----------|-----|------|----------------|
|
|
651
|
+
| `soa_id` | ✅ | string (UUID) | |
|
|
652
|
+
| `control_id` | ✅ | string | |
|
|
653
|
+
| `included` | ✅ | boolean | |
|
|
654
|
+
| `justification` | ✅ | string | |
|
|
655
|
+
| `status` | — | enum | `implemented` \| `partial` \| `not_implemented` \| `na` \| `not_started` |
|
|
656
|
+
| `responsible_party` | — | string | |
|
|
657
|
+
|
|
658
|
+
#### `export_soa`
|
|
659
|
+
Export the Statement of Applicability.
|
|
660
|
+
|
|
661
|
+
| Parameter | Req | Type | Values / Notes |
|
|
662
|
+
|-----------|-----|------|----------------|
|
|
663
|
+
| `soa_id` | ✅ | string (UUID) | |
|
|
664
|
+
| `format` | ✅ | enum | `markdown` \| `csv` |
|
|
665
|
+
|
|
666
|
+
---
|
|
667
|
+
|
|
668
|
+
### Group 6 — Audit Management *(reads: viewer+, writes: admin)*
|
|
669
|
+
|
|
670
|
+
#### `create_audit`
|
|
671
|
+
Create an internal audit with auditor, planned date, and scope.
|
|
672
|
+
|
|
673
|
+
| Parameter | Req | Type | Values / Notes |
|
|
674
|
+
|-----------|-----|------|----------------|
|
|
675
|
+
| `name` | ✅ | string | Audit name |
|
|
676
|
+
| `scope` | ✅ | string | |
|
|
677
|
+
| `auditor` | ✅ | string | |
|
|
678
|
+
| `planned_date` | ✅ | string | `YYYY-MM-DD` |
|
|
679
|
+
| `controls_in_scope` | — | array | Control IDs |
|
|
680
|
+
| `clauses_in_scope` | — | array | Clause IDs |
|
|
681
|
+
|
|
682
|
+
#### `record_finding`
|
|
683
|
+
Record a finding. Non-conformities (`nc`) require a severity.
|
|
684
|
+
|
|
685
|
+
| Parameter | Req | Type | Values / Notes |
|
|
686
|
+
|-----------|-----|------|----------------|
|
|
687
|
+
| `audit_id` | ✅ | string (UUID) | |
|
|
688
|
+
| `type` | ✅ | enum | `nc` \| `obs` \| `ofi` |
|
|
689
|
+
| `clause_or_control` | ✅ | string | |
|
|
690
|
+
| `description` | ✅ | string | |
|
|
691
|
+
| `objective_evidence` | ✅ | string | |
|
|
692
|
+
| `severity` | — | enum | `major` \| `minor` — required for `type=nc` |
|
|
693
|
+
|
|
694
|
+
#### `create_corrective_action`
|
|
695
|
+
Raise a Corrective Action Request (CAR) linked to a finding.
|
|
696
|
+
|
|
697
|
+
| Parameter | Req | Type | Values / Notes |
|
|
698
|
+
|-----------|-----|------|----------------|
|
|
699
|
+
| `finding_id` | ✅ | string (UUID) | |
|
|
700
|
+
| `description` | ✅ | string | |
|
|
701
|
+
| `owner` | ✅ | string | |
|
|
702
|
+
| `due_date` | ✅ | string | `YYYY-MM-DD` |
|
|
703
|
+
| `root_cause` | — | string | |
|
|
704
|
+
|
|
705
|
+
#### `update_corrective_action`
|
|
706
|
+
Update CAR status. Closing (`status=closed`) requires `effectiveness_verified: true` (ISO 27001 Clause 10.1).
|
|
707
|
+
|
|
708
|
+
| Parameter | Req | Type | Values / Notes |
|
|
709
|
+
|-----------|-----|------|----------------|
|
|
710
|
+
| `car_id` | ✅ | string (UUID) | |
|
|
711
|
+
| `description` | — | string | |
|
|
712
|
+
| `owner` | — | string | |
|
|
713
|
+
| `due_date` | — | string | `YYYY-MM-DD` |
|
|
714
|
+
| `status` | — | enum | `open` \| `in_progress` \| `implemented` \| `verified` \| `closed` |
|
|
715
|
+
| `root_cause` | — | string | |
|
|
716
|
+
| `effectiveness_verified` | — | boolean | Must be `true` to close the CAR |
|
|
717
|
+
| `evidence_ref` | — | string | |
|
|
718
|
+
|
|
719
|
+
#### `generate_audit_report`
|
|
720
|
+
Export a full audit report (executive summary, findings, CARs).
|
|
721
|
+
|
|
722
|
+
| Parameter | Req | Type | Values / Notes |
|
|
723
|
+
|-----------|-----|------|----------------|
|
|
724
|
+
| `audit_id` | ✅ | string (UUID) | |
|
|
725
|
+
| `format` | ✅ | enum | `markdown` \| `json` |
|
|
726
|
+
|
|
727
|
+
---
|
|
728
|
+
|
|
729
|
+
### Group 7 — Evidence Tracking *(reads: viewer+, writes: analyst+)*
|
|
730
|
+
|
|
731
|
+
#### `register_evidence`
|
|
732
|
+
Register an evidence artefact for a control.
|
|
733
|
+
|
|
734
|
+
| Parameter | Req | Type | Values / Notes |
|
|
735
|
+
|-----------|-----|------|----------------|
|
|
736
|
+
| `control_id` | ✅ | string | |
|
|
737
|
+
| `type` | ✅ | enum | `policy` \| `procedure` \| `log` \| `screenshot` \| `report` \| `certificate` \| `configuration` \| `meeting_minutes` \| `training_record` \| `contract` \| `audit_report` \| `test_result` \| `ticket` \| `other` |
|
|
738
|
+
| `description` | ✅ | string | |
|
|
739
|
+
| `source_url` | — | string | URL to the artefact |
|
|
740
|
+
| `collected_by` | ✅ | string | |
|
|
741
|
+
| `collected_date` | ✅ | string | `YYYY-MM-DD` |
|
|
742
|
+
| `expiry_date` | — | string | `YYYY-MM-DD` |
|
|
743
|
+
|
|
744
|
+
#### `list_evidence`
|
|
745
|
+
List evidence for a control, optionally filtered by currency.
|
|
746
|
+
|
|
747
|
+
| Parameter | Req | Type | Values / Notes |
|
|
748
|
+
|-----------|-----|------|----------------|
|
|
749
|
+
| `control_id` | ✅ | string | |
|
|
750
|
+
| `status` | — | enum | `current` \| `stale` \| `expired` |
|
|
751
|
+
|
|
752
|
+
#### `get_evidence_gaps`
|
|
753
|
+
Find controls marked `implemented` or `partial` that have no current evidence.
|
|
754
|
+
|
|
755
|
+
| Parameter | Req | Type | Values / Notes |
|
|
756
|
+
|-----------|-----|------|----------------|
|
|
757
|
+
| `assessment_id` | ✅ | string (UUID) | |
|
|
758
|
+
|
|
759
|
+
#### `link_jira_ticket`
|
|
760
|
+
Link evidence to an existing Jira issue (`jira_key`) or create a new one (`summary`). Provide at least one.
|
|
761
|
+
|
|
762
|
+
| Parameter | Req | Type | Values / Notes |
|
|
763
|
+
|-----------|-----|------|----------------|
|
|
764
|
+
| `evidence_id` | ✅ | string (UUID) | |
|
|
765
|
+
| `jira_key` | — | string | e.g. `ISMS-42` — links to existing issue |
|
|
766
|
+
| `summary` | — | string | Creates a new Jira task with this title |
|
|
767
|
+
| `description` | — | string | Body for the new issue |
|
|
768
|
+
|
|
769
|
+
#### `link_github_issue`
|
|
770
|
+
Link evidence to an existing GitHub issue (`issue_number`) or create a new one (`title`). Provide at least one.
|
|
771
|
+
|
|
772
|
+
| Parameter | Req | Type | Values / Notes |
|
|
773
|
+
|-----------|-----|------|----------------|
|
|
774
|
+
| `evidence_id` | ✅ | string (UUID) | |
|
|
775
|
+
| `issue_number` | — | integer | Links to an existing issue |
|
|
776
|
+
| `title` | — | string | Creates a new issue with this title |
|
|
777
|
+
| `body` | — | string | Body for the new issue |
|
|
778
|
+
|
|
779
|
+
---
|
|
780
|
+
|
|
781
|
+
### Group 8 — Server Info *(minimum role: viewer)*
|
|
782
|
+
|
|
783
|
+
#### `get_server_info`
|
|
784
|
+
Return version, uptime, DB stats, control counts, and rate limit config. No parameters.
|
|
785
|
+
|
|
786
|
+
---
|
|
787
|
+
|
|
788
|
+
### Group 9 — Admin & Key Management *(minimum role: admin)*
|
|
789
|
+
|
|
790
|
+
#### `query_audit_log`
|
|
791
|
+
Query the tamper-evident audit log.
|
|
792
|
+
|
|
793
|
+
| Parameter | Req | Type | Values / Notes |
|
|
794
|
+
|-----------|-----|------|----------------|
|
|
795
|
+
| `start_date` | — | string | `YYYY-MM-DD` |
|
|
796
|
+
| `end_date` | — | string | `YYYY-MM-DD` |
|
|
797
|
+
| `tool` | — | string | Filter by tool name |
|
|
798
|
+
| `outcome` | — | enum | `success` \| `denied` \| `error` |
|
|
799
|
+
| `role` | — | enum | `viewer` \| `analyst` \| `admin` |
|
|
800
|
+
| `key_hash` | — | string | Filter by API key hash (max 64 chars) |
|
|
801
|
+
| `limit` | — | integer | Default: `50`, max `100` |
|
|
802
|
+
| `offset` | — | integer | Default: `0` |
|
|
803
|
+
|
|
804
|
+
#### `list_api_keys`
|
|
805
|
+
List all API keys with metadata. Never returns key hashes. No parameters.
|
|
806
|
+
|
|
807
|
+
#### `revoke_api_key`
|
|
808
|
+
Immediately revoke a key by label.
|
|
809
|
+
|
|
810
|
+
| Parameter | Req | Type | Values / Notes |
|
|
811
|
+
|-----------|-----|------|----------------|
|
|
812
|
+
| `label` | ✅ | string | The label assigned at key generation |
|
|
813
|
+
|
|
814
|
+
---
|
|
815
|
+
|
|
816
|
+
## Architecture
|
|
817
|
+
|
|
818
|
+
```
|
|
819
|
+
┌─────────────────────────────────────────────────────────┐
|
|
820
|
+
│ Claude (LLM) │
|
|
821
|
+
└──────────────────────────┬──────────────────────────────┘
|
|
822
|
+
│ MCP (stdio or SSE)
|
|
823
|
+
┌──────────────────────────▼──────────────────────────────┐
|
|
824
|
+
│ iso27001-mcp server │
|
|
825
|
+
│ │
|
|
826
|
+
│ ┌─────────────────────────────────────────────────┐ │
|
|
827
|
+
│ │ 9-Step Security Pipeline │ │
|
|
828
|
+
│ │ │ │
|
|
829
|
+
│ │ 1. Extract API key (meta or MCP_API_KEY env) │ │
|
|
830
|
+
│ │ 2. validateKey() HMAC-SHA256, timing-safe │ │
|
|
831
|
+
│ │ 3. checkRateLimit() sliding 60s window (RPM) │ │
|
|
832
|
+
│ │ 4. loadRole() viewer | analyst | admin │ │
|
|
833
|
+
│ │ 5. assertPermission() RBAC check │ │
|
|
834
|
+
│ │ 6. sanitiseParams() strip injection patterns │ │
|
|
835
|
+
│ │ 7. Domain handler business logic │ │
|
|
836
|
+
│ │ 8. writeAuditEvent() tamper-evident row_hash │ │
|
|
837
|
+
│ │ 9. Return result or structured McpError │ │
|
|
838
|
+
│ └─────────────────────────────────────────────────┘ │
|
|
839
|
+
│ │
|
|
840
|
+
│ ┌─────────────┐ ┌──────────┐ ┌────────────────────┐ │
|
|
841
|
+
│ │ Controls │ │ Risks │ │ Policies │ │
|
|
842
|
+
│ │ Gap Assess │ │ Register │ │ (Mustache tmpl) │ │
|
|
843
|
+
│ │ SoA │ │ Treatmts │ │ Version history │ │
|
|
844
|
+
│ └─────────────┘ └──────────┘ └────────────────────┘ │
|
|
845
|
+
│ ┌─────────────┐ ┌──────────┐ ┌────────────────────┐ │
|
|
846
|
+
│ │ Audits │ │ Evidence │ │ Audit Log │ │
|
|
847
|
+
│ │ Findings │ │ Jira/GH │ │ (tamper-evident) │ │
|
|
848
|
+
│ │ CARs │ │ Gaps │ │ │ │
|
|
849
|
+
│ └─────────────┘ └──────────┘ └────────────────────┘ │
|
|
850
|
+
│ │
|
|
851
|
+
│ ┌─────────────────────────────────────────────────┐ │
|
|
852
|
+
│ │ AES-256 encrypted SQLite (isms.db) │ │
|
|
853
|
+
│ │ better-sqlite3-multiple-ciphers │ │
|
|
854
|
+
│ │ WAL mode · foreign keys · FTS5 index │ │
|
|
855
|
+
│ └─────────────────────────────────────────────────┘ │
|
|
856
|
+
└─────────────────────────────────────────────────────────┘
|
|
857
|
+
```
|
|
858
|
+
|
|
859
|
+
### Database
|
|
860
|
+
|
|
861
|
+
All data is stored in a single encrypted SQLite file (`isms.db`) using AES-256 via `better-sqlite3-multiple-ciphers`. The schema is managed by two SQL migrations applied automatically on first startup:
|
|
862
|
+
|
|
863
|
+
- `0001_initial.sql` — 17 tables covering every ISMS domain (controls, gap assessments, risks, policies, audits, evidence, API keys, audit log, and more)
|
|
864
|
+
- `0002_fts_index.sql` — FTS5 full-text search index on controls, plus 12 performance indexes
|
|
865
|
+
|
|
866
|
+
### Seed Data
|
|
867
|
+
|
|
868
|
+
On first startup, `seedAll()` inserts all ISO 27001 reference data and verifies SHA-256 checksums before inserting:
|
|
869
|
+
|
|
870
|
+
- **93** ISO 27001:2022 Annex A controls across 4 themes (Organizational, People, Physical, Technological)
|
|
871
|
+
- **114** ISO 27001:2013 controls across 14 Annex A domains
|
|
872
|
+
- **125** version mappings (2013 ↔ 2022), including direct, merged, split, and new_2022 relationships
|
|
873
|
+
- **41** clause requirements for clauses 4–10 with sub-clauses, requirement text, and implementation notes
|
|
874
|
+
|
|
875
|
+
### Security Pipeline
|
|
876
|
+
|
|
877
|
+
Every tool call passes through the same 9-step pipeline before any business logic runs. Audit events are always written — including on authentication failure and RBAC denial — so the log is a complete record of all attempts, not just successful ones.
|
|
878
|
+
|
|
879
|
+
### Business Rules Enforced
|
|
880
|
+
|
|
881
|
+
The server encodes ISO 27001 requirements as hard constraints, not just guidance:
|
|
882
|
+
|
|
883
|
+
| Rule | Tool | Behaviour |
|
|
884
|
+
|------|------|-----------|
|
|
885
|
+
| `implemented` without evidence → silently downgraded | `update_control_status` | Status becomes `partial`; response includes `warning` field |
|
|
886
|
+
| `na` status requires justification | `update_control_status` | `BUSINESS_RULE` error if `na_justification` absent |
|
|
887
|
+
| Cannot update an archived assessment | `update_control_status` | `BUSINESS_RULE` error |
|
|
888
|
+
| `mitigate` treatment requires control references | `create_treatment_plan` | `BUSINESS_RULE` error if `controls[]` is empty |
|
|
889
|
+
| CAR closure requires effectiveness verified | `update_corrective_action` | Enforces Clause 10.1; `BUSINESS_RULE` error otherwise |
|
|
890
|
+
| NC findings require severity | `record_finding` | `BUSINESS_RULE` error if `severity` absent for `type=nc` |
|
|
891
|
+
|
|
892
|
+
### RBAC
|
|
893
|
+
|
|
894
|
+
Three roles with strict hierarchy. A key can only call tools at or below its assigned role level.
|
|
895
|
+
|
|
896
|
+
| Role | Tools available | Typical user |
|
|
897
|
+
|------|----------------|--------------|
|
|
898
|
+
| `viewer` | 22 (all read-only tools) | Auditor, stakeholder |
|
|
899
|
+
| `analyst` | 35 (reads + gap/risk/policy/evidence writes) | ISMS practitioner, consultant |
|
|
900
|
+
| `admin` | 43 (all tools, including audit log and key management) | CISO, ISMS owner |
|
|
901
|
+
|
|
902
|
+
---
|
|
903
|
+
|
|
904
|
+
## Modes
|
|
905
|
+
|
|
906
|
+
The server supports four operating modes selected with the `--mode` flag:
|
|
907
|
+
|
|
908
|
+
| Mode | Transport | Typical use |
|
|
909
|
+
|------|-----------|-------------|
|
|
910
|
+
| `local` *(default)* | stdio | Claude Desktop, single user |
|
|
911
|
+
| `ci` | stdio | Automated pipelines, no TTY |
|
|
912
|
+
| `team` | SSE over HTTP | Shared instance, multiple users |
|
|
913
|
+
| `hosted` | SSE over HTTP | Production, behind a TLS proxy |
|
|
914
|
+
|
|
915
|
+
### Local / CI (stdio)
|
|
916
|
+
|
|
917
|
+
```bash
|
|
918
|
+
iso27001-mcp --mode local --db ./isms.db
|
|
919
|
+
```
|
|
920
|
+
|
|
921
|
+
Claude Desktop manages the process. The server reads from stdin and writes to stdout.
|
|
922
|
+
|
|
923
|
+
### Team / Hosted (SSE)
|
|
924
|
+
|
|
925
|
+
```bash
|
|
926
|
+
iso27001-mcp --mode hosted --db /data/isms.db
|
|
927
|
+
```
|
|
928
|
+
|
|
929
|
+
Starts an Express HTTP server on `SSE_PORT` (default `3000`):
|
|
930
|
+
|
|
931
|
+
| Endpoint | Description |
|
|
932
|
+
|----------|-------------|
|
|
933
|
+
| `GET /health` | Health check — no auth required |
|
|
934
|
+
| `GET /sse` | Open SSE connection; first event contains `{ type: "session", sessionId }` |
|
|
935
|
+
| `POST /messages?sessionId=X` | Send an MCP message on an active session |
|
|
936
|
+
|
|
937
|
+
Sessions expire after `SESSION_TTL_HOURS` hours of inactivity. In `NODE_ENV=production`, CORS is restricted to `https://claude.ai` and `/messages` is rate-limited to 100 requests per minute per IP.
|
|
938
|
+
|
|
939
|
+
---
|
|
940
|
+
|
|
941
|
+
## Integrations
|
|
942
|
+
|
|
943
|
+
### Jira
|
|
944
|
+
|
|
945
|
+
```bash
|
|
946
|
+
JIRA_BASE_URL=https://your-org.atlassian.net
|
|
947
|
+
JIRA_API_TOKEN=your_api_token
|
|
948
|
+
JIRA_PROJECT_KEY=SEC
|
|
949
|
+
JIRA_USER_EMAIL=you@your-org.com
|
|
950
|
+
```
|
|
951
|
+
|
|
952
|
+
Use `link_jira_ticket` to create a Task in your Jira project or link an existing one. The Jira key and browse URL are stored on the evidence record. Requests time out after 10 seconds and retry once on 5xx responses. A clear `INTEGRATION_ERROR` is returned — with the exact missing variable names — if credentials are not configured.
|
|
953
|
+
|
|
954
|
+
### GitHub
|
|
955
|
+
|
|
956
|
+
```bash
|
|
957
|
+
GITHUB_TOKEN=ghp_your_token # requires issues:write, metadata:read
|
|
958
|
+
GITHUB_REPO=your-org/your-repo
|
|
959
|
+
```
|
|
960
|
+
|
|
961
|
+
Use `link_github_issue` to create an issue with `compliance` and `iso27001` labels or link an existing one by number. The issue URL and number are stored on the evidence record.
|
|
962
|
+
|
|
963
|
+
---
|
|
964
|
+
|
|
965
|
+
## Development
|
|
966
|
+
|
|
967
|
+
```bash
|
|
968
|
+
# Install dependencies
|
|
969
|
+
npm install
|
|
970
|
+
|
|
971
|
+
# Typecheck (strict — zero errors tolerated)
|
|
972
|
+
npm run typecheck
|
|
973
|
+
|
|
974
|
+
# Build dist/
|
|
975
|
+
npm run build
|
|
976
|
+
|
|
977
|
+
# Run all tests (183 unit + integration tests)
|
|
978
|
+
npm test
|
|
979
|
+
|
|
980
|
+
# Watch mode
|
|
981
|
+
npm run test:watch
|
|
982
|
+
|
|
983
|
+
# Lint
|
|
984
|
+
npm run lint
|
|
985
|
+
|
|
986
|
+
# Verify seed data SHA-256 checksums
|
|
987
|
+
npm run verify-checksums
|
|
988
|
+
|
|
989
|
+
# Run from source without building
|
|
990
|
+
npm run dev
|
|
991
|
+
```
|
|
992
|
+
|
|
993
|
+
### Project Structure
|
|
994
|
+
|
|
995
|
+
```
|
|
996
|
+
src/
|
|
997
|
+
├── index.ts CLI entry (keygen, keys, server startup)
|
|
998
|
+
├── server.ts McpServer factory
|
|
999
|
+
├── auth/
|
|
1000
|
+
│ ├── api-key.ts Key generation, HMAC validation, expiry, revocation
|
|
1001
|
+
│ └── rbac.ts Permission matrix (43 tools × 3 roles)
|
|
1002
|
+
├── security/
|
|
1003
|
+
│ ├── sanitise.ts Prompt-injection stripping for free-text fields
|
|
1004
|
+
│ ├── rate-limiter.ts Sliding-window RPM counter per key hash
|
|
1005
|
+
│ ├── secrets.ts Env var validation (fail-fast on startup)
|
|
1006
|
+
│ └── validate.ts Zod schemas for all 43 tool inputs
|
|
1007
|
+
├── audit/
|
|
1008
|
+
│ └── logger.ts Tamper-evident audit event writer
|
|
1009
|
+
├── db/
|
|
1010
|
+
│ ├── connection.ts Encrypted SQLite open/close/migrate
|
|
1011
|
+
│ ├── dal.ts Shared helpers: newId, now, toJson, computeEvidenceStatus
|
|
1012
|
+
│ └── migrations/ 0001_initial.sql, 0002_fts_index.sql
|
|
1013
|
+
├── seed/
|
|
1014
|
+
│ ├── seeder.ts Idempotent seed runner with checksum verification
|
|
1015
|
+
│ ├── controls-2022.json 93 ISO 27001:2022 Annex A controls
|
|
1016
|
+
│ ├── controls-2013.json 114 ISO 27001:2013 controls
|
|
1017
|
+
│ ├── version-mapping.json 125 cross-version mappings
|
|
1018
|
+
│ ├── clause-requirements.json 41 clause requirements (clauses 4–10)
|
|
1019
|
+
│ └── policy-templates/ 12 Mustache .md policy templates
|
|
1020
|
+
├── tools/
|
|
1021
|
+
│ ├── index.ts Tool registry and security pipeline
|
|
1022
|
+
│ ├── controls.ts Group 1: Control Registry (7 tools)
|
|
1023
|
+
│ ├── gap-analysis.ts Group 2: Gap Analysis (7 tools)
|
|
1024
|
+
│ ├── risks.ts Group 3: Risk Management (8 tools)
|
|
1025
|
+
│ ├── policies.ts Group 4: Policy Management (4 tools)
|
|
1026
|
+
│ ├── soa.ts Group 5: Statement of Applicability (3 tools)
|
|
1027
|
+
│ ├── audit-management.ts Group 6: Audit Management (5 tools)
|
|
1028
|
+
│ ├── evidence-tracking.ts Group 7: Evidence Tracking (5 tools)
|
|
1029
|
+
│ └── server-info.ts Group 8: Server Info (1 tool)
|
|
1030
|
+
└── transport/
|
|
1031
|
+
└── sse.ts Express SSE server for team/hosted modes
|
|
1032
|
+
|
|
1033
|
+
tests/
|
|
1034
|
+
├── fixtures/
|
|
1035
|
+
│ ├── mock-db.ts In-memory mock DB for unit tests
|
|
1036
|
+
│ └── test-db.ts Real encrypted DB fixture (macOS only)
|
|
1037
|
+
├── unit/
|
|
1038
|
+
│ ├── auth/ api-key, rbac
|
|
1039
|
+
│ ├── security/ sanitise, rate-limiter
|
|
1040
|
+
│ ├── audit/ logger
|
|
1041
|
+
│ └── tools/ One file per handler module
|
|
1042
|
+
└── integration/
|
|
1043
|
+
├── mcp-protocol.test.ts Schema and registration validation
|
|
1044
|
+
├── db-operations.test.ts Migrations, seed counts, FTS5 (macOS only)
|
|
1045
|
+
└── business-rules.test.ts All 6 enforced business rules end-to-end
|
|
1046
|
+
```
|
|
1047
|
+
|
|
1048
|
+
---
|
|
1049
|
+
|
|
1050
|
+
## Security
|
|
1051
|
+
|
|
1052
|
+
### API Key Storage
|
|
1053
|
+
|
|
1054
|
+
API keys are never stored in plaintext. Only an HMAC-SHA256 hash is persisted in the database. The raw `iso27001_...` key is printed once to stdout at generation time — there is no way to retrieve it afterwards.
|
|
1055
|
+
|
|
1056
|
+
### Database Encryption
|
|
1057
|
+
|
|
1058
|
+
The SQLite database (`isms.db`) is encrypted at rest using AES-256 via `better-sqlite3-multiple-ciphers`. The `DB_ENCRYPTION_KEY` is required at every startup and is never written to disk by the server.
|
|
1059
|
+
|
|
1060
|
+
### Tamper-Evident Audit Trail
|
|
1061
|
+
|
|
1062
|
+
Every tool call writes a row to `audit_log` with a `row_hash` computed as:
|
|
1063
|
+
|
|
1064
|
+
```
|
|
1065
|
+
SHA-256(timestamp | tool | key_hash | outcome)
|
|
1066
|
+
```
|
|
1067
|
+
|
|
1068
|
+
Any modification to an audit row after insertion will cause `verifyRowHash()` to fail. The same events are also appended in JSON-L format to `AUDIT_LOG_PATH` for off-database retention and SIEM ingestion.
|
|
1069
|
+
|
|
1070
|
+
### Production Checklist
|
|
1071
|
+
|
|
1072
|
+
- [ ] Set `NODE_ENV=production`
|
|
1073
|
+
- [ ] Set `BEHIND_TLS_PROXY=true` (the server logs a loud warning if this is absent in production)
|
|
1074
|
+
- [ ] Terminate TLS upstream (nginx, Caddy, AWS ALB, etc.)
|
|
1075
|
+
- [ ] Use `--expires` on all API keys — especially admin keys
|
|
1076
|
+
- [ ] Set `RATE_LIMIT_RPM` appropriate to your team size
|
|
1077
|
+
- [ ] Store `DB_ENCRYPTION_KEY` and `HMAC_SECRET` in a secrets manager, not in `.env`
|
|
1078
|
+
- [ ] Back up `isms.db` regularly — it is the single source of truth for your entire ISMS
|
|
1079
|
+
|
|
1080
|
+
---
|
|
1081
|
+
|
|
1082
|
+
## License
|
|
1083
|
+
|
|
1084
|
+
MIT © 2026
|