Unofficial Substack MCP server with 29 tools, browser auth, rich text support, public research, and strategy helpers. Not affiliated with Substack Inc.
This Substack MCP server has significant definition quality issues. Of 29 tools, most lack complete input schemas visible in source code. Parameter descriptions are present and mostly clear (baseline: 72 chars avg), but the server suffers from missing type definitions, weak error messaging, and incomplete schema documentation. The server includes unusual confirmation-flag patterns (confirm_create, confirm_update, confirm_publish) embedded in tool parameters rather than handled at the protocol level, which violates the tool-composition principle of doing one thing. Many tools (research_*, generate_*, analyze_*) appear to be AI-powered helpers without clear implementations visible; their definitions are inferred rather than directly registered. Writing tools (create_formatted_post, update_post, publish_post) have risk annotations but no output schema documentation. The codebase shows proper use of Python async patterns and Pydantic for validation, but the tool interface design prioritizes safety guardrails (confirmation flags) over clarity and composability.
Analyze your own published posts to identify patterns, strengths, and improvement opportunities
Analyze your content strategy to identify gaps and opportunities
Create a new formatted draft post on Substack. Supports full markdown formatting. IMPORTANT: You MUST ALWAYS ask the user to confirm creation in a follow-up message BEFORE calling this tool with confirm_create=true. Never set confirm_create=true on the first request, even if the user explicitly asks to create. This ensures users have time to review the content before creating.
Delete a draft post from the authenticated user's Substack publication. IMPORTANT: You MUST ALWAYS ask the user to confirm deletion in a follow-up message BEFORE calling this tool with confirm_delete=true. Never set confirm_delete=true on the first request.
Create a copy of an existing post as a new draft
11 tools (research_*, generate_*, analyze_*, content_gap_analysis, title_and_hook_optimizer, series_planner, study_topic_on_substack, extract_coding_lessons, repurpose_post) have NO visible input schema definitions in the provided source code. These appear to be AI-powered helpers whose implementations are inferred rather than explicitly registered with JSON Schema.
Writing tools (create_formatted_post, update_post, publish_post, schedule_post, delete_draft) embed confirmation-safety flags (confirm_create, confirm_update, confirm_publish, confirm_schedule, confirm_delete) as boolean parameters. This violates the single-responsibility principle and makes tool definitions confusing. The description instructs LLMs to never set the flag true on first call, then true on second call, this is a brittle protocol requiring LLM self-discipline rather than framework enforcement.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 52 | <=2025-11-25 | v2 |
Extract and format coding lessons or tutorials from content for educational purposes
Generate content ideas based on your publication's niche and audience
Get analytics data for a published post on the authenticated user's Substack publication
Get the full content of a draft or published post
Fetch and parse the Substack-supported public RSS feed for a publication.
Get all sections (topics/categories) for the authenticated user's Substack publication
Get the subscriber count for the authenticated user's Substack publication
Return documented Substack integration surfaces for a target URL (publication, post, or note).
List all draft posts for the authenticated user's Substack publication
List published posts for the authenticated user's Substack publication
List all scheduled posts for the authenticated user's Substack publication
Get a preview of how a draft post will look when published
Publish a Substack draft post immediately. IMPORTANT: You MUST ALWAYS ask the user to confirm publication in a follow-up message BEFORE calling this tool with confirm_publish=true. Never set confirm_publish=true on the first request.
Transform an existing post into different formats (thread, email, social posts, etc.)
Research a Substack publication to get insights about topics, audience, and trends
Research a specific Substack post to get detailed insights
Research a Substack publication for content strategy insights
Schedule a Substack draft post for future publication. IMPORTANT: You MUST ALWAYS ask the user to confirm scheduling in a follow-up message BEFORE calling this tool with confirm_schedule=true. Never set confirm_schedule=true on the first request.
Call Substack's limited help-documented profile lookup surface to search profiles by LinkedIn handle.
Plan and organize a multi-part content series
Study how a specific topic is covered across Substack to find trends and gaps
Optimize post titles and hooks for better engagement and click-through rates
Update an existing Substack draft post. WARNING: This tool COMPLETELY REPLACES the specified fields - it does NOT make partial edits. If you provide content, it will REPLACE ALL existing content. To make small edits, first use get_post_content to read the current content, make your changes, then provide the ENTIRE updated content. IMPORTANT: You MUST ALWAYS ask the user to confirm updates in a follow-up message BEFORE calling this tool with confirm_update=true. Never set confirm_update=true on the first request.
Upload an image to Substack CDN and get an optimized URL.
publish_post has minimal schema (only post_id required, confirm_publish with default false). No output schema documented. Users cannot know what happens when a post is published (does it return the published URL? timestamp? status?).
Error handling is minimal or absent across all tools. No indication of how the tool communicates errors (does it return error in response? throw exception?). Descriptions lack recovery guidance (e.g., 'If post not found, call list_drafts to find the correct ID'). Per pattern:recovery-guide, errors should tell the LLM what to do next.
get_sections and get_subscriber_count have minimal descriptions (<50 chars) and no schema visible. Output structure unknown (does get_sections return array of {id, name}? or flat list?). Users cannot plan tool composition.
Tools named with 'and' (e.g., title_and_hook_optimizer) signal multiple responsibilities. This tool optimizes both titles AND hooks, these could be split into optimize_post_title and optimize_post_hook so agents compose them independently. Combined tools make it harder for agents to reuse individual transformations.
Tools accept post_id but no guidance on how to find a post ID if the user only knows the title or content snippet. Common discovery flow missing: if user says 'update my draft about Python', agent must first call list_drafts, scan results for matching title, then extract ID. No tool pairs post_id with human-readable metadata in responses (e.g., list_drafts should return {post_id, title, created_date} so agent can identify drafts by title later).