@houtini/fmp-mcp 1.0.2 → 1.1.1

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@houtini/fmp-mcp",
3
- "version": "1.0.2",
4
- "description": "Model Context Protocol (MCP) server for Financial Modeling Prep API - stdio transport for Claude Desktop integration",
3
+ "version": "1.1.1",
4
+ "description": "Model Context Protocol (MCP) server for Financial Modeling Prep API - comprehensive financial data including quotes, fundamentals, analyst data, technical indicators, and market insights",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "fmp-mcp": "./build/index.js"
@@ -19,7 +19,12 @@
19
19
  "financial-data",
20
20
  "model-context-protocol",
21
21
  "claude",
22
- "ai-tools"
22
+ "ai-tools",
23
+ "analyst-data",
24
+ "technical-indicators",
25
+ "market-data",
26
+ "insider-trading",
27
+ "economic-data"
23
28
  ],
24
29
  "author": "Houtini AI",
25
30
  "license": "MIT",
package/src/index.ts CHANGED
@@ -171,6 +171,336 @@ const TOOLS: Tool[] = [
171
171
  required: ['symbol'],
172
172
  },
173
173
  },
174
+ {
175
+ name: 'get_market_gainers',
176
+ description: 'Get stocks with the largest price increases (top gainers)',
177
+ inputSchema: {
178
+ type: 'object',
179
+ properties: {},
180
+ },
181
+ },
182
+ {
183
+ name: 'get_market_losers',
184
+ description: 'Get stocks with the largest price drops (top losers)',
185
+ inputSchema: {
186
+ type: 'object',
187
+ properties: {},
188
+ },
189
+ },
190
+ {
191
+ name: 'get_most_active',
192
+ description: 'Get most actively traded stocks by volume',
193
+ inputSchema: {
194
+ type: 'object',
195
+ properties: {},
196
+ },
197
+ },
198
+ {
199
+ name: 'get_sector_performance',
200
+ description: 'Get current sector performance snapshot',
201
+ inputSchema: {
202
+ type: 'object',
203
+ properties: {
204
+ date: {
205
+ type: 'string',
206
+ description: 'Date in YYYY-MM-DD format (optional, defaults to latest)',
207
+ },
208
+ },
209
+ },
210
+ },
211
+ {
212
+ name: 'get_analyst_estimates',
213
+ description: 'Get analyst financial estimates for a stock (revenue, EPS forecasts)',
214
+ inputSchema: {
215
+ type: 'object',
216
+ properties: {
217
+ symbol: {
218
+ type: 'string',
219
+ description: 'Stock ticker symbol',
220
+ },
221
+ period: {
222
+ type: 'string',
223
+ description: 'Period type (annual or quarter)',
224
+ enum: ['annual', 'quarter'],
225
+ },
226
+ limit: {
227
+ type: 'number',
228
+ description: 'Number of periods to return (default: 10)',
229
+ },
230
+ },
231
+ required: ['symbol'],
232
+ },
233
+ },
234
+ {
235
+ name: 'get_price_target',
236
+ description: 'Get analyst price target summary for a stock',
237
+ inputSchema: {
238
+ type: 'object',
239
+ properties: {
240
+ symbol: {
241
+ type: 'string',
242
+ description: 'Stock ticker symbol',
243
+ },
244
+ },
245
+ required: ['symbol'],
246
+ },
247
+ },
248
+ {
249
+ name: 'get_analyst_ratings',
250
+ description: 'Get analyst ratings and upgrades/downgrades for a stock',
251
+ inputSchema: {
252
+ type: 'object',
253
+ properties: {
254
+ symbol: {
255
+ type: 'string',
256
+ description: 'Stock ticker symbol',
257
+ },
258
+ },
259
+ required: ['symbol'],
260
+ },
261
+ },
262
+ {
263
+ name: 'get_insider_trading',
264
+ description: 'Get recent insider trading activity for a stock',
265
+ inputSchema: {
266
+ type: 'object',
267
+ properties: {
268
+ symbol: {
269
+ type: 'string',
270
+ description: 'Stock ticker symbol',
271
+ },
272
+ limit: {
273
+ type: 'number',
274
+ description: 'Number of transactions to return (default: 100)',
275
+ },
276
+ },
277
+ required: ['symbol'],
278
+ },
279
+ },
280
+ {
281
+ name: 'get_key_metrics',
282
+ description: 'Get key financial metrics (P/E, ROE, debt ratios, etc.)',
283
+ inputSchema: {
284
+ type: 'object',
285
+ properties: {
286
+ symbol: {
287
+ type: 'string',
288
+ description: 'Stock ticker symbol',
289
+ },
290
+ period: {
291
+ type: 'string',
292
+ description: 'Period type (annual or quarter)',
293
+ enum: ['annual', 'quarter'],
294
+ },
295
+ limit: {
296
+ type: 'number',
297
+ description: 'Number of periods to return (default: 5)',
298
+ },
299
+ },
300
+ required: ['symbol'],
301
+ },
302
+ },
303
+ {
304
+ name: 'get_financial_ratios',
305
+ description: 'Get detailed financial ratios (profitability, liquidity, efficiency)',
306
+ inputSchema: {
307
+ type: 'object',
308
+ properties: {
309
+ symbol: {
310
+ type: 'string',
311
+ description: 'Stock ticker symbol',
312
+ },
313
+ period: {
314
+ type: 'string',
315
+ description: 'Period type (annual or quarter)',
316
+ enum: ['annual', 'quarter'],
317
+ },
318
+ limit: {
319
+ type: 'number',
320
+ description: 'Number of periods to return (default: 5)',
321
+ },
322
+ },
323
+ required: ['symbol'],
324
+ },
325
+ },
326
+ {
327
+ name: 'get_earnings_calendar',
328
+ description: 'Get upcoming earnings announcements calendar',
329
+ inputSchema: {
330
+ type: 'object',
331
+ properties: {
332
+ from: {
333
+ type: 'string',
334
+ description: 'Start date in YYYY-MM-DD format (optional)',
335
+ },
336
+ to: {
337
+ type: 'string',
338
+ description: 'End date in YYYY-MM-DD format (optional)',
339
+ },
340
+ },
341
+ },
342
+ },
343
+ {
344
+ name: 'get_economic_calendar',
345
+ description: 'Get upcoming economic data releases calendar',
346
+ inputSchema: {
347
+ type: 'object',
348
+ properties: {
349
+ from: {
350
+ type: 'string',
351
+ description: 'Start date in YYYY-MM-DD format (optional)',
352
+ },
353
+ to: {
354
+ type: 'string',
355
+ description: 'End date in YYYY-MM-DD format (optional)',
356
+ },
357
+ },
358
+ },
359
+ },
360
+ {
361
+ name: 'get_economic_indicator',
362
+ description: 'Get economic indicator data (GDP, unemployment, inflation, etc.)',
363
+ inputSchema: {
364
+ type: 'object',
365
+ properties: {
366
+ name: {
367
+ type: 'string',
368
+ description: 'Indicator name (e.g., GDP, unemploymentRate, CPI)',
369
+ },
370
+ from: {
371
+ type: 'string',
372
+ description: 'Start date in YYYY-MM-DD format (optional)',
373
+ },
374
+ to: {
375
+ type: 'string',
376
+ description: 'End date in YYYY-MM-DD format (optional)',
377
+ },
378
+ },
379
+ required: ['name'],
380
+ },
381
+ },
382
+ {
383
+ name: 'get_technical_indicator_rsi',
384
+ description: 'Get Relative Strength Index (RSI) technical indicator',
385
+ inputSchema: {
386
+ type: 'object',
387
+ properties: {
388
+ symbol: {
389
+ type: 'string',
390
+ description: 'Stock ticker symbol',
391
+ },
392
+ timeframe: {
393
+ type: 'string',
394
+ description: 'Timeframe (1min, 5min, 15min, 30min, 1hour, 4hour, 1day)',
395
+ enum: ['1min', '5min', '15min', '30min', '1hour', '4hour', '1day'],
396
+ },
397
+ period: {
398
+ type: 'number',
399
+ description: 'Period length (default: 14)',
400
+ },
401
+ },
402
+ required: ['symbol', 'timeframe'],
403
+ },
404
+ },
405
+ {
406
+ name: 'get_technical_indicator_sma',
407
+ description: 'Get Simple Moving Average (SMA) technical indicator',
408
+ inputSchema: {
409
+ type: 'object',
410
+ properties: {
411
+ symbol: {
412
+ type: 'string',
413
+ description: 'Stock ticker symbol',
414
+ },
415
+ timeframe: {
416
+ type: 'string',
417
+ description: 'Timeframe (1min, 5min, 15min, 30min, 1hour, 4hour, 1day)',
418
+ enum: ['1min', '5min', '15min', '30min', '1hour', '4hour', '1day'],
419
+ },
420
+ period: {
421
+ type: 'number',
422
+ description: 'Period length (default: 10)',
423
+ },
424
+ },
425
+ required: ['symbol', 'timeframe'],
426
+ },
427
+ },
428
+ {
429
+ name: 'get_technical_indicator_ema',
430
+ description: 'Get Exponential Moving Average (EMA) technical indicator',
431
+ inputSchema: {
432
+ type: 'object',
433
+ properties: {
434
+ symbol: {
435
+ type: 'string',
436
+ description: 'Stock ticker symbol',
437
+ },
438
+ timeframe: {
439
+ type: 'string',
440
+ description: 'Timeframe (1min, 5min, 15min, 30min, 1hour, 4hour, 1day)',
441
+ enum: ['1min', '5min', '15min', '30min', '1hour', '4hour', '1day'],
442
+ },
443
+ period: {
444
+ type: 'number',
445
+ description: 'Period length (default: 10)',
446
+ },
447
+ },
448
+ required: ['symbol', 'timeframe'],
449
+ },
450
+ },
451
+ {
452
+ name: 'get_historical_chart',
453
+ description: 'Get historical price data with flexible time intervals',
454
+ inputSchema: {
455
+ type: 'object',
456
+ properties: {
457
+ symbol: {
458
+ type: 'string',
459
+ description: 'Stock ticker symbol',
460
+ },
461
+ interval: {
462
+ type: 'string',
463
+ description: 'Time interval (1min, 5min, 15min, 30min, 1hour, 4hour)',
464
+ enum: ['1min', '5min', '15min', '30min', '1hour', '4hour'],
465
+ },
466
+ from: {
467
+ type: 'string',
468
+ description: 'Start date in YYYY-MM-DD format (optional)',
469
+ },
470
+ to: {
471
+ type: 'string',
472
+ description: 'End date in YYYY-MM-DD format (optional)',
473
+ },
474
+ },
475
+ required: ['symbol', 'interval'],
476
+ },
477
+ },
478
+ {
479
+ name: 'get_institutional_holders',
480
+ description: 'Get institutional ownership (13F filings) for a stock',
481
+ inputSchema: {
482
+ type: 'object',
483
+ properties: {
484
+ symbol: {
485
+ type: 'string',
486
+ description: 'Stock ticker symbol',
487
+ },
488
+ limit: {
489
+ type: 'number',
490
+ description: 'Number of holders to return (default: 100)',
491
+ },
492
+ },
493
+ required: ['symbol'],
494
+ },
495
+ },
496
+ {
497
+ name: 'get_sp500_constituents',
498
+ description: 'Get list of S&P 500 index constituents',
499
+ inputSchema: {
500
+ type: 'object',
501
+ properties: {},
502
+ },
503
+ },
174
504
  ];
175
505
 
176
506
  /**
@@ -179,7 +509,7 @@ const TOOLS: Tool[] = [
179
509
  const server = new Server(
180
510
  {
181
511
  name: 'fmp-mcp-server',
182
- version: '1.0.0',
512
+ version: '1.1.0',
183
513
  },
184
514
  {
185
515
  capabilities: {
@@ -308,6 +638,297 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
308
638
  };
309
639
  }
310
640
 
641
+ case 'get_market_gainers': {
642
+ const data = await fetchFMP('/biggest-gainers');
643
+ return {
644
+ content: [
645
+ {
646
+ type: 'text',
647
+ text: JSON.stringify(data, null, 2),
648
+ },
649
+ ],
650
+ };
651
+ }
652
+
653
+ case 'get_market_losers': {
654
+ const data = await fetchFMP('/biggest-losers');
655
+ return {
656
+ content: [
657
+ {
658
+ type: 'text',
659
+ text: JSON.stringify(data, null, 2),
660
+ },
661
+ ],
662
+ };
663
+ }
664
+
665
+ case 'get_most_active': {
666
+ const data = await fetchFMP('/most-actives');
667
+ return {
668
+ content: [
669
+ {
670
+ type: 'text',
671
+ text: JSON.stringify(data, null, 2),
672
+ },
673
+ ],
674
+ };
675
+ }
676
+
677
+ case 'get_sector_performance': {
678
+ const { date } = args as { date?: string };
679
+ const endpoint = date
680
+ ? `/sector-performance-snapshot?date=${date}`
681
+ : '/sector-performance-snapshot?date=' + new Date().toISOString().split('T')[0];
682
+ const data = await fetchFMP(endpoint);
683
+ return {
684
+ content: [
685
+ {
686
+ type: 'text',
687
+ text: JSON.stringify(data, null, 2),
688
+ },
689
+ ],
690
+ };
691
+ }
692
+
693
+ case 'get_analyst_estimates': {
694
+ const { symbol, period = 'annual', limit = 10 } = args as {
695
+ symbol: string;
696
+ period?: string;
697
+ limit?: number;
698
+ };
699
+ const data = await fetchFMP(`/analyst-estimates?symbol=${symbol.toUpperCase()}&period=${period}&limit=${limit}`);
700
+ return {
701
+ content: [
702
+ {
703
+ type: 'text',
704
+ text: JSON.stringify(data, null, 2),
705
+ },
706
+ ],
707
+ };
708
+ }
709
+
710
+ case 'get_price_target': {
711
+ const { symbol } = args as { symbol: string };
712
+ const data = await fetchFMP(`/price-target-summary?symbol=${symbol.toUpperCase()}`);
713
+ return {
714
+ content: [
715
+ {
716
+ type: 'text',
717
+ text: JSON.stringify(data, null, 2),
718
+ },
719
+ ],
720
+ };
721
+ }
722
+
723
+ case 'get_analyst_ratings': {
724
+ const { symbol } = args as { symbol: string };
725
+ const data = await fetchFMP(`/grades?symbol=${symbol.toUpperCase()}`);
726
+ return {
727
+ content: [
728
+ {
729
+ type: 'text',
730
+ text: JSON.stringify(data, null, 2),
731
+ },
732
+ ],
733
+ };
734
+ }
735
+
736
+ case 'get_insider_trading': {
737
+ const { symbol, limit = 100 } = args as { symbol: string; limit?: number };
738
+ const data = await fetchFMP(`/insider-trading/search?symbol=${symbol.toUpperCase()}&limit=${limit}`);
739
+ return {
740
+ content: [
741
+ {
742
+ type: 'text',
743
+ text: JSON.stringify(data, null, 2),
744
+ },
745
+ ],
746
+ };
747
+ }
748
+
749
+ case 'get_key_metrics': {
750
+ const { symbol, period = 'annual', limit = 5 } = args as {
751
+ symbol: string;
752
+ period?: string;
753
+ limit?: number;
754
+ };
755
+ const data = await fetchFMP(`/key-metrics?symbol=${symbol.toUpperCase()}&period=${period}&limit=${limit}`);
756
+ return {
757
+ content: [
758
+ {
759
+ type: 'text',
760
+ text: JSON.stringify(data, null, 2),
761
+ },
762
+ ],
763
+ };
764
+ }
765
+
766
+ case 'get_financial_ratios': {
767
+ const { symbol, period = 'annual', limit = 5 } = args as {
768
+ symbol: string;
769
+ period?: string;
770
+ limit?: number;
771
+ };
772
+ const data = await fetchFMP(`/ratios?symbol=${symbol.toUpperCase()}&period=${period}&limit=${limit}`);
773
+ return {
774
+ content: [
775
+ {
776
+ type: 'text',
777
+ text: JSON.stringify(data, null, 2),
778
+ },
779
+ ],
780
+ };
781
+ }
782
+
783
+ case 'get_earnings_calendar': {
784
+ const { from, to } = args as { from?: string; to?: string };
785
+ let endpoint = '/earnings-calendar';
786
+ const params = [];
787
+ if (from) params.push(`from=${from}`);
788
+ if (to) params.push(`to=${to}`);
789
+ if (params.length > 0) endpoint += `?${params.join('&')}`;
790
+ const data = await fetchFMP(endpoint);
791
+ return {
792
+ content: [
793
+ {
794
+ type: 'text',
795
+ text: JSON.stringify(data, null, 2),
796
+ },
797
+ ],
798
+ };
799
+ }
800
+
801
+ case 'get_economic_calendar': {
802
+ const { from, to } = args as { from?: string; to?: string };
803
+ let endpoint = '/economic-calendar';
804
+ const params = [];
805
+ if (from) params.push(`from=${from}`);
806
+ if (to) params.push(`to=${to}`);
807
+ if (params.length > 0) endpoint += `?${params.join('&')}`;
808
+ const data = await fetchFMP(endpoint);
809
+ return {
810
+ content: [
811
+ {
812
+ type: 'text',
813
+ text: JSON.stringify(data, null, 2),
814
+ },
815
+ ],
816
+ };
817
+ }
818
+
819
+ case 'get_economic_indicator': {
820
+ const { name, from, to } = args as { name: string; from?: string; to?: string };
821
+ let endpoint = `/economic-indicators?name=${name}`;
822
+ if (from) endpoint += `&from=${from}`;
823
+ if (to) endpoint += `&to=${to}`;
824
+ const data = await fetchFMP(endpoint);
825
+ return {
826
+ content: [
827
+ {
828
+ type: 'text',
829
+ text: JSON.stringify(data, null, 2),
830
+ },
831
+ ],
832
+ };
833
+ }
834
+
835
+ case 'get_technical_indicator_rsi': {
836
+ const { symbol, timeframe, period = 14 } = args as {
837
+ symbol: string;
838
+ timeframe: string;
839
+ period?: number;
840
+ };
841
+ const data = await fetchFMP(`/technical-indicators/rsi?symbol=${symbol.toUpperCase()}&timeframe=${timeframe}&periodLength=${period}`);
842
+ return {
843
+ content: [
844
+ {
845
+ type: 'text',
846
+ text: JSON.stringify(data, null, 2),
847
+ },
848
+ ],
849
+ };
850
+ }
851
+
852
+ case 'get_technical_indicator_sma': {
853
+ const { symbol, timeframe, period = 10 } = args as {
854
+ symbol: string;
855
+ timeframe: string;
856
+ period?: number;
857
+ };
858
+ const data = await fetchFMP(`/technical-indicators/sma?symbol=${symbol.toUpperCase()}&timeframe=${timeframe}&periodLength=${period}`);
859
+ return {
860
+ content: [
861
+ {
862
+ type: 'text',
863
+ text: JSON.stringify(data, null, 2),
864
+ },
865
+ ],
866
+ };
867
+ }
868
+
869
+ case 'get_technical_indicator_ema': {
870
+ const { symbol, timeframe, period = 10 } = args as {
871
+ symbol: string;
872
+ timeframe: string;
873
+ period?: number;
874
+ };
875
+ const data = await fetchFMP(`/technical-indicators/ema?symbol=${symbol.toUpperCase()}&timeframe=${timeframe}&periodLength=${period}`);
876
+ return {
877
+ content: [
878
+ {
879
+ type: 'text',
880
+ text: JSON.stringify(data, null, 2),
881
+ },
882
+ ],
883
+ };
884
+ }
885
+
886
+ case 'get_historical_chart': {
887
+ const { symbol, interval, from, to } = args as {
888
+ symbol: string;
889
+ interval: string;
890
+ from?: string;
891
+ to?: string;
892
+ };
893
+ let endpoint = `/historical-chart/${interval}?symbol=${symbol.toUpperCase()}`;
894
+ if (from) endpoint += `&from=${from}`;
895
+ if (to) endpoint += `&to=${to}`;
896
+ const data = await fetchFMP(endpoint);
897
+ return {
898
+ content: [
899
+ {
900
+ type: 'text',
901
+ text: JSON.stringify(data, null, 2),
902
+ },
903
+ ],
904
+ };
905
+ }
906
+
907
+ case 'get_institutional_holders': {
908
+ const { symbol, limit = 100 } = args as { symbol: string; limit?: number };
909
+ const data = await fetchFMP(`/institutional-ownership/latest?symbol=${symbol.toUpperCase()}&limit=${limit}`);
910
+ return {
911
+ content: [
912
+ {
913
+ type: 'text',
914
+ text: JSON.stringify(data, null, 2),
915
+ },
916
+ ],
917
+ };
918
+ }
919
+
920
+ case 'get_sp500_constituents': {
921
+ const data = await fetchFMP('/sp500-constituent');
922
+ return {
923
+ content: [
924
+ {
925
+ type: 'text',
926
+ text: JSON.stringify(data, null, 2),
927
+ },
928
+ ],
929
+ };
930
+ }
931
+
311
932
  default:
312
933
  throw new Error(`Unknown tool: ${name}`);
313
934
  }
@@ -332,7 +953,6 @@ async function main() {
332
953
  const transport = new StdioServerTransport();
333
954
  await server.connect(transport);
334
955
 
335
- // Log to stderr so it doesn't interfere with stdio protocol
336
956
  console.error('FMP MCP Server running on stdio');
337
957
  }
338
958
 
package/commit_msg.txt DELETED
@@ -1,8 +0,0 @@
1
- fix: correct stock news endpoint and document paid tier requirements
2
-
3
- - Fix stock news endpoint from /stock_news?tickers= to /news/stock?symbols=
4
- - Update README with clear free vs paid tier indicators
5
- - Add API Limitations section explaining 402 Payment Required errors
6
- - Bump version to 1.0.2
7
-
8
- Resolves 404 errors on get_stock_news tool (now correctly returns 402 for free tier)