ouroboros-ai 0.2.3__py3-none-any.whl → 0.4.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ouroboros-ai might be problematic. Click here for more details.

Files changed (44) hide show
  1. ouroboros/__init__.py +1 -1
  2. ouroboros/bigbang/__init__.py +9 -0
  3. ouroboros/bigbang/interview.py +16 -18
  4. ouroboros/bigbang/ontology.py +180 -0
  5. ouroboros/cli/commands/__init__.py +2 -0
  6. ouroboros/cli/commands/init.py +162 -97
  7. ouroboros/cli/commands/mcp.py +161 -0
  8. ouroboros/cli/commands/run.py +165 -27
  9. ouroboros/cli/main.py +2 -1
  10. ouroboros/core/ontology_aspect.py +455 -0
  11. ouroboros/core/ontology_questions.py +462 -0
  12. ouroboros/evaluation/__init__.py +16 -1
  13. ouroboros/evaluation/consensus.py +569 -11
  14. ouroboros/evaluation/models.py +81 -0
  15. ouroboros/events/ontology.py +135 -0
  16. ouroboros/mcp/__init__.py +83 -0
  17. ouroboros/mcp/client/__init__.py +20 -0
  18. ouroboros/mcp/client/adapter.py +632 -0
  19. ouroboros/mcp/client/manager.py +600 -0
  20. ouroboros/mcp/client/protocol.py +161 -0
  21. ouroboros/mcp/errors.py +377 -0
  22. ouroboros/mcp/resources/__init__.py +22 -0
  23. ouroboros/mcp/resources/handlers.py +328 -0
  24. ouroboros/mcp/server/__init__.py +21 -0
  25. ouroboros/mcp/server/adapter.py +408 -0
  26. ouroboros/mcp/server/protocol.py +291 -0
  27. ouroboros/mcp/server/security.py +636 -0
  28. ouroboros/mcp/tools/__init__.py +24 -0
  29. ouroboros/mcp/tools/definitions.py +351 -0
  30. ouroboros/mcp/tools/registry.py +269 -0
  31. ouroboros/mcp/types.py +333 -0
  32. ouroboros/orchestrator/__init__.py +31 -0
  33. ouroboros/orchestrator/events.py +40 -0
  34. ouroboros/orchestrator/mcp_config.py +419 -0
  35. ouroboros/orchestrator/mcp_tools.py +483 -0
  36. ouroboros/orchestrator/runner.py +119 -2
  37. ouroboros/providers/claude_code_adapter.py +75 -0
  38. ouroboros/strategies/__init__.py +23 -0
  39. ouroboros/strategies/devil_advocate.py +197 -0
  40. {ouroboros_ai-0.2.3.dist-info → ouroboros_ai-0.4.0.dist-info}/METADATA +73 -17
  41. {ouroboros_ai-0.2.3.dist-info → ouroboros_ai-0.4.0.dist-info}/RECORD +44 -19
  42. {ouroboros_ai-0.2.3.dist-info → ouroboros_ai-0.4.0.dist-info}/WHEEL +0 -0
  43. {ouroboros_ai-0.2.3.dist-info → ouroboros_ai-0.4.0.dist-info}/entry_points.txt +0 -0
  44. {ouroboros_ai-0.2.3.dist-info → ouroboros_ai-0.4.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,408 @@
1
+ """MCP Server adapter implementation.
2
+
3
+ This module provides the MCPServerAdapter class that implements the MCPServer
4
+ protocol using the MCP SDK (FastMCP). It handles tool registration, resource
5
+ handling, and server lifecycle.
6
+ """
7
+
8
+ import asyncio
9
+ from collections.abc import Sequence
10
+ from typing import Any
11
+
12
+ import structlog
13
+
14
+ from ouroboros.core.types import Result
15
+ from ouroboros.mcp.errors import (
16
+ MCPResourceNotFoundError,
17
+ MCPServerError,
18
+ MCPToolError,
19
+ )
20
+ from ouroboros.mcp.server.protocol import PromptHandler, ResourceHandler, ToolHandler
21
+ from ouroboros.mcp.server.security import AuthConfig, RateLimitConfig, SecurityLayer
22
+ from ouroboros.mcp.types import (
23
+ MCPCapabilities,
24
+ MCPPromptDefinition,
25
+ MCPResourceContent,
26
+ MCPResourceDefinition,
27
+ MCPServerInfo,
28
+ MCPToolDefinition,
29
+ MCPToolResult,
30
+ )
31
+
32
+ log = structlog.get_logger(__name__)
33
+
34
+
35
+ class MCPServerAdapter:
36
+ """Concrete implementation of MCPServer protocol.
37
+
38
+ Uses the MCP SDK to expose Ouroboros functionality as an MCP server.
39
+ Supports tool registration, resource handling, and optional security.
40
+
41
+ Example:
42
+ server = MCPServerAdapter(
43
+ name="ouroboros-mcp",
44
+ version="1.0.0",
45
+ )
46
+
47
+ # Register handlers
48
+ server.register_tool(ExecuteSeedHandler())
49
+ server.register_resource(SessionResourceHandler())
50
+
51
+ # Start serving
52
+ await server.serve()
53
+ """
54
+
55
+ def __init__(
56
+ self,
57
+ *,
58
+ name: str = "ouroboros-mcp",
59
+ version: str = "1.0.0",
60
+ auth_config: AuthConfig | None = None,
61
+ rate_limit_config: RateLimitConfig | None = None,
62
+ ) -> None:
63
+ """Initialize the server adapter.
64
+
65
+ Args:
66
+ name: Server name for identification.
67
+ version: Server version.
68
+ auth_config: Optional authentication configuration.
69
+ rate_limit_config: Optional rate limiting configuration.
70
+ """
71
+ self._name = name
72
+ self._version = version
73
+ self._tool_handlers: dict[str, ToolHandler] = {}
74
+ self._resource_handlers: dict[str, ResourceHandler] = {}
75
+ self._prompt_handlers: dict[str, PromptHandler] = {}
76
+ self._mcp_server: Any = None
77
+
78
+ # Initialize security layer
79
+ self._security = SecurityLayer(
80
+ auth_config=auth_config or AuthConfig(),
81
+ rate_limit_config=rate_limit_config or RateLimitConfig(),
82
+ )
83
+
84
+ @property
85
+ def info(self) -> MCPServerInfo:
86
+ """Return server information."""
87
+ return MCPServerInfo(
88
+ name=self._name,
89
+ version=self._version,
90
+ capabilities=MCPCapabilities(
91
+ tools=len(self._tool_handlers) > 0,
92
+ resources=len(self._resource_handlers) > 0,
93
+ prompts=len(self._prompt_handlers) > 0,
94
+ logging=True,
95
+ ),
96
+ tools=tuple(h.definition for h in self._tool_handlers.values()),
97
+ resources=tuple(
98
+ defn
99
+ for handler in self._resource_handlers.values()
100
+ for defn in handler.definitions
101
+ ),
102
+ prompts=tuple(h.definition for h in self._prompt_handlers.values()),
103
+ )
104
+
105
+ def register_tool(self, handler: ToolHandler) -> None:
106
+ """Register a tool handler.
107
+
108
+ Args:
109
+ handler: The tool handler to register.
110
+ """
111
+ name = handler.definition.name
112
+ self._tool_handlers[name] = handler
113
+ log.info("mcp.server.tool_registered", tool=name)
114
+
115
+ def register_resource(self, handler: ResourceHandler) -> None:
116
+ """Register a resource handler.
117
+
118
+ Args:
119
+ handler: The resource handler to register.
120
+ """
121
+ for defn in handler.definitions:
122
+ self._resource_handlers[defn.uri] = handler
123
+ log.info("mcp.server.resource_registered", uri=defn.uri)
124
+
125
+ def register_prompt(self, handler: PromptHandler) -> None:
126
+ """Register a prompt handler.
127
+
128
+ Args:
129
+ handler: The prompt handler to register.
130
+ """
131
+ name = handler.definition.name
132
+ self._prompt_handlers[name] = handler
133
+ log.info("mcp.server.prompt_registered", prompt=name)
134
+
135
+ async def list_tools(self) -> Sequence[MCPToolDefinition]:
136
+ """List all registered tools.
137
+
138
+ Returns:
139
+ Sequence of tool definitions.
140
+ """
141
+ return tuple(h.definition for h in self._tool_handlers.values())
142
+
143
+ async def list_resources(self) -> Sequence[MCPResourceDefinition]:
144
+ """List all registered resources.
145
+
146
+ Returns:
147
+ Sequence of resource definitions.
148
+ """
149
+ # Collect unique definitions from all handlers
150
+ seen_uris: set[str] = set()
151
+ definitions: list[MCPResourceDefinition] = []
152
+
153
+ for handler in self._resource_handlers.values():
154
+ for defn in handler.definitions:
155
+ if defn.uri not in seen_uris:
156
+ seen_uris.add(defn.uri)
157
+ definitions.append(defn)
158
+
159
+ return definitions
160
+
161
+ async def list_prompts(self) -> Sequence[MCPPromptDefinition]:
162
+ """List all registered prompts.
163
+
164
+ Returns:
165
+ Sequence of prompt definitions.
166
+ """
167
+ return tuple(h.definition for h in self._prompt_handlers.values())
168
+
169
+ async def call_tool(
170
+ self,
171
+ name: str,
172
+ arguments: dict[str, Any],
173
+ credentials: dict[str, str] | None = None,
174
+ ) -> Result[MCPToolResult, MCPServerError]:
175
+ """Call a registered tool.
176
+
177
+ Args:
178
+ name: Name of the tool to call.
179
+ arguments: Arguments for the tool.
180
+ credentials: Optional credentials for authentication.
181
+
182
+ Returns:
183
+ Result containing the tool result or an error.
184
+ """
185
+ handler = self._tool_handlers.get(name)
186
+ if not handler:
187
+ return Result.err(
188
+ MCPResourceNotFoundError(
189
+ f"Tool not found: {name}",
190
+ server_name=self._name,
191
+ resource_type="tool",
192
+ resource_id=name,
193
+ )
194
+ )
195
+
196
+ # Security check
197
+ security_result = await self._security.check_request(name, arguments, credentials)
198
+ if security_result.is_err:
199
+ return Result.err(security_result.error)
200
+
201
+ try:
202
+ result = await asyncio.wait_for(handler.handle(arguments), timeout=30.0)
203
+ return result
204
+ except asyncio.TimeoutError:
205
+ log.error("mcp.server.tool_timeout", tool=name)
206
+ return Result.err(
207
+ MCPToolError(
208
+ f"Tool execution timed out after 30s: {name}",
209
+ server_name=self._name,
210
+ tool_name=name,
211
+ )
212
+ )
213
+ except Exception as e:
214
+ log.error("mcp.server.tool_error", tool=name, error=str(e))
215
+ return Result.err(
216
+ MCPToolError(
217
+ f"Tool execution failed: {e}",
218
+ server_name=self._name,
219
+ tool_name=name,
220
+ )
221
+ )
222
+
223
+ async def read_resource(
224
+ self,
225
+ uri: str,
226
+ ) -> Result[MCPResourceContent, MCPServerError]:
227
+ """Read a registered resource.
228
+
229
+ Args:
230
+ uri: URI of the resource to read.
231
+
232
+ Returns:
233
+ Result containing the resource content or an error.
234
+ """
235
+ handler = self._resource_handlers.get(uri)
236
+ if not handler:
237
+ return Result.err(
238
+ MCPResourceNotFoundError(
239
+ f"Resource not found: {uri}",
240
+ server_name=self._name,
241
+ resource_type="resource",
242
+ resource_id=uri,
243
+ )
244
+ )
245
+
246
+ try:
247
+ result = await handler.handle(uri)
248
+ return result
249
+ except Exception as e:
250
+ log.error("mcp.server.resource_error", uri=uri, error=str(e))
251
+ return Result.err(
252
+ MCPServerError(
253
+ f"Resource read failed: {e}",
254
+ server_name=self._name,
255
+ )
256
+ )
257
+
258
+ async def get_prompt(
259
+ self,
260
+ name: str,
261
+ arguments: dict[str, str],
262
+ ) -> Result[str, MCPServerError]:
263
+ """Get a filled prompt.
264
+
265
+ Args:
266
+ name: Name of the prompt.
267
+ arguments: Arguments to fill in the template.
268
+
269
+ Returns:
270
+ Result containing the filled prompt or an error.
271
+ """
272
+ handler = self._prompt_handlers.get(name)
273
+ if not handler:
274
+ return Result.err(
275
+ MCPResourceNotFoundError(
276
+ f"Prompt not found: {name}",
277
+ server_name=self._name,
278
+ resource_type="prompt",
279
+ resource_id=name,
280
+ )
281
+ )
282
+
283
+ try:
284
+ result = await handler.handle(arguments)
285
+ return result
286
+ except Exception as e:
287
+ log.error("mcp.server.prompt_error", prompt=name, error=str(e))
288
+ return Result.err(
289
+ MCPServerError(
290
+ f"Prompt generation failed: {e}",
291
+ server_name=self._name,
292
+ )
293
+ )
294
+
295
+ async def serve(self, transport: str = "stdio") -> None:
296
+ """Start serving MCP requests.
297
+
298
+ This method blocks until the server is stopped.
299
+ Uses the MCP SDK's FastMCP server implementation.
300
+
301
+ Args:
302
+ transport: Transport type - "stdio" or "sse".
303
+ """
304
+ try:
305
+ from mcp.server.fastmcp import FastMCP
306
+ except ImportError as e:
307
+ msg = "mcp package not installed. Install with: pip install mcp"
308
+ raise ImportError(msg) from e
309
+
310
+ # Create FastMCP server
311
+ self._mcp_server = FastMCP(self._name)
312
+
313
+ # Register tools with FastMCP
314
+ for _name, handler in self._tool_handlers.items():
315
+ defn = handler.definition
316
+
317
+ # Create a closure to capture the handler
318
+ async def create_tool_wrapper(
319
+ h: ToolHandler,
320
+ ) -> Any:
321
+ async def tool_wrapper(**kwargs: Any) -> Any:
322
+ result = await h.handle(kwargs)
323
+ if result.is_ok:
324
+ # Convert MCPToolResult to FastMCP format
325
+ tool_result = result.value
326
+ return tool_result.text_content
327
+ else:
328
+ return f"Error: {result.error}"
329
+
330
+ return tool_wrapper
331
+
332
+ wrapper = await create_tool_wrapper(handler)
333
+ self._mcp_server.tool(
334
+ name=defn.name,
335
+ description=defn.description,
336
+ )(wrapper)
337
+
338
+ # Register resources with FastMCP
339
+ for uri, res_handler in self._resource_handlers.items():
340
+
341
+ async def create_resource_wrapper(
342
+ h: ResourceHandler,
343
+ resource_uri: str,
344
+ ) -> Any:
345
+ async def resource_wrapper() -> str:
346
+ result = await h.handle(resource_uri)
347
+ if result.is_ok:
348
+ content = result.value
349
+ return content.text or ""
350
+ else:
351
+ return f"Error: {result.error}"
352
+
353
+ return resource_wrapper
354
+
355
+ wrapper = await create_resource_wrapper(res_handler, uri)
356
+ self._mcp_server.resource(uri)(wrapper)
357
+
358
+ log.info(
359
+ "mcp.server.starting",
360
+ name=self._name,
361
+ tools=len(self._tool_handlers),
362
+ resources=len(self._resource_handlers),
363
+ )
364
+
365
+ # Run the server with the appropriate transport
366
+ if transport == "sse":
367
+ await self._mcp_server.run_sse_async()
368
+ else:
369
+ await self._mcp_server.run_stdio_async()
370
+
371
+ async def shutdown(self) -> None:
372
+ """Shutdown the server gracefully."""
373
+ log.info("mcp.server.shutdown", name=self._name)
374
+ # FastMCP handles its own shutdown when run_async completes
375
+
376
+
377
+ def create_ouroboros_server(
378
+ *,
379
+ name: str = "ouroboros-mcp",
380
+ version: str = "1.0.0",
381
+ auth_config: AuthConfig | None = None,
382
+ rate_limit_config: RateLimitConfig | None = None,
383
+ ) -> MCPServerAdapter:
384
+ """Create an Ouroboros MCP server with default handlers.
385
+
386
+ This is a convenience function that creates a server with all
387
+ standard Ouroboros tools and resources pre-registered.
388
+
389
+ Args:
390
+ name: Server name.
391
+ version: Server version.
392
+ auth_config: Optional authentication configuration.
393
+ rate_limit_config: Optional rate limiting configuration.
394
+
395
+ Returns:
396
+ Configured MCPServerAdapter ready to serve.
397
+ """
398
+ server = MCPServerAdapter(
399
+ name=name,
400
+ version=version,
401
+ auth_config=auth_config,
402
+ rate_limit_config=rate_limit_config,
403
+ )
404
+
405
+ # Tools and resources will be registered separately
406
+ # to avoid circular imports
407
+
408
+ return server
@@ -0,0 +1,291 @@
1
+ """MCP Server protocol definitions.
2
+
3
+ This module defines the protocols that MCP server implementations must follow.
4
+ It provides interfaces for the server, tool handlers, and resource handlers.
5
+ """
6
+
7
+ from collections.abc import Awaitable, Callable, Sequence
8
+ from typing import Any, Protocol
9
+
10
+ from ouroboros.core.types import Result
11
+ from ouroboros.mcp.errors import MCPServerError
12
+ from ouroboros.mcp.types import (
13
+ MCPPromptDefinition,
14
+ MCPResourceContent,
15
+ MCPResourceDefinition,
16
+ MCPServerInfo,
17
+ MCPToolDefinition,
18
+ MCPToolResult,
19
+ )
20
+
21
+ # Type aliases for handler functions
22
+ ToolHandlerFunc = Callable[[dict[str, Any]], Awaitable[Result[MCPToolResult, MCPServerError]]]
23
+ ResourceHandlerFunc = Callable[[str], Awaitable[Result[MCPResourceContent, MCPServerError]]]
24
+ PromptHandlerFunc = Callable[[dict[str, str]], Awaitable[Result[str, MCPServerError]]]
25
+
26
+
27
+ class ToolHandler(Protocol):
28
+ """Protocol for tool handler implementations.
29
+
30
+ Tool handlers process incoming tool calls from MCP clients.
31
+ Each handler corresponds to a specific tool and is responsible
32
+ for validating arguments and executing the tool logic.
33
+
34
+ Example:
35
+ class MyToolHandler:
36
+ def __init__(self, service: MyService):
37
+ self._service = service
38
+
39
+ @property
40
+ def definition(self) -> MCPToolDefinition:
41
+ return MCPToolDefinition(
42
+ name="my_tool",
43
+ description="Does something useful",
44
+ parameters=(
45
+ MCPToolParameter(name="input", type=ToolInputType.STRING),
46
+ ),
47
+ )
48
+
49
+ async def handle(
50
+ self, arguments: dict[str, Any]
51
+ ) -> Result[MCPToolResult, MCPServerError]:
52
+ result = await self._service.process(arguments["input"])
53
+ return Result.ok(MCPToolResult(...))
54
+ """
55
+
56
+ @property
57
+ def definition(self) -> MCPToolDefinition:
58
+ """Return the tool definition."""
59
+ ...
60
+
61
+ async def handle(
62
+ self,
63
+ arguments: dict[str, Any],
64
+ ) -> Result[MCPToolResult, MCPServerError]:
65
+ """Handle a tool call.
66
+
67
+ Args:
68
+ arguments: The arguments passed to the tool.
69
+
70
+ Returns:
71
+ Result containing the tool result or an error.
72
+ """
73
+ ...
74
+
75
+
76
+ class ResourceHandler(Protocol):
77
+ """Protocol for resource handler implementations.
78
+
79
+ Resource handlers provide read access to resources via URI.
80
+ Each handler is responsible for one or more resource URIs.
81
+
82
+ Example:
83
+ class SessionResourceHandler:
84
+ @property
85
+ def definitions(self) -> Sequence[MCPResourceDefinition]:
86
+ return [
87
+ MCPResourceDefinition(
88
+ uri="ouroboros://sessions/current",
89
+ name="Current Session",
90
+ description="The current active session",
91
+ ),
92
+ ]
93
+
94
+ async def handle(
95
+ self, uri: str
96
+ ) -> Result[MCPResourceContent, MCPServerError]:
97
+ # Fetch and return the resource content
98
+ ...
99
+ """
100
+
101
+ @property
102
+ def definitions(self) -> Sequence[MCPResourceDefinition]:
103
+ """Return the list of resource definitions this handler provides."""
104
+ ...
105
+
106
+ async def handle(
107
+ self,
108
+ uri: str,
109
+ ) -> Result[MCPResourceContent, MCPServerError]:
110
+ """Handle a resource read request.
111
+
112
+ Args:
113
+ uri: The URI of the resource to read.
114
+
115
+ Returns:
116
+ Result containing the resource content or an error.
117
+ """
118
+ ...
119
+
120
+
121
+ class PromptHandler(Protocol):
122
+ """Protocol for prompt handler implementations.
123
+
124
+ Prompt handlers provide dynamic prompt templates that can be
125
+ filled with arguments from the client.
126
+
127
+ Example:
128
+ class AnalysisPromptHandler:
129
+ @property
130
+ def definition(self) -> MCPPromptDefinition:
131
+ return MCPPromptDefinition(
132
+ name="analyze",
133
+ description="Analyze code for issues",
134
+ arguments=(
135
+ MCPPromptArgument(name="code", required=True),
136
+ ),
137
+ )
138
+
139
+ async def handle(
140
+ self, arguments: dict[str, str]
141
+ ) -> Result[str, MCPServerError]:
142
+ return Result.ok(f"Analyze this code:\n{arguments['code']}")
143
+ """
144
+
145
+ @property
146
+ def definition(self) -> MCPPromptDefinition:
147
+ """Return the prompt definition."""
148
+ ...
149
+
150
+ async def handle(
151
+ self,
152
+ arguments: dict[str, str],
153
+ ) -> Result[str, MCPServerError]:
154
+ """Handle a prompt request.
155
+
156
+ Args:
157
+ arguments: The arguments to fill in the prompt template.
158
+
159
+ Returns:
160
+ Result containing the filled prompt or an error.
161
+ """
162
+ ...
163
+
164
+
165
+ class MCPServer(Protocol):
166
+ """Protocol for MCP server implementations.
167
+
168
+ This protocol defines the interface that all MCP server adapters must
169
+ implement. It supports registering handlers for tools, resources, and
170
+ prompts, as well as starting and stopping the server.
171
+
172
+ Example:
173
+ server = MCPServerAdapter(name="ouroboros-mcp")
174
+
175
+ # Register handlers
176
+ server.register_tool(ExecuteSeedHandler())
177
+ server.register_resource(SessionResourceHandler())
178
+
179
+ # Start serving
180
+ await server.serve()
181
+ """
182
+
183
+ @property
184
+ def info(self) -> MCPServerInfo:
185
+ """Return server information."""
186
+ ...
187
+
188
+ def register_tool(self, handler: ToolHandler) -> None:
189
+ """Register a tool handler.
190
+
191
+ Args:
192
+ handler: The tool handler to register.
193
+ """
194
+ ...
195
+
196
+ def register_resource(self, handler: ResourceHandler) -> None:
197
+ """Register a resource handler.
198
+
199
+ Args:
200
+ handler: The resource handler to register.
201
+ """
202
+ ...
203
+
204
+ def register_prompt(self, handler: PromptHandler) -> None:
205
+ """Register a prompt handler.
206
+
207
+ Args:
208
+ handler: The prompt handler to register.
209
+ """
210
+ ...
211
+
212
+ async def list_tools(self) -> Sequence[MCPToolDefinition]:
213
+ """List all registered tools.
214
+
215
+ Returns:
216
+ Sequence of tool definitions.
217
+ """
218
+ ...
219
+
220
+ async def list_resources(self) -> Sequence[MCPResourceDefinition]:
221
+ """List all registered resources.
222
+
223
+ Returns:
224
+ Sequence of resource definitions.
225
+ """
226
+ ...
227
+
228
+ async def list_prompts(self) -> Sequence[MCPPromptDefinition]:
229
+ """List all registered prompts.
230
+
231
+ Returns:
232
+ Sequence of prompt definitions.
233
+ """
234
+ ...
235
+
236
+ async def call_tool(
237
+ self,
238
+ name: str,
239
+ arguments: dict[str, Any],
240
+ ) -> Result[MCPToolResult, MCPServerError]:
241
+ """Call a registered tool.
242
+
243
+ Args:
244
+ name: Name of the tool to call.
245
+ arguments: Arguments for the tool.
246
+
247
+ Returns:
248
+ Result containing the tool result or an error.
249
+ """
250
+ ...
251
+
252
+ async def read_resource(
253
+ self,
254
+ uri: str,
255
+ ) -> Result[MCPResourceContent, MCPServerError]:
256
+ """Read a registered resource.
257
+
258
+ Args:
259
+ uri: URI of the resource to read.
260
+
261
+ Returns:
262
+ Result containing the resource content or an error.
263
+ """
264
+ ...
265
+
266
+ async def get_prompt(
267
+ self,
268
+ name: str,
269
+ arguments: dict[str, str],
270
+ ) -> Result[str, MCPServerError]:
271
+ """Get a filled prompt.
272
+
273
+ Args:
274
+ name: Name of the prompt.
275
+ arguments: Arguments to fill in the template.
276
+
277
+ Returns:
278
+ Result containing the filled prompt or an error.
279
+ """
280
+ ...
281
+
282
+ async def serve(self) -> None:
283
+ """Start serving MCP requests.
284
+
285
+ This method blocks until the server is stopped.
286
+ """
287
+ ...
288
+
289
+ async def shutdown(self) -> None:
290
+ """Shutdown the server gracefully."""
291
+ ...