@rubytech/create-maxy 1.0.763 → 1.0.765
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/package.json +1 -1
- package/payload/platform/package-lock.json +56 -1
- package/payload/platform/package.json +1 -0
- package/payload/platform/plugins/docs/references/outlook-guide.md +69 -0
- package/payload/platform/plugins/docs/references/platform.md +1 -1
- package/payload/platform/plugins/outlook/PLUGIN.md +48 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/graph-client.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/graph-client.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/graph-client.test.js +94 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/graph-client.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/log.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/log.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/log.test.js +31 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/log.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/pkce-flow.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/pkce-flow.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/pkce-flow.test.js +213 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/pkce-flow.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/token-store.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/token-store.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/token-store.test.js +130 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/token-store.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/auth/pkce-flow.d.ts +65 -0
- package/payload/platform/plugins/outlook/mcp/dist/auth/pkce-flow.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/auth/pkce-flow.js +261 -0
- package/payload/platform/plugins/outlook/mcp/dist/auth/pkce-flow.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/auth/token-store.d.ts +61 -0
- package/payload/platform/plugins/outlook/mcp/dist/auth/token-store.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/auth/token-store.js +170 -0
- package/payload/platform/plugins/outlook/mcp/dist/auth/token-store.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/index.d.ts +18 -0
- package/payload/platform/plugins/outlook/mcp/dist/index.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/index.js +152 -0
- package/payload/platform/plugins/outlook/mcp/dist/index.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.d.ts +60 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.js +189 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/log.d.ts +23 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/log.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/log.js +53 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/log.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/account-register.d.ts +26 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/account-register.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/account-register.js +50 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/account-register.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-event.d.ts +12 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-event.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-event.js +32 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-event.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-list.d.ts +59 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-list.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-list.js +54 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-list.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/contacts-list.d.ts +14 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/contacts-list.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/contacts-list.js +45 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/contacts-list.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-list.d.ts +15 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-list.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-list.js +48 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-list.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-search.d.ts +8 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-search.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-search.js +49 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-search.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mailbox-info.d.ts +19 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mailbox-info.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mailbox-info.js +58 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mailbox-info.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/package.json +20 -0
- package/payload/platform/plugins/outlook/mcp/scripts/verify-doc-impl.sh +109 -0
- package/payload/platform/plugins/outlook/references/auth.md +118 -0
- package/payload/platform/plugins/outlook/references/graph-surfaces.md +114 -0
- package/payload/platform/plugins/outlook/skills/outlook/SKILL.md +65 -0
- package/payload/platform/templates/specialists/agents/personal-assistant.md +1 -1
- package/payload/server/chunk-EIQT6QDH.js +9562 -0
- package/payload/server/chunk-IO2WQEY4.js +9562 -0
- package/payload/server/chunk-TKYZ7AEB.js +3142 -0
- package/payload/server/client-pool-CX2MFW75.js +28 -0
- package/payload/server/maxy-edge.js +2 -2
- package/payload/server/public/assets/{admin-V6NDkEoR.js → admin-g-Fjko8R.js} +5 -5
- package/payload/server/public/assets/{graph-BHcUKzXh.js → graph-DHBGJFDX.js} +1 -1
- package/payload/server/public/assets/page-BscgOyqp.js +50 -0
- package/payload/server/public/graph.html +2 -2
- package/payload/server/public/index.html +2 -2
- package/payload/server/server.js +146 -39
- package/payload/server/public/assets/page-DxH_Opxt.js +0 -50
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@maxy/outlook",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"start": "node dist/index.js"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@microsoft/microsoft-graph-client": "^3.0.7",
|
|
13
|
+
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
14
|
+
"zod": "^3.24.0"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@types/node": "^22.0.0",
|
|
18
|
+
"typescript": "^5.7.0"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# verify-doc-impl.sh
|
|
3
|
+
#
|
|
4
|
+
# Doc-impl alignment grep, promoted from Task 811's manual verification step
|
|
5
|
+
# to a permanent gate. Run from anywhere; resolves to the plugin tree itself.
|
|
6
|
+
#
|
|
7
|
+
# Verifies:
|
|
8
|
+
# 1. Every `outlook-*` tool name in `platform/plugins/docs/references/outlook-guide.md`
|
|
9
|
+
# resolves to a `server.tool("outlook-...", ...)` registration in mcp/src/index.ts.
|
|
10
|
+
# 2. Every `[outlook-mcp]` log-line shape in outlook-guide.md matches a
|
|
11
|
+
# log({event:"..."}) literal in mcp/src/.
|
|
12
|
+
# 3. Every tool name in `PLUGIN.md` frontmatter matches a registration in mcp/src/index.ts.
|
|
13
|
+
# 4. Public-agent isolation: `outlook` does not appear in public-agent assembly files.
|
|
14
|
+
# 5. Bearer-token redaction: log.ts contains the redaction regex pair.
|
|
15
|
+
#
|
|
16
|
+
# Exit non-zero on any mismatch. Print the first diverging item.
|
|
17
|
+
|
|
18
|
+
set -euo pipefail
|
|
19
|
+
|
|
20
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
21
|
+
PLUGIN_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
22
|
+
REPO_ROOT="$(cd "$PLUGIN_DIR/../../../.." && pwd)"
|
|
23
|
+
GUIDE="$REPO_ROOT/platform/plugins/docs/references/outlook-guide.md"
|
|
24
|
+
PLUGIN_MD="$REPO_ROOT/platform/plugins/outlook/PLUGIN.md"
|
|
25
|
+
INDEX_TS="$PLUGIN_DIR/src/index.ts"
|
|
26
|
+
SRC_DIR="$PLUGIN_DIR/src"
|
|
27
|
+
|
|
28
|
+
fail() {
|
|
29
|
+
echo "[verify-doc-impl] FAIL: $1" >&2
|
|
30
|
+
exit 1
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
[ -f "$GUIDE" ] || fail "operator guide missing: $GUIDE"
|
|
34
|
+
[ -f "$PLUGIN_MD" ] || fail "PLUGIN.md missing: $PLUGIN_MD"
|
|
35
|
+
[ -f "$INDEX_TS" ] || fail "index.ts missing: $INDEX_TS"
|
|
36
|
+
|
|
37
|
+
# Tool names registered in src/index.ts. The MCP-SDK call shape is:
|
|
38
|
+
# server.tool(
|
|
39
|
+
# "outlook-XYZ",
|
|
40
|
+
# ...
|
|
41
|
+
# so the tool name appears on its own line as ` "outlook-XYZ",`.
|
|
42
|
+
TOOLS_REGISTERED=$(grep -oE '"outlook-[a-z\-]+",' "$INDEX_TS" \
|
|
43
|
+
| sed -E 's/^"|",$//g' | sort -u)
|
|
44
|
+
|
|
45
|
+
# Tool names referenced in outlook-guide.md (backtick-wrapped)
|
|
46
|
+
TOOLS_IN_GUIDE=$(grep -oE '`outlook-[a-z\-]+`' "$GUIDE" | tr -d '`' | sort -u)
|
|
47
|
+
|
|
48
|
+
# Tool names in PLUGIN.md frontmatter (lines starting with " - outlook-")
|
|
49
|
+
TOOLS_IN_PLUGIN_MD=$(grep -E '^\s+- outlook-' "$PLUGIN_MD" | sed -E 's/^[[:space:]]*-[[:space:]]+//' | sort -u)
|
|
50
|
+
|
|
51
|
+
# Set 1: every tool in guide must be registered
|
|
52
|
+
while IFS= read -r tool; do
|
|
53
|
+
[ -z "$tool" ] && continue
|
|
54
|
+
if ! echo "$TOOLS_REGISTERED" | grep -qx "$tool"; then
|
|
55
|
+
fail "tool '$tool' referenced in outlook-guide.md but not registered in mcp/src/index.ts"
|
|
56
|
+
fi
|
|
57
|
+
done <<< "$TOOLS_IN_GUIDE"
|
|
58
|
+
|
|
59
|
+
# Set 2: every tool in PLUGIN.md frontmatter must be registered
|
|
60
|
+
while IFS= read -r tool; do
|
|
61
|
+
[ -z "$tool" ] && continue
|
|
62
|
+
if ! echo "$TOOLS_REGISTERED" | grep -qx "$tool"; then
|
|
63
|
+
fail "tool '$tool' declared in PLUGIN.md frontmatter but not registered in mcp/src/index.ts"
|
|
64
|
+
fi
|
|
65
|
+
done <<< "$TOOLS_IN_PLUGIN_MD"
|
|
66
|
+
|
|
67
|
+
# Set 3: every registered tool must appear in PLUGIN.md frontmatter
|
|
68
|
+
while IFS= read -r tool; do
|
|
69
|
+
[ -z "$tool" ] && continue
|
|
70
|
+
if ! echo "$TOOLS_IN_PLUGIN_MD" | grep -qx "$tool"; then
|
|
71
|
+
fail "tool '$tool' registered in mcp/src/index.ts but missing from PLUGIN.md frontmatter"
|
|
72
|
+
fi
|
|
73
|
+
done <<< "$TOOLS_REGISTERED"
|
|
74
|
+
|
|
75
|
+
# Log-shape alignment: every event tag in outlook-guide.md must have a matching
|
|
76
|
+
# log({ event: "..." }) literal in mcp/src/. Event tags appear in the table as:
|
|
77
|
+
# | Auth init | `auth-init account=<id> codeChallenge=...` |
|
|
78
|
+
# We pull the first word inside backticks on each table row that contains "account=".
|
|
79
|
+
EVENTS_IN_GUIDE=$(grep -E '`[a-z\-]+ account=' "$GUIDE" \
|
|
80
|
+
| sed -E 's/.*`([a-z\-]+) account=.*/\1/' | sort -u)
|
|
81
|
+
EVENTS_IN_SRC=$(grep -rh -oE 'event:[[:space:]]*"[a-z\-]+"' "$SRC_DIR" \
|
|
82
|
+
| sed -E 's/^event:[[:space:]]*"|"$//g' | sort -u)
|
|
83
|
+
|
|
84
|
+
while IFS= read -r ev; do
|
|
85
|
+
[ -z "$ev" ] && continue
|
|
86
|
+
if ! echo "$EVENTS_IN_SRC" | grep -qx "$ev"; then
|
|
87
|
+
fail "log event '$ev' documented in outlook-guide.md but no log({event:\"$ev\"}) literal in mcp/src/"
|
|
88
|
+
fi
|
|
89
|
+
done <<< "$EVENTS_IN_GUIDE"
|
|
90
|
+
|
|
91
|
+
# Public-agent isolation: outlook must not appear in public-agent assembly files.
|
|
92
|
+
ISOLATION_HITS=$( (cd "$REPO_ROOT" && grep -rE 'outlook' \
|
|
93
|
+
platform/ui/app/lib/claude-agent/public-agent.ts \
|
|
94
|
+
platform/ui/app/lib/claude-agent/system-prompt-assembly.ts \
|
|
95
|
+
platform/templates/agents/public/ 2>/dev/null) || true)
|
|
96
|
+
if [ -n "$ISOLATION_HITS" ]; then
|
|
97
|
+
echo "$ISOLATION_HITS" >&2
|
|
98
|
+
fail "isolation breach: 'outlook' string appears in public-agent assembly path"
|
|
99
|
+
fi
|
|
100
|
+
|
|
101
|
+
# Bearer redaction guard: lib/log.ts must contain both regex literals.
|
|
102
|
+
if ! grep -q 'Bearer\\s+\[A-Za-z0-9' "$SRC_DIR/lib/log.ts"; then
|
|
103
|
+
fail "Bearer redaction regex missing in lib/log.ts"
|
|
104
|
+
fi
|
|
105
|
+
if ! grep -q 'access_token=\[A-Za-z0-9' "$SRC_DIR/lib/log.ts"; then
|
|
106
|
+
fail "access_token redaction regex missing in lib/log.ts"
|
|
107
|
+
fi
|
|
108
|
+
|
|
109
|
+
echo "[verify-doc-impl] OK — $(echo "$TOOLS_REGISTERED" | wc -l | tr -d ' ') tools, $(echo "$EVENTS_IN_GUIDE" | wc -l | tr -d ' ') events, isolation, redaction all aligned"
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# Outlook Auth Reference
|
|
2
|
+
|
|
3
|
+
## Vendored upstream
|
|
4
|
+
|
|
5
|
+
The PKCE flow and encrypted token store are adapted from:
|
|
6
|
+
|
|
7
|
+
- **Repo:** [`nsakki55/outlook-mcp`](https://github.com/nsakki55/outlook-mcp)
|
|
8
|
+
- **Pinned commit:** `e49d8e68ac8d69db653c25803127dc3b98626cda`
|
|
9
|
+
- **License:** MIT
|
|
10
|
+
|
|
11
|
+
Adaptations:
|
|
12
|
+
|
|
13
|
+
- Per-account paths (`{ACCOUNTS_DIR}/{accountId}/secrets/outlook/`) instead of upstream's single-user `~/.outlook-mcp/`
|
|
14
|
+
- `keytar` fallback removed (Pi runs headless; no Secret Service)
|
|
15
|
+
- `node-persist` removed; single JSON blob written atomically (temp + rename)
|
|
16
|
+
- Loopback callback port is **ephemeral** via `server.listen(0)` (upstream uses fixed `49152`)
|
|
17
|
+
- No `xdg-open` browser auto-launch; auth URL is logged + returned to the operator for the VNC browser
|
|
18
|
+
- `outlook-account-register` awaits the full PKCE flow synchronously (5-min timeout)
|
|
19
|
+
|
|
20
|
+
To re-vendor at a newer SHA:
|
|
21
|
+
|
|
22
|
+
1. Fetch `tokenManager.ts` and `authManager.ts` from the new SHA.
|
|
23
|
+
2. Apply the adaptations above.
|
|
24
|
+
3. Update the **Pinned commit** line above.
|
|
25
|
+
4. Bump `@maxy/outlook` version.
|
|
26
|
+
5. Run the test suite.
|
|
27
|
+
|
|
28
|
+
## Entra app registration (one-time per Maxy install)
|
|
29
|
+
|
|
30
|
+
The plugin requires an Azure AD ("Entra ID") app the operator owns. Steps:
|
|
31
|
+
|
|
32
|
+
1. Sign in to the [Azure portal](https://portal.azure.com) with a Microsoft account.
|
|
33
|
+
2. Go to **Microsoft Entra ID → App registrations → New registration**.
|
|
34
|
+
3. **Name:** `Maxy Outlook` (or any name the operator prefers).
|
|
35
|
+
4. **Supported account types:** *Accounts in any organizational directory and personal Microsoft accounts*.
|
|
36
|
+
5. **Redirect URI** (Platform: *Mobile and desktop applications*): `http://localhost`
|
|
37
|
+
- **Note:** no port is specified. Microsoft Identity Platform treats native-app loopback redirects with port-flexible matching, allowing the plugin to use an ephemeral port.
|
|
38
|
+
6. Click **Register**. Copy the **Application (client) ID** — this is `OUTLOOK_CLIENT_ID`.
|
|
39
|
+
7. Go to **API permissions → Add a permission → Microsoft Graph → Delegated permissions**, add:
|
|
40
|
+
- `offline_access`
|
|
41
|
+
- `User.Read`
|
|
42
|
+
- `Mail.Read`
|
|
43
|
+
- `Calendars.Read`
|
|
44
|
+
- `Contacts.Read`
|
|
45
|
+
8. Click **Grant admin consent for <tenant>** if applicable. Personal accounts auto-consent at first sign-in.
|
|
46
|
+
9. Set the env var on the Pi:
|
|
47
|
+
```
|
|
48
|
+
OUTLOOK_CLIENT_ID=<the Application (client) ID copied above>
|
|
49
|
+
OUTLOOK_TENANT_ID=common # or your tenant GUID for single-tenant
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## PKCE flow (per-account)
|
|
53
|
+
|
|
54
|
+
Triggered by `outlook-account-register`. Sequence:
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
operator plugin Microsoft
|
|
58
|
+
| | |
|
|
59
|
+
| outlook-account-register | |
|
|
60
|
+
|--------------------------------------------->| |
|
|
61
|
+
| | bind 127.0.0.1:<ephemeral-port> |
|
|
62
|
+
| | generate code_verifier (32 bytes) |
|
|
63
|
+
| | code_challenge = SHA256(verifier) |
|
|
64
|
+
| | state = randomBytes(16) |
|
|
65
|
+
| | |
|
|
66
|
+
| { authUrl, status: "pending" } | |
|
|
67
|
+
|<---------------------------------------------| |
|
|
68
|
+
| | |
|
|
69
|
+
| open authUrl in VNC browser | |
|
|
70
|
+
|---------------------------------------------------------------------------------> |
|
|
71
|
+
| | |
|
|
72
|
+
| consent ←--------------------------------------- |
|
|
73
|
+
| | |
|
|
74
|
+
| | GET /callback?code=...&state=... |
|
|
75
|
+
| | <----------------------------------|
|
|
76
|
+
| | |
|
|
77
|
+
| | verify state |
|
|
78
|
+
| | POST /token (code + verifier) |
|
|
79
|
+
| | -----------------------------------> |
|
|
80
|
+
| | < tokens |
|
|
81
|
+
| | <----------------------------------- |
|
|
82
|
+
| | encrypt → write {tokens.enc} |
|
|
83
|
+
| | GET /me (record graphUserId) |
|
|
84
|
+
| | -----------------------------------> |
|
|
85
|
+
| | |
|
|
86
|
+
| { status: "registered", graphUserId, ... } | |
|
|
87
|
+
|<---------------------------------------------| |
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Token store layout
|
|
91
|
+
|
|
92
|
+
Per-account, mode 0700 directory + mode 0600 files:
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
data/accounts/<accountId>/secrets/outlook/
|
|
96
|
+
├── .key # 32 random bytes, base64-encoded — the AES-256-CBC key
|
|
97
|
+
└── tokens.enc # AES-256-CBC ciphertext: "<iv-hex>:<cipher-hex>" of JSON blob
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The JSON blob shape:
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
{
|
|
104
|
+
accessToken: string;
|
|
105
|
+
refreshToken: string | null;
|
|
106
|
+
accessTokenExpiry: number; // unix ms
|
|
107
|
+
refreshTokenExpiry: number; // unix ms; ~90 days from issue
|
|
108
|
+
lastRefresh: number; // unix ms
|
|
109
|
+
graphUserId: string | null; // from /me.id
|
|
110
|
+
scopes: string[]; // granted scopes from token response
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Atomic write: temp + rename. Either old or new tokens, never partial.
|
|
115
|
+
|
|
116
|
+
## Refresh
|
|
117
|
+
|
|
118
|
+
Triggered automatically when the access token is within `5 minutes` of expiry (`refreshThresholdMs`). Failure → terminal `token-refresh-failed`, tokens cleared, operator must re-register. Refresh tokens last 90 days.
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Graph Surfaces
|
|
2
|
+
|
|
3
|
+
Microsoft Graph endpoints used by each tool, with the response shape and the fields selected.
|
|
4
|
+
|
|
5
|
+
## outlook-mail-list
|
|
6
|
+
|
|
7
|
+
**Endpoint (Inbox):** `GET /me/mailFolders/Inbox/messages?$top={N}&$orderby=receivedDateTime DESC&$select=id,subject,from,receivedDateTime,bodyPreview,isRead`
|
|
8
|
+
|
|
9
|
+
**Endpoint (other folder):** `GET /me/mailFolders/{folderId-or-displayName}/messages?...`
|
|
10
|
+
|
|
11
|
+
**Returned shape:**
|
|
12
|
+
```typescript
|
|
13
|
+
Array<{
|
|
14
|
+
id: string;
|
|
15
|
+
subject: string | null;
|
|
16
|
+
from: string | null; // emailAddress.address
|
|
17
|
+
receivedDateTime: string; // ISO 8601
|
|
18
|
+
bodyPreview: string; // truncated to 1024 chars
|
|
19
|
+
isRead: boolean;
|
|
20
|
+
}>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## outlook-mail-search
|
|
24
|
+
|
|
25
|
+
**Endpoint:** `GET /me/messages?$search="{query}"&$top={N}&$select=id,subject,from,receivedDateTime,bodyPreview,isRead`
|
|
26
|
+
|
|
27
|
+
**Required header:** `ConsistencyLevel: eventual` (Graph requirement for `$search`).
|
|
28
|
+
|
|
29
|
+
**Returned shape:** identical to `outlook-mail-list`.
|
|
30
|
+
|
|
31
|
+
## outlook-calendar-list
|
|
32
|
+
|
|
33
|
+
**Endpoint:** `GET /me/calendarView?startDateTime={now}&endDateTime={now+rangeDays}&$top={N}&$orderby=start/dateTime ASC&$select=id,subject,start,end,location,attendees,isAllDay,organizer`
|
|
34
|
+
|
|
35
|
+
**Returned shape:**
|
|
36
|
+
```typescript
|
|
37
|
+
Array<{
|
|
38
|
+
id: string;
|
|
39
|
+
subject: string | null;
|
|
40
|
+
start: { dateTime: string; timeZone: string };
|
|
41
|
+
end: { dateTime: string; timeZone: string };
|
|
42
|
+
location: string | null;
|
|
43
|
+
attendees: Array<{ email: string; name: string | null; response: string }>;
|
|
44
|
+
isAllDay: boolean;
|
|
45
|
+
organizer: string | null;
|
|
46
|
+
}>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## outlook-calendar-event
|
|
50
|
+
|
|
51
|
+
**Endpoint:** `GET /me/events/{eventId}?$select=id,subject,start,end,location,attendees,isAllDay,organizer,bodyPreview,body,webLink`
|
|
52
|
+
|
|
53
|
+
**Returned shape:** as `outlook-calendar-list` plus:
|
|
54
|
+
```typescript
|
|
55
|
+
{
|
|
56
|
+
bodyPreview: string; // 1024 chars
|
|
57
|
+
body: string; // up to 16384 chars (HTML or text per content type)
|
|
58
|
+
webLink: string | null;
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## outlook-contacts-list
|
|
63
|
+
|
|
64
|
+
**Endpoint:** `GET /me/contacts?$top={N}&$select=id,displayName,emailAddresses,businessPhones,homePhones,mobilePhone,jobTitle,companyName`
|
|
65
|
+
|
|
66
|
+
**Returned shape:**
|
|
67
|
+
```typescript
|
|
68
|
+
Array<{
|
|
69
|
+
id: string;
|
|
70
|
+
displayName: string | null;
|
|
71
|
+
emailAddresses: string[]; // .address values flattened
|
|
72
|
+
phones: string[]; // business + home + mobile concatenated
|
|
73
|
+
jobTitle: string | null;
|
|
74
|
+
companyName: string | null;
|
|
75
|
+
}>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## outlook-mailbox-info
|
|
79
|
+
|
|
80
|
+
**Endpoint:** `GET /me/mailFolders?$top=50&$select=id` (best-effort — folder count is null if Graph is unreachable)
|
|
81
|
+
|
|
82
|
+
**Returned shape:**
|
|
83
|
+
```typescript
|
|
84
|
+
{
|
|
85
|
+
registered: boolean;
|
|
86
|
+
graphUserId: string | null;
|
|
87
|
+
scopes: string[];
|
|
88
|
+
tokenExpSec: number | null;
|
|
89
|
+
refreshTokenExpSec: number | null;
|
|
90
|
+
tokenWithinRefreshWindow: boolean;
|
|
91
|
+
folderCount: number | null;
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## outlook-account-register
|
|
96
|
+
|
|
97
|
+
No Graph endpoint of its own. The flow exchanges an authorization code at:
|
|
98
|
+
|
|
99
|
+
- `POST https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token`
|
|
100
|
+
|
|
101
|
+
After the token exchange, the tool fetches `GET /me?$select=id,mail,userPrincipalName` to record `graphUserId`.
|
|
102
|
+
|
|
103
|
+
## Error classification
|
|
104
|
+
|
|
105
|
+
All tool failures route through `lib/graph-client.ts:classifyGraphError`. Decisions key off **status code + Graph `error.code` field + headers**, never the error `message` body.
|
|
106
|
+
|
|
107
|
+
| HTTP status | Graph `error.code` | Class | Action |
|
|
108
|
+
|---|---|---|---|
|
|
109
|
+
| 401 | (any) | `auth` | Refresh once, retry; if still 401 → terminal `auth-required` |
|
|
110
|
+
| 429 | (any) — header `Retry-After` present | `rate-limit-recoverable` | Backoff per header, retry once |
|
|
111
|
+
| 429 | (any) — header `Retry-After` absent | `rate-limit-terminal` | Terminal abort |
|
|
112
|
+
| 503 | `MailboxNotEnabledForRESTAPI` | `on-prem` | Terminal: route operator to IMAP plugin |
|
|
113
|
+
| 5xx | (any) | `5xx` | Retry once with 500 ms; then terminal |
|
|
114
|
+
| any | (any) | `other` | Re-throw |
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: outlook
|
|
3
|
+
description: "Microsoft 365 / Outlook.com via Microsoft Graph (read-only). Use when the user asks about their Outlook mail, calendar, or contacts — listing, searching, or checking events. First-time use requires outlook-account-register; subsequent use is transparent. Tools — outlook-mail-list / outlook-mail-search (inbox), outlook-calendar-list / outlook-calendar-event (calendar), outlook-contacts-list (contacts), outlook-mailbox-info (health), outlook-account-register (PKCE register)."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Outlook (Microsoft Graph)
|
|
7
|
+
|
|
8
|
+
Read-only access to the user's Outlook.com or Microsoft 365 mailbox via Microsoft Graph. Per-account OAuth, encrypted token storage, refresh handled automatically.
|
|
9
|
+
|
|
10
|
+
## When to activate
|
|
11
|
+
|
|
12
|
+
Activate when the user asks about:
|
|
13
|
+
|
|
14
|
+
- Their Outlook / Office 365 / Hotmail mail (recent messages, search by keyword/sender)
|
|
15
|
+
- Their Outlook calendar (upcoming events, specific event details, free/busy windows)
|
|
16
|
+
- Their Outlook contacts
|
|
17
|
+
|
|
18
|
+
Do **not** activate for:
|
|
19
|
+
|
|
20
|
+
- IMAP-only providers (Gmail, iCloud, custom domains not on Microsoft 365) — use the `email` plugin instead.
|
|
21
|
+
- On-premises Exchange — Microsoft Graph deprecated hybrid REST 2023-07. The plugin detects on-prem mailboxes and emits a clear error pointing to the IMAP path.
|
|
22
|
+
- Sending / drafting / modifying messages or events — out of scope. Read-only.
|
|
23
|
+
|
|
24
|
+
## First-time setup (one-time per account)
|
|
25
|
+
|
|
26
|
+
The Outlook plugin needs an **Entra app registration** in the operator's Microsoft tenant. This is a one-time-per-install step (not per-account), documented at [`references/auth.md`](references/auth.md).
|
|
27
|
+
|
|
28
|
+
Once the Entra app exists and `OUTLOOK_CLIENT_ID` is set in the Maxy installation, run:
|
|
29
|
+
|
|
30
|
+
1. **`outlook-account-register`** — the tool returns an `authUrl`. The operator opens this URL in the VNC browser, signs in with the Microsoft account they want to connect, and consents to the requested scopes (`offline_access`, `User.Read`, `Mail.Read`, `Calendars.Read`, `Contacts.Read`).
|
|
31
|
+
2. Tool returns `{ status: "registered", graphUserId, scopes, tokenExpSec }` once consent completes.
|
|
32
|
+
|
|
33
|
+
Subsequent tool calls use the persisted refresh token to mint access tokens transparently. Re-register is only needed if the refresh token expires (90 days) or the user revokes consent.
|
|
34
|
+
|
|
35
|
+
## Reading mail
|
|
36
|
+
|
|
37
|
+
- `outlook-mail-list` — recent mail, default top=25, folder=Inbox.
|
|
38
|
+
- `outlook-mail-search query=<keyword>` — Microsoft Graph `$search` over the mailbox.
|
|
39
|
+
|
|
40
|
+
## Reading calendar
|
|
41
|
+
|
|
42
|
+
- `outlook-calendar-list rangeDays=<N>` — events in the next N days (default 7, max 365).
|
|
43
|
+
- `outlook-calendar-event eventId=<id>` — single event with full body and attendees.
|
|
44
|
+
|
|
45
|
+
## Reading contacts
|
|
46
|
+
|
|
47
|
+
- `outlook-contacts-list` — top contacts, default top=50.
|
|
48
|
+
|
|
49
|
+
## Health check
|
|
50
|
+
|
|
51
|
+
- `outlook-mailbox-info` — quick state probe: is the account registered? Are tokens within the refresh window? How many folders are visible? Useful when troubleshooting a tool that returned `auth-required`.
|
|
52
|
+
|
|
53
|
+
## What can go wrong
|
|
54
|
+
|
|
55
|
+
| Error | Meaning | Operator action |
|
|
56
|
+
|---|---|---|
|
|
57
|
+
| `auth-required` | Account not registered, or refresh token expired | Run `outlook-account-register` |
|
|
58
|
+
| `Outlook token refresh failed` | Network down or refresh token invalidated | Verify connectivity; re-run register if persistent |
|
|
59
|
+
| `Microsoft Graph does not support on-premises Exchange` | Mailbox is on hybrid Exchange | Use the `email` plugin (IMAP) |
|
|
60
|
+
| `Outlook rate-limited without Retry-After hint` | Graph 429 with no backoff guidance | Retry later; if persistent, file a bug |
|
|
61
|
+
|
|
62
|
+
## Reference files
|
|
63
|
+
|
|
64
|
+
- [`references/auth.md`](references/auth.md) — Entra app registration + PKCE flow + re-vendor procedure
|
|
65
|
+
- [`references/graph-surfaces.md`](references/graph-surfaces.md) — Graph endpoint and response shape per tool
|
|
@@ -3,7 +3,7 @@ name: personal-assistant
|
|
|
3
3
|
description: "Your personal assistant — scheduling, platform administration, messaging channels, system health, and browser automation. Delegate when a task involves managing your calendar, configuring the platform, operating messaging channels, or completing interactive browser tasks."
|
|
4
4
|
summary: "Handles the operational tasks you'd give a personal assistant — scheduling meetings, managing your platform settings, connecting messaging channels, and completing browser-based tasks on your behalf. For example, when you want to schedule a weekly check-in, set up Telegram, or fill out an online form."
|
|
5
5
|
model: claude-sonnet-4-6
|
|
6
|
-
tools: mcp__admin__system-status, mcp__admin__brand-settings, mcp__admin__account-manage, mcp__admin__account-update, mcp__admin__logs-read, mcp__admin__plugin-read, mcp__admin__api-key-store, mcp__admin__api-key-verify, mcp__admin__render-component, mcp__admin__file-attach, mcp__admin__wifi, mcp__contacts__contact-create, mcp__contacts__contact-lookup, mcp__contacts__contact-update, mcp__contacts__contact-delete, mcp__contacts__contact-list, mcp__contacts__contact-export, mcp__contacts__contact-erase, mcp__contacts__group-create, mcp__contacts__group-manage, mcp__telegram__message, mcp__telegram__message-history, mcp__telegram__telegram-webhook-register, mcp__whatsapp__whatsapp-login-start, mcp__whatsapp__whatsapp-login-wait, mcp__whatsapp__whatsapp-status, mcp__whatsapp__whatsapp-disconnect, mcp__whatsapp__whatsapp-send, mcp__whatsapp__whatsapp-send-document, mcp__whatsapp__whatsapp-config, mcp__whatsapp__whatsapp-activity, mcp__whatsapp__whatsapp-conversations, mcp__whatsapp__whatsapp-messages, mcp__whatsapp__whatsapp-group-info, mcp__email__email-setup, mcp__email__email-read, mcp__email__email-send, mcp__email__email-reply, mcp__email__email-search, mcp__email__email-graph-query, mcp__email__email-otp-extract, mcp__email__email-status, mcp__email__email-auto-respond-config, mcp__scheduling__schedule-event, mcp__scheduling__schedule-list, mcp__scheduling__schedule-get, mcp__scheduling__schedule-update, mcp__scheduling__schedule-cancel, mcp__scheduling__schedule-export-ics, mcp__scheduling__schedule-import-ics, mcp__scheduling__time-resolve, mcp__memory__memory-search, mcp__memory__profile-update, mcp__plugin_playwright_playwright__browser_navigate, mcp__plugin_playwright_playwright__browser_navigate_back, mcp__plugin_playwright_playwright__browser_snapshot, mcp__plugin_playwright_playwright__browser_click, mcp__plugin_playwright_playwright__browser_fill, mcp__plugin_playwright_playwright__browser_fill_form, mcp__plugin_playwright_playwright__browser_type, mcp__plugin_playwright_playwright__browser_press_key, mcp__plugin_playwright_playwright__browser_hover, mcp__plugin_playwright_playwright__browser_select_option, mcp__plugin_playwright_playwright__browser_wait_for, mcp__plugin_playwright_playwright__browser_handle_dialog, mcp__plugin_playwright_playwright__browser_evaluate, mcp__plugin_playwright_playwright__browser_console_messages, mcp__plugin_playwright_playwright__browser_resize, mcp__plugin_playwright_playwright__browser_tabs, mcp__plugin_playwright_playwright__browser_close
|
|
6
|
+
tools: mcp__admin__system-status, mcp__admin__brand-settings, mcp__admin__account-manage, mcp__admin__account-update, mcp__admin__logs-read, mcp__admin__plugin-read, mcp__admin__api-key-store, mcp__admin__api-key-verify, mcp__admin__render-component, mcp__admin__file-attach, mcp__admin__wifi, mcp__contacts__contact-create, mcp__contacts__contact-lookup, mcp__contacts__contact-update, mcp__contacts__contact-delete, mcp__contacts__contact-list, mcp__contacts__contact-export, mcp__contacts__contact-erase, mcp__contacts__group-create, mcp__contacts__group-manage, mcp__telegram__message, mcp__telegram__message-history, mcp__telegram__telegram-webhook-register, mcp__whatsapp__whatsapp-login-start, mcp__whatsapp__whatsapp-login-wait, mcp__whatsapp__whatsapp-status, mcp__whatsapp__whatsapp-disconnect, mcp__whatsapp__whatsapp-send, mcp__whatsapp__whatsapp-send-document, mcp__whatsapp__whatsapp-config, mcp__whatsapp__whatsapp-activity, mcp__whatsapp__whatsapp-conversations, mcp__whatsapp__whatsapp-messages, mcp__whatsapp__whatsapp-group-info, mcp__email__email-setup, mcp__email__email-read, mcp__email__email-send, mcp__email__email-reply, mcp__email__email-search, mcp__email__email-graph-query, mcp__email__email-otp-extract, mcp__email__email-status, mcp__email__email-auto-respond-config, mcp__outlook__outlook-account-register, mcp__outlook__outlook-mail-list, mcp__outlook__outlook-mail-search, mcp__outlook__outlook-calendar-list, mcp__outlook__outlook-calendar-event, mcp__outlook__outlook-contacts-list, mcp__outlook__outlook-mailbox-info, mcp__scheduling__schedule-event, mcp__scheduling__schedule-list, mcp__scheduling__schedule-get, mcp__scheduling__schedule-update, mcp__scheduling__schedule-cancel, mcp__scheduling__schedule-export-ics, mcp__scheduling__schedule-import-ics, mcp__scheduling__time-resolve, mcp__memory__memory-search, mcp__memory__profile-update, mcp__plugin_playwright_playwright__browser_navigate, mcp__plugin_playwright_playwright__browser_navigate_back, mcp__plugin_playwright_playwright__browser_snapshot, mcp__plugin_playwright_playwright__browser_click, mcp__plugin_playwright_playwright__browser_fill, mcp__plugin_playwright_playwright__browser_fill_form, mcp__plugin_playwright_playwright__browser_type, mcp__plugin_playwright_playwright__browser_press_key, mcp__plugin_playwright_playwright__browser_hover, mcp__plugin_playwright_playwright__browser_select_option, mcp__plugin_playwright_playwright__browser_wait_for, mcp__plugin_playwright_playwright__browser_handle_dialog, mcp__plugin_playwright_playwright__browser_evaluate, mcp__plugin_playwright_playwright__browser_console_messages, mcp__plugin_playwright_playwright__browser_resize, mcp__plugin_playwright_playwright__browser_tabs, mcp__plugin_playwright_playwright__browser_close
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Personal Assistant
|