google-sheet-mcp 1.0.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.
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * google-sheet-mcp CLI
4
+ *
5
+ * Usage:
6
+ * npx google-sheet-mcp init — Setup (service account, default)
7
+ * npx google-sheet-mcp init --auth oauth — Setup (OAuth2, personal account)
8
+ * npx google-sheet-mcp test — Test connection
9
+ * npx google-sheet-mcp token-status — Check OAuth2 token health
10
+ * npx google-sheet-mcp list — List sheets
11
+ * npx google-sheet-mcp read — Read sheet data
12
+ * npx google-sheet-mcp config — Show current config
13
+ */
14
+
15
+ import { program } from "commander";
16
+ import { initCommand } from "./commands/init.mjs";
17
+ import { testCommand } from "./commands/test.mjs";
18
+ import { listCommand } from "./commands/list.mjs";
19
+ import { readCommand } from "./commands/read.mjs";
20
+ import { configCommand } from "./commands/config.mjs";
21
+ import { createCommand } from "./commands/create.mjs";
22
+ import { appendCommand } from "./commands/append.mjs";
23
+ import { tokenStatusCommand } from "./commands/token-status.mjs";
24
+
25
+ program
26
+ .name("google-sheet-mcp")
27
+ .description(
28
+ "Connect Google Sheets to Cursor, VS Code, Claude Code and AI agents in 3 minutes."
29
+ )
30
+ .version("1.0.0");
31
+
32
+ program
33
+ .command("init")
34
+ .description("Interactive setup: connect a Google Sheet")
35
+ .option(
36
+ "--auth <type>",
37
+ "Authentication type: service-account (default) or oauth",
38
+ "service-account"
39
+ )
40
+ .action(initCommand);
41
+
42
+ program
43
+ .command("test")
44
+ .description("Test connection to the configured Google Sheet")
45
+ .option("-s, --sheet <name>", "Test reading a specific sheet")
46
+ .action(testCommand);
47
+
48
+ program
49
+ .command("list")
50
+ .description("List all sheets in the connected spreadsheet")
51
+ .action(listCommand);
52
+
53
+ program
54
+ .command("read")
55
+ .description("Read data from a sheet")
56
+ .requiredOption("-s, --sheet <name>", "Sheet name to read")
57
+ .option("-r, --range <range>", "Cell range in A1 notation (e.g., A1:Z100)")
58
+ .option("--raw", "Return raw 2D array instead of objects")
59
+ .action(readCommand);
60
+
61
+ program
62
+ .command("config")
63
+ .description("Show current configuration")
64
+ .action(configCommand);
65
+
66
+ program
67
+ .command("create")
68
+ .description("Create a new sheet")
69
+ .requiredOption("-s, --sheet <name>", "New sheet name")
70
+ .action(createCommand);
71
+
72
+ program
73
+ .command("append")
74
+ .description("Append a row to a sheet")
75
+ .requiredOption("-s, --sheet <name>", "Sheet name")
76
+ .requiredOption(
77
+ "-d, --data <json>",
78
+ "Row data as JSON (e.g., '{\"name\":\"Anton\"}')"
79
+ )
80
+ .action(appendCommand);
81
+
82
+ program
83
+ .command("token-status")
84
+ .description("Check OAuth2 token health (validates refresh token)")
85
+ .action(tokenStatusCommand);
86
+
87
+ program.parse(process.argv);
@@ -0,0 +1,55 @@
1
+ /**
2
+ * append — Add a row to a sheet.
3
+ */
4
+
5
+ import chalk from "chalk";
6
+ import ora from "ora";
7
+ import { loadConfig } from "../../config/config.mjs";
8
+ import { createSheetsClient } from "../../server/sheets-client.mjs";
9
+
10
+ export async function appendCommand(options) {
11
+ const config = loadConfig();
12
+ if (!config) {
13
+ console.error(chalk.red("❌ No configuration found. Run `npx google-sheet-mcp init` first."));
14
+ process.exit(1);
15
+ }
16
+
17
+ let data;
18
+ try {
19
+ data = JSON.parse(options.data);
20
+ } catch {
21
+ console.error(chalk.red("❌ Invalid JSON for --data. Example: '{\"name\":\"Anton\"}'"));
22
+ process.exit(1);
23
+ }
24
+
25
+ const spinner = ora(`Appending to "${options.sheet}"...`).start();
26
+
27
+ try {
28
+ // First, get headers to align columns
29
+ const sheets = createSheetsClient(config.credentialsPath);
30
+ const headerRes = await sheets.spreadsheets.values.get({
31
+ spreadsheetId: config.spreadsheetId,
32
+ range: `${options.sheet}!1:1`,
33
+ });
34
+
35
+ const headers = headerRes.data.values?.[0] || Object.keys(data);
36
+ const row = headers.map((h) => data[h] ?? "");
37
+
38
+ await sheets.spreadsheets.values.append({
39
+ spreadsheetId: config.spreadsheetId,
40
+ range: `${options.sheet}!A1`,
41
+ valueInputOption: "USER_ENTERED",
42
+ requestBody: {
43
+ values: [row],
44
+ },
45
+ });
46
+
47
+ spinner.succeed(`Row appended to "${options.sheet}"`);
48
+ console.log(chalk.gray(` ${headers.slice(0, 6).join(" | ")}` + (headers.length > 6 ? "..." : "")));
49
+ console.log(chalk.white(` ${row.slice(0, 6).join(" | ")}` + (row.length > 6 ? "..." : "")));
50
+
51
+ } catch (err) {
52
+ spinner.fail(`Failed: ${err.message}`);
53
+ process.exit(1);
54
+ }
55
+ }
@@ -0,0 +1,93 @@
1
+ /**
2
+ * config — Show current configuration.
3
+ */
4
+
5
+ import chalk from "chalk";
6
+ import { loadConfig } from "../../config/config.mjs";
7
+
8
+ export async function configCommand() {
9
+ const config = loadConfig();
10
+ if (!config) {
11
+ console.log(chalk.yellow("⚠️ No configuration found."));
12
+ console.log();
13
+ console.log("To set up, run:");
14
+ console.log(chalk.cyan(" npx google-sheet-mcp init"));
15
+ console.log();
16
+ console.log("Or set environment variables:");
17
+ console.log(chalk.cyan(" Service Account: GOOGLE_SPREADSHEET_ID + GOOGLE_APPLICATION_CREDENTIALS"));
18
+ console.log(chalk.cyan(" OAuth2: GOOGLE_SPREADSHEET_ID + GOOGLE_CLIENT_ID + GOOGLE_CLIENT_SECRET + GOOGLE_REFRESH_TOKEN"));
19
+ return;
20
+ }
21
+
22
+ const authType = config.authType || "service-account";
23
+
24
+ console.log(chalk.bold.cyan("\n⚙️ Current Configuration\n"));
25
+ console.log(chalk.gray(` Source: ${config.source}`));
26
+ if (config._path) {
27
+ console.log(chalk.gray(` Config file: ${config._path}`));
28
+ }
29
+ console.log(chalk.white(` Spreadsheet ID: ${config.spreadsheetId}`));
30
+ console.log(chalk.white(` Auth type: ${authType}`));
31
+
32
+ if (authType === "oauth2" && config.oauth2) {
33
+ console.log(
34
+ chalk.white(
35
+ ` Client ID: ${config.oauth2.client_id?.substring(0, 16)}...`
36
+ )
37
+ );
38
+ console.log(
39
+ chalk.gray(` Refresh token: ${config.oauth2.refresh_token?.substring(0, 12)}...`)
40
+ );
41
+ console.log();
42
+ console.log(chalk.gray(" Token health:"));
43
+ console.log(chalk.cyan(" npx google-sheet-mcp token-status"));
44
+ } else {
45
+ console.log(chalk.white(` Key file: ${config.credentialsPath}`));
46
+ }
47
+
48
+ if (config.sheets && config.sheets.length > 0) {
49
+ console.log(chalk.white(` Known sheets: ${config.sheets.join(", ")}`));
50
+ }
51
+ console.log();
52
+
53
+ // MCP config hint
54
+ console.log(chalk.bold("MCP Configuration for AI IDEs:"));
55
+ console.log();
56
+ console.log(chalk.gray(" Add this to your MCP config:"));
57
+ console.log();
58
+
59
+ if (authType === "oauth2") {
60
+ console.log(
61
+ chalk.white(` {
62
+ "mcpServers": {
63
+ "google-sheets": {
64
+ "command": "npx",
65
+ "args": ["google-sheet-mcp"],
66
+ "env": {
67
+ "GOOGLE_SPREADSHEET_ID": "${config.spreadsheetId}",
68
+ "GOOGLE_CLIENT_ID": "${config.oauth2?.client_id}",
69
+ "GOOGLE_CLIENT_SECRET": "${config.oauth2?.client_secret}",
70
+ "GOOGLE_REFRESH_TOKEN": "${config.oauth2?.refresh_token}"
71
+ }
72
+ }
73
+ }
74
+ }`)
75
+ );
76
+ } else {
77
+ console.log(
78
+ chalk.white(` {
79
+ "mcpServers": {
80
+ "google-sheets": {
81
+ "command": "npx",
82
+ "args": ["google-sheet-mcp"],
83
+ "env": {
84
+ "GOOGLE_SPREADSHEET_ID": "${config.spreadsheetId}",
85
+ "GOOGLE_APPLICATION_CREDENTIALS": "${config.credentialsPath}"
86
+ }
87
+ }
88
+ }
89
+ }`)
90
+ );
91
+ }
92
+ console.log();
93
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * create — Create a new sheet tab in the spreadsheet.
3
+ */
4
+
5
+ import chalk from "chalk";
6
+ import ora from "ora";
7
+ import { loadConfig } from "../../config/config.mjs";
8
+ import { createSheetsClient } from "../../server/sheets-client.mjs";
9
+
10
+ export async function createCommand(options) {
11
+ const config = loadConfig();
12
+ if (!config) {
13
+ console.error(chalk.red("❌ No configuration found. Run `npx google-sheet-mcp init` first."));
14
+ process.exit(1);
15
+ }
16
+
17
+ const spinner = ora(`Creating sheet "${options.sheet}"...`).start();
18
+
19
+ try {
20
+ const sheets = createSheetsClient(config.credentialsPath);
21
+
22
+ await sheets.spreadsheets.batchUpdate({
23
+ spreadsheetId: config.spreadsheetId,
24
+ requestBody: {
25
+ requests: [
26
+ {
27
+ addSheet: {
28
+ properties: {
29
+ title: options.sheet,
30
+ },
31
+ },
32
+ },
33
+ ],
34
+ },
35
+ });
36
+
37
+ spinner.succeed(`Sheet "${options.sheet}" created`);
38
+ console.log();
39
+ console.log(` Read it: ${chalk.cyan(`npx google-sheet-mcp read -s "${options.sheet}"`)}`);
40
+
41
+ } catch (err) {
42
+ spinner.fail(`Failed: ${err.message}`);
43
+ process.exit(1);
44
+ }
45
+ }
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Show MCP configuration snippets for all supported IDEs.
3
+ */
4
+
5
+ import chalk from "chalk";
6
+
7
+ export function showMCPConfig() {
8
+ console.log(chalk.bold("━━━ MCP Configuration ━━━"));
9
+ console.log();
10
+ console.log(chalk.bold("Cursor (.cursor/mcp.json):"));
11
+ console.log(
12
+ chalk.white(`{
13
+ "mcpServers": {
14
+ "google-sheets": {
15
+ "command": "npx",
16
+ "args": ["google-sheet-mcp"]
17
+ }
18
+ }
19
+ }`)
20
+ );
21
+ console.log();
22
+ console.log(chalk.bold("VS Code (.vscode/mcp.json):"));
23
+ console.log(
24
+ chalk.white(`{
25
+ "servers": {
26
+ "google-sheets": {
27
+ "type": "stdio",
28
+ "command": "npx",
29
+ "args": ["google-sheet-mcp"]
30
+ }
31
+ }
32
+ }`)
33
+ );
34
+ console.log();
35
+ console.log(chalk.bold("Claude Code (.claude/mcp.json):"));
36
+ console.log(
37
+ chalk.white(`{
38
+ "mcpServers": {
39
+ "google-sheets": {
40
+ "command": "npx",
41
+ "args": ["google-sheet-mcp"]
42
+ }
43
+ }
44
+ }`)
45
+ );
46
+ console.log();
47
+ console.log(chalk.bold("Codex CLI (codex.json):"));
48
+ console.log(
49
+ chalk.white(`{
50
+ "mcpServers": {
51
+ "google-sheets": {
52
+ "command": "npx",
53
+ "args": ["-y", "google-sheet-mcp"]
54
+ }
55
+ }
56
+ }`)
57
+ );
58
+ console.log();
59
+ console.log(chalk.gray("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"));
60
+ console.log();
61
+ console.log(
62
+ "After adding the config, restart your IDE. The AI will see these tools:"
63
+ );
64
+ console.log(chalk.green(" • sheets_list_tabs — list all sheets"));
65
+ console.log(chalk.green(" • sheets_read_range — read data"));
66
+ console.log(chalk.green(" • sheets_get_sheet — sheet metadata"));
67
+ console.log(chalk.green(" • sheets_write_range — write data"));
68
+ console.log(chalk.green(" • sheets_create_tab — create new tab"));
69
+ console.log(chalk.green(" • sheets_append_row — append a row"));
70
+ console.log();
71
+ }