google-services-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.
Files changed (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +225 -0
  3. package/dist/auth/config.d.ts +43 -0
  4. package/dist/auth/config.d.ts.map +1 -0
  5. package/dist/auth/config.js +108 -0
  6. package/dist/auth/config.js.map +1 -0
  7. package/dist/auth/manager.d.ts +50 -0
  8. package/dist/auth/manager.d.ts.map +1 -0
  9. package/dist/auth/manager.js +140 -0
  10. package/dist/auth/manager.js.map +1 -0
  11. package/dist/auth/oauth.d.ts +49 -0
  12. package/dist/auth/oauth.d.ts.map +1 -0
  13. package/dist/auth/oauth.js +211 -0
  14. package/dist/auth/oauth.js.map +1 -0
  15. package/dist/auth/store.d.ts +18 -0
  16. package/dist/auth/store.d.ts.map +1 -0
  17. package/dist/auth/store.js +45 -0
  18. package/dist/auth/store.js.map +1 -0
  19. package/dist/cli.d.ts +7 -0
  20. package/dist/cli.d.ts.map +1 -0
  21. package/dist/cli.js +112 -0
  22. package/dist/cli.js.map +1 -0
  23. package/dist/main.d.ts +3 -0
  24. package/dist/main.d.ts.map +1 -0
  25. package/dist/main.js +21 -0
  26. package/dist/main.js.map +1 -0
  27. package/dist/server.d.ts +3 -0
  28. package/dist/server.d.ts.map +1 -0
  29. package/dist/server.js +11 -0
  30. package/dist/server.js.map +1 -0
  31. package/dist/services/calendar.d.ts +77 -0
  32. package/dist/services/calendar.d.ts.map +1 -0
  33. package/dist/services/calendar.js +141 -0
  34. package/dist/services/calendar.js.map +1 -0
  35. package/dist/services/contacts-tasks.d.ts +61 -0
  36. package/dist/services/contacts-tasks.d.ts.map +1 -0
  37. package/dist/services/contacts-tasks.js +103 -0
  38. package/dist/services/contacts-tasks.js.map +1 -0
  39. package/dist/services/docs.d.ts +30 -0
  40. package/dist/services/docs.d.ts.map +1 -0
  41. package/dist/services/docs.js +60 -0
  42. package/dist/services/docs.js.map +1 -0
  43. package/dist/services/drive.d.ts +51 -0
  44. package/dist/services/drive.d.ts.map +1 -0
  45. package/dist/services/drive.js +80 -0
  46. package/dist/services/drive.js.map +1 -0
  47. package/dist/services/forms.d.ts +28 -0
  48. package/dist/services/forms.d.ts.map +1 -0
  49. package/dist/services/forms.js +54 -0
  50. package/dist/services/forms.js.map +1 -0
  51. package/dist/services/gmail.d.ts +64 -0
  52. package/dist/services/gmail.d.ts.map +1 -0
  53. package/dist/services/gmail.js +144 -0
  54. package/dist/services/gmail.js.map +1 -0
  55. package/dist/services/sheets.d.ts +44 -0
  56. package/dist/services/sheets.d.ts.map +1 -0
  57. package/dist/services/sheets.js +53 -0
  58. package/dist/services/sheets.js.map +1 -0
  59. package/dist/services/slides.d.ts +28 -0
  60. package/dist/services/slides.d.ts.map +1 -0
  61. package/dist/services/slides.js +54 -0
  62. package/dist/services/slides.js.map +1 -0
  63. package/dist/services/youtube.d.ts +40 -0
  64. package/dist/services/youtube.d.ts.map +1 -0
  65. package/dist/services/youtube.js +91 -0
  66. package/dist/services/youtube.js.map +1 -0
  67. package/dist/tools/index.d.ts +3 -0
  68. package/dist/tools/index.d.ts.map +1 -0
  69. package/dist/tools/index.js +659 -0
  70. package/dist/tools/index.js.map +1 -0
  71. package/dist/util/result.d.ts +29 -0
  72. package/dist/util/result.d.ts.map +1 -0
  73. package/dist/util/result.js +21 -0
  74. package/dist/util/result.js.map +1 -0
  75. package/package.json +54 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../src/auth/oauth.ts"],"names":[],"mappings":"AAIA,OAAO,EAAyC,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAIjF,MAAM,WAAW,QAAQ;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4DAA4D;IAC5D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAMD,yEAAyE;AACzE,eAAO,MAAM,uBAAuB,QAAgB,CAAC;AAErD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAIzD;AAoBD,2CAA2C;AAC3C,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAYlE;AAED,iEAAiE;AACjE,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ5D;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,EACrB,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GACnC,OAAO,CAAC,YAAY,CAAC,CA0FvB;AA+BD,iDAAiD;AACjD,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAMlF;AAED,4GAA4G;AAC5G,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAKhG;AAED,oFAAoF;AACpF,wBAAsB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAanG;AAED,yDAAyD;AACzD,wBAAgB,aAAa,IAAI,MAAM,CAEtC"}
@@ -0,0 +1,211 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import { createServer } from "node:http";
3
+ import { execFile } from "node:child_process";
4
+ import { promisify } from "node:util";
5
+ import { DEFAULT_REDIRECT_PORT, DEFAULT_SCOPES } from "./config.js";
6
+ const execFileAsync = promisify(execFile);
7
+ const TOKEN_ENDPOINT = "https://oauth2.googleapis.com/token";
8
+ const AUTH_ENDPOINT = "https://accounts.google.com/o/oauth2/v2/auth";
9
+ const USERINFO_ENDPOINT = "https://www.googleapis.com/oauth2/v2/userinfo";
10
+ /** How long the loopback callback server waits for Google's redirect. */
11
+ export const DEFAULT_AUTH_TIMEOUT_MS = 5 * 60 * 1000;
12
+ /**
13
+ * Resolve the redirect URI this server registers with Google. A full
14
+ * `redirectUri` override wins; otherwise the URI is derived from the loopback
15
+ * port. The value must exactly match a redirect URI registered for the OAuth
16
+ * client in the Google Cloud Console.
17
+ */
18
+ export function resolveRedirectUri(config) {
19
+ if (config.redirectUri)
20
+ return config.redirectUri;
21
+ const port = config.redirectPort ?? DEFAULT_REDIRECT_PORT;
22
+ return `http://127.0.0.1:${port}`;
23
+ }
24
+ /** Parse the resolved redirect URI into bind host/port and accepted paths. */
25
+ function parseCallbackTarget(config) {
26
+ const uri = new URL(resolveRedirectUri(config));
27
+ const hostname = uri.hostname || "127.0.0.1";
28
+ const host = hostname === "localhost" ? "127.0.0.1" : hostname;
29
+ const port = uri.port ? Number(uri.port) : DEFAULT_REDIRECT_PORT;
30
+ const configuredPath = uri.pathname && uri.pathname !== "/" ? uri.pathname : "/";
31
+ return { host, port, paths: new Set([configuredPath, "/", "/oauth2callback"]) };
32
+ }
33
+ /** Build the Google consent-screen URL. */
34
+ export function buildAuthUrl(config, state) {
35
+ const scopes = config.scopes?.length ? config.scopes : DEFAULT_SCOPES;
36
+ const url = new URL(AUTH_ENDPOINT);
37
+ url.searchParams.set("client_id", config.clientId);
38
+ url.searchParams.set("redirect_uri", resolveRedirectUri(config));
39
+ url.searchParams.set("response_type", "code");
40
+ url.searchParams.set("scope", scopes.join(" "));
41
+ url.searchParams.set("access_type", "offline");
42
+ url.searchParams.set("prompt", "consent");
43
+ url.searchParams.set("state", state);
44
+ url.searchParams.set("include_granted_scopes", "true");
45
+ return url.toString();
46
+ }
47
+ /** Open a URL in the default browser on the current platform. */
48
+ export async function openBrowser(url) {
49
+ if (process.platform === "darwin") {
50
+ await execFileAsync("open", [url]);
51
+ }
52
+ else if (process.platform === "win32") {
53
+ await execFileAsync("cmd", ["/c", "start", "", url]);
54
+ }
55
+ else {
56
+ await execFileAsync("xdg-open", [url]);
57
+ }
58
+ }
59
+ /**
60
+ * Start a loopback HTTP server on the configured redirect URI and wait for
61
+ * Google to redirect back with an authorization code. Resolves with the code
62
+ * and state; rejects on CSRF state mismatch, a missing code, a bind failure,
63
+ * or when `timeoutMs` elapses.
64
+ *
65
+ * The listener is always closed once the promise settles, so an aborted or
66
+ * timed-out flow never leaves a stale port occupied (which would otherwise
67
+ * cause EADDRINUSE on the next attempt).
68
+ */
69
+ export function waitForOAuthCallback(config, expectedState, options = {}) {
70
+ return new Promise((resolve, reject) => {
71
+ const target = parseCallbackTarget(config);
72
+ const timeoutMs = options.timeoutMs ?? DEFAULT_AUTH_TIMEOUT_MS;
73
+ let timer;
74
+ let server;
75
+ let closed = false;
76
+ /** Close the listener (optionally force-dropping active connections) and stop the timer. */
77
+ const finish = (force) => {
78
+ if (closed)
79
+ return;
80
+ closed = true;
81
+ if (timer)
82
+ clearTimeout(timer);
83
+ timer = undefined;
84
+ if (server) {
85
+ if (force)
86
+ server.closeAllConnections?.();
87
+ server.close();
88
+ }
89
+ };
90
+ const callbackHtml = "<html><body><h3>Google Service MCP: authorization received.</h3>" +
91
+ "<p>You can close this window and return to your terminal.</p></body></html>";
92
+ server = createServer((req, res) => {
93
+ let url;
94
+ try {
95
+ url = new URL(req.url ?? "/", resolveRedirectUri(config));
96
+ }
97
+ catch {
98
+ res.writeHead(400).end();
99
+ return;
100
+ }
101
+ // Accept the configured redirect path plus the legacy root paths
102
+ // (`/` for `http://127.0.0.1:<port>`, `/oauth2callback` for older configs).
103
+ if (!target.paths.has(url.pathname)) {
104
+ res.writeHead(404);
105
+ res.end("Not found");
106
+ return;
107
+ }
108
+ const code = url.searchParams.get("code") ?? "";
109
+ const state = url.searchParams.get("state") ?? "";
110
+ if (state !== expectedState) {
111
+ res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
112
+ res.end(callbackHtml);
113
+ finish(false);
114
+ reject(new Error("OAuth state mismatch — possible CSRF attack. Aborting authorization."));
115
+ return;
116
+ }
117
+ if (!code) {
118
+ res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
119
+ res.end(callbackHtml);
120
+ finish(false);
121
+ reject(new Error("No authorization code in callback URL."));
122
+ return;
123
+ }
124
+ res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
125
+ res.end(callbackHtml);
126
+ finish(false);
127
+ resolve({ code, state });
128
+ });
129
+ server.on("error", (e) => {
130
+ finish(true);
131
+ if (e.code === "EADDRINUSE") {
132
+ reject(new Error(`Could not start the OAuth callback server: port ${target.port} (host ${target.host}) is already in use. ` +
133
+ `Set GOOGLE_MCP_REDIRECT_URI (or redirectUri in config.json, GOOGLE_MCP_REDIRECT_PORT, ` +
134
+ `or redirectPort) to a free loopback endpoint and retry.`));
135
+ }
136
+ else {
137
+ reject(new Error(`OAuth callback server failed: ${e.message}`));
138
+ }
139
+ });
140
+ timer = setTimeout(() => {
141
+ finish(true);
142
+ reject(new Error(`Timed out waiting for the OAuth callback after ${Math.round(timeoutMs / 1000)}s. ` +
143
+ `Open the authorization URL in a browser and approve the prompt.`));
144
+ }, timeoutMs);
145
+ timer.unref?.();
146
+ server.listen(target.port, target.host);
147
+ });
148
+ }
149
+ async function postTokenRequest(config, body) {
150
+ const params = new URLSearchParams({
151
+ client_id: config.clientId,
152
+ });
153
+ params.set("client_secret", config.clientSecret);
154
+ for (const [key, value] of Object.entries(body)) {
155
+ params.set(key, value);
156
+ }
157
+ const response = await fetch(TOKEN_ENDPOINT, {
158
+ method: "POST",
159
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
160
+ body: params,
161
+ });
162
+ const data = await response.json().catch(() => ({}));
163
+ if (!response.ok || typeof data.access_token !== "string") {
164
+ throw new Error(`Token request failed: ${JSON.stringify(data)}`);
165
+ }
166
+ const expiresIn = typeof data.expires_in === "number" ? data.expires_in : 3600;
167
+ const refresh = typeof data.refresh_token === "string" && data.refresh_token
168
+ ? data.refresh_token
169
+ : (body.refresh_token ?? undefined);
170
+ return {
171
+ accessToken: data.access_token,
172
+ refreshToken: refresh,
173
+ expiryDate: Date.now() + expiresIn * 1000,
174
+ };
175
+ }
176
+ /** Exchange an authorization code for tokens. */
177
+ export async function exchangeCode(config, code) {
178
+ return postTokenRequest(config, {
179
+ code,
180
+ redirect_uri: resolveRedirectUri(config),
181
+ grant_type: "authorization_code",
182
+ });
183
+ }
184
+ /** Refresh an expired access token. Keeps the existing refresh token if the provider does not rotate it. */
185
+ export async function refreshAccessToken(config, refreshToken) {
186
+ return postTokenRequest(config, {
187
+ refresh_token: refreshToken,
188
+ grant_type: "refresh_token",
189
+ });
190
+ }
191
+ /** Best-effort fetch of the signed-in user's profile (email/name). Never throws. */
192
+ export async function fetchUserInfo(accessToken) {
193
+ try {
194
+ const response = await fetch(USERINFO_ENDPOINT, {
195
+ headers: { Authorization: `Bearer ${accessToken}` },
196
+ });
197
+ if (response.ok) {
198
+ const data = await response.json();
199
+ return { email: data.email, name: data.name };
200
+ }
201
+ }
202
+ catch {
203
+ // ignore network failures
204
+ }
205
+ return {};
206
+ }
207
+ /** Generate a random state value for CSRF protection. */
208
+ export function generateState() {
209
+ return randomBytes(16).toString("hex");
210
+ }
211
+ //# sourceMappingURL=oauth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.js","sourceRoot":"","sources":["../../src/auth/oauth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /** A fully-authenticated account record persisted to disk. */
2
+ export interface StoredAccount {
3
+ /** Sanitized account name (the identifier used in tool calls). */
4
+ name: string;
5
+ /** Email address returned by Google at authorization time, if available. */
6
+ email?: string;
7
+ accessToken: string;
8
+ refreshToken: string;
9
+ /** Epoch milliseconds after which accessToken is no longer valid. */
10
+ expiryDate?: number;
11
+ scopes: string[];
12
+ createdAt: string;
13
+ }
14
+ export declare function saveAccount(account: StoredAccount): Promise<void>;
15
+ export declare function loadAccount(name: string): Promise<StoredAccount | null>;
16
+ export declare function loadAllAccounts(): Promise<StoredAccount[]>;
17
+ export declare function deleteAccount(name: string): Promise<boolean>;
18
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/auth/store.ts"],"names":[],"mappings":"AAIA,8DAA8D;AAC9D,MAAM,WAAW,aAAa;IAC5B,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAKvE;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAO7E;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC,CAchE;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOlE"}
@@ -0,0 +1,45 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { ensureDirs, getAccountPath, getAccountsDir, sanitizeName } from "./config.js";
4
+ export async function saveAccount(account) {
5
+ await ensureDirs();
6
+ const safeName = sanitizeName(account.name);
7
+ const toWrite = { ...account, name: safeName };
8
+ await fs.writeFile(getAccountPath(safeName), JSON.stringify(toWrite, null, 2), "utf8");
9
+ }
10
+ export async function loadAccount(name) {
11
+ try {
12
+ const raw = await fs.readFile(getAccountPath(name), "utf8");
13
+ return JSON.parse(raw);
14
+ }
15
+ catch {
16
+ return null;
17
+ }
18
+ }
19
+ export async function loadAllAccounts() {
20
+ await ensureDirs();
21
+ const files = await fs.readdir(getAccountsDir());
22
+ const accounts = [];
23
+ for (const file of files) {
24
+ if (!file.endsWith(".json"))
25
+ continue;
26
+ try {
27
+ const raw = await fs.readFile(path.join(getAccountsDir(), file), "utf8");
28
+ accounts.push(JSON.parse(raw));
29
+ }
30
+ catch {
31
+ // Corrupt or unreadable account file — skip it rather than crash the server.
32
+ }
33
+ }
34
+ return accounts.sort((a, b) => a.name.localeCompare(b.name));
35
+ }
36
+ export async function deleteAccount(name) {
37
+ try {
38
+ await fs.unlink(getAccountPath(name));
39
+ return true;
40
+ }
41
+ catch {
42
+ return false;
43
+ }
44
+ }
45
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/auth/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAgBvF,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAsB;IACtD,MAAM,UAAU,EAAE,CAAC;IACnB,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAkB,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IAC9D,MAAM,EAAE,CAAC,SAAS,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AACzF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAY;IAC5C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;QAC5D,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAkB,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,MAAM,UAAU,EAAE,CAAC;IACnB,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAoB,EAAE,CAAC;IACrC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;YAAE,SAAS;QACtC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;YACzE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAkB,CAAC,CAAC;QAClD,CAAC;QAAC,MAAM,CAAC;YACP,6EAA6E;QAC/E,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAY;IAC9C,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC;QACtC,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ export interface CliResult {
2
+ exitCode: number;
3
+ output: string;
4
+ }
5
+ /** Pure dispatch used by the CLI. Returns exit code + text output. */
6
+ export declare function dispatchCommand(args: string[]): Promise<CliResult>;
7
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAyBD,sEAAsE;AACtE,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CAiFxE"}
package/dist/cli.js ADDED
@@ -0,0 +1,112 @@
1
+ import { authManager } from "./auth/manager.js";
2
+ const VERSION = "0.1.0";
3
+ const HELP = `google-services-mcp — Google services MCP server
4
+
5
+ Usage:
6
+ google-services-mcp Run the MCP server over stdio
7
+ google-services-mcp add <name> [--timeout <seconds>] Add a Google account (opens browser)
8
+ google-services-mcp list List connected accounts
9
+ google-services-mcp remove <name> Remove an account
10
+ google-services-mcp set-default <name> Set the default account
11
+ google-services-mcp status Show config, accounts and token health
12
+ google-services-mcp --version Print version
13
+ google-services-mcp --help Show this help
14
+ `;
15
+ /** Parse an optional `--timeout <seconds>` flag into milliseconds. */
16
+ function parseTimeout(args) {
17
+ const idx = args.indexOf("--timeout");
18
+ if (idx === -1)
19
+ return undefined;
20
+ const seconds = Number(args[idx + 1]);
21
+ return Number.isFinite(seconds) && seconds > 0 ? seconds * 1000 : undefined;
22
+ }
23
+ /** Pure dispatch used by the CLI. Returns exit code + text output. */
24
+ export async function dispatchCommand(args) {
25
+ const [cmd, ...rest] = args;
26
+ switch (cmd) {
27
+ case undefined:
28
+ case "serve":
29
+ throw new Error("serve must be handled by main(); use --help");
30
+ case "-h":
31
+ case "--help":
32
+ case "help":
33
+ return { exitCode: 0, output: HELP };
34
+ case "--version":
35
+ case "-v": {
36
+ return { exitCode: 0, output: `${VERSION}\n` };
37
+ }
38
+ case "add": {
39
+ const name = rest[0];
40
+ if (!name) {
41
+ return { exitCode: 1, output: "Usage: google-services-mcp add <name> [--timeout <seconds>]\n" };
42
+ }
43
+ try {
44
+ const timeoutMs = parseTimeout(rest);
45
+ const account = await authManager.addAccount(name, ...(timeoutMs ? [{ timeoutMs }] : []));
46
+ return {
47
+ exitCode: 0,
48
+ output: `Added account "${account.name}" for ${account.email}\n`,
49
+ };
50
+ }
51
+ catch (error) {
52
+ return { exitCode: 1, output: `Error: ${error instanceof Error ? error.message : String(error)}\n` };
53
+ }
54
+ }
55
+ case "list": {
56
+ const accounts = await authManager.listAccounts();
57
+ if (accounts.length === 0)
58
+ return { exitCode: 0, output: "No accounts configured.\n" };
59
+ const status = await authManager.getStatus();
60
+ const lines = accounts.map((a) => {
61
+ const def = a.name === status.defaultAccount ? " (default)" : "";
62
+ return ` ${a.name}${def} — ${a.email ?? "(no email)"}`;
63
+ });
64
+ return { exitCode: 0, output: `Accounts:\n${lines.join("\n")}\n` };
65
+ }
66
+ case "remove": {
67
+ const name = rest[0];
68
+ if (!name)
69
+ return { exitCode: 1, output: "Usage: google-services-mcp remove <name>\n" };
70
+ const removed = await authManager.removeAccount(name);
71
+ if (!removed)
72
+ return { exitCode: 1, output: `No account named "${name}" was found.\n` };
73
+ return { exitCode: 0, output: `Removed account "${name}".\n` };
74
+ }
75
+ case "set-default": {
76
+ const name = rest[0];
77
+ if (!name)
78
+ return { exitCode: 1, output: "Usage: google-services-mcp set-default <name>\n" };
79
+ try {
80
+ await authManager.setDefaultAccount(name);
81
+ return { exitCode: 0, output: `Default account set to "${name}".\n` };
82
+ }
83
+ catch (error) {
84
+ return { exitCode: 1, output: `Error: ${error instanceof Error ? error.message : String(error)}\n` };
85
+ }
86
+ }
87
+ case "status": {
88
+ const status = await authManager.getStatus();
89
+ const lines = [
90
+ `Credentials configured: ${status.credentialsConfigured ? "yes" : "no"}`,
91
+ `Data directory: ${status.dataDir}`,
92
+ `Default account: ${status.defaultAccount ?? "(none)"}`,
93
+ "",
94
+ "Accounts:",
95
+ ];
96
+ if (status.accounts.length === 0) {
97
+ lines.push(" (none)");
98
+ }
99
+ else {
100
+ for (const a of status.accounts) {
101
+ const health = a.tokenHealthy ? "ok" : "expired";
102
+ const email = a.email ? ` — ${a.email}` : "";
103
+ lines.push(` ${a.name}${email} [token ${health}]`);
104
+ }
105
+ }
106
+ return { exitCode: 0, output: lines.join("\n") + "\n" };
107
+ }
108
+ default:
109
+ return { exitCode: 1, output: `Unknown command: ${cmd}\n\n${HELP}` };
110
+ }
111
+ }
112
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAOhD,MAAM,OAAO,GAAG,OAAO,CAAC;AAExB,MAAM,IAAI,GAAG;;;;;;;;;;;CAWZ,CAAC;AAEF,sEAAsE;AACtE,SAAS,YAAY,CAAC,IAAc;IAClC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACtC,IAAI,GAAG,KAAK,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC;IACjC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IACtC,OAAO,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AAC9E,CAAC;AAED,sEAAsE;AACtE,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAc;IAClD,MAAM,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IAE5B,QAAQ,GAAG,EAAE,CAAC;QACZ,KAAK,SAAS,CAAC;QACf,KAAK,OAAO;YACV,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACjE,KAAK,IAAI,CAAC;QACV,KAAK,QAAQ,CAAC;QACd,KAAK,MAAM;YACT,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QACvC,KAAK,WAAW,CAAC;QACjB,KAAK,IAAI,CAAC,CAAC,CAAC;YACV,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,IAAI,EAAE,CAAC;QACjD,CAAC;QACD,KAAK,KAAK,CAAC,CAAC,CAAC;YACX,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACrB,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,+DAA+D,EAAE,CAAC;YAClG,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;gBACrC,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;gBAC1F,OAAO;oBACL,QAAQ,EAAE,CAAC;oBACX,MAAM,EAAE,kBAAkB,OAAO,CAAC,IAAI,SAAS,OAAO,CAAC,KAAK,IAAI;iBACjE,CAAC;YACJ,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,UAAU,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;YACvG,CAAC;QACH,CAAC;QACD,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,YAAY,EAAE,CAAC;YAClD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,2BAA2B,EAAE,CAAC;YACvF,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,SAAS,EAAE,CAAC;YAC7C,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBAC/B,MAAM,GAAG,GAAG,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;gBACjE,OAAO,KAAK,CAAC,CAAC,IAAI,GAAG,GAAG,MAAM,CAAC,CAAC,KAAK,IAAI,YAAY,EAAE,CAAC;YAC1D,CAAC,CAAC,CAAC;YACH,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,cAAc,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QACrE,CAAC;QACD,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACrB,IAAI,CAAC,IAAI;gBAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,4CAA4C,EAAE,CAAC;YACxF,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;YACtD,IAAI,CAAC,OAAO;gBAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,qBAAqB,IAAI,gBAAgB,EAAE,CAAC;YACxF,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,oBAAoB,IAAI,MAAM,EAAE,CAAC;QACjE,CAAC;QACD,KAAK,aAAa,CAAC,CAAC,CAAC;YACnB,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACrB,IAAI,CAAC,IAAI;gBAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,iDAAiD,EAAE,CAAC;YAC7F,IAAI,CAAC;gBACH,MAAM,WAAW,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;gBAC1C,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,2BAA2B,IAAI,MAAM,EAAE,CAAC;YACxE,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,UAAU,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;YACvG,CAAC;QACH,CAAC;QACD,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,SAAS,EAAE,CAAC;YAC7C,MAAM,KAAK,GAAG;gBACZ,2BAA2B,MAAM,CAAC,qBAAqB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE;gBACxE,mBAAmB,MAAM,CAAC,OAAO,EAAE;gBACnC,oBAAoB,MAAM,CAAC,cAAc,IAAI,QAAQ,EAAE;gBACvD,EAAE;gBACF,WAAW;aACZ,CAAC;YACF,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACjC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACzB,CAAC;iBAAM,CAAC;gBACN,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;oBAChC,MAAM,MAAM,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;oBACjD,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC7C,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,GAAG,KAAK,WAAW,MAAM,GAAG,CAAC,CAAC;gBACtD,CAAC;YACH,CAAC;YACD,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC;QAC1D,CAAC;QACD;YACE,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,oBAAoB,GAAG,OAAO,IAAI,EAAE,EAAE,CAAC;IACzE,CAAC;AACH,CAAC"}
package/dist/main.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":""}
package/dist/main.js ADDED
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env node
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { createServer } from "./server.js";
4
+ import { dispatchCommand } from "./cli.js";
5
+ async function main() {
6
+ const args = process.argv.slice(2);
7
+ if (args[0] === undefined || args[0] === "serve") {
8
+ const server = createServer();
9
+ const transport = new StdioServerTransport();
10
+ await server.connect(transport);
11
+ return;
12
+ }
13
+ const result = await dispatchCommand(args);
14
+ process.stdout.write(result.output);
15
+ process.exitCode = result.exitCode;
16
+ }
17
+ main().catch((error) => {
18
+ process.stderr.write(`Error: ${error instanceof Error ? error.message : String(error)}\n`);
19
+ process.exit(1);
20
+ });
21
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAEnC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,SAAS,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,OAAO,EAAE,CAAC;QACjD,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;QAC9B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAChC,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,IAAI,CAAC,CAAC;IAC3C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACpC,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;AACrC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC3F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function createServer(): McpServer;
3
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGpE,wBAAgB,YAAY,IAAI,SAAS,CAOxC"}
package/dist/server.js ADDED
@@ -0,0 +1,11 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { registerTools } from "./tools/index.js";
3
+ export function createServer() {
4
+ const server = new McpServer({
5
+ name: "google-services-mcp",
6
+ version: "0.1.0",
7
+ });
8
+ registerTools(server);
9
+ return server;
10
+ }
11
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,MAAM,UAAU,YAAY;IAC1B,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,qBAAqB;QAC3B,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IACH,aAAa,CAAC,MAAM,CAAC,CAAC;IACtB,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,77 @@
1
+ import type { Auth } from "googleapis";
2
+ export interface ListEventsOptions {
3
+ calendarId?: string;
4
+ timeMin?: string;
5
+ timeMax?: string;
6
+ maxResults?: number;
7
+ q?: string;
8
+ }
9
+ export interface CreateEventOptions {
10
+ calendarId?: string;
11
+ summary: string;
12
+ description?: string;
13
+ location?: string;
14
+ /** RFC3339 datetime, or a plain date (YYYY-MM-DD) for all-day events. */
15
+ start: string;
16
+ /** RFC3339 datetime, or a plain date (YYYY-MM-DD, exclusive) for all-day events. */
17
+ end: string;
18
+ attendees?: string[];
19
+ }
20
+ export interface UpdateEventOptions {
21
+ calendarId?: string;
22
+ eventId: string;
23
+ summary?: string;
24
+ description?: string;
25
+ location?: string;
26
+ start?: string;
27
+ end?: string;
28
+ attendees?: string[];
29
+ }
30
+ export interface GetEventOptions {
31
+ calendarId?: string;
32
+ eventId: string;
33
+ }
34
+ export interface DeleteEventOptions extends GetEventOptions {
35
+ }
36
+ export interface CalendarSummary {
37
+ id: string;
38
+ summary?: string;
39
+ isPrimary?: boolean;
40
+ accessRole?: string;
41
+ }
42
+ export interface EventSummary {
43
+ id: string;
44
+ summary?: string;
45
+ description?: string;
46
+ location?: string;
47
+ start?: {
48
+ dateTime?: string;
49
+ date?: string;
50
+ };
51
+ end?: {
52
+ dateTime?: string;
53
+ date?: string;
54
+ };
55
+ hangoutLink?: string;
56
+ htmlLink?: string;
57
+ attendees?: Array<{
58
+ email: string;
59
+ displayName?: string;
60
+ responseStatus?: string;
61
+ }>;
62
+ }
63
+ /** List the user's calendars. */
64
+ export declare function listCalendars(client: Auth.OAuth2Client): Promise<CalendarSummary[]>;
65
+ /** List events in a calendar, optionally filtered by time range / free-text query. */
66
+ export declare function listEvents(client: Auth.OAuth2Client, opts: ListEventsOptions): Promise<EventSummary[]>;
67
+ /** Create an event. Returns the created event. */
68
+ export declare function createEvent(client: Auth.OAuth2Client, opts: CreateEventOptions): Promise<EventSummary>;
69
+ /** Get a single event. */
70
+ export declare function getEvent(client: Auth.OAuth2Client, opts: GetEventOptions): Promise<EventSummary>;
71
+ /** Update an existing event (partial). */
72
+ export declare function updateEvent(client: Auth.OAuth2Client, opts: UpdateEventOptions): Promise<EventSummary>;
73
+ /** Delete an event. */
74
+ export declare function deleteEvent(client: Auth.OAuth2Client, opts: DeleteEventOptions): Promise<void>;
75
+ /** Create an event with an attached Google Meet conference. Returns the hangout link. */
76
+ export declare function createMeetLink(client: Auth.OAuth2Client, opts: CreateEventOptions): Promise<EventSummary>;
77
+ //# sourceMappingURL=calendar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar.d.ts","sourceRoot":"","sources":["../../src/services/calendar.ts"],"names":[],"mappings":"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"}