Compare commits

...
Author SHA1 Message Date
praisonai-triage-agent[bot]andMervin Praison 4140e499da fix: correct MCP SSE launch, shebang ordering, and E2E helper scripts
- execution_mixin: replace non-existent FastMCP.create_app() with the
  repo's working low-level SSE transport pattern (connect_sse +
  handle_post_message), matching mcp/mcp_server.py; normalize base_path
  leading slash. Fixes AttributeError at MCP server startup.
- examples (36 files): move '# praisonai: skip=true' below the shebang so
  direct execution still works; directive stays within the runner's
  first-30-lines scan.
- failover_example: display real 'last_error' instead of unmodeled
  'failure_count' (which always printed 0).
- scripts/apply_e2e_batch3_*.py: make skip insertion shebang-aware, wire
  the previously-uncalled fix_mcp_env_examples(), and make the E2E report
  path a CLI argument (defaulting to the audit path).

Co-authored-by: Mervin Praison <[email protected]>
2026-07-23 12:10:41 +00:00
40 changed files with 93 additions and 46 deletions

No files matched your search

+1 -1
View File
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""
CI Integration Example - Using Doctor in CI/CD pipelines
+1 -1
View File
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""
PraisonAI Endpoints Example
+1 -1
View File
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""
Fixed example demonstrating proper guardrail usage with PraisonAI Agents.
This addresses the issues reported in issue #875.
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""
ManagedAgent + ClickHouse Persistence — Real conversation with session resume.
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""
ManagedAgent + MongoDB Persistence — Real conversation with session resume.
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""
ManagedAgent + MySQL Persistence — Real conversation with session resume.
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""
ManagedAgent + PostgreSQL Persistence — Real conversation with session resume.
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""
ManagedAgent + Redis Persistence — Real conversation with session resume.
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""
ManagedAgent + SQLite Persistence — Real conversation with session resume.
+1 -1
View File
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""
Custom Tools MCP Server Example
+1 -1
View File
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""
HTTP Stream MCP Server Example
+1 -1
View File
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""
MCP Client Example
+1 -1
View File
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""
Context Agent Example - Basic Usage
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""
Minimal Example: Latency Tracking for MCP Server
+1 -1
View File
@@ -66,7 +66,7 @@ def demonstrate_failover():
print(f" {profile_info.get('name', 'unknown')}:")
print(f" Status: {profile_info.get('status', 'unknown')}")
print(f" Priority: {profile_info.get('priority', 'N/A')}")
print(f" Failures: {profile_info.get('failure_count', 0)}")
print(f" Last error: {profile_info.get('last_error') or 'none'}")
print()
# Get next available profile
+1 -1
View File
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""
Managed Agent Backend Example — Real end-to-end test.
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""
Comprehensive MongoDB Integration Example for PraisonAI Agents
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""
MongoDB Tools Example for PraisonAI Agents
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""
Memory Quality Management Example
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python
# praisonai: skip=true
# coding: utf-8
# # News and Podcast Aggregator Agent using Agents
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""
SearxNG Search Tool Example
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""
AI Brief Generator Example
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""
AI Hook Generator Example
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""
AI News Crawler Example
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""
AI Script Writer Example
+1 -1
View File
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""
Example: LLM-based Recipes
+1 -1
View File
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""
HTTP Recipe Registry Example
+1 -1
View File
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""Run all examples and collect PASS/SKIP/FAIL results."""
import subprocess
import sys
+1 -1
View File
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""
A2A (Agent-to-Agent) Server and Client Example
+1 -1
View File
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""
A2U (Agent-to-User) Event Stream Example
+1 -1
View File
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""
Multi-Agent Router as HTTP API Example
+1 -1
View File
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""
Unified Endpoints Client Example
+1 -1
View File
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""
MCP HTTP Server Example
+1 -1
View File
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""
PraisonAI Recipe Server Example
+1 -1
View File
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""
Tools as MCP Server Example
+1 -1
View File
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""
Unified Server Example
@@ -1,5 +1,5 @@
# praisonai: skip=true
#!/usr/bin/env python3
# praisonai: skip=true
"""
Agent Comparison Test - Run 5 tasks with both wrapper and direct agent
+11 -2
View File
@@ -9,9 +9,15 @@ ROOT = Path(__file__).resolve().parents[1]
def _prepend_skip(rel: str) -> None:
path = ROOT / rel
text = path.read_text(encoding="utf-8")
if "# praisonai: skip=true" in text.splitlines()[:3]:
lines = text.splitlines(keepends=True)
if any("# praisonai: skip=true" in ln for ln in lines[:3]):
return
path.write_text("# praisonai: skip=true\n" + text, encoding="utf-8")
# Preserve a shebang on the first line so direct execution still works.
if lines and lines[0].startswith("#!"):
lines.insert(1, "# praisonai: skip=true\n")
path.write_text("".join(lines), encoding="utf-8")
else:
path.write_text("# praisonai: skip=true\n" + text, encoding="utf-8")
def fix_knowledge_reranker() -> None:
@@ -133,6 +139,9 @@ def main() -> None:
fix_knowledge_reranker()
print("fixed knowledge-reranker")
fix_mcp_env_examples()
print("fixed MCP environment examples")
# advanced-task-management TaskOutput import
p = ROOT / "examples/python/tasks/advanced-task-management.py"
if p.exists():
+20 -3
View File
@@ -1,12 +1,13 @@
"""Apply batch-3 E2E fixes: skip directives for non-runnable examples."""
from __future__ import annotations
import argparse
import json
import re
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
REPORT = Path(__file__).resolve().parents[2] / "PraisonAI-main-e2e" / "examples-e2e-reports" / "post_merge_20260723_132751" / "report.json"
DEFAULT_REPORT = Path(__file__).resolve().parents[2] / "PraisonAI-main-e2e" / "examples-e2e-reports" / "post_merge_20260723_132751" / "report.json"
SKIP_LINE = "# praisonai: skip=true"
SKIP_RE = re.compile(r"^#\s*praisonai:\s*skip\s*=", re.MULTILINE)
@@ -55,13 +56,29 @@ def add_skip(path: Path) -> bool:
text = path.read_text(encoding="utf-8", errors="ignore")
if SKIP_RE.search("\n".join(text.splitlines()[:30])):
return False
new_text = SKIP_LINE + "\n" + text.lstrip("\ufeff")
text = text.lstrip("\ufeff")
lines = text.splitlines(keepends=True)
# Preserve a shebang on the first line so direct execution still works.
if lines and lines[0].startswith("#!"):
lines.insert(1, SKIP_LINE + "\n")
new_text = "".join(lines)
else:
new_text = SKIP_LINE + "\n" + text
path.write_text(new_text, encoding="utf-8")
return True
def main() -> None:
report = json.loads(REPORT.read_text(encoding="utf-8"))
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
"report",
nargs="?",
type=Path,
default=DEFAULT_REPORT,
help="Path to the E2E report.json (defaults to the audit report path).",
)
args = parser.parse_args()
report = json.loads(args.report.read_text(encoding="utf-8"))
targets: set[str] = set()
for it in report.get("results", []):
if it.get("status") in ("failed", "timeout"):
@@ -1640,7 +1640,8 @@ Write the complete compiled report:"""
from mcp.server.fastmcp import FastMCP
from mcp.server.sse import SseServerTransport
from starlette.applications import Starlette
from starlette.routing import Mount
from starlette.requests import Request
from starlette.routing import Mount, Route
import threading
import time
import asyncio
@@ -1667,11 +1668,31 @@ Write the complete compiled report:"""
except Exception as e:
return f"Error executing task: {str(e)}"
# Create and run MCP server
# Create and run MCP server using the low-level SSE transport
# pattern (FastMCP has no create_app(); this mirrors the working
# implementation in praisonaiagents/mcp/mcp_server.py).
base_path = (path or "/mcp").rstrip("/") or "/mcp"
transport = SseServerTransport(f"{base_path}/sse")
if not base_path.startswith("/"):
base_path = f"/{base_path}"
sse_path = f"{base_path}/sse"
messages_path = f"{base_path}/messages/"
transport = SseServerTransport(messages_path)
async def handle_sse(request: Request):
async with transport.connect_sse(
request.scope, request.receive, request._send
) as (read_stream, write_stream):
await mcp._mcp_server.run(
read_stream,
write_stream,
mcp._mcp_server.create_initialization_options()
)
starlette_app = Starlette(
routes=[Mount(base_path, mcp.create_app())]
routes=[
Route(sse_path, endpoint=handle_sse),
Mount(messages_path, app=transport.handle_post_message),
]
)
def run_mcp_server():