
- Claude connects to Gong sales calls using MCP (Model Context Protocol) so it can read transcripts and extract intelligence automatically.
- Instead of manually reviewing hours of recordings, Claude analyzes yesterday's calls every morning and pulls out customer pain points, competitor mentions, attribution data, and feature requests.
- This is useful for tracking what customers are saying, answering questions like "How many people mentioned MCP last month?", and pulling exact quotes for case studies.
- Built with FastMCP (an open-source framework from Prefect) and Prefect handles the scheduling and orchestration.
Sales calls contain incredibly valuable information that nobody ever extracts.
Customer mentions their current workflow setup isn't quite working for them? That's product intel. They mention they found us through a specific conference talk? That's attribution data. They compare us to a competitor? That's competitive intelligence. Someone asks about a specific feature? That's adoption tracking.
All of this matters, but so many folks don’t capture it systematically.
What actually happens is someone hears something interesting on a call, maybe mentions it in Slack, and then it disappears. Three weeks later when someone asks "Have any customers mentioned FastMCP?" the answer is always some variant of "I think so? Maybe? Let me check..." followed by nobody actually checking.
At Prefect, like many companies, we have hours upon hours of sales calls sitting in Gong. The intelligence was there. We just had no realistic way to extract it.
I built a system that does it automatically. Every morning, Claude reads through yesterday's sales calls, and works way better than any manual process we could have done.And it was all made possible with FastMCP.
What is FastMCP?
FastMCP is a Python framework for building MCP servers. MCP (Model Context Protocol) is Anthropic's protocol for giving Claude access to external data and tools.
Before FastMCP, if you wanted Claude to access your internal systems, you had to:
- Build a custom API endpoint
- Write a bunch of client code for the AI to call it
- Handle authentication, rate limiting, error cases
- Parse responses and feed them back to the AI
- Repeat for every single data source
With FastMCP, you build a server once that exposes your data as "tools." Claude can then discover and call those tools naturally, like it's having a conversation.
Here's what makes this powerful: Claude can decide which tools to use and when. You don't write explicit logic like "fetch call 12345, then analyze it." You just say "analyze yesterday's calls" and Claude figures out it needs to call get_recent_calls, then get_transcript for each result, then do its analysis.
It's genuinely different from traditional APIs.
The Three Pieces
My system has three components that work together. Each is a separate Python script with its own responsibility:
1. The MCP Server (gong_mcp_server.py) This runs as a standalone server on http://127.0.0.1:8000. It connects to Gong's API and exposes two tools that Claude can call: get_recent_calls and get_transcript. This is the bridge between Claude and Gong. It handles authentication, rate limiting, and all the messy API details.
2. The Daily Analysis Flow (daily_gong_attribution_mcp.py) This is a Prefect flow that runs every morning at 7am. It connects to Claude, tells it to analyze yesterday's calls, and Claude uses the MCP server tools to fetch the data it needs. The flow then saves the results, posts to Slack, and updates our master intelligence document. Prefect handles the scheduling, error handling, and orchestration.
3. The Ad-hoc Search Tool (search_mcp_mentions.py) This is a standalone script I run whenever I need to answer a specific question like "How many times was FastMCP mentioned in the last 30 days?" It also connects to Claude and uses the same MCP server, but instead of running automatically, I trigger it on-demand with command-line arguments.
The MCP server is always running in the background. The Prefect flow and search tool are clients that connect to it when they need data from Gong.
Building the MCP Server with FastMCP
FastMCP made this super easy. Here's the core of my Gong MCP server - just the two main tools (the full implementation includes authentication, error handling, and rate limiting):
1from fastmcp import FastMCP
2import httpx
3import base64
4
5mcp = FastMCP("gong-attribution")
6
7@mcp.tool()
8async def get_recent_calls(days: int = 7) -> dict:
9 """Get list of recent Gong calls from the last N days"""
10
11 # Calculate date range
12 end_date = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
13 start_date = end_date - timedelta(days=days)
14
15 # Fetch from Gong API (with pagination)
16 all_calls = []
17 cursor = None
18
19 while True:
20 params = {
21 "fromDateTime": start_date.isoformat() + "Z",
22 "toDateTime": end_date.isoformat() + "Z"
23 }
24 if cursor:
25 params["cursor"] = cursor
26
27 response = await gong_api_call("get", "calls", params=params)
28 calls = response.get('calls', [])
29 all_calls.extend(calls)
30
31 cursor = response.get('records', {}).get('cursor')
32 if not cursor:
33 break
34
35 return {
36 "count": len(all_calls),
37 "calls": [
38 {
39 "id": call['id'],
40 "title": call.get('title', ''),
41 "date": call.get('started', ''),
42 "duration": call.get('duration', 0)
43 }
44 for call in all_calls
45 ]
46 }
47
48@mcp.tool()
49async def get_transcript(call_ids: list[str]) -> dict:
50 """Get full transcript for specific Gong call IDs"""
51
52 response = await gong_api_call(
53 "post",
54 "calls/transcript",
55 json={"filter": {"callIds": call_ids}}
56 )
57
58 transcripts = response.get('callTranscripts', [])
59
60 result = []
61 for transcript in transcripts:
62 speaker_segments = transcript.get('transcript', [])
63 full_text = extract_transcript_text(speaker_segments)
64
65 result.append({
66 "call_id": transcript.get('callId'),
67 "transcript": full_text,
68 "sentence_count": len(speaker_segments)
69 })
70
71 return {"transcripts": result}
72That's the core of it. Claude can now access our sales calls in Gong. The actual server file includes helper functions for authentication, rate limiting (Gong's API is strict about 3 calls/second), and handling Retry-After headers from 429 responses. The MCP tools themselves are just these two functions.
- HTTP server setup
- MCP protocol implementation
- Tool discovery and registration
- Request/response formatting
- Error handling
We just write normal Python functions with the @mcp.tool() decorator and FastMCP makes them available to Claude.
How Claude Uses These Tools
When I run my daily analysis flow, here's what actually happens:
1. I send Claude a high-level instruction:
prompt = f"""
Analyze yesterday's sales calls. For each call:
1prompt = f"""
2Analyze yesterday's sales calls. For each call:
31. Get the transcript
42. Extract pain points, competitor mentions, and buying signals
53. Identify how the customer heard about us
64. Note any FastMCP mentions
7"""
8
9response = client.messages.create(
10 model="claude-sonnet-4-5",
11 tools=[get_recent_calls, get_transcript], # MCP tools
12 messages=[{"role": "user", "content": prompt}]
13)
142. Claude decides to call get_recent_calls:
1{
2
3"type": "tool_use",
4
5"name": "get_recent_calls",
6
7"input": {"days": 1}
8
9}3. We execute the tool and return results:
1{
2
3"count": 6,
4
5"calls": [
6
7{"id": "123456", "title": "Prefect // Company", "date": "2025-11-05"},
8
9{"id": "123457", "title": "Prefect // Company", "date": "2025-11-05"},
10
11...
12
13]
14
15}4. Claude sees the results and decides to get transcripts:
1{
2
3"type": "tool_use",
4
5"name": "get_transcript",
6
7"input": {"call_ids": ["123456", "123457", ...]}
8
9}5. We return the full transcripts and Claude analyzes them:
1{
2
3"transcripts": [
4
5{
6
7"call_id": "123456",
8
9"transcript": "[45 minutes of conversation text]"
10
11},
12
13...
14
15]
16
17}6. Claude synthesizes everything into structured insights.
I never wrote explicit logic saying "first fetch calls, then fetch transcripts, then analyze." Claude figured that out. It's making decisions about which tools to use based on what it needs to accomplish the task.
Why This Is Better Than Traditional Integration
Compare my MCP approach to what you'd typically build:
Traditional REST API approach:
1# You write all this orchestration logic
2
3calls = fetch_calls_from_gong(days=1)
4
5transcripts = []
6
7for call in calls:
8
9transcript = fetch_transcript(call['id'])
10
11transcripts.append(transcript)
12
13# Then you call an LLM with the data
14
15for transcript in transcripts:
16
17analysis = llm.analyze(transcript, prompt="Extract insights...")
18
19save_analysis(analysis)You're doing all the orchestration. The LLM is just a text processor.
MCP approach:
1# You just ask Claude to do the task
2
3response = client.messages.create(
4
5model="claude-sonnet-4-5",
6
7tools=mcp_tools,
8
9messages=[{"role": "user", "content": "Analyze yesterday's calls"}]
10
11)Claude orchestrates itself. It decides:which tools to call → in what order → with what parameters. You get to write at a higher level of abstraction.
This is really powerful when the task gets more complex. Maybe you want to compare this week's calls to last week's. Claude will figure out it needs to fetch two date ranges, analyze both, and compare them.Once you build the right tools, you have the full universe of semantic combinations at your disposal without having to anticipate them. Instead of writing a rigid control flow for every possible query, you define primitive operations (get calls, get transcripts) and Claude composes them into whatever workflow the task requires. New questions don't require new code.
The Ad-hoc Search Tool (MCP's Real Superpower)
The daily analysis flow is cool, but the ad-hoc search tool is where MCP really shines.
Sometimes I need to answer questions like: "How many customers mentioned FastMCP in the last 30 days?" or "What are people saying about our deployment experience?"
With traditional systems, you'd need to:
- Decide what queries you might want to run
- Pre-process and index all your data
- Build query interfaces for each question type
- Hope you guessed the right questions
With MCP, you just ask Claude:
1# Find all MCP mentions in the last 30 days
2
3uv run python search_mcp_mentions.py 30
4
5# Do deep analysis on those calls
6
7uv run python search_mcp_mentions.py 30 --deep-analysisThe search tool doesn't have anything pre-indexed. It just has the MCP server running. When you run it:
- It fetches 30 days of calls using get_recent_calls(30)
- For each call, it fetches the transcript using get_transcript([call_id])
- It searches for MCP mentions using simple keywords
- For deep analysis, it sends each matching transcript to Claude with a prompt asking for structured analysis
The MCP abstraction means we can build these ad-hoc tools trivially. The hard part (accessing Gong) is solved once. Every other tool just uses those same MCP endpoints.
Building Your Own MCP Server
FastMCP makes this stupidly easy. Here's the pattern:
1. Install FastMCP:
1pip install fastmcp2. Create your server:
1from fastmcp import FastMCP
2
3mcp = FastMCP("your-data-source")
4
5@mcp.tool()
6
7async def your_tool(parameters) -> dict:
8
9"""Tool description that Claude will see"""
10
11# Your implementation
12
13return {"result": data}3. Run it:
1python your_mcp_server.py
2
3# Server runs on http://127.0.0.1:80004. Use it with Claude:
1import Anthropic
2
3client = Anthropic(api_key="your-key")
4
5response = client.messages.create(
6
7model="claude-sonnet-4-5",
8
9tools=[your_tool],
10
11messages=[{"role": "user", "content": "Do something with the data"}]
12
13)That's the entire pattern.
You could build an MCP server for:
- Your customer support tickets (Zendesk, Intercom)
- Your CRM data (Salesforce, HubSpot)
- Your analytics (Amplitude, Mixpanel)
- Your code repository (GitHub, GitLab)
- Your documentation (Notion, Confluence)
With FastMCP, each server is super easy to build.
Hosting with FastMCP Cloud
I started by running my MCP server locally. For production, I moved it to FastMCP Cloud so it runs 24/7 without depending on my laptop. The deployment was straightforward, and my Prefect flows just point to the cloud URL instead of localhost.
The Technical Details That Matter
Rate limiting: Gong's API is strict (3 calls/second). My MCP server handles this by:
- Respecting Retry-After headers from 429 responses
- Implementing exponential backoff (60s, 120s, 240s)
- Adding strategic pauses in bulk operations (60s after fetching call lists, 3s between transcripts)
- Using background tasks (part of the MCP spec) to handle long-running operations without blocking other requests
Pagination: Gong's API returns calls in pages. My get_recent_calls tool handles this automatically:
1while True:
2
3response = await fetch_page(cursor)
4
5all_calls.extend(response['calls'])
6
7cursor = response.get('cursor')
8
9if not cursor:
10
11breakTranscript extraction: Gong returns transcripts as structured arrays of speaker segments. I flatten these into plain text that Claude can analyze.
What I Learned Building This
MCP changes how you think about AI integration. You stop thinking "what data should I feed the AI?" and start thinking "what data sources should I connect the AI to?"
FastMCP removes all the boilerplate. I spent a couple hours building the actual MCP server. The rest of the time went into understanding Gong's API quirks and building the analysis flows.
Claude is shockingly good at understanding sales conversations. It can tell the difference between genuine excitement and polite interest. It catches subtle competitive mentions. It extracts quotes with context intact.
The agentic loop is worth it. Letting Claude decide which tools to call (instead of hard-coding the orchestration) makes the system way more flexible. Adding new capabilities is trivial.
HTML reports > everything else. I generate HTML reports that are perfect for sharing with people internally.
Try Building Your Own
The core insight: FastMCP makes it trivial to give Claude superpowers. You write minimal Python with FastMCP, and suddenly Claude can access whatever data you need.
Start with something simple:
- Pick a data source you wish you could query naturally (support tickets, CRM data, whatever)
- Build a FastMCP server with 2-3 basic tools
- Connect Claude to it
- Ask Claude questions and watch it figure out how to use your tools
You'll be shocked how quickly you can build something useful.
The Future of This Pattern
I'm seeing the beginning of a shift in how AI systems are built. Instead of:
- Export data from system A
- Transform it for AI consumption
- Feed it to the AI
- Parse the output
- Load it into system B
You'll just:
- Connect AI to systems A and B via MCP
- Tell the AI what you want
- Let it orchestrate everything
MCP servers become the new API layer. Every company will have MCP servers exposing their internal data to AI assistants. Those AIs will orchestrate themselves across dozens of tools, stitching together information to answer complex questions.
I built this for sales intelligence, but the pattern works for anything. Customer support analysis. Code review automation. Documentation generation. Data pipeline monitoring.
FastMCP makes it so easy that there's no excuse not to try.
To learn more about FastMCP:
- Try FastMCP - it's open source!
- Deploy your MCP servers for free with FastMCP Cloud
To learn more about Prefect
- Visit prefect.io
- Explore Prefect on GitHub to open issues and pull requests
- Follow Prefect on LinkedIn for regular updates
- Join our active Slack community
Related Content








