@onlypult/mcp 0.1.0
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/LICENSE +21 -0
- package/README.md +94 -0
- package/dist/api-client.d.ts +23 -0
- package/dist/api-client.js +74 -0
- package/dist/api-client.js.map +1 -0
- package/dist/api-error.d.ts +9 -0
- package/dist/api-error.js +28 -0
- package/dist/api-error.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +73 -0
- package/dist/cli.js.map +1 -0
- package/dist/media-upload.d.ts +28 -0
- package/dist/media-upload.js +123 -0
- package/dist/media-upload.js.map +1 -0
- package/dist/package-version.d.ts +2 -0
- package/dist/package-version.js +10 -0
- package/dist/package-version.js.map +1 -0
- package/dist/schemas/platform-options.d.ts +1145 -0
- package/dist/schemas/platform-options.js +80 -0
- package/dist/schemas/platform-options.js.map +1 -0
- package/dist/tools/media.d.ts +3 -0
- package/dist/tools/media.js +170 -0
- package/dist/tools/media.js.map +1 -0
- package/dist/tools/posts.d.ts +3 -0
- package/dist/tools/posts.js +188 -0
- package/dist/tools/posts.js.map +1 -0
- package/dist/tools/profiles.d.ts +3 -0
- package/dist/tools/profiles.js +98 -0
- package/dist/tools/profiles.js.map +1 -0
- package/dist/types.d.ts +50 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +49 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Onlypult
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# @onlypult/mcp
|
|
2
|
+
|
|
3
|
+
Local MCP (Model Context Protocol) server for [Onlypult](https://onlypult.com), for use with Cursor, Claude Desktop, Windsurf, and other MCP-compatible AI tools that run stdio servers **on your own machine**.
|
|
4
|
+
|
|
5
|
+
Running locally means the AI agent can read files directly from your disk — so `media_upload_file` can post a screenshot or a video by path (`./photo.jpg`), with no browser step.
|
|
6
|
+
|
|
7
|
+
> Just want profiles/posts/scheduling and don't need local file uploads? You can also connect directly to the hosted server at `https://mcp.onlypult.com/mcp` with no install — see [onlypult.com/dev/mcp.html](https://onlypult.com/dev/mcp.html). This package exists specifically for the local-file-upload case.
|
|
8
|
+
|
|
9
|
+
## Install / configure
|
|
10
|
+
|
|
11
|
+
You don't need to install anything by hand — your MCP client runs it via `npx`.
|
|
12
|
+
|
|
13
|
+
Get an API key from **Onlypult → Settings → API Keys** (starts with `op_`).
|
|
14
|
+
|
|
15
|
+
### Cursor
|
|
16
|
+
|
|
17
|
+
`.cursor/mcp.json`:
|
|
18
|
+
|
|
19
|
+
```json
|
|
20
|
+
{
|
|
21
|
+
"mcpServers": {
|
|
22
|
+
"onlypult": {
|
|
23
|
+
"command": "npx",
|
|
24
|
+
"args": ["-y", "@onlypult/mcp@latest"],
|
|
25
|
+
"env": {
|
|
26
|
+
"ONLYPULT_API_KEY": "op_your_key_here"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Claude Desktop
|
|
34
|
+
|
|
35
|
+
`claude_desktop_config.json` (macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`, Windows: `%APPDATA%/Claude/claude_desktop_config.json`):
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"mcpServers": {
|
|
40
|
+
"onlypult": {
|
|
41
|
+
"command": "npx",
|
|
42
|
+
"args": ["-y", "@onlypult/mcp@latest"],
|
|
43
|
+
"env": {
|
|
44
|
+
"ONLYPULT_API_KEY": "op_your_key_here"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Restart Cursor / Claude Desktop after editing the config.
|
|
52
|
+
|
|
53
|
+
## What this package does
|
|
54
|
+
|
|
55
|
+
It's a thin Node.js wrapper around the Onlypult Public REST API (`https://api.onlypult.com/v1`), exposed as MCP tools:
|
|
56
|
+
|
|
57
|
+
| Tool | Description |
|
|
58
|
+
|---|---|
|
|
59
|
+
| `account_get` | Timezone, plan end date, publish_at format |
|
|
60
|
+
| `profiles_list` / `profiles_get` / `profiles_platforms_list` | Connected social accounts |
|
|
61
|
+
| `profiles_get_pinterest_boards` / `profiles_get_youtube_categories` | Platform-specific lookups |
|
|
62
|
+
| `posts_create` / `posts_create_story` / `posts_create_reels` / `posts_create_shorts` | Create posts |
|
|
63
|
+
| `posts_publish_now` / `posts_cross_post` | Convenience shortcuts |
|
|
64
|
+
| `posts_list` / `posts_list_failed` / `posts_get` | Read posts |
|
|
65
|
+
| `posts_update` / `posts_delete` | Modify posts |
|
|
66
|
+
| `posts_retry` / `posts_retry_all_failed` | Retry failed posts |
|
|
67
|
+
| `media_get_upload_url` / `media_check_status` | Browser-based upload (works anywhere) |
|
|
68
|
+
| **`media_upload_file`** | **Upload a local file by path — only works because this server runs on your machine** |
|
|
69
|
+
|
|
70
|
+
Full tool/parameter reference: [onlypult.com/dev/mcp.html](https://onlypult.com/dev/mcp.html) / [mcp.md](https://onlypult.com/dev/mcp.md).
|
|
71
|
+
|
|
72
|
+
## Requirements
|
|
73
|
+
|
|
74
|
+
- Node.js 18+
|
|
75
|
+
- An Onlypult API key (`op_...`) — Settings → API Keys in the dashboard
|
|
76
|
+
|
|
77
|
+
## Environment variables
|
|
78
|
+
|
|
79
|
+
| Variable | Required | Description |
|
|
80
|
+
|---|---|---|
|
|
81
|
+
| `ONLYPULT_API_KEY` | Yes | Your personal API key, `op_...` |
|
|
82
|
+
| `ONLYPULT_API_URL` | No | Override API base URL (default `https://api.onlypult.com`) — for self-hosted/staging use |
|
|
83
|
+
|
|
84
|
+
## Troubleshooting
|
|
85
|
+
|
|
86
|
+
**"missing Onlypult API key"** — `ONLYPULT_API_KEY` isn't set in your MCP client config's `env` block, or doesn't start with `op_`.
|
|
87
|
+
|
|
88
|
+
**Tools show up but calls fail with 401** — key may be revoked or mistyped. Re-copy it from Settings → API Keys.
|
|
89
|
+
|
|
90
|
+
**`media_upload_file` says it can't read the path** — the path must be readable by the process Cursor/Claude Desktop launched (your machine, since this is the local package). Use an absolute path if a relative one doesn't resolve as expected.
|
|
91
|
+
|
|
92
|
+
## License
|
|
93
|
+
|
|
94
|
+
MIT
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export declare const API_BASE: string;
|
|
2
|
+
export interface PaginatedResponse<T> {
|
|
3
|
+
items: T;
|
|
4
|
+
meta: {
|
|
5
|
+
total: number;
|
|
6
|
+
page: number;
|
|
7
|
+
limit: number;
|
|
8
|
+
pages: number;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export declare class OnlypultApiError extends Error {
|
|
12
|
+
readonly status: number;
|
|
13
|
+
readonly body: unknown;
|
|
14
|
+
constructor(status: number, body: unknown, message: string);
|
|
15
|
+
}
|
|
16
|
+
export declare function postForm<T>(apiKey: string, path: string, form: FormData): Promise<T>;
|
|
17
|
+
export declare function createApiClient(apiKey: string): {
|
|
18
|
+
get: <T>(path: string, query?: Record<string, string | number | boolean | undefined>) => Promise<T>;
|
|
19
|
+
post: <T>(path: string, body?: unknown) => Promise<T>;
|
|
20
|
+
put: <T>(path: string, body?: unknown) => Promise<T>;
|
|
21
|
+
delete: <T>(path: string) => Promise<T>;
|
|
22
|
+
};
|
|
23
|
+
export type ApiClient = ReturnType<typeof createApiClient>;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
export const API_BASE = process.env.ONLYPULT_API_URL ?? 'https://api.onlypult.com';
|
|
2
|
+
function unwrapResponse(data) {
|
|
3
|
+
if (data !== null && typeof data === 'object' && 'data' in data) {
|
|
4
|
+
const envelope = data;
|
|
5
|
+
if (envelope.meta !== undefined) {
|
|
6
|
+
return { items: envelope.data, meta: envelope.meta };
|
|
7
|
+
}
|
|
8
|
+
return envelope.data;
|
|
9
|
+
}
|
|
10
|
+
return data;
|
|
11
|
+
}
|
|
12
|
+
export class OnlypultApiError extends Error {
|
|
13
|
+
status;
|
|
14
|
+
body;
|
|
15
|
+
constructor(status, body, message) {
|
|
16
|
+
super(message);
|
|
17
|
+
this.status = status;
|
|
18
|
+
this.body = body;
|
|
19
|
+
this.name = 'OnlypultApiError';
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
async function request(apiKey, method, path, body, query) {
|
|
23
|
+
const url = new URL(`${API_BASE}${path}`);
|
|
24
|
+
if (query) {
|
|
25
|
+
for (const [key, value] of Object.entries(query)) {
|
|
26
|
+
if (value !== undefined) {
|
|
27
|
+
url.searchParams.set(key, String(value));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const res = await fetch(url.toString(), {
|
|
32
|
+
method,
|
|
33
|
+
headers: {
|
|
34
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
35
|
+
'Content-Type': 'application/json',
|
|
36
|
+
'Accept': 'application/json',
|
|
37
|
+
},
|
|
38
|
+
body: body !== undefined ? JSON.stringify(body) : undefined,
|
|
39
|
+
});
|
|
40
|
+
const data = await res.json().catch(() => null);
|
|
41
|
+
if (!res.ok) {
|
|
42
|
+
const body = data;
|
|
43
|
+
const message = body?.error?.message ?? body?.message ?? `HTTP ${res.status}`;
|
|
44
|
+
throw new OnlypultApiError(res.status, data, message);
|
|
45
|
+
}
|
|
46
|
+
return unwrapResponse(data);
|
|
47
|
+
}
|
|
48
|
+
export async function postForm(apiKey, path, form) {
|
|
49
|
+
const url = `${API_BASE}${path}`;
|
|
50
|
+
const res = await fetch(url, {
|
|
51
|
+
method: 'POST',
|
|
52
|
+
headers: {
|
|
53
|
+
Authorization: `Bearer ${apiKey}`,
|
|
54
|
+
Accept: 'application/json',
|
|
55
|
+
},
|
|
56
|
+
body: form,
|
|
57
|
+
});
|
|
58
|
+
const data = await res.json().catch(() => null);
|
|
59
|
+
if (!res.ok) {
|
|
60
|
+
const body = data;
|
|
61
|
+
const message = body?.error?.message ?? body?.message ?? `HTTP ${res.status}`;
|
|
62
|
+
throw new OnlypultApiError(res.status, data, message);
|
|
63
|
+
}
|
|
64
|
+
return unwrapResponse(data);
|
|
65
|
+
}
|
|
66
|
+
export function createApiClient(apiKey) {
|
|
67
|
+
return {
|
|
68
|
+
get: (path, query) => request(apiKey, 'GET', path, undefined, query),
|
|
69
|
+
post: (path, body) => request(apiKey, 'POST', path, body),
|
|
70
|
+
put: (path, body) => request(apiKey, 'PUT', path, body),
|
|
71
|
+
delete: (path) => request(apiKey, 'DELETE', path),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=api-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.js","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { OnlypultApiError } from './api-client.js';
|
|
2
|
+
export declare function formatApiErrorForAgent(err: OnlypultApiError): string;
|
|
3
|
+
export declare function apiErrorResult(err: unknown): {
|
|
4
|
+
isError: true;
|
|
5
|
+
content: {
|
|
6
|
+
type: "text";
|
|
7
|
+
text: string;
|
|
8
|
+
}[];
|
|
9
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { OnlypultApiError } from './api-client.js';
|
|
2
|
+
export function formatApiErrorForAgent(err) {
|
|
3
|
+
const body = err.body;
|
|
4
|
+
if (body?.error?.message) {
|
|
5
|
+
const { code, message, retryable, field } = body.error;
|
|
6
|
+
const lines = [
|
|
7
|
+
`Error: ${message}`,
|
|
8
|
+
code ? `Code: ${code}` : null,
|
|
9
|
+
field ? `Field: ${field}` : null,
|
|
10
|
+
retryable === false ? 'Do NOT retry this request — fix the issue first (e.g. renew plan or choose an earlier publish_at).' : null,
|
|
11
|
+
].filter(Boolean);
|
|
12
|
+
return lines.join('\n');
|
|
13
|
+
}
|
|
14
|
+
if (body) {
|
|
15
|
+
return `API error (${err.status}): ${JSON.stringify(body, null, 2)}`;
|
|
16
|
+
}
|
|
17
|
+
return `API error (${err.status}): ${err.message}`;
|
|
18
|
+
}
|
|
19
|
+
export function apiErrorResult(err) {
|
|
20
|
+
if (err instanceof OnlypultApiError) {
|
|
21
|
+
return {
|
|
22
|
+
isError: true,
|
|
23
|
+
content: [{ type: 'text', text: formatApiErrorForAgent(err) }],
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
throw err;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=api-error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-error.js","sourceRoot":"","sources":["../src/api-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAYnD,MAAM,UAAU,sBAAsB,CAAC,GAAqB;IAC1D,MAAM,IAAI,GAAG,GAAG,CAAC,IAA2B,CAAC;IAE7C,IAAI,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;QACzB,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;QACvD,MAAM,KAAK,GAAG;YACZ,UAAU,OAAO,EAAE;YACnB,IAAI,CAAC,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI;YAC7B,KAAK,CAAC,CAAC,CAAC,UAAU,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI;YAChC,SAAS,KAAK,KAAK,CAAC,CAAC,CAAC,oGAAoG,CAAC,CAAC,CAAC,IAAI;SAClI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAElB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,IAAI,IAAI,EAAE,CAAC;QACT,OAAO,cAAc,GAAG,CAAC,MAAM,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;IACvE,CAAC;IAED,OAAO,cAAc,GAAG,CAAC,MAAM,MAAM,GAAG,CAAC,OAAO,EAAE,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAY;IACzC,IAAI,GAAG,YAAY,gBAAgB,EAAE,CAAC;QACpC,OAAO;YACL,OAAO,EAAE,IAAa;YACtB,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,sBAAsB,CAAC,GAAG,CAAC,EAAE,CAAC;SACxE,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,CAAC;AACZ,CAAC"}
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @onlypult/mcp — local stdio entrypoint.
|
|
4
|
+
*
|
|
5
|
+
* This is the entrypoint end users run via `npx @onlypult/mcp`.
|
|
6
|
+
* It only supports stdio transport (Cursor, Claude Desktop, Windsurf, etc.)
|
|
7
|
+
* and requires ONLYPULT_API_KEY to be set. It intentionally does not
|
|
8
|
+
* include the HTTP/OAuth machinery used by the hosted mcp.onlypult.com
|
|
9
|
+
* server (see the onlypult-mcp deploy repo).
|
|
10
|
+
*/
|
|
11
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
12
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
13
|
+
import { createApiClient } from './api-client.js';
|
|
14
|
+
import { readPackageVersion } from './package-version.js';
|
|
15
|
+
import { registerProfileTools } from './tools/profiles.js';
|
|
16
|
+
import { registerPostTools } from './tools/posts.js';
|
|
17
|
+
import { registerMediaTools } from './tools/media.js';
|
|
18
|
+
const API_KEY_PREFIX = 'op_';
|
|
19
|
+
const PACKAGE_VERSION = readPackageVersion();
|
|
20
|
+
function readApiKey() {
|
|
21
|
+
const fromEnv = process.env.ONLYPULT_API_KEY?.trim();
|
|
22
|
+
if (fromEnv)
|
|
23
|
+
return fromEnv;
|
|
24
|
+
const argIndex = process.argv.findIndex((a) => a === '--api-key');
|
|
25
|
+
if (argIndex !== -1 && process.argv[argIndex + 1]) {
|
|
26
|
+
return process.argv[argIndex + 1].trim();
|
|
27
|
+
}
|
|
28
|
+
console.error([
|
|
29
|
+
'Error: missing Onlypult API key.',
|
|
30
|
+
'',
|
|
31
|
+
'Set ONLYPULT_API_KEY in your MCP client config, e.g.:',
|
|
32
|
+
'',
|
|
33
|
+
'{',
|
|
34
|
+
' "mcpServers": {',
|
|
35
|
+
' "onlypult": {',
|
|
36
|
+
' "command": "npx",',
|
|
37
|
+
' "args": ["-y", "@onlypult/mcp@latest"],',
|
|
38
|
+
' "env": { "ONLYPULT_API_KEY": "op_your_key_here" }',
|
|
39
|
+
' }',
|
|
40
|
+
' }',
|
|
41
|
+
'}',
|
|
42
|
+
'',
|
|
43
|
+
'Get a key from Onlypult → Settings → API Keys.',
|
|
44
|
+
].join('\n'));
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
function validateApiKey(key) {
|
|
48
|
+
if (!key.startsWith(API_KEY_PREFIX)) {
|
|
49
|
+
console.error(`Error: ONLYPULT_API_KEY must start with "${API_KEY_PREFIX}". Get a key from Onlypult → Settings → API Keys.`);
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async function main() {
|
|
54
|
+
const apiKey = readApiKey();
|
|
55
|
+
validateApiKey(apiKey);
|
|
56
|
+
const server = new McpServer({ name: 'onlypult-local', version: PACKAGE_VERSION }, { capabilities: { tools: {} } });
|
|
57
|
+
const ctx = () => ({
|
|
58
|
+
api: createApiClient(apiKey),
|
|
59
|
+
apiKey,
|
|
60
|
+
});
|
|
61
|
+
registerProfileTools(server, ctx);
|
|
62
|
+
registerPostTools(server, ctx);
|
|
63
|
+
registerMediaTools(server, ctx);
|
|
64
|
+
const transport = new StdioServerTransport();
|
|
65
|
+
await server.connect(transport);
|
|
66
|
+
// stdout is reserved for JSON-RPC; log startup to stderr only.
|
|
67
|
+
console.error(`Onlypult MCP (local) v${PACKAGE_VERSION} running via stdio — local file uploads enabled.`);
|
|
68
|
+
}
|
|
69
|
+
main().catch((err) => {
|
|
70
|
+
console.error('Fatal error starting Onlypult MCP server:', err);
|
|
71
|
+
process.exit(1);
|
|
72
|
+
});
|
|
73
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type ApiClient } from './api-client.js';
|
|
2
|
+
export interface UploadSession {
|
|
3
|
+
token: string;
|
|
4
|
+
upload_url: string;
|
|
5
|
+
}
|
|
6
|
+
export interface UploadedMediaFile {
|
|
7
|
+
id: string;
|
|
8
|
+
url: string | null;
|
|
9
|
+
type: string | null;
|
|
10
|
+
filename: string | null;
|
|
11
|
+
token: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function guessMimeType(fileName: string): string;
|
|
14
|
+
export declare function assertReadableLocalFile(filePath: string): Promise<{
|
|
15
|
+
resolved: string;
|
|
16
|
+
size: number;
|
|
17
|
+
fileName: string;
|
|
18
|
+
}>;
|
|
19
|
+
export declare function createUploadSession(api: ApiClient, options?: {
|
|
20
|
+
is_story?: boolean;
|
|
21
|
+
is_reels?: boolean;
|
|
22
|
+
}): Promise<UploadSession>;
|
|
23
|
+
export declare function uploadLocalFile(apiKey: string, api: ApiClient, filePath: string, options?: {
|
|
24
|
+
token?: string;
|
|
25
|
+
is_story?: boolean;
|
|
26
|
+
is_reels?: boolean;
|
|
27
|
+
}): Promise<UploadedMediaFile>;
|
|
28
|
+
export declare function isLocalFileUploadError(err: unknown): boolean;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { access, readFile, stat } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { OnlypultApiError, postForm } from './api-client.js';
|
|
4
|
+
const CHUNK_SIZE = 5 * 1024 * 1024;
|
|
5
|
+
const MIME_BY_EXT = {
|
|
6
|
+
'.jpg': 'image/jpeg',
|
|
7
|
+
'.jpeg': 'image/jpeg',
|
|
8
|
+
'.png': 'image/png',
|
|
9
|
+
'.webp': 'image/webp',
|
|
10
|
+
'.gif': 'image/gif',
|
|
11
|
+
'.mp4': 'video/mp4',
|
|
12
|
+
'.mov': 'video/quicktime',
|
|
13
|
+
'.webm': 'video/webm',
|
|
14
|
+
};
|
|
15
|
+
export function guessMimeType(fileName) {
|
|
16
|
+
const ext = path.extname(fileName).toLowerCase();
|
|
17
|
+
return MIME_BY_EXT[ext] ?? 'application/octet-stream';
|
|
18
|
+
}
|
|
19
|
+
export async function assertReadableLocalFile(filePath) {
|
|
20
|
+
const resolved = path.resolve(filePath.trim());
|
|
21
|
+
if (resolved === '' || resolved === path.sep) {
|
|
22
|
+
throw new Error('file_path is required');
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
await access(resolved);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
throw new Error(`Cannot read file at "${resolved}". `
|
|
29
|
+
+ 'media_upload_file only works when the MCP server runs on the same machine as the file '
|
|
30
|
+
+ '(local Cursor / Claude Desktop stdio). For remote MCP (Claude.ai, ChatGPT) or files outside '
|
|
31
|
+
+ 'the server host, use media_get_upload_url or media_urls in posts_create.');
|
|
32
|
+
}
|
|
33
|
+
const fileStat = await stat(resolved);
|
|
34
|
+
if (!fileStat.isFile()) {
|
|
35
|
+
throw new Error(`Path is not a file: ${resolved}`);
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
resolved,
|
|
39
|
+
size: fileStat.size,
|
|
40
|
+
fileName: path.basename(resolved),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export async function createUploadSession(api, options = {}) {
|
|
44
|
+
return api.post('/v1/media/upload-url', {
|
|
45
|
+
is_story: options.is_story ?? false,
|
|
46
|
+
is_reels: options.is_reels ?? false,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
export async function uploadLocalFile(apiKey, api, filePath, options = {}) {
|
|
50
|
+
const { resolved, size, fileName } = await assertReadableLocalFile(filePath);
|
|
51
|
+
const mimeType = guessMimeType(fileName);
|
|
52
|
+
let token = options.token?.trim();
|
|
53
|
+
if (!token) {
|
|
54
|
+
const session = await createUploadSession(api, options);
|
|
55
|
+
token = session.token;
|
|
56
|
+
}
|
|
57
|
+
const file = size > CHUNK_SIZE
|
|
58
|
+
? await uploadLargeFile(apiKey, api, token, resolved, fileName, mimeType, size)
|
|
59
|
+
: await uploadSmallFile(apiKey, token, resolved, fileName);
|
|
60
|
+
return { ...file, token };
|
|
61
|
+
}
|
|
62
|
+
async function uploadSmallFile(apiKey, token, resolvedPath, fileName) {
|
|
63
|
+
const buffer = await readFile(resolvedPath);
|
|
64
|
+
const form = new FormData();
|
|
65
|
+
form.append('token', token);
|
|
66
|
+
form.append('file', new Blob([buffer]), fileName);
|
|
67
|
+
return postForm(apiKey, '/v1/media/upload', form);
|
|
68
|
+
}
|
|
69
|
+
async function uploadLargeFile(apiKey, api, token, resolvedPath, fileName, mimeType, size) {
|
|
70
|
+
const quantityParts = Math.max(1, Math.ceil(size / CHUNK_SIZE));
|
|
71
|
+
const init = await api.post('/v1/media/init-multipart-upload', {
|
|
72
|
+
token,
|
|
73
|
+
file_name: fileName,
|
|
74
|
+
mime_type: mimeType,
|
|
75
|
+
file_size: size,
|
|
76
|
+
quantity_parts: quantityParts,
|
|
77
|
+
});
|
|
78
|
+
if (!init.completeUrl || !init.uploadId) {
|
|
79
|
+
throw new Error('Multipart upload initialization failed: missing completeUrl or uploadId');
|
|
80
|
+
}
|
|
81
|
+
const parts = init.multipartUploadUrls ?? [];
|
|
82
|
+
if (parts.length === 0) {
|
|
83
|
+
return uploadSmallFile(apiKey, token, resolvedPath, fileName);
|
|
84
|
+
}
|
|
85
|
+
const sortedParts = [...parts].sort((a, b) => a.partNumber - b.partNumber);
|
|
86
|
+
const fileBuffer = await readFile(resolvedPath);
|
|
87
|
+
for (let index = 0; index < sortedParts.length; index += 1) {
|
|
88
|
+
const part = sortedParts[index];
|
|
89
|
+
const start = index * CHUNK_SIZE;
|
|
90
|
+
const end = Math.min(start + CHUNK_SIZE, size);
|
|
91
|
+
const chunk = fileBuffer.subarray(start, end);
|
|
92
|
+
const putRes = await fetch(part.url, {
|
|
93
|
+
method: 'PUT',
|
|
94
|
+
headers: { 'Content-Type': 'application/octet-stream' },
|
|
95
|
+
body: chunk,
|
|
96
|
+
});
|
|
97
|
+
if (!putRes.ok) {
|
|
98
|
+
throw new Error(`Failed to upload part ${part.partNumber}: HTTP ${putRes.status}`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
const complete = await fetch(init.completeUrl, {
|
|
102
|
+
method: 'POST',
|
|
103
|
+
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
|
|
104
|
+
body: JSON.stringify({
|
|
105
|
+
phase: 'finish',
|
|
106
|
+
session_id: init.uploadId,
|
|
107
|
+
}),
|
|
108
|
+
});
|
|
109
|
+
const completeData = await complete.json().catch(() => null);
|
|
110
|
+
if (!complete.ok || !completeData?.fid) {
|
|
111
|
+
throw new OnlypultApiError(complete.status, completeData, completeData?.success === false
|
|
112
|
+
? 'Multipart complete failed'
|
|
113
|
+
: `Multipart complete failed: HTTP ${complete.status}`);
|
|
114
|
+
}
|
|
115
|
+
return api.post('/v1/media/upload', {
|
|
116
|
+
token,
|
|
117
|
+
from_fid: completeData.fid,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
export function isLocalFileUploadError(err) {
|
|
121
|
+
return err instanceof Error && err.message.includes('media_upload_file only works');
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=media-upload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media-upload.js","sourceRoot":"","sources":["../src/media-upload.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
/** Read version from package.json at publish/install root (one level above dist/). */
|
|
5
|
+
export function readPackageVersion() {
|
|
6
|
+
const packagePath = join(dirname(fileURLToPath(import.meta.url)), '../package.json');
|
|
7
|
+
const pkg = JSON.parse(readFileSync(packagePath, 'utf8'));
|
|
8
|
+
return pkg.version;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=package-version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-version.js","sourceRoot":"","sources":["../src/package-version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,sFAAsF;AACtF,MAAM,UAAU,kBAAkB;IAChC,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAC;IACrF,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,WAAW,EAAE,MAAM,CAAC,CAAwB,CAAC;IACjF,OAAO,GAAG,CAAC,OAAO,CAAC;AACrB,CAAC"}
|