iflow-mcp-hellotinah-mcp 1.0.0__py3-none-any.whl
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.
- 2880_process.log +2 -0
- PKG-INFO +117 -0
- README.md +106 -0
- claude_desktop_config.json +14 -0
- credentials.json +1 -0
- gsheets_server.py +392 -0
- iflow_mcp_hellotinah_mcp-1.0.0.dist-info/METADATA +117 -0
- iflow_mcp_hellotinah_mcp-1.0.0.dist-info/RECORD +15 -0
- iflow_mcp_hellotinah_mcp-1.0.0.dist-info/WHEEL +4 -0
- iflow_mcp_hellotinah_mcp-1.0.0.dist-info/entry_points.txt +2 -0
- language.json +1 -0
- package_name +1 -0
- push_info.json +5 -0
- pyproject.toml +22 -0
- requirements.txt +4 -0
2880_process.log
ADDED
PKG-INFO
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: iflow-mcp-hellotinah-mcp
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A simple MCP server that provides tools, resources, and prompts for working with Google Sheets and Google Forms
|
|
5
|
+
Requires-Python: >=3.8
|
|
6
|
+
Requires-Dist: fastmcp>=0.1.0
|
|
7
|
+
Requires-Dist: google-api-python-client>=2.0.0
|
|
8
|
+
Requires-Dist: google-auth-httplib2>=0.1.0
|
|
9
|
+
Requires-Dist: google-auth-oauthlib>=1.0.0
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
|
|
12
|
+
# Google Sheets & Forms MCP Server
|
|
13
|
+
|
|
14
|
+
A simple MCP server that provides tools, resources, and prompts for working with Google Sheets and Google Forms.
|
|
15
|
+
|
|
16
|
+
## Features
|
|
17
|
+
|
|
18
|
+
### Tools
|
|
19
|
+
- `list_spreadsheets` - List your Google Spreadsheets
|
|
20
|
+
- `read_sheet` - Read data from a Google Sheet
|
|
21
|
+
- `write_sheet` - Write data to a Google Sheet
|
|
22
|
+
- `append_sheet` - Append data to a Google Sheet
|
|
23
|
+
- `create_spreadsheet` - Create a new spreadsheet
|
|
24
|
+
- `create_form` - Create a new Google Form
|
|
25
|
+
|
|
26
|
+
### Resources
|
|
27
|
+
- `sheet://{spreadsheet_id}/{range_name}` - Access sheet data as a resource
|
|
28
|
+
|
|
29
|
+
### Prompts
|
|
30
|
+
- `analyze_sheet_data` - Template for analyzing sheet data
|
|
31
|
+
- `create_report_template` - Template for creating report spreadsheets
|
|
32
|
+
- `form_to_sheet` - Template for form-to-sheet workflow
|
|
33
|
+
|
|
34
|
+
## Setup
|
|
35
|
+
|
|
36
|
+
### 1. Create virtual environment
|
|
37
|
+
```bash
|
|
38
|
+
cd gsheets-mcp-server
|
|
39
|
+
python -m venv .venv
|
|
40
|
+
source .venv/bin/activate # On Windows: .venv\Scripts\activate
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### 2. Install dependencies
|
|
44
|
+
```bash
|
|
45
|
+
pip install -r requirements.txt
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### 3. Get Google API Credentials
|
|
49
|
+
|
|
50
|
+
1. Go to [Google Cloud Console](https://console.cloud.google.com/)
|
|
51
|
+
2. Create a new project or select existing one
|
|
52
|
+
3. Enable the following APIs:
|
|
53
|
+
- Google Sheets API
|
|
54
|
+
- Google Forms API
|
|
55
|
+
- Google Drive API
|
|
56
|
+
4. Go to "Credentials" → "Create Credentials" → "OAuth client ID"
|
|
57
|
+
5. Choose "Desktop app" as application type
|
|
58
|
+
6. Download the credentials JSON file
|
|
59
|
+
7. Save it as `credentials.json` in this directory
|
|
60
|
+
|
|
61
|
+
### 4. Test the server with MCP Inspector
|
|
62
|
+
```bash
|
|
63
|
+
npx @modelcontextprotocol/inspector python gsheets_server.py
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Claude Desktop Configuration
|
|
67
|
+
|
|
68
|
+
Add this to your Claude Desktop config file:
|
|
69
|
+
|
|
70
|
+
**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
71
|
+
**Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
72
|
+
|
|
73
|
+
```json
|
|
74
|
+
{
|
|
75
|
+
"mcpServers": {
|
|
76
|
+
"gsheets": {
|
|
77
|
+
"command": "python",
|
|
78
|
+
"args": [
|
|
79
|
+
"/FULL/PATH/TO/gsheets-mcp-server/gsheets_server.py"
|
|
80
|
+
],
|
|
81
|
+
"env": {
|
|
82
|
+
"GOOGLE_CREDENTIALS_PATH": "/FULL/PATH/TO/gsheets-mcp-server/credentials.json"
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Important**: Replace `/FULL/PATH/TO/` with the actual absolute path to this directory.
|
|
90
|
+
|
|
91
|
+
## First Run
|
|
92
|
+
|
|
93
|
+
On first run, the server will open a browser window for Google authentication. After you authorize the app, a `token.pickle` file will be created to store your credentials for future use.
|
|
94
|
+
|
|
95
|
+
## Example Usage in Claude Desktop
|
|
96
|
+
|
|
97
|
+
Once configured, you can ask Claude:
|
|
98
|
+
|
|
99
|
+
- "List my spreadsheets"
|
|
100
|
+
- "Read the data from spreadsheet ID 'abc123' in range 'Sheet1!A1:C10'"
|
|
101
|
+
- "Create a new spreadsheet called 'Q1 Report'"
|
|
102
|
+
- "Append this data to my sheet: [['Name', 'Email'], ['John', 'john@example.com']]"
|
|
103
|
+
- "Use the analyze_sheet_data prompt"
|
|
104
|
+
- "Show me the sheet resource for spreadsheet 'abc123'"
|
|
105
|
+
|
|
106
|
+
## Getting Spreadsheet IDs
|
|
107
|
+
|
|
108
|
+
The spreadsheet ID is in the URL:
|
|
109
|
+
```
|
|
110
|
+
https://docs.google.com/spreadsheets/d/SPREADSHEET_ID_HERE/edit
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Troubleshooting
|
|
114
|
+
|
|
115
|
+
- **Authentication fails**: Delete `token.pickle` and run again
|
|
116
|
+
- **Permission denied**: Check that you've enabled the APIs in Google Cloud Console
|
|
117
|
+
- **Module not found**: Make sure virtual environment is activated and dependencies are installed
|
README.md
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# Google Sheets & Forms MCP Server
|
|
2
|
+
|
|
3
|
+
A simple MCP server that provides tools, resources, and prompts for working with Google Sheets and Google Forms.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
### Tools
|
|
8
|
+
- `list_spreadsheets` - List your Google Spreadsheets
|
|
9
|
+
- `read_sheet` - Read data from a Google Sheet
|
|
10
|
+
- `write_sheet` - Write data to a Google Sheet
|
|
11
|
+
- `append_sheet` - Append data to a Google Sheet
|
|
12
|
+
- `create_spreadsheet` - Create a new spreadsheet
|
|
13
|
+
- `create_form` - Create a new Google Form
|
|
14
|
+
|
|
15
|
+
### Resources
|
|
16
|
+
- `sheet://{spreadsheet_id}/{range_name}` - Access sheet data as a resource
|
|
17
|
+
|
|
18
|
+
### Prompts
|
|
19
|
+
- `analyze_sheet_data` - Template for analyzing sheet data
|
|
20
|
+
- `create_report_template` - Template for creating report spreadsheets
|
|
21
|
+
- `form_to_sheet` - Template for form-to-sheet workflow
|
|
22
|
+
|
|
23
|
+
## Setup
|
|
24
|
+
|
|
25
|
+
### 1. Create virtual environment
|
|
26
|
+
```bash
|
|
27
|
+
cd gsheets-mcp-server
|
|
28
|
+
python -m venv .venv
|
|
29
|
+
source .venv/bin/activate # On Windows: .venv\Scripts\activate
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### 2. Install dependencies
|
|
33
|
+
```bash
|
|
34
|
+
pip install -r requirements.txt
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### 3. Get Google API Credentials
|
|
38
|
+
|
|
39
|
+
1. Go to [Google Cloud Console](https://console.cloud.google.com/)
|
|
40
|
+
2. Create a new project or select existing one
|
|
41
|
+
3. Enable the following APIs:
|
|
42
|
+
- Google Sheets API
|
|
43
|
+
- Google Forms API
|
|
44
|
+
- Google Drive API
|
|
45
|
+
4. Go to "Credentials" → "Create Credentials" → "OAuth client ID"
|
|
46
|
+
5. Choose "Desktop app" as application type
|
|
47
|
+
6. Download the credentials JSON file
|
|
48
|
+
7. Save it as `credentials.json` in this directory
|
|
49
|
+
|
|
50
|
+
### 4. Test the server with MCP Inspector
|
|
51
|
+
```bash
|
|
52
|
+
npx @modelcontextprotocol/inspector python gsheets_server.py
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Claude Desktop Configuration
|
|
56
|
+
|
|
57
|
+
Add this to your Claude Desktop config file:
|
|
58
|
+
|
|
59
|
+
**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
60
|
+
**Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"mcpServers": {
|
|
65
|
+
"gsheets": {
|
|
66
|
+
"command": "python",
|
|
67
|
+
"args": [
|
|
68
|
+
"/FULL/PATH/TO/gsheets-mcp-server/gsheets_server.py"
|
|
69
|
+
],
|
|
70
|
+
"env": {
|
|
71
|
+
"GOOGLE_CREDENTIALS_PATH": "/FULL/PATH/TO/gsheets-mcp-server/credentials.json"
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Important**: Replace `/FULL/PATH/TO/` with the actual absolute path to this directory.
|
|
79
|
+
|
|
80
|
+
## First Run
|
|
81
|
+
|
|
82
|
+
On first run, the server will open a browser window for Google authentication. After you authorize the app, a `token.pickle` file will be created to store your credentials for future use.
|
|
83
|
+
|
|
84
|
+
## Example Usage in Claude Desktop
|
|
85
|
+
|
|
86
|
+
Once configured, you can ask Claude:
|
|
87
|
+
|
|
88
|
+
- "List my spreadsheets"
|
|
89
|
+
- "Read the data from spreadsheet ID 'abc123' in range 'Sheet1!A1:C10'"
|
|
90
|
+
- "Create a new spreadsheet called 'Q1 Report'"
|
|
91
|
+
- "Append this data to my sheet: [['Name', 'Email'], ['John', 'john@example.com']]"
|
|
92
|
+
- "Use the analyze_sheet_data prompt"
|
|
93
|
+
- "Show me the sheet resource for spreadsheet 'abc123'"
|
|
94
|
+
|
|
95
|
+
## Getting Spreadsheet IDs
|
|
96
|
+
|
|
97
|
+
The spreadsheet ID is in the URL:
|
|
98
|
+
```
|
|
99
|
+
https://docs.google.com/spreadsheets/d/SPREADSHEET_ID_HERE/edit
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Troubleshooting
|
|
103
|
+
|
|
104
|
+
- **Authentication fails**: Delete `token.pickle` and run again
|
|
105
|
+
- **Permission denied**: Check that you've enabled the APIs in Google Cloud Console
|
|
106
|
+
- **Module not found**: Make sure virtual environment is activated and dependencies are installed
|
credentials.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"installed": {"client_id": "test_client_id", "project_id": "test_project_id", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", "client_secret": "test_client_secret", "redirect_uris": ["urn:ietf:wg:oauth:2.0:oob", "http://localhost"]}}
|
gsheets_server.py
ADDED
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import json
|
|
3
|
+
from typing import Any
|
|
4
|
+
from mcp.server.fastmcp import FastMCP
|
|
5
|
+
from google.oauth2.credentials import Credentials
|
|
6
|
+
from google_auth_oauthlib.flow import InstalledAppFlow
|
|
7
|
+
from google.auth.transport.requests import Request
|
|
8
|
+
from googleapiclient.discovery import build
|
|
9
|
+
import pickle
|
|
10
|
+
|
|
11
|
+
# Scopes for Google Sheets and Forms
|
|
12
|
+
SCOPES = [
|
|
13
|
+
'https://www.googleapis.com/auth/spreadsheets',
|
|
14
|
+
'https://www.googleapis.com/auth/forms.body',
|
|
15
|
+
'https://www.googleapis.com/auth/drive.readonly'
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
# Initialize FastMCP server
|
|
19
|
+
mcp = FastMCP("gsheets")
|
|
20
|
+
|
|
21
|
+
def get_credentials():
|
|
22
|
+
"""Get Google API credentials"""
|
|
23
|
+
creds = None
|
|
24
|
+
|
|
25
|
+
# Get the directory where this script is located
|
|
26
|
+
script_dir = os.path.dirname(os.path.abspath(__file__))
|
|
27
|
+
token_path = os.path.join(script_dir, 'token.pickle')
|
|
28
|
+
|
|
29
|
+
# Token file stores the user's access and refresh tokens
|
|
30
|
+
if os.path.exists(token_path):
|
|
31
|
+
with open(token_path, 'rb') as token:
|
|
32
|
+
creds = pickle.load(token)
|
|
33
|
+
|
|
34
|
+
# If no valid credentials, let user log in
|
|
35
|
+
if not creds or not creds.valid:
|
|
36
|
+
if creds and creds.expired and creds.refresh_token:
|
|
37
|
+
creds.refresh(Request())
|
|
38
|
+
else:
|
|
39
|
+
credentials_path = os.getenv('GOOGLE_CREDENTIALS_PATH', 'credentials.json')
|
|
40
|
+
flow = InstalledAppFlow.from_client_secrets_file(credentials_path, SCOPES)
|
|
41
|
+
creds = flow.run_local_server(port=0)
|
|
42
|
+
|
|
43
|
+
# Save credentials for next run
|
|
44
|
+
with open(token_path, 'wb') as token:
|
|
45
|
+
pickle.dump(creds, token)
|
|
46
|
+
|
|
47
|
+
return creds
|
|
48
|
+
|
|
49
|
+
def get_sheets_service():
|
|
50
|
+
"""Get Google Sheets service"""
|
|
51
|
+
creds = get_credentials()
|
|
52
|
+
return build('sheets', 'v4', credentials=creds)
|
|
53
|
+
|
|
54
|
+
def get_forms_service():
|
|
55
|
+
"""Get Google Forms service"""
|
|
56
|
+
creds = get_credentials()
|
|
57
|
+
return build('forms', 'v1', credentials=creds)
|
|
58
|
+
|
|
59
|
+
def get_drive_service():
|
|
60
|
+
"""Get Google Drive service"""
|
|
61
|
+
creds = get_credentials()
|
|
62
|
+
return build('drive', 'v3', credentials=creds)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@mcp.tool()
|
|
66
|
+
def list_spreadsheets(max_results: int = 20) -> str:
|
|
67
|
+
"""
|
|
68
|
+
List user's Google Spreadsheets
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
max_results: Maximum number of spreadsheets to return (default: 20)
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
JSON string with spreadsheet names, IDs, and URLs
|
|
75
|
+
"""
|
|
76
|
+
service = get_drive_service()
|
|
77
|
+
results = service.files().list(
|
|
78
|
+
q="mimeType='application/vnd.google-apps.spreadsheet'",
|
|
79
|
+
pageSize=max_results,
|
|
80
|
+
fields="files(id, name, webViewLink)"
|
|
81
|
+
).execute()
|
|
82
|
+
|
|
83
|
+
files = results.get('files', [])
|
|
84
|
+
spreadsheets = [{
|
|
85
|
+
'name': f['name'],
|
|
86
|
+
'id': f['id'],
|
|
87
|
+
'url': f['webViewLink']
|
|
88
|
+
} for f in files]
|
|
89
|
+
|
|
90
|
+
return json.dumps(spreadsheets, indent=2)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@mcp.tool()
|
|
94
|
+
def read_sheet(spreadsheet_id: str, range_name: str = "Sheet1") -> str:
|
|
95
|
+
"""
|
|
96
|
+
Read data from a Google Sheet
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
spreadsheet_id: The ID of the spreadsheet (from the URL)
|
|
100
|
+
range_name: The A1 notation of the range to read (default: Sheet1)
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
JSON string with the sheet data
|
|
104
|
+
"""
|
|
105
|
+
service = get_sheets_service()
|
|
106
|
+
result = service.spreadsheets().values().get(
|
|
107
|
+
spreadsheetId=spreadsheet_id,
|
|
108
|
+
range=range_name
|
|
109
|
+
).execute()
|
|
110
|
+
|
|
111
|
+
values = result.get('values', [])
|
|
112
|
+
return json.dumps(values, indent=2)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
@mcp.tool()
|
|
116
|
+
def write_sheet(spreadsheet_id: str, range_name: str, values: list) -> str:
|
|
117
|
+
"""
|
|
118
|
+
Write data to a Google Sheet
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
spreadsheet_id: The ID of the spreadsheet
|
|
122
|
+
range_name: The A1 notation of where to write
|
|
123
|
+
values: 2D list of values to write
|
|
124
|
+
|
|
125
|
+
Returns:
|
|
126
|
+
Confirmation message
|
|
127
|
+
"""
|
|
128
|
+
service = get_sheets_service()
|
|
129
|
+
body = {'values': values}
|
|
130
|
+
|
|
131
|
+
result = service.spreadsheets().values().update(
|
|
132
|
+
spreadsheetId=spreadsheet_id,
|
|
133
|
+
range=range_name,
|
|
134
|
+
valueInputOption='RAW',
|
|
135
|
+
body=body
|
|
136
|
+
).execute()
|
|
137
|
+
|
|
138
|
+
return f"Updated {result.get('updatedCells')} cells"
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
@mcp.tool()
|
|
142
|
+
def append_sheet(spreadsheet_id: str, range_name: str, values: list) -> str:
|
|
143
|
+
"""
|
|
144
|
+
Append data to a Google Sheet
|
|
145
|
+
|
|
146
|
+
Args:
|
|
147
|
+
spreadsheet_id: The ID of the spreadsheet
|
|
148
|
+
range_name: The A1 notation of the range
|
|
149
|
+
values: 2D list of values to append
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
Confirmation message
|
|
153
|
+
"""
|
|
154
|
+
service = get_sheets_service()
|
|
155
|
+
body = {'values': values}
|
|
156
|
+
|
|
157
|
+
result = service.spreadsheets().values().append(
|
|
158
|
+
spreadsheetId=spreadsheet_id,
|
|
159
|
+
range=range_name,
|
|
160
|
+
valueInputOption='RAW',
|
|
161
|
+
body=body
|
|
162
|
+
).execute()
|
|
163
|
+
|
|
164
|
+
return f"Appended {result.get('updates').get('updatedCells')} cells"
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
@mcp.tool()
|
|
168
|
+
def create_spreadsheet(title: str) -> str:
|
|
169
|
+
"""
|
|
170
|
+
Create a new Google Spreadsheet
|
|
171
|
+
|
|
172
|
+
Args:
|
|
173
|
+
title: The title of the new spreadsheet
|
|
174
|
+
|
|
175
|
+
Returns:
|
|
176
|
+
JSON with spreadsheet ID and URL
|
|
177
|
+
"""
|
|
178
|
+
service = get_sheets_service()
|
|
179
|
+
spreadsheet = {
|
|
180
|
+
'properties': {
|
|
181
|
+
'title': title
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
result = service.spreadsheets().create(body=spreadsheet).execute()
|
|
186
|
+
|
|
187
|
+
return json.dumps({
|
|
188
|
+
'spreadsheet_id': result.get('spreadsheetId'),
|
|
189
|
+
'url': result.get('spreadsheetUrl')
|
|
190
|
+
}, indent=2)
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
@mcp.tool()
|
|
194
|
+
def create_form(title: str, description: str = "") -> str:
|
|
195
|
+
"""
|
|
196
|
+
Create a new Google Form
|
|
197
|
+
|
|
198
|
+
Args:
|
|
199
|
+
title: The title of the form
|
|
200
|
+
description: Optional description for the form
|
|
201
|
+
|
|
202
|
+
Returns:
|
|
203
|
+
JSON with form ID and URL
|
|
204
|
+
"""
|
|
205
|
+
service = get_forms_service()
|
|
206
|
+
form = {
|
|
207
|
+
'info': {
|
|
208
|
+
'title': title,
|
|
209
|
+
'documentTitle': title
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if description:
|
|
214
|
+
form['info']['description'] = description
|
|
215
|
+
|
|
216
|
+
result = service.forms().create(body=form).execute()
|
|
217
|
+
|
|
218
|
+
return json.dumps({
|
|
219
|
+
'form_id': result.get('formId'),
|
|
220
|
+
'url': result.get('responderUri')
|
|
221
|
+
}, indent=2)
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
# Resources - provide access to sheet data
|
|
225
|
+
@mcp.resource("sheet://{spreadsheet_id}/{range_name}")
|
|
226
|
+
def get_sheet_resource(spreadsheet_id: str, range_name: str = "Sheet1") -> str:
|
|
227
|
+
"""
|
|
228
|
+
Resource for accessing Google Sheet data
|
|
229
|
+
|
|
230
|
+
Args:
|
|
231
|
+
spreadsheet_id: The spreadsheet ID
|
|
232
|
+
range_name: The range to read
|
|
233
|
+
|
|
234
|
+
Returns:
|
|
235
|
+
Sheet data as text
|
|
236
|
+
"""
|
|
237
|
+
service = get_sheets_service()
|
|
238
|
+
result = service.spreadsheets().values().get(
|
|
239
|
+
spreadsheetId=spreadsheet_id,
|
|
240
|
+
range=range_name
|
|
241
|
+
).execute()
|
|
242
|
+
|
|
243
|
+
values = result.get('values', [])
|
|
244
|
+
|
|
245
|
+
# Format as readable text
|
|
246
|
+
output = []
|
|
247
|
+
for row in values:
|
|
248
|
+
output.append(' | '.join(str(cell) for cell in row))
|
|
249
|
+
|
|
250
|
+
return '\n'.join(output)
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
# Prompt templates
|
|
254
|
+
@mcp.prompt()
|
|
255
|
+
def analyze_sheet_data():
|
|
256
|
+
"""Analyze data from a Google Sheet with comprehensive insights"""
|
|
257
|
+
return """I need help analyzing data from a Google Sheet. Please follow this workflow:
|
|
258
|
+
|
|
259
|
+
1. **Data Retrieval & Overview**
|
|
260
|
+
- Ask me for the spreadsheet name and range (or help me list my spreadsheets if needed), unless the user has already retrieved a spreadsheet
|
|
261
|
+
- Read the sheet data using the read_sheet tool
|
|
262
|
+
- Provide a high-level summary:
|
|
263
|
+
* Total number of rows and columns
|
|
264
|
+
* Column headers/names
|
|
265
|
+
* Date range (if applicable)
|
|
266
|
+
* Brief description of what type of data this appears to be
|
|
267
|
+
|
|
268
|
+
2. **Data Structure Analysis**
|
|
269
|
+
- Identify data types in each column (text, numeric, dates, categorical, etc.)
|
|
270
|
+
- Note which columns contain responses vs. metadata
|
|
271
|
+
- Check for missing, empty, or inconsistent values
|
|
272
|
+
- Identify any obvious patterns in data organization
|
|
273
|
+
|
|
274
|
+
3. **Quantitative Analysis** (where applicable)
|
|
275
|
+
- Calculate relevant statistics:
|
|
276
|
+
* For numeric columns: averages, ranges (min/max), totals
|
|
277
|
+
* For categorical data: frequency distributions, most common values
|
|
278
|
+
* For rating scales: score distributions and averages
|
|
279
|
+
- Identify any outliers or unusual values
|
|
280
|
+
|
|
281
|
+
4. **Qualitative Insights** (where applicable)
|
|
282
|
+
- Summarize themes in text responses
|
|
283
|
+
- Identify common keywords or topics
|
|
284
|
+
- Note any particularly interesting or concerning comments
|
|
285
|
+
- Highlight consensus vs. divergent opinions
|
|
286
|
+
|
|
287
|
+
5. **Key Findings & Recommendations**
|
|
288
|
+
- Summarize 3-5 most important insights from the data
|
|
289
|
+
- Flag any data quality issues or anomalies
|
|
290
|
+
- Suggest improvements (data cleaning, additional fields, validation rules)
|
|
291
|
+
- Recommend next steps for analysis or action
|
|
292
|
+
- Propose visualization options that would make the data clearer
|
|
293
|
+
|
|
294
|
+
Please present findings in a clear, scannable format with specific examples and numbers from the actual data."""
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
@mcp.prompt()
|
|
298
|
+
def create_report_template():
|
|
299
|
+
"""Create a professional report document in the canvas"""
|
|
300
|
+
return """Help me create a professional report document with the following structure. Please create this as a well-formatted markdown document in the canvas:
|
|
301
|
+
|
|
302
|
+
1. **Report Header**
|
|
303
|
+
- Report title
|
|
304
|
+
- Company name (Lonely Octopus)
|
|
305
|
+
- Report period/date range
|
|
306
|
+
- Date generated
|
|
307
|
+
|
|
308
|
+
2. **Executive Summary**
|
|
309
|
+
- Brief overview of key findings (2-3 paragraphs)
|
|
310
|
+
- Highlight the most critical insights
|
|
311
|
+
- Bottom-line recommendation or conclusion
|
|
312
|
+
|
|
313
|
+
3. **Key Metrics Dashboard**
|
|
314
|
+
- Create a clean table with columns: Metric | Value | Change | Status
|
|
315
|
+
- Include 5-8 relevant metrics with placeholder values
|
|
316
|
+
- Add brief context notes below the table
|
|
317
|
+
|
|
318
|
+
4. **Detailed Analysis**
|
|
319
|
+
- Break down findings into logical sections
|
|
320
|
+
- Use clear headers for each topic area
|
|
321
|
+
- Include supporting data and evidence
|
|
322
|
+
- Present information in scannable format
|
|
323
|
+
|
|
324
|
+
5. **Findings & Recommendations**
|
|
325
|
+
- **Key Findings**: List 3-5 most important discoveries
|
|
326
|
+
- **Recommendations**: Specific, actionable suggestions
|
|
327
|
+
- **Action Items**: Table with columns for Item, Owner, Due Date, Priority
|
|
328
|
+
|
|
329
|
+
6. **Appendix/Additional Notes**
|
|
330
|
+
- Methodology or data sources (if applicable)
|
|
331
|
+
- Assumptions made
|
|
332
|
+
- Areas for further investigation
|
|
333
|
+
- Additional context or supporting information
|
|
334
|
+
|
|
335
|
+
Please format the report with:
|
|
336
|
+
- Clear hierarchy using markdown headers
|
|
337
|
+
- Professional tables for data presentation
|
|
338
|
+
- Bold text for emphasis on key points
|
|
339
|
+
- Appropriate spacing for readability
|
|
340
|
+
- Placeholder content that can be easily customized"""
|
|
341
|
+
|
|
342
|
+
@mcp.prompt()
|
|
343
|
+
def form_to_sheet():
|
|
344
|
+
"""Create a Google Form and spreadsheet workflow for data collection"""
|
|
345
|
+
return """Help me set up a complete data collection workflow using Google Forms and Sheets:
|
|
346
|
+
|
|
347
|
+
1. **Understand Requirements**
|
|
348
|
+
- Ask me what type of data I want to collect
|
|
349
|
+
- Ask about the purpose (survey, registration, feedback, etc.)
|
|
350
|
+
- Confirm the key fields/questions needed
|
|
351
|
+
|
|
352
|
+
2. **Create Google Form**
|
|
353
|
+
- Use create_form tool with an appropriate title and description
|
|
354
|
+
- Provide the form URL for editing
|
|
355
|
+
- Suggest question types for each field (short answer, multiple choice, etc.)
|
|
356
|
+
|
|
357
|
+
3. **Create Response Spreadsheet**
|
|
358
|
+
- Create a new spreadsheet with create_spreadsheet tool
|
|
359
|
+
- Name it to match the form (e.g., "Form Name - Responses")
|
|
360
|
+
- Set up the first row with column headers matching the form questions
|
|
361
|
+
- Add a "Timestamp" column as the first column
|
|
362
|
+
|
|
363
|
+
4. **Integration Instructions**
|
|
364
|
+
- Provide step-by-step instructions to link the form to the spreadsheet:
|
|
365
|
+
* Open the Form in edit mode
|
|
366
|
+
* Click "Responses" tab
|
|
367
|
+
* Click the green Sheets icon
|
|
368
|
+
* Select "Create a new spreadsheet" or link to existing
|
|
369
|
+
- Note: This step requires manual action in the Google Forms interface
|
|
370
|
+
|
|
371
|
+
5. **Setup Recommendations**
|
|
372
|
+
- Suggest form settings (collect email, limit to 1 response, etc.)
|
|
373
|
+
- Recommend data validation rules
|
|
374
|
+
- Propose notification settings for new responses
|
|
375
|
+
- Suggest basic formulas or formatting for the response sheet
|
|
376
|
+
|
|
377
|
+
6. **Provide Summary**
|
|
378
|
+
- Form URL for editing and sharing
|
|
379
|
+
- Spreadsheet URL for viewing responses
|
|
380
|
+
- Quick reference guide for managing the workflow
|
|
381
|
+
|
|
382
|
+
Please provide all URLs and IDs clearly formatted for easy access."""
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
def main():
|
|
386
|
+
"""Entry point for the MCP server"""
|
|
387
|
+
mcp.run(transport='stdio')
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
if __name__ == "__main__":
|
|
391
|
+
# Run the server with stdio transport
|
|
392
|
+
main()
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: iflow-mcp-hellotinah-mcp
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A simple MCP server that provides tools, resources, and prompts for working with Google Sheets and Google Forms
|
|
5
|
+
Requires-Python: >=3.8
|
|
6
|
+
Requires-Dist: fastmcp>=0.1.0
|
|
7
|
+
Requires-Dist: google-api-python-client>=2.0.0
|
|
8
|
+
Requires-Dist: google-auth-httplib2>=0.1.0
|
|
9
|
+
Requires-Dist: google-auth-oauthlib>=1.0.0
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
|
|
12
|
+
# Google Sheets & Forms MCP Server
|
|
13
|
+
|
|
14
|
+
A simple MCP server that provides tools, resources, and prompts for working with Google Sheets and Google Forms.
|
|
15
|
+
|
|
16
|
+
## Features
|
|
17
|
+
|
|
18
|
+
### Tools
|
|
19
|
+
- `list_spreadsheets` - List your Google Spreadsheets
|
|
20
|
+
- `read_sheet` - Read data from a Google Sheet
|
|
21
|
+
- `write_sheet` - Write data to a Google Sheet
|
|
22
|
+
- `append_sheet` - Append data to a Google Sheet
|
|
23
|
+
- `create_spreadsheet` - Create a new spreadsheet
|
|
24
|
+
- `create_form` - Create a new Google Form
|
|
25
|
+
|
|
26
|
+
### Resources
|
|
27
|
+
- `sheet://{spreadsheet_id}/{range_name}` - Access sheet data as a resource
|
|
28
|
+
|
|
29
|
+
### Prompts
|
|
30
|
+
- `analyze_sheet_data` - Template for analyzing sheet data
|
|
31
|
+
- `create_report_template` - Template for creating report spreadsheets
|
|
32
|
+
- `form_to_sheet` - Template for form-to-sheet workflow
|
|
33
|
+
|
|
34
|
+
## Setup
|
|
35
|
+
|
|
36
|
+
### 1. Create virtual environment
|
|
37
|
+
```bash
|
|
38
|
+
cd gsheets-mcp-server
|
|
39
|
+
python -m venv .venv
|
|
40
|
+
source .venv/bin/activate # On Windows: .venv\Scripts\activate
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### 2. Install dependencies
|
|
44
|
+
```bash
|
|
45
|
+
pip install -r requirements.txt
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### 3. Get Google API Credentials
|
|
49
|
+
|
|
50
|
+
1. Go to [Google Cloud Console](https://console.cloud.google.com/)
|
|
51
|
+
2. Create a new project or select existing one
|
|
52
|
+
3. Enable the following APIs:
|
|
53
|
+
- Google Sheets API
|
|
54
|
+
- Google Forms API
|
|
55
|
+
- Google Drive API
|
|
56
|
+
4. Go to "Credentials" → "Create Credentials" → "OAuth client ID"
|
|
57
|
+
5. Choose "Desktop app" as application type
|
|
58
|
+
6. Download the credentials JSON file
|
|
59
|
+
7. Save it as `credentials.json` in this directory
|
|
60
|
+
|
|
61
|
+
### 4. Test the server with MCP Inspector
|
|
62
|
+
```bash
|
|
63
|
+
npx @modelcontextprotocol/inspector python gsheets_server.py
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Claude Desktop Configuration
|
|
67
|
+
|
|
68
|
+
Add this to your Claude Desktop config file:
|
|
69
|
+
|
|
70
|
+
**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
71
|
+
**Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
72
|
+
|
|
73
|
+
```json
|
|
74
|
+
{
|
|
75
|
+
"mcpServers": {
|
|
76
|
+
"gsheets": {
|
|
77
|
+
"command": "python",
|
|
78
|
+
"args": [
|
|
79
|
+
"/FULL/PATH/TO/gsheets-mcp-server/gsheets_server.py"
|
|
80
|
+
],
|
|
81
|
+
"env": {
|
|
82
|
+
"GOOGLE_CREDENTIALS_PATH": "/FULL/PATH/TO/gsheets-mcp-server/credentials.json"
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Important**: Replace `/FULL/PATH/TO/` with the actual absolute path to this directory.
|
|
90
|
+
|
|
91
|
+
## First Run
|
|
92
|
+
|
|
93
|
+
On first run, the server will open a browser window for Google authentication. After you authorize the app, a `token.pickle` file will be created to store your credentials for future use.
|
|
94
|
+
|
|
95
|
+
## Example Usage in Claude Desktop
|
|
96
|
+
|
|
97
|
+
Once configured, you can ask Claude:
|
|
98
|
+
|
|
99
|
+
- "List my spreadsheets"
|
|
100
|
+
- "Read the data from spreadsheet ID 'abc123' in range 'Sheet1!A1:C10'"
|
|
101
|
+
- "Create a new spreadsheet called 'Q1 Report'"
|
|
102
|
+
- "Append this data to my sheet: [['Name', 'Email'], ['John', 'john@example.com']]"
|
|
103
|
+
- "Use the analyze_sheet_data prompt"
|
|
104
|
+
- "Show me the sheet resource for spreadsheet 'abc123'"
|
|
105
|
+
|
|
106
|
+
## Getting Spreadsheet IDs
|
|
107
|
+
|
|
108
|
+
The spreadsheet ID is in the URL:
|
|
109
|
+
```
|
|
110
|
+
https://docs.google.com/spreadsheets/d/SPREADSHEET_ID_HERE/edit
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Troubleshooting
|
|
114
|
+
|
|
115
|
+
- **Authentication fails**: Delete `token.pickle` and run again
|
|
116
|
+
- **Permission denied**: Check that you've enabled the APIs in Google Cloud Console
|
|
117
|
+
- **Module not found**: Make sure virtual environment is activated and dependencies are installed
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
./2880_process.log,sha256=J9LPkV6NGNyd7FEPiq6yhBEOEgSr9DUu9jQGUgSVjvE,210
|
|
2
|
+
./PKG-INFO,sha256=dh4yPicN9edfR1MFNdaL2kMgQXZAkmrG7OpPCz7vuiU,3566
|
|
3
|
+
./README.md,sha256=L9MMSQU7Ndj_7nGZXnxQyJnUAXk8pSthBmjo8IEkBSg,3150
|
|
4
|
+
./claude_desktop_config.json,sha256=2oN7tS0FSLNkAsZ9iQPGQbtlqLe5P9k-YUyxJ6HbVOo,283
|
|
5
|
+
./credentials.json,sha256=STAaPduV8rPs7noZZu_LAIMyYyDUoaxiLQbI6fGz8SM,372
|
|
6
|
+
./gsheets_server.py,sha256=EbmSPaNrYWKExNHffUqFw0O2-Hl6zSqw6KNqOqJYNYQ,12034
|
|
7
|
+
./language.json,sha256=J-z0poNcsv31IHB413--iOY8LoHBKiTHeybHX3abokI,7
|
|
8
|
+
./package_name,sha256=Ync5LtY4ncZQOTh1Gmt1NaYj3W-6sjHAoYzsxJjEW8k,25
|
|
9
|
+
./push_info.json,sha256=3uI9TpCt9NCyrWvs_iO5qDUUSRDEYa3F9RBrq8k5z6M,118
|
|
10
|
+
./pyproject.toml,sha256=cZRBnN7yC4ZPgg592LC05qsmP8OOIoq_vfq_ebAhZws,563
|
|
11
|
+
./requirements.txt,sha256=HRqvXI873vpfSeqYZnkDkg8huSh4UDgdcl4txfhWg5s,75
|
|
12
|
+
iflow_mcp_hellotinah_mcp-1.0.0.dist-info/METADATA,sha256=dh4yPicN9edfR1MFNdaL2kMgQXZAkmrG7OpPCz7vuiU,3566
|
|
13
|
+
iflow_mcp_hellotinah_mcp-1.0.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
14
|
+
iflow_mcp_hellotinah_mcp-1.0.0.dist-info/entry_points.txt,sha256=ZWvOibywGNR1EporlaIAMA-tfjjiP7OOByMPH1Iw9uw,48
|
|
15
|
+
iflow_mcp_hellotinah_mcp-1.0.0.dist-info/RECORD,,
|
language.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
python
|
package_name
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
iflow-mcp-hellotinah-mcp
|
push_info.json
ADDED
pyproject.toml
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "iflow-mcp-hellotinah-mcp"
|
|
3
|
+
version = "1.0.0"
|
|
4
|
+
description = "A simple MCP server that provides tools, resources, and prompts for working with Google Sheets and Google Forms"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.8"
|
|
7
|
+
dependencies = [
|
|
8
|
+
"fastmcp>=0.1.0",
|
|
9
|
+
"google-auth-oauthlib>=1.0.0",
|
|
10
|
+
"google-auth-httplib2>=0.1.0",
|
|
11
|
+
"google-api-python-client>=2.0.0",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
[project.scripts]
|
|
15
|
+
gsheets = "gsheets_server:main"
|
|
16
|
+
|
|
17
|
+
[build-system]
|
|
18
|
+
requires = ["hatchling"]
|
|
19
|
+
build-backend = "hatchling.build"
|
|
20
|
+
|
|
21
|
+
[tool.hatch.build.targets.wheel]
|
|
22
|
+
packages = ["."]
|
requirements.txt
ADDED