@publishq/mcp 0.0.6 → 0.0.7

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
@@ -51,10 +51,7 @@ Add this to your `claude_desktop_config.json`:
51
51
  "mcpServers": {
52
52
  "publishq": {
53
53
  "command": "npx",
54
- "args": ["-y", "@publishq/mcp@latest"],
55
- "env": {
56
- "PUBLISHQ_API_KEY": "pq_live_your_key_here"
57
- }
54
+ "args": ["-y", "@publishq/mcp@latest"]
58
55
  }
59
56
  }
60
57
  }
@@ -91,6 +88,7 @@ Any MCP client that launches a stdio server works the same way: run the command
91
88
  | `publishq_list_media` | List uploaded/generated media |
92
89
  | `publishq_get_media` | Get one media file by ID |
93
90
  | `publishq_upload_media` | Upload a file and get a media ID: a local path (local server) or a link or chat attachment (hosted server) |
91
+ | `publishq_create_media_upload` | Get a signed URL to upload a file from your own disk, up to 4 GB |
94
92
  | `publishq_delete_media` | Delete a media file no draft or scheduled post uses |
95
93
 
96
94
  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.
package/dist/index.js CHANGED
@@ -16,6 +16,7 @@ import {
16
16
  McpError
17
17
  } from "@modelcontextprotocol/sdk/types.js";
18
18
  import {
19
+ zCreateMediaUploadBody,
19
20
  zCreatePostBody,
20
21
  zCreateWorkspaceBody,
21
22
  zDeleteMediaPath,
@@ -66,8 +67,38 @@ async function run(call) {
66
67
  return errorResult(error);
67
68
  }
68
69
  }
70
+ var isPlainObject = (value) => !!value && typeof value === "object" && !Array.isArray(value);
71
+ var isAnnotationOnly = (node) => isPlainObject(node) && Object.keys(node).every((key) => key === "description" || key === "title");
72
+ var isEmpty = (value) => isPlainObject(value) && Object.keys(value).length === 0;
73
+ function booleanSchema(value) {
74
+ if (isEmpty(value)) return true;
75
+ if (isPlainObject(value) && Object.keys(value).length === 1 && isEmpty(value.not)) {
76
+ return false;
77
+ }
78
+ return void 0;
79
+ }
80
+ function portableSchema(node) {
81
+ if (Array.isArray(node)) return node.map(portableSchema);
82
+ if (!isPlainObject(node)) return node;
83
+ const result = {};
84
+ for (const [key, value] of Object.entries(node)) {
85
+ result[key] = key === "additionalProperties" ? booleanSchema(value) ?? portableSchema(value) : portableSchema(value);
86
+ }
87
+ const allOf = result.allOf;
88
+ if (Array.isArray(allOf)) {
89
+ const annotations = allOf.filter(isAnnotationOnly);
90
+ const schemas = allOf.filter((member) => !isAnnotationOnly(member));
91
+ if (annotations.length > 0 && schemas.length === 1 && isPlainObject(schemas[0])) {
92
+ delete result.allOf;
93
+ return { ...Object.assign({}, ...annotations), ...schemas[0], ...result };
94
+ }
95
+ }
96
+ return result;
97
+ }
69
98
  function advertisedSchema(schema) {
70
- const jsonSchema = toJSONSchema(schema, { io: "input", target: "draft-7" });
99
+ const jsonSchema = portableSchema(
100
+ toJSONSchema(schema, { io: "input", target: "draft-7" })
101
+ );
71
102
  if (jsonSchema.type !== "object") {
72
103
  throw new Error("MCP tool input schema must describe an object.");
73
104
  }
@@ -233,6 +264,16 @@ function publishqTools(publishq2) {
233
264
  },
234
265
  (args) => run(publishq2.media.get(args.id))
235
266
  );
267
+ register(
268
+ {
269
+ name: "publishq_create_media_upload",
270
+ title: "Start a media upload",
271
+ description: 'Get a signed upload URL for a file of up to 4 GB on the machine you run commands on, and the media ID it becomes. Send the file with a PUT to uploadUrl, with the same Content-Type and no Authorization header, for example `curl -X PUT -H "Content-Type: image/jpeg" --upload-file ./photo.jpg "<uploadUrl>"`. Then attach the media ID to a post through mediaIds. The URL expires after an hour.',
272
+ inputSchema: advertisedSchema(zCreateMediaUploadBody),
273
+ annotations: { readOnlyHint: false, openWorldHint: true }
274
+ },
275
+ (args) => run(publishq2.media.createUpload(args))
276
+ );
236
277
  register(
237
278
  {
238
279
  name: "publishq_delete_media",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@publishq/mcp",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "private": false,
5
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",
@@ -31,7 +31,7 @@
31
31
  "dependencies": {
32
32
  "@modelcontextprotocol/sdk": "1.29.0",
33
33
  "zod": "4.4.3",
34
- "@publishq/sdk": "^0.0.6"
34
+ "@publishq/sdk": "^0.0.7"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@types/node": "^20",