Small MCP server for Hermes Agent that:
- starts a local FastAPI OAuth flow,
- stores Google OAuth tokens per profile in
google_profiles/, - provides tools to check token status, schedule Google Meet events, and send emails from multiple connected accounts.
- Configure WhatsApp in Hermes:
hermes whatsapp setup- Verify WhatsApp channel is connected:
hermes gateway list- Start Hermes gateway:
hermes gateway runEverything sensitive stays on your machine. The repo ships only code and example config shapes.
git clone https://github.com/Chi-SquareX/hermes-agent.git
cd hermes-agent
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txtcp .env.example .envEdit .env with your Google Cloud OAuth client ID and secret. Keep GOOGLE_REDIRECT_URI aligned with HERMES_PORT (default 8010):
GOOGLE_REDIRECT_URI=http://localhost:8010/auth/callback
HERMES_PORT=8010- Enable Gmail API and Google Calendar API.
- Create an OAuth client (Desktop or Web).
- Add authorized redirect URI:
http://localhost:8010/auth/callback(or whatever port you set).
Start the dashboard (see below), open the login link, and complete OAuth. Tokens are written automatically under google_profiles/ — you do not copy the example token files by hand.
See google_profiles/index.json.example and google_profiles/token.json.example for the on-disk layout after OAuth.
- Install dependencies:
pip install -r requirements.txt - Copy
.env.example→.envand fill in credentials. - Add the matching redirect URI in Google Cloud Console.
Run:
hermes mcp add my-enterprise-server \
--command /ABS/PATH/TO/venv/bin/python \
--args "/ABS/PATH/TO/hermes_oauth_server.py"Example (replace paths with your venv Python and this repo):
hermes mcp add my-enterprise-server \
--command /ABS/PATH/TO/.venv/bin/python \
--args "/ABS/PATH/TO/hermes-agent/hermes_oauth_server.py"Then restart Hermes/gateway so new tools are loaded.
- Open Claude Desktop MCP config file:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
- Add this server entry:
{
"mcpServers": {
"hermes-oauth": {
"command": "/path/to/python/interpreter",
"args": ["/path/to/hermes_oauth_server.py"]
}
}
}- Restart Claude Desktop.
The dashboard port is controlled by HERMES_PORT in .env (default 8010). GOOGLE_REDIRECT_URI must use the same port.
One container, one port, clean restarts:
docker compose up --buildStop and free the port:
docker compose downOpen http://localhost:8010 (or your HERMES_PORT).
google_profiles/, expense_data/, and .env are mounted into the container so tokens and expense data persist on your machine.
If the Hermes MCP server is running, it detects the dashboard on the configured port and will not start a duplicate process.
python scripts/restart_dashboard.pyThis stops anything bound to the configured port and starts uvicorn with reload.
Manual start:
uvicorn app:app --host 127.0.0.1 --port 8010 --reloadMultiple stale Python/uvicorn processes were left running (started by the Hermes MCP auto-launcher without reload). New code was started on alternate ports as a workaround when those old processes could not be fully released on Windows. Use one fixed port via HERMES_PORT in .env, Docker, or scripts/restart_dashboard.py.
Each profile uses a profile_id (for example work, sales-team-1). The first account uses default; additional accounts get an auto-assigned id from the Google email unless you provide a unique profile_id before OAuth.
list_email_profiles(lists all connected Google accounts)start_google_oauth_and_get_login_url(optionalprofile_id)has_access_token(all profiles, or one viaprofile_id/email)schedule_meet(creates Calendar event + Google Meet link)send_email,read_emails,archive_email(optionalprofile_id/email)linkedin_search_people(search LinkedIn people by keywords, with optional title/company/location terms)linkedin_search_companies(search LinkedIn companies by keywords, with optional industry/location terms)linkedin_get_recent_posts(get recent posts from a LinkedIn profile URL)linkedin_like_post(like a specific post URL)linkedin_comment_on_post(comment on a specific post URL)
LinkedIn safety throttles (optional .env settings):
LINKEDIN_MIN_ACTION_GAP_SECONDS(default4.0)LINKEDIN_JITTER_MIN_SECONDS(default0.6)LINKEDIN_JITTER_MAX_SECONDS(default1.8)LINKEDIN_MAX_ACTIONS_PER_MINUTE(default12)LINKEDIN_MAX_MUTATING_ACTIONS_PER_HOUR(default20)LINKEDIN_DETECTION_BACKOFF_SECONDS(default900)
If you have multiple profiles connected, pass profile_id or email to Gmail/Calendar tools so the agent uses the right account.
These paths are gitignored and stay on your machine only:
| Path | Contents |
|---|---|
.env |
Google OAuth client ID and secret |
google_profiles/*.json |
OAuth tokens and profile index (except *.example) |
expense_data/ |
Parsed expense transactions from your email |
google_token.json |
Legacy single-account token (auto-migrated) |
.oauth_state.json |
Short-lived OAuth CSRF state |
- Use
.env.exampleandgoogle_profiles/*.exampleas templates — real values are created locally via OAuth. - Legacy single-account
google_token.jsonfiles are migrated automatically on first use. - Re-run OAuth when scopes change.