@aaa-sentinel/mcp-server 0.8.0 → 0.10.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.
Files changed (3) hide show
  1. package/README.md +14 -10
  2. package/dist/cli.js +67 -8
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -29,7 +29,7 @@ dashboard you have to remember to visit.
29
29
  only those; the scopes you leave out are simply not reachable from the assistant.
30
30
  - A **Pro** plan or above: the API is not available on the free plan. Chargeback, cost anomalies,
31
31
  unit cost, managed clients and the agent need **Business**, and the security tools also need the
32
- security add-on on the account — the table below says which.
32
+ risk and compliance add-on on the account — the table below says which.
33
33
 
34
34
  ## Configuration
35
35
 
@@ -107,15 +107,19 @@ status as plain JSON.
107
107
  | `get_dashboard` | `accountId?` | `dashboard:read` | Pro |
108
108
  | `get_cost_forecast` | `accountId` | `reports:read` | Pro |
109
109
  | `list_cost_anomalies` | `accountId?` | `reports:read` | Business |
110
- | `get_security_overview` | — | `security:read` | Pro + security add-on |
111
- | `get_security_score` | `accountId` | `security:read` | Pro + security add-on |
112
- | `list_security_findings` | `accountId`, `source?`, `category?` | `security:read` | Pro + security add-on |
113
- | `get_security_critical_changes` | `accountId` | `security:read` | Pro + security add-on |
114
- | `list_security_vulnerabilities` | `accountId` | `security:read` | Pro + security add-on |
115
- | `get_security_conformance` | `accountId` or `clientId` | `security:read` | Pro + security add-on |
116
- | `get_security_posture_history` | `accountId` or `clientId`, `days?` | `security:read` | Pro + security add-on |
110
+ | `get_security_overview` | — | `security:read` | Pro + risk and compliance add-on |
111
+ | `get_security_score` | `accountId` | `security:read` | Pro + risk and compliance add-on |
112
+ | `list_security_findings` | `accountId`, `source?`, `category?` | `security:read` | Pro + risk and compliance add-on |
113
+ | `get_security_critical_changes` | `accountId` | `security:read` | Pro + risk and compliance add-on |
114
+ | `list_security_vulnerabilities` | `accountId` | `security:read` | Pro + risk and compliance add-on |
115
+ | `get_security_tool_spend` | `accountId` | `security:read` | Pro + risk and compliance add-on |
116
+ | `get_security_conformance` | `accountId` or `clientId` | `security:read` | Pro + risk and compliance add-on |
117
+ | `get_security_posture_history` | `accountId` or `clientId`, `days?` | `security:read` | Pro + risk and compliance add-on |
117
118
  | `get_account` | `accountId` | `accounts:read` | Pro |
118
119
  | `get_account_monthly_costs` | `accountId` | `accounts:read` | Pro |
120
+ | `list_architecture_apps` | `accountId`, `limit?`, `cursor?` | `accounts:read` | Pro |
121
+ | `get_architecture_app` | `accountId`, `appId`, `limit?`, `cursor?` | `accounts:read` | Pro |
122
+ | `get_architecture_graph` | `accountId`, `app?` | `accounts:read` | Pro |
119
123
  | `get_cost_history` | `accountId` | `reports:read` | Pro |
120
124
  | `get_cost_by_tags` | `accountId` | `reports:read` | Pro |
121
125
  | `get_multicloud_report` | — | `reports:read` | Pro |
@@ -165,14 +169,14 @@ not an outage yet), `down`, or `recovering` (still counted as down until the rec
165
169
  confirmed). The last result carries a reason code such as `timeout`, `status_mismatch` or
166
170
  `queue_dlq_not_empty`; the full list is in the API reference.
167
171
 
168
- The security tools need the security add-on enabled on the account (20 €/month per account).
172
+ The security tools need the risk and compliance add-on enabled on the account (20 €/month per account).
169
173
  Without it they answer with `access: "teaser"` and no scan data, so the assistant can tell
170
174
  "not enabled" apart from "nothing found".
171
175
 
172
176
  ### Why there is nothing that writes
173
177
 
174
178
  There is no tool to approve a remediation, launch a playbook, stop an instance, start a security
175
- scan or enable the (billed) security add-on, and that is a
179
+ scan or enable the (billed) risk and compliance add-on, and that is a
176
180
  decision rather than a gap. An MCP server with write access puts a model — with its own idea of
177
181
  what is convenient, and a prompt an attacker may have influenced — inside the path that changes
178
182
  your infrastructure. Execution stays in the product, where it is gated by approvals, dry runs and
package/dist/cli.js CHANGED
@@ -6065,7 +6065,7 @@ function defineTool(def) {
6065
6065
  }
6066
6066
  var SAVINGS_TYPES = ["compute", "storage", "network", "database", "serverless", "governance"];
6067
6067
  var SECURITY_SOURCES = ["own", "corroborated", "securityhub", "guardduty", "defender", "scc"];
6068
- var SECURITY_CATEGORIES = ["security_network", "security_exposure", "security_encryption", "security_iam", "security_logging", "security_secrets"];
6068
+ var SECURITY_CATEGORIES = ["security_network", "security_exposure", "security_encryption", "security_iam", "security_logging", "security_secrets", "security_patching"];
6069
6069
  var AGENT_STATUSES = ["proposed", "pending_approval", "pending_second_approval", "approved", "executing", "completed", "failed", "cancelled", "expired"];
6070
6070
  var BillingPeriod = string2().regex(/^\d{4}-(0[1-9]|1[0-2])$/, "Use YYYY-MM");
6071
6071
  var ACCOUNT_ID = { type: "string", description: "Account identifier, as returned by list_accounts." };
@@ -6204,14 +6204,14 @@ var TOOLS = [
6204
6204
  // queda en la API y la app, no en un agente ajeno.
6205
6205
  defineTool({
6206
6206
  name: "get_security_overview",
6207
- description: 'Get the security posture of every cloud account: Score (0-100), band, findings by severity and attack chains. Accounts without the security add-on come back as access "teaser" with no data. Requires the security:read scope and the Pro plan or above.',
6207
+ description: 'Get the security posture of every cloud account: Score (0-100), band, findings by severity and attack chains. Accounts without the risk and compliance add-on come back as access "teaser" with no data. Requires the security:read scope and the Pro plan or above.',
6208
6208
  inputSchema: { type: "object", properties: {} },
6209
6209
  argsSchema: object({}),
6210
6210
  handler: async (_args, config2) => apiGet("/v1/security/overview", void 0, config2)
6211
6211
  }),
6212
6212
  defineTool({
6213
6213
  name: "get_security_score",
6214
- description: "Get the security Score of the latest security scan of one account, with its coverage (which rules could not be evaluated and which permission was missing). Requires the security:read scope, the Pro plan and the security add-on on that account.",
6214
+ description: "Get the security Score of the latest security scan of one account, with its coverage (which rules could not be evaluated and which permission was missing). Requires the security:read scope, the Pro plan and the risk and compliance add-on on that account.",
6215
6215
  inputSchema: {
6216
6216
  type: "object",
6217
6217
  properties: { accountId: { type: "string", description: "Account identifier, as returned by list_accounts." } },
@@ -6222,7 +6222,7 @@ var TOOLS = [
6222
6222
  }),
6223
6223
  defineTool({
6224
6224
  name: "list_security_findings",
6225
- description: 'List the security findings of the latest security scan of one account (up to 500, most severe first), with attack chains and a diff against the previous scan. Use category "security_iam" for the permissions view: effective administrators, unused identities, keys and service accounts, granted permissions that are not used, and assignments to deleted identities. Requires the security:read scope, the Pro plan and the security add-on on that account.',
6225
+ description: 'List the security findings of the latest security scan of one account (up to 500, most severe first), with attack chains and a diff against the previous scan. Use category "security_iam" for the permissions view: effective administrators, unused identities, keys and service accounts, granted permissions that are not used, and assignments to deleted identities. Each finding may carry resourceCost, and the response exposedCost (what the account pays per month in resources with critical or high findings): both are estimates from the latest cost scan of at most 14 days (list price or what the resource was billed), in USD and approximate, absent when there is no cost data. Each finding may also carry attribution (the Owner, Team and CostCenter tags of its resource; unowned when its tags were read and it has neither Owner nor Team; absent when its tags were not read), and the response attributionSummary (findings and exposed cost by team and by cost center); critical findings without an owner come first among the critical ones. Requires the security:read scope, the Pro plan and the risk and compliance add-on on that account.',
6226
6226
  inputSchema: {
6227
6227
  type: "object",
6228
6228
  properties: {
@@ -6249,7 +6249,7 @@ var TOOLS = [
6249
6249
  }),
6250
6250
  defineTool({
6251
6251
  name: "get_security_critical_changes",
6252
- description: "List the critical configuration changes of the last 7 days in one account (up to 100, newest first), read from CloudTrail in AWS, the activity log in Azure or the Admin Activity audit logs in GCP: public bucket, storage or snapshot, remote admin open to the internet, logging turned off, root use, admin granted. Each comes with who made it and, for rule-backed changes, whether a re-check confirmed the risk. Accounts without the security add-on return supported false and an empty list. Requires the security:read scope and the Pro plan or above.",
6252
+ description: "List the critical configuration changes of the last 7 days in one account (up to 100, newest first), read from CloudTrail in AWS, the activity log in Azure or the Admin Activity audit logs in GCP: public bucket, storage or snapshot, remote admin open to the internet, logging turned off, root use, admin granted. Each comes with who made it and, for rule-backed changes, whether a re-check confirmed the risk. Accounts without the risk and compliance add-on return supported false and an empty list. Requires the security:read scope and the Pro plan or above.",
6253
6253
  inputSchema: {
6254
6254
  type: "object",
6255
6255
  properties: { accountId: { type: "string", description: "Account identifier, as returned by list_accounts." } },
@@ -6260,7 +6260,7 @@ var TOOLS = [
6260
6260
  }),
6261
6261
  defineTool({
6262
6262
  name: "list_security_vulnerabilities",
6263
- description: "List the vulnerabilities (CVEs) that the cloud native scanner already found in one account (Amazon Inspector or ECR basic scanning, Microsoft Defender for Cloud, GCP Artifact Analysis and VM Manager), up to 200, highest priority first. Each one has the cloud severity and an effective severity that rises when the resource is exposed to the internet, has a known exploit or is unused according to a cost rule (low CPU is shown as context only). AAA Sentinel does not scan on its own: tools shows whether each scanner is active, absent or could not be read, truncated whether the cloud has more than the cap, and partial why the list may be incomplete (scanner missing in some regions or resource types listed in uncovered, failed reads, time budget, unreadable entries, expired rows). Amazon Inspector only sees image use on ECS and EKS: when the account has container Lambdas, App Runner services or images not in use there, uncovered.gaps says ecr_images_outside_ecs_eks and those images come last with imageInUse false. An account without the security add-on returns access teaser and an empty list, which does not mean it has no vulnerabilities. bySeverity counts the effective severity. Requires the security:read scope and the Pro plan or above.",
6263
+ description: "List the vulnerabilities (CVEs) that the cloud native scanner already found in one account (Amazon Inspector or ECR basic scanning, Microsoft Defender for Cloud, GCP Artifact Analysis and VM Manager), up to 200, highest priority first. Each one has the cloud severity and an effective severity that rises when the resource is exposed to the internet, has a known exploit or is unused according to a cost rule (low CPU is shown as context only). AAA Sentinel does not scan on its own: tools shows whether each scanner is active, absent or could not be read, truncated whether the cloud has more than the cap, and partial why the list may be incomplete (scanner missing in some regions or resource types listed in uncovered, failed reads, time budget, unreadable entries, expired rows). Amazon Inspector only sees image use on ECS and EKS: when the account has container Lambdas, App Runner services or images not in use there, uncovered.gaps says ecr_images_outside_ecs_eks and those images come last with imageInUse false. An account without the risk and compliance add-on returns access teaser and an empty list, which does not mean it has no vulnerabilities. bySeverity counts the effective severity. Requires the security:read scope and the Pro plan or above.",
6264
6264
  inputSchema: {
6265
6265
  type: "object",
6266
6266
  properties: { accountId: { type: "string", description: "Account identifier, as returned by list_accounts." } },
@@ -6269,6 +6269,17 @@ var TOOLS = [
6269
6269
  argsSchema: object({ accountId: string2().min(1) }),
6270
6270
  handler: async ({ accountId }, config2) => apiGet("/v1/security/vulnerabilities", { accountId }, config2)
6271
6271
  }),
6272
+ defineTool({
6273
+ name: "get_security_tool_spend",
6274
+ description: "Get what one account pays for the cloud's own security tools (AWS Security Hub, GuardDuty, Inspector, Config, WAF and CloudTrail; Microsoft Defender for Cloud and Azure WAF; GCP Security Command Center and Cloud Armor) this month so far and last month, and what AAA Sentinel does with each one: imports and deduplicates its findings, uses it as a data source, checks it, or does not use it for its diagnosis. Answers whether you pay twice for the same thing: overlap counts own findings the tool also reports (corroborated) and findings only the tool brings (importedOnly; capped means at least). Each tool has current and previous ({ spendUsd, costScannedAt }, null when that month has no real bill) and billing.current/previous carry totalSpendUsd (totalPartial when some tool has no amount). Amounts are in USD from the real bill of the latest cost scan of each month; spendUsd 0 means the bill read has no charge for that service, and null means it is not billed separately or its bill name is not confirmed and does not appear. state null means no state is available (no scan, an older scan, or a tool whose state is not read). CloudTrail is the whole service (management and data events together); Azure WAF (azurewaf) and Cloud Armor have no line of their own in the bill. On AWS the payer account sees the whole organization and on GCP the whole billing account (billing.scope). That AAA Sentinel does not use a tool does not mean it can be turned off. Requires the security:read scope, the Pro plan or above and the risk and compliance add-on on the account.",
6275
+ inputSchema: {
6276
+ type: "object",
6277
+ properties: { accountId: { type: "string", description: "Account identifier, as returned by list_accounts." } },
6278
+ required: ["accountId"]
6279
+ },
6280
+ argsSchema: object({ accountId: string2().min(1) }),
6281
+ handler: async ({ accountId }, config2) => apiGet("/v1/security/tools", { accountId }, config2)
6282
+ }),
6272
6283
  defineTool({
6273
6284
  name: "get_security_conformance",
6274
6285
  description: "Get CIS benchmark coverage for one account, or for every account of a managed client (clientId, Business plan). Pass exactly one of accountId or clientId. Requires the security:read scope, plus reports:read when using clientId.",
@@ -6286,7 +6297,7 @@ var TOOLS = [
6286
6297
  }),
6287
6298
  defineTool({
6288
6299
  name: "get_security_posture_history",
6289
- description: "Get how the security posture changed over 30, 90 or 365 days (default 90) for one account, or for every account with the security add-on of a managed client (clientId, Business plan, up to 20 accounts; omitted counts the rest). Returns points, one per UTC day (the last scan of that day: score, scored/total rules, open findings by severity, events), and summary: from/to (Score of the first and last point), resolved (distinct findings gone in a scan that fully evaluated their rule), opened (new, from rules already fully evaluated before), surfaced (new but not comparable: rule not fully evaluated before, or an external tool), unverified (gone without confirmation), meanFixDays by severity, comparable and notComparableReasons. When comparable is false, do not describe the Score change as the account getting better or worse. Points keep the Score computed each day, without discounting risks accepted later (acceptedRisks). Pass exactly one of accountId or clientId. Requires the security:read scope, plus reports:read when using clientId.",
6300
+ description: "Get how the security posture changed over 30, 90 or 365 days (default 90) for one account, or for every account with the risk and compliance add-on of a managed client (clientId, Business plan, up to 20 accounts; omitted counts the rest). Returns points, one per UTC day (the last scan of that day: score, scored/total rules, open findings by severity, events), and summary: from/to (Score of the first and last point), resolved (distinct findings gone in a scan that fully evaluated their rule), opened (new, from rules already fully evaluated before), surfaced (new but not comparable: rule not fully evaluated before, or an external tool), unverified (gone without confirmation), meanFixDays by severity, comparable and notComparableReasons. When comparable is false, do not describe the Score change as the account getting better or worse. Points keep the Score computed each day, without discounting risks accepted later (acceptedRisks). Each point also has exposedCost (monthly spend on resources with critical or high findings, or null without cost data), and the summary has exposedCost (from/to) and comboSavings (monthly spend no longer paid after exposed unused resources were deleted, counted only when the resource stopped existing in a scan that fully evaluated its rules, at the last known amount of each resource). Each point uses the cost scan that was current when that security scan ran; amounts are estimates (list price or what the resource was billed), in USD and approximate. Pass exactly one of accountId or clientId. Requires the security:read scope, plus reports:read when using clientId.",
6290
6301
  inputSchema: {
6291
6302
  type: "object",
6292
6303
  properties: {
@@ -6319,6 +6330,54 @@ var TOOLS = [
6319
6330
  argsSchema: object({ accountId: string2().min(1) }),
6320
6331
  handler: async ({ accountId }, config2) => apiGet(`/v1/accounts/${encodeURIComponent(accountId)}/monthly-costs`, void 0, config2)
6321
6332
  }),
6333
+ // ── Mapa de arquitectura ───────────────────────────────────
6334
+ defineTool({
6335
+ name: "list_architecture_apps",
6336
+ description: 'List the applications of one cloud account in the architecture map (AWS today; other providers return supported false), most expensive first. Each application comes from a tag (source "tag"), a CloudFormation stack ("stack"), a manual grouping ("manual") or a suggestion not yet confirmed ("suggested"), with its component count, regions, monthlyUsd (sum of priced components, null when none has a price), cost findings and their savingsUsd, and tag coverage. unassigned summarizes components with no application. Amounts: fields ending in Usd are monthly estimates in USD; the sibling without the suffix (monthly, savings) is the same amount in the organization currency (currency.code, approximate). snapshot says which map version this is (builtAt) and what could not be read. Configuration metadata only, never traffic or contents. Paginated: pass nextCursor as cursor; a cursor from before the map changed is rejected and you start again. Requires the accounts:read scope.',
6337
+ inputSchema: objectWith(
6338
+ {
6339
+ accountId: ACCOUNT_ID,
6340
+ limit: { type: "integer", minimum: 1, maximum: 500, description: "Page size (1-500, default 100)." },
6341
+ cursor: CURSOR
6342
+ },
6343
+ ["accountId"]
6344
+ ),
6345
+ argsSchema: object({ accountId: string2().min(1), limit: number2().int().min(1).max(500).optional(), cursor: string2().min(1).optional() }),
6346
+ handler: async ({ accountId, limit, cursor }, config2) => apiGet(`/v1/architecture/accounts/${encodeURIComponent(accountId)}/apps`, { limit: asText(limit), cursor }, config2)
6347
+ }),
6348
+ defineTool({
6349
+ name: "get_architecture_app",
6350
+ description: 'Get one application of the architecture map with its components, most expensive first: type, region, customer tags, monthlyUsd (null means no known price), cost findings and savingsUsd, whether it is reachable from the internet (exposed) and how it was assigned (assignedBy: tag, manual, stack, suggested or none). Amounts: fields ending in Usd are monthly estimates in USD; the sibling without the suffix (monthly, savings) is the same amount in the organization currency (currency.code, approximate). Use appId "unassigned" for components with no application. Paginated like list_architecture_apps. Requires the accounts:read scope.',
6351
+ inputSchema: objectWith(
6352
+ {
6353
+ accountId: ACCOUNT_ID,
6354
+ appId: { type: "string", description: 'Application identifier, as returned by list_architecture_apps, or "unassigned".' },
6355
+ limit: { type: "integer", minimum: 1, maximum: 1e3, description: "Page size (1-1000, default 200)." },
6356
+ cursor: CURSOR
6357
+ },
6358
+ ["accountId", "appId"]
6359
+ ),
6360
+ argsSchema: object({
6361
+ accountId: string2().min(1),
6362
+ appId: string2().min(1),
6363
+ limit: number2().int().min(1).max(1e3).optional(),
6364
+ cursor: string2().min(1).optional()
6365
+ }),
6366
+ handler: async ({ accountId, appId, limit, cursor }, config2) => apiGet(`/v1/architecture/accounts/${encodeURIComponent(accountId)}/apps/${encodeURIComponent(appId)}`, { limit: asText(limit), cursor }, config2)
6367
+ }),
6368
+ defineTool({
6369
+ name: "get_architecture_graph",
6370
+ description: 'Get how things connect in the architecture map. Without app: one card per application and the links between applications (counts of configured, allowed and resilience connections), plus the internet and outside accounts they talk to. With app: its components (nodes), the edges that touch them, the endpoints outside the application and the network containers (region, VPC, subnet). Every edge says where it comes from: kind "configured" (configuration links A to B) or "allowed" (a network rule permits it), its relation (invokes, routes_to, subscribes, network_allows...) and proof (the provider API call and identifier that show it); never observed traffic, so do not describe edges as traffic. Bounded to 1,500 components and 4,000 edges per application (truncated says so); a large application can return several megabytes, so call it with app only when you need the connections, and use get_architecture_app (paginated) to list components. Amounts: fields ending in Usd are monthly estimates in USD; the sibling without the suffix (monthly, savings) is the same amount in the organization currency (currency.code, approximate). Requires the accounts:read scope and the Pro or Business plan.',
6371
+ inputSchema: objectWith(
6372
+ {
6373
+ accountId: ACCOUNT_ID,
6374
+ app: { type: "string", description: 'Application identifier from list_architecture_apps, or "unassigned" (optional; without it, the account level).' }
6375
+ },
6376
+ ["accountId"]
6377
+ ),
6378
+ argsSchema: object({ accountId: string2().min(1), app: string2().min(1).optional() }),
6379
+ handler: async ({ accountId, app }, config2) => apiGet(`/v1/architecture/accounts/${encodeURIComponent(accountId)}/graph`, { app }, config2)
6380
+ }),
6322
6381
  defineTool({
6323
6382
  name: "get_cost_history",
6324
6383
  description: "Get the spend history of one cloud account for the last 12 months. Requires the reports:read scope and the Pro plan or above.",
@@ -6640,7 +6699,7 @@ function findTool(name) {
6640
6699
 
6641
6700
  // src/protocol.ts
6642
6701
  var SERVER_NAME = "aaa-sentinel-mcp";
6643
- var SERVER_VERSION = "0.8.0";
6702
+ var SERVER_VERSION = "0.10.0";
6644
6703
  var SUPPORTED_PROTOCOL_VERSIONS = ["2025-06-18", "2025-03-26", "2024-11-05"];
6645
6704
  var PARSE_ERROR = -32700;
6646
6705
  var INVALID_REQUEST = -32600;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aaa-sentinel/mcp-server",
3
- "version": "0.8.0",
3
+ "version": "0.10.0",
4
4
  "description": "Read-only MCP server for AAA Sentinel: query cloud costs, savings, security posture, AI spend, uptime monitoring, the remediation agent and managed clients from an AI assistant",
5
5
  "license": "MIT",
6
6
  "type": "module",