npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@bluebossa63/mcp-stock-analyzer-ts-stdio

v1.0.7

Published

MCP server (Node 20, STDIO-only) with Yahoo Finance, OpenAI-compatible sentiment, evaluation, and n8n Command Line integration.

Downloads

38

Readme

mcp-stock-analyzer-ts (STDIO)

An MCP server (Node 20+) that exposes stock-analysis utilities as Model Context Protocol tools.
Designed to work smoothly with n8n’s MCP Client (Command Line) node and OpenAI-compatible LLMs.


✨ What’s inside (current state)

Pure AI-driven evaluation (no local math):

  • defineSentiment → calls your OpenAI-compatible endpoint to classify sentiment from headlines/text.
  • evaluateWithAI → passes intraday time series + sentiment to the model with an engineered prompt; returns per-timeframe decisions (and optional overall if requested).

Convenience fetchers:

  • fetchChart → Yahoo Finance OHLCV (range/interval).
  • fetchMultiIntraday → pulls 1m, 10m (fallback 15m), 60m series.
  • fetchNewsTitles → Yahoo Finance RSS headlines.

AI-only orchestration:

  • getSentimentFromNews → fetch headlines + run defineSentiment.
  • evaluateScoreWithAI → run the model on your provided {intraday, sentiment} (no fetching).
  • pipelineEvaluateAI → one-shot: fetch intraday + news → sentiment → model evaluation.

Diagnostics:

  • debug-env, debug-echo-openai

No local calculations remain (e.g., SMA). All decisioning is model-driven when you call evaluateWithAI/evaluateScoreWithAI or the pipeline tool.


🧰 Tool reference

| Tool | Purpose | Input (JSON) | Output (JSON, in result.content[0].text) | |---|---|---|---| | fetchChart | Single Yahoo series | { "symbol":"AAPL", "range":"1mo", "interval":"1d" } | { symbol, currency?, points: [{t,c,o?,h?,l?,v?}] } | | fetchMultiIntraday | 1m / 10m(→15m) / 60m | { "symbol":"NVDA" } | { symbol, intraday: { "1m": PriceSeries, "10m": PriceSeries?, "60m": PriceSeries } } | | fetchNewsTitles | Headlines (RSS) | { "symbol":"NVDA", "max": 10 } | { symbol, titles: string[] } | | defineSentiment | LLM sentiment | { "articles": ["...","..."] } | { sentiment: "positive"|"neutral"|"negative", confidence: number, reasoning?: string } | | getSentimentFromNews | Headlines → sentiment | { "symbol":"NVDA", "max": 10 } | { symbol, titles, sentiment } | | evaluateWithAI | Model eval (compact series) | { "symbol":"NVDA", "intraday": { "1m":{points:[{t,c}]}, ... }, "sentiment": {...}, "aggregate": false } | { perTimeframe: { "<tf>": { decision, reasoning } }, overall? } | | evaluateScoreWithAI | Same as above (explicit name) | same as evaluateWithAI | same | | pipelineEvaluateAI | One-shot pipeline | { "symbol":"NVDA", "maxNews":10, "aggregate":false, "perTimeframeMaxPoints":200 } | same as evaluateWithAI |

Yahoo ranges/intervals (validated combos)

  • 1d → 1m
  • 5d → 15m
  • 1mo → 60m
  • 3mo+ → 1d / 1wk / 1mo (Use 15m instead of 10m for 5-day intraday data.)

🚀 Quick start

1) Install & build

npm ci
npm run build

2) Run as STDIO (for n8n MCP Client)

npx -y @bluebossa63/mcp-stock-analyzer-ts-stdio

3) Environment (single variable friendly)

The n8n MCP node may only accept one env var. This server supports blob hydration:

  • Preferred: set one of the following in the node’s Environment Variables field:

Comma/newline blob

MCP_ENV=OPENAI_BASE_URL=https://api.openai.com,OPENAI_API_KEY=sk-...,OPENAI_MODEL=gpt-4o-mini

JSON blob

MCP_ENV_JSON={"OPENAI_BASE_URL":"https://api.openai.com","OPENAI_API_KEY":"sk-...","OPENAI_MODEL":"gpt-4o-mini"}

Base64 blob

printf 'OPENAI_BASE_URL=https://api.openai.com\nOPENAI_API_KEY=sk-...\nOPENAI_MODEL=gpt-4o-mini\n' | base64
# paste result as:
MCP_ENV_B64=PD9...
  • Wrapper command alternative (bypasses env parsing):
    • Command: sh
    • Arguments:
      -lc 'OPENAI_BASE_URL=https://api.openai.com OPENAI_API_KEY=sk-... OPENAI_MODEL=gpt-4o-mini npx -y @bluebossa63/mcp-stock-analyzer-ts-stdio'

4) Required env keys

  • OPENAI_BASE_URL (default https://api.openai.com)
  • OPENAI_API_KEY (required)
  • OPENAI_MODEL (default gpt-4o-mini)

Optional (for webhooks):

  • N8N_WEBHOOK_URL
  • N8N_AUTH_HEADER (e.g., x-api-key: abc123)

🔌 n8n wiring patterns

A) News → Sentiment → Intraday → Evaluate (modular)

  1. MCP: fetchNewsTitles { "symbol":"NVDA", "max": 10 }
  2. Function: map titles → { "articles": [...] }
  3. MCP: defineSentiment (from step 2)
  4. MCP: fetchMultiIntraday { "symbol":"NVDA" }
  5. Function: build toolParameters for evaluateScoreWithAI:
    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 }) } }];
  6. MCP: evaluateScoreWithAI with toolParameters = {{$json.toolParameters}}

B) One-shot

  • MCP: pipelineEvaluateAI { "symbol":"NVDA", "maxNews": 10, "aggregate": false, "perTimeframeMaxPoints": 200 }

C) Post to n8n webhook (optional)

If you add the postToN8N/evaluateAndPost tools (see code snippets), you can push results to your own webhook.


🧪 Local smoke tests

Sentiment only:

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 datacenter demand','Analyst warns of volatility']); console.log(r) })"

Evaluate with AI (provide your own small series):

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:'positive', confidence:0.75, reasoning:'…' },
    aggregate:false, perTimeframeMaxPoints:120
  });
  console.log(JSON.stringify(res,null,2));
})"

🛡️ Robustness & Troubleshooting

  • Env hydration: runs at the top of ai.ts so even if your MCP node collapses variables into one, parsing works.
  • Yahoo compat: fetchMultiIntraday transparently falls back 5d/10m → 5d/15m. Use fetchChart for custom pairs.
  • Network hiccups: if you see fetch failed, consider adding to your env blob:
    • NODE_OPTIONS=--dns-result-order=ipv4first
    • corporate proxy/CA: HTTPS_PROXY, HTTP_PROXY, NO_PROXY, NODE_EXTRA_CA_CERTS
  • 401: check key with debug-echo-openai (shows base + prefix) and ensure Authorization is set (the code forces it).

🔒 Notes

  • Do not log secrets; debug-echo-openai masks the key.
  • Be mindful of token size; evaluateWithAI compacts each timeframe (default last 120 points). Tune via perTimeframeMaxPoints.

License

MIT © 2025