Initial commit: marketplace structure with connectors.json and index.html

This commit is contained in:
2026-07-16 18:49:01 +01:00
commit dedd09d7c7
13 changed files with 1872 additions and 0 deletions
+57
View File
@@ -0,0 +1,57 @@
{
"id": "gmail",
"name": "Gmail",
"version": "1.0.0",
"type": "mcp_local",
"launch_command": "python3 gmail_mcp_server.py",
"transport": "stdio",
"requires": [
"OAUTH",
"PYTHON"
],
"dependencies": [
"google-api-python-client>=2.150.0",
"google-auth>=2.35.0",
"google-auth-oauthlib>=1.2.0"
],
"setup_instructions": [
"Install dependencies: pip install -r requirements.txt",
"Create secrets/google_oauth_client.json with {\"client_id\": \"...\", \"client_secret\": \"...\"}",
"Run: python3 gmail_oauth_setup.py (opens browser for OAuth)",
"Set GMAIL_CREDS_PATH env var or place token at secrets/gmail_creds.json"
],
"docs": [
{
"lang": "en",
"description": "Full Gmail integration: read, send, modify, and manage emails with OAuth2 authentication. Supports push notifications via history polling.",
"llm_short_description": "Gmail MCP server: read, send, modify, and manage Gmail messages. Requires OAuth setup with Google Cloud Console. Tools: list_messages, get_message, get_thread, send_message, modify_message, list_labels, create_label, get_profile, download_attachments."
}
],
"mcp_config": {
"command": "python3",
"args": [
"gmail_mcp_server.py"
],
"env": {
"GMAIL_CREDS_PATH": "{secrets}/gmail_creds.json"
}
},
"homepage": "https://mail.google.com",
"icon_small": "icon_sm.svg",
"icon_large": "icon_lg.svg",
"scope": "user",
"tags": [
"email",
"mcp",
"local",
"google"
],
"auth": {
"type": "oauth2",
"provider": "google",
"scopes": [
"https://www.googleapis.com/auth/gmail.modify",
"https://www.googleapis.com/auth/gmail.labels"
]
}
}
File diff suppressed because it is too large Load Diff
+108
View File
@@ -0,0 +1,108 @@
#!/usr/bin/env python3
"""Generate a Google OAuth token for Gmail API.
This script runs a local OAuth flow that:
1. Opens your browser automatically to the Google authorization page
2. Handles the callback via a local HTTP server
3. Saves the resulting token to ./secrets/gmail_creds.json
No manual copy-paste required.
"""
from __future__ import annotations
import json
import os
import sys
SCOPES = [
"https://www.googleapis.com/auth/gmail.modify",
"https://www.googleapis.com/auth/gmail.labels",
]
_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
SECRET_PATH = os.path.join(_ROOT, "secrets", "gmail_creds.json")
_OAUTH_CLIENT_PATH = os.path.join(_ROOT, "secrets", "google_oauth_client.json")
def _load_oauth_client() -> tuple[str, str]:
if not os.path.exists(_OAUTH_CLIENT_PATH):
print(f"Missing OAuth client file: {_OAUTH_CLIENT_PATH}")
print("Create it with: {\"client_id\": \"...\", \"client_secret\": \"...\"}")
sys.exit(1)
with open(_OAUTH_CLIENT_PATH) as f:
data = json.load(f)
return data["client_id"], data["client_secret"]
def main() -> None:
# Lazy-import so we can show helpful errors if not installed.
try:
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
except ImportError as e:
print(f"Missing dependencies: {e}")
print("Install with: pip3 install google-auth google-auth-oauthlib google-api-python-client")
sys.exit(1)
creds = None
# Try to load existing credentials first, in case they have refresh token.
if os.path.exists(SECRET_PATH):
print(f"Existing credentials found at {SECRET_PATH}")
try:
creds = Credentials.from_authorized_user_file(SECRET_PATH, SCOPES)
except Exception:
creds = None
# If creds exist and are valid, we're good.
if creds and creds.valid:
print("Credentials are already valid!")
return
# If creds exist but expired, try to refresh.
if creds and creds.expired and creds.refresh_token:
print("Token expired. Attempting refresh...")
try:
creds.refresh(Request())
print("Token refreshed successfully!")
except Exception as e:
print(f"Refresh failed: {e}")
creds = None
if not creds or not creds.valid:
client_id, client_secret = _load_oauth_client()
# Start OAuth flow using local server (opens browser automatically).
flow = InstalledAppFlow.from_client_config(
{
"installed": {
"client_id": client_id,
"client_secret": client_secret,
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"redirect_uris": ["http://localhost"],
}
},
SCOPES,
)
print("\nOpening browser for Google authorization...")
creds = flow.run_local_server(
port=0, # pick a random available port
open_browser=True,
prompt="consent",
access_type="offline",
)
# Save credentials.
os.makedirs(os.path.dirname(SECRET_PATH), exist_ok=True)
with open(SECRET_PATH, "w") as f:
f.write(creds.to_json())
print(f"\n✅ Gmail OAuth token saved to {SECRET_PATH}")
print(f" Scopes: {creds.scopes}")
if __name__ == "__main__":
main()
+5
View File
@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 96 96">
<rect x="8" y="16" width="80" height="64" rx="6" fill="#EA4335"/>
<polygon points="8,16 48,48 88,16" fill="white" opacity="0.2"/>
<polygon points="8,80 48,48 88,80" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 254 B

+5
View File
@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
<rect x="4" y="8" width="40" height="32" rx="3" fill="#EA4335"/>
<polygon points="4,8 24,24 44,8" fill="white" opacity="0.2"/>
<polygon points="4,40 24,24 44,40" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 251 B

+3
View File
@@ -0,0 +1,3 @@
google-api-python-client>=2.150.0
google-auth>=2.35.0
google-auth-oauthlib>=1.2.0