> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sagescreen.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Ghostwrite a LinkedIn or Reddit comment/DM in the operator's voice.

> Ghostwrite a LinkedIn or Reddit comment/DM in the operator's voice.

    `message` must be a JSON string with this shape:
    {
      "persona": {
        "name": "Ryan Meinzer",
        "role": "Co-founder",
        "company": "SageScreen",
        "landingUrl": "https://sagescreen.io",
        "demoCalendarUrl": "https://cal.com/sagescreen/demo",
        "introCalendarUrl": "https://cal.com/sagescreen/intro"
      },
      "voice": "ryan",
      "channel": "linkedin-comment",
      "context": {
        "postText": "Full text of the LinkedIn post or Reddit thread being responded to.",
        "authorName": "Jane Smith",
        "authorTitle": "VP of Talent at Acme Corp",
        "subreddit": "recruiting",
        "dmText": "Text of the DM being replied to (for dm-reply channels).",
        "crmNotes": ["Most recent CRM note about this person", "Older note"]
      },
      "prompt": {
        "tone": "curious",
        "slant": "peer",
        "cta": { "style": "none", "landingUrl": "" },
        "calendar": { "type": "demo", "url": "https://cal.com/sagescreen/demo" },
        "extraInstructions": "Keep it under 20 words.",
        "withContext": false
      }
    }

    voice vs persona: voice ("ryan", "theo", "kayla", "nicole") controls HOW it sounds —
    word choice, rhythm, sentence style. persona is WHO is signing it — the name and title
    shown to the reader. They are independent: voice="ryan" + persona.name="Ryan Meinzer"
    means ghostwrite in Ryan's style as Ryan. voice="theo" + persona.name="Ryan Meinzer"
    means write in Theo's style but sign it as Ryan.

    channel values: "linkedin-comment" | "linkedin-dm-reply" | "linkedin-dm-init" | "reddit-comment" | "reddit-dm-reply" | "reddit-dm-init"
    cta.style values: "none" (no pitch) | "soft" | "direct"
    cta.landingUrl: product landing page URL to weave in when cta.style is not "none".
    calendar.type values: "none" | "demo" | "intro"
    calendar.url: the resolved booking URL for the selected calendar type.
    context fields are all optional — include what you have.

    Returns the paste-ready message text. No preamble, no quotes, no markdown.



## OpenAPI

````yaml /openapi/private/specs/mcp/sagescreen.yml post /tools/comment_agent
openapi: 3.1.0
info:
  title: SageScreen — MCP Tool Catalog
  description: >-
    Agent-callable tools exposed by the SageScreen MCP server at
    `https://mcp.sagescreen.net`.


    These are the same tools served over the Model Context Protocol; this
    reference documents their **REST** surface (`POST /tools/{name}`, body = the
    tool's arguments), which is what the playground below invokes. The live,
    machine-readable catalog is `GET /tools/list`.


    **This page is generated deterministically** from the server's tool registry
    (`apps/docs/scripts/generate_mcp_spec.py`), not hand-written and not
    AI-generated — it cannot drift from the shipped tools.


    All calls authenticate with the `X-Service-Token` header (or `?token=`).
  version: 1.0.0
servers:
  - url: https://mcp.sagescreen.net
    description: Production MCP server
security:
  - serviceToken: []
  - tokenQuery: []
tags:
  - name: Agents
  - name: Contact Push
  - name: Image Generation
  - name: Other
  - name: Productlane
  - name: Reply.io
  - name: Sequences
  - name: Spaces
  - name: WordPress
paths:
  /tools/comment_agent:
    post:
      tags:
        - Agents
      summary: Ghostwrite a LinkedIn or Reddit comment/DM in the operator's voice.
      description: |-
        Ghostwrite a LinkedIn or Reddit comment/DM in the operator's voice.

            `message` must be a JSON string with this shape:
            {
              "persona": {
                "name": "Ryan Meinzer",
                "role": "Co-founder",
                "company": "SageScreen",
                "landingUrl": "https://sagescreen.io",
                "demoCalendarUrl": "https://cal.com/sagescreen/demo",
                "introCalendarUrl": "https://cal.com/sagescreen/intro"
              },
              "voice": "ryan",
              "channel": "linkedin-comment",
              "context": {
                "postText": "Full text of the LinkedIn post or Reddit thread being responded to.",
                "authorName": "Jane Smith",
                "authorTitle": "VP of Talent at Acme Corp",
                "subreddit": "recruiting",
                "dmText": "Text of the DM being replied to (for dm-reply channels).",
                "crmNotes": ["Most recent CRM note about this person", "Older note"]
              },
              "prompt": {
                "tone": "curious",
                "slant": "peer",
                "cta": { "style": "none", "landingUrl": "" },
                "calendar": { "type": "demo", "url": "https://cal.com/sagescreen/demo" },
                "extraInstructions": "Keep it under 20 words.",
                "withContext": false
              }
            }

            voice vs persona: voice ("ryan", "theo", "kayla", "nicole") controls HOW it sounds —
            word choice, rhythm, sentence style. persona is WHO is signing it — the name and title
            shown to the reader. They are independent: voice="ryan" + persona.name="Ryan Meinzer"
            means ghostwrite in Ryan's style as Ryan. voice="theo" + persona.name="Ryan Meinzer"
            means write in Theo's style but sign it as Ryan.

            channel values: "linkedin-comment" | "linkedin-dm-reply" | "linkedin-dm-init" | "reddit-comment" | "reddit-dm-reply" | "reddit-dm-init"
            cta.style values: "none" (no pitch) | "soft" | "direct"
            cta.landingUrl: product landing page URL to weave in when cta.style is not "none".
            calendar.type values: "none" | "demo" | "intro"
            calendar.url: the resolved booking URL for the selected calendar type.
            context fields are all optional — include what you have.

            Returns the paste-ready message text. No preamble, no quotes, no markdown.
      operationId: comment_agent
      requestBody:
        required: true
        content:
          application/json:
            schema:
              properties:
                message:
                  title: Message
                  type: string
              required:
                - message
              type: object
      responses:
        '200':
          description: >-
            Tool result. The shape is tool-specific; most tools return a JSON
            object, some a `{"result": ...}` envelope.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        '400':
          description: Bad arguments (unknown kwargs, malformed JSON body).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          description: Unknown tool name.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Tool raised an error during execution.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  schemas:
    ErrorResponse:
      type: object
      properties:
        error:
          type: string
          description: Human-readable error message.
        detail:
          type: string
          description: Optional additional context.
      required:
        - error
  responses:
    Unauthorized:
      description: Missing or invalid service token.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error: Unauthorized
  securitySchemes:
    serviceToken:
      type: apiKey
      in: header
      name: X-Service-Token
    tokenQuery:
      type: apiKey
      in: query
      name: token

````