outx-mcp-server 1.0.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 +217 -0
- package/dist/client.d.ts +19 -0
- package/dist/client.js +91 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/engagement.d.ts +3 -0
- package/dist/tools/engagement.js +40 -0
- package/dist/tools/engagement.js.map +1 -0
- package/dist/tools/linkedin.d.ts +3 -0
- package/dist/tools/linkedin.js +57 -0
- package/dist/tools/linkedin.js.map +1 -0
- package/dist/tools/posts.d.ts +3 -0
- package/dist/tools/posts.js +32 -0
- package/dist/tools/posts.js.map +1 -0
- package/dist/tools/watchlists.d.ts +3 -0
- package/dist/tools/watchlists.js +177 -0
- package/dist/tools/watchlists.js.map +1 -0
- package/package.json +43 -0
- package/src/client.ts +105 -0
- package/src/index.ts +33 -0
- package/src/tools/engagement.ts +56 -0
- package/src/tools/linkedin.ts +98 -0
- package/src/tools/posts.ts +41 -0
- package/src/tools/watchlists.ts +246 -0
- package/tsconfig.json +17 -0
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import type { OutxClient } from "../client.js";
|
|
4
|
+
|
|
5
|
+
const fetchFreqEnum = z
|
|
6
|
+
.enum(["1", "3", "6", "12", "24", "48", "72"])
|
|
7
|
+
.describe("How often to scan for new posts (hours)");
|
|
8
|
+
|
|
9
|
+
export function registerWatchlistTools(
|
|
10
|
+
server: McpServer,
|
|
11
|
+
client: OutxClient
|
|
12
|
+
): void {
|
|
13
|
+
// ── Keyword Watchlists ──────────────────────────────────
|
|
14
|
+
|
|
15
|
+
server.tool(
|
|
16
|
+
"create_keyword_watchlist",
|
|
17
|
+
"Create a watchlist that monitors LinkedIn posts matching keywords. Posts appear after the first scan cycle.",
|
|
18
|
+
{
|
|
19
|
+
keywords: z
|
|
20
|
+
.array(z.string())
|
|
21
|
+
.min(1)
|
|
22
|
+
.describe("Keywords to track (e.g. ['AI startup funding', 'series A'])"),
|
|
23
|
+
required_keywords: z
|
|
24
|
+
.array(z.string())
|
|
25
|
+
.optional()
|
|
26
|
+
.describe("Posts MUST contain at least one of these words"),
|
|
27
|
+
exclude_keywords: z
|
|
28
|
+
.array(z.string())
|
|
29
|
+
.optional()
|
|
30
|
+
.describe("Exclude posts containing any of these words"),
|
|
31
|
+
name: z.string().optional().describe("Watchlist name"),
|
|
32
|
+
description: z.string().optional(),
|
|
33
|
+
labels: z.array(z.string()).optional().describe("Custom labels for categorization"),
|
|
34
|
+
fetchFreqInHours: fetchFreqEnum.optional(),
|
|
35
|
+
},
|
|
36
|
+
async (params) => {
|
|
37
|
+
const body: Record<string, unknown> = {
|
|
38
|
+
keywords: params.keywords.map((kw) => {
|
|
39
|
+
const obj: Record<string, unknown> = { keyword: kw };
|
|
40
|
+
if (params.required_keywords) obj.required_keywords = params.required_keywords;
|
|
41
|
+
if (params.exclude_keywords) obj.exclude_keywords = params.exclude_keywords;
|
|
42
|
+
return obj;
|
|
43
|
+
}),
|
|
44
|
+
};
|
|
45
|
+
if (params.name) body.name = params.name;
|
|
46
|
+
if (params.description) body.description = params.description;
|
|
47
|
+
if (params.labels) body.labels = params.labels;
|
|
48
|
+
if (params.fetchFreqInHours)
|
|
49
|
+
body.fetchFreqInHours = parseInt(params.fetchFreqInHours);
|
|
50
|
+
|
|
51
|
+
const result = await client.post("/api-keyword-watchlist", body);
|
|
52
|
+
return { content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }] };
|
|
53
|
+
}
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
server.tool(
|
|
57
|
+
"list_keyword_watchlists",
|
|
58
|
+
"List all keyword watchlists for your account.",
|
|
59
|
+
{},
|
|
60
|
+
async () => {
|
|
61
|
+
const result = await client.get("/api-keyword-watchlist");
|
|
62
|
+
return { content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }] };
|
|
63
|
+
}
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
server.tool(
|
|
67
|
+
"update_keyword_watchlist",
|
|
68
|
+
"Update a keyword watchlist's name, frequency, or status.",
|
|
69
|
+
{
|
|
70
|
+
id: z.string().describe("Watchlist ID"),
|
|
71
|
+
name: z.string().optional(),
|
|
72
|
+
fetchFreqInHours: fetchFreqEnum.optional(),
|
|
73
|
+
status: z.enum(["active", "paused"]).optional(),
|
|
74
|
+
},
|
|
75
|
+
async (params) => {
|
|
76
|
+
const body: Record<string, unknown> = { id: params.id };
|
|
77
|
+
if (params.name) body.name = params.name;
|
|
78
|
+
if (params.fetchFreqInHours)
|
|
79
|
+
body.fetchFreqInHours = parseInt(params.fetchFreqInHours);
|
|
80
|
+
if (params.status) body.status = params.status;
|
|
81
|
+
|
|
82
|
+
const result = await client.put("/api-keyword-watchlist", body);
|
|
83
|
+
return { content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }] };
|
|
84
|
+
}
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
server.tool(
|
|
88
|
+
"delete_keyword_watchlist",
|
|
89
|
+
"Delete a keyword watchlist and all its tracked data.",
|
|
90
|
+
{
|
|
91
|
+
id: z.string().describe("Watchlist ID to delete"),
|
|
92
|
+
},
|
|
93
|
+
async (params) => {
|
|
94
|
+
const result = await client.delete("/api-keyword-watchlist", {
|
|
95
|
+
id: params.id,
|
|
96
|
+
});
|
|
97
|
+
return { content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }] };
|
|
98
|
+
}
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
// ── People Watchlists ───────────────────────────────────
|
|
102
|
+
|
|
103
|
+
server.tool(
|
|
104
|
+
"create_people_watchlist",
|
|
105
|
+
"Create a watchlist that monitors posts from specific LinkedIn profiles.",
|
|
106
|
+
{
|
|
107
|
+
profiles: z
|
|
108
|
+
.array(z.string())
|
|
109
|
+
.min(1)
|
|
110
|
+
.describe("LinkedIn profile URLs or slugs to track"),
|
|
111
|
+
name: z.string().optional().describe("Watchlist name"),
|
|
112
|
+
description: z.string().optional(),
|
|
113
|
+
labels: z.array(z.string()).optional(),
|
|
114
|
+
fetchFreqInHours: fetchFreqEnum.optional(),
|
|
115
|
+
},
|
|
116
|
+
async (params) => {
|
|
117
|
+
const body: Record<string, unknown> = { profiles: params.profiles };
|
|
118
|
+
if (params.name) body.name = params.name;
|
|
119
|
+
if (params.description) body.description = params.description;
|
|
120
|
+
if (params.labels) body.labels = params.labels;
|
|
121
|
+
if (params.fetchFreqInHours)
|
|
122
|
+
body.fetchFreqInHours = parseInt(params.fetchFreqInHours);
|
|
123
|
+
|
|
124
|
+
const result = await client.post("/api-people-watchlist", body);
|
|
125
|
+
return { content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }] };
|
|
126
|
+
}
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
server.tool(
|
|
130
|
+
"list_people_watchlists",
|
|
131
|
+
"List all people watchlists for your account.",
|
|
132
|
+
{},
|
|
133
|
+
async () => {
|
|
134
|
+
const result = await client.get("/api-people-watchlist");
|
|
135
|
+
return { content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }] };
|
|
136
|
+
}
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
server.tool(
|
|
140
|
+
"update_people_watchlist",
|
|
141
|
+
"Update a people watchlist's name, frequency, or status.",
|
|
142
|
+
{
|
|
143
|
+
id: z.string().describe("Watchlist ID"),
|
|
144
|
+
name: z.string().optional(),
|
|
145
|
+
fetchFreqInHours: fetchFreqEnum.optional(),
|
|
146
|
+
status: z.enum(["active", "paused"]).optional(),
|
|
147
|
+
},
|
|
148
|
+
async (params) => {
|
|
149
|
+
const body: Record<string, unknown> = { id: params.id };
|
|
150
|
+
if (params.name) body.name = params.name;
|
|
151
|
+
if (params.fetchFreqInHours)
|
|
152
|
+
body.fetchFreqInHours = parseInt(params.fetchFreqInHours);
|
|
153
|
+
if (params.status) body.status = params.status;
|
|
154
|
+
|
|
155
|
+
const result = await client.put("/api-people-watchlist", body);
|
|
156
|
+
return { content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }] };
|
|
157
|
+
}
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
server.tool(
|
|
161
|
+
"delete_people_watchlist",
|
|
162
|
+
"Delete a people watchlist and all its tracked data.",
|
|
163
|
+
{
|
|
164
|
+
id: z.string().describe("Watchlist ID to delete"),
|
|
165
|
+
},
|
|
166
|
+
async (params) => {
|
|
167
|
+
const result = await client.delete("/api-people-watchlist", {
|
|
168
|
+
id: params.id,
|
|
169
|
+
});
|
|
170
|
+
return { content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }] };
|
|
171
|
+
}
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
// ── Company Watchlists ──────────────────────────────────
|
|
175
|
+
|
|
176
|
+
server.tool(
|
|
177
|
+
"create_company_watchlist",
|
|
178
|
+
"Create a watchlist that monitors posts from LinkedIn company pages.",
|
|
179
|
+
{
|
|
180
|
+
companies: z
|
|
181
|
+
.array(z.string())
|
|
182
|
+
.min(1)
|
|
183
|
+
.describe("LinkedIn company URLs or slugs to track"),
|
|
184
|
+
name: z.string().optional().describe("Watchlist name"),
|
|
185
|
+
description: z.string().optional(),
|
|
186
|
+
labels: z.array(z.string()).optional(),
|
|
187
|
+
fetchFreqInHours: fetchFreqEnum.optional(),
|
|
188
|
+
},
|
|
189
|
+
async (params) => {
|
|
190
|
+
const body: Record<string, unknown> = { companies: params.companies };
|
|
191
|
+
if (params.name) body.name = params.name;
|
|
192
|
+
if (params.description) body.description = params.description;
|
|
193
|
+
if (params.labels) body.labels = params.labels;
|
|
194
|
+
if (params.fetchFreqInHours)
|
|
195
|
+
body.fetchFreqInHours = parseInt(params.fetchFreqInHours);
|
|
196
|
+
|
|
197
|
+
const result = await client.post("/api-company-watchlist", body);
|
|
198
|
+
return { content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }] };
|
|
199
|
+
}
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
server.tool(
|
|
203
|
+
"list_company_watchlists",
|
|
204
|
+
"List all company watchlists for your account.",
|
|
205
|
+
{},
|
|
206
|
+
async () => {
|
|
207
|
+
const result = await client.get("/api-company-watchlist");
|
|
208
|
+
return { content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }] };
|
|
209
|
+
}
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
server.tool(
|
|
213
|
+
"update_company_watchlist",
|
|
214
|
+
"Update a company watchlist's name, frequency, or status.",
|
|
215
|
+
{
|
|
216
|
+
id: z.string().describe("Watchlist ID"),
|
|
217
|
+
name: z.string().optional(),
|
|
218
|
+
fetchFreqInHours: fetchFreqEnum.optional(),
|
|
219
|
+
status: z.enum(["active", "paused"]).optional(),
|
|
220
|
+
},
|
|
221
|
+
async (params) => {
|
|
222
|
+
const body: Record<string, unknown> = { id: params.id };
|
|
223
|
+
if (params.name) body.name = params.name;
|
|
224
|
+
if (params.fetchFreqInHours)
|
|
225
|
+
body.fetchFreqInHours = parseInt(params.fetchFreqInHours);
|
|
226
|
+
if (params.status) body.status = params.status;
|
|
227
|
+
|
|
228
|
+
const result = await client.put("/api-company-watchlist", body);
|
|
229
|
+
return { content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }] };
|
|
230
|
+
}
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
server.tool(
|
|
234
|
+
"delete_company_watchlist",
|
|
235
|
+
"Delete a company watchlist and all its tracked data.",
|
|
236
|
+
{
|
|
237
|
+
id: z.string().describe("Watchlist ID to delete"),
|
|
238
|
+
},
|
|
239
|
+
async (params) => {
|
|
240
|
+
const result = await client.delete("/api-company-watchlist", {
|
|
241
|
+
id: params.id,
|
|
242
|
+
});
|
|
243
|
+
return { content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }] };
|
|
244
|
+
}
|
|
245
|
+
);
|
|
246
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "NodeNext",
|
|
5
|
+
"moduleResolution": "NodeNext",
|
|
6
|
+
"outDir": "dist",
|
|
7
|
+
"rootDir": "src",
|
|
8
|
+
"strict": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"forceConsistentCasingInFileNames": true,
|
|
12
|
+
"declaration": true,
|
|
13
|
+
"sourceMap": true
|
|
14
|
+
},
|
|
15
|
+
"include": ["src/**/*"],
|
|
16
|
+
"exclude": ["node_modules", "dist"]
|
|
17
|
+
}
|