Protocol

MCP server

tinyposter speaks Model Context Protocol. Drop the URL + a personal access token into any MCP-aware AI client.

What is MCP?

Model Context Protocol is the standard way AI agents call external tools. Anthropic, Google, and OpenAI all support it. tinyposter exposes its full feature set as MCP tools, so any MCP-aware client (Claude Desktop, Claude Code, Cursor, Zed, etc.) can post for you with a single config snippet.

Endpoint

  • URL: https://tinyposter.app/api/mcp
  • Transport: JSON-RPC 2.0 over HTTP POST
  • Auth: Authorization: Bearer tp_…
  • Methods: initialize, tools/list, tools/call, ping

Setup

Claude Desktop / Claude Code

Open claude_desktop_config.json from Settings → Developer → Edit Config (Mac/Windows) and add:

claude_desktop_config.jsonjson
{
  "mcpServers": {
    "tinyposter": {
      "url": "https://tinyposter.app/api/mcp",
      "headers": {
        "Authorization": "Bearer tp_PASTE_YOUR_TOKEN_HERE"
      }
    }
  }
}

Restart Claude. Done. Detailed walkthrough on the Claude page.

Cursor

Cursor → Settings → Tools & Integrations → MCP Servers → Add New. Use the same config as above.

Raw / curl

Want to test without an AI client? Hit it directly:

bash
# 1. Discover tools
curl https://tinyposter.app/api/mcp \
  -H "Authorization: Bearer tp_..." \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

# 2. Call a tool
curl https://tinyposter.app/api/mcp \
  -H "Authorization: Bearer tp_..." \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc":"2.0",
    "id":2,
    "method":"tools/call",
    "params":{ "name":"view_calendar", "arguments":{ "days_ahead":7 } }
  }'

Tool reference

Each tool is also documented in the MCP tools/list response with its JSON schema.

list_brands

List the brands the user owns. Each brand maps to its own set of connected social accounts.

input schema
{
  "type": "object",
  "properties": {},
  "additionalProperties": false
}
list_accounts

List the connected social media accounts for a brand. Defaults to the user's active brand.

input schema
{
  "type": "object",
  "properties": {
    "brand_id": {
      "type": "string",
      "description": "Brand id to operate on. Defaults to the user's currently active brand. Use list_brands to discover ids."
    }
  },
  "additionalProperties": false
}
get_usage

Get the user's plan, post quota, and how many posts they've used this billing period. Quota is shared across all brands.

input schema
{
  "type": "object",
  "properties": {},
  "additionalProperties": false
}
post_now

Publish a post immediately to one or more connected social platforms on a brand. The post is queued for publishing in the next minute.

input schema
{
  "type": "object",
  "required": [
    "text",
    "platforms"
  ],
  "properties": {
    "brand_id": {
      "type": "string",
      "description": "Brand id to operate on. Defaults to the user's currently active brand. Use list_brands to discover ids."
    },
    "text": {
      "type": "string",
      "description": "The post text/caption."
    },
    "platforms": {
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "TWITTER",
          "INSTAGRAM",
          "FACEBOOK",
          "LINKEDIN",
          "TIKTOK",
          "YOUTUBE",
          "PINTEREST",
          "BLUESKY",
          "THREADS",
          "REDDIT",
          "MASTODON"
        ]
      },
      "description": "Which connected platforms to publish to. Use list_accounts to see what's available.",
      "minItems": 1
    },
    "title": {
      "type": "string",
      "description": "Optional internal title (used for video titles on YouTube/TikTok)."
    },
    "media_urls": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Optional public URLs of images or videos to attach."
    }
  },
  "additionalProperties": false
}
schedule_post

Schedule a post to publish at a specific date/time on a brand. Use ISO 8601 (e.g. 2026-01-15T14:30:00-05:00).

input schema
{
  "type": "object",
  "required": [
    "text",
    "platforms",
    "scheduled_at"
  ],
  "properties": {
    "brand_id": {
      "type": "string",
      "description": "Brand id to operate on. Defaults to the user's currently active brand. Use list_brands to discover ids."
    },
    "text": {
      "type": "string"
    },
    "platforms": {
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "TWITTER",
          "INSTAGRAM",
          "FACEBOOK",
          "LINKEDIN",
          "TIKTOK",
          "YOUTUBE",
          "PINTEREST",
          "BLUESKY",
          "THREADS",
          "REDDIT",
          "MASTODON"
        ]
      },
      "minItems": 1
    },
    "scheduled_at": {
      "type": "string",
      "description": "ISO 8601 datetime for when to publish."
    },
    "title": {
      "type": "string"
    },
    "media_urls": {
      "type": "array",
      "items": {
        "type": "string"
      }
    }
  },
  "additionalProperties": false
}
list_posts

List posts for a brand (scheduled, publishing, published, failed). Defaults to the active brand.

input schema
{
  "type": "object",
  "properties": {
    "brand_id": {
      "type": "string",
      "description": "Brand id to operate on. Defaults to the user's currently active brand. Use list_brands to discover ids."
    },
    "from": {
      "type": "string",
      "description": "ISO datetime; only posts scheduled at or after this."
    },
    "to": {
      "type": "string",
      "description": "ISO datetime; only posts scheduled at or before this."
    },
    "status": {
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "draft",
          "scheduled",
          "publishing",
          "published",
          "failed",
          "canceled"
        ]
      },
      "description": "Filter by these statuses."
    },
    "limit": {
      "type": "integer",
      "minimum": 1,
      "maximum": 100,
      "default": 50
    }
  },
  "additionalProperties": false
}
view_calendar

Get a quick view of upcoming scheduled posts for a brand grouped by date.

input schema
{
  "type": "object",
  "properties": {
    "brand_id": {
      "type": "string",
      "description": "Brand id to operate on. Defaults to the user's currently active brand. Use list_brands to discover ids."
    },
    "days_ahead": {
      "type": "integer",
      "minimum": 1,
      "maximum": 60,
      "default": 14
    }
  },
  "additionalProperties": false
}
cancel_post

Cancel a scheduled post by id. Cannot cancel posts that have already been published.

input schema
{
  "type": "object",
  "required": [
    "id"
  ],
  "properties": {
    "id": {
      "type": "string"
    }
  },
  "additionalProperties": false
}

Things to ask

  • “Post ‘Friday recap incoming’ to X and LinkedIn.”
  • “Schedule a Threads post for Sunday at 9am ET that says...”
  • “What's on my calendar next week?”
  • “Cancel the post I scheduled for Saturday.”
  • “Which platforms am I connected to?”
  • “How many posts do I have left this month?”

Troubleshooting

Claude doesn't list tinyposter as a tool

Quit Claude fully (Cmd+Q) and re-open. Config is only read on launch.

I get rate limited

The MCP endpoint allows 120 calls/min/token. If you're hitting that, batch the work or move to the REST API (240/min) for bulk operations.

Can I have two clients use the same token?

You can, but if one leaks, both stop working when you revoke. Better practice: one token per client (“Claude Desktop”, “Cursor”, “CI”, etc.) so you can revoke surgically.

Same actions, two protocols
Anything you can do via MCP, you can do via the REST API. They use the same tokens, the same data, and the same Bundle.social pipeline behind the scenes.