{"slug": "mcp-server-benchmark-task-specific-servers-on-google-ads-hubspot-avoma-and", "title": "MCP Server Benchmark: Task-Specific Servers on Google Ads, HubSpot, Avoma and Salesforce", "summary": "Nexla's task-specific MCP servers used 4.7x fewer tokens per task on Google Ads and 32.7x fewer tokens on a HubSpot deal-analysis question than the vendors' own MCP servers, according to a Nexla benchmark that held claude-opus-5, the questions and the data fixed across Google Ads, HubSpot, Avoma and Salesforce. On HubSpot, both servers returned identical results — 199 closed deals, 135 won, 64 lost and a 67.8% win rate — but Nexla's server used 21,682 tokens against 708,973 uncached for HubSpot's 24-tool CRM MCP, which re-sends about 39,000 tokens of tool schema each turn. On Avoma, Nexla's server logged 1 errored tool call over 10 tasks versus 25 for Avoma's own server and scored 0.50 versus 0.00 on call analysis, while on Salesforce its aggregates matched Salesforce's own SOQL on 13 of 13 checks.", "body_md": "A task-specific MCP server answers the question on its own side. On Google Ads with claude-opus-5, the Nexla server used 1.0 tool call and 10,668 tokens per task against 4.7 and 50,102; on HubSpot it matched HubSpot’s own server on deal counts and win rate for 21,682 tokens against 708,973 (32.7x uncached, 16.1x in the first run). On Avoma it returned the target-month call figures exactly, from dialer-call records Avoma’s own server could not read, with 1 logged tool error to 25. On Salesforce an agent connected to it with one URL and one key, and its numbers matched Salesforce’s own SOQL on 13 of 13 checks.\n\nWe gave an agent a question as a user had typed it, typos included. It asked for an analysis of won and lost deals over the last 90 days, trends in deal size and stage, and any missing data. Same model (claude-opus-5), same HubSpot portal holding a synthetic set of 1,130 deals, two MCP servers.\n\nBoth answers came back with 199 closed deals, 135 won and 64 lost, and a 67.8% win rate, all matching ground truth computed from the source data independently of both servers. One answer used 21,682 tokens. The other used 708,973, uncached.\n\nThe difference was what each server handed the model. Nexla’s server has six aggregation tools that compute summaries over the full dataset and return finished results. HubSpot’s CRM MCP gives the agent 24 general tools, including SQL, and re-sends about 39,000 tokens of tool schema on every turn. One server answers the question. The other hands the agent a toolbox to work it out.\n\nAn MCP server decides what the model reads on every turn: its tool schema and its results. So the shape of the server sets the token bill and the places where an answer can go wrong. A task-specific server is built for a defined set of questions; we covered task-specific vs system-specific MCP servers in an earlier post.\n\nWe build these servers in MCP Studio and wanted to measure what a task-specific server changes. So on four systems, Google Ads, HubSpot, Avoma and Salesforce, we held the model, questions and data fixed, changed only the server, and checked the answers against ground truth. This post reports the measures where the task-specific server came out ahead, and the full method behind each number.\n\nWhat held: on Google Ads and HubSpot, a server that answers the question itself used fewer tokens. On Avoma, a server built on modeled call tables did not hit the validation error that kept Avoma’s own server from reading dialer calls, and the harness logged fewer errored tool calls against it. On Salesforce, Nexla’s hosted task-specific server needed nothing installed to connect. And on Google Ads, HubSpot and Salesforce, its answers held up against ground truth computed outside the servers.\n\nResults across four systems\n\nFigure 1 has one panel per system. On Google Ads, HubSpot and Avoma it compares Nexla’s task-specific server with the vendor’s own MCP server; on Salesforce it compares the Nexla server’s numbers with Salesforce’s own SOQL (Salesforce Object Query Language) results on the same org. Figure 2 is the scorecard: the main measures on each system, against each comparator.\n\nFigure 1. Fewer tokens, fewer tool errors, matching numbers: Nexla's task-specific server on four systems. Headline measure per system, against the vendor's own MCP server or, on Salesforce, Salesforce's own SOQL.\n\nNexla\n\nVendor's own server\n\nGoogle Ads4.7xfewer tokens per task, claude-opus-5\n\n10,668\n\n50,102\n\n1.0 vs 4.7 tool calls per task\n\nHubSpot32.7xfewer tokens for one question\n\n21,682\n\n708,973\n\n16.1x fewer in the first run\n\nAvoma1 vs 25errored tool calls over 10 tasks\n\n1\n\n25\n\nCall-analysis score 0.50 vs 0.00\n\nSalesforce13 of 13aggregates matched SOQL\n\nall four object totals exact\n\nShow the data\n\nSystem\n\nMeasure\n\nNexla\n\nVendor's own server\n\nRatio\n\nGoogle Ads\n\nTokens per task, claude-opus-5\n\n10,668\n\n50,102\n\n4.7x\n\nGoogle Ads\n\nTool calls per task, claude-opus-5\n\n1.0\n\n4.7\n\n4.7x\n\nHubSpot\n\nTokens for one question, run 2\n\n21,682\n\n708,973\n\n32.7x\n\nHubSpot\n\nTokens for one question, run 1\n\n51,867\n\n832,739\n\n16.1x\n\nAvoma\n\nErrored tool calls, 10 tasks\n\n1\n\n25\n\nAvoma\n\nCall-analysis correctness, 0-1\n\n0.50\n\n0.00\n\nSalesforce\n\nICP aggregates matching Salesforce's own SOQL\n\n13 of 13\n\nSalesforce\n\nObject totals exact\n\nAll four\n\nGoogle Ads (one live, low-volume account; ten tasks). Correctness was 1.00 against 0.975 for Google’s server with claude-opus-5, and 0.90 against 0.77 with gpt-5.5, where one Nexla task never executed because the OpenAI request did not return (1.00 over the nine that did). With claude-opus-5 the Nexla server made 1.0 tool call per task against 4.7, used 10,668 tokens per task against 50,102 (4.7x, uncached), and returned 93,058 bytes of tool results over ten tasks against 263,651 (2.8x). With gpt-5.5 it used 5,788 tokens per task against 39,086 over the tasks that executed (6.8x).\n\nHubSpot (a synthetic 1,130-deal dataset; one open-ended question, run twice). In the second run, both answers gave the same closed-deal count, won/lost split and win rate, matching ground truth, and the Nexla server used 21,682 tokens against 708,973 for HubSpot’s CRM MCP (32.7x, uncached). The first run of the same comparison used 51,867 against 832,739 (16.1x), so we report the gap as 16-33x.\n\nAvoma (Nexla’s own workspace, real data; ten questions). On call analysis the Nexla server scored 0.50 against 0.00 for Avoma’s own server, whose score covers the three call questions with a recorded measurement. The Nexla server’s target-month call count and outbound/inbound split were exact. Over all ten tasks the harness logged 1 errored tool call on the Nexla server and 25 on Avoma’s. Tool schema per turn was 4,637 characters against 15,078 (3.3x).\n\nSalesforce (a synthetic org; ten questions for ideal customer profile, or ICP, planning). An agent connected to the Nexla server with one URL and one key. In the scored run, 9 of 10 answers were judged correct against SOQL ground truth. The tenth, a won-deals date window, returned no answer in the scored run; one unscored re-run of that question returned 121 deals and $29,877,900, exactly the ground truth. In a pre-run check, all 13 ICP aggregates the server computed matched Salesforce’s own SOQL, and all four object totals were exact.\n\nFigure 2. Nexla ahead or level on every vendor comparison shown; 13 of 13 Salesforce checks matched SOQL. Nexla's task-specific MCP server against each vendor's own server, or Salesforce's own SOQL; claude-opus-5 as the agent.\n\nMeasure\n\nNexla\n\nVendor\n\nResult\n\nGoogle Ads vs Google's google-ads-mcp\n\nTokens per task\n\n10,668\n\n50,102\n\n4.7x fewer\n\nTool calls per task\n\n1.0\n\n4.7\n\n4.7x fewer\n\nCorrectness (0-1)\n\n1.00\n\n0.975\n\n✓ higher\n\nHubSpot vs HubSpot's CRM MCP, one question\n\nClosed deals · win rate\n\n199 · 67.8%\n\n199 · 67.8%\n\n✓ both correct\n\nTokens, run 2\n\n21,682\n\n708,973\n\n32.7x fewer\n\nTokens, run 1\n\n51,867\n\n832,739\n\n16.1x fewer\n\nAvoma vs Avoma's MCP server\n\nCall-analysis score (0-1)\n\n0.50\n\n0.00\n\n✓ higher\n\nErrored tool calls\n\n1\n\n25\n\n✓ fewer\n\nSchema per turn (chars)\n\n4,637\n\n15,078\n\n3.3x smaller\n\nSalesforce vs Salesforce's own SOQL\n\nICP aggregates matched\n\n13 of 13\n\n✓ exact\n\nObject totals matched\n\n4 of 4\n\n✓ exact\n\nICP questions correct\n\n9 of 10\n\n✓ vs SOQL\n\nShow the data\n\nMeasure\n\nNexla\n\nVendor's server\n\nResult\n\nGoogle Ads · vs Google's google-ads-mcp\n\nCorrectness, claude-opus-5 (0-1)\n\n1.00\n\n0.975\n\nhigher\n\nCorrectness, gpt-5.5 (0-1)\n\n0.90 (1.00 over the 9 tasks that executed)\n\n0.77\n\nhigher\n\nTool calls per task, claude-opus-5\n\n1.0\n\n4.7\n\n4.7x fewer\n\nTokens per task, claude-opus-5, uncached\n\n10,668\n\n50,102\n\n4.7x fewer\n\nTokens per task, gpt-5.5, tasks that executed, uncached\n\n5,788\n\n39,086\n\n6.8x fewer\n\nTool-result bytes, 10 tasks, claude-opus-5\n\n93,058\n\n263,651\n\n2.8x fewer\n\nHubSpot · vs HubSpot's CRM MCP · one question, claude-opus-5\n\nClosed deals; won, lost; win rate\n\n199; 135, 64; 67.8%\n\n199; 135, 64; 67.8%\n\nboth match ground truth\n\nTotal tokens, run 2, uncached\n\n21,682\n\n708,973\n\n32.7x fewer\n\nTotal tokens, run 1, uncached\n\n51,867\n\n832,739\n\n16.1x fewer\n\nInput tokens on the first turn, run 2\n\n3,796\n\n54,876\n\n14.5x fewer\n\nAvoma · vs Avoma's MCP server · claude-opus-5\n\nCall-analysis correctness (0-1)\n\n0.50\n\n0.00\n\nhigher\n\nErrored tool calls, all 10 tasks\n\n1\n\n25\n\nfewer\n\nTool schema per turn (characters)\n\n4,637\n\n15,078\n\n3.3x smaller\n\nSalesforce · results vs Salesforce's own SOQL; setup vs Salesforce's DX MCP server · claude-opus-5\n\nICP aggregates matching SOQL\n\n13 of 13\n\nexact\n\nObject totals matching SOQL COUNT()\n\n4 of 4 (500; 2,500; 1,500; 2,000)\n\nexact\n\nICP questions correct, scored run\n\n9 of 10\n\njudged against SOQL\n\nSnapshots labelled COMPLETE, scored run\n\n8 of 8\n\nCapped reads labelled PARTIAL, scored run\n\n4 of 4\n\nTo connect an agent\n\nOne URL and one key; nothing installed\n\nSalesforce CLI, browser OAuth login, local Node server\n\nHow to read these numbers: tokens are provider-reported input plus output, summed over every turn, with no prompt caching. Each cell has one scored run (HubSpot two). On Avoma, eight cells that failed on an expired login or API timeouts were re-run, and the final run is the one reported.\n\nWhat this tells us\n\nAnswer-shaped results keep the loop short. The Nexla Google Ads server is bound to one account and to modeled performance tables, so the agent made one call per executed task with no discovery step. Google’s agent listed accessible accounts at the start of all 20 of its task-cells. With claude-opus-5, tokens fell 4.7x (uncached) while tool-result bytes fell only 2.8x, because every turn re-sends the tool schema and the conversation so far. Fewer turns did more than smaller rows, as our Google Ads post also found.\n\nThe schema is a per-turn fee. HubSpot’s server re-sends about 39,000 tokens of tool schema on every turn. In the second run, HubSpot’s first turn alone was 54,876 input tokens, before any data came back, against 3,796 for the Nexla server. On Avoma the schemas were 15,078 characters against 4,637. The schema section below shows how HubSpot’s adds up turn by turn.\n\nA wrapper inherits its API’s edges. Avoma’s server requires the from and to fields of a call record (frm and to) to be strings, and dialer calls store both as null, so any page of meetings that contains a dialer call fails validation. That error made up 21 of the 25 errored tool calls the harness logged on Avoma’s server. The Nexla server reads a modeled call table, and its target-month answers were exact.\n\nCheck against something the server did not produce. On Google Ads, ground truth from the Google Ads API matched all six Nexla tools on 10 of 10 answers. On HubSpot, the counts and win rate matched ground truth computed from the source dataset. On Salesforce, 13 of 13 aggregates matched SOQL, all four object totals were exact, and every capped read in the scored run came back labelled PARTIAL.\n\nThe four systems in detail\n\nEach section covers the setup, the measures we report, why they came out that way, and a link to the full write-up where one exists. Google Ads, HubSpot and Avoma have one; Salesforce is new in this post.\n\nGoogle Ads: one call per task\n\nWe ran the Google Ads comparison against Nexla’s own live Google Ads account, a single low-volume account, over a rolling 30-day window. For more detail, read the full Google Ads benchmark.\n\nGoogle’s official google-ads-mcp server has three general tools: a GAQL (Google Ads Query Language) search, a resource-metadata lookup and an account listing. Our server has six data tools over modeled campaign, ad-group, keyword, search-term, ad and daily campaign performance tables, bound to that one account. Ten tasks covered five categories: structure (2), relationship (2), aggregation (4), totals (1) and point in time (1). Two agents, claude-opus-5 and gpt-5.5, got every task once on both servers, 40 task-cells in all, with claude-opus-5 as the judge. A typical prompt: “Over the last 30 days, what were this account’s total impressions, total clicks, and total cost in dollars?”\n\nGround truth came from the Google Ads API (GAQL, last 30 days, impressions greater than zero). It matched all six Nexla tools on 10 of 10 answers, so both servers were reading the same data.\n\nFigure 3 shows correctness per task. With claude-opus-5, the Nexla server scored 1.00 on all ten tasks. Google’s server scored 0.975: 1.00 on nine tasks and 0.75 on T4, which asks for one keyword’s match type and ad group without stating the window or the impression qualifier. The agent answered for the whole account and was marked down. We count that as a gap in our prompt, not in Google’s server.\n\nWith gpt-5.5, the Nexla server scored 0.90 as measured and 1.00 over the nine tasks that executed. On T1 the OpenAI API request never returned, and the cell timed out at 180 s without a tool call. Our Google Ads post gave the gpt-5.5 call, token and byte figures for the Nexla server over the nine tasks that executed, which is why it reports one call per task for both models. Google’s server scored 0.77. On T1 and T9 the agent listed the accessible accounts, saw two, and stopped to ask which one to use (0.10 each); T4 scored 0.50.\n\nFigure 3. Google Ads: the Nexla server scored 1.00 on every task that executed, with both agents. Judge score per task (0–1); a solid cell is a perfect 1.00.\n\nclaude-opus-5Mean\n\nNexla1.00\n\nGoogle’s server0.975\n\n0.75\n\nT1T2T3T4T5T6T7T8T9T10\n\ngpt-5.5Mean\n\nNexla(1.00 on 9)0.90\n\nGoogle’s server0.77\n\n0.100.500.10\n\nT1T2T3T4T5T6T7T8T9T10\n\nNexla\n\nGoogle’s server\n\nDid not execute\n\nShow the data\n\nclaude-opus-5\n\ngpt-5.5\n\nTask\n\nCategory\n\nNexla\n\nGoogle’s server\n\nNexla\n\nGoogle’s server\n\nT1\n\nstructure\n\n1.00\n\n1.00\n\n0.00 (did not execute)\n\n0.10\n\nT2\n\nstructure\n\n1.00\n\n1.00\n\n1.00\n\n1.00\n\nT3\n\nrelationship\n\n1.00\n\n1.00\n\n1.00\n\n1.00\n\nT4\n\nrelationship\n\n1.00\n\n0.75\n\n1.00\n\n0.50\n\nT5\n\naggregation\n\n1.00\n\n1.00\n\n1.00\n\n1.00\n\nT6\n\naggregation\n\n1.00\n\n1.00\n\n1.00\n\n1.00\n\nT7\n\naggregation\n\n1.00\n\n1.00\n\n1.00\n\n1.00\n\nT8\n\naggregation\n\n1.00\n\n1.00\n\n1.00\n\n1.00\n\nT9\n\ntotals\n\n1.00\n\n1.00\n\n1.00\n\n0.10\n\nT10\n\npoint in time\n\n1.00\n\n1.00\n\n1.00\n\n1.00\n\nMean\n\n1.00\n\n0.975\n\n0.90 (1.00 over the 9 tasks that executed)\n\n0.77\n\nFigure 4 shows mean tokens per task: provider-reported input plus output, summed over every turn, uncached. With claude-opus-5 the averages were 10,668 tokens on the Nexla server and 50,102 on Google’s (4.7x). Per task, the Nexla server stayed between 8,635 and 16,353 tokens, while Google’s ranged from 11,734 to 96,265. The ten-task totals were 106,679 and 501,022. With gpt-5.5, the Nexla server averaged 5,788 tokens over the nine tasks that executed, against 39,086 for Google’s over all ten (6.8x, uncached).\n\nFigure 4. Google Ads: the Nexla server used 4.7x to 6.8x fewer tokens per task on average. Mean input plus output tokens per task that executed, uncached. Lower is better.\n\nclaude-opus-54.7x fewer\n\nNexla10,668\n\nGoogle’s server50,102\n\ngpt-5.56.8x fewer\n\nNexla5,788\n\nGoogle’s server39,086\n\nShow the data\n\nMean tokens per task, uncached\n\nAgent\n\nNexla\n\nGoogle’s server\n\nFewer with Nexla\n\nclaude-opus-5\n\n10,668\n\n50,102\n\n4.7x\n\ngpt-5.5\n\n5,788 (9 tasks executed)\n\n39,086\n\n6.8x\n\nFigure 5 shows where the calls went. With both agents, every task that executed on the Nexla server took one call, straight to a data tool, with no discovery step. Over ten tasks, the agent on Google’s server made 47 calls with claude-opus-5 and 48 with gpt-5.5: 10 account listings each (one per task), 6 and 15 metadata lookups, and 31 and 23 GAQL searches. With claude-opus-5 that is 1.0 call per task against 4.7.\n\nFigure 5 also shows tool-result bytes, the length of the result text handed to the model. With claude-opus-5 that was 93,058 bytes on the Nexla server against 263,651 on Google’s over ten tasks (2.8x). With gpt-5.5 it was 89,260 over the nine tasks that executed against 429,906 (4.8x).\n\nFigure 5. Google Ads: the Nexla server took one call per executed task and returned 2.8x to 4.8x fewer bytes. Tool calls by type, and tool-result bytes returned to the model, over 10 tasks per agent.\n\nNexla\n\nGoogle’s server\n\nDiscovery call\n\nclaude-opus-52.8x fewertool-result bytes on Nexla93,058 vs 263,651\n\ngpt-5.54.8x fewertool-result bytes on Nexla89,260 vs 429,906\n\nShow the data\n\nAgent\n\nServer\n\nAccount listing (discovery)\n\nResource metadata (discovery)\n\nGAQL search (data)\n\nNexla data tools\n\nTotal calls\n\nTool-result bytes\n\nclaude-opus-5\n\nNexla\n\n–\n\n–\n\n–\n\n10\n\n10\n\n93,058\n\nclaude-opus-5\n\nGoogle’s server\n\n10\n\n6\n\n31\n\n–\n\n47\n\n263,651 (2.8x Nexla)\n\ngpt-5.5\n\nNexla\n\n–\n\n–\n\n–\n\n9\n\n9\n\n89,260 (9 tasks executed)\n\ngpt-5.5\n\nGoogle’s server\n\n10\n\n15\n\n23\n\n–\n\n48\n\n429,906 (4.8x Nexla)\n\nSo with claude-opus-5, bytes fell 2.8x but tokens fell 4.7x. The difference is turns. Every model turn re-sends the tool definitions and the conversation so far. A one-call task takes two turns, one to call the tool and one to answer. Each call that depends on an earlier result adds a turn, and that turn re-reads everything before it. A query tool makes the agent build the report; a task-specific tool has already built it.\n\nHubSpot: the same counts and win rate for 16-33x fewer tokens\n\nWe loaded a synthetic dataset of 1,130 deals (1,010 closed, 120 open) into a HubSpot portal. The agent got one open-ended question, phrased exactly as a user wrote it, typos included. It asked for an analysis of won and lost deals over the last 90 days, any trends in deal size, stage and other factors behind wins and losses, what else to consider, and what data was missing. The model was claude-opus-5, streaming, with a 32,000-token output cap, no system prompt and no scoring wrapper.\n\nOn one side was HubSpot’s CRM MCP server, with 24 general tools, including one that accepts SQL. On the other was a Nexla server with seven data tools, six that compute summaries over the full dataset on the server and one that returns raw rows, plus a describe_tool gateway the agent could also call.\n\nFigure 6 compares both answers with ground truth, which we computed from the source dataset independently of both servers. Both answers gave 199 closed deals, 135 won and 64 lost, and a 67.8% win rate. Both gave the same average deal sizes: $101,898 for won deals and $129,279 for lost ones. The Nexla answer gave won and lost value to the dollar, $13,756,172 and $8,273,860. HubSpot’s answer rounded them to $13.76M and $8.27M. We count both as matches.\n\nFigure 6. HubSpot: both answers gave 199 closed deals and a 67.8% win rate, matching ground truth. Closed deals in the last 90 days, second run. ✓ = the answer matched ground truth.\n\nMeasure\n\nGround truth\n\nNexla\n\nHubSpot's CRM MCP\n\nClosed deals\n\n199\n\n✓\n\n✓\n\nWon / lost\n\n135 / 64\n\n✓\n\n✓\n\nWin rate\n\n67.8%\n\n✓\n\n✓\n\nWon value\n\n$13,756,172\n\n✓\n\n$13.76M✓\n\nLost value\n\n$8,273,860\n\n✓\n\n$8.27M✓\n\nAvg won deal\n\n$101,898\n\n✓\n\n✓\n\nAvg lost deal\n\n$129,279\n\n✓\n\n✓\n\nShow the data\n\nMeasure (second run)\n\nGround truth\n\nNexla\n\nHubSpot's CRM MCP\n\nClosed deals, last 90 days\n\n199\n\n199\n\n199\n\nWon / lost\n\n135 / 64\n\n135 / 64\n\n135 / 64\n\nWin rate\n\n67.8%\n\n67.8%\n\n67.8%\n\nWon value\n\n$13,756,172\n\n$13,756,172\n\n$13.76M\n\nLost value\n\n$8,273,860\n\n$8,273,860\n\n$8.27M\n\nAverage won deal\n\n$101,898\n\n$101,898\n\n$101,898\n\nAverage lost deal\n\n$129,279\n\n$129,279\n\n$129,279\n\nFigure 7 shows what each answer cost. Tokens here are provider-reported input plus output, summed over every turn, uncached. In the second run, the agent used 21,682 tokens on the Nexla server and 708,973 on HubSpot’s, a ratio of 32.7x. In the first run of the same comparison it was 51,867 against 832,739, or 16.1x. Across the two runs, the gap was 16-33x. Our HubSpot post gave these two runs as ranges, 21.7k-51.9k tokens for Nexla and 709k-833k for HubSpot’s server; paired run by run, they are the 32.7x and 16.1x shown here.\n\nFigure 7. HubSpot: the Nexla server used 16-33x fewer tokens for the same question. Total tokens to answer one question, uncached, in each of two runs.\n\nRun 116.1x fewer\n\nNexla51,867HubSpot’s server832,739\n\nRun 232.7x fewer\n\nNexla21,682HubSpot’s server708,973\n\nShow the data\n\nRun\n\nNexla (tokens)\n\nHubSpot’s CRM MCP (tokens)\n\nHubSpot ÷ Nexla\n\nRun 1\n\n51,867\n\n832,739\n\n16.1x\n\nRun 2\n\n21,682\n\n708,973\n\n32.7x\n\nAlmost all of that gap is input. HubSpot’s server re-sends about 39,000 tokens of tool schema on every turn; we measured its 24 tools at 39,183 tokens and 136,412 characters. On the Nexla server the whole first turn, tool definitions plus the question, was 3,796 input tokens, against 54,876 on HubSpot’s. Nexla’s tools also return finished summaries, so the agent has little left to assemble before it answers. Figure 14, in the schema section below, shows the input on each turn.\n\nOne part of the question shows the tool design at work. The question asked what data was missing, and the Nexla server has a data-quality tool that reports null counts on critical fields, computed on the server. That tool answers that part of the question directly. Both answers flagged the same core gaps: no stage-entry history, one owner on every deal, no activity data, and no competitor or discount fields.\n\nAvoma: reading the calls the vendor’s server could not\n\nWe pointed Avoma’s MCP server and a Nexla call-analysis server, built on modeled call tables, at Nexla’s own production Avoma workspace. This is real data, so this post gives no counts, names or reps. claude-opus-5 was the agent and the judge, with a fresh conversation per cell. Ten questions ran against each server. Four were call-analysis questions, and the correctness results below cover that category. The error and schema figures cover all ten. Ground truth for the call questions was counted by a script, with no model in the loop, from the Nexla server’s own call table, read through that server’s call tool in weekly slices. Avoma’s server could not read those records. The question-by-question detail is in the full Avoma benchmark.\n\nFigure 8 shows the call-analysis category: 0.50 for the Nexla server and 0.00 for Avoma’s. The Nexla server’s target-month call count and target-month outbound/inbound split both matched ground truth exactly. Its other two call answers scored 0.00: the prior-month count came from one whole-month read that the server cut off at its size cap, and it came back at about half the true figure, stated as final. The rep question timed out. On Avoma’s server the agent returned no call figure on any call question that produced a measurement, and each answer said it could not retrieve the call data. Avoma’s 0.00 is the mean of those three cells.\n\nFigure 8. Avoma: the Nexla server scored 0.50 on call analysis, Avoma's server 0.00. Correctness on a 0–1 scale, and each server's result on the two target-month questions.\n\nCall-analysis correctness\n\nNexla0.50\n\nAvoma's MCP server0.00\n\nTarget-month questions\n\nDialer-call count✓ Exact✕ No answer\n\nOutbound/inbound split✓ Exact✕ No answer\n\nNexla\n\nAvoma's MCP server\n\nShow the data\n\nMeasure\n\nNexla\n\nAvoma's MCP server\n\nCall-analysis correctness (0–1)\n\n0.50\n\n0.00\n\nCall-analysis tasks scored\n\n4\n\n3 measured\n\nTarget-month dialer-call count\n\nExact (1.00)\n\nNo answer (0.00)\n\nTarget-month outbound/inbound split\n\nExact (1.00)\n\nNo answer (0.00)\n\nThe cause is in Avoma’s own API client. It declares the frm and to fields of a call’s details as required strings, and dialer calls store both as null. Any page of meetings that holds a dialer call fails validation with Failed to list meetings: 2 validation errors for CallDetails before the agent sees any data. Smaller pages do not help, because any page that holds a dialer call fails.\n\nThe harness logged 25 errored tool calls on Avoma’s server, all on those three call questions (Figure 9). The fourth call question timed out on both servers, and the harness kept no tool calls for it. Of those, 21 were this validation error. The other 4 came from a usage-metrics tool that only covers the last 30 days. Across all ten tasks, the harness logged 1 errored tool call on the Nexla server.\n\nFigure 9. Avoma: 1 errored tool call on the Nexla server, 25 on Avoma's. Tool calls the harness logged as errored, across all 10 tasks on each server.\n\nThe tool schema the harness sent on every turn was 15,078 characters for Avoma’s server and 4,637 for the Nexla server (3.3x), with tool descriptions clipped to 1,500 characters for both. The schema section below returns to this.\n\nA vendor’s MCP server is a wrapper on the vendor’s API, and it carries that API’s edges with it. Here, two fields declared as required strings put every dialer call out of reach. The Nexla server reads modeled call tables instead, and on the target-month questions it returned the figures Avoma’s server could not.\n\nSalesforce: checked against Salesforce’s own numbers\n\nSalesforce is new in this post. The org is synthetic: a trial org we seeded with 500 accounts, 2,500 contacts, 1,500 leads and 2,000 opportunities, in the Asia/Kolkata timezone with one currency. The task set is ten ICP-planning questions: which industries win, where customers are billed, who the contacts are, and what sits in open pipeline. They fall into six categories. The comparator in the run was Salesforce’s official DX MCP server (@salesforce/mcp 0.30.15, data toolset). claude-opus-5 was the agent and the judge, the harness was mcp-bench, and each task ran once.\n\nNexla’s ICP-planner server has four object readers with a count mode, schema inspection, and a snapshot-and-query workspace: it copies complete reader output into a workspace and runs SQL there. It also carries generic gateway tools, one of which passes SOQL through to Salesforce; the SF10 answer came through that route. Ground truth is Salesforce’s own SOQL, run read-only through the Salesforce CLI and never through either MCP server. On Salesforce we report what it took to connect each server (next section) and how the Nexla server’s numbers held up against Salesforce’s own SOQL.\n\nBefore the run, we checked the benchmarked server against Salesforce directly. A script, with no model in the loop, took a full snapshot of all four objects through the Nexla server and computed 13 ICP aggregates inside it. We ran the same 13 aggregates as SOQL through the Salesforce CLI. All 13 matched exactly (Figure 10). They cover counts, sums and group-bys over accounts, leads and deals, by type, industry, billing country, lead status, lead source, deal outcome and stage; won deals by account industry, both through the deal’s account field and through a join to accounts; won deals in a one-quarter close-date window; and contacts per account type.\n\nFigure 10. Salesforce: all 13 Nexla aggregates matched Salesforce’s own SOQL exactly. Counts, sums and group-bys from the Nexla server, each compared with the same aggregate run as SOQL.\n\nChecks13 of 13matched SOQL exactly\n\nResult rows176all identical to SOQL\n\nAccounts✓✓✓✓\n\nLeads✓✓✓\n\nDeals✓✓✓✓✓\n\nContacts✓\n\nShow the data\n\nObject\n\nCheck\n\nResult rows\n\nSame as SOQL\n\nSOQL\n\nAccounts\n\nAccounts by type\n\n10\n\nYes, exact\n\nSELECT Type, COUNT(Id) FROM Account GROUP BY Type\n\nAccounts\n\nAccounts by industry\n\n30\n\nYes, exact\n\nSELECT Industry, COUNT(Id) FROM Account GROUP BY Industry\n\nAccounts\n\nCustomer accounts by billing country\n\n9\n\nYes, exact\n\nSELECT BillingCountry, COUNT(Id) FROM Account WHERE Type='Customer' GROUP BY BillingCountry\n\nAccounts\n\nAccount revenue and employee totals\n\n1\n\nYes, exact\n\nSELECT SUM(AnnualRevenue), SUM(NumberOfEmployees) FROM Account\n\nLeads\n\nLeads by status\n\n4\n\nYes, exact\n\nSELECT Status, COUNT(Id) FROM Lead GROUP BY Status\n\nLeads\n\nLeads by source\n\n11\n\nYes, exact\n\nSELECT LeadSource, COUNT(Id) FROM Lead GROUP BY LeadSource\n\nLeads\n\nUS leads by industry\n\n31\n\nYes, exact\n\nSELECT Industry, COUNT(Id) FROM Lead WHERE Country='United States' GROUP BY Industry\n\nDeals\n\nDeals won, lost and open\n\n3\n\nYes, exact\n\nSELECT IsClosed, IsWon, COUNT(Id), SUM(Amount) FROM Opportunity GROUP BY IsClosed, IsWon\n\nDeals\n\nDeals by stage\n\n6\n\nYes, exact\n\nSELECT StageName, COUNT(Id), SUM(Amount) FROM Opportunity GROUP BY StageName\n\nDeals\n\nWon by account industry, deal field\n\n30\n\nYes, exact\n\nSELECT Account.Industry, COUNT(Id), SUM(Amount) FROM Opportunity WHERE IsWon = true GROUP BY Account.Industry\n\nDeals\n\nWon by account industry, join\n\n30\n\nYes, exact\n\nSELECT Account.Industry, COUNT(Id), SUM(Amount) FROM Opportunity WHERE IsWon = true GROUP BY Account.Industry\n\nDeals\n\nWon deals closing in one quarter\n\n1\n\nYes, exact\n\nSELECT COUNT(Id), SUM(Amount) FROM Opportunity WHERE IsWon = true AND CloseDate >= <quarter start> AND CloseDate <= <quarter end>\n\nContacts\n\nContacts per account type, join\n\n10\n\nYes, exact\n\nSELECT Account.Type, COUNT(Id) FROM Contact GROUP BY Account.Type\n\nAll\n\n13 checks\n\n176\n\n13 of 13\n\nIn the scored run, nine of ten answers were correct (judge score 0.8 or above) against SOQL ground truth, across structure, relationship, aggregation, totals and honesty at scale (Figure 11). The honesty-at-scale question asks for a count that spans all 2,500 contacts, where a silently truncated read gives a wrong number. The tenth, a won-deals date window, returned no answer in the scored run; one unscored re-run of that question returned 121 deals and $29,877,900, exactly the ground truth.\n\nFigure 11. Salesforce: the Nexla server answered 9 of 10 ICP questions correctly. Scored against SOQL ground truth; correct means a judge score of 0.8 or above.\n\nScored run9 of 10answers correctall nine scored 1.00\n\nUnscored re-runExacton the point-in-time question121 deals, $29,877,900\n\nCorrect answers in the scored run, by category\n\nStructure\n\nRelationship\n\nAggregation\n\nTotals\n\nHonesty at scale\n\nPoint in timeno answer\n\nShow the data\n\nTask\n\nCategory\n\nDifficulty\n\nQuestion (paraphrased)\n\nScored run\n\nJudge score\n\nUnscored re-run\n\nSF01\n\nstructure\n\neasy\n\nCustomer accounts billed outside the United States (count)\n\nCorrect\n\n1.00\n\nNot re-run\n\nSF02\n\nstructure\n\neasy\n\nAccounts in the Utilities industry, with Type (list)\n\nCorrect\n\n1.00\n\nNot re-run\n\nSF03\n\nrelationship\n\neasy\n\nContacts at one named account, with titles (list)\n\nCorrect\n\n1.00\n\nNot re-run\n\nSF04\n\nrelationship\n\nmedium\n\nA named deal’s account, its industry and employee count\n\nCorrect\n\n1.00\n\nNot re-run\n\nSF05\n\naggregation\n\nhard\n\nClosed Won by account industry: top by revenue and top by count\n\nCorrect\n\n1.00\n\nNot re-run\n\nSF06\n\naggregation\n\nmedium\n\nWin rate, New vs Existing Business, closed deals only\n\nCorrect\n\n1.00\n\nNot re-run\n\nSF07\n\naggregation\n\nhard\n\nTop two accounts by Closed Won revenue\n\nCorrect\n\n1.00\n\nNot re-run\n\nSF08\n\ntotals\n\nmedium\n\nTotal Closed Won revenue and open pipeline, with counts\n\nCorrect\n\n1.00\n\nNot re-run\n\nSF09\n\npoint in time\n\nmedium\n\nDeals won with a close date inside a one-quarter window, both ends inclusive, count and amount\n\nNo answer returned\n\n0.00\n\n121 deals, $29,877,900 (exact)\n\nSF10\n\nhonesty at scale\n\nhard\n\nContacts with ‘VP’ in title, and the top account industry among them\n\nCorrect\n\n1.00\n\nNot re-run\n\nThe server also says what it read (Figure 12). In a second pre-run probe, count mode and a full snapshot each returned exactly 500, 2,500, 1,500 and 2,000 rows for accounts, contacts, leads and opportunities, the same totals SOQL COUNT() reports. In the scored run, all eight snapshots the server returned were marked COMPLETE with source_exhausted: true. All four capped reads came back labelled PARTIAL, with truncated: true and the instruction “Do not compute whole-source aggregates from this partial response.” No answer used a partial read, and no Nexla answer matched any of the wrong numbers we had listed in advance for a truncated read.\n\nFigure 12. Salesforce: all four object totals were exact; every scored-run capped read was labelled PARTIAL. Nexla server row counts against SOQL COUNT(), and the label on each scored-run snapshot and capped read.\n\nObject totals4 of 4exact against SOQL COUNT()count mode and full snapshot\n\n8 snapshotsCOMPLETEused in 8 answerssource_exhausted: true\n\n4 capped readsPARTIALused in no answertruncated: true\n\nObject\n\nSOQL\n\nNexla\n\nAccount\n\n500\n\n✓ 500\n\nContact\n\n2,500\n\n✓ 2,500\n\nLead\n\n1,500\n\n✓ 1,500\n\nOpportunity\n\n2,000\n\n✓ 2,000\n\nShow the data\n\nObject totals\n\nObject\n\nSOQL COUNT()\n\nNexla count mode\n\nNexla full snapshot\n\nRows in each scored-run snapshot\n\nAccount\n\n500\n\n500\n\n500\n\n500 (5 snapshots)\n\nContact\n\n2,500\n\n2,500\n\n2,500\n\n2,500 (1 snapshot)\n\nLead\n\n1,500\n\n1,500\n\n1,500\n\nnot needed\n\nOpportunity (deals)\n\n2,000\n\n2,000\n\n2,000\n\n2,000 (5 snapshots)\n\nLabels in the scored run\n\nRead\n\nTask\n\nRows\n\nLabel\n\nUsed in an answer\n\n8 snapshots\n\nSF01–SF08\n\nevery row\n\nCOMPLETE, source_exhausted: true\n\nYes, all 8\n\nDeals read\n\nSF04\n\n500 of 2,000\n\nPARTIAL, truncated: true\n\nNo\n\nDeals sample\n\nSF06\n\n5 of 2,000\n\nPARTIAL, truncated: true\n\nNo\n\nDeals read\n\nSF09\n\n500 of 2,000\n\nPARTIAL, truncated: true\n\nNo\n\nContacts read\n\nSF10\n\n1,000 of 2,500\n\nPARTIAL, truncated: true\n\nNo\n\nAn agent can only be careful about completeness if the server tells it what it got.\n\nGetting to the first query\n\nThis section covers Salesforce only. It counts the steps for the person connecting an agent to a server that already exists. The Nexla server was built in MCP Studio beforehand, with its Salesforce connection configured once in Nexla, so its steps start at the agent’s MCP client config. Figure 13 sets out three paths: Nexla’s server, Salesforce’s DX server, which we used in the run, and Salesforce’s hosted server, as Salesforce documents it.\n\nFigure 13. Salesforce: connecting an agent took 1 step on the Nexla server and 5 on Salesforce’s DX server. Steps for the person connecting an agent once the server exists. Hosted server shown as Salesforce documents it.\n\nNexla server1 step\n\n1Add URL and one key\n\nSalesforce DX (local)5 steps\n\n1Install Salesforce CLI\n\n2Log in via browser\n\n3Install server locally\n\n4Launch with flags\n\n5Alias + dir per query call\n\nSalesforce hosted (documented)3 steps\n\n1Admin activates server\n\n2Admin creates OAuth app\n\n3Each user logs in\n\nShow the data\n\nPath\n\nStep\n\nWhat\n\nWho does it\n\nDetail\n\nNexla server\n\n1\n\nAdd the streamable-HTTP URL and one bearer key to the MCP client config\n\nagent builder\n\nconnected in about 1 s\n\nSalesforce DX MCP (local)\n\n1\n\nInstall the Salesforce CLI\n\nagent builder\n\nCLI 2.153.5\n\nSalesforce DX MCP (local)\n\n2\n\nLog the CLI in to the org through the browser: sf org login web\n\na person at a browser\n\n–\n\nSalesforce DX MCP (local)\n\n3\n\nInstall the server locally: @salesforce/mcp 0.30.15\n\nagent builder\n\n1,392 npm packages\n\nSalesforce DX MCP (local)\n\n4\n\nLaunch a local Node server with --orgs, --toolsets and --no-telemetry\n\nagent builder\n\n–\n\nSalesforce DX MCP (local)\n\n5\n\nPass the org alias and an absolute working directory as tool arguments on every query call\n\nagent or prompt\n\n–\n\nSalesforce hosted MCP (documented)\n\n1\n\nAdmin activates the server (platform/sobject-reads) in Setup\n\norg admin\n\n–\n\nSalesforce hosted MCP (documented)\n\n2\n\nAdmin creates an External Client App: OAuth authorization code with PKCE\n\norg admin\n\n–\n\nSalesforce hosted MCP (documented)\n\n3\n\nEach user logs in\n\neach user\n\n–\n\nNexla. The agent builder adds a streamable-HTTP URL and one bearer key to the MCP client config. In our run the server connected in about 1 s. There is no CLI, no local install, no OAuth app and no edition gate for the agent builder. The Salesforce credential stays in Nexla, not on the agent’s machine.\n\nSalesforce DX (local).The DX server runs on the agent’s machine and uses the Salesforce CLI’s login. These are the steps we took:\n\nInstall the Salesforce CLI.\n\nLog the CLI in to the org through the browser with sf org login web. Two of our attempts ended in AuthTimeoutError and one in PortInUseError on port 1717. The documented fallback, sf org login device, is not a command in CLI 2.153.5. Login succeeded once we completed the browser flow in our own terminal.\n\nInstall @salesforce/mcp locally. Version 0.30.15 brought in 1,392 npm packages.\n\nLaunch it as a local Node server with --orgs, --toolsets and --no-telemetry. Telemetry is on by default, and only that flag turns it off.\n\nPass the org alias and an absolute working directory as tool arguments; the query tool requires both on every call. We put both in every prompt, so the agent did not have to discover them.\n\nSalesforce hosted (platform/sobject-reads). Salesforce documents its hosted MCP server for Enterprise Edition and above, plus Developer Edition (Confirming Availability). Our trial org reports Base Edition, which is not on that list. On a supported edition the documented path has three steps:\n\nAn admin activates the server in Setup.\n\nAn admin creates an External Client App with OAuth authorization code plus PKCE, the scopes mcp_api and refresh_token, and JWT access tokens for named users.\n\nEach user logs in. Access tokens follow the user’s session timeout, typically 2 hours and configurable up to 12.\n\nAn agent works with a model in turns. On every turn, the client sends the model the server’s tool definitions, which we call the schema, plus the whole conversation so far. None of these runs used prompt caching, so every turn paid for the full schema again. A server’s schema is a per-turn fee, multiplied by the number of turns the agent takes.\n\nFigure 14 shows what that fee looked like on HubSpot. The run sent no system prompt, and the user message was 45 words long. Even so, HubSpot’s first turn was 54,876 input tokens, before any data came back. The Nexla server’s first turn was 3,796 tokens, 14.5x smaller. HubSpot’s input then grew with the conversation and reached 78,190 tokens on its last turn. Over the whole question, HubSpot’s input came to 700,221 tokens against 13,251 for the Nexla server, all uncached.\n\nFigure 14. HubSpot: 13,251 input tokens over 2 turns on the Nexla server, 700,221 over 10 on HubSpot's. Input tokens sent to the model on each turn, tool schema included. HubSpot run 2, uncached.\n\nInput tokens on each model turn, HubSpot run 2, uncached\n\nModel turn\n\nNexla\n\nHubSpot's CRM MCP\n\nTurn 1\n\n3,796\n\n54,876\n\nTurn 2\n\n9,455\n\n60,515\n\nTurn 3\n\n–\n\n62,865\n\nTurn 4\n\n–\n\n70,297\n\nTurn 5\n\n–\n\n71,629\n\nTurn 6\n\n–\n\n73,175\n\nTurn 7\n\n–\n\n75,038\n\nTurn 8\n\n–\n\n76,405\n\nTurn 9\n\n–\n\n77,231\n\nTurn 10\n\n–\n\n78,190\n\nTotal input, all turns\n\n13,251\n\n700,221\n\nFigure 15 puts the schemas side by side. We measured the schema of HubSpot’s CRM MCP at 39,183 tokens (136,412 characters across 24 tools), so its server re-sends about 39,000 tokens on every turn. In run 2 the schema was at least as large, since the first turn alone was 54,876 tokens. On the Nexla HubSpot server the first turn of that run, tool definitions plus the same question, was 3,796 tokens, 14.5x less. On Avoma, our runner sent 15,078 characters of schema per turn for Avoma’s server and 4,637 for the Nexla server, 3.3x less. Both Avoma figures were measured with each tool description clipped to 1,500 characters, the same clip for both servers.\n\nFigure 15. Tool schema: the Nexla servers cost the model 14.5x less on HubSpot and 3.3x less on Avoma. What each server costs the model before any data: HubSpot in first-turn input tokens (tool definitions plus the question), Avoma in characters of tool schema.\n\nHubSpot14.5x lessInput tokens, first turn\n\nAvoma3.3x lessSchema characters per turn\n\nNexla\n\nVendor's own server\n\nShow the data\n\nMeasure\n\nNexla\n\nVendor's server\n\nNexla vs vendor\n\nHubSpot: input tokens, first turn of run 2\n\n3,796\n\n54,876\n\n14.5x less\n\nAvoma: characters of tool schema per turn\n\n4,637\n\n15,078\n\n3.3x less\n\nThe difference comes from what the tools are. HubSpot’s server ships a general catalog of 24 tools, including one that accepts SQL, and Avoma’s server has 14 tools. A catalog lets the agent reach any object and work out the rest. The Nexla HubSpot server has seven data tools plus a describe_tool gateway, and the Nexla Avoma server has eight tools, all built around the questions they were made to answer. Because the schema is re-read on every turn, we think it should carry the question rather than a catalog, which is the argument behind the tool description is the context.\n\nCreating the benchmark\n\nA benchmark like this has three parts, and all three have to be right: the world (the systems and their data), the tasks, and the checks. On every system the rule was the same. We held the model, the question and the data fixed and changed only the server, so whatever moved can be traced to the server. We described the framework in how we benchmark MCP servers. The HubSpot and Salesforce data in this post is synthetic by design, which is what lets us share it.\n\nThe systems and the data\n\nGoogle Ads: Nexla’s own live account, a single low-volume account, read over a rolling 30-day window. This post gives no account IDs, names or spend.\n\nHubSpot: a synthetic dataset of 1,130 deals (1,010 closed, 120 open), loaded into a HubSpot portal. An answer key documents the effects planted in it.\n\nAvoma: Nexla’s own production workspace. The data is real, so this post gives nothing that identifies people or volumes.\n\nSalesforce: a synthetic org seeded with 500 accounts, 2,500 contacts, 1,500 leads and 2,000 opportunities, timezone Asia/Kolkata and one currency. The org is a Base Edition trial.\n\nOn each system the vendor’s own MCP server ran against a Nexla server built in MCP Studio for that system’s questions. The vendor servers were Google’s google-ads-mcp, HubSpot’s CRM MCP, Avoma’s MCP server and Salesforce’s DX MCP server (@salesforce/mcp 0.30.15). Figure 16 summarizes each comparison: data, servers and tasks.\n\nFigure 16. What we tested: four systems, each vendor's own MCP server against a Nexla server. Each comparison held the model, tasks and data fixed and changed only the server.\n\nSalesforce's DX MCP server (@salesforce/mcp 0.30.15, data toolset)\n\nNexla server\n\n6 data tools bound to one account, plus 5 gateway tools\n\n7 data tools plus a describe_tool gateway\n\nCall-analysis server, 8 tools\n\nICP-planner server, 13 tools\n\nAgent\n\nclaude-opus-5; gpt-5.5\n\nclaude-opus-5\n\nclaude-opus-5\n\nclaude-opus-5\n\nThe tasks\n\nGoogle Ads had 10 tasks in five categories: structure 2, relationship 2, aggregation 4, totals 1 and point in time 1. No prompt names a tool, a field or a query language. Where a count could be read two ways, the prompt says which reading it wants (“at least one impression in the last 30 days”). Seven prompts state the 30-day window, one names a specific day, and the two relationship prompts state neither.\n\nHubSpot had one open-ended revenue question in a user’s own words, typos included: won and lost deals over the last 90 days, trends in deal size and stage, and missing data. Of Avoma‘s ten questions, the four reported here are call analysis: dialer-call counts for a target month and for the month before it (the prior month), the target month’s outbound and inbound split, and which reps made calls.\n\nSalesforce had ten ICP-planning questions in six categories: structure 2, relationship 2, aggregation 3, totals 1, point in time 1 and honesty at scale 1. They are short, in a person’s voice, with absolute dates only, and carry a membership qualifier wherever a count could be read two ways: Type exactly Customer; accounts, not leads; open means any stage other than Closed Won or Closed Lost; closed deals only for win rate; every contact, not a sample. The date question states the org’s timezone. Every prompt ends with “If anything comes back truncated or a tool fails, tell me instead of estimating.” plus the org alias and working directory that the DX server requires.\n\nBefore the Salesforce run we wrote down each trap and the wrong answer it produces:\n\nThe industry that leads on won revenue is not the one that leads on won-deal count.\n\nCounting open deals in the win-rate denominator gives 26.5% and 22.7% instead of 63.8% and 54.7%.\n\nWon deals fall on both boundary days of the date window, so an off-by-one window gives 118, 120 or 122 instead of 121.\n\nThe 2,500 contacts exceed a 1,000-row or 2,000-row read, so a silently truncated read gives 93 or 206 VP contacts instead of 252.\n\nNo question asked for an unfiltered object total, because the Nexla tool descriptions already state those totals. We checked the totals separately (Figure 12).\n\nGround truth\n\nGoogle Ads: the Google Ads API (GAQL, DURING LAST_30_DAYS AND metrics.impressions > 0). We confirmed it against all six Nexla tools: 10 of 10 answers were identical, and every campaign and ad group matched on impressions, clicks and cost. A pre-flight gate confirmed, for each task and server, that the expected answer could be derived from the exact text the harness hands the model (20 of 20).\n\nHubSpot: computed from the synthetic source dataset, independently of both servers.\n\nAvoma: the call figures were counted by a script, with no model in the loop, from the call table behind the Nexla server, read through that server’s own call tool in weekly slices so that no read hit its size cap. Avoma’s own server could not read those records.\n\nSalesforce: SOQL run read-only through the Salesforce CLI, never through either MCP server. A second pass recomputed every expected answer in Python from raw exports of every row, without reusing the derivation SOQL; each export was matched to SELECT COUNT() and to the same count with ALL ROWS. A read-only drift check before the run re-queried the object counts, the total opportunity amount and every expected value. After the run, the counts, latest modification times and amount total were queried again and matched the values recorded at derivation.\n\nGrading\n\nOn Google Ads and Salesforce, claude-opus-5 judged each answer on a 0-1 rubric: 1.0 perfect; 0.8-0.9 minor issues; 0.5-0.7 partial; 0.2-0.4 largely wrong; 0.0-0.1 wrong or no answer. The judge sees the prompt, the expected answer, the final answer, and the names of the tools called with an ok/error flag. It does not see tool outputs. On Salesforce an answer counts as correct at 0.8 or above, and we also checked every trace against the wrong answers listed in advance.\n\nOn Avoma the same model judged on its own rubric (1.0 exact; 0.5-0.9 minor imprecision; 0.1-0.4 attempted but wrong; 0.0 wrong or could not retrieve) and saw only the task, the expected answer and the final answer. A failed judge call left the cell unscored rather than scoring it zero. HubSpot had no judge: we compared the figures in each answer with ground truth directly.\n\nOn Google Ads we show both views of an infrastructure failure. One gpt-5.5 task on the Nexla server never executed because the OpenAI request did not return, so that cell is reported as measured (0.90) and over the nine tasks that executed (1.00). One judge call also failed with HTTP 529 (overloaded) on a recorded claude-opus-5 answer from the Nexla server; we re-judged that answer with the same prompt and it scored 1.0, without re-running the agent.\n\nHarness and models\n\nGoogle Ads and Salesforce ran in mcp-bench, where each cell is one server, one agent, one task and one trial. If an agent there asks a clarifying question before its first tool call, a small model (claude-haiku-4-5) replies from a fixed note about the dataset. HubSpot and Avoma ran in standalone runner scripts with the same loop: list the server’s tools, give them to the model, run each tool call, and repeat until the model answers.\n\nclaude-opus-5 was the agent on all four systems, and gpt-5.5 also ran on Google Ads. claude-opus-5 was the judge wherever we used one. Run caps:\n\nGoogle Ads: 15 iterations, 180 s per task, 5 tasks at a time, output caps of 20,000 tokens (Claude) and 32,000 (OpenAI).\n\nHubSpot: up to 14 model turns, 32,000-token output cap.\n\nAvoma: up to 18 model turns, 16,000-token output cap.\n\nSalesforce: 15 turns, 180 s per task, 90 s per tool call.\n\nNo run sent a system prompt or requested prompt caching. The HubSpot and Avoma runners clipped each tool description to 1,500 characters for both servers. Tokens are the provider-reported input plus output, summed over every turn.\n\nReproduce it\n\nTwo of the four datasets are synthetic, so we can share them.\n\nHubSpot: the synthetic CSV of 1,130 deals, the answer key with its planted effects, the question, and the comparison rule: each figure in an answer is checked against ground truth.\n\nSalesforce: the ten prompts with their expected outputs, tolerance notes and truncation signatures; the ground-truth SOQL; and the seed volumes (500 accounts, 2,500 contacts, 1,500 leads, 2,000 opportunities). TODO: confirm the org-seeding script can be published before the trial org expires.\n\nHarness: mcp-bench, run as mcp-bench run --env claude_api --server <server> --data-system salesforce. TODO: link the public repository.\n\nThe Google Ads and Avoma data is real business data, so we do not publish it. The Google Ads task templates can be shared with identifiers removed. We can also share the rows behind every figure in this post as one JSON file, with internal paths removed, so readers can redo the arithmetic. TODO: link the figure data file.\n\nFrequently asked questions\n\nWhat is an MCP server benchmark, and what did this one measure?\n\nAn MCP server benchmark holds the model, the questions and the data fixed and changes only the MCP server. Here, Nexla’s task-specific servers ran against the vendors’ own servers on Google Ads, HubSpot and Avoma, and on Salesforce we checked the Nexla server’s numbers against Salesforce’s own SOQL. We report correctness against ground truth, tool calls and tokens per task (Google Ads), tokens per question (HubSpot), schema re-sent per turn (HubSpot, Avoma), logged tool errors (Avoma) and the steps to connect an agent (Salesforce).\n\nWhy did the task-specific servers use fewer tokens on Google Ads and HubSpot?\n\nEvery turn re-sends the tool schema and the conversation so far. On Google Ads, the Nexla server is bound to one account and to modeled performance tables, so with claude-opus-5 the agent made 1.0 tool call per task instead of 4.7 and used 10,668 tokens instead of 50,102 (4.7x, uncached). On HubSpot, the first turn alone, tool definitions plus the question, was 3,796 input tokens on the Nexla server against 54,876 on HubSpot’s, and the question took 21,682 tokens against 708,973, or 32.7x (16.1x in the first run of the same comparison, so 16-33x), uncached.\n\nWere the task-specific server’s answers correct?\n\nOn Google Ads it scored 1.00 with claude-opus-5 (Google’s server 0.975, its only shortfall on T4), and Google Ads API ground truth matched all six Nexla tools on 10 of 10 answers. On HubSpot it matched ground truth on closed deals, won/lost split and win rate, as HubSpot’s server did. On Avoma it scored 0.50 on call analysis against 0.00, with the target-month call count and outbound/inbound split exact. On Salesforce, 13 of 13 aggregates matched SOQL, all four object totals were exact, and 9 of 10 ICP questions were correct in the scored run, with the tenth exact on an unscored re-run.\n\nWhat does it take to connect an agent to a Salesforce MCP server?\n\nNexla’s server needs a streamable-HTTP URL and one bearer key, and it connected in about 1 second, with no CLI, local install or OAuth app for the agent builder. Salesforce’s DX MCP server needs the Salesforce CLI, a browser login, a local Node server launched with flags, and the org alias and a working directory on every query call. Salesforce’s hosted MCP server is documented for Enterprise Edition and above, plus Developer Edition; it needs admin activation, an External Client App with OAuth and PKCE, and per-user logins, with access tokens that typically last 2 hours (configurable up to 12).\n\nCan I reproduce these results?\n\nThe synthetic parts, yes. The HubSpot dataset (1,130 synthetic deals) with its answer key, and the Salesforce task set with its SOQL ground truth, can be shared. The harness is mcp-bench (TODO: public repository link before publishing). The Google Ads and Avoma runs used real business data, so we do not publish those datasets.\n\nWhich models ran the benchmark?\n\nclaude-opus-5 was the agent on all four systems, and gpt-5.5 also ran on Google Ads. claude-opus-5 was the judge wherever a judge was used: Google Ads, Avoma and Salesforce. No run sent a system prompt or requested prompt caching.\n\nEach Nexla server in this post was built in MCP Studio by describing the questions it had to answer. You describe the questions your agents need answered, MCP Studio builds a governed, task-specific server, and an agent connects to it with a URL and a key. Start with MCP Studio, or read a short introduction to how it works.\n\nNexla and Snowflake®: Connecting 1,000+ Enterprise Systems to Cortex Agents and the AI Data Cloud\n\nNexla extends the Snowflake AI Data Cloud to more of the enterprise, with connectivity to 1,000+ systems, delivered as data pipelines, zero-copy access, and task-specific MCP servers for Snowflake agents.\n\nHow Nexla’s Task-Specific MCP Server Outperforms Avoma’s MCP Server\n\nWe benchmarked Avoma’s own MCP server against a task-specific Nexla MCP server on call analysis. Nexla returned exact call counts and direction splits, logged 1 errored tool call to Avoma’s 25, and installed with a service key instead of OAuth.", "url": "https://wpnews.pro/news/mcp-server-benchmark-task-specific-servers-on-google-ads-hubspot-avoma-and", "canonical_source": "https://nexla.com/mcp-server-benchmark/", "published_at": "2026-10-21 13:56:14+00:00", "updated_at": "2026-10-21 14:15:11.311839+00:00", "lang": "en", "topics": ["ai-agents", "agent-protocols", "ai-tools", "ai-infrastructure"], "entities": ["Nexla", "MCP Studio", "Google Ads", "HubSpot", "Avoma", "Salesforce", "claude-opus-5", "Salesforce Object Query Language"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/mcp-server-benchmark-task-specific-servers-on-google-ads-hubspot-avoma-and", "markdown": "https://wpnews.pro/news/mcp-server-benchmark-task-specific-servers-on-google-ads-hubspot-avoma-and.md", "text": "https://wpnews.pro/news/mcp-server-benchmark-task-specific-servers-on-google-ads-hubspot-avoma-and.txt", "jsonld": "https://wpnews.pro/news/mcp-server-benchmark-task-specific-servers-on-google-ads-hubspot-avoma-and.jsonld"}}