@atomicmail/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 +233 -0
- package/esm/lib/src/consts.d.ts +13 -0
- package/esm/lib/src/consts.d.ts.map +1 -0
- package/esm/lib/src/consts.js +12 -0
- package/esm/mcp/src/auth-session.d.ts +88 -0
- package/esm/mcp/src/auth-session.d.ts.map +1 -0
- package/esm/mcp/src/auth-session.js +378 -0
- package/esm/mcp/src/credentials.d.ts +20 -0
- package/esm/mcp/src/credentials.d.ts.map +1 -0
- package/esm/mcp/src/credentials.js +83 -0
- package/esm/mcp/src/docs-content.d.ts +4 -0
- package/esm/mcp/src/docs-content.d.ts.map +1 -0
- package/esm/mcp/src/docs-content.js +405 -0
- package/esm/mcp/src/main.d.ts +3 -0
- package/esm/mcp/src/main.d.ts.map +1 -0
- package/esm/mcp/src/main.js +116 -0
- package/esm/mcp/src/tools/docs.d.ts +3 -0
- package/esm/mcp/src/tools/docs.d.ts.map +1 -0
- package/esm/mcp/src/tools/docs.js +22 -0
- package/esm/mcp/src/tools/jmap.d.ts +4 -0
- package/esm/mcp/src/tools/jmap.d.ts.map +1 -0
- package/esm/mcp/src/tools/jmap.js +202 -0
- package/esm/mcp/src/tools/register.d.ts +4 -0
- package/esm/mcp/src/tools/register.d.ts.map +1 -0
- package/esm/mcp/src/tools/register.js +79 -0
- package/esm/package.json +3 -0
- package/package.json +43 -0
package/README.md
ADDED
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# @atomicmail/mcp
|
|
2
|
+
|
|
3
|
+
AtomicMail MCP server — a local stdio Model Context Protocol server that gives
|
|
4
|
+
an AI agent a programmable email inbox over JMAP, with automatic Proof-of-Work
|
|
5
|
+
auth and capability-token rotation.
|
|
6
|
+
|
|
7
|
+
The server is authored in TypeScript on Deno and built with
|
|
8
|
+
[`dnt`](https://jsr.io/@deno/dnt) into a Node-compatible npm package, so the
|
|
9
|
+
**same source** runs unchanged on Deno, Node, and Bun.
|
|
10
|
+
|
|
11
|
+
It is the MCP companion to [`@atomic-mail/agent-skill`](../../skill/) — a
|
|
12
|
+
CLI-first skill with identical credential semantics. The MCP and the skill share
|
|
13
|
+
the same on-disk credential layout (`credentials.json` + `session.jwt` +
|
|
14
|
+
`capability.jwt`), so you can mix and match the two freely.
|
|
15
|
+
|
|
16
|
+
## Tools exposed
|
|
17
|
+
|
|
18
|
+
| Tool | Description |
|
|
19
|
+
| -------------- | ----------------------------------------------------------------- |
|
|
20
|
+
| `register` | PoW signup. Persists credentials to disk; returns the API key. |
|
|
21
|
+
| `jmap_session` | `GET /.well-known/jmap` — discover accountId + mailbox URLs. |
|
|
22
|
+
| `jmap_request` | Send any JMAP method-call batch. Inline or via saved preset file. |
|
|
23
|
+
| `get_docs` | Built-in docs. Topics include `installation`, `presets`, `auth`. |
|
|
24
|
+
|
|
25
|
+
## Install
|
|
26
|
+
|
|
27
|
+
The package is published to npm. Any of these work:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npx -y @atomicmail/mcp
|
|
31
|
+
bunx @atomicmail/mcp
|
|
32
|
+
deno run -A npm:@atomicmail/mcp/atomicmail-mcp
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
You don't typically run it directly — your MCP host (Cursor, Claude Desktop,
|
|
36
|
+
...) will spawn it for you. See the configuration section below.
|
|
37
|
+
|
|
38
|
+
## Configure (priority order)
|
|
39
|
+
|
|
40
|
+
The server resolves configuration from two sources, with environment variables
|
|
41
|
+
overriding individual fields from the file:
|
|
42
|
+
|
|
43
|
+
1. **`credentials.json` in the credential directory.** The same file produced by
|
|
44
|
+
`atomic-mail-signup`. Default location: `~/.atomicmail/credentials.json`.
|
|
45
|
+
Override the directory with `ATOMIC_MAIL_CREDENTIALS_DIR`.
|
|
46
|
+
2. **Environment variables.** Useful for hermetic MCP host configs:
|
|
47
|
+
|
|
48
|
+
| Variable | Required | Description |
|
|
49
|
+
| ----------------------------- | -------- | --------------------------------- |
|
|
50
|
+
| `ATOMIC_MAIL_AUTH_URL` | Yes\* | Auth service base URL |
|
|
51
|
+
| `ATOMIC_MAIL_API_URL` | Yes\* | API service / JMAP base URL |
|
|
52
|
+
| `ATOMIC_MAIL_SCRYPT_SALT` | No | Optional PoW salt override |
|
|
53
|
+
| `ATOMIC_MAIL_API_KEY` | No | Existing API key (skips signup) |
|
|
54
|
+
| `ATOMIC_MAIL_CREDENTIALS_DIR` | No | Override default credential dir |
|
|
55
|
+
|
|
56
|
+
\* "Yes" means at least one source must provide `authUrl` and `apiUrl`. If
|
|
57
|
+
`credentials.json` is present and complete, no env vars are required. PoW
|
|
58
|
+
salt defaults to the built-in value that matches `auth-service`.
|
|
59
|
+
|
|
60
|
+
If neither source resolves `authUrl` and `apiUrl`, the server fails fast on
|
|
61
|
+
startup with the missing fields listed.
|
|
62
|
+
|
|
63
|
+
## Credential files
|
|
64
|
+
|
|
65
|
+
All three live in the credential directory and are written with mode `0600`:
|
|
66
|
+
|
|
67
|
+
- `credentials.json` — `{ apiKey, inboxId, authUrl, apiUrl, scryptSalt }`.
|
|
68
|
+
Long-lived. Treat as a secret — copying it to a new machine is enough to log
|
|
69
|
+
in.
|
|
70
|
+
- `session.jwt` — 4-hour TTL, rotated automatically via PoW when near expiry.
|
|
71
|
+
- `capability.jwt` — 2-minute TTL, rotated automatically before each JMAP
|
|
72
|
+
request when near expiry.
|
|
73
|
+
|
|
74
|
+
Because the on-disk layout is identical to the
|
|
75
|
+
[`@atomic-mail/agent-skill`](../../skill/) skill, you can:
|
|
76
|
+
|
|
77
|
+
- Bootstrap once with `atomic-mail-signup`, then point the MCP at the same
|
|
78
|
+
directory.
|
|
79
|
+
- Run `atomic-mail-jmap` from a shell while the MCP is also running — both will
|
|
80
|
+
see fresh JWTs as the other rotates them.
|
|
81
|
+
|
|
82
|
+
## MCP host configuration examples
|
|
83
|
+
|
|
84
|
+
### Cursor
|
|
85
|
+
|
|
86
|
+
`~/.cursor/mcp.json` (or per-project `.cursor/mcp.json`):
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"mcpServers": {
|
|
91
|
+
"atomicmail": {
|
|
92
|
+
"command": "npx",
|
|
93
|
+
"args": ["-y", "@atomicmail/mcp"],
|
|
94
|
+
"env": {
|
|
95
|
+
"ATOMIC_MAIL_AUTH_URL": "https://auth.atomicmail.io",
|
|
96
|
+
"ATOMIC_MAIL_API_URL": "https://api.atomicmail.io"
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Claude Desktop
|
|
104
|
+
|
|
105
|
+
`claude_desktop_config.json`:
|
|
106
|
+
|
|
107
|
+
```json
|
|
108
|
+
{
|
|
109
|
+
"mcpServers": {
|
|
110
|
+
"atomicmail": {
|
|
111
|
+
"command": "npx",
|
|
112
|
+
"args": ["-y", "@atomicmail/mcp"],
|
|
113
|
+
"env": {
|
|
114
|
+
"ATOMIC_MAIL_AUTH_URL": "https://auth.atomicmail.io",
|
|
115
|
+
"ATOMIC_MAIL_API_URL": "https://api.atomicmail.io"
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Sharing credentials with the skill CLI
|
|
123
|
+
|
|
124
|
+
If you've already run `atomic-mail-signup`, no auth-service URL needs to be
|
|
125
|
+
repeated — the MCP reads URLs (and optional salt override) from `credentials.json`:
|
|
126
|
+
|
|
127
|
+
```json
|
|
128
|
+
{
|
|
129
|
+
"mcpServers": {
|
|
130
|
+
"atomicmail": {
|
|
131
|
+
"command": "npx",
|
|
132
|
+
"args": ["-y", "@atomicmail/mcp"],
|
|
133
|
+
"env": {
|
|
134
|
+
"ATOMIC_MAIL_CREDENTIALS_DIR": "/Users/me/.atomicmail"
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
When you skip the env entirely (`{}`), the MCP defaults to `~/.atomicmail/`.
|
|
142
|
+
|
|
143
|
+
## Typical agent workflow
|
|
144
|
+
|
|
145
|
+
Once the MCP is wired in, an agent will:
|
|
146
|
+
|
|
147
|
+
1. Call `register` (only on the first run, with no existing API key).
|
|
148
|
+
2. Call `jmap_session` to discover the `accountId` and the INBOX id.
|
|
149
|
+
3. Call `jmap_request` with whatever method calls it needs (inline) or reference
|
|
150
|
+
saved presets via `opsFile`.
|
|
151
|
+
4. Call `get_docs` with topic `presets` or `jmap_cheatsheet` for ready-to-use
|
|
152
|
+
JMAP recipes.
|
|
153
|
+
|
|
154
|
+
## JMAP presets (the `opsFile` parameter)
|
|
155
|
+
|
|
156
|
+
`jmap_request` accepts either an inline `methodCalls` array or an `opsFile`
|
|
157
|
+
path. Relative paths resolve against the credential directory, so common batches
|
|
158
|
+
can be saved once and reused. This mirrors the skill's
|
|
159
|
+
`atomic-mail-jmap --ops-file` behavior — both consume the same files.
|
|
160
|
+
|
|
161
|
+
Example: drop `~/.atomicmail/fetch_last_100.json` containing
|
|
162
|
+
|
|
163
|
+
```json
|
|
164
|
+
[
|
|
165
|
+
[
|
|
166
|
+
"Email/query",
|
|
167
|
+
{
|
|
168
|
+
"accountId": "ACC",
|
|
169
|
+
"filter": { "inMailbox": "INBOX" },
|
|
170
|
+
"sort": [{ "property": "receivedAt", "isAscending": false }],
|
|
171
|
+
"limit": 100
|
|
172
|
+
},
|
|
173
|
+
"q0"
|
|
174
|
+
]
|
|
175
|
+
]
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
…then `jmap_request` with `{ "opsFile": "fetch_last_100.json" }`.
|
|
179
|
+
|
|
180
|
+
See `get_docs presets` for the full preset format.
|
|
181
|
+
|
|
182
|
+
## Develop
|
|
183
|
+
|
|
184
|
+
The project is a Deno-first codebase. You'll need [Deno](https://deno.com/)
|
|
185
|
+
installed.
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
# Run directly with Deno (live source, no build step)
|
|
189
|
+
deno task start
|
|
190
|
+
|
|
191
|
+
# Type-check
|
|
192
|
+
deno task check
|
|
193
|
+
|
|
194
|
+
# Format
|
|
195
|
+
deno task fmt
|
|
196
|
+
|
|
197
|
+
# Build the npm package via dnt
|
|
198
|
+
deno task build:npm
|
|
199
|
+
|
|
200
|
+
# Run the built artifact under Node
|
|
201
|
+
node npm/esm/main.js
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
The dnt build emits to `./npm/`. The package's `bin` is `atomicmail-mcp`, mapped
|
|
205
|
+
to `npm/esm/main.js`. After a build you can also `npm install` it locally and
|
|
206
|
+
use the binary directly.
|
|
207
|
+
|
|
208
|
+
### Project layout
|
|
209
|
+
|
|
210
|
+
```
|
|
211
|
+
services/mcp-server-local/
|
|
212
|
+
├── deno.json # Deno config + import map
|
|
213
|
+
├── build_npm.ts # dnt build script
|
|
214
|
+
├── README.md
|
|
215
|
+
├── src/
|
|
216
|
+
│ ├── main.ts # MCP server entry (stdio transport)
|
|
217
|
+
│ ├── auth-session.ts# PoW + JWT rotation, with disk persistence
|
|
218
|
+
│ ├── credentials.ts # File I/O: credentials.json, *.jwt
|
|
219
|
+
│ ├── docs-content.ts# Static text served by the get_docs tool
|
|
220
|
+
│ └── tools/
|
|
221
|
+
│ ├── register.ts
|
|
222
|
+
│ ├── jmap.ts
|
|
223
|
+
│ └── docs.ts
|
|
224
|
+
└── npm/ # dnt output (gitignored)
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
The auth-session and credentials files are kept in-step with their counterparts
|
|
228
|
+
in [`skill/scripts/lib/`](../../skill/scripts/lib/) so both projects produce and
|
|
229
|
+
consume identical credential files.
|
|
230
|
+
|
|
231
|
+
## License
|
|
232
|
+
|
|
233
|
+
MIT
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fixed proof-of-work scrypt salt. The auth-service passes this string (UTF-8
|
|
3
|
+
* bytes of the hex text, not decoded binary) to `scrypt` as the `salt`
|
|
4
|
+
* argument; all PoW clients must use the same value.
|
|
5
|
+
*/
|
|
6
|
+
export declare const DEFAULT_POW_SCRYPT_SALT_HEX = "0b980734412c292d6549110276b604ab1dea4883bd460d77d1b984adf8bca083";
|
|
7
|
+
export declare const ONE_SEC_MS = 1000;
|
|
8
|
+
export declare const ONE_MIN_MS: number;
|
|
9
|
+
export declare const ONE_HOUR_MS: number;
|
|
10
|
+
export declare const ONE_DAY_MS: number;
|
|
11
|
+
export declare const ONE_MONTH_MS: number;
|
|
12
|
+
export declare const ONE_YEAR_MS: number;
|
|
13
|
+
//# sourceMappingURL=consts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../../../src/lib/src/consts.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,qEAC4B,CAAC;AAErE,eAAO,MAAM,UAAU,OAAO,CAAC;AAC/B,eAAO,MAAM,UAAU,QAAkB,CAAC;AAC1C,eAAO,MAAM,WAAW,QAAkB,CAAC;AAC3C,eAAO,MAAM,UAAU,QAAmB,CAAC;AAC3C,eAAO,MAAM,YAAY,QAAkB,CAAC;AAC5C,eAAO,MAAM,WAAW,QAAmB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fixed proof-of-work scrypt salt. The auth-service passes this string (UTF-8
|
|
3
|
+
* bytes of the hex text, not decoded binary) to `scrypt` as the `salt`
|
|
4
|
+
* argument; all PoW clients must use the same value.
|
|
5
|
+
*/
|
|
6
|
+
export const DEFAULT_POW_SCRYPT_SALT_HEX = "0b980734412c292d6549110276b604ab1dea4883bd460d77d1b984adf8bca083";
|
|
7
|
+
export const ONE_SEC_MS = 1000;
|
|
8
|
+
export const ONE_MIN_MS = ONE_SEC_MS * 60;
|
|
9
|
+
export const ONE_HOUR_MS = ONE_MIN_MS * 60;
|
|
10
|
+
export const ONE_DAY_MS = ONE_HOUR_MS * 24;
|
|
11
|
+
export const ONE_MONTH_MS = ONE_DAY_MS * 30;
|
|
12
|
+
export const ONE_YEAR_MS = ONE_DAY_MS * 365;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { type SkillFiles } from "./credentials.js";
|
|
2
|
+
export declare const SESSION_TTL_MS: number;
|
|
3
|
+
export declare const CAPABILITY_TTL_MS: number;
|
|
4
|
+
export declare const SESSION_SAFETY_MARGIN_MS = 60000;
|
|
5
|
+
export declare const CAPABILITY_SAFETY_MARGIN_MS = 20000;
|
|
6
|
+
export interface JwtPayload {
|
|
7
|
+
exp?: number;
|
|
8
|
+
iat?: number;
|
|
9
|
+
jti?: string;
|
|
10
|
+
inboxId?: string;
|
|
11
|
+
[key: string]: unknown;
|
|
12
|
+
}
|
|
13
|
+
export declare function decodeJwtPayload<T = JwtPayload>(jwt: string): T;
|
|
14
|
+
export declare function isJwtExpired(jwt: string, marginMs: number): boolean;
|
|
15
|
+
export type ConfigSource = "credentials-file" | "env" | "mixed" | "incomplete";
|
|
16
|
+
export interface ResolvedConfig {
|
|
17
|
+
authUrl: string;
|
|
18
|
+
apiUrl: string;
|
|
19
|
+
scryptSalt: string;
|
|
20
|
+
apiKey?: string;
|
|
21
|
+
inboxId?: string;
|
|
22
|
+
credentialDir: string;
|
|
23
|
+
files: SkillFiles;
|
|
24
|
+
source: ConfigSource;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Resolve credential directory from (in priority order):
|
|
28
|
+
* 1. ATOMIC_MAIL_CREDENTIALS_DIR env var
|
|
29
|
+
* 2. ~/.atomicmail/ (POSIX) or %USERPROFILE%/.atomicmail (Windows)
|
|
30
|
+
*/
|
|
31
|
+
export declare function resolveCredentialDir(): string;
|
|
32
|
+
/**
|
|
33
|
+
* Resolve server configuration from:
|
|
34
|
+
* 1. credentials.json in the credential directory (if present and valid).
|
|
35
|
+
* 2. ATOMIC_MAIL_* environment variables (overlay on top of (1) so env
|
|
36
|
+
* always wins on a per-field basis).
|
|
37
|
+
*
|
|
38
|
+
* The auth and api base URLs MUST be resolvable from at least one source.
|
|
39
|
+
* PoW scrypt salt defaults to the deployment constant when not set in env or
|
|
40
|
+
* credentials.json.
|
|
41
|
+
* The api key is optional; without it, the agent must call the register tool
|
|
42
|
+
* before any JMAP request.
|
|
43
|
+
*/
|
|
44
|
+
export declare function resolveConfig(): Promise<ResolvedConfig>;
|
|
45
|
+
export interface AuthSessionConfig {
|
|
46
|
+
authUrl: string;
|
|
47
|
+
apiUrl: string;
|
|
48
|
+
scryptSalt: string;
|
|
49
|
+
apiKey?: string;
|
|
50
|
+
inboxId?: string;
|
|
51
|
+
credentialDir: string;
|
|
52
|
+
files: SkillFiles;
|
|
53
|
+
}
|
|
54
|
+
export declare class AuthSession {
|
|
55
|
+
private readonly authUrl;
|
|
56
|
+
readonly apiUrl: string;
|
|
57
|
+
private readonly scryptSalt;
|
|
58
|
+
private apiKey;
|
|
59
|
+
private inboxId;
|
|
60
|
+
readonly credentialDir: string;
|
|
61
|
+
readonly files: SkillFiles;
|
|
62
|
+
private sessionJWT;
|
|
63
|
+
private capabilityJWT;
|
|
64
|
+
constructor(cfg: AuthSessionConfig);
|
|
65
|
+
/** Construct a session and load any previously persisted JWTs from disk. */
|
|
66
|
+
static create(cfg: AuthSessionConfig): Promise<AuthSession>;
|
|
67
|
+
get hasApiKey(): boolean;
|
|
68
|
+
get currentInboxId(): string | undefined;
|
|
69
|
+
private loadFromDisk;
|
|
70
|
+
/**
|
|
71
|
+
* Full PoW signup. Persists credentials.json + session.jwt + capability.jwt
|
|
72
|
+
* to disk and updates in-memory state. Throws if an API key is already
|
|
73
|
+
* configured (refuse to clobber an existing account).
|
|
74
|
+
*/
|
|
75
|
+
signup(username: string): Promise<{
|
|
76
|
+
apiKey: string;
|
|
77
|
+
inboxId: string;
|
|
78
|
+
}>;
|
|
79
|
+
/**
|
|
80
|
+
* Get a valid capability JWT, rotating session/capability tokens as needed.
|
|
81
|
+
* This is the primary method tool handlers call before every JMAP request.
|
|
82
|
+
*/
|
|
83
|
+
getCapabilityToken(): Promise<string>;
|
|
84
|
+
private ensureSession;
|
|
85
|
+
/** Clean shutdown. No-op today; reserved for future cleanup. */
|
|
86
|
+
destroy(): void;
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=auth-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-session.d.ts","sourceRoot":"","sources":["../../../src/mcp/src/auth-session.ts"],"names":[],"mappings":"AAsBA,OAAO,EAGL,KAAK,UAAU,EAKhB,MAAM,kBAAkB,CAAC;AAO1B,eAAO,MAAM,cAAc,QAAqB,CAAC;AACjD,eAAO,MAAM,iBAAiB,QAAgB,CAAC;AAI/C,eAAO,MAAM,wBAAwB,QAAS,CAAC;AAC/C,eAAO,MAAM,2BAA2B,QAAS,CAAC;AAElD,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,wBAAgB,gBAAgB,CAAC,CAAC,GAAG,UAAU,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,CAc/D;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAQnE;AAgLD,MAAM,MAAM,YAAY,GACpB,kBAAkB,GAClB,KAAK,GACL,OAAO,GACP,YAAY,CAAC;AAEjB,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,UAAU,CAAC;IAClB,MAAM,EAAE,YAAY,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAW7C;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,cAAc,CAAC,CAqD7D;AAID,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,UAAU,CAAC;CACnB;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,OAAO,CAAqB;IACpC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAE3B,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,aAAa,CAAqB;gBAE9B,GAAG,EAAE,iBAAiB;IAUlC,4EAA4E;WAC/D,MAAM,CAAC,GAAG,EAAE,iBAAiB,GAAG,OAAO,CAAC,WAAW,CAAC;IAMjE,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,IAAI,cAAc,IAAI,MAAM,GAAG,SAAS,CAEvC;YAEa,YAAY;IAK1B;;;;OAIG;IACG,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;QACtC,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IA6CF;;;OAGG;IACG,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC;YA8B7B,aAAa;IA0B3B,gEAAgE;IAChE,OAAO,IAAI,IAAI;CAGhB"}
|