Skip to content

Commit f95564f

Browse files
committed
2 parents 97b5568 + ae8517a commit f95564f

21 files changed

Lines changed: 813 additions & 184 deletions

File tree

README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
<a href="https://iproyal.com/?r=835844"><img src="images/iproyal-1.png" alt="IPRoyal Banner" width="550" height="250" style="vertical-align: middle; margin-left: 10px;"/></a>
1+
<p align="center">
2+
<a href="https://codingfleet.com/code-generator/python/?utm_source=github-repo&utm_medium=banner-2">
3+
<img src="images/codingfleet-banner-2.png" alt="CodingFleet Code Generator" width="350" height="350">
4+
</a><a href="https://codingfleet.com/code-converter/python/?utm_source=github-repo&utm_medium=banner-3">
5+
<img src="images/codingfleet-banner-3.png" alt="CodingFleet Code Converter" width="350" height="350">
6+
</a>
7+
</p>
8+
29

310

411
# Python Code Tutorials
@@ -182,6 +189,7 @@ This is a repository of all the tutorials of [The Python Code](https://www.thepy
182189
- [How to Query the Ethereum Blockchain with Python](https://www.thepythoncode.com/article/query-ethereum-blockchain-with-python). ([code](general/query-ethereum))
183190
- [Data Cleaning with Pandas in Python](https://www.thepythoncode.com/article/data-cleaning-using-pandas-in-python). ([code](general/data-cleaning-pandas))
184191
- [How to Minify CSS with Python](https://www.thepythoncode.com/article/minimize-css-files-in-python). ([code](general/minify-css))
192+
- [Build a real MCP client and server in Python with FastMCP (Todo Manager example)](https://www.thepythoncode.com/article/fastmcp-mcp-client-server-todo-manager). ([code](general/fastmcp-mcp-client-server-todo-manager))
185193

186194

187195

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
# [How to Extract Saved WiFi Passwords in Python](https://www.thepythoncode.com/article/extract-saved-wifi-passwords-in-python)
1+
# [How to Extract Saved WiFi Passwords in Python](https://www.thepythoncode.com/article/extract-saved-wifi-passwords-in-python)
2+
3+
This program lists saved Wi-Fi networks and their passwords on Windows and Linux machines. In addition to the SSID (Wi-Fi network name) and passwords, the output also shows the network’s security type and ciphers.

ethical-hacking/get-wifi-passwords/get_wifi_passwords.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,16 @@ def get_windows_saved_wifi_passwords(verbose=1):
2828
[list]: list of extracted profiles, a profile has the fields ["ssid", "ciphers", "key"]
2929
"""
3030
ssids = get_windows_saved_ssids()
31-
Profile = namedtuple("Profile", ["ssid", "ciphers", "key"])
31+
Profile = namedtuple("Profile", ["ssid", "security", "ciphers", "key"])
3232
profiles = []
3333
for ssid in ssids:
3434
ssid_details = subprocess.check_output(f"""netsh wlan show profile "{ssid}" key=clear""").decode()
35+
36+
#get the security type
37+
security = re.findall(r"Authentication\s(.*)", ssid_details)
38+
# clear spaces and colon
39+
security = "/".join(dict.fromkeys(c.strip().strip(":").strip() for c in security))
40+
3541
# get the ciphers
3642
ciphers = re.findall(r"Cipher\s(.*)", ssid_details)
3743
# clear spaces and colon
@@ -43,7 +49,7 @@ def get_windows_saved_wifi_passwords(verbose=1):
4349
key = key[0].strip().strip(":").strip()
4450
except IndexError:
4551
key = "None"
46-
profile = Profile(ssid=ssid, ciphers=ciphers, key=key)
52+
profile = Profile(ssid=ssid, security=security, ciphers=ciphers, key=key)
4753
if verbose >= 1:
4854
print_windows_profile(profile)
4955
profiles.append(profile)
@@ -52,12 +58,13 @@ def get_windows_saved_wifi_passwords(verbose=1):
5258

5359
def print_windows_profile(profile):
5460
"""Prints a single profile on Windows"""
55-
print(f"{profile.ssid:25}{profile.ciphers:15}{profile.key:50}")
61+
#print(f"{profile.ssid:25}{profile.ciphers:15}{profile.key:50}")
62+
print(f"{profile.ssid:25}{profile.security:30}{profile.ciphers:35}{profile.key:50}")
5663

5764

5865
def print_windows_profiles(verbose):
5966
"""Prints all extracted SSIDs along with Key on Windows"""
60-
print("SSID CIPHER(S) KEY")
67+
print("SSID Securities CIPHER(S) KEY")
6168
print("-"*50)
6269
get_windows_saved_wifi_passwords(verbose)
6370

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Grab your API key from Open Router:- https://openrouter.ai/
2+
Model is Used is DeepSeek: DeepSeek V3.1 (free). However, feel free to try others.
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
#!/usr/bin/env python3
2+
import requests
3+
import json
4+
import os
5+
import argparse
6+
from typing import Dict, List, Tuple
7+
from openai import OpenAI
8+
9+
class SecurityHeadersAnalyzer:
10+
def __init__(self, api_key: str = None, base_url: str = None, model: str = None):
11+
self.api_key = api_key or os.getenv('OPENROUTER_API_KEY') or os.getenv('OPENAI_API_KEY')
12+
self.base_url = base_url or os.getenv('OPENROUTER_BASE_URL', 'https://openrouter.ai/api/v1')
13+
self.model = model or os.getenv('LLM_MODEL', 'deepseek/deepseek-chat-v3.1:free')
14+
15+
if not self.api_key:
16+
raise ValueError("API key is required. Set OPENROUTER_API_KEY or provide --api-key")
17+
18+
self.client = OpenAI(base_url=self.base_url, api_key=self.api_key)
19+
20+
def fetch_headers(self, url: str, timeout: int = 10) -> Tuple[Dict[str, str], int]:
21+
"""Fetch HTTP headers from URL"""
22+
if not url.startswith(('http://', 'https://')):
23+
url = 'https://' + url
24+
25+
try:
26+
response = requests.get(url, timeout=timeout, allow_redirects=True)
27+
return dict(response.headers), response.status_code
28+
except requests.exceptions.RequestException as e:
29+
print(f"Error fetching {url}: {e}")
30+
return {}, 0
31+
32+
def analyze_headers(self, url: str, headers: Dict[str, str], status_code: int) -> str:
33+
"""Analyze headers using LLM"""
34+
prompt = f"""Analyze the HTTP security headers for {url} (Status: {status_code})
35+
36+
Headers:
37+
{json.dumps(headers, indent=2)}
38+
39+
Provide a comprehensive security analysis including:
40+
1. Security score (0-100) and overall assessment
41+
2. Critical security issues that need immediate attention
42+
3. Missing important security headers
43+
4. Analysis of existing security headers and their effectiveness
44+
5. Specific recommendations for improvement
45+
6. Potential security risks based on current configuration
46+
47+
Focus on practical, actionable advice following current web security best practices. Please do not include ** and #
48+
in the response except for specific references where necessary. use numbers, romans, alphabets instead Format the response well please. """
49+
50+
try:
51+
completion = self.client.chat.completions.create(
52+
model=self.model,
53+
messages=[{"role": "user", "content": prompt}],
54+
temperature=0.2
55+
)
56+
return completion.choices[0].message.content
57+
except Exception as e:
58+
return f"Analysis failed: {e}"
59+
60+
def analyze_url(self, url: str, timeout: int = 10) -> Dict:
61+
"""Analyze a single URL"""
62+
print(f"\nAnalyzing: {url}")
63+
print("-" * 50)
64+
65+
headers, status_code = self.fetch_headers(url, timeout)
66+
if not headers:
67+
return {"url": url, "error": "Failed to fetch headers"}
68+
69+
print(f"Status Code: {status_code}")
70+
print(f"\nHTTP Headers ({len(headers)} found):")
71+
print("-" * 30)
72+
for key, value in headers.items():
73+
print(f"{key}: {value}")
74+
75+
print(f"\nAnalyzing with AI...")
76+
analysis = self.analyze_headers(url, headers, status_code)
77+
78+
print("\nSECURITY ANALYSIS")
79+
print("=" * 50)
80+
print(analysis)
81+
82+
return {
83+
"url": url,
84+
"status_code": status_code,
85+
"headers_count": len(headers),
86+
"analysis": analysis,
87+
"raw_headers": headers
88+
}
89+
90+
def analyze_multiple_urls(self, urls: List[str], timeout: int = 10) -> List[Dict]:
91+
"""Analyze multiple URLs"""
92+
results = []
93+
for i, url in enumerate(urls, 1):
94+
print(f"\n[{i}/{len(urls)}]")
95+
result = self.analyze_url(url, timeout)
96+
results.append(result)
97+
return results
98+
99+
def export_results(self, results: List[Dict], filename: str):
100+
"""Export results to JSON"""
101+
with open(filename, 'w') as f:
102+
json.dump(results, f, indent=2, ensure_ascii=False)
103+
print(f"\nResults exported to: {filename}")
104+
105+
def main():
106+
parser = argparse.ArgumentParser(
107+
description='Analyze HTTP security headers using AI',
108+
formatter_class=argparse.RawDescriptionHelpFormatter,
109+
epilog='''Examples:
110+
python security_headers.py https://example.com
111+
python security_headers.py example.com google.com
112+
python security_headers.py example.com --export results.json
113+
114+
Environment Variables:
115+
OPENROUTER_API_KEY - API key for OpenRouter
116+
OPENAI_API_KEY - API key for OpenAI
117+
LLM_MODEL - Model to use (default: deepseek/deepseek-chat-v3.1:free)'''
118+
)
119+
120+
parser.add_argument('urls', nargs='+', help='URLs to analyze')
121+
parser.add_argument('--api-key', help='API key for LLM service')
122+
parser.add_argument('--base-url', help='Base URL for LLM API')
123+
parser.add_argument('--model', help='LLM model to use')
124+
parser.add_argument('--timeout', type=int, default=10, help='Request timeout (default: 10s)')
125+
parser.add_argument('--export', help='Export results to JSON file')
126+
127+
args = parser.parse_args()
128+
129+
try:
130+
analyzer = SecurityHeadersAnalyzer(
131+
api_key=args.api_key,
132+
base_url=args.base_url,
133+
model=args.model
134+
)
135+
136+
results = analyzer.analyze_multiple_urls(args.urls, args.timeout)
137+
138+
if args.export:
139+
analyzer.export_results(results, args.export)
140+
141+
except ValueError as e:
142+
print(f"Error: {e}")
143+
return 1
144+
except KeyboardInterrupt:
145+
print("\nAnalysis interrupted by user")
146+
return 1
147+
148+
if __name__ == '__main__':
149+
main()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
openai
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Build a real MCP client and server in Python with FastMCP (Todo Manager example)
2+
3+
This folder contains the code that accompanies the article:
4+
5+
- Article: https://www.thepythoncode.com/article/fastmcp-mcp-client-server-todo-manager
6+
7+
What’s included
8+
- `todo_server.py`: FastMCP MCP server exposing tools, resources, and a prompt for a Todo Manager.
9+
- `todo_client_test.py`: A small client script that connects to the server and exercises all features.
10+
- `requirements.txt`: Python dependencies for this tutorial.
11+
12+
Quick start
13+
1) Install requirements
14+
```bash
15+
python -m venv .venv && source .venv/bin/activate # or use your preferred env manager
16+
pip install -r requirements.txt
17+
```
18+
19+
2) Run the server (stdio transport by default)
20+
```bash
21+
python todo_server.py
22+
```
23+
24+
3) In a separate terminal, run the client
25+
```bash
26+
python todo_client_test.py
27+
```
28+
29+
Optional: run the server over HTTP
30+
- In `todo_server.py`, replace the last line with:
31+
```python
32+
mcp.run(transport="http", host="127.0.0.1", port=8000)
33+
```
34+
- Then change the client constructor to `Client("http://127.0.0.1:8000/mcp")`.
35+
36+
Notes
37+
- Requires Python 3.10+.
38+
- The example uses in-memory storage for simplicity.
39+
- For production tips (HTTPS, auth, containerization), see the article.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
fastmcp>=2.12
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import asyncio
2+
from fastmcp import Client
3+
4+
async def main():
5+
# Option A: Connect to local Python script (stdio)
6+
client = Client("todo_server.py")
7+
8+
# Option B: In-memory (for tests)
9+
# from todo_server import mcp
10+
# client = Client(mcp)
11+
12+
async with client:
13+
await client.ping()
14+
print("[OK] Connected")
15+
16+
# Create a few todos
17+
t1 = await client.call_tool("create_todo", {"title": "Write README", "priority": "high"})
18+
t2 = await client.call_tool("create_todo", {"title": "Refactor utils", "description": "Split helpers into modules"})
19+
t3 = await client.call_tool("create_todo", {"title": "Add tests", "priority": "low"})
20+
print("Created IDs:", t1.data["id"], t2.data["id"], t3.data["id"])
21+
22+
# List open
23+
open_list = await client.call_tool("list_todos", {"status": "open"})
24+
print("Open IDs:", [t["id"] for t in open_list.data["items"]])
25+
26+
# Complete one
27+
updated = await client.call_tool("complete_todo", {"todo_id": t2.data["id"]})
28+
print("Completed:", updated.data["id"], "status:", updated.data["status"])
29+
30+
# Search
31+
found = await client.call_tool("search_todos", {"query": "readme"})
32+
print("Search 'readme':", [t["id"] for t in found.data["items"]])
33+
34+
# Resources
35+
stats = await client.read_resource("stats://todos")
36+
print("Stats:", getattr(stats[0], "text", None) or stats[0])
37+
38+
todo2 = await client.read_resource(f"todo://{t2.data['id']}")
39+
print("todo://{id}:", getattr(todo2[0], "text", None) or todo2[0])
40+
41+
# Prompt
42+
prompt_msgs = await client.get_prompt("suggest_next_action", {"pending": 2, "project": "MCP tutorial"})
43+
msgs_pretty = [
44+
{"role": m.role, "content": getattr(m, "content", None) or getattr(m, "text", None)}
45+
for m in getattr(prompt_msgs, "messages", [])
46+
]
47+
print("Prompt messages:", msgs_pretty)
48+
49+
if __name__ == "__main__":
50+
asyncio.run(main())

0 commit comments

Comments
 (0)