Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mcp_utils.py to maintain a json of all known MCP Servers #9559

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions litellm/experimental_mcp_client/mcp_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
"""
Utility functions for Model Context Protocol (MCP) server management.
"""
import os
import json
import requests
import re

from typing import Dict, Any, List

def extract_json_from_markdown(markdown_content: str) -> List[Dict[str, Any]]:
"""
Extracts JSON configuration from markdown content by looking for code blocks.

Args:
markdown_content (str): The markdown content to parse

Returns:
Dict[str, Any]: Extracted JSON configuration or empty dict if not found
"""
# Use a regex to find all JSON code blocks
json_blocks = re.findall(r"```json\s*([\s\S]*?)```", markdown_content, re.DOTALL)
extracted_jsons = []
for block in json_blocks:
try:
# Attempt to parse each JSON block
extracted_jsons.append(json.loads(block.strip()))
except json.JSONDecodeError:
continue # Skip invalid JSON blocks

return extracted_jsons

def fetch_mcp_servers() -> List[Dict[str, Any]]:
"""
Fetches MCP server configurations from the modelcontextprotocol/servers repository
and returns them in a standardized format.
Scans the src directory README.md files for server configurations and extracts JSON from key "mcpServers".

Returns:
List[Dict[str, Any]]: List of server configurations
"""
base_url = "https://api.github.com/repos/modelcontextprotocol/servers/contents/src"
headers = {"Accept": "application/vnd.github.v3+json"}

try:
# Get list of files in the src directory
response = requests.get(base_url, headers=headers)
response.raise_for_status()

server_configs = []

for item in response.json():
if item["type"] != "dir": # Skip non-directory items
continue

# Get the README.md content
readme_url = f"https://raw.githubusercontent.com/modelcontextprotocol/servers/main/src/{item['name']}/README.md"
readme_response = requests.get(readme_url)

if readme_response.status_code != 200:
continue

# Extract JSON configuration from the README
config = extract_json_from_markdown(readme_response.text)


# Iterate over each JSON object in the list
for json_obj in config:
if isinstance(json_obj, dict): # Ensure it's a dictionary
for key, value in json_obj.items():
if key == "mcpServers" and isinstance(value, dict):
server_configs.append(value)
break

return server_configs

except requests.RequestException as e:
print(f"Error fetching MCP servers: {e}")
return []

def update_mcp_servers_file(output_file: str = None) -> None:
"""
Updates the MCP servers JSON file with the latest configurations.

Args:
output_file (str): Path to the output JSON file. Defaults to the root directory of the repository.
"""
# Determine the root directory of the repository
root_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../"))
output_file = output_file or os.path.join(root_dir, "mcp_servers.json")

servers = fetch_mcp_servers()

if servers:
with open(output_file, 'w') as f:
json.dump(servers, f, indent=2)
print(f"Successfully updated {output_file} with {len(servers)} server configurations")
else:
print("No server configurations were fetched. File not updated.")

if __name__ == "__main__":
# Update the MCP servers file in the root directory of the repository
update_mcp_servers_file()
Loading