MCP server unifying 169 Google Workspace tools across Drive, Docs, Sheets, Slides, Gmail, Calendar, and Forms behind a single OAuth 2.0 flow. Read-before-edit guards, lazy auth, multi-account profiles, no telemetry.
Drift inferred · capture-to-capture
No drift recorded — single capability capture; advisories appear once its surface changes.
transport stdio · http counts 0 tools · 0 res
· 0 prompts
permission surface via code analysis
No tools enumerated yet for this server.
prompt-surface
shipped agent-instruction files + hidden-content / dangerous-code findings —
quoted from the analyzed source
analyzed commit 9b3ea0b · analyzer v33 · 1w ago
skills & prompt files 1
danger signals7
- dynamic code execution new Function() karthikcsq-google-tools-mcp-9b3ea0b/tests/errorsAndLogger.test.js :308
const tagged = new Function(`return "${secret}";`); - over-broad OAuth scope https://www.googleapis.com/auth/documents
expected for this server's purpose
karthikcsq-google-tools-mcp-9b3ea0b/dist/auth.js :36
'https://www.googleapis.com/auth/documents', - over-broad OAuth scope https://www.googleapis.com/auth/drive
expected for this server's purpose
karthikcsq-google-tools-mcp-9b3ea0b/dist/auth.js :37
'https://www.googleapis.com/auth/drive', - over-broad OAuth scope https://www.googleapis.com/auth/spreadsheets
expected for this server's purpose
karthikcsq-google-tools-mcp-9b3ea0b/dist/auth.js :38
'https://www.googleapis.com/auth/spreadsheets', - over-broad OAuth scope gmail.modify karthikcsq-google-tools-mcp-9b3ea0b/dist/auth.js :41
'https://www.googleapis.com/auth/gmail.modify', - over-broad OAuth scope https://www.googleapis.com/auth/drive
expected for this server's purpose
karthikcsq-google-tools-mcp-9b3ea0b/tests/authConcurrency.test.js :26
SCOPES: ['https://www.googleapis.com/auth/drive'], - credential in logs credential in log karthikcsq-google-tools-mcp-9b3ea0b/tests/errorsAndLogger.test.js :373
logger.debug('debug keeps its level', { refresh_token: secretValues[2] });
evidence-backed
findings quoted directly from the published source artifact — not inferred
code files: 325
filesystem 70
- fs karthikcsq-google-tools-mcp-9b3ea0b/dist/auth.js :8
import * as fs from 'fs/promises'; - fs karthikcsq-google-tools-mcp-9b3ea0b/dist/clientAdapters.js :9
import * as fs from 'node:fs/promises'; - fs karthikcsq-google-tools-mcp-9b3ea0b/dist/config.js :6
import * as fs from 'fs'; - fs karthikcsq-google-tools-mcp-9b3ea0b/dist/doctor.js :1
import * as fs from 'node:fs/promises'; - fs karthikcsq-google-tools-mcp-9b3ea0b/dist/googleDocsApiHelpers.js :1359
body: fs.createReadStream(localFilePath), - fs karthikcsq-google-tools-mcp-9b3ea0b/dist/handleRuntime.js :22
import * as fs from 'node:fs/promises'; - fs karthikcsq-google-tools-mcp-9b3ea0b/dist/httpState.js :1
import * as fs from 'node:fs'; - fs karthikcsq-google-tools-mcp-9b3ea0b/dist/logger.js :4
import * as fs from 'fs'; - fs karthikcsq-google-tools-mcp-9b3ea0b/dist/setup.js :5
import * as fs from 'fs/promises'; - fs karthikcsq-google-tools-mcp-9b3ea0b/dist/setupInspect.js :3
import * as fs from 'fs/promises'; - fs (weak) karthikcsq-google-tools-mcp-9b3ea0b/dist/tools/docs/appendToGoogleDoc.js :1
import * as fs from 'fs/promises'; - fs (weak) karthikcsq-google-tools-mcp-9b3ea0b/dist/tools/docs/replaceRangeWithMarkdown.js :49
import * as fs from 'fs/promises';
show 28 more
- fs karthikcsq-google-tools-mcp-9b3ea0b/dist/tools/drive/downloadFile.js :4
import * as fs from 'fs/promises'; - fs karthikcsq-google-tools-mcp-9b3ea0b/dist/tools/drive/uploadFile.js :1
import * as fs from 'fs'; - fs karthikcsq-google-tools-mcp-9b3ea0b/dist/tools/index.js :5
import * as fs from 'fs/promises'; - fs karthikcsq-google-tools-mcp-9b3ea0b/dist/tools/utils/appendMarkdownToGoogleDoc.js :1
import * as fs from 'fs/promises'; - fs karthikcsq-google-tools-mcp-9b3ea0b/dist/tools/utils/replaceDocumentWithMarkdown.js :30
import * as fs from 'fs/promises'; - fs karthikcsq-google-tools-mcp-9b3ea0b/dist/updateCheck.js :31
import { readFile as fsReadFile, writeFile as fsWriteFile, mkdir as fsMkdir } from 'node:fs/promises'; - fs karthikcsq-google-tools-mcp-9b3ea0b/dist/workspace.js :18
import * as fs from 'fs/promises'; - fs (weak) karthikcsq-google-tools-mcp-9b3ea0b/scripts/call-local-tool.js :2
import fs from 'node:fs/promises'; - fs (weak) karthikcsq-google-tools-mcp-9b3ea0b/scripts/check-release.mjs :19
import { readFileSync } from 'node:fs'; - fs (weak) karthikcsq-google-tools-mcp-9b3ea0b/scripts/inventory-mcp-migration.mjs :18
import { mkdir, readFile, writeFile } from 'node:fs/promises'; - fs (weak) karthikcsq-google-tools-mcp-9b3ea0b/scripts/live-coverage.mjs :28
import * as fs from 'node:fs'; - fs (weak) karthikcsq-google-tools-mcp-9b3ea0b/scripts/live-mission.mjs :31
import * as fs from 'node:fs'; - fs (weak) karthikcsq-google-tools-mcp-9b3ea0b/scripts/live-smoke.mjs :19
import * as fs from 'node:fs'; - fs (weak) karthikcsq-google-tools-mcp-9b3ea0b/scripts/live-smoke/bootstrap.mjs :9
import * as fs from 'node:fs'; - fs (weak) karthikcsq-google-tools-mcp-9b3ea0b/scripts/live-smoke/call.mjs :19
import * as fs from 'node:fs'; - fs (weak) karthikcsq-google-tools-mcp-9b3ea0b/scripts/live-smoke/context.mjs :8
import * as fs from 'node:fs/promises'; - fs (weak) karthikcsq-google-tools-mcp-9b3ea0b/scripts/live-smoke/journal.mjs :8
import * as fs from 'node:fs'; - fs (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/batchModifyTextHandleIntegration.test.js :12
import * as fs from 'node:fs/promises'; - fs (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/config.test.js :4
import { access, mkdtemp, mkdir, rm, writeFile, copyFile } from 'node:fs/promises'; - fs (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/createFlowsReadSeeding.test.js :13
import * as fs from 'node:fs/promises'; - fs (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/diagnosticsLogging.test.js :3
import { chmod, mkdir, mkdtemp, readdir, readFile, rm, stat, symlink, utimes, writeFile } from 'node:fs/promises'; - fs (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/docsConflictGuardPrecision.test.js :12
import * as fs from 'node:fs/promises'; - fs (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/docsHandleLeaseFailure.test.js :17
import * as fs from 'node:fs/promises'; - fs (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/doctorSetupInspection.test.js :2
import * as fs from 'node:fs/promises'; - fs (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/documentationConsistency.test.js :2
import fs from 'node:fs/promises'; - fs (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/entrypointSmoke.test.js :14
import * as fs from 'node:fs/promises'; - fs (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/errorsAndLogger.test.js :2
import { mkdtemp, readFile, rm } from 'node:fs/promises'; - fs (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/extraDocsToolsWriteControl.test.js :9
import fs from 'fs';
30 more not shown — this panel samples each group; the count above is the real total.
shell / exec 12
- shell karthikcsq-google-tools-mcp-9b3ea0b/dist/setup.js :8
import { exec, execSync } from 'child_process'; - shell karthikcsq-google-tools-mcp-9b3ea0b/dist/shellSafe.js :9
// Windows needs care. `execFile()` refuses to spawn a `.cmd`/`.bat` file - shell (weak) karthikcsq-google-tools-mcp-9b3ea0b/scripts/inventory-mcp-migration.mjs :17
import { execFileSync } from 'node:child_process'; - shell (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/authConsentFlow.test.js :40
// execFile rather than exec (issue #125). Without this export the whole - shell (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/config.test.js :2
import { spawn } from 'node:child_process'; - shell (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/diagnosticsLogging.test.js :2
import { spawn } from 'node:child_process'; - shell (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/entrypointSmoke.test.js :12
import { spawn } from 'node:child_process'; - shell (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/errorsAndLogger.test.js :6
import { spawnSync } from 'node:child_process'; - shell (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/httpOperations.test.js :2
import { execFile } from 'node:child_process'; - shell (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/mcpServerFacade.test.js :5
import { spawn } from 'node:child_process'; - shell (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/packageContents.test.js :22
import { spawnSync } from 'node:child_process'; - shell (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/setupIdempotency.test.js :2
import { spawn } from 'node:child_process';
network 20
- net karthikcsq-google-tools-mcp-9b3ea0b/dist/auth.js :11
import * as http from 'http'; - net karthikcsq-google-tools-mcp-9b3ea0b/dist/mcpServer.js :3
import http from 'node:http'; - net karthikcsq-google-tools-mcp-9b3ea0b/dist/tools/maps/mapsClient.js :47
try { response = await fetch(url, options); } - net (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/authConsentFlow.test.js :14
import http from 'node:http'; - net (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/batchModifyTextHandleIntegration.test.js :119
const response = await handler.fetch(modernCall(name, args)); - net (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/config.test.js :5
import http from 'node:http'; - net (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/createFlowsReadSeeding.test.js :149
const response = await handler.fetch(modernCall(name, args, token)); - net (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/diagnosticsLogging.test.js :47
await handler.fetch(request('ok', { body: `content ${secret}` })); - net (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/docsConflictGuardPrecision.test.js :185
const response = await handler.fetch(modernCall(name, args)); - net (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/docsHandleLeaseFailure.test.js :166
const response = await handler.fetch(modernCall(name, args, token)); - net (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/entrypointSmoke.test.js :13
import http from 'node:http'; - net (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/httpOperations.test.js :4
import http from 'node:http';
show 8 more
- net (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/insertImageGuardBeforeUpload.test.js :128
const response = await handler.fetch(modernCall(name, args, token)); - net (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/mcpSdkV2Compatibility.test.js :98
const discoverResponse = await handler.fetch(modernRequest({ - net (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/mcpServerFacade.test.js :4
import http from 'node:http'; - net (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/modifyTextBulletPreset.test.js :95
const response = await handler.fetch(new Request('http://localhost/mcp', { - net (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/modifyTextClearStyle.test.js :94
const response = await handler.fetch(new Request('http://localhost/mcp', { - net (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/modifyTextNoOpLeaseRelease.test.js :103
const response = await handler.fetch(modernCall(name, args, token)); - net (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/readHandleIntegration.test.js :156
const response = await handler.fetch(modernCall(name, args, token)); - net (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/replaceRangeHandleIntegration.test.js :130
const response = await handler.fetch(modernCall(name, args));
secrets 6
- secrets karthikcsq-google-tools-mcp-9b3ea0b/dist/auth.js :66
if (process.env.GOOGLE_CLIENT_ID && process.env.GOOGLE_CLIENT_SECRET) { - secrets karthikcsq-google-tools-mcp-9b3ea0b/dist/setup.js :406
process.env.GOOGLE_CLIENT_SECRET = clientSecret; - secrets karthikcsq-google-tools-mcp-9b3ea0b/dist/tools/maps/mapsClient.js :14
const apiKey = process.env.GOOGLE_MAPS_API_KEY; - secrets (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/authConsentFlow.test.js :97
process.env.GOOGLE_CLIENT_SECRET = 'test-client-secret'; - secrets (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/errorsAndLogger.test.js :33
const originalClientSecret = process.env.GOOGLE_CLIENT_SECRET; - secrets (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/maps.test.js :23
delete process.env.GOOGLE_MAPS_API_KEY;
declared dependencies 23
- @modelcontextprotocol/node@2.0.0
- @modelcontextprotocol/server@2.0.0
- @clack/prompts@^1.2.0
- @googleapis/calendar@^16.0.0
- @googleapis/docs@^10.0.0
- @googleapis/drive@^21.0.0
- @googleapis/forms@^7.0.0
- @googleapis/gmail@^18.0.0
- @googleapis/script@^12.0.0
- @googleapis/serviceusage@^23.1.0
- @googleapis/sheets@^14.0.0
- @googleapis/slides@^6.0.0
show 11 more
- @googleapis/tasks@^13.0.0
- chalk@^5.6.2
- diff@^9.0.0
- google-auth-library@^10.5.0
- hono@^4.13.5
- mammoth@^1.9.0
- markdown-it@^14.3.1
- pdf-parse@^1.1.1
- zod@^4.2.0
- @jest/globals@^30.3.0
- jest@^30.3.0
perm:untrusted 1
- untrusted (weak) karthikcsq-google-tools-mcp-9b3ea0b/tests/mcpServerFacade.test.js :94
const list = await (await handler.fetch(modern('tools/list'))).json();
transport_posture 1
- binds all interfaces (0.0.0.0) karthikcsq-google-tools-mcp-9b3ea0b/tests/httpAuth.test.js :86
expect(() => assertSafeHttpBinding({ host: '0.0.0.0', noAuth: false })).toThrow(/loopback-only/);