# Install required packages
!pip install --upgrade --quiet python-dotenv
!pip install --upgrade --quiet pydantic-ai
!pip install --upgrade --quiet perplexityai
print('✓ Packages installed!')
Slides: from-vibes-to-benchmarks.pdf
import nest_asyncio
from dotenv import load_dotenv
import os
load_dotenv()
nest_asyncio.apply()
# These should all be in .env
# Get your Braintrust API key from https://www.braintrust.dev
os.environ["BRAINTRUST_API_URL"] = "https://api.braintrust.dev"
os.environ["BRAINTRUST_API_KEY"] = ""
os.environ["TAVILY_API_KEY"] = ""
os.environ['ANTHROPIC_API_KEY'] = ''
os.environ['OPENAI_API_KEY'] = ''
os.environ['PERPLEXITY_API_KEY'] = ''
os.environ["PERPLEXITY_API_KEY"] = ""
tavily_key = os.getenv('TAVILY_API_KEY')
import nest_asyncio
from dotenv import load_dotenv
load_dotenv()
nest_asyncio.apply()
import os
os.environ["BRAINTRUST_OTEL_COMPAT"] = "true"
from braintrust.otel import BraintrustSpanProcessor
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
provider = TracerProvider()
trace.set_tracer_provider(provider)
provider.add_span_processor(BraintrustSpanProcessor())
tracer = trace.get_tracer(__name__)
import braintrust
from pydantic_ai import Agent
from pydantic_ai.common_tools.tavily import tavily_search_tool
from pydantic_ai import WebSearchTool, WebSearchUserLocation
from pydantic_ai.mcp import MCPServerStdio
from perplexity import Perplexity
from typing import List, Literal
import json
braintrust.init_logger(project="default-otel-project") # uses API key already in env
Agent.instrument_all()
agent = Agent(
'anthropic:claude-haiku-4-5',
toolsets=[],
)
instructions = f"""
You are a helpful assistant.
"""
prompt = f"""
What files are in the current directory?
"""
result = agent.run_sync(prompt,
instructions=instructions)
print(result.output)
Instead of sharing the output of the command, we're going to let it run the command itself! (kind of.)
We'll use the official reference implementation of a Filesystem MCP. You can find the documentation here.
It explains that we should install? run? it using the following snippet that describes the server:
{
"servers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"${workspaceFolder}"
]
}
}
}
This means we can run npx -y @modelcontextprotocol/server-filesystem output on the command line to start an MCP server, giving it access to the output folder. npx is software that installs and runs node commands without needing to do the typical first npm install -g packagename step.
We need to tweak it to be Pydantic-friendly, which will make it look like this:
file_server = MCPServerStdio(
command="npx",
args=["-y", "@modelcontextprotocol/server-filesystem", "output"]
)
It's literally a direct wrapper around running the command on the command line, it just pipes the input back and forth from Pydantic.
Note: The first time you run
npxit spits out a bunch of "hi! you're installing something!" which makes errors show up in MCP world. I recommend running the command first to test-drive it before you add it to your Python script.
file_server = MCPServerStdio(
command="npx",
args=["-y", "@modelcontextprotocol/server-filesystem", "output"]
)
agent = Agent(
'anthropic:claude-haiku-4-5',
toolsets=[file_server],
)
instructions = f"""
You are a helpful assistant.
"""
prompt = f"""
What files are in the current directory? Explain in detail how you discovered them.
"""
result = agent.run_sync(prompt,
instructions=instructions)
print(result.output)
Now we can add some MCP servers to give a little more power:
Make a note that the PowerPoint one doesn't use npx, but instead uvx. It's more or less the same, it's just Python-y instead of Node.js-y.
ppt_server = MCPServerStdio(
command="XXX",
args=[],
tool_prefix="ppt",
)
agent = Agent(
'anthropic:claude-haiku-4-5',
toolsets=[ppt_server],
retries=5
)
instructions = f"""
You are a helpful assistant.
"""
prompt = f"""
How many slides does this PPT have? Explain how you found out.
Filepath: 05-MCP.pptx
"""
result = agent.run_sync(prompt,
instructions=instructions)
print(result.output)
file_server = MCPServerStdio(
command="npx",
args=["-y", "@modelcontextprotocol/server-filesystem", "output"]
)
# You MUST pass the API key, doesn't matter if it's set in env or not
perplexity_server = MCPServerStdio(
command="npx",
args=["-y", "@perplexity-ai/mcp-server"],
env={
'PERPLEXITY_API_KEY': os.environ.get('PERPLEXITY_API_KEY', '')
}
)
ppt_server = MCPServerStdio(
command="uvx",
args=["--from", "office-powerpoint-mcp-server", "ppt_mcp_server"],
tool_prefix="ppt",
)
markitdown_server = MCPServerStdio(
command="markitdown-mcp",
args=[],
tool_prefix="markitdown",
)
agent = Agent(
'anthropic:claude-haiku-4-5',
toolsets=[file_server, ppt_server, markitdown_server, perplexity_server],
retries=5
)
instructions = f"""
You are provided the path to a PowerPoint file. Your task is to:
1. Analyze the content of the PowerPoint presentation.
2. Summarize the key points and main messages conveyed in the slides.
3. Identify the target audience for the presentation.
4. Take screenshots of the slides to illustrate the content.
5. Perform brief research to find any additional context or information relevant to the presentation topic.
6. Suggest well-cited improvements to enhance clarity, engagement, and visual appeal.
7. Provide follow-up materials such as tutorials or related articles to help the audience better understand the topic.
Save a markdown file called review.md that includes all of the above.
"""
from pydantic import BaseModel
class Powerpoint(BaseModel):
actions_summary: str
powerpoint_visual_description: str
improvements_summary: str
@braintrust.traced
def analyze_powerpoint(path: str):
prompt = f"""
PATH: {path}
"""
result = agent.run_sync(prompt,
instructions=instructions,
output_type=Powerpoint)
output = result.output.model_dump()
return output
path = "05-MCP.pptx"
result = analyze_powerpoint(path)
print(result)