Model Context Protocol (MCP) support with new use case (#42)

* initial mcp

* food ordering with mcp

* prompt eng

* splitting out goals and updating docs

* a diff so I can get tests from codex

* a diff so I can get tests from codex

* oops, missing files

* tests, file formatting

* readme and setup updates

* setup.md link fixes

* readme change

* readme change

* readme change

* stripe food setup script

* single agent mode default

* prompt engineering for better multi agent performance

* performance should be greatly improved

* Update goals/finance.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update activities/tool_activities.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* co-pilot PR suggested this change, and now fixed it

* stronger wording around json format response

* formatting

* moved docs to dir

* moved image assets under docs

* cleanup env example, stripe guidance

* cleanup

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Steve Androulakis
2025-06-09 16:39:57 -07:00
committed by GitHub
parent 1811e4cf59
commit 5d55a9fe80
49 changed files with 3268 additions and 279 deletions

View File

@@ -2,7 +2,7 @@ import os
from typing import List
import tools.tool_registry as tool_registry
from models.tool_definitions import AgentGoal
from models.tool_definitions import AgentGoal, MCPServerDefinition
# Turn on Silly Mode - this should be a description of the persona you'd like the bot to have and can be a single word or a phrase.
# Example if you want the bot to be a specific person, like Mario or Christopher Walken, or to describe a specific tone:
@@ -311,7 +311,7 @@ goal_fin_check_account_balances = AgentGoal(
)
# this tool checks account balances, and uses ./data/customer_account_data.json as dummy data
# it also uses a separate workflow/tool, see ./SETUP.md for details
# it also uses a separate workflow/tool, see ./setup.md for details
goal_fin_move_money = AgentGoal(
id="goal_fin_move_money",
category_tag="fin",
@@ -351,7 +351,7 @@ goal_fin_move_money = AgentGoal(
)
# this starts a loan approval process
# it also uses a separate workflow/tool, see ./SETUP.md for details
# it also uses a separate workflow/tool, see ./setup.md for details
goal_fin_loan_application = AgentGoal(
id="goal_fin_loan_application",
category_tag="fin",
@@ -455,6 +455,126 @@ goal_ecomm_list_orders = AgentGoal(
),
)
# ----- MCP Integrations -----
goal_mcp_stripe = AgentGoal(
id="goal_mcp_stripe",
category_tag="mcp-integrations",
agent_name="Stripe MCP Agent",
agent_friendly_description="Manage Stripe operations via MCP",
tools=[], # Will be populated dynamically
mcp_server_definition=MCPServerDefinition(
name="stripe-mcp",
command="npx",
args=[
"-y",
"@stripe/mcp",
"--tools=all",
f"--api-key={os.getenv('STRIPE_API_KEY')}",
],
env=None,
included_tools=["list_customers", "list_products"],
),
description="Help manage Stripe operations for customer and product data by using the customers.read and products.read tools.",
starter_prompt="Welcome! I can help you read Stripe customer and product information.",
example_conversation_history="\n ".join(
[
"agent: Welcome! I can help you read Stripe customer and product information. What would you like to do first?",
"user: what customers are there?",
"agent: I'll check for customers now.",
"user_confirmed_tool_run: <user clicks confirm on customers.read tool>",
'tool_result: { "customers": [{"id": "cus_abc", "name": "Customer A"}, {"id": "cus_xyz", "name": "Customer B"}] }',
"agent: I found two customers: Customer A and Customer B. Can I help with anything else?",
"user: what products exist?",
"agent: Let me get the list of products for you.",
"user_confirmed_tool_run: <user clicks confirm on products.read tool>",
'tool_result: { "products": [{"id": "prod_123", "name": "Gold Plan"}, {"id": "prod_456", "name": "Silver Plan"}] }',
"agent: I found two products: Gold Plan and Silver Plan.",
]
),
)
# ----- Food Ordering Goal -----
goal_food_ordering = AgentGoal(
id="goal_food_ordering",
category_tag="food",
agent_name="Food Ordering Assistant",
agent_friendly_description="Order food from Tony's Pizza Palace using Stripe for payment processing. Browse menu, add items to your order, and check out securely. Please ensure context carries over between tool runs.",
tools=[tool_registry.food_add_to_cart_tool],
mcp_server_definition=MCPServerDefinition(
name="stripe-mcp",
command="npx",
args=[
"-y",
"@stripe/mcp",
"--tools=all",
f"--api-key={os.getenv('STRIPE_API_KEY')}",
],
env=None,
included_tools=[
"list_products",
"list_prices",
"create_customer",
"create_invoice",
"create_invoice_item",
"finalize_invoice",
],
),
description="The user wants to order food from Tony's Pizza Palace. "
"First, help the user browse the menu by calling list_products. "
"When they express interest in items, get pricing using list_prices. "
"Add items to their cart using AddToCart as they decide - the order doesn't matter, multiple items can be added. "
"After they're done selecting items, get their customer details and create a Stripe customer. "
"For checkout: 1) create_invoice, 2) create_invoice_item for each individual item (IMPORTANT: create_invoice_item does NOT accept quantity parameter - call it once per item, so if user wants 2 pizzas, call create_invoice_item twice with the same price), "
"3) finalize_invoice. The finalized invoice will contain a hosted_invoice_url for payment.",
starter_prompt=starter_prompt_generic,
example_conversation_history="\n ".join(
[
"user: I want to order food.",
"agent: Welcome to Tony's Pizza Palace! I can help you browse our menu, add items to your cart, and process payment. Let me show you what we have available.",
"user_confirmed_tool_run: <user clicks confirm on list_products tool with limit=100 and product.metadata.use_case == 'food_ordering_demo'>",
'tool_result: {"products": [{"id": "prod_pepperoni", "name": "Pepperoni Pizza", "description": "A timeless classic featuring pepperoni"}, {"id": "prod_margherita", "name": "Margherita Pizza", "description": "Fresh mozzarella and basil"}, {"id": "prod_garlic_bread", "name": "Garlic Bread", "description": "Warm crusty bread with garlic butter"}, {"id": "prod_soda", "name": "Soda", "description": "A large bottle of cola"}]}',
"agent: We have Pepperoni Pizza, Margherita Pizza, Garlic Bread, and Soda available. What would you like to order?",
"user: I'd like 2 pepperoni pizzas and a soda.",
"agent: Excellent! Let me get the pricing for the pepperoni pizzas first so you know the cost.",
"user_confirmed_tool_run: <user clicks confirm on list_prices tool with product='prod_pepperoni'>",
'tool_result: {"prices": [{"id": "price_pepperoni_large", "product": "prod_pepperoni", "unit_amount": 2299, "currency": "usd"}]}',
"agent: Pepperoni Pizza is $22.99 each. Now let me check the soda pricing:",
"user_confirmed_tool_run: <user clicks confirm on list_prices tool with product='prod_soda'>",
'tool_result: {"prices": [{"id": "price_soda", "product": "prod_soda", "unit_amount": 250, "currency": "usd"}]}',
"agent: And Soda is $2.50. So 2 Pepperoni Pizzas ($22.99 each) plus 1 Soda ($2.50) = $48.48 total. What's your email address to add these items to your cart?",
"user: jane.smith@example.com",
"agent: Perfect! Adding 2 Pepperoni Pizzas to your cart for jane.smith@example.com. Note: I'm using quantity=2 since you want 2 pizzas.",
"user_confirmed_tool_run: <user clicks confirm on AddToCart tool with customer_email='jane.smith@example.com', item_name='Pepperoni Pizza', item_price=22.99, quantity=2, stripe_product_id='prod_pepperoni'>",
'tool_result: {"status": "success", "message": "Added 2 x Pepperoni Pizza ($22.99) to cart for jane.smith@example.com", "item_added": {"quantity": 2, "name": "Pepperoni Pizza"}}',
"agent: Great! Added 2 Pepperoni Pizzas to your cart. Now adding the Soda (quantity=1):",
"user_confirmed_tool_run: <user clicks confirm on AddToCart tool with customer_email='jane.smith@example.com', item_name='Soda', item_price=2.50, quantity=1, stripe_product_id='prod_soda'>",
'tool_result: {"status": "success", "message": "Added 1 x Soda ($2.50) to cart for jane.smith@example.com", "item_added": {"quantity": 1, "name": "Soda"}}',
"agent: Excellent! Your cart now contains: 2 Pepperoni Pizzas ($22.99 each) and 1 Soda ($2.50). Ready to checkout? I'll need your full name.",
"user: Yes, let's proceed with payment. My name is Jane Smith.",
"agent: Thank you Jane! Creating your Stripe customer profile with name and email.",
"user_confirmed_tool_run: <user clicks confirm on create_customer tool with name='Jane Smith' and email='jane.smith@example.com'>",
'tool_result: {"customer": {"id": "cus_ExAmPlE12345", "name": "Jane Smith", "email": "jane.smith@example.com"}}',
"agent: Customer profile created! Now I'll create a draft invoice for your order.",
"user_confirmed_tool_run: <user clicks confirm on create_invoice tool with customer='cus_ExAmPlE12345'>",
'tool_result: {"invoice": {"id": "in_InvOicE54321", "status": "draft", "customer": "cus_ExAmPlE12345"}}',
"agent: Invoice created! Now adding your first Pepperoni Pizza to the invoice.",
"user_confirmed_tool_run: <user clicks confirm on create_invoice_item tool with customer='cus_ExAmPlE12345', invoice='in_InvOicE54321', price='price_pepperoni_large'>",
'tool_result: {"status": "success", "invoice_item": {"id": "ii_pizza1"}}',
"agent: First pizza added! Now adding your second Pepperoni Pizza to the invoice.",
"user_confirmed_tool_run: <user clicks confirm on create_invoice_item tool with customer='cus_ExAmPlE12345', invoice='in_InvOicE54321', price='price_pepperoni_large'>",
'tool_result: {"status": "success", "invoice_item": {"id": "ii_pizza2"}}',
"agent: Both pizzas added! Now adding your Soda to the invoice.",
"user_confirmed_tool_run: <user clicks confirm on create_invoice_item tool with customer='cus_ExAmPlE12345', invoice='in_InvOicE54321', price='price_soda'>",
'tool_result: {"status": "success", "invoice_item": {"id": "ii_soda"}}',
"agent: All items added to invoice! Now finalizing to generate the payment link.",
"user_confirmed_tool_run: <user clicks confirm on finalize_invoice tool with invoice='in_InvOicE54321'>",
'tool_result: {"invoice": {"id": "in_InvOicE54321", "status": "open", "hosted_invoice_url": "https://invoice.stripe.com/i/acct_1NBOLuKVZbzw7QA5/test_YWNjdF8xTkJPTHVLVlpienc3UUE1LF9SbGJlZ2xLMjhlc3lxNzFkVVBXbkswOUlFa2Rna1RxLDEzMDAwMTY4Nw0200RKeJRMlw?s=ap", "amount_due": 4848}}',
"agent: Perfect! Your order is complete with 2 Pepperoni Pizzas and 1 Soda. Total: $48.48. Pay securely here: https://invoice.stripe.com/i/acct_1NBOLuKVZbzw7QA5/test_YWNjdF8xTkJPTHVLVlpienc3UUE1LF9SbGJlZ2xLMjhlc3lxNzFkVVBXbkswOUlFa2Rna1RxLDEzMDAwMTY4Nw0200RKeJRMlw?s=ap\\n\\nThank you for ordering from Tony's Pizza Palace!",
]
),
)
# Add the goals to a list for more generic processing, like listing available agents
goal_list: List[AgentGoal] = []
goal_list.append(goal_choose_agent_type)
@@ -469,19 +589,21 @@ goal_list.append(goal_fin_move_money)
goal_list.append(goal_fin_loan_application)
goal_list.append(goal_ecomm_list_orders)
goal_list.append(goal_ecomm_order_status)
goal_list.append(goal_mcp_stripe)
goal_list.append(goal_food_ordering)
# for multi-goal, just set list agents as the last tool
first_goal_value = os.getenv("AGENT_GOAL")
if first_goal_value is None:
multi_goal_mode = True # default if unset
multi_goal_mode = False # default to single agent mode if unset
elif (
first_goal_value is not None
and first_goal_value.lower() != "goal_choose_agent_type"
and first_goal_value.lower() == "goal_choose_agent_type"
):
multi_goal_mode = False
else:
multi_goal_mode = True
else:
multi_goal_mode = False
if multi_goal_mode:
for goal in goal_list: