@@ -66,7 +66,8 @@ def _extract_server_info_from_url(self, repo_url: str) -> Dict[str, str]:
6666 else :
6767 # Fallback to repo name if structure is unexpected
6868 server_name = parts [4 ] # 'servers'
69- logger .warning (f"Could not find server name in URL: { repo_url } " )
69+ logger .warning (
70+ f"Could not find server name in URL: { repo_url } " )
7071 else :
7172 # Third-party repo: use repo name as server name
7273 server_name = parts [4 ]
@@ -344,7 +345,8 @@ def _extract_with_llms(self, prompt: tuple[str, str]) -> Dict:
344345 try :
345346 response = self .client .converse (
346347 modelId = LLMModel .CLAUDE_3_7_SONNET ,
347- system = [{"text" : "You are a helpful assistant for README analysis." }],
348+ system = [
349+ {"text" : "You are a helpful assistant for README analysis." }],
348350 messages = [
349351 {
350352 "role" : "user" ,
@@ -364,7 +366,8 @@ def _extract_with_llms(self, prompt: tuple[str, str]) -> Dict:
364366 content = response ["output" ]["message" ]["content" ]
365367
366368 # Find the first text item
367- text_items = [item .get ("text" ) for item in content if "text" in item ]
369+ text_items = [item .get ("text" )
370+ for item in content if "text" in item ]
368371 if text_items :
369372 try :
370373 # Look for JSON content within the text
@@ -377,18 +380,22 @@ def _extract_with_llms(self, prompt: tuple[str, str]) -> Dict:
377380 # If not, try to find JSON in the text (it might be surrounded by other text)
378381 import re
379382
380- json_match = re .search (r"(\{.*\})" , text_content , re .DOTALL )
383+ json_match = re .search (
384+ r"(\{.*\})" , text_content , re .DOTALL )
381385 if json_match :
382386 return json .loads (json_match .group (1 ))
383387 else :
384- logger .error (f"No JSON content found in response: { text_content [:100 ]} ..." )
388+ logger .error (
389+ f"No JSON content found in response: { text_content [:100 ]} ..." )
385390 return self ._get_minimal_manifest ()
386391 except (json .JSONDecodeError , ValueError ) as e :
387- logger .error (f"Failed to parse JSON from response: { e } " )
392+ logger .error (
393+ f"Failed to parse JSON from response: { e } " )
388394 else :
389395 logger .error ("No text items found in response content" )
390396 else :
391- logger .error (f"Unexpected response structure: { response .keys ()} " )
397+ logger .error (
398+ f"Unexpected response structure: { response .keys ()} " )
392399
393400 # If we get here, something went wrong with the parsing
394401 return self ._get_minimal_manifest ()
@@ -437,7 +444,8 @@ def generate_manifest(self, repo_url: str, server_name: Optional[str] = None) ->
437444
438445 # If server info doesn't have a description, extract from README
439446 if not server_info ["desc" ]:
440- server_info ["desc" ] = self ._extract_description_from_readme (readme_content )
447+ server_info ["desc" ] = self ._extract_description_from_readme (
448+ readme_content )
441449
442450 # Get prompt as tuple and extract manifest
443451 prompt = self ._create_prompt (repo_url , readme_content )
@@ -457,19 +465,24 @@ def generate_manifest(self, repo_url: str, server_name: Optional[str] = None) ->
457465 manifest ["description" ] = server_info ["desc" ]
458466
459467 # Categorize the server
460- sample_server = {"name" : manifest .get ("name" , "" ), "description" : manifest .get ("description" , "" )}
468+ sample_server = {"name" : manifest .get (
469+ "name" , "" ), "description" : manifest .get ("description" , "" )}
461470
462- categorized_servers = asyncio .run (self .categorize_servers ([sample_server ]))
471+ categorized_servers = asyncio .run (
472+ self .categorize_servers ([sample_server ]))
463473 if categorized_servers :
464- manifest ["categories" ] = [categorized_servers [0 ].get ("category" , "Unknown" )]
474+ manifest ["categories" ] = [
475+ categorized_servers [0 ].get ("category" , "Unknown" )]
465476 manifest ["tags" ] = manifest .get ("tags" , [])
466477 logger .info (f"Server categorized as: { manifest ['categories' ][0 ]} " )
467478
468479 # Sort installations by priority before running
469- manifest ["installations" ] = self ._filter_and_sort_installations (manifest .get ("installations" , {}))
480+ manifest ["installations" ] = self ._filter_and_sort_installations (
481+ manifest .get ("installations" , {}))
470482 logger .info (f"Server installations: { manifest ['installations' ]} " )
471483 try :
472- capabilities = asyncio .run (self ._run_server_and_extract_capabilities (manifest ))
484+ capabilities = asyncio .run (
485+ self ._run_server_and_extract_capabilities (manifest ))
473486 if capabilities :
474487 manifest .update (capabilities )
475488 except Exception as e :
@@ -483,16 +496,21 @@ async def _run_server_and_extract_capabilities(self, manifest: dict[str, Any]) -
483496 env_vars = {}
484497 if envs :
485498 for k , v in envs .items ():
486- env_vars [k ] = manifest .get ("arguments" , {}).get (k , {}).get ("example" , v )
499+ env_vars [k ] = manifest .get ("arguments" , {}).get (
500+ k , {}).get ("example" , v )
487501 await mcp_client .connect_to_server (installation ["command" ], installation ["args" ], env_vars )
488502 result = {}
489503 try :
490504 tools = await mcp_client .list_tools ()
491- result ["tools" ] = [json .loads (tool .model_dump_json ()) for tool in tools .tools ] # to avoid $schema field
505+ # to avoid $schema field
506+ result ["tools" ] = [json .loads (tool .model_dump_json ())
507+ for tool in tools .tools ]
492508 prompts = await mcp_client .list_prompts ()
493- result ["prompts" ] = [json .loads (prompt .model_dump_json ()) for prompt in prompts .prompts ]
509+ result ["prompts" ] = [json .loads (
510+ prompt .model_dump_json ()) for prompt in prompts .prompts ]
494511 resources = await mcp_client .list_resources ()
495- result ["resources" ] = [json .loads (resource .model_dump_json ()) for resource in resources .resources ]
512+ result ["resources" ] = [json .loads (
513+ resource .model_dump_json ()) for resource in resources .resources ]
496514 except Exception as e :
497515 traceback .print_exc ()
498516 logger .error (f"Failed to list tools: { e } " )
@@ -502,9 +520,12 @@ async def _run_server_and_extract_capabilities(self, manifest: dict[str, Any]) -
502520 return result
503521
504522 def _filter_and_sort_installations (self , installations : dict [str , dict [str , Any ]]):
505- priority = {"uvx" : 0 , "npm" : 1 , "python" : 2 , "docker" : 3 , "cli" : 4 , "custom" : 5 }
506- filtered_installations = {k : v for k , v in installations .items () if k in priority }
507- sorted_installations = sorted (filtered_installations .items (), key = lambda x : priority .get (x [0 ], 6 ))
523+ priority = {"uvx" : 0 , "npm" : 1 , "python" : 2 ,
524+ "docker" : 3 , "cli" : 4 , "custom" : 5 }
525+ filtered_installations = {k : v for k ,
526+ v in installations .items () if k in priority }
527+ sorted_installations = sorted (
528+ filtered_installations .items (), key = lambda x : priority .get (x [0 ], 6 ))
508529 return dict (sorted_installations )
509530
510531
@@ -540,7 +561,8 @@ def main(repo_url: str, is_official: bool = False):
540561 existing_manifest ["name" ] = new_name
541562 with open (new_filename , "w" , encoding = "utf-8" ) as file :
542563 json .dump (existing_manifest , file , indent = 2 )
543- logger .info (f"Previous community manifest saved to { new_filename } " )
564+ logger .info (
565+ f"Previous community manifest saved to { new_filename } " )
544566
545567 with open (filename , "w" , encoding = "utf-8" ) as file :
546568 json .dump (manifest , file , indent = 2 )
@@ -558,9 +580,21 @@ def main(repo_url: str, is_official: bool = False):
558580 sys .exit (1 )
559581
560582 repo_url = sys .argv [1 ].strip ()
561- is_official = bool (sys .argv [2 ]) if len (sys .argv ) > 2 else False
583+
584+ # Check if the URL is a simple URL without protocol
562585 if not repo_url .startswith (("http://" , "https://" )):
563- logger .error ("Error: URL must start with http:// or https://" )
586+ # Add https:// if it's a github.com URL without protocol
587+ if repo_url .startswith ("github.com" ):
588+ repo_url = "https://" + repo_url
589+ # Check if it's a full URL without protocol
590+ elif "github.com" in repo_url :
591+ repo_url = "https://" + repo_url
592+
593+ is_official = bool (sys .argv [2 ]) if len (sys .argv ) > 2 else False
594+
595+ # Validate URL format
596+ if not "github.com" in repo_url :
597+ logger .error ("Error: URL must be a GitHub URL" )
564598 sys .exit (1 )
565599
566600 logger .add (sys .stderr , format = "{time} {level} {message}" , level = "INFO" )
0 commit comments