@mcpher/gas-fakes 2.3.13 → 2.3.15
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/README.md +11 -5
- package/gf_agent/README.md +101 -0
- package/gf_agent/SKILL.md +396 -0
- package/gf_agent/documentation.md +105 -0
- package/gf_agent/gf-agent-contributor/SKILL.md +56 -0
- package/gf_agent/index.md +21 -0
- package/gf_agent/knowledge/00-execution-context.md +4 -0
- package/gf_agent/knowledge/01-drive.md +12 -0
- package/gf_agent/knowledge/02-syntax.md +13 -0
- package/gf_agent/knowledge/03-auth.md +15 -0
- package/gf_agent/knowledge/04-advanced.md +24 -0
- package/gf_agent/knowledge/05-sheets-forms.md +25 -0
- package/gf_agent/knowledge/06-jdbc-cloudsql.md +21 -0
- package/gf_agent/knowledge/07-jdbc-auth-details.md +30 -0
- package/gf_agent/knowledge/08-docs-limitations.md +4 -0
- package/gf_agent/knowledge/09-orchestrator-pattern.md +54 -0
- package/gf_agent/knowledge/10-sandbox-security.md +61 -0
- package/gf_agent/knowledge/11-chart-builder-limitations.md +15 -0
- package/gf_agent/knowledge/12-gmail-eventual-consistency.md +13 -0
- package/gf_agent/knowledge/README.md +16 -0
- package/gf_agent/scripts/SKILL.template.md +65 -0
- package/gf_agent/scripts/builder.js +78 -47
- package/gf_agent/skills/base.md +156 -0
- package/gf_agent/skills/cache.md +20 -0
- package/gf_agent/skills/calendar.md +780 -0
- package/gf_agent/skills/charts.md +127 -0
- package/gf_agent/skills/document.md +6626 -0
- package/gf_agent/skills/drive.md +423 -0
- package/gf_agent/skills/forms.md +4036 -0
- package/gf_agent/skills/gmail.md +576 -0
- package/gf_agent/skills/jdbc.md +3101 -0
- package/gf_agent/skills/lock.md +20 -0
- package/gf_agent/skills/properties.md +19 -0
- package/gf_agent/skills/script.md +50 -0
- package/gf_agent/skills/slides.md +5054 -0
- package/gf_agent/skills/spreadsheet.md +56075 -0
- package/gf_agent/skills/urlfetch.md +28 -0
- package/gf_agent/skills/utilities.md +33 -0
- package/gf_agent/skills/xml.md +270 -0
- package/package.json +1 -1
- package/src/cli/mcp.js +82 -67
- package/src/cli/setup.js +87 -9
- package/src/services/advgmail/fakeadvgmailmessages.js +85 -3
- package/src/services/driveapp/fakedrivemeta.js +1 -1
- package/src/services/gmailapp/fakegmailapp.js +217 -1
- package/src/services/gmailapp/fakegmailattachment.js +5 -0
- package/src/services/gmailapp/fakegmaildraft.js +32 -4
- package/src/services/gmailapp/fakegmaillabel.js +45 -0
- package/src/services/gmailapp/fakegmailmessage.js +212 -9
- package/src/services/gmailapp/fakegmailthread.js +151 -1
- package/src/services/spreadsheetapp/fakeembeddedchartbuilder.js +113 -28
- package/src/support/sxgmail.js +22 -2
- package/docs_discovery.json +0 -4939
- package/drive_tools.js +0 -20
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Service: urlfetch
|
|
2
|
+
|
|
3
|
+
## Class: HTTPResponse
|
|
4
|
+
|
|
5
|
+
Supported Methods:
|
|
6
|
+
- `getAllHeaders()`
|
|
7
|
+
- `getAs(String)`
|
|
8
|
+
- `getBlob()`
|
|
9
|
+
- `getContent()`
|
|
10
|
+
- `getContentText()`
|
|
11
|
+
- `getContentText(String)`
|
|
12
|
+
- `getHeaders()`
|
|
13
|
+
- `getResponseCode()`
|
|
14
|
+
- `fetch(String,Object)`
|
|
15
|
+
- `fetch(String)`
|
|
16
|
+
- `fetchAll(Object)`
|
|
17
|
+
- `getRequest(String,Object)`
|
|
18
|
+
- `getRequest(String)`
|
|
19
|
+
|
|
20
|
+
## Class: UrlFetchApp
|
|
21
|
+
|
|
22
|
+
Supported Methods:
|
|
23
|
+
- `fetch(String,Object)`
|
|
24
|
+
- `fetch(String)`
|
|
25
|
+
- `fetchAll(Object)`
|
|
26
|
+
- `getRequest(String,Object)`
|
|
27
|
+
- `getRequest(String)`
|
|
28
|
+
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Service: utilities
|
|
2
|
+
|
|
3
|
+
## Class: Utilities
|
|
4
|
+
|
|
5
|
+
Supported Methods:
|
|
6
|
+
- `base64Decode(String,Charset)`
|
|
7
|
+
- `base64Decode(String)`
|
|
8
|
+
- `base64DecodeWebSafe(String,Charset)`
|
|
9
|
+
- `base64DecodeWebSafe(String)`
|
|
10
|
+
- `base64Encode(Byte)`
|
|
11
|
+
- `base64Encode(String,Charset)`
|
|
12
|
+
- `base64Encode(String)`
|
|
13
|
+
- `base64EncodeWebSafe(Byte)`
|
|
14
|
+
- `base64EncodeWebSafe(String,Charset)`
|
|
15
|
+
- `base64EncodeWebSafe(String)`
|
|
16
|
+
- `computeHmacSha256Signature(Byte,Byte)`
|
|
17
|
+
- `computeHmacSha256Signature(String,String,Charset)`
|
|
18
|
+
- `computeHmacSha256Signature(String,String)`
|
|
19
|
+
- `getUuid()`
|
|
20
|
+
- `gzip(BlobSource,String)`
|
|
21
|
+
- `gzip(BlobSource)`
|
|
22
|
+
- `newBlob(Byte,String,String)`
|
|
23
|
+
- `newBlob(Byte,String)`
|
|
24
|
+
- `newBlob(Byte)`
|
|
25
|
+
- `newBlob(String,String,String)`
|
|
26
|
+
- `newBlob(String,String)`
|
|
27
|
+
- `newBlob(String)`
|
|
28
|
+
- `sleep(Integer)`
|
|
29
|
+
- `ungzip(BlobSource)`
|
|
30
|
+
- `unzip(BlobSource)`
|
|
31
|
+
- `zip(BlobSource,String)`
|
|
32
|
+
- `zip(BlobSource)`
|
|
33
|
+
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
# Service: xml
|
|
2
|
+
|
|
3
|
+
## Class: Attribute
|
|
4
|
+
|
|
5
|
+
Supported Methods:
|
|
6
|
+
- `getName()`
|
|
7
|
+
- `getNamespace()`
|
|
8
|
+
- `getRootElement()`
|
|
9
|
+
- `getAttribute(String,Namespace)`
|
|
10
|
+
- `getAttribute(String)`
|
|
11
|
+
- `getChild(String,Namespace)`
|
|
12
|
+
- `getChild(String)`
|
|
13
|
+
- `getChildren()`
|
|
14
|
+
- `getChildren(String,Namespace)`
|
|
15
|
+
- `getChildren(String)`
|
|
16
|
+
- `getChildText(String,Namespace)`
|
|
17
|
+
- `getChildText(String)`
|
|
18
|
+
- `getName()`
|
|
19
|
+
- `getNamespace()`
|
|
20
|
+
- `getNamespace(String)`
|
|
21
|
+
- `getQualifiedName()`
|
|
22
|
+
- `getText()`
|
|
23
|
+
- `getValue()`
|
|
24
|
+
- `getName()`
|
|
25
|
+
- `format(Document)`
|
|
26
|
+
- `format(Element)`
|
|
27
|
+
- `getPrefix()`
|
|
28
|
+
- `getURI()`
|
|
29
|
+
- `getText()`
|
|
30
|
+
- `getValue()`
|
|
31
|
+
- `getNamespace(String,String)`
|
|
32
|
+
- `getNamespace(String)`
|
|
33
|
+
- `getPrettyFormat()`
|
|
34
|
+
- `getRawFormat()`
|
|
35
|
+
- `parse(String)`
|
|
36
|
+
|
|
37
|
+
## Class: Cdata
|
|
38
|
+
|
|
39
|
+
Supported Methods:
|
|
40
|
+
- `getRootElement()`
|
|
41
|
+
- `getAttribute(String,Namespace)`
|
|
42
|
+
- `getAttribute(String)`
|
|
43
|
+
- `getChild(String,Namespace)`
|
|
44
|
+
- `getChild(String)`
|
|
45
|
+
- `getChildren()`
|
|
46
|
+
- `getChildren(String,Namespace)`
|
|
47
|
+
- `getChildren(String)`
|
|
48
|
+
- `getChildText(String,Namespace)`
|
|
49
|
+
- `getChildText(String)`
|
|
50
|
+
- `getName()`
|
|
51
|
+
- `getNamespace()`
|
|
52
|
+
- `getNamespace(String)`
|
|
53
|
+
- `getQualifiedName()`
|
|
54
|
+
- `getText()`
|
|
55
|
+
- `getValue()`
|
|
56
|
+
- `getName()`
|
|
57
|
+
- `format(Document)`
|
|
58
|
+
- `format(Element)`
|
|
59
|
+
- `getPrefix()`
|
|
60
|
+
- `getURI()`
|
|
61
|
+
- `getText()`
|
|
62
|
+
- `getValue()`
|
|
63
|
+
- `getNamespace(String,String)`
|
|
64
|
+
- `getNamespace(String)`
|
|
65
|
+
- `getPrettyFormat()`
|
|
66
|
+
- `getRawFormat()`
|
|
67
|
+
- `parse(String)`
|
|
68
|
+
|
|
69
|
+
## Class: Comment
|
|
70
|
+
|
|
71
|
+
Supported Methods:
|
|
72
|
+
- `getRootElement()`
|
|
73
|
+
- `getAttribute(String,Namespace)`
|
|
74
|
+
- `getAttribute(String)`
|
|
75
|
+
- `getChild(String,Namespace)`
|
|
76
|
+
- `getChild(String)`
|
|
77
|
+
- `getChildren()`
|
|
78
|
+
- `getChildren(String,Namespace)`
|
|
79
|
+
- `getChildren(String)`
|
|
80
|
+
- `getChildText(String,Namespace)`
|
|
81
|
+
- `getChildText(String)`
|
|
82
|
+
- `getName()`
|
|
83
|
+
- `getNamespace()`
|
|
84
|
+
- `getNamespace(String)`
|
|
85
|
+
- `getQualifiedName()`
|
|
86
|
+
- `getText()`
|
|
87
|
+
- `getValue()`
|
|
88
|
+
- `getName()`
|
|
89
|
+
- `format(Document)`
|
|
90
|
+
- `format(Element)`
|
|
91
|
+
- `getPrefix()`
|
|
92
|
+
- `getURI()`
|
|
93
|
+
- `getText()`
|
|
94
|
+
- `getValue()`
|
|
95
|
+
- `getNamespace(String,String)`
|
|
96
|
+
- `getNamespace(String)`
|
|
97
|
+
- `getPrettyFormat()`
|
|
98
|
+
- `getRawFormat()`
|
|
99
|
+
- `parse(String)`
|
|
100
|
+
|
|
101
|
+
## Class: DocType
|
|
102
|
+
|
|
103
|
+
Supported Methods:
|
|
104
|
+
- `getRootElement()`
|
|
105
|
+
- `getAttribute(String,Namespace)`
|
|
106
|
+
- `getAttribute(String)`
|
|
107
|
+
- `getChild(String,Namespace)`
|
|
108
|
+
- `getChild(String)`
|
|
109
|
+
- `getChildren()`
|
|
110
|
+
- `getChildren(String,Namespace)`
|
|
111
|
+
- `getChildren(String)`
|
|
112
|
+
- `getChildText(String,Namespace)`
|
|
113
|
+
- `getChildText(String)`
|
|
114
|
+
- `getName()`
|
|
115
|
+
- `getNamespace()`
|
|
116
|
+
- `getNamespace(String)`
|
|
117
|
+
- `getQualifiedName()`
|
|
118
|
+
- `getText()`
|
|
119
|
+
- `getValue()`
|
|
120
|
+
- `getName()`
|
|
121
|
+
- `format(Document)`
|
|
122
|
+
- `format(Element)`
|
|
123
|
+
- `getPrefix()`
|
|
124
|
+
- `getURI()`
|
|
125
|
+
- `getText()`
|
|
126
|
+
- `getValue()`
|
|
127
|
+
- `getNamespace(String,String)`
|
|
128
|
+
- `getNamespace(String)`
|
|
129
|
+
- `getPrettyFormat()`
|
|
130
|
+
- `getRawFormat()`
|
|
131
|
+
- `parse(String)`
|
|
132
|
+
|
|
133
|
+
## Class: Document
|
|
134
|
+
|
|
135
|
+
Supported Methods:
|
|
136
|
+
- `getRootElement()`
|
|
137
|
+
- `getAttribute(String,Namespace)`
|
|
138
|
+
- `getAttribute(String)`
|
|
139
|
+
- `getChild(String,Namespace)`
|
|
140
|
+
- `getChild(String)`
|
|
141
|
+
- `getChildren()`
|
|
142
|
+
- `getChildren(String,Namespace)`
|
|
143
|
+
- `getChildren(String)`
|
|
144
|
+
- `getChildText(String,Namespace)`
|
|
145
|
+
- `getChildText(String)`
|
|
146
|
+
- `getName()`
|
|
147
|
+
- `getNamespace()`
|
|
148
|
+
- `getNamespace(String)`
|
|
149
|
+
- `getQualifiedName()`
|
|
150
|
+
- `getText()`
|
|
151
|
+
- `getValue()`
|
|
152
|
+
- `getName()`
|
|
153
|
+
- `format(Document)`
|
|
154
|
+
- `format(Element)`
|
|
155
|
+
- `getPrefix()`
|
|
156
|
+
- `getURI()`
|
|
157
|
+
- `getText()`
|
|
158
|
+
- `getValue()`
|
|
159
|
+
- `getNamespace(String,String)`
|
|
160
|
+
- `getNamespace(String)`
|
|
161
|
+
- `getPrettyFormat()`
|
|
162
|
+
- `getRawFormat()`
|
|
163
|
+
- `parse(String)`
|
|
164
|
+
|
|
165
|
+
## Class: Element
|
|
166
|
+
|
|
167
|
+
Supported Methods:
|
|
168
|
+
- `getAttribute(String,Namespace)`
|
|
169
|
+
- `getAttribute(String)`
|
|
170
|
+
- `getChild(String,Namespace)`
|
|
171
|
+
- `getChild(String)`
|
|
172
|
+
- `getChildren()`
|
|
173
|
+
- `getChildren(String,Namespace)`
|
|
174
|
+
- `getChildren(String)`
|
|
175
|
+
- `getChildText(String,Namespace)`
|
|
176
|
+
- `getChildText(String)`
|
|
177
|
+
- `getName()`
|
|
178
|
+
- `getNamespace()`
|
|
179
|
+
- `getNamespace(String)`
|
|
180
|
+
- `getQualifiedName()`
|
|
181
|
+
- `getText()`
|
|
182
|
+
- `getValue()`
|
|
183
|
+
- `getName()`
|
|
184
|
+
- `format(Document)`
|
|
185
|
+
- `format(Element)`
|
|
186
|
+
- `getPrefix()`
|
|
187
|
+
- `getURI()`
|
|
188
|
+
- `getText()`
|
|
189
|
+
- `getValue()`
|
|
190
|
+
- `getNamespace(String,String)`
|
|
191
|
+
- `getNamespace(String)`
|
|
192
|
+
- `getPrettyFormat()`
|
|
193
|
+
- `getRawFormat()`
|
|
194
|
+
- `parse(String)`
|
|
195
|
+
|
|
196
|
+
## Class: EntityRef
|
|
197
|
+
|
|
198
|
+
Supported Methods:
|
|
199
|
+
- `getName()`
|
|
200
|
+
- `format(Document)`
|
|
201
|
+
- `format(Element)`
|
|
202
|
+
- `getPrefix()`
|
|
203
|
+
- `getURI()`
|
|
204
|
+
- `getText()`
|
|
205
|
+
- `getValue()`
|
|
206
|
+
- `getNamespace(String,String)`
|
|
207
|
+
- `getNamespace(String)`
|
|
208
|
+
- `getPrettyFormat()`
|
|
209
|
+
- `getRawFormat()`
|
|
210
|
+
- `parse(String)`
|
|
211
|
+
|
|
212
|
+
## Class: Format
|
|
213
|
+
|
|
214
|
+
Supported Methods:
|
|
215
|
+
- `format(Document)`
|
|
216
|
+
- `format(Element)`
|
|
217
|
+
- `getPrefix()`
|
|
218
|
+
- `getURI()`
|
|
219
|
+
- `getText()`
|
|
220
|
+
- `getValue()`
|
|
221
|
+
- `getNamespace(String,String)`
|
|
222
|
+
- `getNamespace(String)`
|
|
223
|
+
- `getPrettyFormat()`
|
|
224
|
+
- `getRawFormat()`
|
|
225
|
+
- `parse(String)`
|
|
226
|
+
|
|
227
|
+
## Class: Namespace
|
|
228
|
+
|
|
229
|
+
Supported Methods:
|
|
230
|
+
- `getPrefix()`
|
|
231
|
+
- `getURI()`
|
|
232
|
+
- `getText()`
|
|
233
|
+
- `getValue()`
|
|
234
|
+
- `getNamespace(String,String)`
|
|
235
|
+
- `getNamespace(String)`
|
|
236
|
+
- `getPrettyFormat()`
|
|
237
|
+
- `getRawFormat()`
|
|
238
|
+
- `parse(String)`
|
|
239
|
+
|
|
240
|
+
## Class: ProcessingInstruction
|
|
241
|
+
|
|
242
|
+
Supported Methods:
|
|
243
|
+
- `getText()`
|
|
244
|
+
- `getValue()`
|
|
245
|
+
- `getNamespace(String,String)`
|
|
246
|
+
- `getNamespace(String)`
|
|
247
|
+
- `getPrettyFormat()`
|
|
248
|
+
- `getRawFormat()`
|
|
249
|
+
- `parse(String)`
|
|
250
|
+
|
|
251
|
+
## Class: Text
|
|
252
|
+
|
|
253
|
+
Supported Methods:
|
|
254
|
+
- `getText()`
|
|
255
|
+
- `getValue()`
|
|
256
|
+
- `getNamespace(String,String)`
|
|
257
|
+
- `getNamespace(String)`
|
|
258
|
+
- `getPrettyFormat()`
|
|
259
|
+
- `getRawFormat()`
|
|
260
|
+
- `parse(String)`
|
|
261
|
+
|
|
262
|
+
## Class: XmlService
|
|
263
|
+
|
|
264
|
+
Supported Methods:
|
|
265
|
+
- `getNamespace(String,String)`
|
|
266
|
+
- `getNamespace(String)`
|
|
267
|
+
- `getPrettyFormat()`
|
|
268
|
+
- `getRawFormat()`
|
|
269
|
+
- `parse(String)`
|
|
270
|
+
|
package/package.json
CHANGED
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
},
|
|
41
41
|
"name": "@mcpher/gas-fakes",
|
|
42
42
|
"author": "bruce mcpherson",
|
|
43
|
-
"version": "2.3.
|
|
43
|
+
"version": "2.3.15",
|
|
44
44
|
"license": "MIT",
|
|
45
45
|
"main": "main.js",
|
|
46
46
|
"description": "An implementation of the Google Workspace Apps Script runtime: Run native App Script Code on Node and Cloud Run",
|
package/src/cli/mcp.js
CHANGED
|
@@ -2,8 +2,15 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
2
2
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { spawn } from "child_process";
|
|
5
|
+
import fs from "fs";
|
|
6
|
+
import os from "os";
|
|
7
|
+
import path from "path";
|
|
8
|
+
import { fileURLToPath } from "url";
|
|
5
9
|
import { MCP_VERSION } from "./utils.js";
|
|
6
10
|
|
|
11
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
12
|
+
const __dirname = path.dirname(__filename);
|
|
13
|
+
|
|
7
14
|
/**
|
|
8
15
|
* Executes a GAS script using the gas-fakes CLI logic.
|
|
9
16
|
*/
|
|
@@ -37,57 +44,11 @@ async function runGasFakes(script) {
|
|
|
37
44
|
});
|
|
38
45
|
}
|
|
39
46
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
name: "document_service",
|
|
48
|
-
description: "Automate Google Docs: Create and edit documents, paragraphs, tables, and styles.",
|
|
49
|
-
example: "const doc = DocumentApp.create('Hello'); doc.getBody().appendParagraph('World');"
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
name: "drive_service",
|
|
53
|
-
description: "Manage Google Drive: Search files, create folders, and handle permissions.",
|
|
54
|
-
example: "const files = DriveApp.getFilesByName('Test'); while(files.hasNext()) console.log(files.next().getName());"
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
name: "gmail_service",
|
|
58
|
-
description: "Automate Gmail: Send emails, search threads, and manage labels.",
|
|
59
|
-
example: "GmailApp.sendEmail('test@example.com', 'Subject', 'Body');"
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
name: "calendar_service",
|
|
63
|
-
description: "Manage Google Calendar: Create events, list calendars, and handle invitations.",
|
|
64
|
-
example: "CalendarApp.getDefaultCalendar().createEvent('Meeting', new Date(), new Date());"
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
name: "slides_service",
|
|
68
|
-
description: "Automate Google Slides: Create and edit presentations, slides, and shapes.",
|
|
69
|
-
example: "const deck = SlidesApp.create('Presentation'); deck.appendSlide().insertShape(SlidesApp.ShapeType.RECTANGLE);"
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
name: "forms_service",
|
|
73
|
-
description: "Automate Google Forms: Create forms, add items, and manage responses.",
|
|
74
|
-
example: "const form = FormApp.create('Survey'); form.addTextItem().setTitle('Name');"
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
name: "jdbc_service",
|
|
78
|
-
description: "Connect to databases via JDBC: Execute SQL queries and manage connections.",
|
|
79
|
-
example: "const conn = Jdbc.getConnection(url, user, pass); const stmt = conn.createStatement();"
|
|
80
|
-
},
|
|
81
|
-
{
|
|
82
|
-
name: "utilities_service",
|
|
83
|
-
description: "General utilities: Formatting, parsing, and base64 encoding/decoding.",
|
|
84
|
-
example: "const base64 = Utilities.base64Encode('hello');"
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
name: "urlfetch_service",
|
|
88
|
-
description: "HTTP Requests: Fetch external resources and APIs via GET/POST.",
|
|
89
|
-
example: "const res = UrlFetchApp.fetch('https://api.example.com'); console.log(res.getContentText());"
|
|
90
|
-
}
|
|
47
|
+
// Available services mapping for the documentation lookup
|
|
48
|
+
const AVAILABLE_SERVICES = [
|
|
49
|
+
"base", "cache", "calendar", "charts", "document", "drive",
|
|
50
|
+
"forms", "gmail", "jdbc", "lock", "properties", "script",
|
|
51
|
+
"slides", "spreadsheet", "urlfetch", "utilities", "xml"
|
|
91
52
|
];
|
|
92
53
|
|
|
93
54
|
export async function startMcpServer() {
|
|
@@ -96,27 +57,81 @@ export async function startMcpServer() {
|
|
|
96
57
|
version: MCP_VERSION,
|
|
97
58
|
});
|
|
98
59
|
|
|
99
|
-
//
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
script: z.string().describe("The Google Apps Script code to execute locally."),
|
|
107
|
-
},
|
|
60
|
+
// Documentation lookup tool
|
|
61
|
+
server.registerTool(
|
|
62
|
+
"lookup_docs",
|
|
63
|
+
{
|
|
64
|
+
description: "Lookup the available Google Apps Script classes and methods supported by gas-fakes for a specific service. You MUST use this tool to read the documentation before writing a script to ensure the methods you plan to use are actually implemented.",
|
|
65
|
+
inputSchema: {
|
|
66
|
+
service: z.enum(AVAILABLE_SERVICES).describe("The Google Apps Script service to look up (e.g., 'spreadsheet', 'drive', 'document')."),
|
|
108
67
|
},
|
|
109
|
-
|
|
110
|
-
|
|
68
|
+
},
|
|
69
|
+
async ({ service }) => {
|
|
70
|
+
try {
|
|
71
|
+
const fileName = `${service.toLowerCase()}.md`;
|
|
72
|
+
|
|
73
|
+
// Define potential paths for the skills documentation
|
|
74
|
+
const potentialPaths = [
|
|
75
|
+
// 1. Local project installation (e.g. from gas-fakes init standalone)
|
|
76
|
+
path.resolve(process.cwd(), "gf_agent", "skills", fileName),
|
|
77
|
+
path.resolve(process.cwd(), "gf_agent_standalone", "gf_agent", "skills", fileName),
|
|
78
|
+
|
|
79
|
+
// 2. Global Gemini CLI skill installation
|
|
80
|
+
path.resolve(os.homedir(), ".gemini", "skills", "gf_agent", "skills", fileName),
|
|
81
|
+
|
|
82
|
+
// 3. Bundled inside the npm package
|
|
83
|
+
path.resolve(__dirname, "../../gf_agent/skills", fileName)
|
|
84
|
+
];
|
|
85
|
+
|
|
86
|
+
let docsPath = null;
|
|
87
|
+
for (const p of potentialPaths) {
|
|
88
|
+
if (fs.existsSync(p)) {
|
|
89
|
+
docsPath = p;
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (!docsPath) {
|
|
95
|
+
// If not found locally, try fetching from the GitHub repository
|
|
96
|
+
const githubRawUrl = `https://raw.githubusercontent.com/brucemcpherson/gas-fakes/main/gf_agent/skills/${fileName}`;
|
|
97
|
+
try {
|
|
98
|
+
const response = await fetch(githubRawUrl);
|
|
99
|
+
if (response.ok) {
|
|
100
|
+
const githubContent = await response.text();
|
|
101
|
+
return {
|
|
102
|
+
content: [{ type: "text", text: githubContent }],
|
|
103
|
+
isError: false,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
} catch (fetchErr) {
|
|
107
|
+
// Silently fail the fetch and fall through to the local error message
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
content: [{ type: "text", text: `Documentation not found for service: ${service}. Checked multiple standard locations and GitHub origin.` }],
|
|
112
|
+
isError: true,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const content = fs.readFileSync(docsPath, "utf-8");
|
|
117
|
+
return {
|
|
118
|
+
content: [{ type: "text", text: content }],
|
|
119
|
+
isError: false,
|
|
120
|
+
};
|
|
121
|
+
} catch (err) {
|
|
122
|
+
return {
|
|
123
|
+
content: [{ type: "text", text: `Failed to read documentation: ${err.message}` }],
|
|
124
|
+
isError: true,
|
|
125
|
+
};
|
|
111
126
|
}
|
|
112
|
-
|
|
113
|
-
|
|
127
|
+
}
|
|
128
|
+
);
|
|
114
129
|
|
|
115
|
-
//
|
|
130
|
+
// Consolidated execution tool
|
|
116
131
|
server.registerTool(
|
|
117
|
-
"
|
|
132
|
+
"run_script",
|
|
118
133
|
{
|
|
119
|
-
description: "
|
|
134
|
+
description: "Executes Google Apps Script code locally using the gas-fakes emulator. You can interact with multiple Workspace services in a single script.",
|
|
120
135
|
inputSchema: {
|
|
121
136
|
script: z.string().describe("The Google Apps Script code to execute locally."),
|
|
122
137
|
},
|
package/src/cli/setup.js
CHANGED
|
@@ -626,20 +626,98 @@ export async function initializeConfiguration(options = {}) {
|
|
|
626
626
|
try {
|
|
627
627
|
// 1. Install or link the agent skill
|
|
628
628
|
let skillCmd;
|
|
629
|
-
const
|
|
630
|
-
const
|
|
629
|
+
const gfAgentSubdir = path.resolve(process.cwd(), "gf_agent", "SKILL.md");
|
|
630
|
+
const gfAgentCurrent = path.resolve(process.cwd(), "SKILL.md");
|
|
631
631
|
|
|
632
|
-
if (
|
|
632
|
+
if (fs.existsSync(gfAgentSubdir)) {
|
|
633
633
|
console.log("Detected local gas-fakes repository. Linking local skill for development...");
|
|
634
|
-
skillCmd = "gemini skills link ./gf_agent";
|
|
634
|
+
skillCmd = "gemini skills link ./gf_agent --consent";
|
|
635
635
|
manualSkillCmd = "1. gemini skills link ./gf_agent";
|
|
636
|
+
execSync(skillCmd, { stdio: ["ignore", "pipe", "ignore"] });
|
|
637
|
+
console.log("Skill linked successfully.");
|
|
638
|
+
} else if (fs.existsSync(gfAgentCurrent) && fs.existsSync(path.resolve(process.cwd(), "index.md"))) {
|
|
639
|
+
console.log("Detected local gf_agent directory. Linking local skill for development...");
|
|
640
|
+
skillCmd = "gemini skills link . --consent";
|
|
641
|
+
manualSkillCmd = "1. gemini skills link .";
|
|
642
|
+
execSync(skillCmd, { stdio: ["ignore", "pipe", "ignore"] });
|
|
643
|
+
console.log("Skill linked successfully.");
|
|
636
644
|
} else {
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
645
|
+
// Not a local clone, check if already installed to avoid overwriting
|
|
646
|
+
let isAlreadyInstalled = false;
|
|
647
|
+
try {
|
|
648
|
+
const existingSkills = execSync("gemini skills list", {
|
|
649
|
+
encoding: "utf8",
|
|
650
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
651
|
+
});
|
|
652
|
+
if (existingSkills.includes("gf_agent")) {
|
|
653
|
+
isAlreadyInstalled = true;
|
|
654
|
+
}
|
|
655
|
+
} catch (err) {
|
|
656
|
+
// Ignore errors checking skills list
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
if (isAlreadyInstalled) {
|
|
660
|
+
console.log("gf_agent skill is already installed. Skipping remote installation.");
|
|
661
|
+
manualSkillCmd = "1. gemini skills update gf_agent (if needed)";
|
|
662
|
+
} else {
|
|
663
|
+
const installChoice = await prompts({
|
|
664
|
+
type: "select",
|
|
665
|
+
name: "method",
|
|
666
|
+
message: "How would you like to install the gf_agent skill?",
|
|
667
|
+
choices: [
|
|
668
|
+
{
|
|
669
|
+
title: "Global (Standard)",
|
|
670
|
+
value: "global",
|
|
671
|
+
description: "Recommended for most users. Installs a read-only copy globally.",
|
|
672
|
+
},
|
|
673
|
+
{
|
|
674
|
+
title: "Local Standalone (Contributor)",
|
|
675
|
+
value: "local",
|
|
676
|
+
description: "Installs a local sparse-clone for skill development and linking.",
|
|
677
|
+
},
|
|
678
|
+
],
|
|
679
|
+
initial: 0,
|
|
680
|
+
});
|
|
681
|
+
|
|
682
|
+
if (installChoice.method === "local") {
|
|
683
|
+
const standaloneDir = "gf_agent_standalone";
|
|
684
|
+
const fullStandalonePath = path.resolve(process.cwd(), standaloneDir);
|
|
685
|
+
console.log(`Setting up local standalone skill environment in "./${standaloneDir}"...`);
|
|
686
|
+
|
|
687
|
+
try {
|
|
688
|
+
if (!fs.existsSync(fullStandalonePath)) {
|
|
689
|
+
fs.mkdirSync(fullStandalonePath, { recursive: true });
|
|
690
|
+
execSync("git init", { cwd: fullStandalonePath, stdio: "ignore" });
|
|
691
|
+
execSync("git remote add origin https://github.com/brucemcpherson/gas-fakes.git", {
|
|
692
|
+
cwd: fullStandalonePath,
|
|
693
|
+
stdio: "ignore",
|
|
694
|
+
});
|
|
695
|
+
execSync("git config core.sparseCheckout true", { cwd: fullStandalonePath, stdio: "ignore" });
|
|
696
|
+
|
|
697
|
+
const sparsePath = path.join(fullStandalonePath, ".git", "info", "sparse-checkout");
|
|
698
|
+
fs.writeFileSync(sparsePath, "gf_agent/*\n");
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
execSync("git pull origin main", { cwd: fullStandalonePath, stdio: "ignore" });
|
|
640
702
|
|
|
641
|
-
|
|
642
|
-
|
|
703
|
+
skillCmd = "gemini skills link ./gf_agent --consent";
|
|
704
|
+
execSync(skillCmd, { cwd: fullStandalonePath, stdio: ["ignore", "pipe", "ignore"] });
|
|
705
|
+
console.log("Skill linked successfully.");
|
|
706
|
+
|
|
707
|
+
manualSkillCmd = `1. cd ${standaloneDir} && gemini skills link ./gf_agent`;
|
|
708
|
+
} catch (gitErr) {
|
|
709
|
+
console.error(`Error during local setup: ${gitErr.message}`);
|
|
710
|
+
throw gitErr;
|
|
711
|
+
}
|
|
712
|
+
} else {
|
|
713
|
+
skillCmd = "gemini skills install https://github.com/brucemcpherson/gas-fakes.git --path gf_agent --consent";
|
|
714
|
+
manualSkillCmd = "1. gemini skills install https://github.com/brucemcpherson/gas-fakes.git --path gf_agent";
|
|
715
|
+
console.log(`Installing global skill from remote...`);
|
|
716
|
+
execSync(skillCmd, { stdio: ["ignore", "pipe", "ignore"] });
|
|
717
|
+
console.log("Skill installed successfully.");
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
}
|
|
643
721
|
|
|
644
722
|
// 2. Add the MCP server
|
|
645
723
|
const mcpCmd = "gemini mcp add --scope project gas-fakes-mcp gas-fakes mcp";
|