JC321 commited on
Commit
83b398d
·
verified ·
1 Parent(s): 74fcd29

Upload 2 files

Browse files
Files changed (2) hide show
  1. mcp_server_sse.py +18 -770
  2. templates/index.html +767 -0
mcp_server_sse.py CHANGED
@@ -6,7 +6,8 @@ Returns clean JSON without emoji formatting
6
  """
7
 
8
  from fastapi import FastAPI, Request, HTTPException
9
- from fastapi.responses import StreamingResponse, JSONResponse, HTMLResponse
 
10
  from fastapi.middleware.cors import CORSMiddleware
11
  from pydantic import BaseModel
12
  from typing import Dict, Any, List, Optional
@@ -18,6 +19,8 @@ from financial_analyzer import FinancialAnalyzer
18
  import time
19
  import sys
20
  import signal
 
 
21
  from contextlib import contextmanager
22
 
23
  # Initialize FastAPI app
@@ -505,775 +508,20 @@ async def sse_endpoint(request: Request):
505
  @app.get("/", response_class=HTMLResponse)
506
  async def root():
507
  """Interactive landing page with tool testing functionality"""
508
- return """
509
- <!DOCTYPE html>
510
- <html lang="en">
511
- <head>
512
- <meta charset="UTF-8">
513
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
514
- <title>SEC Financial Report MCP Server</title>
515
- <style>
516
- body {
517
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
518
- max-width: 1000px;
519
- margin: 30px auto;
520
- padding: 20px;
521
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
522
- min-height: 100vh;
523
- }
524
- .container {
525
- background: white;
526
- border-radius: 12px;
527
- padding: 40px;
528
- box-shadow: 0 10px 30px rgba(0,0,0,0.2);
529
- }
530
- h1 {
531
- color: #667eea;
532
- margin-top: 0;
533
- }
534
- .badge {
535
- display: inline-block;
536
- background: #10b981;
537
- color: white;
538
- padding: 4px 12px;
539
- border-radius: 12px;
540
- font-size: 12px;
541
- font-weight: bold;
542
- }
543
- .config-box {
544
- background: #f5f5f5;
545
- padding: 20px;
546
- border-radius: 8px;
547
- margin: 20px 0;
548
- font-family: 'Monaco', 'Courier New', monospace;
549
- font-size: 13px;
550
- overflow-x: auto;
551
- }
552
- .tools {
553
- margin: 30px 0;
554
- }
555
- .tool {
556
- background: #f9f9f9;
557
- margin: 10px 0;
558
- border-radius: 8px;
559
- border: 2px solid #e0e0e0;
560
- overflow: hidden;
561
- transition: all 0.3s;
562
- }
563
- .tool:hover {
564
- border-color: #667eea;
565
- }
566
- .tool-header {
567
- padding: 15px 20px;
568
- cursor: pointer;
569
- display: flex;
570
- justify-content: space-between;
571
- align-items: center;
572
- background: linear-gradient(to right, #f9f9f9, #ffffff);
573
- }
574
- .tool-header:hover {
575
- background: linear-gradient(to right, #f0f0f0, #f9f9f9);
576
- }
577
- .tool-title {
578
- display: flex;
579
- align-items: center;
580
- gap: 10px;
581
- }
582
- .tool-title h3 {
583
- margin: 0;
584
- color: #333;
585
- font-size: 16px;
586
- }
587
- .tool-title .desc {
588
- color: #666;
589
- font-size: 13px;
590
- }
591
- .toggle-icon {
592
- font-size: 20px;
593
- color: #667eea;
594
- transition: transform 0.3s;
595
- }
596
- .toggle-icon.expanded {
597
- transform: rotate(90deg);
598
- }
599
- .tool-body {
600
- display: none;
601
- padding: 20px;
602
- background: white;
603
- border-top: 1px solid #e0e0e0;
604
- }
605
- .tool-body.show {
606
- display: block;
607
- }
608
- .param-group {
609
- margin-bottom: 15px;
610
- }
611
- .param-group label {
612
- display: block;
613
- margin-bottom: 5px;
614
- font-weight: 500;
615
- color: #333;
616
- font-size: 14px;
617
- }
618
- .param-group input, .param-group select {
619
- width: 100%;
620
- padding: 10px;
621
- border: 2px solid #e0e0e0;
622
- border-radius: 6px;
623
- font-size: 14px;
624
- box-sizing: border-box;
625
- }
626
- .param-group input:focus, .param-group select:focus {
627
- outline: none;
628
- border-color: #667eea;
629
- }
630
- .param-hint {
631
- font-size: 12px;
632
- color: #999;
633
- margin-top: 3px;
634
- }
635
- .example-box {
636
- background: #f8f9fa;
637
- border: 1px solid #dee2e6;
638
- border-radius: 4px;
639
- padding: 10px;
640
- margin: 10px 0;
641
- font-size: 12px;
642
- }
643
- .example-box .example-title {
644
- font-weight: 600;
645
- color: #495057;
646
- margin-bottom: 5px;
647
- display: flex;
648
- align-items: center;
649
- gap: 5px;
650
- }
651
- .example-box .example-title::before {
652
- content: "💡";
653
- font-size: 14px;
654
- }
655
- .example-box .example-content {
656
- font-family: 'Monaco', 'Courier New', monospace;
657
- color: #6c757d;
658
- background: white;
659
- padding: 8px;
660
- border-radius: 3px;
661
- border-left: 3px solid #667eea;
662
- }
663
- .example-item {
664
- margin: 3px 0;
665
- }
666
- .example-label {
667
- color: #667eea;
668
- font-weight: 500;
669
- }
670
- .api-example-box {
671
- background: #1e1e1e;
672
- border-radius: 4px;
673
- padding: 12px;
674
- margin: 10px 0;
675
- font-family: 'Monaco', 'Courier New', monospace;
676
- font-size: 11px;
677
- overflow-x: auto;
678
- }
679
- .api-example-box .api-title {
680
- color: #9cdcfe;
681
- font-weight: 600;
682
- margin-bottom: 8px;
683
- display: flex;
684
- align-items: center;
685
- gap: 5px;
686
- }
687
- .api-example-box .api-title::before {
688
- content: "📡";
689
- font-size: 14px;
690
- }
691
- .api-example-box pre {
692
- margin: 0;
693
- color: #d4d4d4;
694
- white-space: pre-wrap;
695
- word-break: break-word;
696
- }
697
- .api-example-box .json-key {
698
- color: #9cdcfe;
699
- }
700
- .api-example-box .json-string {
701
- color: #ce9178;
702
- }
703
- .api-example-box .json-number {
704
- color: #b5cea8;
705
- }
706
- .test-btn {
707
- background: linear-gradient(135deg, #667eea, #764ba2);
708
- color: white;
709
- border: none;
710
- padding: 12px 30px;
711
- border-radius: 6px;
712
- cursor: pointer;
713
- font-size: 14px;
714
- font-weight: 600;
715
- transition: transform 0.2s, box-shadow 0.2s;
716
- margin-top: 10px;
717
- }
718
- .test-btn:hover {
719
- transform: translateY(-2px);
720
- box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
721
- }
722
- .test-btn:active {
723
- transform: translateY(0);
724
- }
725
- .test-btn:disabled {
726
- background: #ccc;
727
- cursor: not-allowed;
728
- transform: none;
729
- }
730
- .result-box {
731
- margin-top: 15px;
732
- padding: 15px;
733
- background: #f5f5f5;
734
- border-radius: 6px;
735
- border-left: 4px solid #667eea;
736
- font-family: 'Monaco', 'Courier New', monospace;
737
- font-size: 12px;
738
- max-height: 400px;
739
- overflow-y: auto;
740
- white-space: pre-wrap;
741
- word-break: break-word;
742
- display: none;
743
- }
744
- .result-box.show {
745
- display: block;
746
- }
747
- .result-box.error {
748
- border-left-color: #ef4444;
749
- background: #fee;
750
- }
751
- .result-box.success {
752
- border-left-color: #10b981;
753
- background: #f0fdf4;
754
- }
755
- .loading {
756
- display: inline-block;
757
- width: 14px;
758
- height: 14px;
759
- border: 2px solid #ffffff;
760
- border-radius: 50%;
761
- border-top-color: transparent;
762
- animation: spin 1s linear infinite;
763
- margin-left: 8px;
764
- }
765
- @keyframes spin {
766
- to { transform: rotate(360deg); }
767
- }
768
- code {
769
- background: #e0e0e0;
770
- padding: 2px 6px;
771
- border-radius: 3px;
772
- font-size: 12px;
773
- }
774
- </style>
775
- </head>
776
- <body>
777
- <div class="container">
778
- <h1>SEC Financial Report MCP Server API</h1>
779
- <p><span class="badge">MCP READY</span> Model Context Protocol Server for SEC EDGAR Financial Data</p>
780
-
781
- <h2>Connect to this MCP Server</h2>
782
- <p>Add the following configuration to your MCP client (e.g., Claude Desktop):</p>
783
-
784
- <div class="config-box">
785
- {
786
- "mcpServers": {
787
- "sec-financial-data": {
788
- "url": "https://jc321-easyreportsmcpserver.hf.space/sse"
789
- }
790
- }
791
- }
792
- </div>
793
-
794
- <p><strong>Use the URL above to connect to this MCP Server.</strong></p>
795
-
796
- <h2>Available Tools (7) - Interactive Testing</h2>
797
- <p style="color: #666; font-size: 14px;">Click on any tool below to expand and test it directly!</p>
798
-
799
- <div class="tools">
800
- <!-- Tool 1: search_company -->
801
- <div class="tool">
802
- <div class="tool-header" onclick="toggleTool('tool1')">
803
- <div class="tool-title">
804
- <span class="toggle-icon" id="icon-tool1">▶</span>
805
- <div>
806
- <h3>search_company</h3>
807
- <div class="desc">Search for a company by name in SEC EDGAR database</div>
808
- </div>
809
- </div>
810
- </div>
811
- <div class="tool-body" id="tool1">
812
- <div class="example-box">
813
- <div class="example-title">Parameter Format Example</div>
814
- <div class="example-content">
815
- <div class="example-item"><span class="example-label">Input:</span> "Microsoft"</div>
816
- <div class="example-item"><span class="example-label">Input:</span> "Apple Inc"</div>
817
- <div class="example-item"><span class="example-label">Input:</span> "Tesla"</div>
818
- </div>
819
- </div>
820
- <div class="api-example-box">
821
- <div class="api-title">API Request Example</div>
822
- <pre>{
823
- <span class="json-key">"jsonrpc"</span>: <span class="json-string">"2.0"</span>,
824
- <span class="json-key">"id"</span>: <span class="json-number">1</span>,
825
- <span class="json-key">"method"</span>: <span class="json-string">"tools/call"</span>,
826
- <span class="json-key">"params"</span>: {
827
- <span class="json-key">"name"</span>: <span class="json-string">"search_company"</span>,
828
- <span class="json-key">"arguments"</span>: {
829
- <span class="json-key">"company_name"</span>: <span class="json-string">"Microsoft"</span>
830
- }
831
- }
832
- }</pre>
833
- </div>
834
- <div class="param-group">
835
- <label>Company Name *</label>
836
- <input type="text" id="tool1-company_name" placeholder="e.g., Microsoft, Apple, Tesla">
837
- <div class="param-hint">Enter the full or partial company name</div>
838
- </div>
839
- <button class="test-btn" onclick="testTool('search_company', 'tool1')">Run Test</button>
840
- <div class="result-box" id="result-tool1"></div>
841
- </div>
842
- </div>
843
-
844
- <!-- Tool 2: advanced_search_company -->
845
- <div class="tool">
846
- <div class="tool-header" onclick="toggleTool('tool2')">
847
- <div class="tool-title">
848
- <span class="toggle-icon" id="icon-tool2">▶</span>
849
- <div>
850
- <h3>advanced_search_company</h3>
851
- <div class="desc">Advanced search supporting name, ticker, or CIK</div>
852
- </div>
853
- </div>
854
- </div>
855
- <div class="tool-body" id="tool2">
856
- <div class="example-box">
857
- <div class="example-title">Parameter Format Example</div>
858
- <div class="example-content">
859
- <div class="example-item"><span class="example-label">By Ticker:</span> "MSFT"</div>
860
- <div class="example-item"><span class="example-label">By CIK:</span> "0000789019"</div>
861
- <div class="example-item"><span class="example-label">By Name:</span> "Microsoft Corporation"</div>
862
- </div>
863
- </div>
864
- <div class="api-example-box">
865
- <div class="api-title">API Request Example</div>
866
- <pre>{
867
- <span class="json-key">"jsonrpc"</span>: <span class="json-string">"2.0"</span>,
868
- <span class="json-key">"id"</span>: <span class="json-number">1</span>,
869
- <span class="json-key">"method"</span>: <span class="json-string">"tools/call"</span>,
870
- <span class="json-key">"params"</span>: {
871
- <span class="json-key">"name"</span>: <span class="json-string">"advanced_search_company"</span>,
872
- <span class="json-key">"arguments"</span>: {
873
- <span class="json-key">"company_input"</span>: <span class="json-string">"MSFT"</span>
874
- }
875
- }
876
- }</pre>
877
- </div>
878
- <div class="param-group">
879
- <label>Company Name / Ticker / CIK *</label>
880
- <input type="text" id="tool2-company_input" placeholder="e.g., MSFT, 0000789019, Microsoft">
881
- <div class="param-hint">Enter company name, ticker symbol, or CIK code</div>
882
- </div>
883
- <button class="test-btn" onclick="testTool('advanced_search_company', 'tool2')">Run Test</button>
884
- <div class="result-box" id="result-tool2"></div>
885
- </div>
886
- </div>
887
-
888
- <!-- Tool 3: get_company_info -->
889
- <div class="tool">
890
- <div class="tool-header" onclick="toggleTool('tool3')">
891
- <div class="tool-title">
892
- <span class="toggle-icon" id="icon-tool3">▶</span>
893
- <div>
894
- <h3>get_company_info</h3>
895
- <div class="desc">Get detailed company information by CIK code</div>
896
- </div>
897
- </div>
898
- </div>
899
- <div class="tool-body" id="tool3">
900
- <div class="example-box">
901
- <div class="example-title">Parameter Format Example</div>
902
- <div class="example-content">
903
- <div class="example-item"><span class="example-label">Microsoft:</span> "0000789019"</div>
904
- <div class="example-item"><span class="example-label">Apple:</span> "0000320193"</div>
905
- <div class="example-item"><span class="example-label">Tesla:</span> "0001318605"</div>
906
- </div>
907
- </div>
908
- <div class="api-example-box">
909
- <div class="api-title">API Request Example</div>
910
- <pre>{
911
- <span class="json-key">"jsonrpc"</span>: <span class="json-string">"2.0"</span>,
912
- <span class="json-key">"id"</span>: <span class="json-number">1</span>,
913
- <span class="json-key">"method"</span>: <span class="json-string">"tools/call"</span>,
914
- <span class="json-key">"params"</span>: {
915
- <span class="json-key">"name"</span>: <span class="json-string">"get_company_info"</span>,
916
- <span class="json-key">"arguments"</span>: {
917
- <span class="json-key">"cik"</span>: <span class="json-string">"0000789019"</span>
918
- }
919
- }
920
- }</pre>
921
- </div>
922
- <div class="param-group">
923
- <label>CIK Code *</label>
924
- <input type="text" id="tool3-cik" placeholder="e.g., 0000789019">
925
- <div class="param-hint">10-digit CIK code (use search_company to find it)</div>
926
- </div>
927
- <button class="test-btn" onclick="testTool('get_company_info', 'tool3')">Run Test</button>
928
- <div class="result-box" id="result-tool3"></div>
929
- </div>
930
- </div>
931
-
932
- <!-- Tool 4: get_company_filings -->
933
- <div class="tool">
934
- <div class="tool-header" onclick="toggleTool('tool4')">
935
- <div class="tool-title">
936
- <span class="toggle-icon" id="icon-tool4">▶</span>
937
- <div>
938
- <h3>get_company_filings</h3>
939
- <div class="desc">Get list of SEC filings (10-K, 10-Q, 20-F, etc.)</div>
940
- </div>
941
- </div>
942
- </div>
943
- <div class="tool-body" id="tool4">
944
- <div class="example-box">
945
- <div class="example-title">Parameter Format Example</div>
946
- <div class="example-content">
947
- <div class="example-item"><span class="example-label">CIK:</span> "0000789019" (Microsoft)</div>
948
- <div class="example-item"><span class="example-label">Form Types:</span> Select "10-K" and "10-Q" from dropdown</div>
949
- <div class="example-item"><span class="example-label">Or:</span> Leave empty to get all filing types</div>
950
- </div>
951
- </div>
952
- <div class="api-example-box">
953
- <div class="api-title">API Request Example</div>
954
- <pre>{
955
- <span class="json-key">"jsonrpc"</span>: <span class="json-string">"2.0"</span>,
956
- <span class="json-key">"id"</span>: <span class="json-number">1</span>,
957
- <span class="json-key">"method"</span>: <span class="json-string">"tools/call"</span>,
958
- <span class="json-key">"params"</span>: {
959
- <span class="json-key">"name"</span>: <span class="json-string">"get_company_filings"</span>,
960
- <span class="json-key">"arguments"</span>: {
961
- <span class="json-key">"cik"</span>: <span class="json-string">"0000789019"</span>,
962
- <span class="json-key">"form_types"</span>: [<span class="json-string">"10-K"</span>, <span class="json-string">"10-Q"</span>]
963
- }
964
- }
965
- }</pre>
966
- </div>
967
- <div class="param-group">
968
- <label>CIK Code *</label>
969
- <input type="text" id="tool4-cik" placeholder="e.g., 0000789019">
970
- </div>
971
- <div class="param-group">
972
- <label>Form Types (Optional)</label>
973
- <select id="tool4-form_types" multiple style="height: 80px;">
974
- <option value="10-K">10-K (Annual Report)</option>
975
- <option value="10-Q">10-Q (Quarterly Report)</option>
976
- <option value="20-F">20-F (Foreign Annual)</option>
977
- <option value="8-K">8-K (Current Report)</option>
978
- </select>
979
- <div class="param-hint">Leave empty for all types, or select specific forms (Ctrl+Click for multiple)</div>
980
- </div>
981
- <button class="test-btn" onclick="testTool('get_company_filings', 'tool4')">Run Test</button>
982
- <div class="result-box" id="result-tool4"></div>
983
- </div>
984
- </div>
985
-
986
- <!-- Tool 5: get_latest_financial_data -->
987
- <div class="tool">
988
- <div class="tool-header" onclick="toggleTool('tool5')">
989
- <div class="tool-title">
990
- <span class="toggle-icon" id="icon-tool5">▶</span>
991
- <div>
992
- <h3>get_latest_financial_data</h3>
993
- <div class="desc">Get the most recent financial data available</div>
994
- </div>
995
- </div>
996
- </div>
997
- <div class="tool-body" id="tool5">
998
- <div class="example-box">
999
- <div class="example-title">Parameter Format Example</div>
1000
- <div class="example-content">
1001
- <div class="example-item"><span class="example-label">Microsoft:</span> "0000789019"</div>
1002
- <div class="example-item"><span class="example-label">Apple:</span> "0000320193"</div>
1003
- <div class="example-item"><span class="example-label">NVIDIA:</span> "0001045810"</div>
1004
- </div>
1005
- </div>
1006
- <div class="api-example-box">
1007
- <div class="api-title">API Request Example</div>
1008
- <pre>{
1009
- <span class="json-key">"jsonrpc"</span>: <span class="json-string">"2.0"</span>,
1010
- <span class="json-key">"id"</span>: <span class="json-number">1</span>,
1011
- <span class="json-key">"method"</span>: <span class="json-string">"tools/call"</span>,
1012
- <span class="json-key">"params"</span>: {
1013
- <span class="json-key">"name"</span>: <span class="json-string">"get_latest_financial_data"</span>,
1014
- <span class="json-key">"arguments"</span>: {
1015
- <span class="json-key">"cik"</span>: <span class="json-string">"0000789019"</span>
1016
- }
1017
- }
1018
- }</pre>
1019
- </div>
1020
- <div class="param-group">
1021
- <label>CIK Code *</label>
1022
- <input type="text" id="tool5-cik" placeholder="e.g., 0000789019">
1023
- </div>
1024
- <button class="test-btn" onclick="testTool('get_latest_financial_data', 'tool5')">Run Test</button>
1025
- <div class="result-box" id="result-tool5"></div>
1026
- </div>
1027
- </div>
1028
-
1029
- <!-- Tool 6: get_financial_data -->
1030
- <div class="tool">
1031
- <div class="tool-header" onclick="toggleTool('tool6')">
1032
- <div class="tool-title">
1033
- <span class="toggle-icon" id="icon-tool6">▶</span>
1034
- <div>
1035
- <h3>get_financial_data</h3>
1036
- <div class="desc">Get financial data for a specific period (annual or quarterly)</div>
1037
- </div>
1038
- </div>
1039
- </div>
1040
- <div class="tool-body" id="tool6">
1041
- <div class="example-box">
1042
- <div class="example-title">Parameter Format Example</div>
1043
- <div class="example-content">
1044
- <div class="example-item"><span class="example-label">Annual Data:</span> CIK="0000789019", Period="2024"</div>
1045
- <div class="example-item"><span class="example-label">Quarterly Data:</span> CIK="0000789019", Period="2024Q3"</div>
1046
- <div class="example-item"><span class="example-label">Format:</span> YYYY for annual, YYYYQX for quarterly</div>
1047
- </div>
1048
- </div>
1049
- <div class="api-example-box">
1050
- <div class="api-title">API Request Example</div>
1051
- <pre>{
1052
- <span class="json-key">"jsonrpc"</span>: <span class="json-string">"2.0"</span>,
1053
- <span class="json-key">"id"</span>: <span class="json-number">1</span>,
1054
- <span class="json-key">"method"</span>: <span class="json-string">"tools/call"</span>,
1055
- <span class="json-key">"params"</span>: {
1056
- <span class="json-key">"name"</span>: <span class="json-string">"get_financial_data"</span>,
1057
- <span class="json-key">"arguments"</span>: {
1058
- <span class="json-key">"cik"</span>: <span class="json-string">"0000789019"</span>,
1059
- <span class="json-key">"period"</span>: <span class="json-string">"2024"</span>
1060
- }
1061
- }
1062
- }</pre>
1063
- </div>
1064
- <div class="param-group">
1065
- <label>CIK Code *</label>
1066
- <input type="text" id="tool6-cik" placeholder="e.g., 0000789019">
1067
- </div>
1068
- <div class="param-group">
1069
- <label>Period *</label>
1070
- <input type="text" id="tool6-period" placeholder="e.g., 2024 or 2024Q3">
1071
- <div class="param-hint">Format: YYYY for annual (e.g., 2024) or YYYYQX for quarterly (e.g., 2024Q3)</div>
1072
- </div>
1073
- <button class="test-btn" onclick="testTool('get_financial_data', 'tool6')">Run Test</button>
1074
- <div class="result-box" id="result-tool6"></div>
1075
- </div>
1076
- </div>
1077
-
1078
- <!-- Tool 7: extract_financial_metrics -->
1079
- <div class="tool">
1080
- <div class="tool-header" onclick="toggleTool('tool7')">
1081
- <div class="tool-title">
1082
- <span class="toggle-icon" id="icon-tool7">▶</span>
1083
- <div>
1084
- <h3>extract_financial_metrics</h3>
1085
- <div class="desc">Extract comprehensive financial metrics for multiple years</div>
1086
- </div>
1087
- </div>
1088
- </div>
1089
- <div class="tool-body" id="tool7">
1090
- <div class="example-box">
1091
- <div class="example-title">Parameter Format Example</div>
1092
- <div class="example-content">
1093
- <div class="example-item"><span class="example-label">3 Years:</span> CIK="0000789019", Years=3</div>
1094
- <div class="example-item"><span class="example-label">5 Years:</span> CIK="0000320193", Years=5</div>
1095
- <div class="example-item"><span class="example-label">Note:</span> Returns annual + quarterly data (if available)</div>
1096
- </div>
1097
- </div>
1098
- <div class="api-example-box">
1099
- <div class="api-title">API Request Example</div>
1100
- <pre>{
1101
- <span class="json-key">"jsonrpc"</span>: <span class="json-string">"2.0"</span>,
1102
- <span class="json-key">"id"</span>: <span class="json-number">1</span>,
1103
- <span class="json-key">"method"</span>: <span class="json-string">"tools/call"</span>,
1104
- <span class="json-key">"params"</span>: {
1105
- <span class="json-key">"name"</span>: <span class="json-string">"extract_financial_metrics"</span>,
1106
- <span class="json-key">"arguments"</span>: {
1107
- <span class="json-key">"cik"</span>: <span class="json-string">"0000789019"</span>,
1108
- <span class="json-key">"years"</span>: <span class="json-number">3</span>
1109
- }
1110
- }
1111
- }</pre>
1112
- </div>
1113
- <div class="param-group">
1114
- <label>CIK Code *</label>
1115
- <input type="text" id="tool7-cik" placeholder="e.g., 0000789019">
1116
- </div>
1117
- <div class="param-group">
1118
- <label>Number of Years</label>
1119
- <select id="tool7-years">
1120
- <option value="1">1 year</option>
1121
- <option value="2">2 years</option>
1122
- <option value="3" selected>3 years</option>
1123
- <option value="5">5 years</option>
1124
- <option value="10">10 years</option>
1125
- </select>
1126
- <div class="param-hint">Number of recent years to extract (1-10)</div>
1127
- </div>
1128
- <button class="test-btn" onclick="testTool('extract_financial_metrics', 'tool7')">Run Test</button>
1129
- <div class="result-box" id="result-tool7"></div>
1130
- </div>
1131
- </div>
1132
- </div>
1133
-
1134
- <h2>Documentation</h2>
1135
- <p>Visit <code>/tools</code> to see all available tools in JSON format.</p>
1136
-
1137
- <hr style="margin: 30px 0; border: none; border-top: 1px solid #e0e0e0;">
1138
- <p style="text-align: center; color: #666; font-size: 14px;">
1139
- Powered by Model Context Protocol | SEC EDGAR Data | v2.1.0
1140
- </p>
1141
- </div>
1142
-
1143
- <script>
1144
- function toggleTool(toolId) {
1145
- const body = document.getElementById(toolId);
1146
- const icon = document.getElementById('icon-' + toolId);
1147
-
1148
- if (body.classList.contains('show')) {
1149
- body.classList.remove('show');
1150
- icon.classList.remove('expanded');
1151
- } else {
1152
- body.classList.add('show');
1153
- icon.classList.add('expanded');
1154
- }
1155
- }
1156
-
1157
- async function testTool(toolName, toolId) {
1158
- const btn = event.target;
1159
- const resultBox = document.getElementById('result-' + toolId);
1160
-
1161
- // Get parameters based on tool
1162
- let args = {};
1163
-
1164
- if (toolName === 'search_company') {
1165
- const companyName = document.getElementById(toolId + '-company_name').value;
1166
- if (!companyName) {
1167
- alert('Please enter a company name');
1168
- return;
1169
- }
1170
- args = { company_name: companyName };
1171
- }
1172
- else if (toolName === 'advanced_search_company') {
1173
- const companyInput = document.getElementById(toolId + '-company_input').value;
1174
- if (!companyInput) {
1175
- alert('Please enter a company name, ticker, or CIK');
1176
- return;
1177
- }
1178
- args = { company_input: companyInput };
1179
- }
1180
- else if (toolName === 'get_company_info') {
1181
- const cik = document.getElementById(toolId + '-cik').value;
1182
- if (!cik) {
1183
- alert('Please enter a CIK code');
1184
- return;
1185
- }
1186
- args = { cik: cik };
1187
- }
1188
- else if (toolName === 'get_company_filings') {
1189
- const cik = document.getElementById(toolId + '-cik').value;
1190
- if (!cik) {
1191
- alert('Please enter a CIK code');
1192
- return;
1193
- }
1194
- const formTypesSelect = document.getElementById(toolId + '-form_types');
1195
- const selectedForms = Array.from(formTypesSelect.selectedOptions).map(opt => opt.value);
1196
- args = { cik: cik };
1197
- if (selectedForms.length > 0) {
1198
- args.form_types = selectedForms;
1199
- }
1200
- }
1201
- else if (toolName === 'get_latest_financial_data') {
1202
- const cik = document.getElementById(toolId + '-cik').value;
1203
- if (!cik) {
1204
- alert('Please enter a CIK code');
1205
- return;
1206
- }
1207
- args = { cik: cik };
1208
- }
1209
- else if (toolName === 'get_financial_data') {
1210
- const cik = document.getElementById(toolId + '-cik').value;
1211
- const period = document.getElementById(toolId + '-period').value;
1212
- if (!cik || !period) {
1213
- alert('Please enter CIK and period');
1214
- return;
1215
- }
1216
- args = { cik: cik, period: period };
1217
- }
1218
- else if (toolName === 'extract_financial_metrics') {
1219
- const cik = document.getElementById(toolId + '-cik').value;
1220
- const years = parseInt(document.getElementById(toolId + '-years').value);
1221
- if (!cik) {
1222
- alert('Please enter a CIK code');
1223
- return;
1224
- }
1225
- args = { cik: cik, years: years };
1226
- }
1227
-
1228
- // Show loading state
1229
- btn.disabled = true;
1230
- btn.innerHTML = 'Running<span class="loading"></span>';
1231
- resultBox.className = 'result-box show';
1232
- resultBox.textContent = 'Loading...';
1233
-
1234
- try {
1235
- const response = await fetch('/message', {
1236
- method: 'POST',
1237
- headers: {
1238
- 'Content-Type': 'application/json',
1239
- },
1240
- body: JSON.stringify({
1241
- jsonrpc: '2.0',
1242
- id: Date.now(),
1243
- method: 'tools/call',
1244
- params: {
1245
- name: toolName,
1246
- arguments: args
1247
- }
1248
- })
1249
- });
1250
-
1251
- const data = await response.json();
1252
-
1253
- if (data.result && data.result.content && data.result.content[0]) {
1254
- const content = data.result.content[0].text;
1255
- const parsed = JSON.parse(content);
1256
- resultBox.className = 'result-box show success';
1257
- resultBox.textContent = JSON.stringify(parsed, null, 2);
1258
- } else if (data.error) {
1259
- resultBox.className = 'result-box show error';
1260
- resultBox.textContent = 'Error: ' + JSON.stringify(data.error, null, 2);
1261
- } else {
1262
- resultBox.className = 'result-box show error';
1263
- resultBox.textContent = 'Unexpected response: ' + JSON.stringify(data, null, 2);
1264
- }
1265
- } catch (error) {
1266
- resultBox.className = 'result-box show error';
1267
- resultBox.textContent = 'Error: ' + error.message;
1268
- } finally {
1269
- btn.disabled = false;
1270
- btn.innerHTML = 'Run Test';
1271
- }
1272
- }
1273
- </script>
1274
- </body>
1275
- </html>
1276
- """
1277
 
1278
 
1279
  @app.get("/tools")
 
6
  """
7
 
8
  from fastapi import FastAPI, Request, HTTPException
9
+ from fastapi.responses import StreamingResponse, JSONResponse, HTMLResponse, FileResponse
10
+ from fastapi.staticfiles import StaticFiles
11
  from fastapi.middleware.cors import CORSMiddleware
12
  from pydantic import BaseModel
13
  from typing import Dict, Any, List, Optional
 
19
  import time
20
  import sys
21
  import signal
22
+ import os
23
+ from pathlib import Path
24
  from contextlib import contextmanager
25
 
26
  # Initialize FastAPI app
 
508
  @app.get("/", response_class=HTMLResponse)
509
  async def root():
510
  """Interactive landing page with tool testing functionality"""
511
+ # Get the path to the templates directory
512
+ current_dir = Path(__file__).parent
513
+ template_path = current_dir / "templates" / "index.html"
514
+
515
+ # Read and return the HTML file
516
+ try:
517
+ with open(template_path, "r", encoding="utf-8") as f:
518
+ html_content = f.read()
519
+ return HTMLResponse(content=html_content)
520
+ except FileNotFoundError:
521
+ return HTMLResponse(
522
+ content="<h1>Error: Template file not found</h1><p>Please ensure templates/index.html exists.</p>",
523
+ status_code=500
524
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
525
 
526
 
527
  @app.get("/tools")
templates/index.html ADDED
@@ -0,0 +1,767 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>SEC Financial Report MCP Server</title>
7
+ <style>
8
+ body {
9
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
10
+ max-width: 1000px;
11
+ margin: 30px auto;
12
+ padding: 20px;
13
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
14
+ min-height: 100vh;
15
+ }
16
+ .container {
17
+ background: white;
18
+ border-radius: 12px;
19
+ padding: 40px;
20
+ box-shadow: 0 10px 30px rgba(0,0,0,0.2);
21
+ }
22
+ h1 {
23
+ color: #667eea;
24
+ margin-top: 0;
25
+ }
26
+ .badge {
27
+ display: inline-block;
28
+ background: #10b981;
29
+ color: white;
30
+ padding: 4px 12px;
31
+ border-radius: 12px;
32
+ font-size: 12px;
33
+ font-weight: bold;
34
+ }
35
+ .config-box {
36
+ background: #f5f5f5;
37
+ padding: 20px;
38
+ border-radius: 8px;
39
+ margin: 20px 0;
40
+ font-family: 'Monaco', 'Courier New', monospace;
41
+ font-size: 13px;
42
+ overflow-x: auto;
43
+ }
44
+ .tools {
45
+ margin: 30px 0;
46
+ }
47
+ .tool {
48
+ background: #f9f9f9;
49
+ margin: 10px 0;
50
+ border-radius: 8px;
51
+ border: 2px solid #e0e0e0;
52
+ overflow: hidden;
53
+ transition: all 0.3s;
54
+ }
55
+ .tool:hover {
56
+ border-color: #667eea;
57
+ }
58
+ .tool-header {
59
+ padding: 15px 20px;
60
+ cursor: pointer;
61
+ display: flex;
62
+ justify-content: space-between;
63
+ align-items: center;
64
+ background: linear-gradient(to right, #f9f9f9, #ffffff);
65
+ }
66
+ .tool-header:hover {
67
+ background: linear-gradient(to right, #f0f0f0, #f9f9f9);
68
+ }
69
+ .tool-title {
70
+ display: flex;
71
+ align-items: center;
72
+ gap: 10px;
73
+ }
74
+ .tool-title h3 {
75
+ margin: 0;
76
+ color: #333;
77
+ font-size: 16px;
78
+ }
79
+ .tool-title .desc {
80
+ color: #666;
81
+ font-size: 13px;
82
+ }
83
+ .toggle-icon {
84
+ font-size: 20px;
85
+ color: #667eea;
86
+ transition: transform 0.3s;
87
+ }
88
+ .toggle-icon.expanded {
89
+ transform: rotate(90deg);
90
+ }
91
+ .tool-body {
92
+ display: none;
93
+ padding: 20px;
94
+ background: white;
95
+ border-top: 1px solid #e0e0e0;
96
+ }
97
+ .tool-body.show {
98
+ display: block;
99
+ }
100
+ .param-group {
101
+ margin-bottom: 15px;
102
+ }
103
+ .param-group label {
104
+ display: block;
105
+ margin-bottom: 5px;
106
+ font-weight: 500;
107
+ color: #333;
108
+ font-size: 14px;
109
+ }
110
+ .param-group input, .param-group select {
111
+ width: 100%;
112
+ padding: 10px;
113
+ border: 2px solid #e0e0e0;
114
+ border-radius: 6px;
115
+ font-size: 14px;
116
+ box-sizing: border-box;
117
+ }
118
+ .param-group input:focus, .param-group select:focus {
119
+ outline: none;
120
+ border-color: #667eea;
121
+ }
122
+ .param-hint {
123
+ font-size: 12px;
124
+ color: #999;
125
+ margin-top: 3px;
126
+ }
127
+ .example-box {
128
+ background: #f8f9fa;
129
+ border: 1px solid #dee2e6;
130
+ border-radius: 4px;
131
+ padding: 10px;
132
+ margin: 10px 0;
133
+ font-size: 12px;
134
+ }
135
+ .example-box .example-title {
136
+ font-weight: 600;
137
+ color: #495057;
138
+ margin-bottom: 5px;
139
+ display: flex;
140
+ align-items: center;
141
+ gap: 5px;
142
+ }
143
+ .example-box .example-title::before {
144
+ content: "💡";
145
+ font-size: 14px;
146
+ }
147
+ .example-box .example-content {
148
+ font-family: 'Monaco', 'Courier New', monospace;
149
+ color: #6c757d;
150
+ background: white;
151
+ padding: 8px;
152
+ border-radius: 3px;
153
+ border-left: 3px solid #667eea;
154
+ }
155
+ .example-item {
156
+ margin: 3px 0;
157
+ }
158
+ .example-label {
159
+ color: #667eea;
160
+ font-weight: 500;
161
+ }
162
+ .api-example-box {
163
+ background: #1e1e1e;
164
+ border-radius: 4px;
165
+ padding: 12px;
166
+ margin: 10px 0;
167
+ font-family: 'Monaco', 'Courier New', monospace;
168
+ font-size: 11px;
169
+ overflow-x: auto;
170
+ }
171
+ .api-example-box .api-title {
172
+ color: #9cdcfe;
173
+ font-weight: 600;
174
+ margin-bottom: 8px;
175
+ display: flex;
176
+ align-items: center;
177
+ gap: 5px;
178
+ }
179
+ .api-example-box .api-title::before {
180
+ content: "📡";
181
+ font-size: 14px;
182
+ }
183
+ .api-example-box pre {
184
+ margin: 0;
185
+ color: #d4d4d4;
186
+ white-space: pre-wrap;
187
+ word-break: break-word;
188
+ }
189
+ .api-example-box .json-key {
190
+ color: #9cdcfe;
191
+ }
192
+ .api-example-box .json-string {
193
+ color: #ce9178;
194
+ }
195
+ .api-example-box .json-number {
196
+ color: #b5cea8;
197
+ }
198
+ .test-btn {
199
+ background: linear-gradient(135deg, #667eea, #764ba2);
200
+ color: white;
201
+ border: none;
202
+ padding: 12px 30px;
203
+ border-radius: 6px;
204
+ cursor: pointer;
205
+ font-size: 14px;
206
+ font-weight: 600;
207
+ transition: transform 0.2s, box-shadow 0.2s;
208
+ margin-top: 10px;
209
+ }
210
+ .test-btn:hover {
211
+ transform: translateY(-2px);
212
+ box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
213
+ }
214
+ .test-btn:active {
215
+ transform: translateY(0);
216
+ }
217
+ .test-btn:disabled {
218
+ background: #ccc;
219
+ cursor: not-allowed;
220
+ transform: none;
221
+ }
222
+ .result-box {
223
+ margin-top: 15px;
224
+ padding: 15px;
225
+ background: #f5f5f5;
226
+ border-radius: 6px;
227
+ border-left: 4px solid #667eea;
228
+ font-family: 'Monaco', 'Courier New', monospace;
229
+ font-size: 12px;
230
+ max-height: 400px;
231
+ overflow-y: auto;
232
+ white-space: pre-wrap;
233
+ word-break: break-word;
234
+ display: none;
235
+ }
236
+ .result-box.show {
237
+ display: block;
238
+ }
239
+ .result-box.error {
240
+ border-left-color: #ef4444;
241
+ background: #fee;
242
+ }
243
+ .result-box.success {
244
+ border-left-color: #10b981;
245
+ background: #f0fdf4;
246
+ }
247
+ .loading {
248
+ display: inline-block;
249
+ width: 14px;
250
+ height: 14px;
251
+ border: 2px solid #ffffff;
252
+ border-radius: 50%;
253
+ border-top-color: transparent;
254
+ animation: spin 1s linear infinite;
255
+ margin-left: 8px;
256
+ }
257
+ @keyframes spin {
258
+ to { transform: rotate(360deg); }
259
+ }
260
+ code {
261
+ background: #e0e0e0;
262
+ padding: 2px 6px;
263
+ border-radius: 3px;
264
+ font-size: 12px;
265
+ }
266
+ </style>
267
+ </head>
268
+ <body>
269
+ <div class="container">
270
+ <h1>SEC Financial Report MCP Server API</h1>
271
+ <p><span class="badge">MCP READY</span> Model Context Protocol Server for SEC EDGAR Financial Data</p>
272
+
273
+ <h2>Connect to this MCP Server</h2>
274
+ <p>Add the following configuration to your MCP client (e.g., Claude Desktop):</p>
275
+
276
+ <div class="config-box">
277
+ {
278
+ "mcpServers": {
279
+ "sec-financial-data": {
280
+ "url": "https://jc321-easyreportsmcpserver.hf.space/sse"
281
+ }
282
+ }
283
+ }
284
+ </div>
285
+
286
+ <p><strong>Use the URL above to connect to this MCP Server.</strong></p>
287
+
288
+ <h2>Available Tools (7) - Interactive Testing</h2>
289
+ <p style="color: #666; font-size: 14px;">Click on any tool below to expand and test it directly!</p>
290
+
291
+ <div class="tools">
292
+ <!-- Tool 1: search_company -->
293
+ <div class="tool">
294
+ <div class="tool-header" onclick="toggleTool('tool1')">
295
+ <div class="tool-title">
296
+ <span class="toggle-icon" id="icon-tool1">▶</span>
297
+ <div>
298
+ <h3>search_company</h3>
299
+ <div class="desc">Search for a company by name in SEC EDGAR database</div>
300
+ </div>
301
+ </div>
302
+ </div>
303
+ <div class="tool-body" id="tool1">
304
+ <div class="example-box">
305
+ <div class="example-title">Parameter Format Example</div>
306
+ <div class="example-content">
307
+ <div class="example-item"><span class="example-label">Input:</span> "Microsoft"</div>
308
+ <div class="example-item"><span class="example-label">Input:</span> "Apple Inc"</div>
309
+ <div class="example-item"><span class="example-label">Input:</span> "Tesla"</div>
310
+ </div>
311
+ </div>
312
+ <div class="api-example-box">
313
+ <div class="api-title">API Request Example</div>
314
+ <pre>{
315
+ <span class="json-key">"jsonrpc"</span>: <span class="json-string">"2.0"</span>,
316
+ <span class="json-key">"id"</span>: <span class="json-number">1</span>,
317
+ <span class="json-key">"method"</span>: <span class="json-string">"tools/call"</span>,
318
+ <span class="json-key">"params"</span>: {
319
+ <span class="json-key">"name"</span>: <span class="json-string">"search_company"</span>,
320
+ <span class="json-key">"arguments"</span>: {
321
+ <span class="json-key">"company_name"</span>: <span class="json-string">"Microsoft"</span>
322
+ }
323
+ }
324
+ }</pre>
325
+ </div>
326
+ <div class="param-group">
327
+ <label>Company Name *</label>
328
+ <input type="text" id="tool1-company_name" placeholder="e.g., Microsoft, Apple, Tesla">
329
+ <div class="param-hint">Enter the full or partial company name</div>
330
+ </div>
331
+ <button class="test-btn" onclick="testTool('search_company', 'tool1')">Run Test</button>
332
+ <div class="result-box" id="result-tool1"></div>
333
+ </div>
334
+ </div>
335
+
336
+ <!-- Tool 2: advanced_search_company -->
337
+ <div class="tool">
338
+ <div class="tool-header" onclick="toggleTool('tool2')">
339
+ <div class="tool-title">
340
+ <span class="toggle-icon" id="icon-tool2">▶</span>
341
+ <div>
342
+ <h3>advanced_search_company</h3>
343
+ <div class="desc">Advanced search supporting name, ticker, or CIK</div>
344
+ </div>
345
+ </div>
346
+ </div>
347
+ <div class="tool-body" id="tool2">
348
+ <div class="example-box">
349
+ <div class="example-title">Parameter Format Example</div>
350
+ <div class="example-content">
351
+ <div class="example-item"><span class="example-label">By Ticker:</span> "MSFT"</div>
352
+ <div class="example-item"><span class="example-label">By CIK:</span> "0000789019"</div>
353
+ <div class="example-item"><span class="example-label">By Name:</span> "Microsoft Corporation"</div>
354
+ </div>
355
+ </div>
356
+ <div class="api-example-box">
357
+ <div class="api-title">API Request Example</div>
358
+ <pre>{
359
+ <span class="json-key">"jsonrpc"</span>: <span class="json-string">"2.0"</span>,
360
+ <span class="json-key">"id"</span>: <span class="json-number">1</span>,
361
+ <span class="json-key">"method"</span>: <span class="json-string">"tools/call"</span>,
362
+ <span class="json-key">"params"</span>: {
363
+ <span class="json-key">"name"</span>: <span class="json-string">"advanced_search_company"</span>,
364
+ <span class="json-key">"arguments"</span>: {
365
+ <span class="json-key">"company_input"</span>: <span class="json-string">"MSFT"</span>
366
+ }
367
+ }
368
+ }</pre>
369
+ </div>
370
+ <div class="param-group">
371
+ <label>Company Name / Ticker / CIK *</label>
372
+ <input type="text" id="tool2-company_input" placeholder="e.g., MSFT, 0000789019, Microsoft">
373
+ <div class="param-hint">Enter company name, ticker symbol, or CIK code</div>
374
+ </div>
375
+ <button class="test-btn" onclick="testTool('advanced_search_company', 'tool2')">Run Test</button>
376
+ <div class="result-box" id="result-tool2"></div>
377
+ </div>
378
+ </div>
379
+
380
+ <!-- Tool 3: get_company_info -->
381
+ <div class="tool">
382
+ <div class="tool-header" onclick="toggleTool('tool3')">
383
+ <div class="tool-title">
384
+ <span class="toggle-icon" id="icon-tool3">▶</span>
385
+ <div>
386
+ <h3>get_company_info</h3>
387
+ <div class="desc">Get detailed company information by CIK code</div>
388
+ </div>
389
+ </div>
390
+ </div>
391
+ <div class="tool-body" id="tool3">
392
+ <div class="example-box">
393
+ <div class="example-title">Parameter Format Example</div>
394
+ <div class="example-content">
395
+ <div class="example-item"><span class="example-label">Microsoft:</span> "0000789019"</div>
396
+ <div class="example-item"><span class="example-label">Apple:</span> "0000320193"</div>
397
+ <div class="example-item"><span class="example-label">Tesla:</span> "0001318605"</div>
398
+ </div>
399
+ </div>
400
+ <div class="api-example-box">
401
+ <div class="api-title">API Request Example</div>
402
+ <pre>{
403
+ <span class="json-key">"jsonrpc"</span>: <span class="json-string">"2.0"</span>,
404
+ <span class="json-key">"id"</span>: <span class="json-number">1</span>,
405
+ <span class="json-key">"method"</span>: <span class="json-string">"tools/call"</span>,
406
+ <span class="json-key">"params"</span>: {
407
+ <span class="json-key">"name"</span>: <span class="json-string">"get_company_info"</span>,
408
+ <span class="json-key">"arguments"</span>: {
409
+ <span class="json-key">"cik"</span>: <span class="json-string">"0000789019"</span>
410
+ }
411
+ }
412
+ }</pre>
413
+ </div>
414
+ <div class="param-group">
415
+ <label>CIK Code *</label>
416
+ <input type="text" id="tool3-cik" placeholder="e.g., 0000789019">
417
+ <div class="param-hint">10-digit CIK code (use search_company to find it)</div>
418
+ </div>
419
+ <button class="test-btn" onclick="testTool('get_company_info', 'tool3')">Run Test</button>
420
+ <div class="result-box" id="result-tool3"></div>
421
+ </div>
422
+ </div>
423
+
424
+ <!-- Tool 4: get_company_filings -->
425
+ <div class="tool">
426
+ <div class="tool-header" onclick="toggleTool('tool4')">
427
+ <div class="tool-title">
428
+ <span class="toggle-icon" id="icon-tool4">▶</span>
429
+ <div>
430
+ <h3>get_company_filings</h3>
431
+ <div class="desc">Get list of SEC filings (10-K, 10-Q, 20-F, etc.)</div>
432
+ </div>
433
+ </div>
434
+ </div>
435
+ <div class="tool-body" id="tool4">
436
+ <div class="example-box">
437
+ <div class="example-title">Parameter Format Example</div>
438
+ <div class="example-content">
439
+ <div class="example-item"><span class="example-label">CIK:</span> "0000789019" (Microsoft)</div>
440
+ <div class="example-item"><span class="example-label">Form Types:</span> Select "10-K" and "10-Q" from dropdown</div>
441
+ <div class="example-item"><span class="example-label">Or:</span> Leave empty to get all filing types</div>
442
+ </div>
443
+ </div>
444
+ <div class="api-example-box">
445
+ <div class="api-title">API Request Example</div>
446
+ <pre>{
447
+ <span class="json-key">"jsonrpc"</span>: <span class="json-string">"2.0"</span>,
448
+ <span class="json-key">"id"</span>: <span class="json-number">1</span>,
449
+ <span class="json-key">"method"</span>: <span class="json-string">"tools/call"</span>,
450
+ <span class="json-key">"params"</span>: {
451
+ <span class="json-key">"name"</span>: <span class="json-string">"get_company_filings"</span>,
452
+ <span class="json-key">"arguments"</span>: {
453
+ <span class="json-key">"cik"</span>: <span class="json-string">"0000789019"</span>,
454
+ <span class="json-key">"form_types"</span>: [<span class="json-string">"10-K"</span>, <span class="json-string">"10-Q"</span>]
455
+ }
456
+ }
457
+ }</pre>
458
+ </div>
459
+ <div class="param-group">
460
+ <label>CIK Code *</label>
461
+ <input type="text" id="tool4-cik" placeholder="e.g., 0000789019">
462
+ </div>
463
+ <div class="param-group">
464
+ <label>Form Types (Optional)</label>
465
+ <select id="tool4-form_types" multiple style="height: 80px;">
466
+ <option value="10-K">10-K (Annual Report)</option>
467
+ <option value="10-Q">10-Q (Quarterly Report)</option>
468
+ <option value="20-F">20-F (Foreign Annual)</option>
469
+ <option value="8-K">8-K (Current Report)</option>
470
+ </select>
471
+ <div class="param-hint">Leave empty for all types, or select specific forms (Ctrl+Click for multiple)</div>
472
+ </div>
473
+ <button class="test-btn" onclick="testTool('get_company_filings', 'tool4')">Run Test</button>
474
+ <div class="result-box" id="result-tool4"></div>
475
+ </div>
476
+ </div>
477
+
478
+ <!-- Tool 5: get_latest_financial_data -->
479
+ <div class="tool">
480
+ <div class="tool-header" onclick="toggleTool('tool5')">
481
+ <div class="tool-title">
482
+ <span class="toggle-icon" id="icon-tool5">▶</span>
483
+ <div>
484
+ <h3>get_latest_financial_data</h3>
485
+ <div class="desc">Get the most recent financial data available</div>
486
+ </div>
487
+ </div>
488
+ </div>
489
+ <div class="tool-body" id="tool5">
490
+ <div class="example-box">
491
+ <div class="example-title">Parameter Format Example</div>
492
+ <div class="example-content">
493
+ <div class="example-item"><span class="example-label">Microsoft:</span> "0000789019"</div>
494
+ <div class="example-item"><span class="example-label">Apple:</span> "0000320193"</div>
495
+ <div class="example-item"><span class="example-label">NVIDIA:</span> "0001045810"</div>
496
+ </div>
497
+ </div>
498
+ <div class="api-example-box">
499
+ <div class="api-title">API Request Example</div>
500
+ <pre>{
501
+ <span class="json-key">"jsonrpc"</span>: <span class="json-string">"2.0"</span>,
502
+ <span class="json-key">"id"</span>: <span class="json-number">1</span>,
503
+ <span class="json-key">"method"</span>: <span class="json-string">"tools/call"</span>,
504
+ <span class="json-key">"params"</span>: {
505
+ <span class="json-key">"name"</span>: <span class="json-string">"get_latest_financial_data"</span>,
506
+ <span class="json-key">"arguments"</span>: {
507
+ <span class="json-key">"cik"</span>: <span class="json-string">"0000789019"</span>
508
+ }
509
+ }
510
+ }</pre>
511
+ </div>
512
+ <div class="param-group">
513
+ <label>CIK Code *</label>
514
+ <input type="text" id="tool5-cik" placeholder="e.g., 0000789019">
515
+ </div>
516
+ <button class="test-btn" onclick="testTool('get_latest_financial_data', 'tool5')">Run Test</button>
517
+ <div class="result-box" id="result-tool5"></div>
518
+ </div>
519
+ </div>
520
+
521
+ <!-- Tool 6: get_financial_data -->
522
+ <div class="tool">
523
+ <div class="tool-header" onclick="toggleTool('tool6')">
524
+ <div class="tool-title">
525
+ <span class="toggle-icon" id="icon-tool6">▶</span>
526
+ <div>
527
+ <h3>get_financial_data</h3>
528
+ <div class="desc">Get financial data for a specific period (annual or quarterly)</div>
529
+ </div>
530
+ </div>
531
+ </div>
532
+ <div class="tool-body" id="tool6">
533
+ <div class="example-box">
534
+ <div class="example-title">Parameter Format Example</div>
535
+ <div class="example-content">
536
+ <div class="example-item"><span class="example-label">Annual Data:</span> CIK="0000789019", Period="2024"</div>
537
+ <div class="example-item"><span class="example-label">Quarterly Data:</span> CIK="0000789019", Period="2024Q3"</div>
538
+ <div class="example-item"><span class="example-label">Format:</span> YYYY for annual, YYYYQX for quarterly</div>
539
+ </div>
540
+ </div>
541
+ <div class="api-example-box">
542
+ <div class="api-title">API Request Example</div>
543
+ <pre>{
544
+ <span class="json-key">"jsonrpc"</span>: <span class="json-string">"2.0"</span>,
545
+ <span class="json-key">"id"</span>: <span class="json-number">1</span>,
546
+ <span class="json-key">"method"</span>: <span class="json-string">"tools/call"</span>,
547
+ <span class="json-key">"params"</span>: {
548
+ <span class="json-key">"name"</span>: <span class="json-string">"get_financial_data"</span>,
549
+ <span class="json-key">"arguments"</span>: {
550
+ <span class="json-key">"cik"</span>: <span class="json-string">"0000789019"</span>,
551
+ <span class="json-key">"period"</span>: <span class="json-string">"2024"</span>
552
+ }
553
+ }
554
+ }</pre>
555
+ </div>
556
+ <div class="param-group">
557
+ <label>CIK Code *</label>
558
+ <input type="text" id="tool6-cik" placeholder="e.g., 0000789019">
559
+ </div>
560
+ <div class="param-group">
561
+ <label>Period *</label>
562
+ <input type="text" id="tool6-period" placeholder="e.g., 2024 or 2024Q3">
563
+ <div class="param-hint">Format: YYYY for annual (e.g., 2024) or YYYYQX for quarterly (e.g., 2024Q3)</div>
564
+ </div>
565
+ <button class="test-btn" onclick="testTool('get_financial_data', 'tool6')">Run Test</button>
566
+ <div class="result-box" id="result-tool6"></div>
567
+ </div>
568
+ </div>
569
+
570
+ <!-- Tool 7: extract_financial_metrics -->
571
+ <div class="tool">
572
+ <div class="tool-header" onclick="toggleTool('tool7')">
573
+ <div class="tool-title">
574
+ <span class="toggle-icon" id="icon-tool7">▶</span>
575
+ <div>
576
+ <h3>extract_financial_metrics</h3>
577
+ <div class="desc">Extract comprehensive financial metrics for multiple years</div>
578
+ </div>
579
+ </div>
580
+ </div>
581
+ <div class="tool-body" id="tool7">
582
+ <div class="example-box">
583
+ <div class="example-title">Parameter Format Example</div>
584
+ <div class="example-content">
585
+ <div class="example-item"><span class="example-label">3 Years:</span> CIK="0000789019", Years=3</div>
586
+ <div class="example-item"><span class="example-label">5 Years:</span> CIK="0000320193", Years=5</div>
587
+ <div class="example-item"><span class="example-label">Note:</span> Returns annual + quarterly data (if available)</div>
588
+ </div>
589
+ </div>
590
+ <div class="api-example-box">
591
+ <div class="api-title">API Request Example</div>
592
+ <pre>{
593
+ <span class="json-key">"jsonrpc"</span>: <span class="json-string">"2.0"</span>,
594
+ <span class="json-key">"id"</span>: <span class="json-number">1</span>,
595
+ <span class="json-key">"method"</span>: <span class="json-string">"tools/call"</span>,
596
+ <span class="json-key">"params"</span>: {
597
+ <span class="json-key">"name"</span>: <span class="json-string">"extract_financial_metrics"</span>,
598
+ <span class="json-key">"arguments"</span>: {
599
+ <span class="json-key">"cik"</span>: <span class="json-string">"0000789019"</span>,
600
+ <span class="json-key">"years"</span>: <span class="json-number">3</span>
601
+ }
602
+ }
603
+ }</pre>
604
+ </div>
605
+ <div class="param-group">
606
+ <label>CIK Code *</label>
607
+ <input type="text" id="tool7-cik" placeholder="e.g., 0000789019">
608
+ </div>
609
+ <div class="param-group">
610
+ <label>Number of Years</label>
611
+ <select id="tool7-years">
612
+ <option value="1">1 year</option>
613
+ <option value="2">2 years</option>
614
+ <option value="3" selected>3 years</option>
615
+ <option value="5">5 years</option>
616
+ <option value="10">10 years</option>
617
+ </select>
618
+ <div class="param-hint">Number of recent years to extract (1-10)</div>
619
+ </div>
620
+ <button class="test-btn" onclick="testTool('extract_financial_metrics', 'tool7')">Run Test</button>
621
+ <div class="result-box" id="result-tool7"></div>
622
+ </div>
623
+ </div>
624
+ </div>
625
+
626
+ <h2>Documentation</h2>
627
+ <p>Visit <code>/tools</code> to see all available tools in JSON format.</p>
628
+
629
+ <hr style="margin: 30px 0; border: none; border-top: 1px solid #e0e0e0;">
630
+ <p style="text-align: center; color: #666; font-size: 14px;">
631
+ Powered by Model Context Protocol | SEC EDGAR Data | v2.3.1
632
+ </p>
633
+ </div>
634
+
635
+ <script>
636
+ function toggleTool(toolId) {
637
+ const body = document.getElementById(toolId);
638
+ const icon = document.getElementById('icon-' + toolId);
639
+
640
+ if (body.classList.contains('show')) {
641
+ body.classList.remove('show');
642
+ icon.classList.remove('expanded');
643
+ } else {
644
+ body.classList.add('show');
645
+ icon.classList.add('expanded');
646
+ }
647
+ }
648
+
649
+ async function testTool(toolName, toolId) {
650
+ const btn = event.target;
651
+ const resultBox = document.getElementById('result-' + toolId);
652
+
653
+ // Get parameters based on tool
654
+ let args = {};
655
+
656
+ if (toolName === 'search_company') {
657
+ const companyName = document.getElementById(toolId + '-company_name').value;
658
+ if (!companyName) {
659
+ alert('Please enter a company name');
660
+ return;
661
+ }
662
+ args = { company_name: companyName };
663
+ }
664
+ else if (toolName === 'advanced_search_company') {
665
+ const companyInput = document.getElementById(toolId + '-company_input').value;
666
+ if (!companyInput) {
667
+ alert('Please enter a company name, ticker, or CIK');
668
+ return;
669
+ }
670
+ args = { company_input: companyInput };
671
+ }
672
+ else if (toolName === 'get_company_info') {
673
+ const cik = document.getElementById(toolId + '-cik').value;
674
+ if (!cik) {
675
+ alert('Please enter a CIK code');
676
+ return;
677
+ }
678
+ args = { cik: cik };
679
+ }
680
+ else if (toolName === 'get_company_filings') {
681
+ const cik = document.getElementById(toolId + '-cik').value;
682
+ if (!cik) {
683
+ alert('Please enter a CIK code');
684
+ return;
685
+ }
686
+ const formTypesSelect = document.getElementById(toolId + '-form_types');
687
+ const selectedForms = Array.from(formTypesSelect.selectedOptions).map(opt => opt.value);
688
+ args = { cik: cik };
689
+ if (selectedForms.length > 0) {
690
+ args.form_types = selectedForms;
691
+ }
692
+ }
693
+ else if (toolName === 'get_latest_financial_data') {
694
+ const cik = document.getElementById(toolId + '-cik').value;
695
+ if (!cik) {
696
+ alert('Please enter a CIK code');
697
+ return;
698
+ }
699
+ args = { cik: cik };
700
+ }
701
+ else if (toolName === 'get_financial_data') {
702
+ const cik = document.getElementById(toolId + '-cik').value;
703
+ const period = document.getElementById(toolId + '-period').value;
704
+ if (!cik || !period) {
705
+ alert('Please enter CIK and period');
706
+ return;
707
+ }
708
+ args = { cik: cik, period: period };
709
+ }
710
+ else if (toolName === 'extract_financial_metrics') {
711
+ const cik = document.getElementById(toolId + '-cik').value;
712
+ const years = parseInt(document.getElementById(toolId + '-years').value);
713
+ if (!cik) {
714
+ alert('Please enter a CIK code');
715
+ return;
716
+ }
717
+ args = { cik: cik, years: years };
718
+ }
719
+
720
+ // Show loading state
721
+ btn.disabled = true;
722
+ btn.innerHTML = 'Running<span class="loading"></span>';
723
+ resultBox.className = 'result-box show';
724
+ resultBox.textContent = 'Loading...';
725
+
726
+ try {
727
+ const response = await fetch('/message', {
728
+ method: 'POST',
729
+ headers: {
730
+ 'Content-Type': 'application/json',
731
+ },
732
+ body: JSON.stringify({
733
+ jsonrpc: '2.0',
734
+ id: Date.now(),
735
+ method: 'tools/call',
736
+ params: {
737
+ name: toolName,
738
+ arguments: args
739
+ }
740
+ })
741
+ });
742
+
743
+ const data = await response.json();
744
+
745
+ if (data.result && data.result.content && data.result.content[0]) {
746
+ const content = data.result.content[0].text;
747
+ const parsed = JSON.parse(content);
748
+ resultBox.className = 'result-box show success';
749
+ resultBox.textContent = JSON.stringify(parsed, null, 2);
750
+ } else if (data.error) {
751
+ resultBox.className = 'result-box show error';
752
+ resultBox.textContent = 'Error: ' + JSON.stringify(data.error, null, 2);
753
+ } else {
754
+ resultBox.className = 'result-box show error';
755
+ resultBox.textContent = 'Unexpected response: ' + JSON.stringify(data, null, 2);
756
+ }
757
+ } catch (error) {
758
+ resultBox.className = 'result-box show error';
759
+ resultBox.textContent = 'Error: ' + error.message;
760
+ } finally {
761
+ btn.disabled = false;
762
+ btn.innerHTML = 'Run Test';
763
+ }
764
+ }
765
+ </script>
766
+ </body>
767
+ </html>