@crowdlisten/harness 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/AGENTS.md +167 -0
- package/LICENSE +21 -0
- package/README.md +153 -0
- package/dist/agent-proxy.d.ts +24 -0
- package/dist/agent-proxy.js +140 -0
- package/dist/agent-tools.d.ts +736 -0
- package/dist/agent-tools.js +409 -0
- package/dist/context/api.d.ts +5 -0
- package/dist/context/api.js +164 -0
- package/dist/context/cli.d.ts +19 -0
- package/dist/context/cli.js +108 -0
- package/dist/context/extractor.d.ts +12 -0
- package/dist/context/extractor.js +43 -0
- package/dist/context/index.d.ts +12 -0
- package/dist/context/index.js +11 -0
- package/dist/context/matcher.d.ts +39 -0
- package/dist/context/matcher.js +246 -0
- package/dist/context/parser.d.ts +28 -0
- package/dist/context/parser.js +157 -0
- package/dist/context/pipeline.d.ts +26 -0
- package/dist/context/pipeline.js +56 -0
- package/dist/context/prompts.d.ts +6 -0
- package/dist/context/prompts.js +60 -0
- package/dist/context/providers.d.ts +6 -0
- package/dist/context/providers.js +106 -0
- package/dist/context/redactor.d.ts +10 -0
- package/dist/context/redactor.js +68 -0
- package/dist/context/server.d.ts +5 -0
- package/dist/context/server.js +134 -0
- package/dist/context/store.d.ts +12 -0
- package/dist/context/store.js +82 -0
- package/dist/context/types.d.ts +79 -0
- package/dist/context/types.js +4 -0
- package/dist/context/user-state.d.ts +40 -0
- package/dist/context/user-state.js +144 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +385 -0
- package/dist/insights/browser/BrowserPool.d.ts +87 -0
- package/dist/insights/browser/BrowserPool.js +266 -0
- package/dist/insights/browser/RequestInterceptor.d.ts +46 -0
- package/dist/insights/browser/RequestInterceptor.js +115 -0
- package/dist/insights/cli.d.ts +8 -0
- package/dist/insights/cli.js +206 -0
- package/dist/insights/core/base/BaseAdapter.d.ts +37 -0
- package/dist/insights/core/base/BaseAdapter.js +123 -0
- package/dist/insights/core/health/HealthMonitor.d.ts +75 -0
- package/dist/insights/core/health/HealthMonitor.js +171 -0
- package/dist/insights/core/interfaces/SocialMediaPlatform.d.ts +125 -0
- package/dist/insights/core/interfaces/SocialMediaPlatform.js +42 -0
- package/dist/insights/core/utils/DataNormalizer.d.ts +53 -0
- package/dist/insights/core/utils/DataNormalizer.js +349 -0
- package/dist/insights/core/utils/InstagramUrlUtils.d.ts +11 -0
- package/dist/insights/core/utils/InstagramUrlUtils.js +60 -0
- package/dist/insights/core/utils/TikTokUrlUtils.d.ts +10 -0
- package/dist/insights/core/utils/TikTokUrlUtils.js +57 -0
- package/dist/insights/handlers.d.ts +157 -0
- package/dist/insights/handlers.js +246 -0
- package/dist/insights/index.d.ts +437 -0
- package/dist/insights/index.js +426 -0
- package/dist/insights/platforms/instagram/InstagramAdapter.d.ts +34 -0
- package/dist/insights/platforms/instagram/InstagramAdapter.js +342 -0
- package/dist/insights/platforms/moltbook/MoltbookAdapter.d.ts +31 -0
- package/dist/insights/platforms/moltbook/MoltbookAdapter.js +227 -0
- package/dist/insights/platforms/reddit/RedditAdapter.d.ts +21 -0
- package/dist/insights/platforms/reddit/RedditAdapter.js +212 -0
- package/dist/insights/platforms/tiktok/TikTokAdapter.d.ts +34 -0
- package/dist/insights/platforms/tiktok/TikTokAdapter.js +269 -0
- package/dist/insights/platforms/twitter/TwitterAdapter.d.ts +23 -0
- package/dist/insights/platforms/twitter/TwitterAdapter.js +211 -0
- package/dist/insights/platforms/xiaohongshu/XiaohongshuAdapter.d.ts +35 -0
- package/dist/insights/platforms/xiaohongshu/XiaohongshuAdapter.js +258 -0
- package/dist/insights/platforms/youtube/YouTubeAdapter.d.ts +22 -0
- package/dist/insights/platforms/youtube/YouTubeAdapter.js +254 -0
- package/dist/insights/service-config.d.ts +7 -0
- package/dist/insights/service-config.js +60 -0
- package/dist/insights/services/UnifiedSocialMediaService.d.ts +94 -0
- package/dist/insights/services/UnifiedSocialMediaService.js +259 -0
- package/dist/insights/vision/VisionExtractor.d.ts +46 -0
- package/dist/insights/vision/VisionExtractor.js +236 -0
- package/dist/learnings.d.ts +50 -0
- package/dist/learnings.js +130 -0
- package/dist/openapi.d.ts +29 -0
- package/dist/openapi.js +169 -0
- package/dist/server-factory.d.ts +20 -0
- package/dist/server-factory.js +41 -0
- package/dist/suggestions.d.ts +16 -0
- package/dist/suggestions.js +72 -0
- package/dist/telemetry.d.ts +44 -0
- package/dist/telemetry.js +93 -0
- package/dist/tools/registry.d.ts +65 -0
- package/dist/tools/registry.js +256 -0
- package/dist/tools.d.ts +2433 -0
- package/dist/tools.js +2294 -0
- package/dist/transport/http.d.ts +15 -0
- package/dist/transport/http.js +154 -0
- package/package.json +76 -0
- package/skills/catalog.json +272 -0
- package/skills/community-catalog.json +4202 -0
- package/skills/competitive-analysis/SKILL.md +174 -0
- package/skills/content-creator/SKILL.md +256 -0
- package/skills/content-strategy/SKILL.md +222 -0
- package/skills/data-storytelling/SKILL.md +248 -0
- package/skills/heuristic-evaluation/SKILL.md +201 -0
- package/skills/market-research-reports/SKILL.md +184 -0
- package/skills/user-stories/SKILL.md +178 -0
- package/skills/ux-researcher/SKILL.md +239 -0
- package/web-dist/assets/index-B1b25lNd.css +1 -0
- package/web-dist/assets/index-CDWHwHbl.js +64 -0
- package/web-dist/index.html +16 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Streamable HTTP Transport for CrowdListen Harness
|
|
4
|
+
*
|
|
5
|
+
* Exposes the full MCP tool surface over HTTP. Stateless mode —
|
|
6
|
+
* each request extracts auth from Authorization header.
|
|
7
|
+
*
|
|
8
|
+
* Endpoints:
|
|
9
|
+
* POST /mcp — MCP tool calls (StreamableHTTPServerTransport)
|
|
10
|
+
* GET /mcp — SSE connection for streaming
|
|
11
|
+
* DELETE /mcp — Session cleanup
|
|
12
|
+
* GET /health — Health check
|
|
13
|
+
* GET /openapi.json — Auto-generated OpenAPI spec
|
|
14
|
+
*/
|
|
15
|
+
export declare function startHttpTransport(port?: number): Promise<void>;
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Streamable HTTP Transport for CrowdListen Harness
|
|
4
|
+
*
|
|
5
|
+
* Exposes the full MCP tool surface over HTTP. Stateless mode —
|
|
6
|
+
* each request extracts auth from Authorization header.
|
|
7
|
+
*
|
|
8
|
+
* Endpoints:
|
|
9
|
+
* POST /mcp — MCP tool calls (StreamableHTTPServerTransport)
|
|
10
|
+
* GET /mcp — SSE connection for streaming
|
|
11
|
+
* DELETE /mcp — Session cleanup
|
|
12
|
+
* GET /health — Health check
|
|
13
|
+
* GET /openapi.json — Auto-generated OpenAPI spec
|
|
14
|
+
*/
|
|
15
|
+
import * as http from "http";
|
|
16
|
+
import * as crypto from "crypto";
|
|
17
|
+
import { createClient } from "@supabase/supabase-js";
|
|
18
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
19
|
+
import { createMcpServer, SERVER_VERSION } from "../server-factory.js";
|
|
20
|
+
import { generateOpenApiSpec } from "../openapi.js";
|
|
21
|
+
import { TOOLS } from "../tools.js";
|
|
22
|
+
const CROWDLISTEN_SUPABASE_URL = process.env.CROWDLISTEN_URL || "https://fnvlxtzonwybshtvrzit.supabase.co";
|
|
23
|
+
const CROWDLISTEN_ANON_KEY = process.env.CROWDLISTEN_ANON_KEY ||
|
|
24
|
+
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImZudmx4dHpvbnd5YnNodHZyeml0Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NTY4NjExMjksImV4cCI6MjA3MjQzNzEyOX0.KAoEVMAVxqANcHBrjT5Et_9xiMZGP7LzdVSoSDLxpaA";
|
|
25
|
+
// ─── Auth Extraction ───────────────────────────────────────────────────────
|
|
26
|
+
async function authenticateRequest(req
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
28
|
+
) {
|
|
29
|
+
const authHeader = req.headers.authorization;
|
|
30
|
+
if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
|
31
|
+
throw new Error("Authorization header required: Bearer <token>");
|
|
32
|
+
}
|
|
33
|
+
const token = authHeader.slice(7);
|
|
34
|
+
const supabase = createClient(CROWDLISTEN_SUPABASE_URL, CROWDLISTEN_ANON_KEY, {
|
|
35
|
+
auth: { autoRefreshToken: false, persistSession: false },
|
|
36
|
+
});
|
|
37
|
+
// Try as JWT first
|
|
38
|
+
const { data, error } = await supabase.auth.getUser(token);
|
|
39
|
+
if (!error && data.user) {
|
|
40
|
+
// Set session so RLS works — refresh_token must be non-empty
|
|
41
|
+
// for Supabase to properly set the auth context
|
|
42
|
+
await supabase.auth.setSession({
|
|
43
|
+
access_token: token,
|
|
44
|
+
refresh_token: token, // reuse access_token; won't refresh but RLS works
|
|
45
|
+
});
|
|
46
|
+
return { supabase, userId: data.user.id };
|
|
47
|
+
}
|
|
48
|
+
// Could be an API key — look up in api_keys table
|
|
49
|
+
const anonSb = createClient(CROWDLISTEN_SUPABASE_URL, CROWDLISTEN_ANON_KEY);
|
|
50
|
+
const { data: keyRow } = await anonSb
|
|
51
|
+
.from("api_keys")
|
|
52
|
+
.select("user_id")
|
|
53
|
+
.eq("key_hash", hashApiKey(token))
|
|
54
|
+
.eq("revoked", false)
|
|
55
|
+
.single();
|
|
56
|
+
if (keyRow) {
|
|
57
|
+
return { supabase: anonSb, userId: keyRow.user_id };
|
|
58
|
+
}
|
|
59
|
+
throw new Error("Invalid token or API key");
|
|
60
|
+
}
|
|
61
|
+
function hashApiKey(key) {
|
|
62
|
+
return crypto.createHash("sha256").update(key).digest("hex");
|
|
63
|
+
}
|
|
64
|
+
// ─── CORS Headers ──────────────────────────────────────────────────────────
|
|
65
|
+
function setCorsHeaders(res) {
|
|
66
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
67
|
+
res.setHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, OPTIONS");
|
|
68
|
+
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, Accept");
|
|
69
|
+
res.setHeader("Access-Control-Max-Age", "86400");
|
|
70
|
+
}
|
|
71
|
+
// ─── HTTP Server ───────────────────────────────────────────────────────────
|
|
72
|
+
export async function startHttpTransport(port = 3848) {
|
|
73
|
+
// Cache the OpenAPI spec
|
|
74
|
+
let cachedSpec = null;
|
|
75
|
+
const httpServer = http.createServer(async (req, res) => {
|
|
76
|
+
setCorsHeaders(res);
|
|
77
|
+
// Handle CORS preflight
|
|
78
|
+
if (req.method === "OPTIONS") {
|
|
79
|
+
res.writeHead(204);
|
|
80
|
+
res.end();
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const url = new URL(req.url || "/", `http://localhost:${port}`);
|
|
84
|
+
// ── Health Check ─────────────────────────────────────────
|
|
85
|
+
if (url.pathname === "/health" && req.method === "GET") {
|
|
86
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
87
|
+
res.end(JSON.stringify({
|
|
88
|
+
status: "ok",
|
|
89
|
+
version: SERVER_VERSION,
|
|
90
|
+
tools: TOOLS.length,
|
|
91
|
+
transport: "streamable-http",
|
|
92
|
+
}));
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
// ── OpenAPI Spec ─────────────────────────────────────────
|
|
96
|
+
if (url.pathname === "/openapi.json" && req.method === "GET") {
|
|
97
|
+
if (!cachedSpec) {
|
|
98
|
+
cachedSpec = JSON.stringify(generateOpenApiSpec(), null, 2);
|
|
99
|
+
}
|
|
100
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
101
|
+
res.end(cachedSpec);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
// ── MCP Endpoints ────────────────────────────────────────
|
|
105
|
+
if (url.pathname === "/mcp") {
|
|
106
|
+
try {
|
|
107
|
+
const { supabase, userId } = await authenticateRequest(req);
|
|
108
|
+
const server = createMcpServer({ supabase, userId });
|
|
109
|
+
const transport = new StreamableHTTPServerTransport({
|
|
110
|
+
sessionIdGenerator: undefined, // Stateless mode
|
|
111
|
+
});
|
|
112
|
+
await server.connect(transport);
|
|
113
|
+
await transport.handleRequest(req, res);
|
|
114
|
+
// Clean up after request completes
|
|
115
|
+
await server.close();
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
119
|
+
const status = message.includes("Authorization") ? 401 : 500;
|
|
120
|
+
res.writeHead(status, { "Content-Type": "application/json" });
|
|
121
|
+
res.end(JSON.stringify({ error: message }));
|
|
122
|
+
}
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
// ── 404 ──────────────────────────────────────────────────
|
|
126
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
127
|
+
res.end(JSON.stringify({
|
|
128
|
+
error: "Not found",
|
|
129
|
+
endpoints: ["/mcp", "/health", "/openapi.json"],
|
|
130
|
+
}));
|
|
131
|
+
});
|
|
132
|
+
httpServer.listen(port, () => {
|
|
133
|
+
console.error(`
|
|
134
|
+
CrowdListen Harness HTTP server running
|
|
135
|
+
|
|
136
|
+
MCP: http://localhost:${port}/mcp
|
|
137
|
+
Health: http://localhost:${port}/health
|
|
138
|
+
OpenAPI: http://localhost:${port}/openapi.json
|
|
139
|
+
|
|
140
|
+
Tools: ${TOOLS.length} across planning, analysis, content, generation, LLM, and agent network
|
|
141
|
+
|
|
142
|
+
Connect from any MCP client:
|
|
143
|
+
{ "url": "http://localhost:${port}/mcp" }
|
|
144
|
+
`);
|
|
145
|
+
});
|
|
146
|
+
// Graceful shutdown
|
|
147
|
+
process.on("SIGINT", () => {
|
|
148
|
+
console.error("\nShutting down...");
|
|
149
|
+
httpServer.close(() => process.exit(0));
|
|
150
|
+
});
|
|
151
|
+
process.on("SIGTERM", () => {
|
|
152
|
+
httpServer.close(() => process.exit(0));
|
|
153
|
+
});
|
|
154
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@crowdlisten/harness",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Crowd context for AI agents — analyzed crowd intelligence from social platforms, with planning, skill packs, and semantic recall",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"crowdlisten-harness": "dist/index.js",
|
|
8
|
+
"crowdlisten-serve": "dist/transport/http.js",
|
|
9
|
+
"crowdlisten": "dist/insights/cli.js"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc",
|
|
13
|
+
"build:web": "cd src/context/web && npx vite build --outDir ../../../web-dist",
|
|
14
|
+
"build:catalog": "node scripts/build-catalog.js",
|
|
15
|
+
"build:all": "npm run build:catalog && npm run build && npm run build:web",
|
|
16
|
+
"dev": "tsx src/index.ts",
|
|
17
|
+
"start": "node dist/index.js",
|
|
18
|
+
"test": "vitest run",
|
|
19
|
+
"test:watch": "vitest",
|
|
20
|
+
"test:coverage": "vitest run --coverage",
|
|
21
|
+
"test:e2e": "vitest run --config vitest.e2e.config.ts"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
25
|
+
"@supabase/supabase-js": "^2.49.4",
|
|
26
|
+
"@the-convocation/twitter-scraper": "^0.22.1",
|
|
27
|
+
"axios": "^1.13.1",
|
|
28
|
+
"commander": "^14.0.3",
|
|
29
|
+
"dotenv": "^17.3.1",
|
|
30
|
+
"jszip": "^3.10.1",
|
|
31
|
+
"node-fetch": "^3.3.2",
|
|
32
|
+
"pdf-parse": "^1.1.1"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"tsx": "^4.19.0",
|
|
36
|
+
"typescript": "^5.7.0",
|
|
37
|
+
"@types/node": "^22.0.0",
|
|
38
|
+
"playwright": "^1.58.2",
|
|
39
|
+
"vitest": "^3.0.0",
|
|
40
|
+
"@vitest/coverage-v8": "^3.0.0",
|
|
41
|
+
"react": "^19.0.0",
|
|
42
|
+
"react-dom": "^19.0.0",
|
|
43
|
+
"@types/react": "^19.0.0",
|
|
44
|
+
"@types/react-dom": "^19.0.0",
|
|
45
|
+
"vite": "^6.0.0",
|
|
46
|
+
"@vitejs/plugin-react": "^4.3.0",
|
|
47
|
+
"tailwindcss": "^4.0.0",
|
|
48
|
+
"@tailwindcss/vite": "^4.0.0"
|
|
49
|
+
},
|
|
50
|
+
"files": [
|
|
51
|
+
"dist",
|
|
52
|
+
"web-dist",
|
|
53
|
+
"skills",
|
|
54
|
+
"README.md",
|
|
55
|
+
"AGENTS.md",
|
|
56
|
+
"LICENSE"
|
|
57
|
+
],
|
|
58
|
+
"keywords": [
|
|
59
|
+
"mcp",
|
|
60
|
+
"planning",
|
|
61
|
+
"delegation",
|
|
62
|
+
"coding-agent",
|
|
63
|
+
"crowdlisten",
|
|
64
|
+
"knowledge-base",
|
|
65
|
+
"context-extraction",
|
|
66
|
+
"social-media",
|
|
67
|
+
"crowd-intelligence",
|
|
68
|
+
"skill-packs"
|
|
69
|
+
],
|
|
70
|
+
"license": "MIT",
|
|
71
|
+
"repository": {
|
|
72
|
+
"type": "git",
|
|
73
|
+
"url": "https://github.com/Crowdlisten/crowdlisten_harness.git"
|
|
74
|
+
},
|
|
75
|
+
"homepage": "https://crowdlisten.com"
|
|
76
|
+
}
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"id": "competitive-analysis",
|
|
4
|
+
"name": "crowdlisten:competitive-analysis",
|
|
5
|
+
"description": "Competitive intelligence through audience perception analysis. Use when comparing brands, products, or competitors in social conversations. Requires CROWDLISTEN_API_KEY.",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"competitive",
|
|
8
|
+
"intelligence",
|
|
9
|
+
"audience",
|
|
10
|
+
"perception",
|
|
11
|
+
"analysis",
|
|
12
|
+
"comparing",
|
|
13
|
+
"brands",
|
|
14
|
+
"products",
|
|
15
|
+
"competitors",
|
|
16
|
+
"social",
|
|
17
|
+
"conversations",
|
|
18
|
+
"crowdlisten",
|
|
19
|
+
"positioning",
|
|
20
|
+
"strategy",
|
|
21
|
+
"market",
|
|
22
|
+
"entry",
|
|
23
|
+
"landscape",
|
|
24
|
+
"assessment",
|
|
25
|
+
"tracking",
|
|
26
|
+
"competitor",
|
|
27
|
+
"changes",
|
|
28
|
+
"time",
|
|
29
|
+
"identifying",
|
|
30
|
+
"underserved",
|
|
31
|
+
"segments",
|
|
32
|
+
"feature",
|
|
33
|
+
"identification",
|
|
34
|
+
"preparing",
|
|
35
|
+
"fundraising",
|
|
36
|
+
"board",
|
|
37
|
+
"meetings",
|
|
38
|
+
"strategic",
|
|
39
|
+
"reviews"
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"id": "content-creator",
|
|
44
|
+
"name": "crowdlisten:content-creator",
|
|
45
|
+
"description": "Generate SEO-optimized marketing content with brand voice analysis. Blog posts, social media, email campaigns. Use when creating any branded content.",
|
|
46
|
+
"keywords": [
|
|
47
|
+
"generate",
|
|
48
|
+
"seo-optimized",
|
|
49
|
+
"marketing",
|
|
50
|
+
"content",
|
|
51
|
+
"brand",
|
|
52
|
+
"voice",
|
|
53
|
+
"analysis",
|
|
54
|
+
"blog",
|
|
55
|
+
"posts",
|
|
56
|
+
"social",
|
|
57
|
+
"media",
|
|
58
|
+
"email",
|
|
59
|
+
"campaigns",
|
|
60
|
+
"creating",
|
|
61
|
+
"branded",
|
|
62
|
+
"creator"
|
|
63
|
+
]
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"id": "content-strategy",
|
|
67
|
+
"name": "crowdlisten:content-strategy",
|
|
68
|
+
"description": "Data-driven content strategy grounded in audience demand. Topic demand analysis, content gaps, platform optimization, voice matching, campaign tracking. Requires CROWDLISTEN_API_KEY.",
|
|
69
|
+
"keywords": [
|
|
70
|
+
"data-driven",
|
|
71
|
+
"content",
|
|
72
|
+
"strategy",
|
|
73
|
+
"grounded",
|
|
74
|
+
"audience",
|
|
75
|
+
"demand",
|
|
76
|
+
"topic",
|
|
77
|
+
"analysis",
|
|
78
|
+
"gaps",
|
|
79
|
+
"platform",
|
|
80
|
+
"optimization",
|
|
81
|
+
"voice",
|
|
82
|
+
"matching",
|
|
83
|
+
"campaign",
|
|
84
|
+
"tracking",
|
|
85
|
+
"crowdlisten",
|
|
86
|
+
"calendar",
|
|
87
|
+
"planning",
|
|
88
|
+
"audience-validated",
|
|
89
|
+
"topics",
|
|
90
|
+
"finding",
|
|
91
|
+
"competitors",
|
|
92
|
+
"haven",
|
|
93
|
+
"covered",
|
|
94
|
+
"optimizing",
|
|
95
|
+
"format",
|
|
96
|
+
"timing",
|
|
97
|
+
"adapting",
|
|
98
|
+
"brand",
|
|
99
|
+
"match",
|
|
100
|
+
"communication",
|
|
101
|
+
"style",
|
|
102
|
+
"measuring",
|
|
103
|
+
"resonance",
|
|
104
|
+
"adjusting",
|
|
105
|
+
"product",
|
|
106
|
+
"launches",
|
|
107
|
+
"performance",
|
|
108
|
+
"monitoring",
|
|
109
|
+
"real-time",
|
|
110
|
+
"sentiment",
|
|
111
|
+
"during",
|
|
112
|
+
"launch",
|
|
113
|
+
"windows",
|
|
114
|
+
"crisis",
|
|
115
|
+
"early",
|
|
116
|
+
"warning",
|
|
117
|
+
"message",
|
|
118
|
+
"scoring"
|
|
119
|
+
]
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"id": "data-storytelling",
|
|
123
|
+
"name": "crowdlisten:data-storytelling",
|
|
124
|
+
"description": "Transform data and analysis into compelling narratives. Problem-Solution, Trend, Comparison, Hero's Journey frameworks. Use when presenting insights to stakeholders.",
|
|
125
|
+
"keywords": [
|
|
126
|
+
"transform",
|
|
127
|
+
"data",
|
|
128
|
+
"analysis",
|
|
129
|
+
"compelling",
|
|
130
|
+
"narratives",
|
|
131
|
+
"problem-solution",
|
|
132
|
+
"trend",
|
|
133
|
+
"comparison",
|
|
134
|
+
"hero",
|
|
135
|
+
"journey",
|
|
136
|
+
"frameworks",
|
|
137
|
+
"presenting",
|
|
138
|
+
"insights",
|
|
139
|
+
"stakeholders",
|
|
140
|
+
"storytelling"
|
|
141
|
+
]
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
"id": "heuristic-evaluation",
|
|
145
|
+
"name": "crowdlisten:heuristic-evaluation",
|
|
146
|
+
"description": "Customer feedback analysis from social conversations. Journey friction detection, pain point mapping, persona generation, churn risk signals. Requires CROWDLISTEN_API_KEY.",
|
|
147
|
+
"keywords": [
|
|
148
|
+
"customer",
|
|
149
|
+
"feedback",
|
|
150
|
+
"analysis",
|
|
151
|
+
"social",
|
|
152
|
+
"conversations",
|
|
153
|
+
"journey",
|
|
154
|
+
"friction",
|
|
155
|
+
"detection",
|
|
156
|
+
"pain",
|
|
157
|
+
"point",
|
|
158
|
+
"mapping",
|
|
159
|
+
"persona",
|
|
160
|
+
"generation",
|
|
161
|
+
"churn",
|
|
162
|
+
"risk",
|
|
163
|
+
"signals",
|
|
164
|
+
"crowdlisten",
|
|
165
|
+
"experience",
|
|
166
|
+
"improvement",
|
|
167
|
+
"optimization",
|
|
168
|
+
"clustering",
|
|
169
|
+
"usability",
|
|
170
|
+
"signal",
|
|
171
|
+
"organic",
|
|
172
|
+
"discussions",
|
|
173
|
+
"support",
|
|
174
|
+
"strategy",
|
|
175
|
+
"ticket",
|
|
176
|
+
"deflection",
|
|
177
|
+
"health",
|
|
178
|
+
"monitoring",
|
|
179
|
+
"prevention",
|
|
180
|
+
"identifying",
|
|
181
|
+
"profiling",
|
|
182
|
+
"target",
|
|
183
|
+
"audience",
|
|
184
|
+
"segments",
|
|
185
|
+
"heuristic",
|
|
186
|
+
"evaluation"
|
|
187
|
+
]
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"id": "market-research-reports",
|
|
191
|
+
"name": "crowdlisten:market-research",
|
|
192
|
+
"description": "Generate comprehensive market research reports with Porter's Five Forces, PESTLE, SWOT, TAM/SAM/SOM, BCG Matrix. Use for market analysis, competitive landscape, industry trends.",
|
|
193
|
+
"keywords": [
|
|
194
|
+
"generate",
|
|
195
|
+
"comprehensive",
|
|
196
|
+
"market",
|
|
197
|
+
"research",
|
|
198
|
+
"reports",
|
|
199
|
+
"porter",
|
|
200
|
+
"five",
|
|
201
|
+
"forces",
|
|
202
|
+
"pestle",
|
|
203
|
+
"swot",
|
|
204
|
+
"matrix",
|
|
205
|
+
"analysis",
|
|
206
|
+
"competitive",
|
|
207
|
+
"landscape",
|
|
208
|
+
"industry",
|
|
209
|
+
"trends"
|
|
210
|
+
]
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
"id": "user-stories",
|
|
214
|
+
"name": "crowdlisten:user-stories",
|
|
215
|
+
"description": "Turn social listening data into product decisions. JTBD extraction, feature demand scoring, persona generation, user story generation from real audience data. Requires CROWDLISTEN_API_KEY.",
|
|
216
|
+
"keywords": [
|
|
217
|
+
"turn",
|
|
218
|
+
"social",
|
|
219
|
+
"listening",
|
|
220
|
+
"data",
|
|
221
|
+
"product",
|
|
222
|
+
"decisions",
|
|
223
|
+
"jtbd",
|
|
224
|
+
"extraction",
|
|
225
|
+
"feature",
|
|
226
|
+
"demand",
|
|
227
|
+
"scoring",
|
|
228
|
+
"persona",
|
|
229
|
+
"generation",
|
|
230
|
+
"user",
|
|
231
|
+
"story",
|
|
232
|
+
"real",
|
|
233
|
+
"audience",
|
|
234
|
+
"crowdlisten",
|
|
235
|
+
"planning",
|
|
236
|
+
"roadmap",
|
|
237
|
+
"prioritization",
|
|
238
|
+
"discussions",
|
|
239
|
+
"request",
|
|
240
|
+
"analysis",
|
|
241
|
+
"early-stage",
|
|
242
|
+
"idea",
|
|
243
|
+
"validation",
|
|
244
|
+
"against",
|
|
245
|
+
"stories"
|
|
246
|
+
]
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
"id": "ux-researcher",
|
|
250
|
+
"name": "crowdlisten:ux-research",
|
|
251
|
+
"description": "UX research synthesis — user personas, journey maps, heuristic evaluation (Nielsen's 10), design recommendations. Use when analyzing user behavior or designing experiences.",
|
|
252
|
+
"keywords": [
|
|
253
|
+
"research",
|
|
254
|
+
"synthesis",
|
|
255
|
+
"user",
|
|
256
|
+
"personas",
|
|
257
|
+
"journey",
|
|
258
|
+
"maps",
|
|
259
|
+
"heuristic",
|
|
260
|
+
"evaluation",
|
|
261
|
+
"nielsen",
|
|
262
|
+
"design",
|
|
263
|
+
"recommendations",
|
|
264
|
+
"analyzing",
|
|
265
|
+
"behavior",
|
|
266
|
+
"designing",
|
|
267
|
+
"experiences",
|
|
268
|
+
"researcher",
|
|
269
|
+
"designer"
|
|
270
|
+
]
|
|
271
|
+
}
|
|
272
|
+
]
|