aws-security-mcp 0.1.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/README.md ADDED
@@ -0,0 +1,235 @@
1
+ # aws-security-mcp
2
+
3
+ MCP server for automated AWS security scanning — 7 modules, risk scoring, zero write operations.
4
+
5
+ <!-- badges -->
6
+ ![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)
7
+ ![Node >= 18](https://img.shields.io/badge/node-%3E%3D18-brightgreen.svg)
8
+ ![MCP Protocol](https://img.shields.io/badge/MCP-1.12-purple.svg)
9
+
10
+ ## Features
11
+
12
+ - **7 Security Scan Modules** — Security Groups, S3, IAM, CloudTrail, RDS, EBS, VPC
13
+ - **Risk Scoring** — every finding scored 0-10 with severity (CRITICAL/HIGH/MEDIUM/LOW) and priority (P0-P3)
14
+ - **100% Read-Only** — uses only Describe/Get/List API calls; never modifies your AWS resources
15
+ - **Parallel Execution** — all 7 modules run concurrently via `Promise.allSettled`
16
+ - **Markdown Report Generation** — structured report with executive summary, findings by severity, and prioritized recommendations
17
+ - **MCP Resources** — embedded security rules and risk scoring model documentation
18
+ - **MCP Prompts** — pre-built workflows for full scans and finding analysis
19
+
20
+ ## Quick Start
21
+
22
+ ### 1. Install
23
+
24
+ ```bash
25
+ npm install
26
+ npm run build
27
+ ```
28
+
29
+ ### 2. Configure AWS Credentials
30
+
31
+ The server uses the standard AWS SDK credential chain. Any of the following will work:
32
+
33
+ ```bash
34
+ # Environment variables
35
+ export AWS_ACCESS_KEY_ID=AKIA...
36
+ export AWS_SECRET_ACCESS_KEY=...
37
+ export AWS_REGION=ap-northeast-1
38
+
39
+ # Or use an AWS profile
40
+ export AWS_PROFILE=your-profile
41
+
42
+ # Or run on an EC2 instance / ECS task with an IAM role attached
43
+ ```
44
+
45
+ See [Recommended IAM Policy](#recommended-iam-policy) below for the minimum permissions required.
46
+
47
+ ### 3. Configure Your AI Tool
48
+
49
+ Add the MCP server to your AI tool's configuration:
50
+
51
+ #### Kiro
52
+
53
+ `.kiro/settings/mcp.json`:
54
+
55
+ ```json
56
+ {
57
+ "mcpServers": {
58
+ "aws-security": {
59
+ "command": "aws-security-mcp",
60
+ "args": ["--region", "ap-northeast-1"]
61
+ }
62
+ }
63
+ }
64
+ ```
65
+
66
+ #### Claude Code
67
+
68
+ `.claude/settings.json`:
69
+
70
+ ```json
71
+ {
72
+ "mcpServers": {
73
+ "aws-security": {
74
+ "command": "aws-security-mcp",
75
+ "args": ["--region", "ap-northeast-1"]
76
+ }
77
+ }
78
+ }
79
+ ```
80
+
81
+ #### Cursor
82
+
83
+ Add in Cursor MCP settings:
84
+
85
+ ```json
86
+ {
87
+ "mcpServers": {
88
+ "aws-security": {
89
+ "command": "aws-security-mcp",
90
+ "args": ["--region", "ap-northeast-1"]
91
+ }
92
+ }
93
+ }
94
+ ```
95
+
96
+ ### 4. Use
97
+
98
+ Ask your AI tool to run a security scan:
99
+
100
+ > "Run a full AWS security scan and generate a report"
101
+
102
+ Or use the built-in `security-scan` prompt for a guided workflow.
103
+
104
+ ## Available Tools
105
+
106
+ | Tool | Description |
107
+ |------|-------------|
108
+ | `scan_all` | Run all 7 security scanners in parallel |
109
+ | `scan_sg` | Scan EC2 security groups for overly permissive rules |
110
+ | `scan_s3` | Check S3 buckets for public access, encryption, versioning |
111
+ | `scan_iam` | Audit IAM users, root account, access keys, policies |
112
+ | `scan_cloudtrail` | Validate CloudTrail logging configuration |
113
+ | `scan_rds` | Scan RDS instances for public access, encryption, backups |
114
+ | `scan_ebs` | Check EBS volumes and snapshots for encryption and public sharing |
115
+ | `scan_vpc` | Review VPC flow logs, default VPC usage, default security groups |
116
+ | `generate_report` | Generate a Markdown report from scan results |
117
+ | `list_modules` | List available scan modules with descriptions |
118
+
119
+ All tools accept an optional `region` parameter (defaults to the server's configured region).
120
+
121
+ ## Recommended IAM Policy
122
+
123
+ Attach this policy to the IAM user or role running the scanner. All actions are read-only.
124
+
125
+ ```json
126
+ {
127
+ "Version": "2012-10-17",
128
+ "Statement": [
129
+ {
130
+ "Sid": "SecurityScannerReadOnly",
131
+ "Effect": "Allow",
132
+ "Action": [
133
+ "ec2:DescribeSecurityGroups",
134
+ "ec2:DescribeInstances",
135
+ "ec2:DescribeVolumes",
136
+ "ec2:DescribeSnapshots",
137
+ "ec2:DescribeSnapshotAttribute",
138
+ "ec2:GetEbsEncryptionByDefault",
139
+ "ec2:DescribeVpcs",
140
+ "ec2:DescribeFlowLogs",
141
+
142
+ "s3:ListAllMyBuckets",
143
+ "s3:GetBucketPublicAccessBlock",
144
+ "s3:GetBucketAcl",
145
+ "s3:GetBucketPolicy",
146
+ "s3:GetBucketPolicyStatus",
147
+ "s3:GetEncryptionConfiguration",
148
+ "s3:GetBucketVersioning",
149
+
150
+ "iam:GetAccountSummary",
151
+ "iam:ListUsers",
152
+ "iam:ListAccessKeys",
153
+ "iam:GetAccessKeyLastUsed",
154
+ "iam:ListAttachedUserPolicies",
155
+ "iam:GenerateCredentialReport",
156
+ "iam:GetCredentialReport",
157
+
158
+ "cloudtrail:DescribeTrails",
159
+ "cloudtrail:GetTrailStatus",
160
+ "cloudtrail:GetEventSelectors",
161
+
162
+ "rds:DescribeDBInstances",
163
+
164
+ "sts:GetCallerIdentity"
165
+ ],
166
+ "Resource": "*"
167
+ }
168
+ ]
169
+ }
170
+ ```
171
+
172
+ ## Scan Modules
173
+
174
+ | Module | What It Checks | Risk Score Range |
175
+ |--------|---------------|-----------------|
176
+ | **Security Groups** | Open ports to 0.0.0.0/0 (SSH, RDP, databases), all-ports rules | 7.5 - 9.5 |
177
+ | **S3** | Public ACLs, public bucket policies, Block Public Access, encryption, versioning | 3.0 - 9.5 |
178
+ | **IAM** | Root MFA, root access keys, inactive users, old access keys, over-permissive policies | 5.0 - 10.0 |
179
+ | **CloudTrail** | Trail existence, multi-region logging, log validation, CloudWatch integration, management events | 5.5 - 9.5 |
180
+ | **RDS** | Public accessibility, storage encryption, backup retention, deletion protection | 4.0 - 8.0 |
181
+ | **EBS** | Default encryption, unencrypted volumes, unencrypted snapshots, public snapshots | 5.5 - 9.5 |
182
+ | **VPC** | Default VPC usage, VPC Flow Logs, default security group rules | 5.5 - 7.0 |
183
+
184
+ ### Risk Scoring
185
+
186
+ | Score | Severity | Priority |
187
+ |-------|----------|----------|
188
+ | 9.0 - 10.0 | CRITICAL | P0 |
189
+ | 7.0 - 8.9 | HIGH | P1 |
190
+ | 4.0 - 6.9 | MEDIUM | P2 |
191
+ | 0.0 - 3.9 | LOW | P3 |
192
+
193
+ ## Output Format
194
+
195
+ ### Scan Results (JSON)
196
+
197
+ Each scan tool returns structured JSON:
198
+
199
+ ```json
200
+ {
201
+ "module": "security_group",
202
+ "status": "success",
203
+ "resourcesScanned": 12,
204
+ "findingsCount": 3,
205
+ "scanTimeMs": 1250,
206
+ "findings": [
207
+ {
208
+ "severity": "CRITICAL",
209
+ "title": "Security group sg-abc123 allows SSH (22) from 0.0.0.0/0",
210
+ "resourceType": "AWS::EC2::SecurityGroup",
211
+ "resourceId": "sg-abc123",
212
+ "resourceArn": "arn:aws:ec2:ap-northeast-1:123456789012:security-group/sg-abc123",
213
+ "region": "ap-northeast-1",
214
+ "description": "...",
215
+ "impact": "...",
216
+ "riskScore": 9.0,
217
+ "remediationSteps": ["..."],
218
+ "priority": "P0"
219
+ }
220
+ ]
221
+ }
222
+ ```
223
+
224
+ ### Markdown Report
225
+
226
+ The `generate_report` tool produces a Markdown report with:
227
+
228
+ - **Executive Summary** — account, region, duration, finding counts by severity
229
+ - **Findings by Severity** — grouped and sorted by risk score
230
+ - **Scan Statistics** — per-module resource counts and status
231
+ - **Recommendations** — prioritized action items
232
+
233
+ ## License
234
+
235
+ MIT
@@ -0,0 +1,2 @@
1
+ /*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */
2
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-ease:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-orange-400:oklch(75% .183 55.934);--color-orange-500:oklch(70.5% .213 47.604);--color-yellow-400:oklch(85.2% .199 91.936);--color-yellow-500:oklch(79.5% .184 86.047);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-500:oklch(62.3% .214 259.815);--color-slate-50:oklch(98.4% .003 247.858);--color-slate-100:oklch(96.8% .007 247.896);--color-slate-200:oklch(92.9% .013 255.508);--color-slate-300:oklch(86.9% .022 252.894);--color-slate-400:oklch(70.4% .04 256.788);--color-slate-500:oklch(55.4% .046 257.417);--color-slate-600:oklch(44.6% .043 257.281);--color-slate-700:oklch(37.2% .044 257.287);--color-slate-800:oklch(27.9% .041 260.031);--color-slate-900:oklch(20.8% .042 265.755);--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-3xl:1.875rem;--text-3xl--line-height:calc(2.25 / 1.875);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--leading-tight:1.25;--radius-lg:.5rem;--ease-in:cubic-bezier(.4, 0, 1, 1);--ease-out:cubic-bezier(0, 0, .2, 1);--ease-in-out:cubic-bezier(.4, 0, .2, 1);--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.inset-0{inset:calc(var(--spacing) * 0)}.start{inset-inline-start:var(--spacing)}.end{inset-inline-end:var(--spacing)}.top-0{top:calc(var(--spacing) * 0)}.right-0{right:calc(var(--spacing) * 0)}.left-0{left:calc(var(--spacing) * 0)}.z-10{z-index:10}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-16{margin-top:calc(var(--spacing) * 16)}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline-block{display:inline-block}.table{display:table}.h-\[300px\]{height:300px}.h-screen{height:100vh}.min-h-screen{min-height:100vh}.w-64{width:calc(var(--spacing) * 64)}.w-full{width:100%}.flex-1{flex:1}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.cursor-pointer{cursor:pointer}.resize{resize:both}.list-inside{list-style-position:inside}.list-decimal{list-style-type:decimal}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-6{gap:calc(var(--spacing) * 6)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-x-auto{overflow-x:auto}.rounded{border-radius:.25rem}.rounded-lg{border-radius:var(--radius-lg)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-blue-500\/30{border-color:#3080ff4d}@supports (color:color-mix(in lab, red, red)){.border-blue-500\/30{border-color:color-mix(in oklab, var(--color-blue-500) 30%, transparent)}}.border-current{border-color:currentColor}.border-green-500\/30{border-color:#00c7584d}@supports (color:color-mix(in lab, red, red)){.border-green-500\/30{border-color:color-mix(in oklab, var(--color-green-500) 30%, transparent)}}.border-orange-500\/30{border-color:#fe6e004d}@supports (color:color-mix(in lab, red, red)){.border-orange-500\/30{border-color:color-mix(in oklab, var(--color-orange-500) 30%, transparent)}}.border-red-500\/30{border-color:#fb2c364d}@supports (color:color-mix(in lab, red, red)){.border-red-500\/30{border-color:color-mix(in oklab, var(--color-red-500) 30%, transparent)}}.border-slate-700{border-color:var(--color-slate-700)}.border-yellow-500\/30{border-color:#edb2004d}@supports (color:color-mix(in lab, red, red)){.border-yellow-500\/30{border-color:color-mix(in oklab, var(--color-yellow-500) 30%, transparent)}}.bg-blue-500\/20{background-color:#3080ff33}@supports (color:color-mix(in lab, red, red)){.bg-blue-500\/20{background-color:color-mix(in oklab, var(--color-blue-500) 20%, transparent)}}.bg-green-500\/20{background-color:#00c75833}@supports (color:color-mix(in lab, red, red)){.bg-green-500\/20{background-color:color-mix(in oklab, var(--color-green-500) 20%, transparent)}}.bg-orange-500\/20{background-color:#fe6e0033}@supports (color:color-mix(in lab, red, red)){.bg-orange-500\/20{background-color:color-mix(in oklab, var(--color-orange-500) 20%, transparent)}}.bg-red-500\/20{background-color:#fb2c3633}@supports (color:color-mix(in lab, red, red)){.bg-red-500\/20{background-color:color-mix(in oklab, var(--color-red-500) 20%, transparent)}}.bg-slate-800{background-color:var(--color-slate-800)}.bg-slate-800\/30{background-color:#1d293d4d}@supports (color:color-mix(in lab, red, red)){.bg-slate-800\/30{background-color:color-mix(in oklab, var(--color-slate-800) 30%, transparent)}}.bg-slate-800\/50{background-color:#1d293d80}@supports (color:color-mix(in lab, red, red)){.bg-slate-800\/50{background-color:color-mix(in oklab, var(--color-slate-800) 50%, transparent)}}.bg-slate-800\/80{background-color:#1d293dcc}@supports (color:color-mix(in lab, red, red)){.bg-slate-800\/80{background-color:color-mix(in oklab, var(--color-slate-800) 80%, transparent)}}.bg-slate-900{background-color:var(--color-slate-900)}.bg-yellow-500\/20{background-color:#edb20033}@supports (color:color-mix(in lab, red, red)){.bg-yellow-500\/20{background-color:color-mix(in oklab, var(--color-yellow-500) 20%, transparent)}}.p-4{padding:calc(var(--spacing) * 4)}.p-6{padding:calc(var(--spacing) * 6)}.p-8{padding:calc(var(--spacing) * 8)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.text-center{text-align:center}.text-left{text-align:left}.font-mono{font-family:var(--font-mono)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.whitespace-nowrap{white-space:nowrap}.text-blue-400{color:var(--color-blue-400)}.text-green-400{color:var(--color-green-400)}.text-orange-400{color:var(--color-orange-400)}.text-red-400{color:var(--color-red-400)}.text-slate-50{color:var(--color-slate-50)}.text-slate-100{color:var(--color-slate-100)}.text-slate-200{color:var(--color-slate-200)}.text-slate-300{color:var(--color-slate-300)}.text-slate-400{color:var(--color-slate-400)}.text-slate-500{color:var(--color-slate-500)}.text-slate-600{color:var(--color-slate-600)}.text-yellow-400{color:var(--color-yellow-400)}.capitalize{text-transform:capitalize}.italic{font-style:italic}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.invert{--tw-invert:invert(100%);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.ease-in{--tw-ease:var(--ease-in);transition-timing-function:var(--ease-in)}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.select-none{-webkit-user-select:none;user-select:none}@media (hover:hover){.hover\:border-slate-500:hover{border-color:var(--color-slate-500)}.hover\:bg-slate-700\/50:hover{background-color:#31415880}@supports (color:color-mix(in lab, red, red)){.hover\:bg-slate-700\/50:hover{background-color:color-mix(in oklab, var(--color-slate-700) 50%, transparent)}}.hover\:text-slate-200:hover{color:var(--color-slate-200)}}@media (width>=40rem){.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (width>=48rem){.md\:col-span-2{grid-column:span 2/span 2}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (width>=64rem){.lg\:mt-0{margin-top:calc(var(--spacing) * 0)}.lg\:ml-64{margin-left:calc(var(--spacing) * 64)}.lg\:flex{display:flex}.lg\:hidden{display:none}.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}}}body{color:#f8fafc;background-color:#0f172a;margin:0;font-family:Inter,system-ui,-apple-system,sans-serif}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:#1e293b}::-webkit-scrollbar-thumb{background:#475569;border-radius:4px}::-webkit-scrollbar-thumb:hover{background:#64748b}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}