@postdom/mcp
Version:
Postdom MCP server for agent-led social publishing and performance measurement.
272 lines (266 loc) • 10.4 kB
TypeScript
import { z } from 'zod';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
declare const corePlatformSchema: z.ZodEnum<{
tiktok: "tiktok";
instagram: "instagram";
youtube: "youtube";
facebook: "facebook";
twitter: "twitter";
linkedin: "linkedin";
bluesky: "bluesky";
snapchat: "snapchat";
threads: "threads";
}>;
type CorePlatform = z.infer<typeof corePlatformSchema>;
declare const mediaUploadPreflightRequestSchema: z.ZodObject<{
content_type: z.ZodEnum<{
"video/mp4": "video/mp4";
"video/quicktime": "video/quicktime";
}>;
size_bytes: z.ZodNumber;
platforms: z.ZodArray<z.ZodEnum<{
tiktok: "tiktok";
instagram: "instagram";
youtube: "youtube";
facebook: "facebook";
twitter: "twitter";
linkedin: "linkedin";
bluesky: "bluesky";
snapchat: "snapchat";
threads: "threads";
}>>;
width_pixels: z.ZodNumber;
height_pixels: z.ZodNumber;
duration_seconds: z.ZodNumber;
}, z.core.$strip>;
type MediaUploadPreflightRequest = z.infer<typeof mediaUploadPreflightRequestSchema>;
declare const mediaUploadResponseSchema: z.ZodObject<{
media_handle: z.ZodString;
upload_url: z.ZodURL;
method: z.ZodLiteral<"PUT">;
headers: z.ZodObject<{
"Content-Type": z.ZodString;
"Content-Length": z.ZodString;
}, z.core.$strip>;
expires_at: z.ZodISODateTime;
}, z.core.$strip>;
type MediaUploadResponse = z.infer<typeof mediaUploadResponseSchema>;
declare const mediaStatusResponseSchema: z.ZodObject<{
media_handle: z.ZodString;
status: z.ZodEnum<{
pending: "pending";
failed: "failed";
stored: "stored";
}>;
content_type: z.ZodEnum<{
"video/mp4": "video/mp4";
"video/quicktime": "video/quicktime";
}>;
size_bytes: z.ZodNumber;
media_url: z.ZodNullable<z.ZodURL>;
failure_reason: z.ZodNullable<z.ZodString>;
}, z.core.$strip>;
type MediaStatusResponse = z.infer<typeof mediaStatusResponseSchema>;
declare const learningModelResultSchema: z.ZodObject<{
candidate: z.ZodEnum<{
shorten_caption: "shorten_caption";
abstain: "abstain";
}>;
reason: z.ZodEnum<{
observed_association: "observed_association";
insufficient_data: "insufficient_data";
customer_constraint: "customer_constraint";
prior_trial_not_supportive: "prior_trial_not_supportive";
no_directional_association: "no_directional_association";
source_unavailable: "source_unavailable";
}>;
sourcePostIds: z.ZodArray<z.ZodUUID>;
}, z.core.$strict>;
type LearningModelResult = z.infer<typeof learningModelResultSchema>;
type LearningExclusion = "wrong_scope" | "wrong_format" | "source_unavailable" | "outside_cohort_window" | "content_revision_unproven" | "missing_observation" | "wrong_observation_age" | "missing_measurement" | "source_conflict" | "customer_promoted" | "customer_excluded";
interface LearningEvidenceEntry {
postId: string;
publishId: string;
postVersion: string;
requestHash: string;
publishedAt: string | null;
captionCodePoints: number | null;
snapshot: {
id: string;
hash: string;
capturedAt: string;
ageHours: number;
} | null;
detectionSnapshots: {
id: string;
hash: string;
capturedAt: string;
}[];
value: number | null;
exclusion: LearningExclusion | null;
}
interface LearningGroup {
n: number;
median: number | null;
minimum: number | null;
maximum: number | null;
}
interface LearningEvidence {
state: "available" | "insufficient_data" | "unavailable";
definition: "tiktok-reported-views-v1";
unit: "reported_view_count";
observedAt: string;
short: LearningGroup;
long: LearningGroup;
sources: LearningEvidenceEntry[];
candidate: LearningModelResult;
caveats: string[];
}
type PostdomPlatform = CorePlatform;
declare const POSTDOM_MCP_VERSION = "0.4.0";
/**
* Every version of this package that has actually been published to npm, oldest
* first.
*
* The manifest version is what the next publish will carry. This is what a
* customer can install today, and the two are the same only after a publish has
* happened. They were treated as one number, so bumping the manifest silently
* rewrote every install instruction on the marketing site to a version npm does
* not have. A version is added here by the act of publishing it, never ahead of
* it: this list is evidence, not intent.
*/
declare const POSTDOM_MCP_PUBLISHED_VERSIONS: readonly ["0.1.0", "0.2.0", "0.3.0"];
declare const performanceMetricSchema: z.ZodEnum<{
views: "views";
likes: "likes";
comments: "comments";
shares: "shares";
saves: "saves";
watch_time_s: "watch_time_s";
avg_watch_pct: "avg_watch_pct";
completion_pct: "completion_pct";
follower_delta: "follower_delta";
}>;
type PerformanceMetric = z.infer<typeof performanceMetricSchema>;
interface PostdomAccount {
id?: string;
orgId?: string;
providerAccountId: string;
platform: string;
handle?: string | null;
status: string;
}
interface PostdomClientOptions {
apiKey: string;
baseUrl?: string;
fetch?: typeof globalThis.fetch;
agentIdentity?: string;
}
declare const POSTDOM_MCP_TOOL_NAMES: readonly ["get_workspace_status", "get_brief", "get_digest", "get_learning", "list_accounts", "connect_account", "upload_media", "get_media", "publish_video", "submit_plan", "get_plan", "get_publish", "get_performance", "get_best_posts"];
/** A failed API call with its problem document's structured fields intact. */
declare class PostdomApiError extends Error {
readonly status: number;
readonly code: string | null;
readonly destinations: readonly {
platform: string;
fact: string;
}[];
constructor(message: string, status: number, code: string | null, destinations: readonly {
platform: string;
fact: string;
}[]);
}
declare class PostdomClient {
private readonly options;
private readonly baseUrl;
private readonly fetch;
constructor(options: PostdomClientOptions);
request<T>(path: string, init?: RequestInit): Promise<T>;
listAccounts(): Promise<PostdomAccount[]>;
getWorkspaceStatus(): Promise<Record<string, unknown>>;
connectAccount(platform: PostdomPlatform): Promise<Record<string, unknown>>;
createMediaUpload(input: MediaUploadPreflightRequest): Promise<MediaUploadResponse>;
getMedia(mediaHandle: string): Promise<MediaStatusResponse>;
publishVideo(input: {
accountIds: string[];
videoUrl?: string;
mediaHandle?: string;
caption: string;
intent: string;
agentIdentity?: string;
publishAt?: string;
planId?: string;
idempotencyKey?: string;
}): Promise<Record<string, unknown>>;
submitPlan(input: {
accountIds: string[];
title: string;
objective: string;
startsAt: string;
endsAt: string;
maxPosts: number;
briefVersion?: number;
intent: string;
agentIdentity?: string;
idempotencyKey?: string;
}): Promise<Record<string, unknown>>;
getPlan(planId: string): Promise<Record<string, unknown>>;
getBrief(): Promise<Record<string, unknown>>;
getDigest(): Promise<Record<string, unknown>>;
getLearning(raw?: unknown): Promise<{
learning: {
scopeId: string;
accountId: string | null;
revision: string | null;
state: "not_configured" | "unavailable" | "ready" | "waiting" | "invalidated" | "forgotten" | "analysis_deferred";
reason: string | null;
checkedAt: string;
nextScanAt: string | null;
latest: {
id: string;
version: string;
kind: "hypothesis" | "evaluation";
createdAt: string;
expiresAt: string;
evidence: LearningEvidence;
result: {
candidate: {
candidate: "shorten_caption" | "abstain";
reason: "observed_association" | "insufficient_data" | "customer_constraint" | "prior_trial_not_supportive" | "no_directional_association" | "source_unavailable";
sourcePostIds: string[];
};
evaluation?: {
state: "inconclusive" | "evaluated";
reason: string;
value: number | null;
} | undefined;
};
} | null;
experiment: {
state: "draft" | "inconclusive" | "evaluated" | "creating_draft" | "awaiting_publication" | "awaiting_observations";
reason: string | null;
postId: string | null;
publishId: string | null;
} | null;
retained: {
rejectedShortCaption: boolean;
priorTrialNotSupportive: boolean;
exclusions: {
postId: string;
reason: "customer_promoted" | "customer_excluded" | "source_conflict";
}[];
} | null;
} | null;
}>;
getPublish(postId: string): Promise<Record<string, unknown>>;
getPostPerformance(postId: string): Promise<Record<string, unknown>>;
getAccountPerformance(accountId: string, window: "7d" | "30d"): Promise<Record<string, unknown>>;
getBestPosts(accountId: string, metric: PerformanceMetric, window: "7d" | "30d"): Promise<Record<string, unknown>>;
}
declare function createPostdomMcpServer(client: PostdomClient): McpServer;
/**
* Serve the same runtime used by the stdio CLI over stateless Streamable HTTP.
* Authentication belongs to the hosting API and must run before this handler.
*/
declare function handlePostdomMcpHttpRequest(request: Request, options: PostdomClientOptions): Promise<Response>;
export { POSTDOM_MCP_PUBLISHED_VERSIONS, POSTDOM_MCP_TOOL_NAMES, POSTDOM_MCP_VERSION, type PostdomAccount, PostdomApiError, PostdomClient, type PostdomClientOptions, type PostdomPlatform, createPostdomMcpServer, handlePostdomMcpHttpRequest };