60e0ffc959
Upgrade checks / Notify on failure (push) Has been cancelled
Upgrade checks / Close issue on success (push) Has been cancelled
Schema Crash Test / Real-world schema crash test (232K schemas) (push) Has been cancelled
Run static analysis / static_analysis (push) Has been cancelled
Tests / Tests: Python 3.10 on ubuntu-latest (push) Has been cancelled
Tests / Tests: Python 3.13 on ubuntu-latest (push) Has been cancelled
Tests / Tests: Python 3.10 on windows-latest (push) Has been cancelled
Tests / Tests with lowest-direct dependencies (push) Has been cancelled
Tests / MCP conformance tests (push) Has been cancelled
Tests / Integration tests (push) Has been cancelled
Tests / Package install smoke (push) Has been cancelled
Upgrade checks / Static analysis (push) Has been cancelled
Upgrade checks / Tests: Python 3.10 on ubuntu-latest (push) Has been cancelled
Upgrade checks / Tests: Python 3.13 on ubuntu-latest (push) Has been cancelled
Upgrade checks / Tests: Python 3.10 on windows-latest (push) Has been cancelled
Upgrade checks / Integration tests (push) Has been cancelled
Update MCPServerConfig Schema / update-config-schema (push) Has been cancelled
Update SDK Documentation / update-sdk-docs (push) Has been cancelled
162 lines
5.7 KiB
Python
162 lines
5.7 KiB
Python
#!/usr/bin/env python
|
|
"""Client script to exercise all diagnostics server components with tracing.
|
|
|
|
Usage:
|
|
# First, start the diagnostics server with tracing in one terminal:
|
|
uv run examples/run_with_tracing.py examples/diagnostics/server.py --transport sse --port 8001
|
|
|
|
# Then run this client in another terminal:
|
|
uv run examples/diagnostics/client_with_tracing.py
|
|
|
|
# View traces in otel-desktop-viewer (http://localhost:8000):
|
|
otel-desktop-viewer
|
|
|
|
This script exercises all 8 components:
|
|
- 4 successful: ping, diag://status, diag://echo/{message}, greet prompt
|
|
- 4 error: fail_tool, diag://error, diag://error/{code}, fail prompt
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
import os
|
|
|
|
# Configure OTEL SDK before importing fastmcp
|
|
from opentelemetry import trace
|
|
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
|
|
from opentelemetry.sdk.resources import Resource
|
|
from opentelemetry.sdk.trace import TracerProvider
|
|
from opentelemetry.sdk.trace.export import BatchSpanProcessor
|
|
|
|
|
|
def setup_tracing():
|
|
"""Set up OpenTelemetry tracing with OTLP export."""
|
|
endpoint = os.environ.get("OTEL_EXPORTER_OTLP_ENDPOINT", "http://localhost:4317")
|
|
service_name = os.environ.get("OTEL_SERVICE_NAME", "fastmcp-diagnostics-client")
|
|
|
|
resource = Resource.create({"service.name": service_name})
|
|
provider = TracerProvider(resource=resource)
|
|
exporter = OTLPSpanExporter(endpoint=endpoint, insecure=True)
|
|
provider.add_span_processor(BatchSpanProcessor(exporter))
|
|
trace.set_tracer_provider(provider)
|
|
|
|
print(f"Tracing enabled: OTLP {endpoint}")
|
|
print(f"Service: {service_name}")
|
|
print("View traces: otel-desktop-viewer (http://localhost:8000)\n")
|
|
|
|
|
|
async def main():
|
|
setup_tracing()
|
|
|
|
from fastmcp import Client
|
|
|
|
server_url = os.environ.get("DIAGNOSTICS_SERVER_URL", "http://localhost:8001/sse")
|
|
print(f"Connecting to: {server_url}\n")
|
|
|
|
async with Client(server_url) as client:
|
|
# List all available components
|
|
tools = await client.list_tools()
|
|
resources = await client.list_resources()
|
|
prompts = await client.list_prompts()
|
|
|
|
print(f"Found {len(tools)} tools: {[t.name for t in tools]}")
|
|
print(f"Found {len(resources)} resources: {[r.uri for r in resources]}")
|
|
print(f"Found {len(prompts)} prompts: {[p.name for p in prompts]}\n")
|
|
|
|
# === SUCCESSFUL OPERATIONS ===
|
|
print("=" * 60)
|
|
print("SUCCESSFUL OPERATIONS")
|
|
print("=" * 60)
|
|
|
|
# Local successful components
|
|
print("\n--- Local Tools ---")
|
|
result = await client.call_tool("ping", {})
|
|
print(f"ping: {result}")
|
|
|
|
print("\n--- Local Resources ---")
|
|
result = await client.read_resource("diag://status")
|
|
print(f"diag://status: {result}")
|
|
|
|
result = await client.read_resource("diag://echo/hello-world")
|
|
print(f"diag://echo/hello-world: {result}")
|
|
|
|
print("\n--- Local Prompts ---")
|
|
result = await client.get_prompt("greet", {"name": "Diagnostics"})
|
|
print(
|
|
f"greet: {result.messages[0].content.text if result.messages else result}"
|
|
)
|
|
|
|
# Proxied components from echo server
|
|
print("\n--- Proxied Tools ---")
|
|
try:
|
|
result = await client.call_tool(
|
|
"proxied_echo_tool", {"text": "proxied test"}
|
|
)
|
|
print(f"proxied_echo_tool: {result}")
|
|
except Exception as e:
|
|
print(f"proxied_echo_tool: ERROR - {e}")
|
|
|
|
print("\n--- Proxied Resources ---")
|
|
try:
|
|
# Resource: echo://static -> echo://proxied/static
|
|
result = await client.read_resource("echo://proxied/static")
|
|
print(f"echo://proxied/static: {result}")
|
|
except Exception as e:
|
|
print(f"echo://proxied/static: ERROR - {e}")
|
|
|
|
try:
|
|
# Template: echo://{text} -> echo://proxied/{text}
|
|
result = await client.read_resource("echo://proxied/test-message")
|
|
print(f"echo://proxied/test-message: {result}")
|
|
except Exception as e:
|
|
print(f"echo://proxied/test-message: ERROR - {e}")
|
|
|
|
print("\n--- Proxied Prompts ---")
|
|
try:
|
|
result = await client.get_prompt("proxied_echo", {"text": "proxied prompt"})
|
|
print(
|
|
f"proxied_echo: {result.messages[0].content.text if result.messages else result}"
|
|
)
|
|
except Exception as e:
|
|
print(f"proxied_echo: ERROR - {e}")
|
|
|
|
# === ERROR OPERATIONS ===
|
|
print("\n" + "=" * 60)
|
|
print("ERROR OPERATIONS (expected to fail)")
|
|
print("=" * 60)
|
|
|
|
print("\n--- Error Tools ---")
|
|
try:
|
|
await client.call_tool("fail_tool", {})
|
|
print("fail_tool: UNEXPECTED SUCCESS")
|
|
except Exception as e:
|
|
print(f"fail_tool: {type(e).__name__} - {e}")
|
|
|
|
print("\n--- Error Resources ---")
|
|
try:
|
|
await client.read_resource("diag://error")
|
|
print("diag://error: UNEXPECTED SUCCESS")
|
|
except Exception as e:
|
|
print(f"diag://error: {type(e).__name__} - {e}")
|
|
|
|
try:
|
|
await client.read_resource("diag://error/500")
|
|
print("diag://error/500: UNEXPECTED SUCCESS")
|
|
except Exception as e:
|
|
print(f"diag://error/500: {type(e).__name__} - {e}")
|
|
|
|
print("\n--- Error Prompts ---")
|
|
try:
|
|
await client.get_prompt("fail", {})
|
|
print("fail: UNEXPECTED SUCCESS")
|
|
except Exception as e:
|
|
print(f"fail: {type(e).__name__} - {e}")
|
|
|
|
print("\n" + "=" * 60)
|
|
print("DONE - Check otel-desktop-viewer for traces")
|
|
print("=" * 60)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
asyncio.run(main())
|