diff --git a/mcp/freshdesk.py b/mcp/freshdesk.py deleted file mode 100644 index aa9df03..0000000 --- a/mcp/freshdesk.py +++ /dev/null @@ -1,43 +0,0 @@ -import os -import asyncio -from dotenv import load_dotenv -import scalekit.client -from scalekit.connect.types import ToolMapping -from utils import authenticate_tool - -load_dotenv() - -scalekit = scalekit.client.ScalekitClient( - client_id=os.getenv("SCALEKIT_CLIENT_ID"), - client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"), - env_url=os.getenv("SCALEKIT_ENV_URL"), -) -connect = scalekit.connect - -def main(): - - - connected_account = connect.get_or_create_connected_account( - connection_name="FRESHDESK", - identifier="avinash", - authorization_details= { - "static_auth": { - "domain": "avinashmkamath.freshdesk.com", - "username": "ikipj7k9dasd8TsUJJWRXZganAk" - } - } - ) - - mcp_response = connect.create_mcp( - identifier = "avinash", - tool_mappings = [ - ToolMapping( - tool_names=["freshdesk_create_ticket","freshdesk_list_tickets"], - connection_name="FRESHDESK", - ) - ] - ) - - print(mcp_response.url) - -main() \ No newline at end of file diff --git a/mcp/main.py b/mcp/main.py index 7509032..2ad18e6 100644 --- a/mcp/main.py +++ b/mcp/main.py @@ -1,60 +1,109 @@ - import os import asyncio from dotenv import load_dotenv import scalekit.client -from scalekit.connect.types import ToolMapping -from utils import authenticate_tool +from scalekit.actions.models.mcp_config import McpConfigConnectionToolMapping +from langgraph.prebuilt import create_react_agent +from langchain_mcp_adapters.client import MultiServerMCPClient load_dotenv() +CONFIG_NAME = "reminder-manager" +CONFIG_DESCRIPTION = "Summarizes emails and creates calendar reminder event" +CONFIG_DESCRIPTION_UPDATED = "Updated summary and calendar automation config" +CONFIG_MAPPINGS = [ + McpConfigConnectionToolMapping( + connection_name="MY_GMAIL", + tools=[], + ), + McpConfigConnectionToolMapping( + connection_name="MY_CALENDAR", + tools=[ + "googlecalendar_create_event", + "googlecalendar_delete_event", + ], + ), +] +INSTANCE_USER_IDENTIFIER = "john-doe" + scalekit = scalekit.client.ScalekitClient( client_id=os.getenv("SCALEKIT_CLIENT_ID"), client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"), env_url=os.getenv("SCALEKIT_ENV_URL"), ) -connect = scalekit.connect +my_mcp = scalekit.actions.mcp async def main(): + # First create the MCP config + config_exists = False + config_name = None + try: + list_resp = my_mcp.list_configs(filter_name=CONFIG_NAME) + config_exists = False + if len(list_resp.configs) > 0 and list_resp.configs[0].id: + config_exists = True + config_name = list_resp.configs[0].name + print(f"Config '{CONFIG_NAME}' already exists.") + except Exception as e: + print(f"Error checking for existing config: {e}") + + if not config_exists: + print(f"Creating MCP config '{CONFIG_NAME}'...") + config_response = my_mcp.create_config( + name=CONFIG_NAME, + description=CONFIG_DESCRIPTION, + connection_tool_mappings=CONFIG_MAPPINGS, + ) + config_name = config_response.config.name + print("Config name: ", config_name) + + # Now get or create an MCP instance for a user + print("Get Or Create MCP instance for user", INSTANCE_USER_IDENTIFIER, "on config", config_name) + instance_response = my_mcp.ensure_instance( + config_name=config_name, + user_identifier=INSTANCE_USER_IDENTIFIER, + name="reminder-mcp-john", + ) + print("Instance name:", instance_response.instance.name) + mcp_url = instance_response.instance.url - #create connected account for identifier default and connection name GMAIL,CALENDAR - authenticate_tool(connect,"GMAIL", "user_1234567890") - authenticate_tool(connect,"GCAL", "user_1234567890") - - mcp_response = connect.create_mcp( - identifier = "user_1234567890", - tool_mappings = [ - ToolMapping( - tool_names=["gmail_fetch_mails", "gmail_send_mails"], - connection_name="GMAIL", - ), - ToolMapping( - tool_names=["googlecalendar_list_events", "googlecalendar_create_event"], - connection_name="GCAL", - ) - ] + # Now create auth links and load these links in browser to authenticate connections + auth_state_response = my_mcp.get_instance_auth_state( + instance_id=instance_response.instance.id, + include_auth_links=True, ) + for conn in getattr(auth_state_response, "connections", []): + print("Connection Name:", conn.connection_name, " Provider: ", conn.provider, " Auth Link: ", conn.authentication_link, "Auth Status: ", conn.connected_account_status) - from langchain_mcp_adapters.client import MultiServerMCPClient - from langgraph.prebuilt import create_react_agent + print("Authenticate with above links and type continue to connect the agent to this mcp") - # Print the URL of the created MCP - print("MCP created successfully:", mcp_response.url) + while True: + choice = input("Type 'continue' to proceed or 'exit' to quit: ").strip().lower() + if choice == "continue": + break + if choice == "exit": + print("Exiting.") + return + print("Invalid input. Please type 'continue' or 'exit'.") + + # Connect your agent to the MCP + print("Connecting your agent to MCP:", mcp_url) client = MultiServerMCPClient( { - "gcal_demo": { + "reminder_demo": { "transport": "streamable_http", - "url": mcp_response.url + "url": mcp_url }, } ) - tools = await client.get_tools() - agent = create_react_agent("openai:gpt-4.1", tools) - gcal_response = await agent.ainvoke({"messages": "show me my calendar events for today"}) - print(gcal_response) + tools = await client.get_tools() + agent = create_react_agent("openai:gpt-4.1", tools) + openai_response = await agent.ainvoke({"messages": "get 1 latest email and create a calendar reminder event in next 15 mins for a duration of 15 mins."}) -asyncio.run(main()) + print(openai_response) +if __name__ == "__main__": + asyncio.run(main()) \ No newline at end of file diff --git a/mcp/prompt.py b/mcp/prompt.py deleted file mode 100644 index acd461e..0000000 --- a/mcp/prompt.py +++ /dev/null @@ -1,8 +0,0 @@ -from langchain_core.prompts import SystemMessagePromptTemplate, MessagesPlaceholder, HumanMessagePromptTemplate,PromptTemplate, ChatPromptTemplate - -prompt = ChatPromptTemplate.from_messages([ - SystemMessagePromptTemplate(prompt=PromptTemplate(input_variables=[], template="You are a helpful assistant. Use tools if needed.")), - MessagesPlaceholder(variable_name="chat_history", optional=True), - HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=["input"], template="{input}")), - MessagesPlaceholder(variable_name="agent_scratchpad") -]) diff --git a/mcp/requirements.txt b/mcp/requirements.txt new file mode 100644 index 0000000..64dd606 --- /dev/null +++ b/mcp/requirements.txt @@ -0,0 +1,21 @@ +# ---- Scalekit SDK ---- +scalekit-sdk-python>=2.4.11 + +# ---- LangChain Ecosystem (modular) ---- +langchain-core==0.3.75 +langchain-community==0.3.30 +langchain-openai==0.3.30 +langchain-mcp-adapters==0.1.9 +langgraph==0.6.5 + +# ---- OpenAI + Tokenizer ---- +openai>=1.53.0 +tiktoken>=0.8.0 + +# ---- Environment + Async ---- +python-dotenv>=1.0.1 +asyncio>=3.4.3 + +# ---- Utility dependencies ---- +tenacity>=8.2.3 +requests>=2.32.3 diff --git a/mcp/utils.py b/mcp/utils.py deleted file mode 100644 index 88dd075..0000000 --- a/mcp/utils.py +++ /dev/null @@ -1,24 +0,0 @@ -def authenticate_tool(connect, connection_name, identifier): - - try: - response = connect.get_connected_account( - connection_name=connection_name, - identifier=identifier - ) - if(response.connected_account.status != "ACTIVE"): - print(f"{connection_name} is not connected: {response.connected_account.status}") - link_response = connect.get_authorization_link( - connection_name=connection_name, - identifier=identifier - ) - print(f"πŸ”—click on the link to authorize {connection_name}", link_response.link) - input(f"βŽ† Press Enter after authorizing {connection_name}...") - except Exception as e: - link_response = connect.get_authorization_link( - connection_name=connection_name, - identifier=identifier - ) - print(f"πŸ”— click on the link to authorize {connection_name}", link_response.link) - input(f"βŽ† Press Enter after authorizing {connection_name}...") - - return True \ No newline at end of file