MCP Tool Reference
All 21 tools exposed by the Pharlo MCP server, organized by domain. The machine-readable equivalent of this page is /mcp-tools.json (opens in a new tab). For end-to-end recipes that chain these tools, see the Agent Workflows; for safe usage rules, see Agent Rules.
Annotations key
| Annotation | Meaning |
|---|---|
readOnly | Does not mutate data — safe to call freely |
destructive | Hard or impossible to undo — Claude will ask for confirmation |
idempotent | Calling multiple times produces the same result |
openWorld | Makes calls to an external platform (YouTube, Facebook) |
Assignments
Assignments are publishing jobs. Each one moves through a lifecycle:
pending → uploading → uploaded → processing → published (or failed / cancelled).
See Workflows for end-to-end prompt patterns, and Assignments REST reference for the underlying API.
create_assignment
Create a new publishing job to post content to a social media platform.
readOnly: false | destructive: true | idempotent: false | openWorld: true
YouTube default privacy is "private". Always set "privacy": "public" explicitly in your prompt or payload if you want the video publicly visible.
Call get_platform_capabilities before this tool to discover supported payload fields, character limits, and allowed values for the target platform.
Three ways to supply media — pick exactly one. mediaUrl for an already-public direct media URL, fileContent for small base64-encoded chat attachments, or uploadSessionId for large local files uploaded through the browser. For the large-file flow, start with create_assignment_upload_session and only call this tool once the session status is completed.
| Parameter | Type | Required | Description |
|---|---|---|---|
connectionId | UUID | Yes | The channel to publish to — get it from list_connections |
type | string | Yes | video, image, link, text, reel, short, story, carousel |
payload | JSON string | Yes | Platform-specific fields (title, description, privacy, tags, etc.) |
scheduledAt | ISO 8601 | No | Scheduled publish time — must include timezone offset e.g. +03:00 |
mediaUrl | URL | No | Publicly accessible media URL (one of three media sources) |
fileContent | base64 string | No | Base64-encoded small chat attachment (one of three media sources) |
uploadSessionId | UUID | No | Completed create_assignment_upload_session ID for large local files (one of three media sources) |
callbackUrl | URL | No | Webhook URL called on every status change — see Webhooks guide |
idempotencyKey | string | No | Unique string to prevent duplicate submissions on retry |
mediaContentType | string | No | MIME type of the media file, e.g. video/mp4 |
mediaSizeBytes | int | No | Media file size in bytes — used for upload progress tracking |
Example prompts:
"Upload https://cdn.example.com/demo.mp4 (opens in a new tab) to my YouTube channel 'Tech Reviews'. Title: 'Product Demo v3', make it public, schedule for Friday at 6 PM Berlin time."
"Post this video to my Facebook page as public. Description: 'Check out our new feature'. Use https://cdn.example.com/promo.mp4 (opens in a new tab)"
Example payload — YouTube video:
{
"connectionId": "7f3e1a2b-4c5d-6e7f-8a9b-0c1d2e3f4a5b",
"type": "video",
"mediaUrl": "https://cdn.example.com/demo.mp4",
"mediaContentType": "video/mp4",
"scheduledAt": "2026-04-25T18:00:00+02:00",
"payload": "{\"title\":\"Product Demo v3\",\"description\":\"See what's new\",\"privacy\":\"public\",\"tags\":[\"demo\",\"product\"]}"
}Example payload — Facebook post:
{
"connectionId": "9a8b7c6d-5e4f-3210-fedc-ba9876543210",
"type": "video",
"mediaUrl": "https://cdn.example.com/promo.mp4",
"payload": "{\"description\":\"Check out our new feature!\",\"privacy\":\"EVERYONE\"}"
}Programmatic usage (custom agents):
import anthropic
client = anthropic.Anthropic()
response = client.beta.messages.create(
model="claude-opus-4-7",
max_tokens=1024,
betas=["mcp-client-2025-04-04"],
mcp_servers=[
{
"type": "url",
"url": "https://pharlo.io/_mcp",
"authorization_token": "mcp_at_your_token",
}
],
messages=[
{
"role": "user",
"content": (
"Upload https://cdn.example.com/demo.mp4 to my YouTube channel "
"'Tech Reviews'. Title: 'Product Demo v3', public, "
"schedule for 2026-04-25T18:00:00+02:00."
),
}
],
)
for block in response.content:
if hasattr(block, "text"):
print(block.text)create_assignment_upload_session
Create a browser upload session for a large local media file that will later be published as an assignment.
readOnly: false | destructive: false | idempotent: false | openWorld: true
Large-file workflow. Use this when the user wants to upload a local video (e.g. to YouTube from their computer) instead of supplying a public mediaUrl. Call it with connectionId only — do not ask for or invent file name, MIME type, or size; the browser upload page reads that metadata from the selected file. Give the returned uploadPageUrl to the user, then poll with get_assignment_upload_session.
| Parameter | Type | Required | Description |
|---|---|---|---|
connectionId | UUID | Yes | The channel the uploaded file will publish to |
fileName | string | No | Optional — normally detected by the browser upload page |
fileMimeType | string | No | Optional — normally detected by the browser upload page |
fileSizeBytes | int | No | Optional — normally detected by the browser upload page |
Response includes: sessionId, uploadPageUrl, status, expiresAt
Example prompts:
"I want to upload a video from my computer to my 'Tech Reviews' YouTube channel."
"Give me an upload link for a large local file."
get_assignment_upload_session
Get the current status of a browser upload session created by create_assignment_upload_session.
readOnly: true | destructive: false | idempotent: true | openWorld: false
Poll this after the user opens uploadPageUrl. When status is completed, call create_assignment with the same session ID as uploadSessionId. If status is expired, cancelled, or consumed, create a new session instead.
| Parameter | Type | Required | Description |
|---|---|---|---|
sessionId | UUID | Yes | The upload session ID returned by create_assignment_upload_session |
Example prompt:
"Is my upload finished yet?"
list_assignments
List publishing assignments with optional filters and pagination.
readOnly: true | destructive: false | idempotent: true | openWorld: false
| Parameter | Type | Required | Description |
|---|---|---|---|
page | int | No | Page number (default: 1) |
limit | int | No | Items per page (default: 10, max: 50) |
status | string | No | pending, uploading, uploaded, processing, published, failed, cancelled |
platform | string | No | youtube, facebook |
connectionId | UUID | No | Filter by channel |
externalId | string | No | Filter by your custom ID |
dateFrom | ISO 8601 | No | Created after this date |
dateTo | ISO 8601 | No | Created before this date |
compact | bool | No | Return compact items (default: true) |
Example prompts:
"Show me my last 10 assignments."
"List all failed assignments from the past week on my YouTube channel."
"What assignments are currently pending or processing?"
get_assignment
Get full details of a specific assignment including status, errors, platform URL, and payload.
readOnly: true | destructive: false | idempotent: true | openWorld: false
| Parameter | Type | Required | Description |
|---|---|---|---|
assignmentId | UUID | Yes | Assignment UUID |
Example prompt:
"What's the status of assignment a1b2c3d4-e5f6-7890-abcd-ef1234567890? Did it publish?"
Example response fields:
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "published",
"platform": "youtube",
"type": "video",
"platformUrl": "https://youtu.be/dQw4w9WgXcQ",
"publishedAt": "2026-04-25T16:02:00Z",
"scheduledAt": "2026-04-25T16:00:00Z",
"payload": { "title": "Product Demo v3", "privacy": "public" }
}update_assignment
Update a pending or uploaded assignment's scheduled time or payload before it is published.
readOnly: false | destructive: true | idempotent: false | openWorld: false
This tool only works on assignments that have not yet been published. To edit a post that is already live, use update_published_content instead — it pushes the change to the platform directly.
| Parameter | Type | Required | Description |
|---|---|---|---|
assignmentId | UUID | Yes | Assignment UUID |
scheduledAt | ISO 8601 | No | New scheduled time (with timezone offset) |
payload | JSON string | No | New content payload |
Example prompts:
"Reschedule assignment a1b2c3d4 to Monday at 9 AM Kyiv time."
"Change the title of my pending assignment a1b2c3d4 to 'Q2 Launch'."
update_published_content
Update the metadata of an already published assignment directly on the platform.
readOnly: false | destructive: false | idempotent: true | openWorld: true
Currently supported for YouTube only. Changes (title, description, tags, privacy) are applied to the platform in real time. For not-yet-published assignments use update_assignment. If the connection token is expired, re-authorize via get_oauth_connect_url first.
| Parameter | Type | Required | Description |
|---|---|---|---|
assignmentId | UUID | Yes | Assignment UUID of the published post |
title | string | No | New video title (max 100 chars) |
description | string | No | New video description (max 5000 chars) |
tags | JSON string | No | Tags as a JSON array string, e.g. ["tag1","tag2"] (max 500 chars total) |
privacy | string | No | public, unlisted, or private |
Example prompts:
"Change the title of my published video a1b2c3d4 to 'Q2 Launch — Updated'."
"Make my published YouTube video a1b2c3d4 unlisted."
retry_assignment
Retry a failed assignment. Re-queues it without creating a new assignment.
readOnly: false | destructive: false | idempotent: true | openWorld: true
| Parameter | Type | Required | Description |
|---|---|---|---|
assignmentId | UUID | Yes | UUID of a failed assignment |
Example prompt:
"Retry my failed assignment a1b2c3d4."
"List all failed assignments from today and retry them."
cancel_assignment
Cancel a pending or scheduled assignment.
readOnly: false | destructive: true | idempotent: false | openWorld: false
Cancelled assignments cannot be restarted. Use update_assignment to reschedule instead of cancelling and recreating.
| Parameter | Type | Required | Description |
|---|---|---|---|
assignmentId | UUID | Yes | Assignment UUID |
Example prompt:
"Cancel assignment a1b2c3d4 — I need to update the video first."
Connections
A connection represents an authorized social media channel (YouTube channel, Facebook page). You need a connectionId before you can create assignments.
See Connections REST reference for the underlying API.
list_connections
List all authorized channels.
readOnly: true | destructive: false | idempotent: true | openWorld: false
| Parameter | Type | Required | Description |
|---|---|---|---|
page | int | No | Page number (default: 1) |
limit | int | No | Items per page (default: 10, max: 50) |
platform | string | No | youtube, facebook |
includeInactive | bool | No | Include deactivated connections (default: false) |
Example prompts:
"List all my connected YouTube channels."
"Show me all my social media connections including inactive ones."
get_connection
Get details for a specific connection: token status, channel metadata, and configuration.
readOnly: true | destructive: false | idempotent: true | openWorld: false
If tokenStatus is expired, use get_oauth_connect_url with connectionId to re-authorize that specific channel without losing it.
| Parameter | Type | Required | Description |
|---|---|---|---|
connectionId | UUID | Yes | Connection UUID |
Example prompt:
"Show me the details and token status of my 'Tech Reviews' YouTube channel."
update_connection
Update a connection's display name or active status.
readOnly: false | destructive: false | idempotent: true | openWorld: false
| Parameter | Type | Required | Description |
|---|---|---|---|
connectionId | UUID | Yes | Connection UUID |
name | string | No | New display name |
isActive | bool | No | true to activate, false to deactivate |
Example prompts:
"Rename my YouTube connection a1b2c3d4 to 'Main Channel'."
"Deactivate the Facebook page connection 9a8b7c6d — we're pausing that account."
Analytics
Live analytics tools that query the platform API in real time (YouTube Data API, Meta Graph API). Each call counts against both your Pharlo bill and the platform's own quota.
See Analytics REST reference for the underlying API.
get_channel_stats
Live channel-level metrics for a connection: subscribers, total views, total posts.
readOnly: true | destructive: false | idempotent: true | openWorld: true
| Parameter | Type | Required | Description |
|---|---|---|---|
connectionId | UUID | Yes | Connection UUID |
Example prompts:
"How many subscribers does my 'Tech Reviews' channel have right now?"
"Show me the current view count and post count for all my YouTube channels."
get_post_stats
Live performance metrics for a single published post: views, likes, comments, shares.
readOnly: true | destructive: false | idempotent: true | openWorld: true
| Parameter | Type | Required | Description |
|---|---|---|---|
connectionId | UUID | Yes | Connection UUID the post belongs to |
postId | UUID | Yes | Assignment UUID of the published post |
Example prompts:
"How is my latest video performing?"
"Get the current view and like count for post a1b2c3d4 on my 'Tech Reviews' channel."
get_connection_stats
Current follower/subscriber/view counts for a single connection, served from the latest cached snapshot.
readOnly: true | destructive: false | idempotent: true | openWorld: true
Unlike get_channel_stats, this returns the latest cached snapshot. If the platform API is unavailable, it still returns the last cached values with a note about cache age.
| Parameter | Type | Required | Description |
|---|---|---|---|
connectionId | UUID | Yes | Connection UUID |
Example prompt:
"What's the latest subscriber count for my 'Tech Reviews' channel?"
get_stats
Unified analytics tool. Select a report with the report parameter; aggregated reports are read from Pharlo's own analytics store (no live platform call).
readOnly: true | destructive: false | idempotent: true | openWorld: false
| Report | Description |
|---|---|
overview | High-level totals: channels, posts, success rate |
dashboard | Daily/weekly aggregates, top posts, growth |
analytics | Engagement trends, totals, top posts (80 KB truncation guard) |
recent_posts | Latest published posts with stats (use limit, max 50) |
subscriber_growth | Follower/subscriber growth time series |
publishing_pattern | Post frequency by hour-of-day and day-of-week |
compare | Side-by-side stats for two connections (requires connectionId + compareConnectionId, must differ) |
| Parameter | Type | Required | Description |
|---|---|---|---|
report | string | Yes | One of the report types above |
platform | string | No | youtube, facebook |
connectionId | UUID | No | Limit to a single connection |
dateFrom | ISO 8601 | No | Start of the date range |
dateTo | ISO 8601 | No | End of the date range |
days | int | No | Trailing window in days |
metric | string | No | analytics report: which metric to trend |
contentType | string | No | analytics report: filter by content type |
limit | int | No | recent_posts report: number of posts (max 50) |
compareConnectionId | UUID | No | compare report: the second connection |
Example prompts:
"Give me an overview of all my channels this month."
"Show me my subscriber growth over the last 90 days."
"Compare my two YouTube channels side by side."
OAuth
Authorize a new social channel (YouTube or Meta) for publishing.
See OAuth REST reference for the underlying API.
get_oauth_connect_url
Generate an OAuth consent URL to connect a new channel or re-authorize an existing one.
readOnly: false | destructive: false | idempotent: false | openWorld: true
Two-step flow: call this tool → user opens the returned URL in a browser and completes OAuth → call list_connections to verify the new channel appears (ticket lifetime: 10 minutes).
| Parameter | Type | Required | Description |
|---|---|---|---|
platform | string | Yes | youtube or facebook |
connectionId | UUID | No | Existing connection UUID to re-authorize (omit when connecting a new channel) |
organizationId | UUID | No | Organization to associate the new connection with |
Response includes: url, ticketId, expiresIn, platform, instructions
Example prompts:
"I want to connect my second YouTube channel to Pharlo."
"My YouTube token has expired — re-authorize my 'Tech Reviews' channel."
check_oauth_status
Check whether a recent OAuth connection attempt (started with get_oauth_connect_url) has completed.
readOnly: true | destructive: false | idempotent: true | openWorld: false
Use the ticketId returned by get_oauth_connect_url to poll the flow: pending (user has not finished in the browser yet), success (with connection details), failed (with error details), or expired.
| Parameter | Type | Required | Description |
|---|---|---|---|
ticketId | string | Yes | OAuth ticket ID returned by get_oauth_connect_url |
Example prompt:
"Did my YouTube connection go through?"
Platforms
Platform capabilities describe what each social network supports: content types, payload fields, character limits, allowed values, and file size constraints. Always check capabilities before creating assignments.
See Platform Capabilities REST reference for the underlying API.
list_platforms
List all supported platforms with slugs, display names, and supported content types.
readOnly: true | destructive: false | idempotent: true | openWorld: false
No parameters.
Example prompt:
"What platforms does Pharlo support?"
Example response:
[
{ "slug": "youtube", "name": "YouTube", "hasCapabilities": true, "contentTypes": ["video", "short"] },
{ "slug": "facebook", "name": "Facebook", "hasCapabilities": true, "contentTypes": ["video", "image", "link", "text", "reel", "story"] }
]get_platform_capabilities
Get detailed capabilities for a platform: content types, file size limits, payload fields with types, defaults, and constraints.
readOnly: true | destructive: false | idempotent: true | openWorld: false
Always call this before create_assignment. Platform capabilities tell you exactly which payload fields are available, their types, maximum lengths, and default values — so Claude can build a valid payload without guessing.
| Parameter | Type | Required | Description |
|---|---|---|---|
platform | string | Yes | youtube or facebook |
Example prompt:
"What payload fields does YouTube support for video assignments?"
Example response (abbreviated):
{
"platform": "youtube",
"contentTypes": {
"video": {
"payloadSchema": {
"title": { "type": "string", "required": true, "maxLength": 100 },
"description": { "type": "string", "maxLength": 5000 },
"privacy": { "type": "enum", "values": ["public", "unlisted", "private"], "default": "private" },
"tags": { "type": "array", "items": "string", "maxItems": 500 }
},
"mediaConstraints": {
"maxSizeBytes": 137438953472,
"allowedMimeTypes": ["video/mp4", "video/quicktime", "video/x-msvideo"]
}
}
}
}Webhooks
Webhooks deliver real-time status change notifications to your server. See Webhooks guide and Webhooks REST reference for setup details.
list_webhook_deliveries
List recent webhook delivery attempts with HTTP response codes and error details.
readOnly: true | destructive: false | idempotent: true | openWorld: false
| Parameter | Type | Required | Description |
|---|---|---|---|
status | string | No | pending, delivered, failed |
page | int | No | Page number (default: 1) |
limit | int | No | Items per page (default: 10, max: 50) |
Example prompts:
"Show me recent webhook delivery failures."
"Were all webhooks delivered successfully today?"