Skip to main content
Glama
drewgilbert-lab

HG GTM Tools MCP

README.md
# HG GTM Tools MCP

Internal MCP server for HG Insights GTM teams (Sales, CS, Marketing, Product). Powers AI-assisted outreach drafting, account research, customer support lookups, and admin via Claude Desktop.

> **What's MCP?** Model Context Protocol — the standard Claude Desktop uses to call backend tools. This repo implements an MCP server that exposes GTM-specific tools (Salesforce lookups, Pylon issue search, account research, etc.). When a CSM types in Claude Desktop, Claude calls the tools defined here.

## Setup

**Prereqs:** Python 3.11+, `uv` ([install](https://docs.astral.sh/uv/getting-started/installation/)), and the [Railway CLI](https://docs.railway.com/cli) for pulling env values. Don't have Railway access yet? Ask in `#gtm-automation`.

First time using Railway CLI? Run `railway login` to auth via browser before the steps below.

```bash
uv sync                                                                        # install deps
railway link -p 283ad9d5-e8d7-48d9-b380-10f9e5fab860 -e production             # link to hg-gtm-tools / production
railway variable list --kv > .env                                              # pull env values into a local .env
uv run pytest                                                                  # confirm setup works (37 tests, ~2s, no network)
uv run python -m src                                                           # run the server on http://localhost:8000/mcp
```

`uv run pytest` works on a fresh clone before you've populated `.env` — tests stub Clerk + Supabase + upstream HTTP. Production env vars come into play only when actually running the server (`python -m src`).

**Production:** [`https://hg-gtm-tools-mcp.madkudu.ai/mcp`](https://hg-gtm-tools-mcp.madkudu.ai/mcp). Manifest at [`/tools/manifest`](https://hg-gtm-tools-mcp.madkudu.ai/tools/manifest) (no auth, lists every registered tool). Deploy with `railway up` from the project root — see [DEPLOYMENT.md](docs/DEPLOYMENT.md).

**Smoke-test live after deploy:** `uv run pytest tests/live/ -v` (opens browser for OAuth on first run). Excluded from default pytest run.

## Docs

**Start here (contributor path):**
- **[Adding a tool](docs/adding-a-tool.md)** — end-to-end walkthrough for new tools
- [Testing](docs/testing.md) — fixtures and patterns
- [Tool naming conventions](docs/tool-naming-conventions.md)
- [Contributing](CONTRIBUTING.md) — short reference for the contributor flow

**Reference:**
- [Architecture](docs/ARCHITECTURE.md) — auth flow, async hand-off, layer responsibilities
- [Deployment](docs/DEPLOYMENT.md) — how `railway up` works, sync jobs
- [Development](docs/DEVELOPMENT.md) — research pipeline + API gotchas
- [Super-Ops role](docs/super-ops-role.md) — generic SOQL access
- [Architecture Diagram](docs/architecture-diagram.html) / [MCP App Diagram](docs/mcp-app-diagram.html) (open in browser)

## Tools

**Outreach creation** (ops): `create_outreach_draft`, `update_outreach_draft`, `list_drafts`

**Outreach viewing** (ops, csm, am, manager, marketing): `my_drafts`, `get_draft_detail`, `approve_draft`, `skip_draft`

**Research** (ops, csm, am, manager, marketing): `start_research`, `get_research_result`, `show_account_brief`, `get_account_detail`

**Book of Accounts** (ops, csm, am, manager, marketing): `get_book_of_accounts`, `update_last_outbound`, `clear_last_outbound_override`

**HG Data Catalogs** (ops, csm, am, manager, marketing): `hg_lookup_industry_codes`, `hg_lookup_intent`, `hg_lookup_products`

**HG Spend Categories** (ops, csm, am, manager, marketing): `hg_get_spend_categories`

**TrustRadius incentive budget** (ops, csm, am, manager, marketing): `tr_get_incentive_budget`

**TrustRadius reviews & campaigns** (ops, csm, am, manager): `tr_search_vendors`, `tr_get_review_report`, `tr_get_campaign_report`

**Vitally Success Plans** (ops, csm, am, manager, marketing): `vitally_show_success_plans`, `vitally_create_success_plan`, `vitally_update_success_plan`

**Customer Projects** (ops, csm, am, manager, marketing): `list_customer_projects`

**Contact search** (ops, csm, am, manager, marketing): `search_crm_contacts` (zip + radius proximity)

**Contact lookup** (ops, csm, am, manager): `lookup_contact`

**Pylon** (ops, csm, am, pm, manager, marketing): `pylon_search_accounts`, `pylon_search_issues`, `pylon_get_issue`

**Jira** (ops, csm, am, pm, manager, marketing): `jira_search_tickets`, `jira_get_ticket`

**Weflow** (ops, csm, am, pm, manager, marketing): `weflow_search_recordings`, `weflow_get_transcript`

**Knowledge Base** (ops, csm, am, pm, manager, marketing): `kb_search`, `kb_read`, `kb_flag_gap`

**CSM Stats** (ops, csm, am, manager): `get_csm_book_stats`

**Lookup** (ops, csm, am, manager, marketing): `lookup_account`

**Google Slides** (ops, csm, am, manager, pm, marketing): `google_slides`

**Admin** (ops): `list_users`, `create_user`, `update_user`, `delete_user`

**Salesforce Contact mutations** (ops, csm, am, manager, marketing): `crm_update_contact`, `crm_create_contact`. Data-quality edits with overwrite protection and full audit log.

**Super-Ops Salesforce** (super_ops): `crm_soql_query`, `crm_describe_sobject`, `crm_soql_update`. Generic SOQL read/write + schema describe for trusted operators. Every call audited. See `docs/super-ops-role.md`.

## Project Structure

```
src/
├── server.py            # FastMCP server + Clerk OIDC auth
├── __main__.py          # Uvicorn entry point
├── auth.py              # Current user from JWT claims
├── roles.py             # Role-based tool filtering (VALID_ROLES)
├── usage.py             # @tracked audit-log decorator
├── manifest.py          # /tools.json manifest endpoint for the dashboard
├── db.py                # Supabase CRUD (sync + async variants)
├── storage.py           # Supabase-backed AsyncKeyValue for OAuth state
├── geo.py               # State/country normalization + zip radius
├── product_map.py       # ProductCode → category mapping
├── tools/               # MCP tool handlers (one file per source)
│   ├── _shared.py       # @tool decorator (the contributor entry point)
│   ├── _registry.py     # Auto-discovery: walks this dir at startup
│   └── *.py             # One file per source — see `ls src/tools/`
├── clients/             # Async upstream API clients (one per service)
├── apps/                # MCP app bundles (Vite + vite-plugin-singlefile)
├── research/            # Account research pipeline (orchestrator + agents)
├── kb/                  # Knowledge base sync + read endpoints
└── sync/                # Scheduled sync jobs

tests/
├── conftest.py          # mcp_client, fake_user, mock_audit_log, env stubs
├── fixtures/upstreams.py  # mock_jira, mock_pylon, mock_salesforce, etc.
└── test_*.py            # one file per tool module being tested

docs/
├── adding-a-tool.md     # end-to-end walkthrough for new contributors
├── testing.md           # fixture reference
└── *.md                 # design docs and references
```

The tools/ directory is intentionally flat: one file per upstream source, auto-discovered at startup. Adding a new tool means dropping a file here. See [docs/adding-a-tool.md](docs/adding-a-tool.md).