Current section
Files
Jump to
Current section
Files
lib/mix/tasks/mcpixir.multi.ex
defmodule Mix.Tasks.Mcpixir.Multi do
@moduledoc """
Demonstrates using Mcpixir with multiple MCP servers at once.
This task shows how to:
1. Configure multiple MCP servers
2. Create and manage sessions for each server
3. Use tools from different servers in a single agent
## Usage
mix mcpixir.multi
## Options
--provider=PROVIDER LLM provider (openai or anthropic, default: anthropic)
--model=MODEL Model to use (default: claude-3-sonnet-20240229 for Anthropic, gpt-4o for OpenAI)
--query=QUERY Query to send to the LLM (default is Barcelona travel query)
--servers=SERVERS Comma-separated list of servers to use (default: "airbnb,playwright,filesystem")
## Examples
mix mcpixir.multi
mix mcpixir.multi --provider=openai
mix mcpixir.multi --servers=airbnb,playwright
"""
use Mix.Task
alias Mcpixir
@shortdoc "Runs a multi-server example with an LLM"
@impl Mix.Task
@spec run([String.t()]) :: :ok
def run(args) do
{opts, _, _} =
OptionParser.parse(args,
strict: [
provider: :string,
model: :string,
query: :string,
servers: :string
]
)
# Load applications
Application.ensure_all_started(:mcpixir)
Application.ensure_all_started(:httpoison)
Application.ensure_all_started(:jason)
# Get LLM provider and model
provider = Keyword.get(opts, :provider, "anthropic")
model = get_default_model(provider, Keyword.get(opts, :model))
query =
Keyword.get(opts, :query, """
Search for a nice place to stay in Barcelona on Airbnb,
then use Google to find nearby restaurants and attractions.
Write the result in the current directory in restaurant.txt
""")
# Parse servers list
servers_str = Keyword.get(opts, :servers, "airbnb,playwright,filesystem")
servers = String.split(servers_str, ",", trim: true)
run_multi_server_example(provider, model, query, servers)
end
defp get_default_model(provider, model) do
if model do
model
else
case provider do
"anthropic" -> "claude-3-sonnet-20240229"
_ -> "gpt-4o"
end
end
end
@spec run_multi_server_example(String.t(), String.t(), String.t(), [String.t()]) :: :ok
defp run_multi_server_example(provider, model, query, servers) do
# Load required API keys
load_api_keys()
# Show banner
IO.puts(IO.ANSI.bright() <> "MCP-Use Multi-Server Example" <> IO.ANSI.reset())
IO.puts("Provider: #{provider}, Model: #{model}")
IO.puts("Servers: #{Enum.join(servers, ", ")}\n")
# Create configuration with selected servers
config = %{
"mcpServers" => create_servers_config(servers)
}
# Create LLM configuration
llm_config = %{
provider: String.to_atom(provider),
model: model
}
IO.puts("Connecting to multiple MCP servers...")
# Create the MCP client
client = Mcpixir.new_client(config)
IO.puts("Creating MCP agent with access to all servers...")
# Create a real agent connected to the LLM with server manager enabled
{:ok, agent} =
Mcpixir.new_agent(%{
llm: llm_config,
client: client,
# Enable dynamic server selection
use_server_manager: true
})
# Run the chat
IO.puts("\nUser query: #{query}")
start_time = :os.system_time(:millisecond)
{:ok, result, _updated_agent} = Mcpixir.run(agent, query)
end_time = :os.system_time(:millisecond)
duration = (end_time - start_time) / 1000
IO.puts("\nResult (completed in #{duration}s):")
IO.puts("------------------------------")
IO.puts(result)
IO.puts("------------------------------")
# Clean up
Mcpixir.Client.stop_all_sessions(client)
end
defp create_servers_config(servers) do
base_configs = %{
"airbnb" => %{
"command" => "npx",
"args" => ["-y", "@openbnb/mcp-server-airbnb", "--ignore-robots-txt"]
},
"playwright" => %{
"command" => "npx",
"args" => ["@playwright/mcp@latest"],
"env" => %{
"DISPLAY" => ":1"
}
},
"filesystem" => %{
"command" => "npx",
"args" => [
"-y",
"@modelcontextprotocol/server-filesystem",
# Use current directory
"."
]
}
}
# Filter for only the requested servers
servers
|> Enum.reduce(%{}, fn server, acc ->
if Map.has_key?(base_configs, server) do
Map.put(acc, server, Map.get(base_configs, server))
else
IO.puts(
IO.ANSI.yellow() <>
"Warning: Unknown server type '#{server}'. Ignoring." <>
IO.ANSI.reset()
)
acc
end
end)
end
defp load_api_keys do
# Check for API keys in environment variables
openai_key = System.get_env("OPENAI_API_KEY")
anthropic_key = System.get_env("ANTHROPIC_API_KEY")
if is_nil(openai_key) do
IO.puts(
IO.ANSI.yellow() <>
"Warning: OPENAI_API_KEY environment variable not set. " <>
"OpenAI models won't work without it." <>
IO.ANSI.reset()
)
end
if is_nil(anthropic_key) do
IO.puts(
IO.ANSI.yellow() <>
"Warning: ANTHROPIC_API_KEY environment variable not set. " <>
"Anthropic models won't work without it." <>
IO.ANSI.reset()
)
end
end
end