Marketing Ops
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| GITHUB_TOKEN | No | GitHub: your own personal access token (get one at https://github.com/settings/tokens/new?description=Charter&scopes=repo,read:user), entered once via `marketing-ops-mcp login github`. | |
| LINEAR_API_KEY | No | Linear: your own personal API key (get one at https://linear.app/settings/account/security), entered once via `marketing-ops-mcp login linear`. | |
| NOTION_API_KEY | No | Notion: your own integration secret (ntn_…) (get one at https://www.notion.so/profile/integrations), then share the pages it should see with the integration; entered once via `marketing-ops-mcp login notion`. | |
| STRIPE_API_KEY | No | Stripe: your own secret or restricted key (get one at https://dashboard.stripe.com/apikeys), entered once via `marketing-ops-mcp login stripe`. | |
| TAVILY_API_KEY | No | Tavily: your own API key (get one at https://app.tavily.com/home), entered once via `marketing-ops-mcp login tavily`. | |
| GRANOLA_API_KEY | No | Granola: your own API key (get one at https://docs.granola.ai/help-center/sharing/integrations/granola-api; in the Granola app: Settings → Connectors → API keys; Business plan or above), entered once via `marketing-ops-mcp login granola`. | |
| SLACK_BOT_TOKEN | No | Slack: bot token (xoxb-…) from your own Slack app (get one at https://docs.r28.ai/charter/auth/setup/slack), entered once via `marketing-ops-mcp login slack`. | |
| GOOGLE_CLIENT_ID | No | Google: client ID of your own OAuth client (make one at https://docs.r28.ai/charter/auth/setup/google). Google connects via browser sign-in over your own OAuth client. | |
| FIRECRAWL_API_KEY | No | Firecrawl: your own API key (get one at https://www.firecrawl.dev/app/api-keys), entered once via `marketing-ops-mcp login firecrawl`. | |
| GOOGLE_CLIENT_SECRET | No | Google: client secret of your own OAuth client (make one at https://docs.r28.ai/charter/auth/setup/google). |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| linear_issues_listA | List issues, optionally filtered. Conditions on one filter object combine with AND. To find a team's open work, filter on team.key and state.type. |
| github_releases_listA | List a repository's releases, newest first. Tags that were never made into releases do not appear here — |
| gdocs_documents_createA | Create a blank document with a title. Only the title is honoured — the document is created empty. To add content, call this and then documents_batch_update with the returned documentId. |
| slack_chat_post_messageA | Send a message to a Slack channel, private group, or DM. Provide |
| firecrawl_monitor_createB | Create a scheduled monitor for scrape, crawl, or search targets. |
| firecrawl_extractA | Extract structured data from one or more URLs using an LLM. Poll results with extract_status. |
| gsheets_spreadsheets_values_appendC | Appends values to a spreadsheet. |
| firecrawl_mapB | Discover and list all URLs of a website starting from a base URL. Use when the user wants to explore a site's structure or find specific pages. |
| tavily_searchA | Execute a real-time web search optimized for AI agents. Use when sources are unknown or current web context is needed. Prefer search_depth advanced with chunks_per_source 3 for stronger evidence per source. |
| gsheets_spreadsheets_values_updateC | Sets values in a range of a spreadsheet. |
| linear_issue_createA | Create an issue. |
| gforms_forms_createA | Create a new form from a title. Only the title and the document title are honoured: the form is created with no description, no items and default settings. To add questions, call this and then forms_batch_update with the returned formId. Pass unpublished=true to create a form that does not yet accept responses. |
| gforms_forms_responses_listA | List a form's submitted responses, newest page first, up to 5000 per page. The only supported filter is on submission time: pass filter='timestamp >= 2026-01-01T00:00:00Z' to read what has arrived since a point in time. Answers come back keyed by questionId. |
| gcalendar_events_insertC | Create a calendar event; returns details of the event. |
| gmail_messages_sendC | Send an email via the Gmail API. |
| stripe_customers_listA | List customers, most recently created first. Filter by email to find one. |
| granola_notes_listA | List meeting notes, filtered by when they were created or last updated and optionally narrowed to one folder and its subfolders. Returns each note's id, title, owner and timestamps, not its content. Fetch that with notes_get. Only notes that already have a generated AI summary appear here. |
| gmail_drafts_createC | Save an email draft to Gmail. |
| notion_data_sources_queryB | Get the rows of a data source, optionally filtered and sorted. The filter grammar is one condition per column type, composed with |
| notion_pages_createA | Create a page — as a subpage of another page, or as a row of a database by giving its |
| firecrawl_scrapeB | Scrape a single URL and optionally extract information. Use when the user wants to read or summarize a specific webpage. Supports markdown, HTML, screenshots, and structured JSON extraction. |
| granola_notes_transcript_getA | Read a meeting transcript one page at a time. Use this for any long transcript, and whenever notes_get answers 413 TRANSCRIPT_TOO_LARGE. Each item is one line of speech with who said it and when. |
| firecrawl_crawlC | Recursively crawl a website and scrape each discovered page. |
| firecrawl_crawl_statusB | Get the status and results of a crawl job. |
| stripe_checkout_sessions_listA | List checkout sessions. Stripe has no payment_status filter, so find paid ones by reading the results. |
| slack_chat_schedule_messageA | Schedule a message for later, up to 120 days ahead. The returned |
| github_repos_list_commitsA | List commits, newest first. Narrow with |
| connectA | Connect one app this server uses. For an app that issues keys, says where to get one and the terminal command that stores it. For Google, once the user's own OAuth client is set, starts the browser sign-in and returns at once: the user approves in the browser and the next call works. To see which apps are connected, call |
| connection_statusA | See which apps this server is connected to, and how to connect each one that is not. Changes nothing. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
| setup | Connect every app this server uses, the quickest way each one allows. |
| what_shipped_to_blog_and_social_drafts | Marketing hears about features from the tracker, not from customers. |
| competitor_pricing_tracker | Price and packaging changes, dated, in a sheet, with an alert when one moves. |
| seo_content_gap | Topics competitors rank for that you have no page on, as a prioritised backlog. |
| webinar_ops_end_to_end | Registration, invite and reminders with no webinar tool. |
| customer_story_pipeline | Your longest-paying happy customers become case-study drafts and a permission ask. |
| weekly_newsletter_draft | Product news, posts and releases gathered into one draft every Friday. |
| event_leads_to_enriched_follow_ups | Booth scans become enriched leads with a follow-up waiting, same day. |
| brand_mention_monitor | Every mention worth replying to shows up with the context to reply. |
| webinar_transcript_to_blog_post | An hour of talk becomes a post and a queue of social snippets. |
| site_qa_crawl | Broken links, empty pages and stale pricing get issues before a prospect finds them. |
| launch_day_pulse | Hourly signups and fresh bugs posted to the launch channel without anyone refreshing dashboards. |
| survey_to_insight_memo | Raw responses become a tagged sheet and a one-page memo. |
| docs_site_freshness_check | Public docs pages older than the code they describe get flagged. |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 29 tools
Tools are namespaced by app (linear_, github_, firecrawl_, etc.) with a distinct resource+action per tool, so cross-app confusion is minimal. The only mild overlap is within firecrawl (scrape's 'optional structured extraction' vs extract) and the meta pair connect/connection_status, but descriptions differentiate them clearly.
The dominant pattern is consistent app_resource_action with the verb last (linear_issues_list, gmail_messages_send, stripe_customers_list). Deviations are minor: inconsistent pluralization (linear_issues_list vs linear_issue_create) and the two meta tools (connect, connection_status) that abandon the pattern entirely.
At 29 tools this is on the heavy side of the rubric, though the breadth is explained by spanning 13+ distinct apps, each contributing only 1-3 tools. It feels borderline: justified by multi-app scope but still a large surface an agent must navigate.
Coverage is a thin slice per app and several descriptions point to tools that do not exist in this set: linear_issue_create references teams_list/users_list/workflow_states_list, gdocs_documents_create references documents_batch_update, gforms_forms_create references forms_batch_update, and granola_notes_list references notes_get. These dangling references create dead ends that will cause agent failures.