mirror of
https://github.com/modelcontextprotocol/servers.git
synced 2026-04-25 23:35:19 +02:00
Merge pull request #7 from modelcontextprotocol/mahesh/update-gdrive
Update README for GDrive
This commit is contained in:
@@ -2,15 +2,37 @@
|
|||||||
|
|
||||||
This MCP server integrates with Google Drive to allow listing, reading, and searching over files.
|
This MCP server integrates with Google Drive to allow listing, reading, and searching over files.
|
||||||
|
|
||||||
|
## Components
|
||||||
|
|
||||||
|
### Tools
|
||||||
|
|
||||||
|
- **search**
|
||||||
|
- Search for files in Google Drive
|
||||||
|
- Input: `query` (string): Search query
|
||||||
|
- Returns file names and MIME types of matching files
|
||||||
|
|
||||||
|
### Resources
|
||||||
|
|
||||||
|
The server provides access to Google Drive files:
|
||||||
|
|
||||||
|
- **Files** (`gdrive:///<file_id>`)
|
||||||
|
- Supports all file types
|
||||||
|
- Google Workspace files are automatically exported:
|
||||||
|
- Docs → Markdown
|
||||||
|
- Sheets → CSV
|
||||||
|
- Presentations → Plain text
|
||||||
|
- Drawings → PNG
|
||||||
|
- Other files are provided in their native format
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
|
|
||||||
1. Create a new Google Cloud project
|
1. [Create a new Google Cloud project](https://console.cloud.google.com/projectcreate)
|
||||||
2. Enable the Google Drive API
|
2. [Enable the Google Drive API](https://console.cloud.google.com/workspace-api/products)
|
||||||
3. Configure an OAuth consent screen ("internal" is fine for testing)
|
3. [Configure an OAuth consent screen](https://console.cloud.google.com/apis/credentials/consent) ("internal" is fine for testing)
|
||||||
4. Add OAuth scope `https://www.googleapis.com/auth/drive.readonly`
|
4. Add OAuth scope `https://www.googleapis.com/auth/drive.readonly`
|
||||||
5. Create an OAuth Client ID for application type "Desktop App"
|
5. [Create an OAuth Client ID](https://console.cloud.google.com/apis/credentials/oauthclient) for application type "Desktop App"
|
||||||
6. Download the JSON file of your client's OAuth keys
|
6. Download the JSON file of your client's OAuth keys
|
||||||
7. Rename the key file to `gcp-oauth.keys.json` and place into the root of this repo
|
7. Rename the key file to `gcp-oauth.keys.json` and place into the root of this repo (i.e. `servers/gcp-oauth.keys.json`)
|
||||||
|
|
||||||
Make sure to build the server with either `npm run build` or `npm run watch`.
|
Make sure to build the server with either `npm run build` or `npm run watch`.
|
||||||
|
|
||||||
@@ -18,16 +40,18 @@ Make sure to build the server with either `npm run build` or `npm run watch`.
|
|||||||
|
|
||||||
To authenticate and save credentials:
|
To authenticate and save credentials:
|
||||||
|
|
||||||
1. Run the server with the `auth` argument: `node build/gdrive auth`
|
1. Run the server with the `auth` argument: `node ./dist auth`
|
||||||
2. This will open an authentication flow in your system browser
|
2. This will open an authentication flow in your system browser
|
||||||
3. Complete the authentication process
|
3. Complete the authentication process
|
||||||
4. Credentials will be saved for future use
|
4. Credentials will be saved in the root of this repo (i.e. `servers/.gdrive-server-credentials.json`)
|
||||||
|
|
||||||
### Running the server
|
### Usage with Desktop App
|
||||||
|
|
||||||
After authenticating:
|
To integrate this server with the desktop app, add the following to your app's server configuration:
|
||||||
|
|
||||||
1. Run the server normally: `node build/gdrive`
|
```json
|
||||||
2. The server will load the saved credentials and start
|
{
|
||||||
|
"mcp-server-gdrive": {
|
||||||
Note: If you haven't authenticated yet, the server will prompt you to run with the `auth` argument first.
|
"command": "mcp-server-gdrive"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -44,7 +44,7 @@ server.setRequestHandler(ListResourcesRequestSchema, async (request) => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
resources: files.map((file) => ({
|
resources: files.map((file) => ({
|
||||||
uri: `gdrive://${file.id}`,
|
uri: `gdrive:///${file.id}`,
|
||||||
mimeType: file.mimeType,
|
mimeType: file.mimeType,
|
||||||
name: file.name,
|
name: file.name,
|
||||||
})),
|
})),
|
||||||
@@ -53,7 +53,7 @@ server.setRequestHandler(ListResourcesRequestSchema, async (request) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
||||||
const fileId = request.params.uri.replace("gdrive://", "");
|
const fileId = request.params.uri.replace("gdrive:///", "");
|
||||||
|
|
||||||
// First get file metadata to check mime type
|
// First get file metadata to check mime type
|
||||||
const file = await drive.files.get({
|
const file = await drive.files.get({
|
||||||
@@ -149,14 +149,16 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|||||||
|
|
||||||
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
||||||
if (request.params.name === "search") {
|
if (request.params.name === "search") {
|
||||||
const query = request.params.arguments?.query as string;
|
const userQuery = request.params.arguments?.query as string;
|
||||||
|
const escapedQuery = userQuery.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
||||||
|
const formattedQuery = `fullText contains '${escapedQuery}'`;
|
||||||
|
|
||||||
const res = await drive.files.list({
|
const res = await drive.files.list({
|
||||||
q: query,
|
q: formattedQuery,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
fields: "files(id, name, mimeType, modifiedTime, size)",
|
fields: "files(id, name, mimeType, modifiedTime, size)",
|
||||||
});
|
});
|
||||||
|
|
||||||
const fileList = res.data.files
|
const fileList = res.data.files
|
||||||
?.map((file: any) => `${file.name} (${file.mimeType})`)
|
?.map((file: any) => `${file.name} (${file.mimeType})`)
|
||||||
.join("\n");
|
.join("\n");
|
||||||
@@ -175,7 +177,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|||||||
|
|
||||||
const credentialsPath = path.join(
|
const credentialsPath = path.join(
|
||||||
path.dirname(new URL(import.meta.url).pathname),
|
path.dirname(new URL(import.meta.url).pathname),
|
||||||
"../../.gdrive-server-credentials.json",
|
"../../../.gdrive-server-credentials.json",
|
||||||
);
|
);
|
||||||
|
|
||||||
async function authenticateAndSaveCredentials() {
|
async function authenticateAndSaveCredentials() {
|
||||||
@@ -183,7 +185,7 @@ async function authenticateAndSaveCredentials() {
|
|||||||
const auth = await authenticate({
|
const auth = await authenticate({
|
||||||
keyfilePath: path.join(
|
keyfilePath: path.join(
|
||||||
path.dirname(new URL(import.meta.url).pathname),
|
path.dirname(new URL(import.meta.url).pathname),
|
||||||
"../../gcp-oauth.keys.json",
|
"../../../gcp-oauth.keys.json",
|
||||||
),
|
),
|
||||||
scopes: ["https://www.googleapis.com/auth/drive.readonly"],
|
scopes: ["https://www.googleapis.com/auth/drive.readonly"],
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user