postfast-mcp 0.1.24 → 0.2.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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +7 -1
- package/dist/core/backend-port.d.ts +97 -0
- package/dist/core/backend-port.js +2 -0
- package/dist/core/backend-port.js.map +1 -0
- package/dist/core/build-tools.d.ts +32 -0
- package/dist/core/build-tools.js +73 -0
- package/dist/core/build-tools.js.map +1 -0
- package/dist/core/index.d.ts +12 -0
- package/dist/core/index.js +12 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/instructions.d.ts +3 -0
- package/dist/core/instructions.js +63 -0
- package/dist/core/instructions.js.map +1 -0
- package/dist/core/shared.d.ts +21 -0
- package/dist/core/shared.js +58 -0
- package/dist/core/shared.js.map +1 -0
- package/dist/core/tool-def.d.ts +47 -0
- package/dist/core/tool-def.js +2 -0
- package/dist/core/tool-def.js.map +1 -0
- package/dist/core/tools/accounts.d.ts +2 -0
- package/dist/core/tools/accounts.js +112 -0
- package/dist/core/tools/accounts.js.map +1 -0
- package/dist/core/tools/index.d.ts +7 -0
- package/dist/core/tools/index.js +16 -0
- package/dist/core/tools/index.js.map +1 -0
- package/dist/core/tools/posts.d.ts +2 -0
- package/dist/core/tools/posts.js +264 -0
- package/dist/core/tools/posts.js.map +1 -0
- package/dist/core/tools/uploads.d.ts +8 -0
- package/dist/core/tools/uploads.js +102 -0
- package/dist/core/tools/uploads.js.map +1 -0
- package/dist/core/tools/workspaces.d.ts +2 -0
- package/dist/core/tools/workspaces.js +15 -0
- package/dist/core/tools/workspaces.js.map +1 -0
- package/dist/core/types.js.map +1 -0
- package/dist/stdio/index.js +15 -0
- package/dist/stdio/index.js.map +1 -0
- package/dist/stdio/rest-adapter.d.ts +27 -0
- package/dist/stdio/rest-adapter.js +170 -0
- package/dist/stdio/rest-adapter.js.map +1 -0
- package/package.json +21 -7
- package/dist/client.d.ts +0 -9
- package/dist/client.js +0 -57
- package/dist/client.js.map +0 -1
- package/dist/index.js +0 -18
- package/dist/index.js.map +0 -1
- package/dist/tools/accounts.d.ts +0 -3
- package/dist/tools/accounts.js +0 -118
- package/dist/tools/accounts.js.map +0 -1
- package/dist/tools/files.d.ts +0 -3
- package/dist/tools/files.js +0 -87
- package/dist/tools/files.js.map +0 -1
- package/dist/tools/posts.d.ts +0 -3
- package/dist/tools/posts.js +0 -228
- package/dist/tools/posts.js.map +0 -1
- package/dist/types.js.map +0 -1
- /package/dist/{types.d.ts → core/types.d.ts} +0 -0
- /package/dist/{types.js → core/types.js} +0 -0
- /package/dist/{index.d.ts → stdio/index.d.ts} +0 -0
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
{
|
|
12
12
|
"name": "postfast",
|
|
13
13
|
"description": "Schedule, manage, and analyze social media posts via PostFast. Supports Facebook, Instagram, X, TikTok, LinkedIn, YouTube, BlueSky, Threads, Pinterest, Telegram, and Google Business Profile.",
|
|
14
|
-
"version": "0.
|
|
14
|
+
"version": "0.2.0",
|
|
15
15
|
"author": {
|
|
16
16
|
"name": "PostFast",
|
|
17
17
|
"email": "me@peturgeorgievv.com"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "postfast",
|
|
3
3
|
"description": "Schedule, manage, and analyze social media posts via PostFast. Supports Facebook, Instagram, X, TikTok, LinkedIn, YouTube, BlueSky, Threads, Pinterest, Telegram, and Google Business Profile. After installing, tell Cowork: 'Set my PostFast API key' — get your key at https://app.postfa.st/dashboard → API.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.2.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "PostFast",
|
|
7
7
|
"email": "me@peturgeorgievv.com"
|
package/README.md
CHANGED
|
@@ -189,9 +189,15 @@ Full REST API documentation: [postfa.st/docs](https://postfa.st/docs)
|
|
|
189
189
|
```bash
|
|
190
190
|
npm install
|
|
191
191
|
npm run build
|
|
192
|
-
node dist/index.js
|
|
192
|
+
node dist/stdio/index.js
|
|
193
193
|
```
|
|
194
194
|
|
|
195
|
+
Tools are authored once in `src/core` (the catalog — schemas, descriptions,
|
|
196
|
+
annotations, per-binding availability) and exposed to consumers as
|
|
197
|
+
`postfast-mcp/core`; `src/stdio` binds the catalog to the public REST API.
|
|
198
|
+
Releases go through changesets: PRs add a `.changeset/*.md`, and merging the
|
|
199
|
+
generated Version Packages PR publishes npm + MCP Registry + the MCPB release.
|
|
200
|
+
|
|
195
201
|
## Badges
|
|
196
202
|
|
|
197
203
|
[](https://glama.ai/mcp/servers/peturgeorgievv-factory/postfast-mcp)
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { AnalyticsResponse, FollowerHistory, GbpLocation, PaginatedPosts, PinterestBoard, Place, SignedUploadUrl, SocialAccount, YouTubePlaylist } from './types.js';
|
|
2
|
+
export interface ListPostsArgs {
|
|
3
|
+
page: number;
|
|
4
|
+
limit: number;
|
|
5
|
+
ids?: string[];
|
|
6
|
+
platforms?: string[];
|
|
7
|
+
statuses?: string[];
|
|
8
|
+
from?: string;
|
|
9
|
+
to?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface CreatePostsArgs {
|
|
12
|
+
posts: unknown[];
|
|
13
|
+
status: string;
|
|
14
|
+
approvalStatus: string;
|
|
15
|
+
controls?: Record<string, unknown>;
|
|
16
|
+
}
|
|
17
|
+
export interface ApprovePostsArgs {
|
|
18
|
+
postIds: string[];
|
|
19
|
+
approvalStatus: string;
|
|
20
|
+
}
|
|
21
|
+
export interface AnalyticsArgs {
|
|
22
|
+
startDate: string;
|
|
23
|
+
endDate: string;
|
|
24
|
+
platforms?: string[];
|
|
25
|
+
socialMediaIds?: string[];
|
|
26
|
+
}
|
|
27
|
+
export interface FollowerHistoryArgs {
|
|
28
|
+
socialMediaId: string;
|
|
29
|
+
from?: string;
|
|
30
|
+
to?: string;
|
|
31
|
+
}
|
|
32
|
+
export interface ConnectLinkArgs {
|
|
33
|
+
expiryDays: number;
|
|
34
|
+
sendEmail: boolean;
|
|
35
|
+
email?: string;
|
|
36
|
+
}
|
|
37
|
+
export interface UploadUrlsArgs {
|
|
38
|
+
contentType: string;
|
|
39
|
+
count: number;
|
|
40
|
+
}
|
|
41
|
+
export interface UploadFromUrlArgs {
|
|
42
|
+
sourceUrl: string;
|
|
43
|
+
contentType?: string;
|
|
44
|
+
}
|
|
45
|
+
/** Remote conversation-media upload: a client-provided file ref or base64 bytes. */
|
|
46
|
+
export interface UploadMediaArgs {
|
|
47
|
+
file?: {
|
|
48
|
+
download_url: string;
|
|
49
|
+
file_id: string;
|
|
50
|
+
mime_type?: string;
|
|
51
|
+
file_name?: string;
|
|
52
|
+
};
|
|
53
|
+
data?: string;
|
|
54
|
+
contentType?: string;
|
|
55
|
+
}
|
|
56
|
+
export interface LocalUploadResult {
|
|
57
|
+
key: string;
|
|
58
|
+
type: 'IMAGE' | 'VIDEO';
|
|
59
|
+
contentType: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Everything the catalog tools need from a backend. The stdio bin implements
|
|
63
|
+
* it over the public REST API (pf-api-key); the deployed host implements it
|
|
64
|
+
* over its command gateway + upload service. `workspaceId` is only ever set on
|
|
65
|
+
* the remote binding — adapters without workspace switching ignore it.
|
|
66
|
+
*
|
|
67
|
+
* Adapters may throw from methods whose tools they never register
|
|
68
|
+
* (e.g. the REST adapter for the remote-only conversation-media uploads).
|
|
69
|
+
*/
|
|
70
|
+
export interface BackendPort {
|
|
71
|
+
listWorkspaces(): Promise<unknown>;
|
|
72
|
+
listAccounts(workspaceId?: string): Promise<SocialAccount[] | unknown>;
|
|
73
|
+
getFollowerHistory(args: FollowerHistoryArgs, workspaceId?: string): Promise<FollowerHistory | unknown>;
|
|
74
|
+
listPinterestBoards(socialMediaId: string, workspaceId?: string): Promise<PinterestBoard[] | unknown>;
|
|
75
|
+
listYoutubePlaylists(socialMediaId: string, workspaceId?: string): Promise<YouTubePlaylist[] | unknown>;
|
|
76
|
+
listGbpLocations(socialMediaId: string, workspaceId?: string): Promise<GbpLocation[] | unknown>;
|
|
77
|
+
searchPlaces(query: string, workspaceId?: string): Promise<Place[] | unknown>;
|
|
78
|
+
generateConnectLink(args: ConnectLinkArgs, workspaceId?: string): Promise<{
|
|
79
|
+
connectUrl: string;
|
|
80
|
+
} | unknown>;
|
|
81
|
+
listPosts(args: ListPostsArgs, workspaceId?: string): Promise<PaginatedPosts | unknown>;
|
|
82
|
+
createPosts(args: CreatePostsArgs, workspaceId?: string): Promise<{
|
|
83
|
+
postIds: string[];
|
|
84
|
+
} | unknown>;
|
|
85
|
+
approvePosts(args: ApprovePostsArgs, workspaceId?: string): Promise<unknown>;
|
|
86
|
+
deletePost(id: string, workspaceId?: string): Promise<{
|
|
87
|
+
deleted: boolean;
|
|
88
|
+
} | unknown>;
|
|
89
|
+
getPostAnalytics(args: AnalyticsArgs, workspaceId?: string): Promise<AnalyticsResponse | unknown>;
|
|
90
|
+
getUploadUrls(args: UploadUrlsArgs, workspaceId?: string): Promise<SignedUploadUrl[] | unknown>;
|
|
91
|
+
/** stdio only: read a local file and push it through the signed-URL flow. */
|
|
92
|
+
uploadLocalFile(filePath: string): Promise<LocalUploadResult>;
|
|
93
|
+
/** Remote only: server-side fetch of a public https URL (SSRF-guarded in the host). */
|
|
94
|
+
uploadFromUrl(args: UploadFromUrlArgs, workspaceId?: string): Promise<unknown>;
|
|
95
|
+
/** Remote only: upload a conversation-attached file or base64 bytes. */
|
|
96
|
+
uploadMedia(args: UploadMediaArgs, workspaceId?: string): Promise<unknown>;
|
|
97
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend-port.js","sourceRoot":"","sources":["../../src/core/backend-port.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
|
|
3
|
+
import type { BackendPort } from './backend-port.js';
|
|
4
|
+
import type { Binding, ResolvedTool } from './tool-def.js';
|
|
5
|
+
export interface BuildToolsOptions {
|
|
6
|
+
binding: Binding;
|
|
7
|
+
/**
|
|
8
|
+
* Inject an optional `workspaceId` field into every workspace-scoped tool
|
|
9
|
+
* (the remote host's multi-workspace connections). The stdio bin never sets
|
|
10
|
+
* this — its pf-api-key is already workspace-scoped.
|
|
11
|
+
*/
|
|
12
|
+
withWorkspaceField?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/** Resolve the catalog for one binding: filter, flatten binding-variant fields. */
|
|
15
|
+
export declare function buildTools(options: BuildToolsOptions): ResolvedTool[];
|
|
16
|
+
/**
|
|
17
|
+
* Wrap backend data as MCP content: a JSON text block (proven across all
|
|
18
|
+
* clients — and byte-stable for existing stdio consumers) plus
|
|
19
|
+
* structuredContent for clients that consume outputSchema. Bare-array
|
|
20
|
+
* responses are wrapped as { data } there, since structuredContent must be an
|
|
21
|
+
* object; the text block stays the raw response.
|
|
22
|
+
*/
|
|
23
|
+
export declare function toolResult(data: unknown): CallToolResult;
|
|
24
|
+
/** A business/tool error the model should see and react to (not a protocol error). */
|
|
25
|
+
export declare function toolError(message: string): CallToolResult;
|
|
26
|
+
/** Run a handler, converting thrown errors into `isError` tool results. */
|
|
27
|
+
export declare function runTool(fn: () => Promise<unknown>): Promise<CallToolResult>;
|
|
28
|
+
export interface RegisterToolsOptions extends BuildToolsOptions {
|
|
29
|
+
port: BackendPort;
|
|
30
|
+
}
|
|
31
|
+
/** Register the resolved catalog for a binding on an MCP server. */
|
|
32
|
+
export declare function registerCatalogTools(server: McpServer, options: RegisterToolsOptions): void;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { workspaceIdField } from './shared.js';
|
|
2
|
+
import { ALL_TOOLS } from './tools/index.js';
|
|
3
|
+
/** Resolve the catalog for one binding: filter, flatten binding-variant fields. */
|
|
4
|
+
export function buildTools(options) {
|
|
5
|
+
const { binding, withWorkspaceField = false } = options;
|
|
6
|
+
return ALL_TOOLS.filter((def) => def.binding === 'both' || def.binding === binding).map((def) => {
|
|
7
|
+
const inputSchema = typeof def.inputSchema === 'function' ? def.inputSchema(binding) : def.inputSchema;
|
|
8
|
+
return {
|
|
9
|
+
name: def.name,
|
|
10
|
+
title: def.title,
|
|
11
|
+
description: typeof def.description === 'function' ? def.description(binding) : def.description,
|
|
12
|
+
inputSchema: withWorkspaceField && def.workspaceScoped !== false
|
|
13
|
+
? { ...inputSchema, workspaceId: workspaceIdField }
|
|
14
|
+
: inputSchema,
|
|
15
|
+
outputSchema: def.outputSchema,
|
|
16
|
+
annotations: def.annotations,
|
|
17
|
+
_meta: def._meta,
|
|
18
|
+
run: def.run,
|
|
19
|
+
};
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Wrap backend data as MCP content: a JSON text block (proven across all
|
|
24
|
+
* clients — and byte-stable for existing stdio consumers) plus
|
|
25
|
+
* structuredContent for clients that consume outputSchema. Bare-array
|
|
26
|
+
* responses are wrapped as { data } there, since structuredContent must be an
|
|
27
|
+
* object; the text block stays the raw response.
|
|
28
|
+
*/
|
|
29
|
+
export function toolResult(data) {
|
|
30
|
+
const result = {
|
|
31
|
+
content: [{ type: 'text', text: JSON.stringify(data, null, 2) }],
|
|
32
|
+
};
|
|
33
|
+
if (data && typeof data === 'object') {
|
|
34
|
+
result.structuredContent = Array.isArray(data)
|
|
35
|
+
? { data }
|
|
36
|
+
: data;
|
|
37
|
+
}
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
/** A business/tool error the model should see and react to (not a protocol error). */
|
|
41
|
+
export function toolError(message) {
|
|
42
|
+
return {
|
|
43
|
+
content: [{ type: 'text', text: message }],
|
|
44
|
+
isError: true,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/** Run a handler, converting thrown errors into `isError` tool results. */
|
|
48
|
+
export async function runTool(fn) {
|
|
49
|
+
try {
|
|
50
|
+
return toolResult(await fn());
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
return toolError(err.message || 'Tool execution failed.');
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/** Register the resolved catalog for a binding on an MCP server. */
|
|
57
|
+
export function registerCatalogTools(server, options) {
|
|
58
|
+
const { port } = options;
|
|
59
|
+
for (const tool of buildTools(options)) {
|
|
60
|
+
server.registerTool(tool.name, {
|
|
61
|
+
title: tool.title,
|
|
62
|
+
description: tool.description,
|
|
63
|
+
inputSchema: tool.inputSchema,
|
|
64
|
+
...(tool.outputSchema ? { outputSchema: tool.outputSchema } : {}),
|
|
65
|
+
annotations: tool.annotations,
|
|
66
|
+
...(tool._meta ? { _meta: tool._meta } : {}),
|
|
67
|
+
}, (args) => runTool(() => {
|
|
68
|
+
const { workspaceId, ...rest } = args ?? {};
|
|
69
|
+
return tool.run(port, rest, workspaceId);
|
|
70
|
+
}));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=build-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-tools.js","sourceRoot":"","sources":["../../src/core/build-tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The PostFast MCP tool catalog — the single place tools are authored.
|
|
3
|
+
* Consumed by two bindings: the stdio bin in this package and the deployed
|
|
4
|
+
* remote host (social-schedule-mcp). Import as "postfast-mcp/core".
|
|
5
|
+
*/
|
|
6
|
+
export * from './backend-port.js';
|
|
7
|
+
export { buildTools, registerCatalogTools, runTool, toolError, toolResult, type BuildToolsOptions, type RegisterToolsOptions, } from './build-tools.js';
|
|
8
|
+
export { SERVER_INSTRUCTIONS, instructionsFor } from './instructions.js';
|
|
9
|
+
export { CREATE_APPROVAL_STATUSES, CREATE_STATUSES, IMAGE_MIME_TYPES, PLATFORMS, POST_STATUSES, SET_APPROVAL_STATUSES, VIDEO_MIME_TYPES, dataListOutputSchema, jsonParse, workspaceIdField, } from './shared.js';
|
|
10
|
+
export type { Binding, ResolvedTool, ToolAnnotations, ToolDef, } from './tool-def.js';
|
|
11
|
+
export { ALL_TOOLS } from './tools/index.js';
|
|
12
|
+
export * from './types.js';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The PostFast MCP tool catalog — the single place tools are authored.
|
|
3
|
+
* Consumed by two bindings: the stdio bin in this package and the deployed
|
|
4
|
+
* remote host (social-schedule-mcp). Import as "postfast-mcp/core".
|
|
5
|
+
*/
|
|
6
|
+
export * from './backend-port.js';
|
|
7
|
+
export { buildTools, registerCatalogTools, runTool, toolError, toolResult, } from './build-tools.js';
|
|
8
|
+
export { SERVER_INSTRUCTIONS, instructionsFor } from './instructions.js';
|
|
9
|
+
export { CREATE_APPROVAL_STATUSES, CREATE_STATUSES, IMAGE_MIME_TYPES, PLATFORMS, POST_STATUSES, SET_APPROVAL_STATUSES, VIDEO_MIME_TYPES, dataListOutputSchema, jsonParse, workspaceIdField, } from './shared.js';
|
|
10
|
+
export { ALL_TOOLS } from './tools/index.js';
|
|
11
|
+
export * from './types.js';
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,cAAc,mBAAmB,CAAC;AAClC,OAAO,EACL,UAAU,EACV,oBAAoB,EACpB,OAAO,EACP,SAAS,EACT,UAAU,GAGX,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EACL,wBAAwB,EACxB,eAAe,EACf,gBAAgB,EAChB,SAAS,EACT,aAAa,EACb,qBAAqB,EACrB,gBAAgB,EAChB,oBAAoB,EACpB,SAAS,EACT,gBAAgB,GACjB,MAAM,aAAa,CAAC;AAOrB,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server `instructions` sent at MCP `initialize` — standing guidance the client
|
|
3
|
+
* model reads before calling tools. Grounded in the PostFast docs + the
|
|
4
|
+
* backend's actual create-posts validation, so it matches what the API
|
|
5
|
+
* enforces (prevents the model discovering rules by failing).
|
|
6
|
+
*
|
|
7
|
+
* The two bindings differ only where their tool surfaces differ: workspace
|
|
8
|
+
* switching and conversation-media/URL uploads exist on the remote host, the
|
|
9
|
+
* stdio bin uploads local files instead.
|
|
10
|
+
*/
|
|
11
|
+
const SHARED_TAIL = `Before scheduling, confirm the target account's connectionStatus is CONNECTED. A DISABLED account will not publish (disconnected accounts are the #1 cause of failed posts) — saving a DRAFT is still allowed.
|
|
12
|
+
|
|
13
|
+
Status & timing: status=SCHEDULED requires scheduledAt on every post (ISO-8601, in the future, within 1 year); status=DRAFT must omit scheduledAt. approvalStatus=APPROVED publishes; PENDING_APPROVAL holds it for review. There is no instant "publish now" — for an immediate post, set scheduledAt a few minutes ahead of now (a time at or before the current moment is rejected).
|
|
14
|
+
|
|
15
|
+
Media: use the key returned by an upload tool, and set mediaItems[].type to match the file (IMAGE for image/* keys, VIDEO for video/* keys — a mismatch is rejected). Videos are capped at 250MB (Telegram 50MB, Bluesky 100MB). Media is REQUIRED on TikTok, YouTube (video only), Instagram, Pinterest, and Google Business Profile; X, LinkedIn, Facebook, Threads, Bluesky, and Telegram allow text-only posts. This requirement applies even to DRAFTS — a draft to a media-required platform without media is rejected. So if the user asks to post to a media-required platform and provides no media, ask them for an image/video (or generate and upload one) BEFORE calling create_posts; don't attempt the post without media.
|
|
16
|
+
|
|
17
|
+
Per-platform limits (media counts / characters):
|
|
18
|
+
- X: up to 4 images or 1 video (no mixing); 280 chars (4,000 with X Premium).
|
|
19
|
+
- TikTok: 1 video OR up to 10 images; 4,000 chars.
|
|
20
|
+
- Instagram: up to 10 images + 10 videos (mixed OK); 2,200 chars, max 30 hashtags.
|
|
21
|
+
- YouTube: 1 video, no images; title max 100 chars.
|
|
22
|
+
- Facebook / LinkedIn: up to 10 images + 1 video.
|
|
23
|
+
- Threads: up to 10 images + 10 videos; 500 chars.
|
|
24
|
+
- Pinterest: up to 5 images or 1 video; title max 100, description max 800.
|
|
25
|
+
- Google Business Profile: 1 image; 1,500 chars.
|
|
26
|
+
- Bluesky: up to 4 images or 1 video. Telegram: up to 10 images + 3 videos.
|
|
27
|
+
If content exceeds the target platform's character limit, don't schedule it as-is — tell the user and offer to shorten or split it (X is 280 unless the account has X Premium = 4,000).
|
|
28
|
+
|
|
29
|
+
Platform-specific options go in the controls object, e.g.:
|
|
30
|
+
- Pinterest: controls.pinterestBoardId is REQUIRED — it is a board's boardId from list_pinterest_boards, NOT the Pinterest account's socialMediaId.
|
|
31
|
+
- Google Business Profile: controls.gbpLocationId is required — the locationId from list_gbp_locations.
|
|
32
|
+
- YouTube: controls.youtubePlaylistId is the playlistId from list_youtube_playlists; youtubeIsShort defaults true; title falls back to the first 100 chars of content.
|
|
33
|
+
- TikTok: controls.tiktokPrivacy is deprecated (videos use the account default, photos default to public); tiktokTitle applies to photo carousels only (max 90); firstComment supported on Business accounts (max 150, comments must be enabled).
|
|
34
|
+
- Instagram: controls.instagramPublishType = TIMELINE | STORY | REEL.
|
|
35
|
+
- Facebook: controls.facebookContentType = POST | REEL | STORY. controls.facebookTargetCountries limits who can see a FEED post by country (ISO 3166-1 alpha-2, max 25; not Reels/Stories).
|
|
36
|
+
- Geotag a place (Facebook/Instagram): call search_places, then pass a returned id as controls.facebookPlaceId (Facebook feed posts only — not Reels/Stories/video) and/or controls.instagramLocationId (Instagram single media only — not carousels). One id works for both.
|
|
37
|
+
- LinkedIn: attach a document via controls.linkedinAttachmentKey.
|
|
38
|
+
- X: controls.xRetweetUrl reposts an existing tweet (content/media are ignored).
|
|
39
|
+
Note: list_pinterest_boards / list_youtube_playlists / list_gbp_locations take the account's socialMediaId; each returned item has BOTH an internal id and the platform id (boardId / playlistId / locationId) — pass the PLATFORM id to controls, not the internal id or the account id.
|
|
40
|
+
|
|
41
|
+
Failed posts carry lastError — usually a disconnected account (reconnect, then retry) or platform-rejected media.`;
|
|
42
|
+
const STDIO_INSTRUCTIONS = `PostFast schedules and publishes social posts across X, Instagram, Facebook, TikTok, LinkedIn, YouTube, Threads, Pinterest, Bluesky, Telegram, and Google Business Profile.
|
|
43
|
+
|
|
44
|
+
Flow: list_accounts to see what's connected → create_posts (one socialMediaId per post; batch up to 15) → attach media via upload_media (a local file, by absolute path) or get_upload_urls (signed PUT upload for raw bytes) → a post publishes when status=SCHEDULED and approvalStatus=APPROVED.
|
|
45
|
+
|
|
46
|
+
The POSTFAST_API_KEY is workspace-scoped — every tool acts in that workspace.
|
|
47
|
+
|
|
48
|
+
${SHARED_TAIL}`;
|
|
49
|
+
const REMOTE_INSTRUCTIONS = `PostFast schedules and publishes social posts across X, Instagram, Facebook, TikTok, LinkedIn, YouTube, Threads, Pinterest, Bluesky, Telegram, and Google Business Profile.
|
|
50
|
+
|
|
51
|
+
Flow: list_accounts (+ list_workspaces) to see what's connected → create_posts (one socialMediaId per post; batch up to 15) → attach media via upload_from_url (a public https URL) or upload_media (a ChatGPT-attached/generated image, or base64) → a post publishes when status=SCHEDULED and approvalStatus=APPROVED.
|
|
52
|
+
|
|
53
|
+
Workspaces: omit workspaceId to use the connection's default; pass a workspaceId (from list_workspaces) to act in another workspace.
|
|
54
|
+
|
|
55
|
+
${SHARED_TAIL}`;
|
|
56
|
+
export const SERVER_INSTRUCTIONS = {
|
|
57
|
+
stdio: STDIO_INSTRUCTIONS,
|
|
58
|
+
remote: REMOTE_INSTRUCTIONS,
|
|
59
|
+
};
|
|
60
|
+
export function instructionsFor(binding) {
|
|
61
|
+
return SERVER_INSTRUCTIONS[binding];
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=instructions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instructions.js","sourceRoot":"","sources":["../../src/core/instructions.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AAEH,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kHA8B8F,CAAC;AAEnH,MAAM,kBAAkB,GAAG;;;;;;EAMzB,WAAW,EAAE,CAAC;AAEhB,MAAM,mBAAmB,GAAG;;;;;;EAM1B,WAAW,EAAE,CAAC;AAEhB,MAAM,CAAC,MAAM,mBAAmB,GAA4B;IAC1D,KAAK,EAAE,kBAAkB;IACzB,MAAM,EAAE,mBAAmB;CAC5B,CAAC;AAEF,MAAM,UAAU,eAAe,CAAC,OAAgB;IAC9C,OAAO,mBAAmB,CAAC,OAAO,CAAC,CAAC;AACtC,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const PLATFORMS: readonly ["FACEBOOK", "INSTAGRAM", "X", "TIKTOK", "LINKEDIN", "YOUTUBE", "BLUESKY", "THREADS", "PINTEREST", "TELEGRAM", "GOOGLE_BUSINESS_PROFILE"];
|
|
3
|
+
export declare const POST_STATUSES: readonly ["DRAFT", "SCHEDULED", "PUBLISHED", "FAILED"];
|
|
4
|
+
export declare const CREATE_STATUSES: readonly ["DRAFT", "SCHEDULED"];
|
|
5
|
+
export declare const CREATE_APPROVAL_STATUSES: readonly ["PENDING_APPROVAL", "APPROVED"];
|
|
6
|
+
export declare const SET_APPROVAL_STATUSES: readonly ["PENDING_APPROVAL", "IN_PROGRESS", "APPROVED", "REJECTED", "NEEDS_WORK"];
|
|
7
|
+
export declare const IMAGE_MIME_TYPES: readonly ["image/jpeg", "image/png", "image/gif", "image/webp"];
|
|
8
|
+
export declare const VIDEO_MIME_TYPES: readonly ["video/mp4", "video/webm", "video/quicktime"];
|
|
9
|
+
/** Some MCP clients stringify complex params — parse them back before validation. */
|
|
10
|
+
export declare function jsonParse<T extends z.ZodTypeAny>(schema: T): z.ZodPreprocess<T>;
|
|
11
|
+
/**
|
|
12
|
+
* Permissive output schema for list-style tools: { data: [...] }. Items are
|
|
13
|
+
* unknown (never type-rejected) and extra top-level keys (totalCount, pageInfo)
|
|
14
|
+
* pass through — so structuredContent is advertised without breaking on real
|
|
15
|
+
* backend responses.
|
|
16
|
+
*/
|
|
17
|
+
export declare const dataListOutputSchema: {
|
|
18
|
+
data: z.ZodOptional<z.ZodArray<z.ZodUnknown>>;
|
|
19
|
+
};
|
|
20
|
+
/** Optional per-call workspace selector, injected only on the remote binding. */
|
|
21
|
+
export declare const workspaceIdField: z.ZodOptional<z.ZodUUID>;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const PLATFORMS = [
|
|
3
|
+
'FACEBOOK',
|
|
4
|
+
'INSTAGRAM',
|
|
5
|
+
'X',
|
|
6
|
+
'TIKTOK',
|
|
7
|
+
'LINKEDIN',
|
|
8
|
+
'YOUTUBE',
|
|
9
|
+
'BLUESKY',
|
|
10
|
+
'THREADS',
|
|
11
|
+
'PINTEREST',
|
|
12
|
+
'TELEGRAM',
|
|
13
|
+
'GOOGLE_BUSINESS_PROFILE',
|
|
14
|
+
];
|
|
15
|
+
export const POST_STATUSES = ['DRAFT', 'SCHEDULED', 'PUBLISHED', 'FAILED'];
|
|
16
|
+
export const CREATE_STATUSES = ['DRAFT', 'SCHEDULED'];
|
|
17
|
+
export const CREATE_APPROVAL_STATUSES = ['PENDING_APPROVAL', 'APPROVED'];
|
|
18
|
+
export const SET_APPROVAL_STATUSES = [
|
|
19
|
+
'PENDING_APPROVAL',
|
|
20
|
+
'IN_PROGRESS',
|
|
21
|
+
'APPROVED',
|
|
22
|
+
'REJECTED',
|
|
23
|
+
'NEEDS_WORK',
|
|
24
|
+
];
|
|
25
|
+
export const IMAGE_MIME_TYPES = [
|
|
26
|
+
'image/jpeg',
|
|
27
|
+
'image/png',
|
|
28
|
+
'image/gif',
|
|
29
|
+
'image/webp',
|
|
30
|
+
];
|
|
31
|
+
export const VIDEO_MIME_TYPES = ['video/mp4', 'video/webm', 'video/quicktime'];
|
|
32
|
+
/** Some MCP clients stringify complex params — parse them back before validation. */
|
|
33
|
+
export function jsonParse(schema) {
|
|
34
|
+
return z.preprocess((val) => {
|
|
35
|
+
if (typeof val === 'string') {
|
|
36
|
+
try {
|
|
37
|
+
return JSON.parse(val);
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return val;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return val;
|
|
44
|
+
}, schema);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Permissive output schema for list-style tools: { data: [...] }. Items are
|
|
48
|
+
* unknown (never type-rejected) and extra top-level keys (totalCount, pageInfo)
|
|
49
|
+
* pass through — so structuredContent is advertised without breaking on real
|
|
50
|
+
* backend responses.
|
|
51
|
+
*/
|
|
52
|
+
export const dataListOutputSchema = { data: z.array(z.unknown()).optional() };
|
|
53
|
+
/** Optional per-call workspace selector, injected only on the remote binding. */
|
|
54
|
+
export const workspaceIdField = z
|
|
55
|
+
.uuid()
|
|
56
|
+
.optional()
|
|
57
|
+
.describe("Target workspace id (from list_workspaces). Omit to use the connection's default workspace.");
|
|
58
|
+
//# sourceMappingURL=shared.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/core/shared.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,UAAU;IACV,WAAW;IACX,GAAG;IACH,QAAQ;IACR,UAAU;IACV,SAAS;IACT,SAAS;IACT,SAAS;IACT,WAAW;IACX,UAAU;IACV,yBAAyB;CACjB,CAAC;AAEX,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,QAAQ,CAAU,CAAC;AACpF,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,WAAW,CAAU,CAAC;AAC/D,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,kBAAkB,EAAE,UAAU,CAAU,CAAC;AAClF,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,kBAAkB;IAClB,aAAa;IACb,UAAU;IACV,UAAU;IACV,YAAY;CACJ,CAAC;AAEX,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,YAAY;IACZ,WAAW;IACX,WAAW;IACX,YAAY;CACJ,CAAC;AACX,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,WAAW,EAAE,YAAY,EAAE,iBAAiB,CAAU,CAAC;AAExF,qFAAqF;AACrF,MAAM,UAAU,SAAS,CAAyB,MAAS;IACzD,OAAO,CAAC,CAAC,UAAU,CAAC,CAAC,GAAG,EAAE,EAAE;QAC1B,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC5B,IAAI,CAAC;gBACH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACzB,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,GAAG,CAAC;YACb,CAAC;QACH,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC,EAAE,MAAM,CAAC,CAAC;AACb,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC;AAE9E,iFAAiF;AACjF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC;KAC9B,IAAI,EAAE;KACN,QAAQ,EAAE;KACV,QAAQ,CACP,6FAA6F,CAC9F,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { ZodRawShape } from 'zod';
|
|
2
|
+
import type { BackendPort } from './backend-port.js';
|
|
3
|
+
/** The two deployments a catalog tool can ship in. */
|
|
4
|
+
export type Binding = 'stdio' | 'remote';
|
|
5
|
+
export interface ToolAnnotations {
|
|
6
|
+
readOnlyHint: boolean;
|
|
7
|
+
destructiveHint: boolean;
|
|
8
|
+
idempotentHint?: boolean;
|
|
9
|
+
openWorldHint: boolean;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* One tool as authored in the catalog. `description`/`inputSchema` may be a
|
|
13
|
+
* function of the binding for the few spots where the surfaces genuinely
|
|
14
|
+
* differ (upload-tool references — stdio uploads local files, the remote
|
|
15
|
+
* uploads conversation media/URLs). Everything else is binding-invariant.
|
|
16
|
+
*/
|
|
17
|
+
export interface ToolDef {
|
|
18
|
+
name: string;
|
|
19
|
+
/** Which binding(s) expose the tool. */
|
|
20
|
+
binding: Binding | 'both';
|
|
21
|
+
title: string;
|
|
22
|
+
description: string | ((binding: Binding) => string);
|
|
23
|
+
inputSchema: ZodRawShape | ((binding: Binding) => ZodRawShape);
|
|
24
|
+
outputSchema?: ZodRawShape;
|
|
25
|
+
annotations: ToolAnnotations;
|
|
26
|
+
/** Extra tool metadata, e.g. the ChatGPT file-param marker on upload_media. */
|
|
27
|
+
_meta?: Record<string, unknown>;
|
|
28
|
+
/** False only for tools that are not scoped to a workspace (list_workspaces). */
|
|
29
|
+
workspaceScoped?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Dispatch to the backend. `args` are the validated tool arguments minus
|
|
32
|
+
* `workspaceId`, which is split off by the registrar and passed separately
|
|
33
|
+
* (always undefined on stdio — the pf-api-key is already workspace-scoped).
|
|
34
|
+
*/
|
|
35
|
+
run: (port: BackendPort, args: Record<string, unknown>, workspaceId?: string) => Promise<unknown>;
|
|
36
|
+
}
|
|
37
|
+
/** A ToolDef with binding-dependent fields resolved for one concrete binding. */
|
|
38
|
+
export interface ResolvedTool {
|
|
39
|
+
name: string;
|
|
40
|
+
title: string;
|
|
41
|
+
description: string;
|
|
42
|
+
inputSchema: ZodRawShape;
|
|
43
|
+
outputSchema?: ZodRawShape;
|
|
44
|
+
annotations: ToolAnnotations;
|
|
45
|
+
_meta?: Record<string, unknown>;
|
|
46
|
+
run: ToolDef['run'];
|
|
47
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-def.js","sourceRoot":"","sources":["../../src/core/tool-def.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { dataListOutputSchema } from '../shared.js';
|
|
3
|
+
export const accountTools = [
|
|
4
|
+
{
|
|
5
|
+
name: 'list_accounts',
|
|
6
|
+
binding: 'both',
|
|
7
|
+
title: 'List Accounts',
|
|
8
|
+
description: 'List all social media accounts connected to the workspace. Each account includes connectionStatus (CONNECTED or DISABLED) and disabledReason (null unless DISABLED), plus followerCount (latest stored snapshot, a string; absent for platforms without follower data), followerCountUpdatedAt, and inboxCapable (whether the account can appear in the social inbox, i.e. comment ingestion is supported). A DISABLED account will not publish until the user reconnects it — pre-check before scheduling. For a follower trend over time, use get_follower_history.',
|
|
9
|
+
inputSchema: {},
|
|
10
|
+
outputSchema: dataListOutputSchema,
|
|
11
|
+
annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
12
|
+
run: (port, _args, workspaceId) => port.listAccounts(workspaceId),
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
name: 'list_pinterest_boards',
|
|
16
|
+
binding: 'both',
|
|
17
|
+
title: 'List Pinterest Boards',
|
|
18
|
+
description: 'List Pinterest boards for a connected Pinterest account (pass its socialMediaId). Use a returned board’s boardId field as controls.pinterestBoardId in create_posts.',
|
|
19
|
+
inputSchema: {
|
|
20
|
+
socialMediaId: z.uuid().describe('Pinterest account id (from list_accounts)'),
|
|
21
|
+
},
|
|
22
|
+
outputSchema: dataListOutputSchema,
|
|
23
|
+
annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: true },
|
|
24
|
+
run: (port, args, workspaceId) => port.listPinterestBoards(args.socialMediaId, workspaceId),
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: 'list_youtube_playlists',
|
|
28
|
+
binding: 'both',
|
|
29
|
+
title: 'List YouTube Playlists',
|
|
30
|
+
description: 'List YouTube playlists for a connected YouTube account (pass its socialMediaId). Use a returned playlist’s playlistId field as controls.youtubePlaylistId in create_posts.',
|
|
31
|
+
inputSchema: {
|
|
32
|
+
socialMediaId: z.uuid().describe('YouTube account id (from list_accounts)'),
|
|
33
|
+
},
|
|
34
|
+
outputSchema: dataListOutputSchema,
|
|
35
|
+
annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: true },
|
|
36
|
+
run: (port, args, workspaceId) => port.listYoutubePlaylists(args.socialMediaId, workspaceId),
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: 'list_gbp_locations',
|
|
40
|
+
binding: 'both',
|
|
41
|
+
title: 'List Google Business Profile Locations',
|
|
42
|
+
description: 'List Google Business Profile locations for a connected GBP account (pass its socialMediaId). Use a returned location’s locationId field as controls.gbpLocationId in create_posts.',
|
|
43
|
+
inputSchema: {
|
|
44
|
+
socialMediaId: z.uuid().describe('GBP account id (from list_accounts)'),
|
|
45
|
+
},
|
|
46
|
+
outputSchema: dataListOutputSchema,
|
|
47
|
+
annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: true },
|
|
48
|
+
run: (port, args, workspaceId) => port.listGbpLocations(args.socialMediaId, workspaceId),
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: 'get_follower_history',
|
|
52
|
+
binding: 'both',
|
|
53
|
+
title: 'Get Follower History',
|
|
54
|
+
description: 'Daily follower-count snapshots for one connected account (pass its socialMediaId from list_accounts). Returns currentFollowerCount, delta (current − first snapshot in range), trackingStartedAt (when PostFast began recording this account), and a series of { capturedAt, followerCount } points. All counts are strings (bigint); currentFollowerCount, delta, and trackingStartedAt may be absent until the account has its first snapshot. Optional from/to bound the range (ISO 8601; default last 90 days, capped at 365). Snapshots are forward-only — no data before trackingStartedAt. Coverage: Facebook Pages, Instagram, YouTube, Pinterest, Threads, Bluesky, Telegram, LinkedIn company pages, and TikTok. Not available: X, personal Facebook.',
|
|
55
|
+
inputSchema: {
|
|
56
|
+
socialMediaId: z.uuid().describe('Account id (from list_accounts)'),
|
|
57
|
+
from: z
|
|
58
|
+
.string()
|
|
59
|
+
.optional()
|
|
60
|
+
.describe('Range start (ISO 8601, e.g. 2026-03-01T00:00:00.000Z). Defaults to 90 days ago.'),
|
|
61
|
+
to: z
|
|
62
|
+
.string()
|
|
63
|
+
.optional()
|
|
64
|
+
.describe('Range end (ISO 8601). Defaults to now; range is capped at 365 days.'),
|
|
65
|
+
},
|
|
66
|
+
outputSchema: {
|
|
67
|
+
socialMediaId: z.string().optional(),
|
|
68
|
+
series: z.array(z.unknown()).optional(),
|
|
69
|
+
currentFollowerCount: z.string().optional(),
|
|
70
|
+
delta: z.string().optional(),
|
|
71
|
+
trackingStartedAt: z.string().optional(),
|
|
72
|
+
},
|
|
73
|
+
annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
74
|
+
run: (port, args, workspaceId) => port.getFollowerHistory(args, workspaceId),
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: 'search_places',
|
|
78
|
+
binding: 'both',
|
|
79
|
+
title: 'Search Places',
|
|
80
|
+
description: 'Search for a place to geotag a post. Pass free text (min 2 chars, e.g. a venue name or address); returns matching places, each with an id that works as BOTH controls.facebookPlaceId (Facebook feed posts) and controls.instagramLocationId (Instagram single-media posts). Only Facebook Pages that carry location data are returned.',
|
|
81
|
+
inputSchema: {
|
|
82
|
+
query: z.string().min(2).describe('Place search text, min 2 characters (e.g. "eiffel tower")'),
|
|
83
|
+
},
|
|
84
|
+
outputSchema: dataListOutputSchema,
|
|
85
|
+
annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: true },
|
|
86
|
+
run: (port, args, workspaceId) => port.searchPlaces(args.query, workspaceId),
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: 'generate_connect_link',
|
|
90
|
+
binding: 'both',
|
|
91
|
+
title: 'Generate Connect Link',
|
|
92
|
+
description: 'Generate a shareable link for external clients to connect their social accounts to the workspace.',
|
|
93
|
+
inputSchema: {
|
|
94
|
+
expiryDays: z
|
|
95
|
+
.number()
|
|
96
|
+
.int()
|
|
97
|
+
.min(1)
|
|
98
|
+
.max(30)
|
|
99
|
+
.default(7)
|
|
100
|
+
.describe('Link expiry in days (1-30, default 7)'),
|
|
101
|
+
sendEmail: z.boolean().default(false).describe('Send the link via email'),
|
|
102
|
+
email: z
|
|
103
|
+
.email()
|
|
104
|
+
.optional()
|
|
105
|
+
.describe('Recipient email (required when sendEmail is true)'),
|
|
106
|
+
},
|
|
107
|
+
outputSchema: { connectUrl: z.string().optional() },
|
|
108
|
+
annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: true },
|
|
109
|
+
run: (port, args, workspaceId) => port.generateConnectLink(args, workspaceId),
|
|
110
|
+
},
|
|
111
|
+
];
|
|
112
|
+
//# sourceMappingURL=accounts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accounts.js","sourceRoot":"","sources":["../../../src/core/tools/accounts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ToolDef } from '../tool-def.js';
|
|
2
|
+
/**
|
|
3
|
+
* Every PostFast tool, in registration order. The order filtered to the stdio
|
|
4
|
+
* binding must stay exactly the published bin's tools/list order — clients and
|
|
5
|
+
* their prompts see it.
|
|
6
|
+
*/
|
|
7
|
+
export declare const ALL_TOOLS: ToolDef[];
|