mcp-sharepoint-us 2.0.15__tar.gz → 2.0.17__tar.gz

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.

Potentially problematic release.


This version of mcp-sharepoint-us might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcp-sharepoint-us
3
- Version: 2.0.15
3
+ Version: 2.0.17
4
4
  Summary: SharePoint MCP Server with Microsoft Graph API
5
5
  License: MIT
6
6
  Project-URL: Homepage, https://github.com/mdev26/mcp-sharepoint-us
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "mcp-sharepoint-us"
7
- version = "2.0.15"
7
+ version = "2.0.17"
8
8
  description = "SharePoint MCP Server with Microsoft Graph API"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -43,11 +43,13 @@ def ensure_context(func):
43
43
  client_id = os.getenv("SHP_ID_APP")
44
44
  client_secret = os.getenv("SHP_ID_APP_SECRET")
45
45
  tenant_id = os.getenv("SHP_TENANT_ID")
46
+ document_library = os.getenv("SHP_DOC_LIBRARY", "Shared Documents")
46
47
  cloud = "government" if ".sharepoint.us" in site_url else "commercial"
47
48
 
48
49
  logger.info(f"Site URL: {site_url}")
49
50
  logger.info(f"Tenant ID: {tenant_id}")
50
51
  logger.info(f"Client ID: {client_id}")
52
+ logger.info(f"Document Library: {document_library}")
51
53
  logger.info(f"Cloud: {cloud}")
52
54
 
53
55
  # Create shared authenticator
@@ -70,7 +72,8 @@ def ensure_context(func):
70
72
 
71
73
  graph_client = GraphAPIClient(
72
74
  site_url=site_url,
73
- token_callback=get_token
75
+ token_callback=get_token,
76
+ document_library_name=document_library
74
77
  )
75
78
  logger.info("Graph API client initialized successfully")
76
79
 
@@ -23,16 +23,18 @@ class GraphAPIClient:
23
23
  where SharePoint REST API may not support app-only authentication.
24
24
  """
25
25
 
26
- def __init__(self, site_url: str, token_callback):
26
+ def __init__(self, site_url: str, token_callback, document_library_name: str = "Documents"):
27
27
  """
28
28
  Initialize Graph API client.
29
29
 
30
30
  Args:
31
31
  site_url: SharePoint site URL (e.g., https://tenant.sharepoint.us/sites/SiteName)
32
32
  token_callback: Function that returns access token
33
+ document_library_name: Name of the document library to use (e.g., "Shared Documents1")
33
34
  """
34
35
  self.site_url = site_url.rstrip("/")
35
36
  self.token_callback = token_callback
37
+ self.document_library_name = document_library_name
36
38
  self._site_id = None
37
39
  self._drive_id = None # Cache drive ID to avoid repeated API calls
38
40
 
@@ -105,7 +107,8 @@ class GraphAPIClient:
105
107
 
106
108
  # 3. SSL/TLS Test (if HTTPS)
107
109
  if parsed.scheme == "https":
108
- logger.info(f"[TLS] Testing TLS handshake...")
110
+ logger.info(f"[TLS] Testing TLS handshake to {hostname}...")
111
+ logger.info(f"[TLS] This will attempt to establish encrypted HTTPS connection")
109
112
  context = ssl.create_default_context()
110
113
  try:
111
114
  with context.wrap_socket(sock, server_hostname=hostname) as ssock:
@@ -122,7 +125,22 @@ class GraphAPIClient:
122
125
  logger.info(f"[TLS] Certificate subject: {subject.get('commonName', 'N/A')}")
123
126
  logger.info(f"[TLS] Certificate issuer: {dict(x[0] for x in cert['issuer']).get('organizationName', 'N/A')}")
124
127
  except ssl.SSLError as e:
125
- logger.error(f"[TLS] ✗ TLS handshake failed: {e}")
128
+ logger.error(f"[TLS] ✗ TLS/SSL handshake failed: {e}")
129
+ logger.error(f"[TLS] This could indicate:")
130
+ logger.error(f"[TLS] - Certificate validation failure")
131
+ logger.error(f"[TLS] - TLS version mismatch")
132
+ logger.error(f"[TLS] - Cipher suite incompatibility")
133
+ return
134
+ except ConnectionResetError as e:
135
+ logger.error(f"[TLS] ✗ Connection reset during TLS handshake")
136
+ logger.error(f"[TLS] TCP connection was established BUT connection dropped during TLS negotiation")
137
+ logger.error(f"[TLS] This indicates:")
138
+ logger.error(f"[TLS] - Firewall is doing deep packet inspection (DPI)")
139
+ logger.error(f"[TLS] - Firewall is blocking TLS connections to {hostname}")
140
+ logger.error(f"[TLS] - SNI (Server Name Indication) filtering is active")
141
+ logger.error(f"[TLS]")
142
+ logger.error(f"[TLS] SOLUTION: Ask network team to whitelist {hostname} in firewall")
143
+ logger.error(f"[TLS] The firewall needs to allow TLS/HTTPS traffic to this endpoint")
126
144
  return
127
145
  except socket.timeout:
128
146
  logger.error(f"[TCP] ✗ Connection timeout after 10 seconds")
@@ -243,16 +261,32 @@ class GraphAPIClient:
243
261
  except requests.exceptions.ConnectionError as e:
244
262
  logger.error(f"✗ ConnectionError getting site ID: {e}", exc_info=True)
245
263
  logger.error("This indicates the connection was established but then dropped.")
246
- logger.error("Running comprehensive diagnostics...")
264
+ logger.error("Running comprehensive diagnostics to identify the exact failure point...")
265
+ logger.error("")
247
266
 
248
267
  # Run diagnostics to help identify the issue
249
268
  self._diagnose_connectivity(url)
250
269
 
251
- logger.error("\nPossible causes:")
252
- logger.error("1. Firewall is blocking graph.microsoft.us")
270
+ logger.error("")
271
+ logger.error("=" * 70)
272
+ logger.error("DIAGNOSIS COMPLETE")
273
+ logger.error("=" * 70)
274
+ logger.error("")
275
+ logger.error("Most common causes of 'Connection reset by peer':")
276
+ logger.error("")
277
+ logger.error("1. ⚠️ FIREWALL BLOCKING HTTPS/TLS (Most likely based on symptoms)")
278
+ logger.error(" - TCP connection succeeds")
279
+ logger.error(" - Connection drops during TLS handshake")
280
+ logger.error(" - Indicates deep packet inspection (DPI) is active")
281
+ logger.error(" - Solution: Ask network team to whitelist graph.microsoft.us")
282
+ logger.error("")
253
283
  logger.error("2. Proxy configuration needed")
254
- logger.error("3. SSL/TLS version mismatch")
255
- logger.error("4. Network instability")
284
+ logger.error(" - Set HTTP_PROXY and HTTPS_PROXY environment variables")
285
+ logger.error("")
286
+ logger.error("3. SSL/TLS version or certificate issue")
287
+ logger.error(" - Less likely if TCP connects successfully")
288
+ logger.error("")
289
+ logger.error("=" * 70)
256
290
  raise
257
291
 
258
292
  except requests.exceptions.Timeout:
@@ -265,7 +299,8 @@ class GraphAPIClient:
265
299
 
266
300
  def _get_drive_id(self) -> str:
267
301
  """
268
- Get the default document library drive ID.
302
+ Get the document library drive ID by name.
303
+ Fetches all drives and finds the one matching self.document_library_name.
269
304
  Caches the result for reuse.
270
305
  """
271
306
  if self._drive_id:
@@ -273,9 +308,10 @@ class GraphAPIClient:
273
308
  return self._drive_id
274
309
 
275
310
  site_id = self._get_site_id()
276
- url = f"{self.graph_endpoint}/sites/{site_id}/drive"
311
+ url = f"{self.graph_endpoint}/sites/{site_id}/drives"
277
312
 
278
- logger.info(f"Fetching drive ID from: {url}")
313
+ logger.info(f"Fetching all drives from: {url}")
314
+ logger.info(f"Looking for document library named: '{self.document_library_name}'")
279
315
 
280
316
  try:
281
317
  logger.debug(f"Sending GET request to: {url}")
@@ -284,16 +320,37 @@ class GraphAPIClient:
284
320
  logger.debug(f"Response received - Status: {response.status_code}")
285
321
  self._handle_response(response)
286
322
 
287
- self._drive_id = response.json()["id"]
288
- logger.info(f" Retrieved drive ID: {self._drive_id}")
289
- return self._drive_id
323
+ drives = response.json().get("value", [])
324
+ logger.info(f"Found {len(drives)} drives in site")
325
+
326
+ # Log all available drives for debugging
327
+ for drive in drives:
328
+ drive_name = drive.get("name", "Unknown")
329
+ drive_id = drive.get("id", "Unknown")
330
+ logger.debug(f" Drive: '{drive_name}' (ID: {drive_id})")
331
+
332
+ # Find the drive matching the configured document library name
333
+ for drive in drives:
334
+ if drive.get("name") == self.document_library_name:
335
+ self._drive_id = drive["id"]
336
+ logger.info(f"✓ Found matching drive '{self.document_library_name}' with ID: {self._drive_id}")
337
+ return self._drive_id
338
+
339
+ # If no match found, raise an error with helpful message
340
+ available_drives = [d.get("name", "Unknown") for d in drives]
341
+ error_msg = (
342
+ f"Could not find document library named '{self.document_library_name}'. "
343
+ f"Available drives: {', '.join(available_drives)}"
344
+ )
345
+ logger.error(error_msg)
346
+ raise ValueError(error_msg)
290
347
 
291
348
  except requests.exceptions.ConnectionError as e:
292
- logger.error(f"✗ ConnectionError getting drive ID: {e}", exc_info=True)
349
+ logger.error(f"✗ ConnectionError getting drives: {e}", exc_info=True)
293
350
  raise
294
351
 
295
352
  except requests.exceptions.RequestException as e:
296
- logger.error(f"✗ Network error getting drive ID: {type(e).__name__}: {e}", exc_info=True)
353
+ logger.error(f"✗ Network error getting drives: {type(e).__name__}: {e}", exc_info=True)
297
354
  raise
298
355
 
299
356
  def list_folders(self, folder_path: str = "") -> List[Dict[str, Any]]:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcp-sharepoint-us
3
- Version: 2.0.15
3
+ Version: 2.0.17
4
4
  Summary: SharePoint MCP Server with Microsoft Graph API
5
5
  License: MIT
6
6
  Project-URL: Homepage, https://github.com/mdev26/mcp-sharepoint-us