@pipeworx/mcp-stocktwits 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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Pipeworx
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,58 @@
1
+ # mcp-stocktwits
2
+
3
+ StockTwits MCP (keyless public read).
4
+
5
+ Part of [Pipeworx](https://pipeworx.io) — an MCP gateway connecting AI agents to 965+ live data sources.
6
+
7
+ ## Tools
8
+
9
+ | Tool | Description |
10
+ |------|-------------|
11
+ | `symbol_stream` | "What are people saying about [ticker]" / "StockTwits sentiment for [TICKER]" / "retail / WSB / Twitter chatter on [stock]" / "Stocktwits feed for [symbol]" — recent messages mentioning a ticker on StockTwits (the largest finance-focused social-media platform). Returns user posts with bullish/bearish sentiment tags, timestamps, like counts. Use for retail-investor sentiment, social-volume tracking, contrarian signal. |
12
+ | `user_stream` | Recent StockTwits posts from a specific user (by user_id string). Supports since/max cursor pagination and a limit cap. Returns messages with sentiment tags, timestamps, and ticker cashtags. Use to follow a particular trader\'s commentary stream. |
13
+ | `watchlist` | Recent StockTwits messages for all tickers in a specific watchlist (by watchlist_id). Supports since/max cursor pagination and a limit cap. Use to track social chatter across a curated list of symbols in one call. |
14
+
15
+ ## Quick Start
16
+
17
+ Add to your MCP client (Claude Desktop, Cursor, Windsurf, etc.):
18
+
19
+ ```json
20
+ {
21
+ "mcpServers": {
22
+ "stocktwits": {
23
+ "url": "https://gateway.pipeworx.io/stocktwits/mcp"
24
+ }
25
+ }
26
+ }
27
+ ```
28
+
29
+ Or connect to the full Pipeworx gateway for access to all 965+ data sources:
30
+
31
+ ```json
32
+ {
33
+ "mcpServers": {
34
+ "pipeworx": {
35
+ "url": "https://gateway.pipeworx.io/mcp"
36
+ }
37
+ }
38
+ }
39
+ ```
40
+
41
+ ## Using with ask_pipeworx
42
+
43
+ Instead of calling tools directly, you can ask questions in plain English:
44
+
45
+ ```
46
+ ask_pipeworx({ question: "your question about Stocktwits data" })
47
+ ```
48
+
49
+ The gateway picks the right tool and fills the arguments automatically.
50
+
51
+ ## More
52
+
53
+ - [All tools and guides](https://github.com/pipeworx-io/examples)
54
+ - [pipeworx.io](https://pipeworx.io)
55
+
56
+ ## License
57
+
58
+ MIT
package/package.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "@pipeworx/mcp-stocktwits",
3
+ "version": "0.1.0",
4
+ "description": "StockTwits MCP (keyless public read).",
5
+ "type": "module",
6
+ "main": "src/index.ts",
7
+ "types": "src/index.ts",
8
+ "keywords": ["mcp", "mcp-server", "model-context-protocol", "pipeworx", "stocktwits"],
9
+ "license": "MIT",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "https://github.com/pipeworx-io/mcp-stocktwits"
13
+ },
14
+ "scripts": {
15
+ "typecheck": "tsc --noEmit"
16
+ },
17
+ "devDependencies": {
18
+ "typescript": "^5.7.0"
19
+ }
20
+ }
package/server.json ADDED
@@ -0,0 +1,18 @@
1
+ {
2
+ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
+ "name": "io.github.pipeworx-io/stocktwits",
4
+ "title": "Stocktwits",
5
+ "description": "StockTwits MCP (keyless public read).",
6
+ "version": "0.1.0",
7
+ "websiteUrl": "https://pipeworx.io/packs/stocktwits",
8
+ "repository": {
9
+ "url": "https://github.com/pipeworx-io/mcp-stocktwits",
10
+ "source": "github"
11
+ },
12
+ "remotes": [
13
+ {
14
+ "type": "streamable-http",
15
+ "url": "https://gateway.pipeworx.io/stocktwits/mcp"
16
+ }
17
+ ]
18
+ }
package/src/index.ts ADDED
@@ -0,0 +1,99 @@
1
+ interface McpToolDefinition {
2
+ name: string;
3
+ description: string;
4
+ inputSchema: {
5
+ type: 'object';
6
+ properties: Record<string, unknown>;
7
+ required?: string[];
8
+ };
9
+ }
10
+
11
+ interface McpToolExport {
12
+ tools: McpToolDefinition[];
13
+ callTool: (name: string, args: Record<string, unknown>) => Promise<unknown>;
14
+ meter?: { credits: number };
15
+ cost?: Record<string, unknown>;
16
+ provider?: string;
17
+ }
18
+
19
+ /**
20
+ * StockTwits MCP (keyless public read).
21
+ */
22
+
23
+
24
+ const BASE = 'https://api.stocktwits.com/api/2';
25
+ const UA = 'pipeworx-mcp-stocktwits/1.0 (+https://pipeworx.io)';
26
+
27
+ const tools: McpToolExport['tools'] = [
28
+ {
29
+ name: 'symbol_stream',
30
+ description: '"What are people saying about [ticker]" / "StockTwits sentiment for [TICKER]" / "retail / WSB / Twitter chatter on [stock]" / "Stocktwits feed for [symbol]" — recent messages mentioning a ticker on StockTwits (the largest finance-focused social-media platform). Returns user posts with bullish/bearish sentiment tags, timestamps, like counts. Use for retail-investor sentiment, social-volume tracking, contrarian signal.',
31
+ inputSchema: {
32
+ type: 'object',
33
+ properties: { symbol: { type: 'string' }, since: { type: 'number' }, max: { type: 'number' }, limit: { type: 'number' }, filter: { type: 'string' } },
34
+ required: ['symbol'],
35
+ },
36
+ },
37
+ {
38
+ name: 'user_stream',
39
+ description: 'Recent StockTwits posts from a specific user (by user_id string). Supports since/max cursor pagination and a limit cap. Returns messages with sentiment tags, timestamps, and ticker cashtags. Use to follow a particular trader\'s commentary stream.',
40
+ inputSchema: {
41
+ type: 'object',
42
+ properties: { user_id: { type: 'string' }, since: { type: 'number' }, max: { type: 'number' }, limit: { type: 'number' } },
43
+ required: ['user_id'],
44
+ },
45
+ },
46
+ { name: 'trending_symbols', description: '"What stocks are trending today" / "most talked-about tickers" / "hot stocks on social media" / "WSB / retail trending names" — top trending tickers on StockTwits by message volume right now. Use for retail-attention scans, meme-stock detection, social-momentum trading.', inputSchema: { type: 'object', properties: { limit: { type: 'number' } } } },
47
+ { name: 'trending_messages', description: '"Most popular posts on StockTwits right now" / "trending stock chatter" — most-engaged-with messages across all StockTwits streams. Use for general market-zeitgeist sense-making.', inputSchema: { type: 'object', properties: { limit: { type: 'number' } } } },
48
+ { name: 'suggested_symbols', description: 'StockTwits editorially curated trending equities — a hand-picked selection distinct from raw-volume trending_symbols. Returns symbol tickers, names, and watch counts. Use when you want editorial picks rather than algorithmic social-volume rank.', inputSchema: { type: 'object', properties: { limit: { type: 'number' } } } },
49
+ { name: 'symbol_search', description: '"Look up StockTwits ticker for [company]" / "search for symbol on StockTwits" — symbol search on StockTwits to confirm a ticker exists or find variant tickers (e.g. crypto, ETFs).', inputSchema: { type: 'object', properties: { q: { type: 'string' }, limit: { type: 'number' } }, required: ['q'] } },
50
+ { name: 'chart_data', description: '"Chart data for [ticker]" / "sparkline data for [stock]" — price sparkline data for a ticker from StockTwits. Use for embedded thumbnail charts; prefer dedicated finance packs (yahoo-finance, alphavantage) for serious price analysis.', inputSchema: { type: 'object', properties: { symbol: { type: 'string' }, period: { type: 'string' } }, required: ['symbol'] } },
51
+ { name: 'watchlists', description: 'List a StockTwits user\'s public watchlists by user_id. Returns watchlist IDs, names, and ticker counts. Use to discover a trader\'s followed symbols; then pass a watchlist_id to the watchlist tool for the message stream.', inputSchema: { type: 'object', properties: { user_id: { type: 'string' } }, required: ['user_id'] } },
52
+ {
53
+ name: 'watchlist',
54
+ description: 'Recent StockTwits messages for all tickers in a specific watchlist (by watchlist_id). Supports since/max cursor pagination and a limit cap. Use to track social chatter across a curated list of symbols in one call.',
55
+ inputSchema: { type: 'object', properties: { watchlist_id: { type: 'string' }, since: { type: 'number' }, max: { type: 'number' }, limit: { type: 'number' } }, required: ['watchlist_id'] },
56
+ },
57
+ ];
58
+
59
+ async function callTool(name: string, args: Record<string, unknown>): Promise<unknown> {
60
+ const get = async (path: string, params?: Record<string, unknown>) => {
61
+ const p = new URLSearchParams();
62
+ if (params) for (const [k, v] of Object.entries(params)) if (v != null) p.set(k, String(v));
63
+ const url = `${BASE}${path}${[...p].length ? `?${p}` : ''}`;
64
+ const res = await fetch(url, { headers: { Accept: 'application/json', 'User-Agent': UA } });
65
+ if (res.status === 429) throw new Error('StockTwits: 429 rate limit (200 req/hr/IP free).');
66
+ if (res.status === 404) throw new Error('StockTwits: 404 — symbol/user/watchlist not found.');
67
+ if (!res.ok) throw new Error(`StockTwits: ${res.status}`);
68
+ return res.json();
69
+ };
70
+ const reqStr = (k: string, ex: string) => {
71
+ const v = args[k];
72
+ if (typeof v !== 'string' || !v.trim()) throw new Error(`Required argument "${k}" is missing. Pass a string like ${ex}.`);
73
+ return v;
74
+ };
75
+ switch (name) {
76
+ case 'symbol_stream':
77
+ return get(`/streams/symbol/${encodeURIComponent(reqStr('symbol', '"AAPL"'))}.json`, { since: args.since, max: args.max, limit: args.limit, filter: args.filter });
78
+ case 'user_stream':
79
+ return get(`/streams/user/${encodeURIComponent(reqStr('user_id', '"<user>"'))}.json`, { since: args.since, max: args.max, limit: args.limit });
80
+ case 'trending_symbols':
81
+ return get('/trending/symbols.json', { limit: args.limit });
82
+ case 'trending_messages':
83
+ return get('/streams/trending.json', { limit: args.limit });
84
+ case 'suggested_symbols':
85
+ return get('/trending/symbols/equities.json', { limit: args.limit });
86
+ case 'symbol_search':
87
+ return get('/search/symbols.json', { q: reqStr('q', '"AAPL"'), limit: args.limit });
88
+ case 'chart_data':
89
+ return get(`/symbols/${encodeURIComponent(reqStr('symbol', '"AAPL"'))}/chart.json`, { period: args.period });
90
+ case 'watchlists':
91
+ return get(`/watchlists/user/${encodeURIComponent(reqStr('user_id', '"<user>"'))}.json`);
92
+ case 'watchlist':
93
+ return get(`/streams/watchlist/${encodeURIComponent(reqStr('watchlist_id', '"<id>"'))}.json`, { since: args.since, max: args.max, limit: args.limit });
94
+ default:
95
+ throw new Error(`Unknown tool: ${name}`);
96
+ }
97
+ }
98
+
99
+ export default { tools, callTool, meter: { credits: 1 } } satisfies McpToolExport;
package/tsconfig.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "strict": true,
7
+ "esModuleInterop": true,
8
+ "skipLibCheck": true,
9
+ "outDir": "dist",
10
+ "rootDir": "src",
11
+ "declaration": true
12
+ },
13
+ "include": ["src"]
14
+ }