Skip to content

MCP access

Run PostForge from the tools you already use.

PostForge speaks MCP. Connect Claude Code or another MCP client with a scoped token and drive the same workflow (sourcing, drafting, review, and scheduling) from your assistant.

Tokens act as you. Review rules and post limits apply.

Connect in three steps

  1. 1

    Create a scoped token

    Settings → MCP access. Choose full access, draft only, or read-only. The token is shown once.

  2. 2

    Add the endpoint to your client

    Send requests to https://thepostforge.ai/mcp with an Authorization: Bearer <token> header.

    A client that cannot set a header connects with OAuth instead: it reads the endpoint's 401, registers itself, and asks you to approve a scope on a consent page. That produces the same kind of token, listed and revocable in the same place.

    https://thepostforge.ai/mcp
    {
      "mcpServers": {
        "postforge": {
          "type": "http",
          "url": "https://thepostforge.ai/mcp",
          "headers": {
            "Authorization": "Bearer <your-token>"
          }
        }
      }
    }

    Settings generates the same config with your real token.

  3. 3

    Ask for the work

    Your client sees the tools below. It can start runs, pick a source, draft, and (with full access) approve. Every step keeps the rules you set in the app.

What stays true

  • The token acts as you, within its scope.
  • Revoking a token is immediate; that client's calls fail with 401.
  • The same review rules, validation checks, and post limits apply.
  • Nothing publishes outside the approval rules you set in the app.

What the tools cover

25 tools, grouped by the part of the workflow they touch. Expand a row for its input schema. Descriptions are the text your client shows the model.

Sources 3

  • discover_sources_for_briefFind source articles that serve an expertise brief.
    {
      "properties": {
        "expertise_brief": {
          "additionalProperties": true,
          "title": "Expertise Brief",
          "type": "object"
        }
      },
      "required": [
        "expertise_brief"
      ],
      "title": "discover_sources_for_briefArguments",
      "type": "object"
    }
  • list_candidatesArticle candidates for a run paused at article selection.
    {
      "properties": {
        "run_id": {
          "title": "Run Id",
          "type": "string"
        }
      },
      "required": [
        "run_id"
      ],
      "title": "list_candidatesArguments",
      "type": "object"
    }
  • select_sourceChoose the article a paused run will draft from.
    {
      "properties": {
        "run_id": {
          "title": "Run Id",
          "type": "string"
        },
        "candidate_id": {
          "title": "Candidate Id",
          "type": "string"
        },
        "perspective": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Perspective"
        },
        "template_slug": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Template Slug"
        }
      },
      "required": [
        "run_id",
        "candidate_id"
      ],
      "title": "select_sourceArguments",
      "type": "object"
    }

Drafting 6

  • cancel_runCancel a run and free the single-active-run slot.
    {
      "properties": {
        "run_id": {
          "title": "Run Id",
          "type": "string"
        }
      },
      "required": [
        "run_id"
      ],
      "title": "cancel_runArguments",
      "type": "object"
    }
  • create_runStart a new LinkedIn post run.
    {
      "properties": {
        "article_url": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Article Url"
        },
        "perspective": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Perspective"
        },
        "post_template": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Post Template"
        },
        "generate_image": {
          "default": false,
          "title": "Generate Image",
          "type": "boolean"
        },
        "force_review": {
          "default": true,
          "title": "Force Review",
          "type": "boolean"
        },
        "allow_duplicate": {
          "default": false,
          "title": "Allow Duplicate",
          "type": "boolean"
        },
        "expertise_brief": {
          "anyOf": [
            {
              "additionalProperties": true,
              "type": "object"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Expertise Brief"
        }
      },
      "title": "create_runArguments",
      "type": "object"
    }
  • edit_draftOffer the user an edit form for a parked draft (pop-up where supported).
    {
      "properties": {
        "run_id": {
          "title": "Run Id",
          "type": "string"
        }
      },
      "required": [
        "run_id"
      ],
      "title": "edit_draftArguments",
      "type": "object"
    }
  • get_draft_optionsShaping context for a new run: voice profile, templates, takes, brief.
    {
      "properties": {},
      "title": "get_draft_optionsArguments",
      "type": "object"
    }
  • get_runRead a run: your active one, or a specific one by id.
    {
      "properties": {
        "run_id": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Run Id"
        }
      },
      "title": "get_runArguments",
      "type": "object"
    }
  • suggest_takesThree article-derived angles for the user to choose from.
    {
      "properties": {
        "article_url": {
          "title": "Article Url",
          "type": "string"
        }
      },
      "required": [
        "article_url"
      ],
      "title": "suggest_takesArguments",
      "type": "object"
    }

Review 2

  • approve_draftApprove a draft parked at awaiting_approval — the publish action.
    {
      "properties": {
        "run_id": {
          "title": "Run Id",
          "type": "string"
        },
        "edited_body": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Edited Body"
        },
        "include_image": {
          "default": true,
          "title": "Include Image",
          "type": "boolean"
        },
        "publish_mode": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Publish Mode"
        },
        "publish_at": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Publish At"
        },
        "save_as_sample": {
          "default": false,
          "title": "Save As Sample",
          "type": "boolean"
        }
      },
      "required": [
        "run_id"
      ],
      "title": "approve_draftArguments",
      "type": "object"
    }
  • check_claimsCheck the parked draft's claims against its selected source.
    {
      "properties": {
        "run_id": {
          "title": "Run Id",
          "type": "string"
        },
        "draft_body": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Draft Body"
        }
      },
      "required": [
        "run_id"
      ],
      "title": "check_claimsArguments",
      "type": "object"
    }

Images 2

  • generate_imageGenerate (first time) or regenerate the run's accompanying image.
    {
      "properties": {
        "run_id": {
          "title": "Run Id",
          "type": "string"
        }
      },
      "required": [
        "run_id"
      ],
      "title": "generate_imageArguments",
      "type": "object"
    }
  • get_imageFetch the run's generated image to show it to the user.
    {
      "properties": {
        "run_id": {
          "title": "Run Id",
          "type": "string"
        }
      },
      "required": [
        "run_id"
      ],
      "title": "get_imageArguments",
      "type": "object"
    }

Voice 10

  • activate_voiceMake a profile the tenant's active voice — global, immediate change.
    {
      "properties": {
        "profile_id": {
          "title": "Profile Id",
          "type": "string"
        }
      },
      "required": [
        "profile_id"
      ],
      "title": "activate_voiceArguments",
      "type": "object"
    }
  • add_writing_sampleAdd one writing sample — the user's own writing, not instructions.
    {
      "properties": {
        "profile_id": {
          "title": "Profile Id",
          "type": "string"
        },
        "text": {
          "maxLength": 8000,
          "minLength": 100,
          "title": "Text",
          "type": "string"
        },
        "sample_kind": {
          "default": "linkedin_post",
          "enum": [
            "linkedin_post",
            "article",
            "comment",
            "other"
          ],
          "title": "Sample Kind",
          "type": "string"
        },
        "user_label": {
          "anyOf": [
            {
              "maxLength": 120,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "User Label"
        },
        "is_pinned": {
          "default": false,
          "title": "Is Pinned",
          "type": "boolean"
        }
      },
      "required": [
        "profile_id",
        "text"
      ],
      "title": "add_writing_sampleArguments",
      "type": "object"
    }
  • analyze_voiceRun (or re-run) voice analysis over the profile's active samples.
    {
      "properties": {
        "profile_id": {
          "title": "Profile Id",
          "type": "string"
        }
      },
      "required": [
        "profile_id"
      ],
      "title": "analyze_voiceArguments",
      "type": "object"
    }
  • create_voice_profileCreate a voice profile.
    {
      "$defs": {
        "EditorialPreferencesIn": {
          "properties": {
            "allow_parentheses": {
              "default": false,
              "title": "Allow Parentheses",
              "type": "boolean"
            },
            "allow_dashes": {
              "default": false,
              "title": "Allow Dashes",
              "type": "boolean"
            },
            "hashtag_mode": {
              "default": "required",
              "enum": [
                "required",
                "optional",
                "none"
              ],
              "title": "Hashtag Mode",
              "type": "string"
            },
            "paragraph_style": {
              "default": "flowing",
              "enum": [
                "flowing",
                "line_breaks"
              ],
              "title": "Paragraph Style",
              "type": "string"
            },
            "structure_mode": {
              "default": "guided",
              "enum": [
                "guided",
                "free"
              ],
              "title": "Structure Mode",
              "type": "string"
            },
            "closing_style": {
              "default": "either",
              "enum": [
                "either",
                "question",
                "statement"
              ],
              "title": "Closing Style",
              "type": "string"
            }
          },
          "title": "EditorialPreferencesIn",
          "type": "object"
        }
      },
      "properties": {
        "name": {
          "maxLength": 80,
          "minLength": 1,
          "title": "Name",
          "type": "string"
        },
        "source_type": {
          "default": "manual",
          "enum": [
            "preset",
            "manual",
            "samples"
          ],
          "title": "Source Type",
          "type": "string"
        },
        "preset_key": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Preset Key"
        },
        "explicit_user_instructions": {
          "anyOf": [
            {
              "maxLength": 1000,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Explicit User Instructions"
        },
        "do_not_use_instructions": {
          "anyOf": [
            {
              "maxLength": 1000,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Do Not Use Instructions"
        },
        "editorial_preferences": {
          "anyOf": [
            {
              "$ref": "#/$defs/EditorialPreferencesIn"
            },
            {
              "type": "null"
            }
          ],
          "default": null
        }
      },
      "required": [
        "name"
      ],
      "title": "create_voice_profileArguments",
      "type": "object"
    }
  • delete_voice_profileDelete a voice profile, its samples, and its analysis history.
    {
      "properties": {
        "profile_id": {
          "title": "Profile Id",
          "type": "string"
        }
      },
      "required": [
        "profile_id"
      ],
      "title": "delete_voice_profileArguments",
      "type": "object"
    }
  • delete_writing_sampleDelete one writing sample. Permanent — there is no restore.
    {
      "properties": {
        "sample_id": {
          "title": "Sample Id",
          "type": "string"
        }
      },
      "required": [
        "sample_id"
      ],
      "title": "delete_writing_sampleArguments",
      "type": "object"
    }
  • get_voice_profileOne voice profile in full: fields, samples, latest analysis.
    {
      "properties": {
        "profile_id": {
          "title": "Profile Id",
          "type": "string"
        }
      },
      "required": [
        "profile_id"
      ],
      "title": "get_voice_profileArguments",
      "type": "object"
    }
  • list_voice_profilesAll voice profiles for the tenant, newest first.
    {
      "properties": {},
      "title": "list_voice_profilesArguments",
      "type": "object"
    }
  • update_voice_profileUpdate a voice profile — patch semantics: only the passed fields change.
    {
      "$defs": {
        "EditorialPreferencesIn": {
          "properties": {
            "allow_parentheses": {
              "default": false,
              "title": "Allow Parentheses",
              "type": "boolean"
            },
            "allow_dashes": {
              "default": false,
              "title": "Allow Dashes",
              "type": "boolean"
            },
            "hashtag_mode": {
              "default": "required",
              "enum": [
                "required",
                "optional",
                "none"
              ],
              "title": "Hashtag Mode",
              "type": "string"
            },
            "paragraph_style": {
              "default": "flowing",
              "enum": [
                "flowing",
                "line_breaks"
              ],
              "title": "Paragraph Style",
              "type": "string"
            },
            "structure_mode": {
              "default": "guided",
              "enum": [
                "guided",
                "free"
              ],
              "title": "Structure Mode",
              "type": "string"
            },
            "closing_style": {
              "default": "either",
              "enum": [
                "either",
                "question",
                "statement"
              ],
              "title": "Closing Style",
              "type": "string"
            }
          },
          "title": "EditorialPreferencesIn",
          "type": "object"
        }
      },
      "properties": {
        "profile_id": {
          "title": "Profile Id",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "maxLength": 80,
              "minLength": 1,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Name"
        },
        "explicit_user_instructions": {
          "anyOf": [
            {
              "maxLength": 1000,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Explicit User Instructions"
        },
        "do_not_use_instructions": {
          "anyOf": [
            {
              "maxLength": 1000,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Do Not Use Instructions"
        },
        "generated_style_guide": {
          "anyOf": [
            {
              "maxLength": 4000,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Generated Style Guide"
        },
        "status": {
          "anyOf": [
            {
              "enum": [
                "draft",
                "archived"
              ],
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Status"
        },
        "example_selection_strategy": {
          "anyOf": [
            {
              "enum": [
                "pinned_first",
                "recent_first"
              ],
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Example Selection Strategy"
        },
        "editorial_preferences": {
          "anyOf": [
            {
              "$ref": "#/$defs/EditorialPreferencesIn"
            },
            {
              "type": "null"
            }
          ],
          "default": null
        }
      },
      "required": [
        "profile_id"
      ],
      "title": "update_voice_profileArguments",
      "type": "object"
    }
  • update_writing_sampleUpdate one writing sample — patch semantics: only passed fields change.
    {
      "properties": {
        "sample_id": {
          "title": "Sample Id",
          "type": "string"
        },
        "user_label": {
          "anyOf": [
            {
              "maxLength": 120,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "User Label"
        },
        "is_pinned": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Is Pinned"
        },
        "is_active": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Is Active"
        }
      },
      "required": [
        "sample_id"
      ],
      "title": "update_writing_sampleArguments",
      "type": "object"
    }

Schedule 2

  • get_scheduleThe tenant's recurring publishing schedule (daily/weekdays/weekly).
    {
      "properties": {},
      "title": "get_scheduleArguments",
      "type": "object"
    }
  • set_scheduleCreate or replace the tenant's recurring publishing schedule.
    {
      "properties": {
        "enabled": {
          "title": "Enabled",
          "type": "boolean"
        },
        "frequency": {
          "enum": [
            "daily",
            "weekdays",
            "weekly"
          ],
          "title": "Frequency",
          "type": "string"
        },
        "hour": {
          "maximum": 23,
          "minimum": 0,
          "title": "Hour",
          "type": "integer"
        },
        "minute": {
          "maximum": 59,
          "minimum": 0,
          "title": "Minute",
          "type": "integer"
        },
        "day_of_week": {
          "anyOf": [
            {
              "maximum": 6,
              "minimum": 0,
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Day Of Week"
        },
        "days_of_week": {
          "anyOf": [
            {
              "items": {
                "type": "integer"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Days Of Week"
        },
        "end_hour": {
          "anyOf": [
            {
              "maximum": 23,
              "minimum": 0,
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "End Hour"
        },
        "end_minute": {
          "anyOf": [
            {
              "maximum": 59,
              "minimum": 0,
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "End Minute"
        },
        "confirmation_email_enabled": {
          "default": false,
          "title": "Confirmation Email Enabled",
          "type": "boolean"
        },
        "generate_image": {
          "default": false,
          "title": "Generate Image",
          "type": "boolean"
        },
        "target_platforms": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Target Platforms"
        }
      },
      "required": [
        "enabled",
        "frequency",
        "hour",
        "minute"
      ],
      "title": "set_scheduleArguments",
      "type": "object"
    }

A token's scope can be narrower than this list: read-only covers the read tools, draft only adds creation, and approval tools need full access.

Can we use analytics? We use PostHog (our analytics provider in the US) to see howPostForge is used, which sets cookies and sends usage data. Nothing is collected until you accept, and you can change your choice any time in Settings.