AI agents and MCP

Marketing MCP setup

Chooses, connects and scopes marketing MCP servers, read-only first, in Claude Code, Claude Desktop, ChatGPT, Codex, Cursor and VS Code. Picks the route (official, export, bridge or reviewed community server), client placement, narrowest identity and scopes and strongest read-only layer per tool, proves each connection with six tests and hands back a stack inventory. Covers HubSpot, Salesforce, GA4, Mixpanel, Amplitude, PostHog, Google Ads, Meta Ads, GTM, Braze, Klaviyo, Intercom, Customer.io, Search Console, BigQuery and Snowflake.

Free, no sign-up. Version 0.2.0, reviewed 6 November 2026.

How to use it

Install it, then ask your agent for the work in plain words. The agent loads the skill when the request matches. Requests like these:

  • Connect HubSpot, GA4 and Google Ads to Claude Code for our weekly pipeline review, read-only, and prove it can't change anything.

  • Our lifecycle team wants Klaviyo in ChatGPT. Set it up so it can report on flows but can't send, suppress or edit anything.

  • Audit which MCP servers are configured on this laptop and in this repo, and tell me which are unofficial, write-capable or holding secrets.

  • Mixpanel MCP signs in but shows no projects. We're on the EU data centre. Fix the connection and test it.

In Claude Code you can also run the slash command /mcp-setup [tools and clients or audit what is connected].

What it needs from you

  • The jobs the connections must do, with one known answer each that you can read in the vendor UI
  • The tools, accounts, workspaces and regions in scope, from martech-context/stack.md if you have it
  • Which clients each person uses (Claude Code, Claude Desktop, ChatGPT, Cursor, VS Code or Codex), which of them decisions.md approves for customer data, and any workspace admin rules
  • Who administers each tool and can enable MCP, change roles or create OAuth apps
  • A sandbox or test account per tool if you want the denied-write test run; otherwise it is marked unproven

What you get back

  • A route decision per tool: official remote, official local, export, bridge or reviewed community server, with the reason
  • Exact read-only connection settings per client, with write tools removed or blocked and new tools denied by default where the client allows, applied by command or handed to you to paste
  • A connection test log per server and client: identity, tool surface, known answer, denied operation, completeness and revocation
  • Scanner findings for configs already on the machine: lookalike or retired servers, inline secrets, missing read-only flags, region mismatches, auto-approved project servers
  • A stack inventory to hand to a colleague, plus proposed updates to martech-context: Agent access lines in stack.md, decisions.md entries, mcp-inventory.md, mcp-tools/ snapshots and a README.md line naming them. Nothing is written without approval.

Install

Each block downloads the skill folder and unzips it where that agent looks for skills. Restart the agent afterwards.

Claude Code
mkdir -p ~/.claude/skills
curl -sL https://www.martechdevs.com/downloads/skills/marketing-mcp-setup.zip -o /tmp/marketing-mcp-setup.zip
unzip -oq /tmp/marketing-mcp-setup.zip -d ~/.claude/skills
mkdir -p ~/.claude/commands
curl -sL https://www.martechdevs.com/downloads/commands/mcp-setup.md -o ~/.claude/commands/mcp-setup.md
Codex
mkdir -p ~/.agents/skills
curl -sL https://www.martechdevs.com/downloads/skills/marketing-mcp-setup.zip -o /tmp/marketing-mcp-setup.zip
unzip -oq /tmp/marketing-mcp-setup.zip -d ~/.agents/skills
Cursor
mkdir -p ~/.cursor/skills
curl -sL https://www.martechdevs.com/downloads/skills/marketing-mcp-setup.zip -o /tmp/marketing-mcp-setup.zip
unzip -oq /tmp/marketing-mcp-setup.zip -d ~/.cursor/skills
Any agent, with the skills CLI
npx skills add https://www.martechdevs.com --skill marketing-mcp-setup

The skill

The full SKILL.md, as the agent reads it.

Connects an AI client to the marketing stack one MCP server at a time, read-only first, proves each connection with six tests and ends in a stack inventory a colleague can audit. It never writes to a production vendor system or handles credentials; its only write attempts are the harmless T4 tests in a sandbox the user names.

When to use

Use this skill when:

  • Someone wants a CRM, analytics, ads, lifecycle, SEO or warehouse tool connected to an AI client over MCP, or is choosing between a vendor server, a community server, a bridge or an export.
  • A connection must become read-only, nobody knows what it can change, it shows the wrong account, region, no projects or no tools, or a vendor update, scope reinstall or new client changed what it exposes.
  • Someone asks which MCP servers are configured on a machine, in a repository or in a team workspace, or an employee or agency leaves.

Use something else when:

  • The agent will change anything through the connection (pause, edit, send, publish, merge, delete): agent-write-safety.
  • Judging a server's code and publisher: mcp-security-review if installed; until then the publisher review in references/choosing-servers.md is the gate.
  • Auditing a GTM container: gtm-container-audit. Building an MCP server over warehouse models: warehouse-and-internal-mcp if installed.
  • Creating martech-context/ from scratch: marketing-context-kit. This skill only proposes the martech-context updates listed in step 9.

Inputs

Read these first if they exist (assets/example-acme-stack.md shows the fields): martech-context/stack.md (tools, account IDs, regions, owners, current Agent access lines), decisions.md (clients approved for customer data, standing restrictions) and metrics.md (definitions behind each known answer).

Then gather:

  • One to five jobs, each with its system of record and one known answer readable in the vendor UI (a closed-period delivery value or one record).
  • Who uses which client, on which plan or workspace, whether an org admin controls connectors, and the admin per tool who can enable MCP, change roles or create OAuth apps.
  • A sandbox or test account per tool for the denied-write test, or "none".

Never ask for, accept or repeat tokens, API keys, client secrets or service account files; if one is pasted, tell the user its owner should rotate it.

Procedure

1. Fix the jobs before the tools

  • No job, no connection. Each job names the question, the system of record and a known answer.
  • First pilot: at most three servers, each with every write tool absent, Blocked or denied at the source by step 6 before first use; a credential recorded as write-capable is fine when no write tool is reachable.
  • Each person connects and tests one server at a time and starts the next only after T1 to T4 pass. Connections found in step 2 are remediation: keep, fix or remove them one server per person at a time.

2. Inventory what is already connected

python3 -I scripts/mcp_inventory.py --discover --project ~/work/acme-marketing --expect-region mixpanel=eu
  • Run from the skill folder. It reads each client's config and settings files and any paths you pass, matches servers against assets/server-registry.json and prints a redacted inventory with findings S01 to S15 (references/failure-modes.md); exit 1 means a FAIL, exit 2 an unreadable file. Always pass --project <repository>: the default is the current directory. --all-projects adds every repository listed in the terminal agent's user config.
  • Never open or paste client config files into the conversation; they can hold tokens. Without Python, record "scanner not run, because ...".
  • Chat-app connectors, ChatGPT plugins, plugin-provided servers and desktop extensions are not in config files: list them from the terminal agent's /mcp and each app's settings.

3. Choose the route per tool

Take the first rung that covers the job:

  1. Vendor-hosted remote server.
  2. Vendor-published local server.
  3. Export or warehouse path: GTM container export, Search Console bulk export to BigQuery, GA4 BigQuery export.
  4. A reporting bridge the team already licenses, with its write tools off.
  5. A community server that passes the publisher review: not archived, a release or commit in the last 90 days, an OSI licence, a pinned install, a read-only option, documented token storage.
  • Never connect production credentials to an unreviewed community server, or to a third-party host using the name of a vendor that publishes its own server.
  • With mcp-security-review installed, run it before step 7 for rungs 4 and 5 and any failed publisher review; NO-GO stops the connection.
  • Routes and traps per tool: CRM, analytics, ads, lifecycle, SEO and warehouse; retired servers: references/choosing-servers.md.

4. Place it in the right client

  • Remote is required when any user works in a web, mobile or cloud-hosted client. Self-host a local server (Google documents Cloud Run for Google Ads and GA4) only when two or more such users need it and someone owns the deployment.
  • Chat-app connectors call vendors from the provider's cloud, so IP allowlists (Braze) and network policies (Snowflake) block them.
  • CRM, lifecycle and support servers go only into a client or workspace that decisions.md approves for customer data; otherwise draft the request for the privacy owner and stop for that tool.
  • Personal connections stay in personal scope; a shared project file holds only servers read-only by an enforced layer, with secrets as environment references (non-interactive runs load project servers without a prompt).
  • OAuth that accepts only registered web callbacks (Google Cloud remote MCP, some Salesforce setups): add the connector in the chat app; references/clients.md says which terminal agent can inherit it and when.
  • Agencies: one project folder or profile per client account. Name servers <vendor>-<account>-<env>-<mode>, for example klaviyo-acme-prod-ro.

5. Choose the identity and scopes

  • Connect as the person who does the job, with the lowest role that passes T3; never an admin: add the one missing permission instead.
  • Request read scopes where the vendor offers them (Customer.io read, Google OAuth scopes, a Search Console --read-only login). Where scopes are fixed (HubSpot, Google Ads adwords, BigQuery bigquery, Stape's hosted GTM endpoint), enforce through role, IAM or client blocks and record the credential as write-capable.
  • Record granted scopes from the auth-status tool or consent screen, not the request. Unattended jobs get their own read-only identity with a named owner. Vendor detail, Google token expiry and custody: references/identity-and-scopes.md.

6. Enforce read-only below the prompt

Strongest layer per tool, checked 2026-11-06:

  • HubSpot: View-only user with Create off, plus a client allowlist of read tools (View users can still create notes and tasks); with no allowlist, block manage_* and submit_feedback.
  • Salesforce: the sobject-reads endpoint only.
  • GA4: never --allow-write or ANALYTICS_MCP_ALLOW_WRITE; mint the credential with analytics.readonly.
  • Mixpanel: a project role without write, plus client blocks.
  • Amplitude: Viewer (or an Enterprise custom role with Use MCP (read) only) plus a client allowlist; Member, Manager and Admin write by default.
  • PostHog: readonly=true&project_id=<id>&mode=tools on the URL.
  • Google Ads: labels: false and assets: false in a tools config named by GOOGLE_ADS_MCP_TOOLS_CONFIG (the default lists four write tools); a dedicated or unattended identity gets Read-only account access, so its adwords token cannot edit that account; otherwise record the credential as write-capable.
  • Meta Ads: ads_mcp_management plus ads_read, never ads_management; for a dedicated identity, also a reporting-only ad account role.
  • GTM: the export JSON, or Read permission with tagmanager.readonly (gtm-container-audit).
  • Braze: a dashboard user without edit rights, plus Use MCP Server.
  • Klaviyo: read-only=true&disable-tools-with-user-generated-content=true on a custom connector (directory connectors ignore it), or the local server with a read-scoped key and READ_ONLY=true.
  • Intercom: block add_internal_note, create_article, update_article and the Fin Operator tools.
  • Customer.io: the default read scope only; live-data and sensitive-data toggles off.
  • Search Console: the bulk export to BigQuery; a community server only with a --read-only login and GSC_ENABLE_WRITES=0.
  • BigQuery: an IAM deny on tools not marked read-only (execute_sql, cancel_job); Data Viewer on approved datasets only.
  • Snowflake: the read_only SQL tool and a SELECT-only MCP_READER set as the user's default role, alone in ALLOWED_ROLES_LIST.

Then in the client:

  • Prefer controls that deny new tools by default (a read-tool allowlist, a glob deny on write verbs, the setting for tools added later, a Blocked write-and-delete category): a list of today's write tools misses tomorrow's.
  • Write tools are Needs approval or Blocked, never always allowed; never remember an approval for a write tool.
  • Mark each tool U (reads outsider text: CRM notes, reviews, conversations, ad copy), P (private data) or S (sends data out); if one profile holds all three, split the job into two sessions with a human hand-off.
  • If only the client layer exists, tell the user the read-only pass depends on the agent not calling write tools, and record the date.

7. Connect

  • Prepare the change from assets/read-only-snippets.md; apply it only after the user approves, through the client's own command or settings screen where one exists (the terminal agents' mcp add and mcp remove, /permissions, connector settings). For a file with no command (Cursor, desktop app or VS Code JSON, Codex keys such as enabled_tools), give the user the block and file path to paste; never read the file into the conversation. Re-run the scanner on every changed file.
  • Admin changes (org MCP switches, roles, OAuth apps, IAM deny policies, Snowflake users and integrations) go to the admin as a draft.
  • The user completes every sign-in and consent screen, after checking the account and company shown.

8. Test every server in every client

Run T1 to T6 per server and client and log each in assets/connection-test-log.csv; per-vendor calls, caps and evidence sources: references/connection-tests.md.

  • T1 identity: the identity call returns the account ID in stack.md; a mismatch is FAIL. More accounts than the job needs is WARN; another client's production account is FAIL.
  • T2 tool surface: the tool list matches the expected read-only surface; save it as the drift baseline. A list of only an exec or discovery tool hides the tools: switch to tools mode first.
  • T3 known answer: a delivery metric (spend, impressions, clicks, sends, sessions) or a record field for a closed period ending at least three full days ago, in the account's time zone and currency, matching exactly; an analytics difference passes only when traced to a named definition difference. Never use conversions or attributed revenue.
  • T4 denied operation: an out-of-scope read fails without substitution, and a harmless write in the named sandbox is denied or the tool is absent. Get the user's go-ahead for the exact call, record and sandbox; match production's role and block rules, or record the layer as not proved. A write that succeeds is FAIL: stop and hand the object's removal to the user. Never test with a delete, send, launch, publish or spend change; a refusal without a tool call proves nothing. No sandbox: UNPROVEN, an open risk.
  • T5 completeness: a request larger than one page states pagination or truncation.
  • T6 revocation: who revokes, how, and one disconnect and reconnect during the pilot.
  • For a client you are not running in, give the user a numbered test script (exact prompt, expected value, what to copy back) and log their answers with tester_role; a test they cannot run is UNPROVEN.

A server counts as connected only when T1 is PASS (or WARN with a dated narrowing request), T2 and T3 are PASS, and T4 is PASS or UNPROVEN with a reason. Results expire after 30 days.

9. Hand over the inventory

python3 -I scripts/mcp_inventory_check.py ~/scratch/mcp-inventory.md
  • Fill assets/stack-inventory-template.md in a scratch file outside martech-context/, one block per server, environment and client, and run the check (omit --as-of on live runs). Exit 1 lists missing labels, placeholders and stale or failed tests.
  • Propose: the inventory as martech-context/mcp-inventory.md, one Agent access line per tool in stack.md, a decisions.md entry per approved connection, tool snapshots in martech-context/mcp-tools/ and a README line under Optional files present naming both. Write nothing until the owner approves.

10. Keep it current

python3 -I scripts/mcp_tools_diff.py current.json --baseline baseline.json --mode ro
  • Build current.json like assets/example-acme-tools-current.json: tool names only, never results. Mark tools the client blocks "blocked": true and tools a source layer denied in T4 "denied_by" (role, iam, grant, scope or server).
  • Re-test on any trigger in references/connection-tests.md. Offboarding someone triggers every T6 revoke step for their identities.

Common failure modes

  • Write tools on by default or a read-only setting that does nothing (the HubSpot connector, a Meta grant with ads_management, Amplitude Member and above, Klaviyo parameters on a directory connector, Google Ads on its bundled config). Detect: T2.
  • Tools hidden behind one exec or discovery tool (PostHog CLI mode, Amplitude progressive discovery). Detect: the T2 list.
  • Wrong account or region; lookalike, retired or shadowed servers; truncated results read as totals. Detect: T1; scanner S01, S02, S07, S10; T5.

Full list with fixes: references/failure-modes.md.

Worked example

Acme Co is fictional: its stack.md and six configs from three laptops in assets/example-acme-client-configs.json.

python3 -I scripts/mcp_inventory.py --fixture assets/example-acme-client-configs.json \
  --expect-region mixpanel=eu --as-of 2026-11-01

It ends Summary: 12 FAIL, 9 WARN, 3 INFO, 8 PASS: a HubSpot lookalike bridge (S01), a shared Klaviyo entry without read-only=true shadowed for one person (S06, S10, S11). The fixed configs scan 0 FAIL, 0 WARN, 2 INFO, 6 PASS, and assets/example-acme-inventory.md passes the check. Decisions, tests, drift: references/worked-example.md.

Acceptance checks

  • Jobs: every connected server maps to a job with a recorded known answer. Pass: no server without a job.
  • Existing configs: the scanner ran, or the inventory says why not; every finding has keep, fix or remove. Pass: no unresolved FAIL.
  • Route: each server records its route and reason; community servers carry a dated publisher review. Pass: no unreviewed community server, lookalike host or retired endpoint.
  • Identity: role, reachable accounts and granted scopes come from the auth-status tool or consent screen. Pass: no unexplained admin identity; no other client's production account reachable.
  • Read-only: each server names its enforcing layer, the exact setting and the proof (tool list compared, or a denied test). Pass: nothing relies on prompt text; client-only layers are labelled, with the date the user was told.
  • Tests: every server and client pair meets the T1 to T4 rule, T5 is PASS or its limits are recorded, T6 is documented, all within 30 days. Pass: scripts/mcp_inventory_check.py exits 0.
  • Secrets: no token, key or secret in chat, config, inventory or a committed file. Pass: S03, S04 and S12 clean on the final configs.
  • Client approvals: write tools are Blocked or Needs approval, new tools denied by default where the client allows, and CRM, lifecycle and support servers sit only in clients approved in decisions.md. Pass: no write tool always allowed or allowlisted; each of those servers cites its approval date.
  • Drift baseline: a tool snapshot per server and client is proposed for martech-context/mcp-tools/. Pass: scripts/mcp_tools_diff.py <snapshot> --mode ro exits 0.
  • Safety: no write, send, publish, delete or spend call ran outside the T4 sandbox tests, and the agent changed no admin setting. Pass: the call log shows reads, the user's sign-ins and only T4 attempts in named sandboxes, each denied or absent, confirmed in the source's own records where they exist; martech-context/ changes have a recorded approval.

Boundaries

  • Read-only, apart from the T4 denied-write tests in a named sandbox; never a delete, send, launch, publish or spend change. Roles, org connector settings, OAuth apps, IAM and warehouse grants leave as drafts for the admin.
  • Never asks for, prints or stores credentials.
  • A publisher review is a gate, not a security audit. AI provider data terms and customer-data approval belong to the privacy or security owner.
  • Hand-offs: writes to agent-write-safety; server trust to mcp-security-review when installed; GTM reads to gtm-container-audit; context files to marketing-context-kit; custom servers to warehouse-and-internal-mcp when installed.
  • Official read-only modes per tool: step 6.
  • Vendor setup skills: Mixpanel's install skill (mixpanel/ai-plugins), dbt's configuring-dbt-mcp-server (dbt-labs/dbt-agent-skills), the PostHog wizard, Customer.io plugins, HubSpot's connectors. Skip the developer token in Google's google-ads-api-mcp-setup (sunset 2026-09-09).

Live docs

Platform settings, limits and menu paths change. Before stating any parameter name, limit, quota or UI path:

  • Fetch the current page from the vendor docs MCP server or llms.txt listed in sources.yaml, or open the canonical URL.
  • If the live page disagrees with this skill, follow the live page and tell the user what changed.
  • Cite the URL you used.

Most used: the HubSpot, Klaviyo, Amplitude, PostHog and Meta Ads MCP pages, the Google Ads and GA4 repositories, the terminal agent's MCP and permissions pages, Google Cloud's MCP deny page and Salesforce hosted servers. Checked 2026-11-01, changed servers and clients 2026-11-06. developer.salesforce.com and help.openai.com refuse automated fetches; some help.salesforce.com pages return an error shell, so read those in a browser.

Files in this skill

Want it set up for you? See implementation plans or book a free call.