11from dataclasses import dataclass
2- from typing import List , Dict , Any , Optional , override
3- from enum import Enum , auto
4- import boto3
2+ from typing import List , Dict , Any , Optional
3+ from enum import Enum
4+ import os
5+ import json
56import asyncio
7+ from openai import OpenAI
68from loguru import logger
79
10+ import dotenv
11+ dotenv .load_dotenv ()
12+
813
914class MCPCategory (Enum ):
1015 DATABASES = "Databases"
@@ -22,12 +27,8 @@ class MCPCategory(Enum):
2227 MCP_TOOLS = "MCP Tools"
2328
2429
25- class LLMProvider :
26- BEDROCK = "bedrock"
27-
28-
2930class LLMModel :
30- CLAUDE_3_7_SONNET = "us. anthropic. claude-3-7- sonnet-20250219-v1:0 "
31+ CLAUDE_3_SONNET = "anthropic/ claude-3-sonnet"
3132
3233
3334@dataclass
@@ -44,43 +45,15 @@ class CategorizationAgentBuildPromptTemplateArgs:
4445 include_examples : bool = False
4546
4647
47- # Tool configuration for categorization
48- CATEGORIZATION_TOOL_CONFIG = {
49- "tools" : [
50- {
51- "toolSpec" : {
52- "name" : "categorize_server" ,
53- "description" : "Categorize an MCP server into exactly one category" ,
54- "inputSchema" : {
55- "json" : {
56- "type" : "object" ,
57- "properties" : {
58- "category" : {
59- "type" : "string" ,
60- "enum" : [cat .value for cat in MCPCategory ],
61- "description" : "Selected category for the server"
62- },
63- "explanation" : {
64- "type" : "string" ,
65- "description" : "Brief explanation of why this category was chosen"
66- }
67- },
68- "required" : ["category" , "explanation" ]
69- }
70- }
71- }
72- }
73- ],
74- "toolChoice" : {"tool" : {"name" : "categorize_server" }}
75- }
76-
77-
7848class CategorizationAgent :
7949 """Agent that categorizes MCP servers into simplified categories"""
8050
8151 def __init__ (self ):
82- """Initialize the agent with the Bedrock client"""
83- self .client = boto3 .client ("bedrock-runtime" )
52+ """Initialize the agent with the OpenAI client"""
53+ self .client = OpenAI (
54+ base_url = "https://openrouter.ai/api/v1" ,
55+ api_key = os .environ .get ("OPENROUTER_API_KEY" ),
56+ )
8457
8558 def build_system_prompt (self ) -> str :
8659 """Build the system prompt for the categorization agent"""
@@ -112,9 +85,10 @@ def build_system_prompt(self) -> str:
11285## 12. Professional Apps
11386Specialized tools addressing industry-specific needs or use cases with tailored functionality for sectors like healthcare, travel, and media, including healthcare applications (Dicom), travel & transport tools (Travel Planner, NS Travel Information), media & entertainment platforms (TMDB), web development solutions (Webflow, Ghost), and design tools (Figma).
11487## 13. MCP Tools
115- Meta-tools for managing, discovering, and enhancing the MCP ecosystem itself, including server management platforms (MCP Create, MCP Installer), server discovery systems (MCP Compass), connection tools (mcp-proxy), unified interfaces (fastn.ai), and deployment solutions (ChatMCP).Please categorize the following MCP server: \n \n
88+ Meta-tools for managing, discovering, and enhancing the MCP ecosystem itself, including server management platforms (MCP Create, MCP Installer), server discovery systems (MCP Compass), connection tools (mcp-proxy), unified interfaces (fastn.ai), and deployment solutions (ChatMCP).
11689
11790Choose the MOST appropriate category based on the server's primary function.
91+ Not that the server itself is an MCP server, so only select MCP Tools when the server is a meta-tool that manages other MCP servers.
11892Only select ONE category per server."""
11993 )
12094
@@ -151,55 +125,68 @@ async def execute(self, server_name: str, server_description: str, include_examp
151125 include_examples = include_examples
152126 )
153127
154- # Create the messages for the Bedrock API
155- messages = [
156- {"role" : "user" , "content" : [
157- {"text" : user_prompt },
158- {"cachePoint" : {"type" : "default" }} # Cache this prompt
159- ]}
160- ]
128+ # Define the function schema
129+ function_schema = {
130+ "name" : "categorize_server" ,
131+ "description" : "Categorize an MCP server into exactly one category" ,
132+ "parameters" : {
133+ "type" : "object" ,
134+ "required" : ["category" , "explanation" ],
135+ "properties" : {
136+ "category" : {
137+ "type" : "string" ,
138+ "enum" : [cat .value for cat in MCPCategory ],
139+ "description" : "Selected category for the server"
140+ },
141+ "explanation" : {
142+ "type" : "string" ,
143+ "description" : "Brief explanation of why this category was chosen"
144+ }
145+ }
146+ }
147+ }
161148
162- # Call Bedrock API with the categorization tool
149+ # Call OpenAI API with the categorization tool
163150 logger .info (f"Categorizing server: { server_name } " )
164- response = self .client .converse (
165- modelId = LLMModel .CLAUDE_3_7_SONNET ,
166- system = [{"text" : system_prompt }],
167- messages = messages ,
168- toolConfig = CATEGORIZATION_TOOL_CONFIG ,
169- inferenceConfig = {"temperature" : 0.0 },
151+ completion = self .client .chat .completions .create (
152+ extra_headers = {
153+ "HTTP-Referer" : os .environ .get ("SITE_URL" , "https://mcpm.sh" ),
154+ "X-Title" : "MCPM" ,
155+ },
156+ model = LLMModel .CLAUDE_3_SONNET ,
157+ messages = [
158+ {
159+ "role" : "system" ,
160+ "content" : system_prompt
161+ },
162+ {
163+ "role" : "user" ,
164+ "content" : user_prompt
165+ }
166+ ],
167+ tools = [{"type" : "function" , "function" : function_schema }],
168+ tool_choice = {"type" : "function" , "function" : {
169+ "name" : "categorize_server" }}
170170 )
171171
172172 # Process the tool response
173- if response .get ("stopReason" ) == "tool_use" :
174- content_list = response ["output" ]["message" ]["content" ]
175-
176- for content_item in content_list :
177- if "toolUse" in content_item :
178- tool_use = content_item ["toolUse" ]
179- if tool_use ["name" ] == "categorize_server" :
180- # Extract the categorization data
181- tool_input = tool_use .get ("input" , {})
182- result = {
183- "category" : tool_input .get ("category" , "Unknown" ),
184- "explanation" : tool_input .get ("explanation" , "No explanation provided." )
185- }
186- logger .info (
187- f"Categorization result: { result ['category' ]} - { result ['explanation' ][:30 ]} ..." )
188- return result
189-
190- logger .error (
191- "No categorization tool use found in the response" )
192- return {
193- "server_name" : server_name ,
194- "category" : "Unknown" ,
195- "explanation" : "Failed to categorize: No tool use in response."
173+ if completion .choices [0 ].message .tool_calls :
174+ tool_call = completion .choices [0 ].message .tool_calls [0 ]
175+ tool_args = json .loads (tool_call .function .arguments )
176+
177+ result = {
178+ "category" : tool_args .get ("category" , "Unknown" ),
179+ "explanation" : tool_args .get ("explanation" , "No explanation provided." )
196180 }
181+ logger .info (
182+ f"Categorization result: { result ['category' ]} - { result ['explanation' ][:30 ]} ..." )
183+ return result
197184 else :
198- logger .error (f "No tool use found in the response: { response } " )
185+ logger .error ("No tool calls found in the response" )
199186 return {
200187 "server_name" : server_name ,
201188 "category" : "Unknown" ,
202- "explanation" : "Failed to categorize: Model did not use the categorization tool ."
189+ "explanation" : "Failed to categorize: No tool use in response ."
203190 }
204191
205192 except Exception as e :
0 commit comments