GTM Otto
What this MCP does
Sources LinkedIn prospects, manages ICPs and sourcing lanes, drafts outreach, and executes approved prospecting actions.
Tools
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['approvalId'], 'properties': {'approvalId': {'type': 'string', 'description': 'The card to approve.'}}, 'additionalProperties': False}
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['playId', 'key', 'config'], 'properties': {'on': {'type': 'boolean', 'description': 'Also switch the lane on/off. Omit to leave the switch alone.'}, 'key': {'enum': ['people_search', 'competitor_posts', 'job_offers', 'account_list', 'post_engagers'], 'type': 'string', 'description': "Which lane. people_search: LinkedIn people search compiled from the play's ICP (+ optional free-text keywords). | competitor_posts: Post discovery: Otto searches LinkedIn daily for posts matching an intent, judges each, and takes who engaged. | job_offers: Hiring signal: companies posting a role â\x86\x92 the buyers inside them. | account_list: Companies you name (names, websites or LinkedIn page URLs) â\x86\x92 Otto finds your buyers inside each. | post_engagers: RETIRED â\x80\x94 folded into competitor_posts.postUrls. Still runs on rows that exist; do not configure it on new plays."}, 'config': {'type': 'object', 'properties': {'intent': {'type': 'string', 'maxLength': 1000, 'description': "competitor_posts only. What you are hunting, in the operator's own words and language â\x80\x94 e.g. 'people struggling with manual LinkedIn prospecting'. Drives the search writer, the post scorer and the comment scorer."}, 'fitGate': {'enum': ['strict', 'standard', 'loose', 'off'], 'type': 'string', 'description': "How the ICP facets LinkedIn could not filter on are judged per person: strict = every unmapped facet must match; standard (default) = one match is enough; loose = role/seniority only (best for engager lanes); off = keep everyone the query returned. The ICP's `exclude` list is absolute at every level."}, 'keywords': {'type': 'string', 'description': "people_search: extra free-text terms on top of the ICP query (alone, a complete search). job_offers: the role being hired, e.g. 'Head of Sales'."}, 'postGate': {'anyOf': [{'type': 'number', 'maximum': 100, 'minimum': 0}, {'type': 'null'}], 'description': 'competitor_posts: post-relevance floor 0â\x80\x93100, or null for OFF (the default). 0 is not off â\x80\x94 it still demands a model verdict.'}, 'postUrls': {'type': 'array', 'items': {'type': 'string'}, 'description': 'competitor_posts (and retired post_engagers): LinkedIn post URLs or urn:li:activity:â\x80¦ URNs to harvest as they are. Max 25.'}, 'reactors': {'type': 'boolean', 'description': 'Post lanes: take the people who reacted (default true). Both off = refused.'}, 'companies': {'type': 'array', 'items': {'type': 'string'}, 'description': "account_list only. One entry per company â\x80\x94 a name ('Acme'), a website ('acme.io') or a LinkedIn page URL ('linkedin.com/company/acme-corp'). Max 100."}, 'commenters': {'type': 'boolean', 'description': 'Post lanes: take the people who commented (default true).'}, 'intentGate': {'anyOf': [{'type': 'number', 'maximum': 100, 'minimum': 0}, {'type': 'null'}], 'description': 'Post lanes: per-person intent (scored from their comment against `intent`) floor 0â\x80\x93100, or null for OFF (the default). 0 is not off â\x80\x94 it still demands a model verdict.'}, 'competitors': {'type': 'array', 'items': {'type': 'string'}, 'description': "competitor_posts only. Keyword ANCHORS â\x80\x94 tools, brands, chores ('Sales Navigator', 'Waalaxy', 'prospects froids'). The fallback searches when no intent is set. Max 25."}, 'minReactions': {'type': ['number', 'null'], 'description': "competitor_posts: reaction floor for FOUND posts ('skip the posts nobody saw'); null = any post. The UI offers 25/50/100/250."}, 'postedWithinDays': {'type': ['number', 'null'], 'description': 'job_offers: how fresh the posting must be, in days; null = any.'}}, 'description': 'The fields to change. See gtm_sources_reference.', 'additionalProperties': False}, 'playId': {'type': 'string', 'description': 'The play, from gtm_list_plays.'}, 'listMode': {'enum': ['replace', 'append'], 'type': 'string', 'description': 'How list fields combine with the current value. Default replace.'}}, 'additionalProperties': False}
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['playId'], 'properties': {'playId': {'type': 'string', 'description': 'The play to bind the seat to.'}}, 'additionalProperties': False}
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['name'], 'properties': {'icp': {'type': 'object', 'properties': {'sizes': {'type': 'array', 'items': {'type': 'string'}}, 'titles': {'type': 'array', 'items': {'type': 'string'}}, 'exclude': {'type': 'array', 'items': {'type': 'string'}}, 'languages': {'type': 'array', 'items': {'type': 'string'}}, 'locations': {'type': 'array', 'items': {'type': 'string'}}, 'seniority': {'type': 'array', 'items': {'type': 'string'}}, 'industries': {'type': 'array', 'items': {'type': 'string'}}}, 'description': "The audience, as plain strings â\x80\x94 the same seven fields the cockpit's ICP screen fills. gtmotto compiles them into a LinkedIn search and normalises odd labels itself ('Swiss' â\x86\x92 Switzerland, 'Fintech' â\x86\x92 Financial Services).", 'additionalProperties': False}, 'goal': {'type': 'string', 'description': 'What a conversation from this play should reach.'}, 'name': {'type': 'string', 'description': "The play's name."}, 'voice': {'type': 'string', 'description': 'How the messages should sound.'}, 'sources': {'type': 'array', 'items': {'type': 'object', 'required': ['key'], 'properties': {'on': {'type': 'boolean'}, 'key': {'enum': ['people_search', 'competitor_posts', 'job_offers', 'account_list', 'post_engagers'], 'type': 'string', 'description': "people_search: LinkedIn people search compiled from the play's ICP (+ optional free-text keywords). | competitor_posts: Post discovery: Otto searches LinkedIn daily for posts matching an intent, judges each, and takes who engaged. | job_offers: Hiring signal: companies posting a role â\x86\x92 the buyers inside them. | account_list: Companies you name (names, websites or LinkedIn page URLs) â\x86\x92 Otto finds your buyers inside each. | post_engagers: RETIRED â\x80\x94 folded into competitor_posts.postUrls. Still runs on rows that exist; do not configure it on new plays."}, 'config': {'type': 'object', 'properties': {'intent': {'type': 'string', 'maxLength': 1000, 'description': "competitor_posts only. What you are hunting, in the operator's own words and language â\x80\x94 e.g. 'people struggling with manual LinkedIn prospecting'. Drives the search writer, the post scorer and the comment scorer."}, 'fitGate': {'enum': ['strict', 'standard', 'loose', 'off'], 'type': 'string', 'description': "How the ICP facets LinkedIn could not filter on are judged per person: strict = every unmapped facet must match; standard (default) = one match is enough; loose = role/seniority only (best for engager lanes); off = keep everyone the query returned. The ICP's `exclude` list is absolute at every level."}, 'keywords': {'type': 'string', 'description': "people_search: extra free-text terms on top of the ICP query (alone, a complete search). job_offers: the role being hired, e.g. 'Head of Sales'."}, 'postGate': {'anyOf': [{'type': 'number', 'maximum': 100, 'minimum': 0}, {'type': 'null'}], 'description': 'competitor_posts: post-relevance floor 0â\x80\x93100, or null for OFF (the default). 0 is not off â\x80\x94 it still demands a model verdict.'}, 'postUrls': {'type': 'array', 'items': {'type': 'string'}, 'description': 'competitor_posts (and retired post_engagers): LinkedIn post URLs or urn:li:activity:â\x80¦ URNs to harvest as they are. Max 25.'}, 'reactors': {'type': 'boolean', 'description': 'Post lanes: take the people who reacted (default true). Both off = refused.'}, 'companies': {'type': 'array', 'items': {'type': 'string'}, 'description': "account_list only. One entry per company â\x80\x94 a name ('Acme'), a website ('acme.io') or a LinkedIn page URL ('linkedin.com/company/acme-corp'). Max 100."}, 'commenters': {'type': 'boolean', 'description': 'Post lanes: take the people who commented (default true).'}, 'intentGate': {'anyOf': [{'type': 'number', 'maximum': 100, 'minimum': 0}, {'type': 'null'}], 'description': 'Post lanes: per-person intent (scored from their comment against `intent`) floor 0â\x80\x93100, or null for OFF (the default). 0 is not off â\x80\x94 it still demands a model verdict.'}, 'competitors': {'type': 'array', 'items': {'type': 'string'}, 'description': "competitor_posts only. Keyword ANCHORS â\x80\x94 tools, brands, chores ('Sales Navigator', 'Waalaxy', 'prospects froids'). The fallback searches when no intent is set. Max 25."}, 'minReactions': {'type': ['number', 'null'], 'description': "competitor_posts: reaction floor for FOUND posts ('skip the posts nobody saw'); null = any post. The UI offers 25/50/100/250."}, 'postedWithinDays': {'type': ['number', 'null'], 'description': 'job_offers: how fresh the posting must be, in days; null = any.'}}, 'additionalProperties': False}}, 'additionalProperties': False}, 'description': 'The sourcing lanes to configure.'}, 'activate': {'type': 'boolean', 'description': 'Default false. True only starts it if a live seat is already connected.'}, 'autonomy': {'type': 'array', 'items': {'type': 'object', 'required': ['key', 'auto'], 'properties': {'key': {'enum': ['visit', 'like', 'comment', 'invite', 'first_dm', 'follow_up', 'reply'], 'type': 'string'}, 'auto': {'type': 'boolean'}}, 'additionalProperties': False}, 'description': 'Only the rungs you name are written. Omitted rungs wait for a human.'}, 'dailyCap': {'type': 'number', 'description': "Actions per day, all kinds summed. Defaults to the seat's full LinkedIn allowance (145), so pass it only to throttle. ACCOUNT-level: sets the ceiling every play on this LinkedIn account shares, not a per-play budget."}, 'productId': {'type': 'string', 'description': 'An existing product. Omit to create one.'}, 'websiteUrl': {'type': 'string', 'description': 'Seeds a NEW product from this website and kicks its research.'}, 'productName': {'type': 'string', 'description': "Defaults to the website's hostname."}, 'workingHours': {'type': 'object', 'required': ['start', 'end', 'tz'], 'properties': {'tz': {'type': 'string'}, 'end': {'type': 'string'}, 'start': {'type': 'string'}}, 'description': "e.g. { start: '09:00', end: '18:00', tz: 'Europe/Paris' }. ACCOUNT-level, like dailyCap.", 'additionalProperties': False}}, 'additionalProperties': False}
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'sizes': {'type': 'array', 'items': {'type': 'string'}, 'description': "Headcount bands, e.g. ['11-50', '51-200']"}, 'locations': {'type': 'array', 'items': {'type': 'string'}, 'description': "e.g. ['France', 'Benelux']"}, 'industries': {'type': 'array', 'items': {'type': 'string'}, 'description': "e.g. ['SaaS', 'Fintech']"}}, 'additionalProperties': False}
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['playId', 'key'], 'properties': {'key': {'enum': ['people_search', 'competitor_posts', 'job_offers', 'account_list', 'post_engagers'], 'type': 'string', 'description': "Which lane. people_search: LinkedIn people search compiled from the play's ICP (+ optional free-text keywords). | competitor_posts: Post discovery: Otto searches LinkedIn daily for posts matching an intent, judges each, and takes who engaged. | job_offers: Hiring signal: companies posting a role â\x86\x92 the buyers inside them. | account_list: Companies you name (names, websites or LinkedIn page URLs) â\x86\x92 Otto finds your buyers inside each. | post_engagers: RETIRED â\x80\x94 folded into competitor_posts.postUrls. Still runs on rows that exist; do not configure it on new plays."}, 'playId': {'type': 'string', 'description': 'The play, from gtm_list_plays.'}}, 'additionalProperties': False}
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['playId'], 'properties': {'playId': {'type': 'string', 'description': 'The play whose seat to check.'}}, 'additionalProperties': False}
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'playId': {'type': 'string', 'description': 'One play; omit for all.'}}, 'additionalProperties': False}
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {}}
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['playId'], 'properties': {'playId': {'type': 'string', 'description': 'The play to report on.'}}, 'additionalProperties': False}
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['playId', 'key'], 'properties': {'key': {'enum': ['people_search', 'competitor_posts', 'job_offers', 'account_list', 'post_engagers'], 'type': 'string', 'description': "Which lane. people_search: LinkedIn people search compiled from the play's ICP (+ optional free-text keywords). | competitor_posts: Post discovery: Otto searches LinkedIn daily for posts matching an intent, judges each, and takes who engaged. | job_offers: Hiring signal: companies posting a role â\x86\x92 the buyers inside them. | account_list: Companies you name (names, websites or LinkedIn page URLs) â\x86\x92 Otto finds your buyers inside each. | post_engagers: RETIRED â\x80\x94 folded into competitor_posts.postUrls. Still runs on rows that exist; do not configure it on new plays."}, 'playId': {'type': 'string', 'description': 'The play, from gtm_list_plays.'}}, 'additionalProperties': False}
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['approvalId'], 'properties': {'approvalId': {'type': 'string', 'description': 'The card to reject.'}}, 'additionalProperties': False}
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['playId', 'key'], 'properties': {'key': {'enum': ['people_search', 'competitor_posts', 'job_offers', 'account_list', 'post_engagers'], 'type': 'string', 'description': "Which lane. people_search: LinkedIn people search compiled from the play's ICP (+ optional free-text keywords). | competitor_posts: Post discovery: Otto searches LinkedIn daily for posts matching an intent, judges each, and takes who engaged. | job_offers: Hiring signal: companies posting a role â\x86\x92 the buyers inside them. | account_list: Companies you name (names, websites or LinkedIn page URLs) â\x86\x92 Otto finds your buyers inside each. | post_engagers: RETIRED â\x80\x94 folded into competitor_posts.postUrls. Still runs on rows that exist; do not configure it on new plays."}, 'playId': {'type': 'string', 'description': 'The play, from gtm_list_plays.'}}, 'additionalProperties': False}
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['playId', 'key', 'on'], 'properties': {'on': {'type': 'boolean'}, 'key': {'enum': ['people_search', 'competitor_posts', 'job_offers', 'account_list', 'post_engagers'], 'type': 'string', 'description': "Which lane. people_search: LinkedIn people search compiled from the play's ICP (+ optional free-text keywords). | competitor_posts: Post discovery: Otto searches LinkedIn daily for posts matching an intent, judges each, and takes who engaged. | job_offers: Hiring signal: companies posting a role â\x86\x92 the buyers inside them. | account_list: Companies you name (names, websites or LinkedIn page URLs) â\x86\x92 Otto finds your buyers inside each. | post_engagers: RETIRED â\x80\x94 folded into competitor_posts.postUrls. Still runs on rows that exist; do not configure it on new plays."}, 'playId': {'type': 'string', 'description': 'The play, from gtm_list_plays.'}}, 'additionalProperties': False}
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['playId'], 'properties': {'playId': {'type': 'string', 'description': 'The play to inspect.'}}, 'additionalProperties': False}
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['playId'], 'properties': {'playId': {'type': 'string', 'description': 'The play, from gtm_list_plays.'}}, 'additionalProperties': False}
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['playId', 'key'], 'properties': {'key': {'enum': ['people_search', 'competitor_posts', 'job_offers', 'account_list', 'post_engagers'], 'type': 'string', 'description': "Which lane. people_search: LinkedIn people search compiled from the play's ICP (+ optional free-text keywords). | competitor_posts: Post discovery: Otto searches LinkedIn daily for posts matching an intent, judges each, and takes who engaged. | job_offers: Hiring signal: companies posting a role â\x86\x92 the buyers inside them. | account_list: Companies you name (names, websites or LinkedIn page URLs) â\x86\x92 Otto finds your buyers inside each. | post_engagers: RETIRED â\x80\x94 folded into competitor_posts.postUrls. Still runs on rows that exist; do not configure it on new plays."}, 'limit': {'type': 'number', 'maximum': 50, 'minimum': 1, 'description': 'Runs to return (default 10, max 50).'}, 'playId': {'type': 'string', 'description': 'The play, from gtm_list_plays.'}}, 'additionalProperties': False}
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {}}
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['playId'], 'properties': {'sizes': {'type': 'array', 'items': {'type': 'string'}}, 'playId': {'type': 'string', 'description': 'The play, from gtm_list_plays.'}, 'titles': {'type': 'array', 'items': {'type': 'string'}}, 'exclude': {'type': 'array', 'items': {'type': 'string'}}, 'languages': {'type': 'array', 'items': {'type': 'string'}}, 'locations': {'type': 'array', 'items': {'type': 'string'}}, 'seniority': {'type': 'array', 'items': {'type': 'string'}}, 'industries': {'type': 'array', 'items': {'type': 'string'}}}, 'additionalProperties': False}
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['playId'], 'properties': {'goal': {'type': 'string', 'description': 'What a conversation from this play should reach.'}, 'name': {'type': 'string'}, 'voice': {'type': 'string', 'description': 'How the messages should sound.'}, 'paused': {'type': 'boolean', 'description': 'true = stop everything; false = resume.'}, 'playId': {'type': 'string', 'description': 'The play, from gtm_list_plays.'}, 'status': {'enum': ['active', 'draft'], 'type': 'string', 'description': "'active' launches; 'draft' un-launches."}, 'dailyCap': {'type': 'number', 'description': "Actions per day, all kinds summed. ACCOUNT-level: the ceiling every play on this LinkedIn account shares. Defaults to the seat's full LinkedIn allowance (145).", 'exclusiveMinimum': 0}, 'workingHours': {'type': 'object', 'required': ['start', 'end', 'tz'], 'properties': {'tz': {'type': 'string'}, 'end': {'type': 'string'}, 'start': {'type': 'string'}}, 'description': "e.g. { start: '09:00', end: '18:00', tz: 'Europe/Paris' }. ACCOUNT-level, like dailyCap.", 'additionalProperties': False}}, 'additionalProperties': False}
Input schema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {}}
Recent tool changes
Similar MCP servers
neuron
Operates AI chatbots and messaging workflows across WhatsApp and social channels, including contacts, campaigns, conversations, p…
Meta Council
Provides governed workflows for consulting, outreach, sales deals, invoices, marketing campaigns, content approvals, accounting a…
Rahul D Sarker: Marketing & RevOps Tools
Provides marketing, revenue operations, sales, advertising, SaaS, and conversion calculators, along with article search and consu…
Emailchaser
Manages cold-email campaigns, leads, sender mailboxes, sequences, outreach automation, deliverability, prospect sourcing, webhook…
LinkedIn MCP Server (Salesbot)
Supports LinkedIn lead discovery, contact enrichment, CRM pipelines, campaign sequencing, message approval and human-reviewed out…
send16-mcp
Provides email marketing and transactional messaging tools for contacts, audiences, campaigns, templates, automations, analytics,…
GrowthKit Revenue Intelligence
Supports B2B revenue operations with lead campaigns, ICP and company enrichment, CRM records and activities, outreach drafting, t…
Nevent MCP
Enables management and analysis of live-event marketing campaigns, audiences, email and messaging templates, paid ads, tracking l…