google-drive-mcp-lib 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.
- package/README.md +357 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +16 -0
- package/dist/cli.js.map +1 -0
- package/dist/client.d.ts +28 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +44 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/handlers.d.ts +14 -0
- package/dist/mcp/handlers.d.ts.map +1 -0
- package/dist/mcp/handlers.js +146 -0
- package/dist/mcp/handlers.js.map +1 -0
- package/dist/mcp/server.d.ts +13 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +87 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools.d.ts +231 -0
- package/dist/mcp/tools.d.ts.map +1 -0
- package/dist/mcp/tools.js +100 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/operations/create-folder.d.ts +14 -0
- package/dist/operations/create-folder.d.ts.map +1 -0
- package/dist/operations/create-folder.js +31 -0
- package/dist/operations/create-folder.js.map +1 -0
- package/dist/operations/delete-file.d.ts +14 -0
- package/dist/operations/delete-file.d.ts.map +1 -0
- package/dist/operations/delete-file.js +13 -0
- package/dist/operations/delete-file.js.map +1 -0
- package/dist/operations/download-file.d.ts +14 -0
- package/dist/operations/download-file.d.ts.map +1 -0
- package/dist/operations/download-file.js +36 -0
- package/dist/operations/download-file.js.map +1 -0
- package/dist/operations/get-file.d.ts +14 -0
- package/dist/operations/get-file.d.ts.map +1 -0
- package/dist/operations/get-file.js +50 -0
- package/dist/operations/get-file.js.map +1 -0
- package/dist/operations/index.d.ts +11 -0
- package/dist/operations/index.d.ts.map +1 -0
- package/dist/operations/index.js +11 -0
- package/dist/operations/index.js.map +1 -0
- package/dist/operations/list-files.d.ts +14 -0
- package/dist/operations/list-files.d.ts.map +1 -0
- package/dist/operations/list-files.js +48 -0
- package/dist/operations/list-files.js.map +1 -0
- package/dist/operations/search-files.d.ts +14 -0
- package/dist/operations/search-files.d.ts.map +1 -0
- package/dist/operations/search-files.js +47 -0
- package/dist/operations/search-files.js.map +1 -0
- package/dist/operations/upload-file.d.ts +14 -0
- package/dist/operations/upload-file.d.ts.map +1 -0
- package/dist/operations/upload-file.js +36 -0
- package/dist/operations/upload-file.js.map +1 -0
- package/dist/tokens.d.ts +31 -0
- package/dist/tokens.d.ts.map +1 -0
- package/dist/tokens.js +77 -0
- package/dist/tokens.js.map +1 -0
- package/dist/types.d.ts +178 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/package.json +64 -0
package/README.md
ADDED
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
# google-drive-mcp-lib
|
|
2
|
+
|
|
3
|
+
A TypeScript npm package providing Google Drive access via the official SDK. This package offers dual mode functionality: a standalone MCP stdio server and a library for easy integration into Node.js/TypeScript projects with typed exported functions.
|
|
4
|
+
|
|
5
|
+
## Summary
|
|
6
|
+
|
|
7
|
+
`google-drive-mcp-lib` enables seamless integration with Google Drive through two modes:
|
|
8
|
+
|
|
9
|
+
1. **Library Mode**: Import typed functions directly into your Node.js/TypeScript project
|
|
10
|
+
2. **MCP Server Mode**: Run as a Model Context Protocol (MCP) stdio server for AI assistants
|
|
11
|
+
|
|
12
|
+
The package handles token resolution with a clear priority system and does not auto-refresh or persist tokens - external systems are responsible for token lifecycle management.
|
|
13
|
+
|
|
14
|
+
## Features
|
|
15
|
+
|
|
16
|
+
- **Dual Mode**: Use as a library or MCP stdio server
|
|
17
|
+
- **TypeScript First**: Full type definitions for all operations
|
|
18
|
+
- **7 Drive Operations**:
|
|
19
|
+
- `listFiles` - List files with pagination and filtering
|
|
20
|
+
- `uploadFile` - Upload files to Drive
|
|
21
|
+
- `getFile` - Get file metadata
|
|
22
|
+
- `downloadFile` - Download file content
|
|
23
|
+
- `createFolder` - Create new folders
|
|
24
|
+
- `searchFiles` - Search files with query strings
|
|
25
|
+
- `deleteFile` - Delete files from Drive
|
|
26
|
+
- **MCP Tools**: All operations available as MCP tools prefixed with `googleDrive`
|
|
27
|
+
- **Flexible Token Resolution**: Multiple ways to provide authentication
|
|
28
|
+
|
|
29
|
+
## Installation
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install google-drive-mcp-lib
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Token Handling
|
|
36
|
+
|
|
37
|
+
Tokens are resolved with the following priority (lowest to highest):
|
|
38
|
+
|
|
39
|
+
1. **JSON File** (`GOOGLE_DRIVE_TOKEN_FILE` or `./token.json`)
|
|
40
|
+
```bash
|
|
41
|
+
export GOOGLE_DRIVE_TOKEN_FILE=/path/to/token.json
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
2. **Environment Variable** (`GOOGLE_DRIVE_TOKEN` as JSON string)
|
|
45
|
+
```bash
|
|
46
|
+
export GOOGLE_DRIVE_TOKEN='{"access_token":"ya29...","refresh_token":"1//..."}'
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
3. **Direct Parameter** (highest priority)
|
|
50
|
+
```typescript
|
|
51
|
+
const files = await listFiles({ tokens: myTokens });
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
> **Important**: The default token file path `./token.json` is resolved relative to the **current working directory** where the process is running, not the project root. For MCP server mode, this is typically the directory from which you run the `npx google-drive-mcp` command. For reliability, use an absolute path via `GOOGLE_DRIVE_TOKEN_FILE` environment variable.
|
|
55
|
+
|
|
56
|
+
### Token Structure
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
interface Tokens {
|
|
60
|
+
access_token: string;
|
|
61
|
+
refresh_token?: string;
|
|
62
|
+
scope?: string;
|
|
63
|
+
token_type?: string;
|
|
64
|
+
expiry_date?: number;
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
> **Note**: This package does not auto-refresh tokens or persist them. External systems are responsible for token rotation and lifecycle management.
|
|
69
|
+
|
|
70
|
+
## Usage
|
|
71
|
+
|
|
72
|
+
### Library Mode
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
import {
|
|
76
|
+
createDriveClient,
|
|
77
|
+
listFiles,
|
|
78
|
+
uploadFile,
|
|
79
|
+
getFile,
|
|
80
|
+
downloadFile,
|
|
81
|
+
createFolder,
|
|
82
|
+
searchFiles,
|
|
83
|
+
deleteFile,
|
|
84
|
+
resolveTokens,
|
|
85
|
+
} from 'google-drive-mcp-lib';
|
|
86
|
+
|
|
87
|
+
// Option 1: Create a client and use it directly
|
|
88
|
+
const drive = createDriveClient({ tokens: myTokens });
|
|
89
|
+
|
|
90
|
+
// Option 2: Use operations directly (tokens resolved automatically)
|
|
91
|
+
const files = await listFiles({ pageSize: 20 });
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
#### List Files
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
const result = await listFiles({
|
|
98
|
+
pageSize: 20,
|
|
99
|
+
orderBy: 'createdTime desc',
|
|
100
|
+
query: "mimeType != 'application/vnd.google-apps.folder'",
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
console.log(result.files);
|
|
104
|
+
// { files: [...], nextPageToken: '...' }
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
#### Upload File
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
import { readFileSync } from 'fs';
|
|
111
|
+
|
|
112
|
+
const content = readFileSync('./document.pdf');
|
|
113
|
+
const result = await uploadFile({
|
|
114
|
+
name: 'document.pdf',
|
|
115
|
+
mimeType: 'application/pdf',
|
|
116
|
+
parents: ['folder-id'],
|
|
117
|
+
body: content,
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
console.log(result.id, result.webViewLink);
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
#### Get File Metadata
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
const file = await getFile({
|
|
127
|
+
fileId: 'file-id',
|
|
128
|
+
fields: ['id', 'name', 'size', 'webViewLink'],
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
console.log(file);
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
#### Download File
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
const result = await downloadFile({
|
|
138
|
+
fileId: 'file-id',
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
console.log(result.name, result.size);
|
|
142
|
+
// result.content is a Buffer
|
|
143
|
+
fs.writeFileSync(result.name, result.content);
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
#### Create Folder
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
const folder = await createFolder({
|
|
150
|
+
name: 'New Folder',
|
|
151
|
+
parents: ['parent-folder-id'],
|
|
152
|
+
description: 'Optional description',
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
console.log(folder.id, folder.webViewLink);
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
#### Search Files
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
const result = await searchFiles({
|
|
162
|
+
query: "name contains 'report' and mimeType = 'application/pdf'",
|
|
163
|
+
pageSize: 10,
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
console.log(result.files);
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
#### Delete File
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
await deleteFile({
|
|
173
|
+
fileId: 'file-id',
|
|
174
|
+
});
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### MCP Server Mode
|
|
178
|
+
|
|
179
|
+
Run as an MCP stdio server:
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
# Using npx
|
|
183
|
+
npx google-drive-mcp-lib
|
|
184
|
+
|
|
185
|
+
# Or with token file
|
|
186
|
+
GOOGLE_DRIVE_TOKEN_FILE=/path/to/token.json npx google-drive-mcp-lib
|
|
187
|
+
|
|
188
|
+
# Or with env var
|
|
189
|
+
GOOGLE_DRIVE_TOKEN='{"access_token":"..."}' npx google-drive-mcp-lib
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
#### Available MCP Tools
|
|
193
|
+
|
|
194
|
+
| Tool Name | Description |
|
|
195
|
+
|-----------|-------------|
|
|
196
|
+
| `googleDriveListFiles` | List files in Google Drive |
|
|
197
|
+
| `googleDriveUploadFile` | Upload a file to Google Drive |
|
|
198
|
+
| `googleDriveGetFile` | Get file metadata |
|
|
199
|
+
| `googleDriveDownloadFile` | Download file content |
|
|
200
|
+
| `googleDriveCreateFolder` | Create a new folder |
|
|
201
|
+
| `googleDriveSearchFiles` | Search files with query |
|
|
202
|
+
| `googleDriveDeleteFile` | Delete a file |
|
|
203
|
+
|
|
204
|
+
## API Reference
|
|
205
|
+
|
|
206
|
+
### Types
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
// Token structure
|
|
210
|
+
export interface Tokens {
|
|
211
|
+
access_token: string;
|
|
212
|
+
refresh_token?: string;
|
|
213
|
+
scope?: string;
|
|
214
|
+
token_type?: string;
|
|
215
|
+
expiry_date?: number;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Client options
|
|
219
|
+
export interface DriveClientOptions {
|
|
220
|
+
tokens?: Tokens;
|
|
221
|
+
clientId?: string;
|
|
222
|
+
clientSecret?: string;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// List files result
|
|
226
|
+
export interface ListFilesResult {
|
|
227
|
+
files: Array<{
|
|
228
|
+
id: string;
|
|
229
|
+
name: string;
|
|
230
|
+
mimeType: string;
|
|
231
|
+
size?: number;
|
|
232
|
+
createdTime?: string;
|
|
233
|
+
modifiedTime?: string;
|
|
234
|
+
parents?: string[];
|
|
235
|
+
webViewLink?: string;
|
|
236
|
+
}>;
|
|
237
|
+
nextPageToken?: string;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Upload file result
|
|
241
|
+
export interface UploadFileResult {
|
|
242
|
+
id: string;
|
|
243
|
+
name: string;
|
|
244
|
+
mimeType: string;
|
|
245
|
+
size?: number;
|
|
246
|
+
webViewLink?: string;
|
|
247
|
+
createdTime?: string;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Download file result
|
|
251
|
+
export interface DownloadFileResult {
|
|
252
|
+
id: string;
|
|
253
|
+
name: string;
|
|
254
|
+
mimeType: string;
|
|
255
|
+
content: Buffer;
|
|
256
|
+
size: number;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Create folder result
|
|
260
|
+
export interface CreateFolderResult {
|
|
261
|
+
id: string;
|
|
262
|
+
name: string;
|
|
263
|
+
mimeType: string;
|
|
264
|
+
parents?: string[];
|
|
265
|
+
webViewLink?: string;
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### Functions
|
|
270
|
+
|
|
271
|
+
#### `createDriveClient(options?: DriveClientOptions)`
|
|
272
|
+
|
|
273
|
+
Create a Google Drive client instance.
|
|
274
|
+
|
|
275
|
+
#### `resolveTokens(provided?: Tokens): Tokens | null`
|
|
276
|
+
|
|
277
|
+
Resolve tokens from available sources.
|
|
278
|
+
|
|
279
|
+
#### `requireTokens(provided?: Tokens): Tokens`
|
|
280
|
+
|
|
281
|
+
Resolve tokens or throw `TokenNotFoundError`.
|
|
282
|
+
|
|
283
|
+
#### `listFiles(options?: ListFilesOperationOptions): Promise<ListFilesResult>`
|
|
284
|
+
|
|
285
|
+
List files in Google Drive.
|
|
286
|
+
|
|
287
|
+
#### `uploadFile(options: UploadFileOperationOptions): Promise<UploadFileResult>`
|
|
288
|
+
|
|
289
|
+
Upload a file to Google Drive.
|
|
290
|
+
|
|
291
|
+
#### `getFile(options: GetFileOperationOptions): Promise<FileMetadata>`
|
|
292
|
+
|
|
293
|
+
Get file metadata.
|
|
294
|
+
|
|
295
|
+
#### `downloadFile(options: DownloadFileOperationOptions): Promise<DownloadFileResult>`
|
|
296
|
+
|
|
297
|
+
Download file content.
|
|
298
|
+
|
|
299
|
+
#### `createFolder(options: CreateFolderOperationOptions): Promise<CreateFolderResult>`
|
|
300
|
+
|
|
301
|
+
Create a new folder.
|
|
302
|
+
|
|
303
|
+
#### `searchFiles(options: SearchFilesOperationOptions): Promise<ListFilesResult>`
|
|
304
|
+
|
|
305
|
+
Search files with query.
|
|
306
|
+
|
|
307
|
+
#### `deleteFile(options: DeleteFileOperationOptions): Promise<boolean>`
|
|
308
|
+
|
|
309
|
+
Delete a file.
|
|
310
|
+
|
|
311
|
+
## Building and Testing
|
|
312
|
+
|
|
313
|
+
### Prerequisites
|
|
314
|
+
|
|
315
|
+
- Node.js 18+
|
|
316
|
+
- npm
|
|
317
|
+
|
|
318
|
+
### Build
|
|
319
|
+
|
|
320
|
+
```bash
|
|
321
|
+
# Install dependencies
|
|
322
|
+
npm install
|
|
323
|
+
|
|
324
|
+
# Build TypeScript
|
|
325
|
+
npm run build
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
### Test
|
|
329
|
+
|
|
330
|
+
```bash
|
|
331
|
+
# Run tests
|
|
332
|
+
npm test
|
|
333
|
+
|
|
334
|
+
# Run tests with coverage
|
|
335
|
+
npm run test:coverage
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### Development
|
|
339
|
+
|
|
340
|
+
```bash
|
|
341
|
+
# Build in watch mode
|
|
342
|
+
tsc --watch
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
## License
|
|
346
|
+
|
|
347
|
+
MIT License
|
|
348
|
+
|
|
349
|
+
## Contributing
|
|
350
|
+
|
|
351
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
352
|
+
|
|
353
|
+
1. Fork the repository
|
|
354
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
355
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
356
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
357
|
+
5. Open a Pull Request
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;GAEG"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* CLI entry point for MCP stdio server
|
|
4
|
+
*/
|
|
5
|
+
import { runMcpServer } from './mcp/server.js';
|
|
6
|
+
async function main() {
|
|
7
|
+
try {
|
|
8
|
+
await runMcpServer();
|
|
9
|
+
}
|
|
10
|
+
catch (error) {
|
|
11
|
+
console.error('Failed to start MCP server:', error);
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
main();
|
|
16
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,MAAM,YAAY,EAAE,CAAC;IACvB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,KAAK,CAAC,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC"}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google Drive client creation
|
|
3
|
+
*/
|
|
4
|
+
import { google } from 'googleapis';
|
|
5
|
+
import { OAuth2Client } from 'google-auth-library';
|
|
6
|
+
import type { DriveClientOptions } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Create a Google Drive client with resolved tokens
|
|
9
|
+
*
|
|
10
|
+
* @param options - Client options including tokens and OAuth client credentials
|
|
11
|
+
* @returns Google Drive API client
|
|
12
|
+
* @throws TokenNotFoundError if no valid tokens found
|
|
13
|
+
*/
|
|
14
|
+
export declare function createDriveClient(options?: DriveClientOptions): import("googleapis").drive_v3.Drive;
|
|
15
|
+
/**
|
|
16
|
+
* Create an OAuth2 client with resolved tokens
|
|
17
|
+
* Useful for custom API calls or advanced use cases
|
|
18
|
+
*
|
|
19
|
+
* @param options - Client options including tokens and OAuth client credentials
|
|
20
|
+
* @returns OAuth2 client configured with tokens
|
|
21
|
+
* @throws TokenNotFoundError if no valid tokens found
|
|
22
|
+
*/
|
|
23
|
+
export declare function createAuthClient(options?: DriveClientOptions): OAuth2Client;
|
|
24
|
+
/**
|
|
25
|
+
* Get the raw googleapis instance for advanced usage
|
|
26
|
+
*/
|
|
27
|
+
export { google };
|
|
28
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,KAAK,EAAU,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAG7D;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,kBAAuB,uCAWjE;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,kBAAuB,GAAG,YAAY,CAU/E;AAED;;GAEG;AACH,OAAO,EAAE,MAAM,EAAE,CAAC"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google Drive client creation
|
|
3
|
+
*/
|
|
4
|
+
import { google } from 'googleapis';
|
|
5
|
+
import { OAuth2Client } from 'google-auth-library';
|
|
6
|
+
import { requireTokens } from './tokens.js';
|
|
7
|
+
/**
|
|
8
|
+
* Create a Google Drive client with resolved tokens
|
|
9
|
+
*
|
|
10
|
+
* @param options - Client options including tokens and OAuth client credentials
|
|
11
|
+
* @returns Google Drive API client
|
|
12
|
+
* @throws TokenNotFoundError if no valid tokens found
|
|
13
|
+
*/
|
|
14
|
+
export function createDriveClient(options = {}) {
|
|
15
|
+
const tokens = requireTokens(options.tokens);
|
|
16
|
+
const auth = new OAuth2Client({
|
|
17
|
+
clientId: options.clientId || process.env.GOOGLE_CLIENT_ID,
|
|
18
|
+
clientSecret: options.clientSecret || process.env.GOOGLE_CLIENT_SECRET,
|
|
19
|
+
});
|
|
20
|
+
auth.setCredentials(tokens);
|
|
21
|
+
return google.drive({ version: 'v3', auth });
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Create an OAuth2 client with resolved tokens
|
|
25
|
+
* Useful for custom API calls or advanced use cases
|
|
26
|
+
*
|
|
27
|
+
* @param options - Client options including tokens and OAuth client credentials
|
|
28
|
+
* @returns OAuth2 client configured with tokens
|
|
29
|
+
* @throws TokenNotFoundError if no valid tokens found
|
|
30
|
+
*/
|
|
31
|
+
export function createAuthClient(options = {}) {
|
|
32
|
+
const tokens = requireTokens(options.tokens);
|
|
33
|
+
const auth = new OAuth2Client({
|
|
34
|
+
clientId: options.clientId || process.env.GOOGLE_CLIENT_ID,
|
|
35
|
+
clientSecret: options.clientSecret || process.env.GOOGLE_CLIENT_SECRET,
|
|
36
|
+
});
|
|
37
|
+
auth.setCredentials(tokens);
|
|
38
|
+
return auth;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Get the raw googleapis instance for advanced usage
|
|
42
|
+
*/
|
|
43
|
+
export { google };
|
|
44
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,UAA8B,EAAE;IAChE,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAE7C,MAAM,IAAI,GAAG,IAAI,YAAY,CAAC;QAC5B,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB;QAC1D,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAoB;KACvE,CAAC,CAAC;IAEH,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;IAE5B,OAAO,MAAM,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;AAC/C,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAAC,UAA8B,EAAE;IAC/D,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAE7C,MAAM,IAAI,GAAG,IAAI,YAAY,CAAC;QAC5B,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB;QAC1D,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAoB;KACvE,CAAC,CAAC;IAEH,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;IAC5B,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,OAAO,EAAE,MAAM,EAAE,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* google-drive-mcp
|
|
3
|
+
*
|
|
4
|
+
* Google Drive MCP server and library for Node.js/TypeScript
|
|
5
|
+
* Dual mode package providing typed functions and MCP stdio server
|
|
6
|
+
*/
|
|
7
|
+
export type { Tokens, DriveClientOptions, FileMetadata, ListFilesOptions, ListFilesResult, UploadFileOptions, UploadFileResult, SearchFilesOptions, CreateFolderOptions, CreateFolderResult, DownloadFileResult, GetFileOptions, OperationOptions, ListFilesOperationOptions, UploadFileOperationOptions, SearchFilesOperationOptions, CreateFolderOperationOptions, GetFileOperationOptions, DownloadFileOperationOptions, DeleteFileOperationOptions, } from './types.js';
|
|
8
|
+
export { resolveTokens, requireTokens, TokenNotFoundError } from './tokens.js';
|
|
9
|
+
export { createDriveClient, createAuthClient, google } from './client.js';
|
|
10
|
+
export { listFiles, uploadFile, getFile, downloadFile, createFolder, searchFiles, deleteFile, } from './operations/index.js';
|
|
11
|
+
export { createMcpServer, runMcpServer } from './mcp/server.js';
|
|
12
|
+
export { toolDefinitions } from './mcp/tools.js';
|
|
13
|
+
export type { ToolName } from './mcp/tools.js';
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,YAAY,EACV,MAAM,EACN,kBAAkB,EAClB,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,EAClB,cAAc,EACd,gBAAgB,EAChB,yBAAyB,EACzB,0BAA0B,EAC1B,2BAA2B,EAC3B,4BAA4B,EAC5B,uBAAuB,EACvB,4BAA4B,EAC5B,0BAA0B,GAC3B,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAG/E,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAG1E,OAAO,EACL,SAAS,EACT,UAAU,EACV,OAAO,EACP,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,UAAU,GACX,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,YAAY,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* google-drive-mcp
|
|
3
|
+
*
|
|
4
|
+
* Google Drive MCP server and library for Node.js/TypeScript
|
|
5
|
+
* Dual mode package providing typed functions and MCP stdio server
|
|
6
|
+
*/
|
|
7
|
+
// Token resolution
|
|
8
|
+
export { resolveTokens, requireTokens, TokenNotFoundError } from './tokens.js';
|
|
9
|
+
// Client creation
|
|
10
|
+
export { createDriveClient, createAuthClient, google } from './client.js';
|
|
11
|
+
// Operations
|
|
12
|
+
export { listFiles, uploadFile, getFile, downloadFile, createFolder, searchFiles, deleteFile, } from './operations/index.js';
|
|
13
|
+
// MCP Server (for programmatic use)
|
|
14
|
+
export { createMcpServer, runMcpServer } from './mcp/server.js';
|
|
15
|
+
export { toolDefinitions } from './mcp/tools.js';
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA0BH,mBAAmB;AACnB,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAE/E,kBAAkB;AAClB,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1E,aAAa;AACb,OAAO,EACL,SAAS,EACT,UAAU,EACV,OAAO,EACP,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,UAAU,GACX,MAAM,uBAAuB,CAAC;AAE/B,oCAAoC;AACpC,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tool handlers
|
|
3
|
+
*/
|
|
4
|
+
import type { CallToolRequest } from '@modelcontextprotocol/sdk/types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Handle MCP tool calls
|
|
7
|
+
*/
|
|
8
|
+
export declare function handleToolCall(request: CallToolRequest): Promise<{
|
|
9
|
+
content: Array<{
|
|
10
|
+
type: string;
|
|
11
|
+
text: string;
|
|
12
|
+
}>;
|
|
13
|
+
}>;
|
|
14
|
+
//# sourceMappingURL=handlers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../../src/mcp/handlers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AA2B1E;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC,CAsI1H"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tool handlers
|
|
3
|
+
*/
|
|
4
|
+
import { listFiles, uploadFile, getFile, downloadFile, createFolder, searchFiles, deleteFile } from '../operations/index.js';
|
|
5
|
+
import { listFilesSchema, uploadFileSchema, getFileSchema, downloadFileSchema, createFolderSchema, searchFilesSchema, deleteFileSchema, } from './tools.js';
|
|
6
|
+
/**
|
|
7
|
+
* Validation error result type
|
|
8
|
+
*/
|
|
9
|
+
function validationError(message) {
|
|
10
|
+
return {
|
|
11
|
+
content: [
|
|
12
|
+
{
|
|
13
|
+
type: 'text',
|
|
14
|
+
text: JSON.stringify({ error: `Validation error: ${message}` }, null, 2),
|
|
15
|
+
},
|
|
16
|
+
],
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Handle MCP tool calls
|
|
21
|
+
*/
|
|
22
|
+
export async function handleToolCall(request) {
|
|
23
|
+
const toolName = request.params.name;
|
|
24
|
+
const args = request.params.arguments ?? {};
|
|
25
|
+
try {
|
|
26
|
+
let result;
|
|
27
|
+
switch (toolName) {
|
|
28
|
+
case 'googleDriveListFiles': {
|
|
29
|
+
const parsed = listFilesSchema.safeParse(args);
|
|
30
|
+
if (!parsed.success) {
|
|
31
|
+
return validationError(parsed.error.message);
|
|
32
|
+
}
|
|
33
|
+
result = await listFiles({
|
|
34
|
+
pageSize: parsed.data.pageSize,
|
|
35
|
+
pageToken: parsed.data.pageToken,
|
|
36
|
+
orderBy: parsed.data.orderBy,
|
|
37
|
+
query: parsed.data.query,
|
|
38
|
+
});
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
case 'googleDriveUploadFile': {
|
|
42
|
+
const parsed = uploadFileSchema.safeParse(args);
|
|
43
|
+
if (!parsed.success) {
|
|
44
|
+
return validationError(parsed.error.message);
|
|
45
|
+
}
|
|
46
|
+
// Decode base64 content to Buffer
|
|
47
|
+
const body = Buffer.from(parsed.data.content, 'base64');
|
|
48
|
+
result = await uploadFile({
|
|
49
|
+
name: parsed.data.name,
|
|
50
|
+
mimeType: parsed.data.mimeType,
|
|
51
|
+
parents: parsed.data.parents,
|
|
52
|
+
body,
|
|
53
|
+
description: parsed.data.description,
|
|
54
|
+
});
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
case 'googleDriveGetFile': {
|
|
58
|
+
const parsed = getFileSchema.safeParse(args);
|
|
59
|
+
if (!parsed.success) {
|
|
60
|
+
return validationError(parsed.error.message);
|
|
61
|
+
}
|
|
62
|
+
result = await getFile({
|
|
63
|
+
fileId: parsed.data.fileId,
|
|
64
|
+
fields: parsed.data.fields,
|
|
65
|
+
});
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
case 'googleDriveDownloadFile': {
|
|
69
|
+
const parsed = downloadFileSchema.safeParse(args);
|
|
70
|
+
if (!parsed.success) {
|
|
71
|
+
return validationError(parsed.error.message);
|
|
72
|
+
}
|
|
73
|
+
const downloadResult = await downloadFile({
|
|
74
|
+
fileId: parsed.data.fileId,
|
|
75
|
+
});
|
|
76
|
+
// Encode content as base64 for MCP response
|
|
77
|
+
result = {
|
|
78
|
+
id: downloadResult.id,
|
|
79
|
+
name: downloadResult.name,
|
|
80
|
+
mimeType: downloadResult.mimeType,
|
|
81
|
+
size: downloadResult.size,
|
|
82
|
+
content: downloadResult.content.toString('base64'),
|
|
83
|
+
};
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
case 'googleDriveCreateFolder': {
|
|
87
|
+
const parsed = createFolderSchema.safeParse(args);
|
|
88
|
+
if (!parsed.success) {
|
|
89
|
+
return validationError(parsed.error.message);
|
|
90
|
+
}
|
|
91
|
+
result = await createFolder({
|
|
92
|
+
name: parsed.data.name,
|
|
93
|
+
parents: parsed.data.parents,
|
|
94
|
+
description: parsed.data.description,
|
|
95
|
+
});
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
case 'googleDriveSearchFiles': {
|
|
99
|
+
const parsed = searchFilesSchema.safeParse(args);
|
|
100
|
+
if (!parsed.success) {
|
|
101
|
+
return validationError(parsed.error.message);
|
|
102
|
+
}
|
|
103
|
+
result = await searchFiles({
|
|
104
|
+
query: parsed.data.query,
|
|
105
|
+
pageSize: parsed.data.pageSize,
|
|
106
|
+
pageToken: parsed.data.pageToken,
|
|
107
|
+
orderBy: parsed.data.orderBy,
|
|
108
|
+
});
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
case 'googleDriveDeleteFile': {
|
|
112
|
+
const parsed = deleteFileSchema.safeParse(args);
|
|
113
|
+
if (!parsed.success) {
|
|
114
|
+
return validationError(parsed.error.message);
|
|
115
|
+
}
|
|
116
|
+
result = await deleteFile({
|
|
117
|
+
fileId: parsed.data.fileId,
|
|
118
|
+
});
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
default:
|
|
122
|
+
throw new Error(`Unknown tool: ${toolName}`);
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
content: [
|
|
126
|
+
{
|
|
127
|
+
type: 'text',
|
|
128
|
+
text: JSON.stringify(result, null, 2),
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
135
|
+
console.error(`Error in tool ${toolName}:`, errorMessage);
|
|
136
|
+
return {
|
|
137
|
+
content: [
|
|
138
|
+
{
|
|
139
|
+
type: 'text',
|
|
140
|
+
text: JSON.stringify({ error: errorMessage }, null, 2),
|
|
141
|
+
},
|
|
142
|
+
],
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=handlers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handlers.js","sourceRoot":"","sources":["../../src/mcp/handlers.ts"],"names":[],"mappings":"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"}
|