mcp-stock-analyzer

bluebossa63/mcp-stock-analyzer

3.2

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.

Tools
5
Resources
0
Prompts
0

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-mini
  • MCP_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_URL and N8N_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

  • 1d1m
  • 5d15m (use 15m, not 10m)
  • 1mo60m
  • 3mo+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_JSON or MCP_ENV_B64 if your host mangles spaces.

Version & CI publishing

  • Server version can be synced from package.json via JSON import: import pkgJson from "../package.json" with { type: "json" }.
  • See .github/workflows/publish.yml for tag-based publishing to npm.