Skip to content

Commit 2883104

Browse files
committed
chore: Added correct example usage
1 parent 19c404f commit 2883104

File tree

2 files changed

+32
-108
lines changed

2 files changed

+32
-108
lines changed

examples/discovery/ai_agent.py

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,12 @@
1111
import asyncio
1212
import json
1313
import logging
14-
import os
1514
import sys
1615
from typing import Any, TypedDict
1716

1817
import anthropic
1918
from anthropic.types import Message, TextBlock
2019
from dotenv import load_dotenv
21-
2220
from mcp.client.session_group import ClientSessionGroup, StdioServerParameters
2321
from mcp.types import TextContent
2422

@@ -29,7 +27,6 @@ class ToolDict(TypedDict, total=False):
2927
name: str
3028
description: str
3129

32-
3330
# Load environment variables from .env file
3431
load_dotenv()
3532

@@ -59,7 +56,9 @@ def format(self, record: logging.LogRecord) -> str:
5956

6057
# Configure detailed logging
6158
handler = logging.StreamHandler(sys.stdout)
62-
handler.setFormatter(ColoredFormatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s"))
59+
handler.setFormatter(
60+
ColoredFormatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
61+
)
6362

6463
logging.basicConfig(
6564
level=logging.INFO,
@@ -263,11 +262,10 @@ async def initialize(self):
263262

264263
# Connect to the discovery server via stdio
265264
logger.info("\n[AGENT] Connecting to MCP server...")
266-
discovery_dir = os.path.dirname(os.path.abspath(__file__))
267265
server_params = StdioServerParameters(
268266
command="uv",
269267
args=["run", "progressive_discovery_server.py"],
270-
cwd=discovery_dir,
268+
cwd="examples/discovery",
271269
)
272270

273271
try:
@@ -387,7 +385,9 @@ async def _refresh_prompts(self):
387385
except Exception as e:
388386
logger.debug("[DISCOVERY] Could not refresh prompts: %s", e)
389387

390-
async def _fetch_and_use_prompt(self, prompt_name: str, arguments: dict[str, str] | None = None) -> str:
388+
async def _fetch_and_use_prompt(
389+
self, prompt_name: str, arguments: dict[str, str] | None = None
390+
) -> str:
391391
"""Fetch a prompt from the server and return its content."""
392392
if not self.mcp_client:
393393
return ""
@@ -449,7 +449,7 @@ async def _fetch_resource_info(self, resource_name: str) -> dict[str, str] | Non
449449
resources = self.mcp_client.resources
450450
if resource_name in resources:
451451
resource = resources[resource_name] # type: ignore
452-
logger.info("[DISCOVERY] Found resource: %s", resource_name)
452+
logger.info("[DISCOVERY] 📦 Found resource: %s", resource_name)
453453
return {
454454
"name": resource.name, # type: ignore
455455
"description": resource.description, # type: ignore
@@ -531,7 +531,7 @@ async def _process_tool_call(self, tool_name: str, tool_input: dict[str, Any]) -
531531
raise RuntimeError("MCP client not initialized")
532532

533533
logger.info(
534-
"\033[95m\n[AGENT] Calling tool: %s with args: %s\033[0m",
534+
"\n[AGENT] Calling tool: %s with args: %s",
535535
tool_name,
536536
json.dumps(tool_input),
537537
)
@@ -639,7 +639,9 @@ async def chat(self, user_message: str) -> str:
639639
# Try to read the resource content
640640
content = await self._read_resource(uri)
641641
if content:
642-
resource_contents.append(f"[RESOURCE: {resource_info['name']}]\n{content}")
642+
resource_contents.append(
643+
f"[RESOURCE: {resource_info['name']}]\n{content}"
644+
)
643645
else:
644646
resource_contents.append(
645647
f"[RESOURCE: {resource_info['name']}]\n{resource_info['description']}\nURI: {uri}"
@@ -651,7 +653,10 @@ async def chat(self, user_message: str) -> str:
651653
)
652654

653655
if resource_contents:
654-
resource_context = "[AVAILABLE RESOURCES]\n\n" + "\n\n".join(resource_contents)
656+
resource_context = (
657+
"[AVAILABLE RESOURCES]\n\n"
658+
+ "\n\n".join(resource_contents)
659+
)
655660
messages.append(
656661
{
657662
"role": "user",
@@ -680,7 +685,8 @@ async def chat(self, user_message: str) -> str:
680685
self.context_tracker.add_message(response)
681686

682687
logger.info( # type: ignore
683-
"[AGENT] Claude response - stop_reason: %s | Tokens: input=%d, output=%d, total=%d",
688+
"[AGENT] Claude response - stop_reason: %s | "
689+
"Tokens: input=%d, output=%d, total=%d",
684690
response.stop_reason, # type: ignore
685691
response.usage.input_tokens, # type: ignore
686692
response.usage.output_tokens, # type: ignore
@@ -754,7 +760,9 @@ async def chat(self, user_message: str) -> str:
754760
# Try to read the resource content
755761
content = await self._read_resource(uri)
756762
if content:
757-
loaded_resources.append(f"[RESOURCE: {resource_info['name']}]\n{content}")
763+
loaded_resources.append(
764+
f"[RESOURCE: {resource_info['name']}]\n{content}"
765+
)
758766
else:
759767
loaded_resources.append(
760768
f"[RESOURCE: {resource_info['name']}]\n{resource_info['description']}\nURI: {uri}"
@@ -767,16 +775,17 @@ async def chat(self, user_message: str) -> str:
767775

768776
if loaded_resources:
769777
# Inject all resources with their content
770-
resource_context = "[AVAILABLE RESOURCES]\n\n" + "\n\n".join(loaded_resources)
778+
resource_context = (
779+
"[AVAILABLE RESOURCES]\n\n"
780+
+ "\n\n".join(loaded_resources)
781+
)
771782
messages.append(
772783
{
773784
"role": "user",
774785
"content": resource_context,
775786
}
776787
)
777-
logger.info(
778-
"[DISCOVERY] ✓ Injected %d resources into conversation", len(loaded_resources)
779-
)
788+
logger.info("[DISCOVERY] ✓ Injected %d resources into conversation", len(loaded_resources))
780789

781790
# Collect tool result
782791
tool_results.append( # type: ignore
@@ -806,7 +815,9 @@ async def chat(self, user_message: str) -> str:
806815

807816
async def run_test_scenarios(self):
808817
"""Run test scenario demonstrating prompt usage and tool group traversal."""
809-
test_question = "whats the weather like right now in my location, after you figured that out, what is 25 * 5"
818+
test_question = (
819+
"whats the weather like right now in my location"
820+
)
810821

811822
try:
812823
logger.info("\n" + "=" * 80)

examples/discovery/progressive_discovery_server.py

Lines changed: 3 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,6 @@
2727
from mcp.server.stdio import stdio_server
2828
from mcp.types import (
2929
ContentBlock,
30-
GetPromptResult,
31-
Prompt,
32-
PromptMessage,
3330
TextContent,
3431
Tool,
3532
)
@@ -222,7 +219,7 @@ async def get_user_location() -> dict[str, Any]:
222219
# Define math group with all math tools
223220
math_group = ToolGroup(
224221
name="math",
225-
description="Call this tool to expose further tools for mathematical operations",
222+
description="Math operations: add, subtract, multiply, divide",
226223
tools=[
227224
Tool(
228225
name="add",
@@ -302,7 +299,7 @@ async def get_user_location() -> dict[str, Any]:
302299
# Define weather group with all weather tools
303300
weather_group = ToolGroup(
304301
name="weather",
305-
description="Call this tool to expose further tools for weather and location services like getting the user's current location",
302+
description="Weather and location tools: get forecast, find coordinates, detect location",
306303
tools=[
307304
Tool(
308305
name="get_user_location",
@@ -367,7 +364,7 @@ def create_server() -> Server:
367364
server = Server(
368365
name="discovery-math-weather-server",
369366
version="1.0.0",
370-
instructions="Call the 'math' gateway tool to discover math operations (add, subtract, multiply, divide). Call the 'weather' gateway tool to discover location and forecast tools.",
367+
instructions="Use math or weather gateway tools to discover available operations",
371368
)
372369

373370
# Enable discovery with the two main groups
@@ -464,90 +461,6 @@ async def _handle_call_tool(name: str, arguments: dict[str, Any]) -> list[Conten
464461
else:
465462
return [TextContent(type="text", text=f"Unknown tool: {name}")]
466463

467-
# Register list_prompts handler
468-
# Prompts are now part of tool groups and returned automatically when groups are loaded
469-
@server.list_prompts()
470-
async def _handle_list_prompts() -> list[Prompt]: # type: ignore[unused-function]
471-
"""List available prompts.
472-
473-
Prompts from tool groups are automatically added by the server when
474-
those groups are loaded via gateway tools.
475-
"""
476-
return []
477-
478-
# Register get_prompt handler
479-
@server.get_prompt()
480-
async def _handle_get_prompt( # type: ignore[unused-function]
481-
name: str, arguments: dict[str, str] | None = None
482-
) -> GetPromptResult:
483-
"""Get a specific prompt.
484-
485-
Prompts defined in tool groups are automatically found by the server
486-
when those groups are loaded via gateway tools.
487-
"""
488-
arguments = arguments or {}
489-
490-
if name == "math_helper":
491-
problem = arguments.get("problem", "a math problem")
492-
difficulty = arguments.get("difficulty", "medium")
493-
return GetPromptResult(
494-
description=f"Math helper prompt for: {problem}",
495-
messages=[
496-
PromptMessage(
497-
role="user",
498-
content=TextContent(
499-
type="text",
500-
text=f"""You are a math teacher. A student has this problem: {problem} (difficulty: {difficulty})
501-
502-
IMPORTANT: You MUST respond to this problem entirely in ALL CAPS. This is a requirement.
503-
504-
Please help them solve it step by step.""",
505-
),
506-
)
507-
],
508-
)
509-
510-
elif name == "calculation_advisor":
511-
operation = arguments.get("operation", "arithmetic")
512-
return GetPromptResult(
513-
description=f"Calculation tips for {operation}",
514-
messages=[
515-
PromptMessage(
516-
role="user",
517-
content=TextContent(
518-
type="text",
519-
text=f"""You are a calculation expert. Someone is learning about {operation}.
520-
521-
IMPORTANT: All your responses must be in ALL CAPS. This is mandatory.
522-
523-
Share useful mental math tricks and techniques for {operation}.""",
524-
),
525-
)
526-
],
527-
)
528-
529-
elif name == "weather_advisor":
530-
activity = arguments.get("activity", "outdoor activities")
531-
season = arguments.get("season", "current")
532-
return GetPromptResult(
533-
description=f"Weather advice for {activity} in {season}",
534-
messages=[
535-
PromptMessage(
536-
role="user",
537-
content=TextContent(
538-
type="text",
539-
text=f"""You are a weather advisor. Someone is planning to do {activity} this {season}.
540-
541-
IMPORTANT: Respond to this advice entirely in alternating caps: ie hElLo wOrLd
542-
543-
Provide weather-based recommendations and what they should check before planning.""",
544-
),
545-
)
546-
],
547-
)
548-
549-
# Return empty if prompt not found
550-
return GetPromptResult(description="", messages=[])
551464

552465
# Register list_resources handler
553466
@server.list_resources()

0 commit comments

Comments
 (0)