langprotect-mcp-gateway 1.3.0__py3-none-any.whl → 1.3.1__py3-none-any.whl
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.
- langprotect_mcp_gateway/setup_helper.py +141 -24
- {langprotect_mcp_gateway-1.3.0.dist-info → langprotect_mcp_gateway-1.3.1.dist-info}/METADATA +1 -1
- langprotect_mcp_gateway-1.3.1.dist-info/RECORD +10 -0
- langprotect_mcp_gateway-1.3.0.dist-info/RECORD +0 -10
- {langprotect_mcp_gateway-1.3.0.dist-info → langprotect_mcp_gateway-1.3.1.dist-info}/WHEEL +0 -0
- {langprotect_mcp_gateway-1.3.0.dist-info → langprotect_mcp_gateway-1.3.1.dist-info}/entry_points.txt +0 -0
- {langprotect_mcp_gateway-1.3.0.dist-info → langprotect_mcp_gateway-1.3.1.dist-info}/licenses/LICENSE +0 -0
- {langprotect_mcp_gateway-1.3.0.dist-info → langprotect_mcp_gateway-1.3.1.dist-info}/top_level.txt +0 -0
|
@@ -7,6 +7,9 @@ Automatically configures VS Code for global MCP gateway usage
|
|
|
7
7
|
import os
|
|
8
8
|
import json
|
|
9
9
|
import sys
|
|
10
|
+
import getpass
|
|
11
|
+
import urllib.request
|
|
12
|
+
import urllib.error
|
|
10
13
|
from pathlib import Path
|
|
11
14
|
|
|
12
15
|
|
|
@@ -22,24 +25,135 @@ def get_vscode_settings_path():
|
|
|
22
25
|
return home / ".config/Code/User/settings.json"
|
|
23
26
|
|
|
24
27
|
|
|
25
|
-
def
|
|
26
|
-
"""
|
|
28
|
+
def validate_credentials(url, email, password):
|
|
29
|
+
"""Validate credentials against the backend API"""
|
|
30
|
+
try:
|
|
31
|
+
import json
|
|
32
|
+
|
|
33
|
+
# Prepare the request
|
|
34
|
+
data = json.dumps({"email": email, "password": password}).encode('utf-8')
|
|
35
|
+
req = urllib.request.Request(
|
|
36
|
+
f"{url}/api/auth/login/",
|
|
37
|
+
data=data,
|
|
38
|
+
headers={'Content-Type': 'application/json'}
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
# Make the request
|
|
42
|
+
with urllib.request.urlopen(req, timeout=10) as response:
|
|
43
|
+
return response.status in [200, 201]
|
|
44
|
+
|
|
45
|
+
except urllib.error.HTTPError as e:
|
|
46
|
+
# Parse error message if available
|
|
47
|
+
try:
|
|
48
|
+
error_body = e.read().decode('utf-8')
|
|
49
|
+
error_data = json.loads(error_body)
|
|
50
|
+
error_msg = error_data.get('detail', error_data.get('message', 'Authentication failed'))
|
|
51
|
+
print(f" ✗ {error_msg}")
|
|
52
|
+
except:
|
|
53
|
+
print(f" ✗ Authentication failed (HTTP {e.code})")
|
|
54
|
+
return False
|
|
55
|
+
except urllib.error.URLError as e:
|
|
56
|
+
print(f" ✗ Cannot connect to {url}")
|
|
57
|
+
print(f" Make sure the backend is running and accessible")
|
|
58
|
+
return False
|
|
59
|
+
except Exception as e:
|
|
60
|
+
print(f" ✗ Error: {e}")
|
|
61
|
+
return False
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def prompt_credentials():
|
|
65
|
+
"""Interactively prompt user for credentials with validation"""
|
|
66
|
+
print()
|
|
67
|
+
print("═" * 65)
|
|
68
|
+
print(" 🔐 Enter Your LangProtect Credentials")
|
|
69
|
+
print("═" * 65)
|
|
70
|
+
print()
|
|
71
|
+
|
|
72
|
+
while True:
|
|
73
|
+
# Prompt for URL
|
|
74
|
+
url = input("Backend URL [http://localhost:8000]: ").strip()
|
|
75
|
+
if not url:
|
|
76
|
+
url = "http://localhost:8000"
|
|
77
|
+
|
|
78
|
+
# Prompt for email
|
|
79
|
+
email = input("Email: ").strip()
|
|
80
|
+
if not email:
|
|
81
|
+
print("✗ Email cannot be empty!")
|
|
82
|
+
print()
|
|
83
|
+
continue
|
|
84
|
+
|
|
85
|
+
# Prompt for password (hidden)
|
|
86
|
+
password = getpass.getpass("Password: ")
|
|
87
|
+
if not password:
|
|
88
|
+
print("✗ Password cannot be empty!")
|
|
89
|
+
print()
|
|
90
|
+
continue
|
|
91
|
+
|
|
92
|
+
# Validate credentials
|
|
93
|
+
print(" Validating credentials...")
|
|
94
|
+
if validate_credentials(url, email, password):
|
|
95
|
+
print(" ✓ Credentials validated successfully!")
|
|
96
|
+
print()
|
|
97
|
+
return url, email, password
|
|
98
|
+
else:
|
|
99
|
+
print()
|
|
100
|
+
print("Please try again or press Ctrl+C to cancel.")
|
|
101
|
+
print()
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def create_wrapper_script(url=None, email=None, password=None):
|
|
105
|
+
"""Create the global wrapper script with credentials"""
|
|
27
106
|
wrapper_dir = Path.home() / ".local/bin"
|
|
28
107
|
wrapper_dir.mkdir(parents=True, exist_ok=True)
|
|
29
108
|
|
|
30
109
|
wrapper_path = wrapper_dir / "langprotect-mcp-wrapper.sh"
|
|
31
110
|
|
|
32
|
-
|
|
111
|
+
# Check if credentials provided via environment variables
|
|
112
|
+
if not url or not email or not password:
|
|
113
|
+
url = os.environ.get('LANGPROTECT_URL')
|
|
114
|
+
email = os.environ.get('LANGPROTECT_EMAIL')
|
|
115
|
+
password = os.environ.get('LANGPROTECT_PASSWORD')
|
|
116
|
+
|
|
117
|
+
# If still not provided, prompt user
|
|
118
|
+
if not url or not email or not password:
|
|
119
|
+
url, email, password = prompt_credentials()
|
|
120
|
+
else:
|
|
121
|
+
# Validate environment credentials
|
|
122
|
+
print(" Using credentials from environment variables...")
|
|
123
|
+
print(" Validating...")
|
|
124
|
+
if not validate_credentials(url, email, password):
|
|
125
|
+
print(" ✗ Environment credentials invalid. Please enter manually:")
|
|
126
|
+
url, email, password = prompt_credentials()
|
|
127
|
+
else:
|
|
128
|
+
print(" ✓ Environment credentials validated!")
|
|
129
|
+
|
|
130
|
+
# Create wrapper with actual credentials
|
|
131
|
+
wrapper_content = f"""#!/bin/bash
|
|
33
132
|
# LangProtect MCP Gateway Wrapper
|
|
34
|
-
#
|
|
133
|
+
# Auto-configured by langprotect-gateway-setup
|
|
134
|
+
|
|
135
|
+
# ============================================================
|
|
136
|
+
# Backend Connection
|
|
137
|
+
# ============================================================
|
|
138
|
+
export LANGPROTECT_URL="${{LANGPROTECT_URL:-{url}}}"
|
|
139
|
+
export LANGPROTECT_EMAIL="${{LANGPROTECT_EMAIL:-{email}}}"
|
|
140
|
+
export LANGPROTECT_PASSWORD="${{LANGPROTECT_PASSWORD:-{password}}}"
|
|
141
|
+
|
|
142
|
+
# ============================================================
|
|
143
|
+
# Security Controls (v1.3.1+)
|
|
144
|
+
# ============================================================
|
|
145
|
+
export LANGPROTECT_ENABLE_MASKING="${{LANGPROTECT_ENABLE_MASKING:-true}}"
|
|
146
|
+
export LANGPROTECT_FAIL_CLOSED="${{LANGPROTECT_FAIL_CLOSED:-false}}"
|
|
147
|
+
export LANGPROTECT_SCAN_TIMEOUT="${{LANGPROTECT_SCAN_TIMEOUT:-5.0}}"
|
|
148
|
+
export LANGPROTECT_ENTROPY_DETECTION="${{LANGPROTECT_ENTROPY_DETECTION:-true}}"
|
|
35
149
|
|
|
36
|
-
#
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
export
|
|
40
|
-
export
|
|
41
|
-
export MCP_SERVER_ARGS="${MCP_SERVER_ARGS:--y,@modelcontextprotocol/server-filesystem,.}"
|
|
150
|
+
# ============================================================
|
|
151
|
+
# MCP Server Configuration
|
|
152
|
+
# ============================================================
|
|
153
|
+
export MCP_SERVER_COMMAND="${{MCP_SERVER_COMMAND:-npx}}"
|
|
154
|
+
export MCP_SERVER_ARGS="${{MCP_SERVER_ARGS:--y,@modelcontextprotocol/server-filesystem,.}}"
|
|
42
155
|
|
|
156
|
+
# Start the gateway
|
|
43
157
|
exec langprotect-gateway "$@"
|
|
44
158
|
"""
|
|
45
159
|
|
|
@@ -130,7 +244,7 @@ def setup():
|
|
|
130
244
|
print("🚀 Setting up LangProtect MCP Gateway...")
|
|
131
245
|
print()
|
|
132
246
|
|
|
133
|
-
# Create wrapper script
|
|
247
|
+
# Create wrapper script (will prompt for credentials if needed)
|
|
134
248
|
print("📝 Creating global wrapper script...")
|
|
135
249
|
wrapper_path = create_wrapper_script()
|
|
136
250
|
print(f" ✅ Created: {wrapper_path}")
|
|
@@ -145,7 +259,7 @@ def setup():
|
|
|
145
259
|
print(f" ⚠️ Could not update VS Code settings: {e}")
|
|
146
260
|
|
|
147
261
|
# Update Claude Desktop config
|
|
148
|
-
print("🍏 Configuring Claude Desktop
|
|
262
|
+
print("🍏 Configuring Claude Desktop...")
|
|
149
263
|
try:
|
|
150
264
|
claude_path = update_claude_config(wrapper_path)
|
|
151
265
|
print(f" ✅ Updated: {claude_path}")
|
|
@@ -158,25 +272,28 @@ def setup():
|
|
|
158
272
|
print()
|
|
159
273
|
print("📋 Next steps:")
|
|
160
274
|
print()
|
|
161
|
-
print("1.
|
|
162
|
-
print(f" Edit: {wrapper_path}")
|
|
163
|
-
print(" Set LANGPROTECT_URL, LANGPROTECT_EMAIL, and LANGPROTECT_PASSWORD")
|
|
164
|
-
print()
|
|
165
|
-
print("2. Reload VS Code:")
|
|
275
|
+
print("1. Reload VS Code:")
|
|
166
276
|
print(" Press Ctrl+Shift+P → 'Developer: Reload Window'")
|
|
167
277
|
print()
|
|
168
|
-
print("
|
|
278
|
+
print("2. Verify it's working:")
|
|
169
279
|
print(" Press Ctrl+Shift+P → 'MCP: List Servers'")
|
|
170
280
|
print(" You should see 'langprotect-gateway' listed")
|
|
171
281
|
print()
|
|
172
|
-
print("
|
|
282
|
+
print("3. Test the protection:")
|
|
283
|
+
print(" Ask AI to read a file with secrets - they'll be masked!")
|
|
284
|
+
print()
|
|
285
|
+
print("🎉 LangProtect is now protecting ALL your VS Code workspaces!")
|
|
173
286
|
print()
|
|
174
|
-
print("💡
|
|
175
|
-
print(" export LANGPROTECT_URL=http://localhost:8000")
|
|
176
|
-
print(" export LANGPROTECT_EMAIL=your.email@company.com")
|
|
177
|
-
print(" export LANGPROTECT_PASSWORD=your-password")
|
|
287
|
+
print("💡 Configuration file:", wrapper_path)
|
|
178
288
|
print()
|
|
179
289
|
|
|
180
290
|
|
|
181
291
|
if __name__ == "__main__":
|
|
182
|
-
|
|
292
|
+
try:
|
|
293
|
+
setup()
|
|
294
|
+
except KeyboardInterrupt:
|
|
295
|
+
print("\n\n⚠️ Setup cancelled by user.")
|
|
296
|
+
sys.exit(1)
|
|
297
|
+
except Exception as e:
|
|
298
|
+
print(f"\n\n❌ Setup failed: {e}")
|
|
299
|
+
sys.exit(1)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
langprotect_mcp_gateway/__init__.py,sha256=PedabfF6wZ_6KxuN60A4qz8T1gD9MszuXwhmrHlGH7I,510
|
|
2
|
+
langprotect_mcp_gateway/gateway.py,sha256=YIggDJ7n0ctUsyyI1s567QFbH7cq5-6CAAdI1J8gQkY,30921
|
|
3
|
+
langprotect_mcp_gateway/response_masker.py,sha256=ui1JusuPwuOKSfrDtt0FxLEGs_y512RcTG4gSz2-MT8,14702
|
|
4
|
+
langprotect_mcp_gateway/setup_helper.py,sha256=alkIyR3jB-RuiD32oNrATc-IskYkTgWUNjy8SLDz5HQ,9746
|
|
5
|
+
langprotect_mcp_gateway-1.3.1.dist-info/licenses/LICENSE,sha256=aoVP65gKtirVmFPToow5L9IKN4FNjfM6Sejq_5b4cbM,1082
|
|
6
|
+
langprotect_mcp_gateway-1.3.1.dist-info/METADATA,sha256=U3u6uT_-AZwBOio_blaZBwRv41aQos9sMMgXrp-ba4w,11787
|
|
7
|
+
langprotect_mcp_gateway-1.3.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
8
|
+
langprotect_mcp_gateway-1.3.1.dist-info/entry_points.txt,sha256=HpnUUuYLQva8b6gazUX0UJO9dFHq86e9gifQfLKpyWc,140
|
|
9
|
+
langprotect_mcp_gateway-1.3.1.dist-info/top_level.txt,sha256=UjNlX13ma4nwJXuEyi9eMX251c5rooeEao4zajX6ZHk,24
|
|
10
|
+
langprotect_mcp_gateway-1.3.1.dist-info/RECORD,,
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
langprotect_mcp_gateway/__init__.py,sha256=PedabfF6wZ_6KxuN60A4qz8T1gD9MszuXwhmrHlGH7I,510
|
|
2
|
-
langprotect_mcp_gateway/gateway.py,sha256=YIggDJ7n0ctUsyyI1s567QFbH7cq5-6CAAdI1J8gQkY,30921
|
|
3
|
-
langprotect_mcp_gateway/response_masker.py,sha256=ui1JusuPwuOKSfrDtt0FxLEGs_y512RcTG4gSz2-MT8,14702
|
|
4
|
-
langprotect_mcp_gateway/setup_helper.py,sha256=ghErneMTua9wPATMq8eatnviVAYJMi2bf2UUt8fnXE8,5639
|
|
5
|
-
langprotect_mcp_gateway-1.3.0.dist-info/licenses/LICENSE,sha256=aoVP65gKtirVmFPToow5L9IKN4FNjfM6Sejq_5b4cbM,1082
|
|
6
|
-
langprotect_mcp_gateway-1.3.0.dist-info/METADATA,sha256=f8QWABfqpzyuO_UgtCxC9LI6jAuuy0fsPluZIgNna54,11787
|
|
7
|
-
langprotect_mcp_gateway-1.3.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
8
|
-
langprotect_mcp_gateway-1.3.0.dist-info/entry_points.txt,sha256=HpnUUuYLQva8b6gazUX0UJO9dFHq86e9gifQfLKpyWc,140
|
|
9
|
-
langprotect_mcp_gateway-1.3.0.dist-info/top_level.txt,sha256=UjNlX13ma4nwJXuEyi9eMX251c5rooeEao4zajX6ZHk,24
|
|
10
|
-
langprotect_mcp_gateway-1.3.0.dist-info/RECORD,,
|
|
File without changes
|
{langprotect_mcp_gateway-1.3.0.dist-info → langprotect_mcp_gateway-1.3.1.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
{langprotect_mcp_gateway-1.3.0.dist-info → langprotect_mcp_gateway-1.3.1.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|
{langprotect_mcp_gateway-1.3.0.dist-info → langprotect_mcp_gateway-1.3.1.dist-info}/top_level.txt
RENAMED
|
File without changes
|