@mcpher/gas-fakes 1.2.8 → 1.2.9

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/gas-fakes.js CHANGED
@@ -2,14 +2,18 @@
2
2
 
3
3
  /**
4
4
  * cli for gas-fakes
5
- * v0.0.1
6
5
  */
7
6
  import fs from "fs";
8
7
  import path from "path";
9
8
  import { Command } from "commander";
10
- import dotenv from 'dotenv'
9
+ import dotenv from "dotenv";
10
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
11
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
12
+ import z from "zod";
13
+ import { exec } from "child_process";
14
+ import { promisify } from "util";
11
15
 
12
- const version = "0.0.2";
16
+ const version = "0.0.3";
13
17
 
14
18
  const program = new Command();
15
19
 
@@ -18,7 +22,6 @@ program
18
22
  .description("CLI tool for gas-fakes")
19
23
  .version(version, "-v, --version", "display the current version");
20
24
 
21
-
22
25
  program
23
26
  .description("Execute Google Apps Script using gas-fakes.")
24
27
  .option(
@@ -57,9 +60,19 @@ program
57
60
  if (Object.keys(options).length == 0) {
58
61
  program.help();
59
62
  } else {
60
- const { filename, script, sandbox, whitelist, json, display, env , gfsettings} = options;
63
+ const {
64
+ filename,
65
+ script,
66
+ sandbox,
67
+ whitelist,
68
+ json,
69
+ display,
70
+ env,
71
+ gfsettings,
72
+ } = options;
61
73
  const obj = { sandbox: !!sandbox, display };
62
- if (!filename && !script) {
74
+
75
+ if (!filename && !script && !obj.script) {
63
76
  console.error(
64
77
  "error: Provide the filename or the script of Google Apps Script."
65
78
  );
@@ -67,24 +80,24 @@ program
67
80
  }
68
81
 
69
82
  if (env) {
70
- const envPath = path.resolve(process.cwd(), env)
71
- console.log ('...using env file in', envPath)
72
- dotenv.config({ path: envPath, quiet: true});
83
+ const envPath = path.resolve(process.cwd(), env);
84
+ console.log("...using env file in", envPath);
85
+ dotenv.config({ path: envPath, quiet: true });
73
86
  }
74
87
 
75
88
  // note this must come after any env file fiddling.
76
89
  if (gfsettings) {
77
- const gfPath = path.resolve(process.cwd(), gfsettings )
78
- console.log ('...using gasfakes settings file in', gfPath)
90
+ const gfPath = path.resolve(process.cwd(), gfsettings);
91
+ console.log("...using gasfakes settings file in", gfPath);
79
92
  obj.gfSettings = gfPath;
80
93
  // override whatever is in env
81
- process.env.GF_SETTINGS_PATH = gfPath
94
+ process.env.GF_SETTINGS_PATH = gfPath;
82
95
  }
83
96
 
84
97
  if (filename) {
85
98
  obj.filename = filename;
86
99
  }
87
- if (script) {
100
+ if (!obj.script && script) {
88
101
  obj.script = script;
89
102
  }
90
103
 
@@ -108,15 +121,22 @@ program
108
121
  }
109
122
  });
110
123
 
124
+ const execAsync = promisify(exec);
125
+ program
126
+ .command("mcp")
127
+ .description("Launch gas-fakes as the MCP server")
128
+ .action(mcp_server);
129
+
111
130
  program.showHelpAfterError("(add --help for additional information)");
112
131
  program.parse();
113
132
 
114
133
  function __getImportScript(o) {
115
- const { scriptText, sandbox, whitelistItems, json_sandbox, gfSettings } = o;
134
+ const { scriptText, sandbox, whitelistItems, json_sandbox } = o;
116
135
  if (scriptText.trim() == "") {
117
136
  console.error("error: Google Apps Script was not found.");
118
137
  process.exit();
119
138
  }
139
+ let gasScriptStr = "";
120
140
  const gasScriptAr = [];
121
141
  if (json_sandbox) {
122
142
  gasScriptAr.push(
@@ -179,8 +199,7 @@ function __getImportScript(o) {
179
199
  `const behavior = ScriptApp.__behavior;`,
180
200
  `behavior.sandboxMode = true;`,
181
201
  `behavior.strictSandbox = true;`,
182
- `behavior.setIdWhitelist([${wl}]);`,
183
- `\n\n${scriptText}\n\n`,
202
+ `behavior.setIdWhitelist([${wl}]);``\n\n${scriptText}\n\n`,
184
203
  `ScriptApp.__behavior.trash();`
185
204
  );
186
205
  } else {
@@ -202,15 +221,14 @@ function __getImportScript(o) {
202
221
  }
203
222
 
204
223
  async function loadScript(o) {
205
-
206
224
  const { filename, script, display } = o;
207
-
208
225
  const scriptText = filename ? fs.readFileSync(filename, "utf8") : script;
209
- const { mainScript, gasScript } = __getImportScript({ scriptText, ...o });
226
+ const { mainScript, gasScript } = __getImportScript({
227
+ scriptText: scriptText.replace(/\\n/g, "\n"),
228
+ ...o,
229
+ });
210
230
  if (display) {
211
- console.log(`--- script ---`);
212
- console.log(gasScript);
213
- console.log(`--- /script ---`);
231
+ console.log(`\n--- script ---\n${gasScript}\n--- /script ---\n`);
214
232
  }
215
233
  const gasFunc = new Function(mainScript);
216
234
  // The script needs access to the settings path variable we just created
@@ -221,3 +239,71 @@ async function loadScript(o) {
221
239
  });
222
240
  gasFunc();
223
241
  }
242
+
243
+ async function mcp_server() {
244
+ const server = new McpServer({
245
+ name: "gas-fakes-mcp",
246
+ version: "0.0.1",
247
+ });
248
+
249
+ const { name, schema, func } = {
250
+ name: "run-gas-by-gas-fakes",
251
+ schema: {
252
+ description:
253
+ "Use this to safely run Google Apps Script in a sandbox using gas-fakes.",
254
+ inputSchema: {
255
+ script: z.string().describe(`Provide Google Apps Script as a string.`),
256
+ sandbox: z
257
+ .boolean()
258
+ .describe("Use to run Google Apps Script in a sandbox."),
259
+ whitelist: z
260
+ .string()
261
+ .describe(
262
+ "Use this to use the specific files and folders on Google Drive. whitelist of file IDs. Set the file IDs in comma-separated list. In this case, the files of the file IDs are used for both read and write. When this is used, the script is run in a sandbox."
263
+ )
264
+ .optional(),
265
+ json: z
266
+ .string()
267
+ .describe(
268
+ `Use this to manage the sandbox more if the detailed information about the sandbox is provided. JSON string including parameters for managing a sandbox. Enclose it with ' or ". When this is used, the option "whitelist" is ignored. When this is used, the script is run in a sandbox.`
269
+ )
270
+ .optional(),
271
+ },
272
+ },
273
+ func: async (options = {}) => {
274
+ const { sandbox, whitelist, json } = options;
275
+ try {
276
+ const opts = [
277
+ { v: sandbox, k: "-x" },
278
+ { v: whitelist, k: "-w" },
279
+ { v: json, k: "-j" },
280
+ ].reduce((ar, { v, k }) => {
281
+ if (v) {
282
+ ar.push(k != "-x" ? `${k} ${v}` : `${k}`);
283
+ }
284
+ return ar;
285
+ }, []);
286
+ const scriptArg = JSON.stringify(options.script.toString());
287
+ const c = `gas-fakes ${opts.join(" ")} -s ${scriptArg.replace(
288
+ /\\n/g,
289
+ "\n"
290
+ )}`;
291
+ const { stdout } = await execAsync(c);
292
+ return {
293
+ content: [{ type: "text", text: stdout || "Done." }],
294
+ isError: false,
295
+ };
296
+ } catch (err) {
297
+ return {
298
+ content: [{ type: "text", text: err.message }],
299
+ isError: true,
300
+ };
301
+ }
302
+ },
303
+ };
304
+
305
+ server.registerTool(name, schema, func);
306
+
307
+ const transport = new StdioServerTransport();
308
+ await server.connect(transport);
309
+ }
package/gasfakes.json ADDED
@@ -0,0 +1,8 @@
1
+ {
2
+ "manifest": "./appsscript.json",
3
+ "clasp": "./.clasp.json",
4
+ "scriptId": "28780abe-aaec-4526-a0bf-9d5c104c68b8",
5
+ "documentId": null,
6
+ "cache": "/tmp/gas-fakes/cache",
7
+ "properties": "/tmp/gas-fakes/properties"
8
+ }
package/package.json CHANGED
@@ -5,6 +5,7 @@
5
5
  "dependencies": {
6
6
  "@mcpher/fake-gasenum": "^1.0.2",
7
7
  "@mcpher/gas-flex-cache": "^1.1.2",
8
+ "@modelcontextprotocol/sdk": "^1.20.2",
8
9
  "@sindresorhus/is": "^7.0.1",
9
10
  "archiver": "^7.0.1",
10
11
  "commander": "^14.0.1",
@@ -24,7 +25,8 @@
24
25
  "subsume": "^4.0.0",
25
26
  "to-readable-stream": "^4.0.0",
26
27
  "unzipper": "^0.12.3",
27
- "yoctocolors": "^2.1.2"
28
+ "yoctocolors": "^2.1.2",
29
+ "zod": "^3.25.76"
28
30
  },
29
31
  "type": "module",
30
32
  "scripts": {
@@ -32,7 +34,7 @@
32
34
  },
33
35
  "name": "@mcpher/gas-fakes",
34
36
  "author": "bruce mcpherson",
35
- "version": "1.2.8",
37
+ "version": "1.2.9",
36
38
  "license": "MIT",
37
39
  "main": "main.js",
38
40
  "description": "A proof of concept implementation of Apps Script Environment on Node",