bluebossa63/mcp-stock-analyzer
If you are the rightful owner of mcp-stock-analyzer and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to dayong@mcphub.com.
The MCP Stock Analyzer TS is a server designed to provide stock analysis tools using AI evaluation of time series and sentiment data, optimized for integration with n8n workflows.
mcp-stock-analyzer-ts (STDIO)
An MCP server (Node 20+) exposing stock-analysis tools.
Design goals:
- AI-only evaluation – the LLM evaluates merged time series + sentiment (no local SMA math).
- N8N-friendly – single-var env hydration, clean JSON I/O.
- Executable code demo – optional tools to POST results to an n8n webhook.
Transport: STDIO (for n8n’s MCP Client node). Runtime: Node ≥20, TypeScript, pure ESM (NodeNext).
Quick start
npm ci
npm run build
npx -y @bluebossa63/mcp-stock-analyzer-ts-stdio
Environment setup (single-var friendly)
Use exactly one:
MCP_ENV=OPENAI_BASE_URL=https://api.openai.com,OPENAI_API_KEY=sk-...,OPENAI_MODEL=gpt-4o-miniMCP_ENV_JSON={"OPENAI_BASE_URL":"https://api.openai.com","OPENAI_API_KEY":"sk-...","OPENAI_MODEL":"gpt-4o-mini"}MCP_ENV_B64= base64 of:OPENAI_BASE_URL=https://api.openai.com OPENAI_API_KEY=sk-... OPENAI_MODEL=gpt-4o-mini
Optional:
N8N_WEBHOOK_URLandN8N_AUTH_HEADER(e.g.,x-api-key: abc123).
Tool catalog
All outputs are text JSON in result.content[0].text.
fetchChart
Input { "symbol":"AAPL", "range":"1mo", "interval":"1d" }
Output { "symbol":"AAPL","currency":"USD","points":[{"t":..., "o":...,"h":...,"l":...,"c":...,"v":...}] }
fetchMultiIntraday
Input { "symbol":"NVDA" }
Output
{
"symbol":"NVDA",
"intraday": {
"1m": { "points":[...] }, // 1d/1m
"15m": { "points":[...] }, // 5d/15m
"60m": { "points":[...] } // 1mo/60m
}
}
fetchNewsTitles
Input { "symbol":"NVDA", "max": 10 } → { "symbol":"NVDA", "titles":[...] }
defineSentiment
Input
{ "articles": ["Beats expectations", "Analyst warns of volatility"] }
Output
{ "sentiment":"positive","confidence":0.78,"reasoning":"..." }
evaluateWithAI / evaluateScoreWithAI
Input
{
"symbol":"NVDA",
"intraday": {
"1m": { "points":[{"t":1710000000000,"c":100},{"t":1710000600000,"c":101}] },
"15m": { "points":[/* ... */] },
"60m": { "points":[/* ... */] }
},
"sentiment": { "sentiment":"positive","confidence": 0.7, "reasoning":"..." },
"aggregate": false,
"perTimeframeMaxPoints": 200,
"extraNotes": "Be conservative."
}
Output
{ "perTimeframe": { "1m": {"decision":"hold","reasoning":"..."}, "15m": {"decision":"buy","reasoning":"..."}, "60m": {"decision":"hold","reasoning":"..."} } }
getSentimentFromNews
Input { "symbol":"NVDA", "max": 10 } → { "symbol":"NVDA", "titles":[...], "sentiment": {...} }
pipelineEvaluateAI
Input { "symbol":"NVDA", "maxNews":10, "aggregate":false, "perTimeframeMaxPoints":200 } → same output as evaluateWithAI.
postToN8N (executable)
Input { "payload": {...}, "webhookUrl":"https://your/webhook", "authHeader":"x-api-key: abc123" }
Output { "ok": true, "status": 200, "statusText": "OK", "body": "..." }
(Env fallback: N8N_WEBHOOK_URL, N8N_AUTH_HEADER)
evaluateAndPost (executable)
Runs evaluateScoreWithAI then POSTs the result.
Input = evaluateScoreWithAI args + optional webhookUrl.
Local smoke tests
Sentiment:
OPENAI_BASE_URL=https://api.openai.com OPENAI_API_KEY=sk-... OPENAI_MODEL=gpt-4o-mini node --input-type=module -e "import('./dist/ai.js').then(async m => { const r = await m.defineSentimentFromTexts(['Strong demand','Macro risks']); console.log(r) })"
Evaluate:
OPENAI_BASE_URL=https://api.openai.com OPENAI_API_KEY=sk-... OPENAI_MODEL=gpt-4o-mini node --input-type=module -e "import('./dist/ai.js').then(async m => {
const res = await m.evaluateWithAI({
symbol:'NVDA',
intraday: { '60m': { points: [ {t:1710000000000,c:100},{t:1710003600000,c:102},{t:1710007200000,c:101} ] } },
sentiment: { sentiment:'neutral', confidence:0.55 },
aggregate:false, perTimeframeMaxPoints:120
});
console.log(JSON.stringify(res,null,2));
})"
n8n wiring patterns
Modular → fetchNewsTitles → defineSentiment → fetchMultiIntraday → evaluateScoreWithAI → (optional) postToN8N
Helper function to build toolParameters:
function parseMcp(item){const raw=item?.json?.result?.content?.[0]?.text;return raw?JSON.parse(raw):null;}
const intradayObj = parseMcp(itemsFromNode('MCP: fetchMultiIntraday')[0]).intraday;
const sentimentObj = parseMcp(itemsFromNode('MCP: defineSentiment')[0]);
const symbol = parseMcp(itemsFromNode('MCP: fetchMultiIntraday')[0]).symbol || "NVDA";
return [{ json: { toolParameters: JSON.stringify({ symbol, intraday: intradayObj, sentiment: sentimentObj, aggregate:false, perTimeframeMaxPoints:200 }) } }];
One-shot → pipelineEvaluateAI → (optional) postToN8N
All-in-one → evaluateAndPost
Yahoo ranges/intervals that work
1d→1m5d→15m(use 15m, not 10m)1mo→60m3mo+→1d/1wk/1mo
Troubleshooting
fetch failed→ add selectively:NODE_OPTIONS=--dns-result-order=ipv4first- corporate proxies:
HTTPS_PROXY,HTTP_PROXY,NO_PROXY - corp CA:
NODE_EXTRA_CA_CERTS=/path/to/ca.pem
- 401 (OpenAI) → missing/garbled key; check with
debug-echo-openai. - Env parsing → prefer
MCP_ENV_JSONorMCP_ENV_B64if your host mangles spaces.
Version & CI publishing
- Server version can be synced from
package.jsonvia JSON import:import pkgJson from "../package.json" with { type: "json" }. - See
.github/workflows/publish.ymlfor tag-based publishing to npm.