Yash030 commited on
Commit
c31d239
Β·
1 Parent(s): ce886a2

Added Server Fix 5

Browse files
Files changed (1) hide show
  1. src/combined_server.py +105 -73
src/combined_server.py CHANGED
@@ -5,10 +5,12 @@ Runs both the ADK Web UI and the MCP Server on the same FastAPI app.
5
  import os
6
  import uvicorn
7
  import nest_asyncio
8
- from fastapi import FastAPI
9
- from mcp.server.fastmcp import FastMCP
10
  from sse_starlette.sse import EventSourceResponse
11
- from starlette.requests import Request
 
 
 
12
 
13
  # ADK Imports
14
  from google.adk.cli.adk_web_server import (
@@ -16,6 +18,10 @@ from google.adk.cli.adk_web_server import (
16
  BaseCredentialService
17
  )
18
  from google.adk.artifacts import FileArtifactService
 
 
 
 
19
  from src.config import get_session_service, get_memory_service
20
  from src.agents import create_root_agent
21
  from src.utils import logger
@@ -63,10 +69,8 @@ os.makedirs(data_dir, exist_ok=True)
63
 
64
  artifact_service = FileArtifactService(root_dir=os.path.join(data_dir, "artifacts"))
65
  credential_service = LocalCredentialService(base_dir=os.path.join(data_dir, "credentials"))
66
- # Import concrete implementations
67
- from google.adk.evaluation.local_eval_sets_manager import LocalEvalSetsManager
68
- from google.adk.evaluation.local_eval_set_results_manager import LocalEvalSetResultsManager
69
 
 
70
  eval_sets_manager = LocalEvalSetsManager(agents_dir=data_dir)
71
  eval_set_results_manager = LocalEvalSetResultsManager(agents_dir=data_dir)
72
 
@@ -91,76 +95,104 @@ adk_server = AdkWebServer(
91
  # This is the main FastAPI app
92
  app = adk_server.get_fast_api_app()
93
 
94
- # --- 4. Create MCP Server ---
95
 
96
  logger.info("πŸ”Œ Creating MCP Server...")
97
- mcp = FastMCP("AI-Package-Doctor")
98
-
99
- @mcp.tool()
100
- async def solve_dependency_issue(issue_description: str) -> str:
101
- """
102
- Analyzes and resolves Python dependency conflicts based on a description.
103
-
104
- Args:
105
- issue_description: A detailed description of the dependency problem, error logs, or requirements.txt content.
106
- """
107
- from google.adk import Runner
108
- from google.genai import types
109
- import uuid
110
-
111
- session_id = f"mcp-session-{uuid.uuid4()}"
112
- logger.info(f"MCP Tool Called: solve_dependency_issue (Session: {session_id})")
113
-
114
- # Create session
115
- await session_service.create_session(
116
- session_id=session_id,
117
- user_id="mcp_user",
118
- app_name="package_conflict_resolver"
119
- )
120
-
121
- runner = Runner(
122
- agent=root_agent,
123
- app_name="package_conflict_resolver",
124
- session_service=session_service
125
- )
126
-
127
- user_msg = types.Content(
128
- role="user",
129
- parts=[types.Part.from_text(text=issue_description)]
130
- )
131
-
132
- response_text = ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
 
134
- # Run agent and collect response
135
- # Note: This runs synchronously in the async function, blocking this request.
136
- # Ideally we'd stream, but for a simple tool return we collect all.
137
- response_generator = runner.run(
138
- session_id=session_id,
139
- user_id="mcp_user",
140
- new_message=user_msg
141
- )
142
-
143
- for event in response_generator:
144
- if hasattr(event, 'content') and event.content and hasattr(event.content, 'parts'):
145
- if event.content.parts:
146
- text = event.content.parts[0].text
147
- if text and text != "None":
148
- response_text += text
149
- elif hasattr(event, 'text'):
150
- response_text += event.text
151
- elif isinstance(event, str):
152
- response_text += event
153
-
154
- return response_text
155
-
156
- # --- 5. Mount MCP to FastAPI ---
157
-
158
- # FastMCP provides a way to mount itself, but we want to be explicit about the SSE endpoint
159
- # to ensure it works with the existing app.
160
- # We will use the mcp.mount_to_fastapi method if available, or manually add the routes.
161
-
162
- # FastMCP's mount_to_fastapi is the easiest way
163
- mcp.mount_to_fastapi(app, path="/mcp")
164
 
165
  logger.info("βœ… Combined Server Configured")
166
  logger.info("πŸ‘‰ Web UI: http://0.0.0.0:7860/dev-ui/")
 
5
  import os
6
  import uvicorn
7
  import nest_asyncio
8
+ from fastapi import FastAPI, Request
 
9
  from sse_starlette.sse import EventSourceResponse
10
+ from mcp.server import Server
11
+ from mcp.server.sse import SseServerTransport
12
+ from mcp.types import Tool, TextContent, ImageContent, EmbeddedResource
13
+ import mcp.types as types
14
 
15
  # ADK Imports
16
  from google.adk.cli.adk_web_server import (
 
18
  BaseCredentialService
19
  )
20
  from google.adk.artifacts import FileArtifactService
21
+ # Import concrete implementations
22
+ from google.adk.evaluation.local_eval_sets_manager import LocalEvalSetsManager
23
+ from google.adk.evaluation.local_eval_set_results_manager import LocalEvalSetResultsManager
24
+
25
  from src.config import get_session_service, get_memory_service
26
  from src.agents import create_root_agent
27
  from src.utils import logger
 
69
 
70
  artifact_service = FileArtifactService(root_dir=os.path.join(data_dir, "artifacts"))
71
  credential_service = LocalCredentialService(base_dir=os.path.join(data_dir, "credentials"))
 
 
 
72
 
73
+ # Use concrete managers with correct arguments
74
  eval_sets_manager = LocalEvalSetsManager(agents_dir=data_dir)
75
  eval_set_results_manager = LocalEvalSetResultsManager(agents_dir=data_dir)
76
 
 
95
  # This is the main FastAPI app
96
  app = adk_server.get_fast_api_app()
97
 
98
+ # --- 4. Create MCP Server (Standard Implementation) ---
99
 
100
  logger.info("πŸ”Œ Creating MCP Server...")
101
+ mcp_server = Server("AI-Package-Doctor")
102
+
103
+ @mcp_server.list_tools()
104
+ async def handle_list_tools() -> list[types.Tool]:
105
+ return [
106
+ types.Tool(
107
+ name="solve_dependency_issue",
108
+ description="Analyzes and resolves Python dependency conflicts based on a description.",
109
+ inputSchema={
110
+ "type": "object",
111
+ "properties": {
112
+ "issue_description": {
113
+ "type": "string",
114
+ "description": "A detailed description of the dependency problem, error logs, or requirements.txt content."
115
+ }
116
+ },
117
+ "required": ["issue_description"]
118
+ }
119
+ )
120
+ ]
121
+
122
+ @mcp_server.call_tool()
123
+ async def handle_call_tool(name: str, arguments: dict | None) -> list[types.TextContent | types.ImageContent | types.EmbeddedResource]:
124
+ if name == "solve_dependency_issue":
125
+ issue_description = arguments.get("issue_description")
126
+ if not issue_description:
127
+ raise ValueError("Missing issue_description")
128
+
129
+ from google.adk import Runner
130
+ from google.genai import types as genai_types
131
+ import uuid
132
+
133
+ session_id = f"mcp-session-{uuid.uuid4()}"
134
+ logger.info(f"MCP Tool Called: solve_dependency_issue (Session: {session_id})")
135
+
136
+ # Create session
137
+ await session_service.create_session(
138
+ session_id=session_id,
139
+ user_id="mcp_user",
140
+ app_name="package_conflict_resolver"
141
+ )
142
+
143
+ runner = Runner(
144
+ agent=root_agent,
145
+ app_name="package_conflict_resolver",
146
+ session_service=session_service
147
+ )
148
+
149
+ user_msg = genai_types.Content(
150
+ role="user",
151
+ parts=[genai_types.Part.from_text(text=issue_description)]
152
+ )
153
+
154
+ response_text = ""
155
+
156
+ # Run agent and collect response
157
+ response_generator = runner.run(
158
+ session_id=session_id,
159
+ user_id="mcp_user",
160
+ new_message=user_msg
161
+ )
162
+
163
+ for event in response_generator:
164
+ if hasattr(event, 'content') and event.content and hasattr(event.content, 'parts'):
165
+ if event.content.parts:
166
+ text = event.content.parts[0].text
167
+ if text and text != "None":
168
+ response_text += text
169
+ elif hasattr(event, 'text'):
170
+ response_text += event.text
171
+ elif isinstance(event, str):
172
+ response_text += event
173
+
174
+ return [types.TextContent(type="text", text=response_text)]
175
 
176
+ raise ValueError(f"Unknown tool: {name}")
177
+
178
+ # --- 5. Mount MCP SSE Endpoint ---
179
+
180
+ # We need to manage the SSE transport manually
181
+ sse_transport = SseServerTransport("/mcp/messages")
182
+
183
+ @app.get("/mcp/sse")
184
+ async def handle_sse(request: Request):
185
+ async with mcp_server.run_sse(sse_transport) as streams:
186
+ async def event_generator():
187
+ async for message in streams[1]:
188
+ yield message
189
+
190
+ return EventSourceResponse(event_generator())
191
+
192
+ @app.post("/mcp/messages")
193
+ async def handle_messages(request: Request):
194
+ await sse_transport.handle_post_message(request.scope, request.receive, request._send)
195
+ return {}
 
 
 
 
 
 
 
 
 
 
196
 
197
  logger.info("βœ… Combined Server Configured")
198
  logger.info("πŸ‘‰ Web UI: http://0.0.0.0:7860/dev-ui/")