-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Add MCP integration for stock price retrieval #429
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| from praisonaiagents import Agent, MCP | ||
|
|
||
| agent = Agent( | ||
| instructions="""You are a helpful assistant that can check stock prices and perform other tasks. | ||
| Use the available tools when relevant to answer user questions.""", | ||
| llm="gpt-4o-mini", | ||
| tools=MCP( | ||
| command="/Users/praison/miniconda3/envs/mcp/bin/python", | ||
| args=["/Users/praison/stockprice/app.py"] | ||
| ) | ||
| ) | ||
|
|
||
| agent.start("What is the stock price of Tesla?") | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,10 @@ | ||||||
| from praisonaiagents import Agent, MCP | ||||||
|
|
||||||
| agent = Agent( | ||||||
| instructions="""You are a helpful assistant that can check stock prices and perform other tasks. | ||||||
| Use the available tools when relevant to answer user questions.""", | ||||||
| llm="gpt-4o-mini", | ||||||
| tools = MCP("/Users/praison/miniconda3/envs/mcp/bin/python /Users/praison/stockprice/app.py") | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This path is hardcoded. Consider using environment variables or a configuration file to make this more configurable and portable.
Suggested change
|
||||||
| ) | ||||||
|
|
||||||
| agent.start("What is the stock price of Tesla?") | ||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,61 @@ | ||||||||||||||||||
| import asyncio | ||||||||||||||||||
| from praisonaiagents import Agent | ||||||||||||||||||
| from mcp import ClientSession, StdioServerParameters | ||||||||||||||||||
| from mcp.client.stdio import stdio_client | ||||||||||||||||||
|
|
||||||||||||||||||
| # Define server configuration - pointing to your stock price app | ||||||||||||||||||
| server_params = StdioServerParameters( | ||||||||||||||||||
| command="/Users/praison/miniconda3/envs/mcp/bin/python", | ||||||||||||||||||
| args=[ | ||||||||||||||||||
| "/Users/praison/stockprice/app.py", | ||||||||||||||||||
| ], | ||||||||||||||||||
|
Comment on lines
+8
to
+11
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These paths are hardcoded. Consider using environment variables or a configuration file to make this more configurable and portable.
Suggested change
|
||||||||||||||||||
| ) | ||||||||||||||||||
|
|
||||||||||||||||||
| # Function to get stock price using MCP | ||||||||||||||||||
| async def get_stock_price(symbol): | ||||||||||||||||||
| # Start server and connect client | ||||||||||||||||||
| async with stdio_client(server_params) as (read, write): | ||||||||||||||||||
| async with ClientSession(read, write) as session: | ||||||||||||||||||
| # Initialize the connection | ||||||||||||||||||
| await session.initialize() | ||||||||||||||||||
|
|
||||||||||||||||||
| # Get tools | ||||||||||||||||||
| tools_result = await session.list_tools() | ||||||||||||||||||
| tools = tools_result.tools | ||||||||||||||||||
| print(f"Available tools: {[tool.name for tool in tools]}") | ||||||||||||||||||
|
|
||||||||||||||||||
| # Find a tool that can get stock prices | ||||||||||||||||||
| # Assuming there's a tool like "get_stock_price" or similar | ||||||||||||||||||
| stock_tool = None | ||||||||||||||||||
| for tool in tools: | ||||||||||||||||||
| if "stock" in tool.name.lower() or "price" in tool.name.lower(): | ||||||||||||||||||
| stock_tool = tool | ||||||||||||||||||
| break | ||||||||||||||||||
|
Comment on lines
+30
to
+33
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This tool discovery mechanism is not very robust. It relies on string matching, which could lead to incorrect tool selection. A more reliable method would be to use tool schemas or annotations to identify the correct tool. # Find a tool that can get stock prices based on schema or annotations
stock_tool = next((tool for tool in tools if tool.inputSchema and "ticker" in tool.inputSchema.get("properties", {})), None) |
||||||||||||||||||
|
|
||||||||||||||||||
| if stock_tool: | ||||||||||||||||||
| print(f"Using tool: {stock_tool.name}") | ||||||||||||||||||
| # Call the tool with the stock symbol | ||||||||||||||||||
| result = await session.call_tool( | ||||||||||||||||||
| stock_tool.name, | ||||||||||||||||||
| arguments={"ticker": symbol} | ||||||||||||||||||
| ) | ||||||||||||||||||
| return result | ||||||||||||||||||
| else: | ||||||||||||||||||
| return "No suitable stock price tool found" | ||||||||||||||||||
|
|
||||||||||||||||||
| # Create a custom tool for the agent | ||||||||||||||||||
| def stock_price_tool(symbol: str) -> str: | ||||||||||||||||||
| """Get the current stock price for a given symbol""" | ||||||||||||||||||
| # Run the async function to get the stock price | ||||||||||||||||||
| result = asyncio.run(get_stock_price(symbol)) | ||||||||||||||||||
| return f"Stock price for {symbol}: {result}" | ||||||||||||||||||
|
Comment on lines
+47
to
+51
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using # Run the async function to get the stock price
loop = asyncio.get_event_loop()
result = loop.run_until_complete(get_stock_price(symbol))
return f"Stock price for {symbol}: {result}" |
||||||||||||||||||
|
|
||||||||||||||||||
| # Create agent with the stock price tool | ||||||||||||||||||
| agent = Agent( | ||||||||||||||||||
| instructions="You are a helpful assistant that can check stock prices. When asked about stock prices, use the stock_price_tool.", | ||||||||||||||||||
| llm="gpt-4o-mini", | ||||||||||||||||||
| tools=[stock_price_tool] | ||||||||||||||||||
| ) | ||||||||||||||||||
|
|
||||||||||||||||||
| # Start the agent | ||||||||||||||||||
| agent.start("What is the stock price of Tesla?") | ||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,23 @@ | ||||||||||
| from praisonaiagents import Agent, MCP | ||||||||||
| import os | ||||||||||
| stock_agent = Agent( | ||||||||||
| instructions="""You are a helpful assistant that can check stock prices and perform other tasks. | ||||||||||
| Use the available tools when relevant to answer user questions.""", | ||||||||||
| llm="gpt-4o-mini", | ||||||||||
| tools=MCP( | ||||||||||
| command="/Users/praison/miniconda3/envs/mcp/bin/python", | ||||||||||
| args=["/Users/praison/stockprice/app.py"] | ||||||||||
|
Comment on lines
+8
to
+9
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The command and args are hardcoded. Consider using environment variables or a configuration file to make this more configurable and portable.
Suggested change
|
||||||||||
| ) | ||||||||||
| ) | ||||||||||
|
|
||||||||||
| brave_api_key = os.getenv("BRAVE_API_KEY") | ||||||||||
|
|
||||||||||
| search_agent = Agent( | ||||||||||
| instructions="""You are a helpful assistant that can search the web for information. | ||||||||||
| Use the available tools when relevant to answer user questions.""", | ||||||||||
| llm="gpt-4o-mini", | ||||||||||
| tools=MCP(f'npx -y @smithery/cli@latest install @smithery-ai/brave-search --client claude --config "{{\\\"braveApiKey\\\":\\\"{brave_api_key}\\\"}}"') | ||||||||||
| ) | ||||||||||
|
|
||||||||||
| stock_agent.start("What is the stock price of Tesla?") | ||||||||||
| search_agent.start("Search more information about Praison AI") | ||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| from praisonaiagents import Agent | ||
|
|
||
| import npx_mcp_wrapper_main | ||
|
|
||
| search_agent = Agent( | ||
| instructions="""You help book apartments on Airbnb.""", | ||
| llm="gpt-4o-mini", | ||
| tools=npx_mcp_wrapper_main.MCP( | ||
| command="npx", | ||
| args=[ | ||
| "-y", | ||
| "@openbnb/mcp-server-airbnb", | ||
| "--ignore-robots-txt", | ||
| ] | ||
| ) | ||
| ) | ||
|
|
||
| search_agent.start("I want to book an apartment in Paris for 2 nights. 03/28 - 03/30 for 2 adults") |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| from praisonaiagents import Agent, MCP | ||
|
|
||
| search_agent = Agent( | ||
| instructions="""You help book apartments on Airbnb.""", | ||
| llm="gpt-4o-mini", | ||
| tools=MCP( | ||
| command="npx", | ||
| args=[ | ||
| "-y", | ||
| "@openbnb/mcp-server-airbnb", | ||
| "--ignore-robots-txt", | ||
| ] | ||
| ) | ||
| ) | ||
|
|
||
| search_agent.start("I want to book an apartment in Paris for 2 nights. 03/28 - 03/30 for 2 adults") | ||
|
|
||
| agent = Agent( | ||
| instructions="""You are a helpful assistant that can check stock prices and perform other tasks. | ||
| Use the available tools when relevant to answer user questions.""", | ||
| llm="gpt-4o-mini", | ||
| tools = MCP("/Users/praison/miniconda3/envs/mcp/bin/python /Users/praison/stockprice/app.py") | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove hardcoded absolute paths Using absolute paths specific to a user's system will prevent the code from working on other machines. Consider using relative paths or environment variables. - tools = MCP("/Users/praison/miniconda3/envs/mcp/bin/python /Users/praison/stockprice/app.py")
+ tools = MCP("python", args=["stockprice/app.py"])Alternatively, use environment variables: import os
...
python_path = os.environ.get("MCP_PYTHON_PATH", "python")
app_path = os.environ.get("STOCKPRICE_APP_PATH", "stockprice/app.py")
tools = MCP(python_path, args=[app_path]) |
||
| ) | ||
|
|
||
| agent.start("What is the stock price of Tesla?") | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| from praisonaiagents import Agent, MCP | ||
|
|
||
| search_agent = Agent( | ||
| instructions="""You help book apartments on Airbnb.""", | ||
| llm="gpt-4o-mini", | ||
| tools=MCP( | ||
| command="npx", | ||
| args=[ | ||
| "-y", | ||
| "@openbnb/mcp-server-airbnb", | ||
| "--ignore-robots-txt", | ||
| ] | ||
| ) | ||
| ) | ||
|
|
||
| search_agent.start("I want to book an apartment in Paris for 2 nights. 03/28 - 03/30 for 2 adults") |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| from praisonaiagents import Agent, MCP | ||
|
|
||
| search_agent = Agent( | ||
| instructions="""You are a helpful assistant that can search the web for information. | ||
| Use the available tools when relevant to answer user questions.""", | ||
| llm="gpt-4o-mini", | ||
| tools=MCP( | ||
| command="npx", | ||
| args=[ | ||
| "-y", | ||
| "@smithery/cli@latest", | ||
| "install", | ||
| "@smithery-ai/brave-search", | ||
| "--client", | ||
| "claude", | ||
| "--config", | ||
| '{"braveApiKey":"BSANfDaqLKO9wq7e08mrPth9ZlJvKtc"}' | ||
| ], | ||
| timeout=30, # 3 minutes for brave-search | ||
| debug=True # Enable detailed logging | ||
| ) | ||
| ) | ||
|
|
||
| search_agent.start("Search more information about Praison AI") |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| from google import genai | ||
| from google.genai import types | ||
| from mcp import ClientSession, StdioServerParameters | ||
| from mcp.client.stdio import stdio_client | ||
| import os | ||
|
|
||
| client = genai.Client( | ||
| api_key=os.getenv("GEMINI_API_KEY") | ||
| ) # Replace with your actual API key setup | ||
|
|
||
|
|
||
| # Create server parameters for stdio connection | ||
| server_params = StdioServerParameters( | ||
| command="npx", # Executable | ||
| args=[ | ||
| "-y", | ||
| "@openbnb/mcp-server-airbnb", | ||
| "--ignore-robots-txt", | ||
| ], # Optional command line arguments | ||
| env=None, # Optional environment variables | ||
| ) | ||
|
|
||
| async def run(): | ||
| async with stdio_client(server_params) as (read, write): | ||
| async with ClientSession( | ||
| read, | ||
| write, | ||
| ) as session: | ||
| prompt = "I want to book an apartment in Paris for 2 nights. 03/28 - 03/30" | ||
| # Initialize the connection | ||
| await session.initialize() | ||
|
|
||
| # Get tools from MCP session and convert to Gemini Tool objects | ||
| mcp_tools = await session.list_tools() | ||
| tools = types.Tool(function_declarations=[ | ||
| { | ||
| "name": tool.name, | ||
| "description": tool.description, | ||
| "parameters": tool.inputSchema, | ||
| } | ||
| for tool in mcp_tools.tools | ||
| ]) | ||
|
|
||
| # Send request with function declarations | ||
| response = client.models.generate_content( | ||
| model="gemini-2.0-flash", # Or your preferred model supporting function calling | ||
| contents=prompt, | ||
| config=types.GenerateContentConfig( | ||
| temperature=0.7, | ||
| tools=[tools], | ||
| ), # Example other config | ||
| ) | ||
| # Check for a function call | ||
| if response.candidates[0].content.parts[0].function_call: | ||
| function_call = response.candidates[0].content.parts[0].function_call | ||
| print(f"Function to call: {function_call.name}") | ||
| print(f"Arguments: {function_call.args}") | ||
| # In a real app, you would call your function here: | ||
| # result = await session.call_tool(function_call.args, arguments=function_call.args) | ||
| # sent new request with function call | ||
| else: | ||
| print("No function call found in the response.") | ||
| print(response.text) | ||
|
|
||
| if __name__ == "__main__": | ||
| import asyncio | ||
| asyncio.run(run()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The command and args are hardcoded. Consider using environment variables or a configuration file to make this more configurable and portable.