GTM MCP Server
This server lets an AI agent research companies and contacts, query the CRM, and safely write contacts to it — with writes off by default and every attempt audited.
Company research:
search_companyenriches firmographic data from a domain or name, with one provider call per invocation.Contact research:
search_contactresolves one named person at a company (no title-based search).CRM lookup:
crm_queryreads CRM data with bounded, typed filters; read-only and emits no audit event.Guarded CRM write:
sync_to_crmupserts one contact, but is disabled by default, supports dry-run, never clears populated fields, and always writes an audit event.List management:
save_to_listadds an existing contact to a named list; repeating the same add reportsunchanged, not a duplicate.Server status:
server_inforeports implemented vs. planned capabilities, database availability, and whether write tools are enabled or in dry-run mode.
Provides a PostgreSQL-backed mock CRM backend, enabling the server's CRM query and write tools to read and upsert CRM records stored in PostgreSQL.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@GTM MCP ServerEnrich Acme Corp and add their VP of Sales to my target list"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
GTM MCP Server
An MCP server that lets an AI agent research a company, find the right contact, and safely sync that work into a CRM — with writes off by default, a dry-run mode, and every attempt audited. MCP is the protocol Claude (and other AI clients) use to call external tools, so this server plugs go-to-market work — enrichment, CRM lookup, guarded CRM writes — directly into an agent's tool set instead of a human copying data between tabs.
Demo
Live Claude Code session using the GTM MCP server:

Claude calling the GTM tools directly — enrichment, CRM lookup, a guarded write — over live tool calls against offline/synthetic sample data, not a real company or CRM.
Related MCP server: AgentsGate
MCP Tools
Tool | Read/Write | Purpose | Safety behavior |
| read | Reports capabilities, configured provider, and current guardrail settings | — |
| read | Firmographic enrichment from a domain or name | One provider call per invocation; never retries a rejection or guesses a domain |
| read | People enrichment from a name and company | Same cost discipline; resolves one named person, not a title |
| read | Query the CRM with bounded, typed filters | No provider cost; emits no audit event (nothing mutated) |
| write | Upsert one contact into the CRM | Disabled by default ( |
| write | Add an existing contact to a named list | Same guardrails as above; adding twice reports |
Write tools stay listed even when disabled — a refusal is audited, not hidden.
Architecture
MCP client (Claude Desktop / Claude Code / Inspector)
│ JSON-RPC over stdio
▼
tools/ schemas from types, annotations, no business logic
▼
services/ EnrichmentService, CrmService — guardrails live here
▼
ports.py CompanyEnrichmentProvider, CrmRepository (no delete method)
▼
adapters/ providers/ (hunter live, sample) · crm/ (Postgres)Dependencies point inward only; only the tool layer imports mcp. Swapping an enrichment
vendor or the CRM backend is one new adapter, with no tool change. Details in
ARCHITECTURE.md and DECISIONS.md.
Guardrails
Enforced by tests, not just documented:
Writes disabled by default — every mutation returns
rejected, not silently skipped.Dry-run mode — full validation runs, then the write returns
dry_runwithout persisting.Bounded and idempotent — one record per call by default; repeating a write reports
unchanged.No delete path, ever — no delete method exists on the CRM port.
Audit trail — every write attempt, including rejections, produces one audit event.
CRM wins conflicts — a field omitted from a submission is never cleared.
Tech Stack
Python 3.13 · MCP SDK v2 · Pydantic · SQLAlchemy · PostgreSQL · pytest · ruff · mypy
Evaluation
The harness in eval/ measures whether an agent uses these tools correctly:
right tool, right order, respecting the read/write boundary, never claiming a write happened
when it did not. Two modes, reported separately:
Deterministic (28 scripted scenarios, offline provider): 28/28 passed, 100% composite.
Live-agent (12 scenarios, Claude Code driving a real model over real MCP): 10/12 passed, 91.2% composite.
Axis | Score |
Safety interpretation | 95.8% |
Read/write policy adherence | 100% |
Tool selection | 79.2% |
Sequence accuracy | 100% |
Efficiency | 89.6% |
Final response | 62.5% |
What held across every run: no false success claim, ever. Rejected, dry-run, and failed writes were all reported as not done.
Run with uv run python -m eval.runner (deterministic) or uv run python -m eval.live (live, costs money).
Quick Start
Requires uv and Docker (for the mock CRM database).
git clone https://github.com/vivz-git/Gtm-Mcp-Server && cd Gtm-Mcp-Server
uv sync --extra dev
cp .env.example .env
docker compose up -d --wait db
uv run alembic upgrade head
uv run python -m scripts.seed # 6 companies, 14 contacts, 3 lists — all synthetic
uv run pytest -m "not integration"
uv run gtm-mcp-server # starts on stdio, waits for a clientNo API key is required: the default provider is a synthetic dataset committed to this repo.
Claude Code usage
The launch contract is committed as .mcp.json — a fresh clone needs no editing.
Start claude from the repository root and approve the project-scoped server when prompted.
Then ask the agent "what GTM capabilities do you have?" or "tell me about cloudscale.io."
Testing
uv run ruff check . # lint
uv run ruff format --check . # formatting
uv run mypy --strict # type checking
uv run pytest -m "not integration" # unit + mcp + e2e (integration needs `docker compose up -d db`)
uv run python -m eval.runner # deterministic evaluation, outside the pytest gate357 tests pass in the standard gate, exercised through a real in-memory MCP Client session
rather than calling Python functions directly, so schema derivation and annotations are covered.
Known Limitations
Default data is synthetic unless a live provider key is configured.
Live enrichment is domain-only, metered, and cannot resolve a company by name.
search_contactresolves one named person per call — no search by title.sync_to_crmhandles contacts only; an enriched company cannot yet be persisted.List membership is additive only — no way to remove a contact.
Live evaluation is one model, one day, twelve scenarios — not a reliability guarantee.
License
MIT
Available Tools
1 toolserver_infoGTM server statusARead-onlyIdempotent
Report which GTM capabilities this server can currently perform.
Call this first when you are unsure whether a GTM capability is available, or when a data-modifying call has failed and you need to know whether writes are disabled. It takes no arguments, reads no customer data, and changes nothing.
Returns which tools are implemented versus merely planned, whether the CRM database is reachable, and whether write tools are permitted to modify data. Do not call tools listed under planned capabilities; they are not registered and the call will fail.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| version | Yes | Server package version. |
| environment | Yes | Environment the server is running in. |
| server_name | Yes | Configured name of this server. |
| dry_run_writes | Yes | When true, write tools validate and audit but never persist changes. |
| database_available | Yes | Whether the CRM database is reachable. CRM tools fail when false. |
| write_tools_enabled | Yes | Whether write tools may modify data. When false they refuse every call. |
| planned_capabilities | Yes | GTM capabilities that are designed but not yet callable. Do not attempt to call these. |
| implemented_capabilities | Yes | GTM capabilities that are implemented and callable right now. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, but the description adds valuable context: it takes no arguments, reads no customer data, changes nothing, and returns specific status categories. There is no contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, front-loaded with the core purpose, and every sentence adds value. It avoids redundancy, clearly separates what the tool returns from when to use it, and is appropriately sized for the tool's simplicity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, no parameters, and annotations covering safety traits, the description covers all necessary context: when to call it, what it returns, and what not to do. Nothing important is missing for an agent to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, and the description explicitly states it takes no arguments, which is sufficient. With no parameters to document, the description does not need to add parameter semantics beyond confirming the absence of inputs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Report which GTM capabilities this server can currently perform.' It clearly identifies the tool's function and is not a tautology of its name or title. Even without siblings, it is unambiguous about what the tool does.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly tells the agent when to call this tool: first when unsure about capability availability, or after a data-modifying call fails to check whether writes are disabled. It also advises against calling tools listed under planned capabilities, providing actionable routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
1 tool update
v0.1.0- First observed
server_info
TDQS
Scored across 1 tool
With only one tool, there is no possibility of confusion between tools. The server_info tool has a clear and singular purpose, so disambiguation is trivially perfect.
The single tool is named server_info, which follows a clear noun_noun pattern. With only one tool there are no inconsistencies to evaluate, so naming is internally consistent.
A server titled 'GTM MCP Server' would be expected to expose a range of GTM operations, but it exposes only a single information reporting tool. This falls at the 'too few' end of the scale for the apparent scope.
The server provides no tools for actual GTM management—no operations for tags, triggers, variables, containers, or any data modification. It only reports capabilities, leaving the domain severely uncovered.
Maintenance
Related MCP Connectors
Let AI agents query data and act across all your business apps via MCP.
Unified MCP Server is a remote MCP connector for AI agents and vertical AI products that provides access to 22,000+ authorized SaaS tools across 400+ integrations and 24 categories directly inside LLMs (Claude, GPT, Gemini, Cohere). Tools operate only on explicitly authorized customer connections, enabling agents to safely read and write against live third-party systems.
Pay-per-use tool marketplace for AI agents. Search, price-check, and call APIs via MCP.
Zero-setup MCP gateway securely connecting AI to your tools with authentication and workflows
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to access a unified catalog of tools from various APIs (OpenAPI, GraphQL, MCP, Google Discovery) through the MCP protocol.MIT

AgentsGateofficial
AlicenseNot gradedqualityAmaintenanceEnables AI agents to securely call MCP tools with risk scoring, checkpoints, rollback, and approval workflows.6 npmMIT- FlicenseNot gradedqualityCmaintenanceAn MCP-native CRM backend for AI agents, enabling customer, opportunity, note, follow-up, and pipeline health management through 15 MCP tools.-
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to interact with multiple CRM systems through a unified set of MCP tools, such as finding contacts, accounts, and deals, while supporting mock, REST, and vendor-specific backends.MIT