github JavaScript analyzed 9b3ea0b

karthikcsq/google-tools-mcp

github

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.

maintainer
karthikcsq
licence
MIT
first seen
2026-08-19
last seen
2026-09-06
releases · 30d
0
short id

Drift inferred · capture-to-capture

No drift recorded — single capability capture; advisories appear once its surface changes.

capabilities 0 tools
transport stdio · http counts 0 tools · 0 res · 0 prompts permission surface via code analysis

No tools enumerated yet for this server.

skills & danger signals github-tarball
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

code evidence vHEAD · github-tarball
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/);