@publishq/mcp 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -12,13 +12,13 @@
12
12
  <strong>A Model Context Protocol server that lets AI agents schedule and publish across your social platforms through PublishQ.</strong>
13
13
  </p>
14
14
 
15
- This is the official [MCP](https://modelcontextprotocol.io) server for [PublishQ](https://publishq.com). Point Claude Desktop, Cursor, or any MCP-compatible agent at it and they can list your connected accounts, create and schedule posts, manage workspaces, and upload media — all through the [PublishQ API](https://publishq.com/docs).
15
+ This is the official [MCP](https://modelcontextprotocol.io) server for [PublishQ](https://publishq.com). Point Claude Desktop, Cursor, or any MCP-compatible agent at it and they can list your connected accounts, create and schedule posts, manage workspaces, and upload media, all through the [PublishQ API](https://publishq.com/docs).
16
16
 
17
17
  It runs locally over stdio and talks to the PublishQ API using your API key.
18
18
 
19
19
  ## Setup
20
20
 
21
- You need a PublishQ API key. Create one under **Settings → API Keys** in the PublishQ dashboard (it starts with `pq_live_`).
21
+ You need a PublishQ API key. Create one under **API Keys** in the PublishQ dashboard (it starts with `pq_live_`).
22
22
 
23
23
  ### Claude Desktop
24
24
 
@@ -29,7 +29,7 @@ Add this to your `claude_desktop_config.json`:
29
29
  "mcpServers": {
30
30
  "publishq": {
31
31
  "command": "npx",
32
- "args": ["-y", "@publishq/mcp"],
32
+ "args": ["-y", "@publishq/mcp@latest"],
33
33
  "env": {
34
34
  "PUBLISHQ_API_KEY": "pq_live_your_key_here"
35
35
  }
@@ -42,7 +42,7 @@ Restart Claude Desktop and you'll see the PublishQ tools available. Now you can
42
42
 
43
43
  ### Other clients (Cursor, Windsurf, etc.)
44
44
 
45
- Any MCP client that launches a stdio server works the same way — run the command `npx -y @publishq/mcp` with `PUBLISHQ_API_KEY` set in the environment.
45
+ Any MCP client that launches a stdio server works the same way: run the command `npx -y @publishq/mcp@latest` with `PUBLISHQ_API_KEY` set in the environment.
46
46
 
47
47
  ## Configuration
48
48
 
@@ -68,7 +68,7 @@ Any MCP client that launches a stdio server works the same way — run the comma
68
68
  | `publishq_create_workspace` | Create a workspace |
69
69
  | `publishq_list_media` | List uploaded/generated media |
70
70
  | `publishq_get_media` | Get one media file by ID |
71
- | `publishq_upload_media` | Upload a local file and get a media ID |
71
+ | `publishq_upload_media` | Upload a local file (up to 4 GB) and get a media ID |
72
72
 
73
73
  The tools are thin wrappers over [`@publishq/sdk`](https://www.npmjs.com/package/@publishq/sdk), so their behavior and scopes match the [PublishQ API](https://publishq.com/docs). `publishq_create_post` accepts an `accounts` array whose entries contain `accountId` plus optional `postOverrides` and `platformSpecificSettings`. `publishq_update_post` accepts content, scheduling, complete media replacement or removal, and thumbnail timestamp changes. `publishq_list_media` can filter by media IDs, types, and sources. For TikTok, the agent should call `publishq_get_tiktok_creator_info` first and then provide the required privacy and interaction settings in that account object. A tool call that hits an API error returns the API error so the agent can react.
74
74
 
@@ -78,8 +78,8 @@ Tools require the same API-key scopes as the underlying endpoints: `posts:read`/
78
78
 
79
79
  ## Related
80
80
 
81
- - [`@publishq/sdk`](https://www.npmjs.com/package/@publishq/sdk) — the TypeScript SDK this server is built on.
82
- - [`@publishq/cli`](https://www.npmjs.com/package/@publishq/cli) — command-line interface for the same API.
81
+ - [`@publishq/sdk`](https://www.npmjs.com/package/@publishq/sdk): the TypeScript SDK this server is built on.
82
+ - [`@publishq/cli`](https://www.npmjs.com/package/@publishq/cli): command-line interface for the same API.
83
83
 
84
84
  ## License
85
85
 
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import { readFileSync } from "fs";
4
+ import { openAsBlob, statSync } from "fs";
5
5
  import { basename } from "path";
6
6
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
7
7
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
@@ -27,10 +27,11 @@ import PublishQ, {
27
27
  zUpdatePostPath
28
28
  } from "@publishq/sdk";
29
29
  import { toJSONSchema } from "zod/v4-mini";
30
+ var OPEN_AS_BLOB_MAX_BYTES = 2 ** 32;
30
31
  var API_KEY = process.env.PUBLISHQ_API_KEY;
31
32
  if (!API_KEY) {
32
33
  console.error(
33
- "ERROR: PUBLISHQ_API_KEY environment variable is required. Create a key at https://publishq.com/app/settings."
34
+ "ERROR: PUBLISHQ_API_KEY environment variable is required. Create a key at https://publishq.com/app/api-keys."
34
35
  );
35
36
  process.exit(1);
36
37
  }
@@ -132,7 +133,7 @@ registerTool(
132
133
  {
133
134
  name: "publishq_update_post",
134
135
  title: "Update a post",
135
- description: "Update a draft or scheduled post. Supports content, scheduledAt, complete media replacement/removal through mediaIds, and thumbnailTimestamp. Published and publishing posts cannot be updated.",
136
+ description: "Update a draft or scheduled post. Supports content, scheduledAt, complete media replacement/removal through mediaIds, thumbnailTimestamp, and accounts (each with postOverrides and platformSpecificSettings, for example a YouTube thumbnailMediaId). Only the fields you send change; send a field as null to remove it. Published and publishing posts cannot be updated.",
136
137
  inputSchema: mergedAdvertisedSchema(zUpdatePostPath, zUpdatePostBody),
137
138
  annotations: { readOnlyHint: false, idempotentHint: true, openWorldHint: true }
138
139
  },
@@ -182,7 +183,7 @@ registerTool(
182
183
  {
183
184
  name: "publishq_get_tiktok_creator_info",
184
185
  title: "Get TikTok creator info",
185
- description: "Get a TikTok account's current privacy options, interaction settings, and max video duration. Call this before creating a TikTok post \u2014 the privacyLevel you set must be one of the returned privacyLevelOptions.",
186
+ description: "Get a TikTok account's current privacy options, interaction settings, and max video duration. Call this before creating a TikTok post. The privacyLevel you set must be one of the returned privacyLevelOptions.",
186
187
  inputSchema: advertisedSchema(zGetTikTokCreatorInfoPath),
187
188
  annotations: { readOnlyHint: true, openWorldHint: true }
188
189
  },
@@ -242,7 +243,7 @@ registerTool(
242
243
  {
243
244
  name: "publishq_upload_media",
244
245
  title: "Upload a media file",
245
- description: "Upload a local media file to PublishQ and get back a media ID you can attach to posts via publishq_create_post (mediaIds). The file is read from the local filesystem where this MCP server runs.",
246
+ description: "Upload a local media file of up to 4 GB to PublishQ and get back a media ID you can attach to posts via publishq_create_post (mediaIds). The file is read from the local filesystem where this MCP server runs.",
246
247
  inputSchema: {
247
248
  type: "object",
248
249
  properties: {
@@ -260,11 +261,24 @@ registerTool(
260
261
  },
261
262
  annotations: { readOnlyHint: false, openWorldHint: true }
262
263
  },
263
- (args) => {
264
+ async (args) => {
264
265
  const filePath = args.filePath;
265
266
  const filename = args.filename;
266
- const buffer = readFileSync(filePath);
267
- const file = new File([buffer], filename ?? basename(filePath));
267
+ if (statSync(filePath).size >= OPEN_AS_BLOB_MAX_BYTES) {
268
+ return {
269
+ content: [
270
+ {
271
+ type: "text",
272
+ text: `${filePath} is too big to upload: files must be smaller than 4 GB.`
273
+ }
274
+ ],
275
+ isError: true
276
+ };
277
+ }
278
+ const file = new File(
279
+ [await openAsBlob(filePath)],
280
+ filename ?? basename(filePath)
281
+ );
268
282
  return run(publishq.media.upload({ file }));
269
283
  }
270
284
  );
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@publishq/mcp",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "private": false,
5
- "description": "Model Context Protocol (MCP) server for PublishQ — let AI agents schedule and publish across your social platforms.",
5
+ "description": "Model Context Protocol (MCP) server for PublishQ. Let AI agents schedule and publish across your social platforms.",
6
6
  "license": "Apache-2.0",
7
7
  "author": "PublishQ",
8
8
  "homepage": "https://publishq.com",
@@ -25,8 +25,8 @@
25
25
  ],
26
26
  "dependencies": {
27
27
  "@modelcontextprotocol/sdk": "1.29.0",
28
- "zod": "4.4.3",
29
- "@publishq/sdk": "^0.0.1"
28
+ "@publishq/sdk": "^0.0.3",
29
+ "zod": "4.4.3"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@types/node": "^20",