1+ #!/usr/bin/env python3
2+ """
3+ Test script for the new MCP tools implemented for issue #66
4+
5+ This script tests:
6+ 1. check_repository_attack_surface - Check if repo is in attack surface
7+ 2. check_repository_sensitive_data - Check if repo has sensitive data
8+ 3. list_application_repository_connections - List app-repo connections
9+ 4. get_sensitive_data_summary - Comprehensive sensitive data summary
10+ """
11+
12+ import asyncio
13+ import json
14+ import os
15+ import sys
16+ from datetime import datetime
17+
18+ # Add the stackhawk_mcp directory to the path
19+ sys .path .insert (0 , os .path .abspath (os .path .join (os .path .dirname (__file__ ), '.' )))
20+
21+ from stackhawk_mcp .server import StackHawkMCPServer
22+
23+
24+ async def test_new_tools ():
25+ """Test the new MCP tools implemented for issue #66"""
26+
27+ api_key = os .environ .get ("STACKHAWK_API_KEY" )
28+ if not api_key :
29+ print ("❌ STACKHAWK_API_KEY environment variable is required" )
30+ print ("Please set it to test the new tools" )
31+ return
32+
33+ print ("🔍 Testing New MCP Tools for Issue #66" )
34+ print ("=" * 60 )
35+
36+ server = StackHawkMCPServer (api_key )
37+
38+ try :
39+ # Get user info
40+ user_info = await server .client .get_user_info ()
41+ org_id = user_info ["user" ]["external" ]["organizations" ][0 ]["organization" ]["id" ]
42+ org_name = user_info ["user" ]["external" ]["organizations" ][0 ]["organization" ]["name" ]
43+
44+ print (f"✅ Connected to organization: { org_name } (ID: { org_id } )" )
45+ print ()
46+
47+ # Test 1: Check Repository Attack Surface
48+ print ("1. Testing check_repository_attack_surface..." )
49+ try :
50+ # Test with the current repository name
51+ current_repo = "stackhawk-mcp" # This repo
52+ result = await server ._check_repository_attack_surface (
53+ repo_name = current_repo ,
54+ include_vulnerabilities = True ,
55+ include_apps = True
56+ )
57+ print ("✅ Repository attack surface check completed!" )
58+ print (f" Repository: { result ['repository_name' ]} " )
59+ print (f" Found in attack surface: { result .get ('found_in_attack_surface' , False )} " )
60+ print (f" Total matching repos: { len (result .get ('matching_repositories' , []))} " )
61+ if result .get ('connected_applications' ):
62+ print (f" Connected apps: { result ['total_connected_apps' ]} " )
63+ print (f" Recommendation: { result .get ('recommendation' , 'None' )} " )
64+ except Exception as e :
65+ print (f"❌ Failed to check repository attack surface: { e } " )
66+
67+ print ("\n " + "=" * 60 + "\n " )
68+
69+ # Test 2: Check Repository Sensitive Data
70+ print ("2. Testing check_repository_sensitive_data..." )
71+ try :
72+ result = await server ._check_repository_sensitive_data (
73+ repo_name = current_repo ,
74+ data_type_filter = "All" ,
75+ include_remediation = True
76+ )
77+ print ("✅ Repository sensitive data check completed!" )
78+ print (f" Repository: { result ['repository_name' ]} " )
79+ print (f" Found in StackHawk: { result .get ('found_in_stackhawk' , False )} " )
80+ print (f" Has sensitive data: { result .get ('has_sensitive_data' , False )} " )
81+ print (f" Total findings: { result .get ('total_findings' , 0 )} " )
82+ if result .get ('data_type_breakdown' ):
83+ print (f" Data type breakdown: { result ['data_type_breakdown' ]} " )
84+ print (f" Recommendation: { result .get ('recommendation' , 'None' )} " )
85+ except Exception as e :
86+ print (f"❌ Failed to check repository sensitive data: { e } " )
87+
88+ print ("\n " + "=" * 60 + "\n " )
89+
90+ # Test 3: List Application Repository Connections
91+ print ("3. Testing list_application_repository_connections..." )
92+ try :
93+ result = await server ._list_application_repository_connections (
94+ include_repo_details = True ,
95+ include_app_details = True ,
96+ filter_connected_only = False
97+ )
98+ print ("✅ Application-repository connections listed!" )
99+ print (f" Total applications: { result ['total_applications' ]} " )
100+ print (f" Total repositories: { result ['total_repositories' ]} " )
101+ print (f" Total connections: { result ['total_connections' ]} " )
102+
103+ coverage_stats = result .get ('coverage_stats' , {})
104+ print (f" Connected applications: { coverage_stats .get ('connected_applications' , 0 )} " )
105+ print (f" Orphaned applications: { coverage_stats .get ('orphaned_applications' , 0 )} " )
106+ print (f" Orphaned repositories: { coverage_stats .get ('orphaned_repositories' , 0 )} " )
107+ print (f" Connection coverage: { coverage_stats .get ('connection_coverage' , 0 ):.1f} %" )
108+
109+ recommendations = result .get ('recommendations' , [])
110+ if recommendations :
111+ print (" Recommendations:" )
112+ for i , rec in enumerate (recommendations [:3 ], 1 ):
113+ print (f" { i } . { rec } " )
114+ except Exception as e :
115+ print (f"❌ Failed to list application-repository connections: { e } " )
116+
117+ print ("\n " + "=" * 60 + "\n " )
118+
119+ # Test 4: Get Comprehensive Sensitive Data Summary
120+ print ("4. Testing get_comprehensive_sensitive_data_summary..." )
121+ try :
122+ result = await server ._get_comprehensive_sensitive_data_summary (
123+ time_period = "30d" ,
124+ include_trends = True ,
125+ include_critical_only = False ,
126+ include_recommendations = True ,
127+ group_by = "data_type"
128+ )
129+ print ("✅ Comprehensive sensitive data summary generated!" )
130+ print (f" Total findings: { result ['total_findings' ]} " )
131+ print (f" Analysis type: { result ['analysis_type' ]} " )
132+ print (f" Overall risk score: { result .get ('overall_risk_score' , 0 ):.1f} " )
133+ print (f" Group by: { result ['group_by' ]} " )
134+
135+ grouped_summary = result .get ('grouped_summary' , {})
136+ print (f" Groups found: { len (grouped_summary )} " )
137+ for group_name , group_data in list (grouped_summary .items ())[:3 ]:
138+ print (f" { group_name } : { group_data ['count' ]} findings, risk: { group_data ['risk_score' ]:.1f} " )
139+
140+ recommendations = result .get ('recommendations' , [])
141+ if recommendations :
142+ print (" Recommendations:" )
143+ for i , rec in enumerate (recommendations [:3 ], 1 ):
144+ print (f" { i } . { rec } " )
145+ except Exception as e :
146+ print (f"❌ Failed to generate comprehensive sensitive data summary: { e } " )
147+
148+ print ("\n " + "=" * 60 + "\n " )
149+
150+ # Test 5: Test MCP Tool Interface
151+ print ("5. Testing MCP tool interface..." )
152+ try :
153+ # List available tools
154+ tools = await server ._list_tools_handler ()
155+ new_tool_names = [
156+ "check_repository_attack_surface" ,
157+ "check_repository_sensitive_data" ,
158+ "list_application_repository_connections" ,
159+ "get_sensitive_data_summary"
160+ ]
161+
162+ found_tools = [tool .name for tool in tools if tool .name in new_tool_names ]
163+ print (f"✅ Found { len (found_tools )} /{ len (new_tool_names )} new tools in MCP interface" )
164+ for tool_name in found_tools :
165+ print (f" ✓ { tool_name } " )
166+
167+ missing_tools = [name for name in new_tool_names if name not in found_tools ]
168+ if missing_tools :
169+ print (" Missing tools:" )
170+ for tool_name in missing_tools :
171+ print (f" ✗ { tool_name } " )
172+ except Exception as e :
173+ print (f"❌ Failed to test MCP tool interface: { e } " )
174+
175+ print ("\n " + "=" * 60 + "\n " )
176+
177+ # Test 6: Demonstrate improved tool usage
178+ print ("6. Testing tool call interface..." )
179+ try :
180+ # Test calling the new tool through the MCP interface
181+ result = await server .call_tool (
182+ "check_repository_attack_surface" ,
183+ {"repo_name" : "test-repo" , "include_vulnerabilities" : True }
184+ )
185+ print ("✅ Tool call interface working!" )
186+ print (f" Response type: { type (result )} " )
187+ print (f" Response length: { len (result ) if result else 0 } " )
188+ except Exception as e :
189+ print (f"⚠️ Tool call interface test failed: { e } " )
190+
191+ print ("\n " + "=" * 60 )
192+ print ("✅ All New MCP Tools Testing Complete!" )
193+ print ("\n Summary of Changes for Issue #66:" )
194+ print ("- ✅ Removed duplicate sensitive data tools" )
195+ print ("- ✅ Added attack surface lookup for current repository" )
196+ print ("- ✅ Added sensitive data lookup for current repository" )
197+ print ("- ✅ Added application/code repository connection mapping" )
198+ print ("- ✅ Consolidated sensitive data tools into single comprehensive tool" )
199+ print ("- ✅ All tools support auto-detection of current repository name" )
200+ print ("- ✅ All tools provide actionable recommendations" )
201+
202+ except Exception as e :
203+ print (f"❌ Error during testing: { e } " )
204+ import traceback
205+ traceback .print_exc ()
206+
207+ finally :
208+ await server .cleanup ()
209+
210+
211+ if __name__ == "__main__" :
212+ asyncio .run (test_new_tools ())
0 commit comments