wcgw 5.0.2__py3-none-any.whl → 5.1.1__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 wcgw might be problematic. Click here for more details.
- wcgw/client/bash_state/bash_state.py +2 -2
- wcgw/client/file_ops/diff_edit.py +14 -2
- wcgw/client/file_ops/extensions.py +137 -0
- wcgw/client/file_ops/search_replace.py +1 -2
- wcgw/client/mcp_server/server.py +10 -18
- wcgw/client/memory.py +4 -1
- wcgw/client/repo_ops/display_tree.py +4 -4
- wcgw/client/tool_prompts.py +16 -15
- wcgw/client/tools.py +95 -38
- {wcgw-5.0.2.dist-info → wcgw-5.1.1.dist-info}/METADATA +6 -18
- wcgw-5.1.1.dist-info/RECORD +37 -0
- wcgw_cli/anthropic_client.py +8 -4
- wcgw_cli/openai_client.py +7 -3
- mcp_wcgw/__init__.py +0 -114
- mcp_wcgw/client/__init__.py +0 -0
- mcp_wcgw/client/__main__.py +0 -79
- mcp_wcgw/client/session.py +0 -234
- mcp_wcgw/client/sse.py +0 -142
- mcp_wcgw/client/stdio.py +0 -128
- mcp_wcgw/py.typed +0 -0
- mcp_wcgw/server/__init__.py +0 -514
- mcp_wcgw/server/__main__.py +0 -50
- mcp_wcgw/server/models.py +0 -16
- mcp_wcgw/server/session.py +0 -288
- mcp_wcgw/server/sse.py +0 -178
- mcp_wcgw/server/stdio.py +0 -83
- mcp_wcgw/server/websocket.py +0 -61
- mcp_wcgw/shared/__init__.py +0 -0
- mcp_wcgw/shared/context.py +0 -14
- mcp_wcgw/shared/exceptions.py +0 -9
- mcp_wcgw/shared/memory.py +0 -87
- mcp_wcgw/shared/progress.py +0 -40
- mcp_wcgw/shared/session.py +0 -288
- mcp_wcgw/shared/version.py +0 -3
- mcp_wcgw/types.py +0 -1060
- wcgw-5.0.2.dist-info/RECORD +0 -58
- {wcgw-5.0.2.dist-info → wcgw-5.1.1.dist-info}/WHEEL +0 -0
- {wcgw-5.0.2.dist-info → wcgw-5.1.1.dist-info}/entry_points.txt +0 -0
- {wcgw-5.0.2.dist-info → wcgw-5.1.1.dist-info}/licenses/LICENSE +0 -0
mcp_wcgw/server/__init__.py
DELETED
|
@@ -1,514 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
MCP Server Module
|
|
3
|
-
|
|
4
|
-
This module provides a framework for creating an MCP (Model Context Protocol) server.
|
|
5
|
-
It allows you to easily define and handle various types of requests and notifications
|
|
6
|
-
in an asynchronous manner.
|
|
7
|
-
|
|
8
|
-
Usage:
|
|
9
|
-
1. Create a Server instance:
|
|
10
|
-
server = Server("your_server_name")
|
|
11
|
-
|
|
12
|
-
2. Define request handlers using decorators:
|
|
13
|
-
@server.list_prompts()
|
|
14
|
-
async def handle_list_prompts() -> list[types.Prompt]:
|
|
15
|
-
# Implementation
|
|
16
|
-
|
|
17
|
-
@server.get_prompt()
|
|
18
|
-
async def handle_get_prompt(
|
|
19
|
-
name: str, arguments: dict[str, str] | None
|
|
20
|
-
) -> types.GetPromptResult:
|
|
21
|
-
# Implementation
|
|
22
|
-
|
|
23
|
-
@server.list_tools()
|
|
24
|
-
async def handle_list_tools() -> list[types.Tool]:
|
|
25
|
-
# Implementation
|
|
26
|
-
|
|
27
|
-
@server.call_tool()
|
|
28
|
-
async def handle_call_tool(
|
|
29
|
-
name: str, arguments: dict | None
|
|
30
|
-
) -> list[types.TextContent | types.ImageContent | types.EmbeddedResource]:
|
|
31
|
-
# Implementation
|
|
32
|
-
|
|
33
|
-
@server.list_resource_templates()
|
|
34
|
-
async def handle_list_resource_templates() -> list[types.ResourceTemplate]:
|
|
35
|
-
# Implementation
|
|
36
|
-
|
|
37
|
-
3. Define notification handlers if needed:
|
|
38
|
-
@server.progress_notification()
|
|
39
|
-
async def handle_progress(
|
|
40
|
-
progress_token: str | int, progress: float, total: float | None
|
|
41
|
-
) -> None:
|
|
42
|
-
# Implementation
|
|
43
|
-
|
|
44
|
-
4. Run the server:
|
|
45
|
-
async def main():
|
|
46
|
-
async with mcp_wcgwserver.stdio.stdio_server() as (read_stream, write_stream):
|
|
47
|
-
await server.run(
|
|
48
|
-
read_stream,
|
|
49
|
-
write_stream,
|
|
50
|
-
InitializationOptions(
|
|
51
|
-
server_name="your_server_name",
|
|
52
|
-
server_version="your_version",
|
|
53
|
-
capabilities=server.get_capabilities(
|
|
54
|
-
notification_options=NotificationOptions(),
|
|
55
|
-
experimental_capabilities={},
|
|
56
|
-
),
|
|
57
|
-
),
|
|
58
|
-
)
|
|
59
|
-
|
|
60
|
-
asyncio.run(main())
|
|
61
|
-
|
|
62
|
-
The Server class provides methods to register handlers for various MCP requests and
|
|
63
|
-
notifications. It automatically manages the request context and handles incoming
|
|
64
|
-
messages from the client.
|
|
65
|
-
"""
|
|
66
|
-
|
|
67
|
-
import contextvars
|
|
68
|
-
import logging
|
|
69
|
-
import warnings
|
|
70
|
-
from collections.abc import Awaitable, Callable
|
|
71
|
-
from typing import Any, Optional, Sequence
|
|
72
|
-
|
|
73
|
-
from anyio.streams.memory import MemoryObjectReceiveStream, MemoryObjectSendStream
|
|
74
|
-
from pydantic import AnyUrl
|
|
75
|
-
|
|
76
|
-
import mcp_wcgw.types as types
|
|
77
|
-
from mcp_wcgw.server.models import InitializationOptions
|
|
78
|
-
from mcp_wcgw.server.session import ServerSession
|
|
79
|
-
from mcp_wcgw.server.stdio import stdio_server as stdio_server
|
|
80
|
-
from mcp_wcgw.shared.context import RequestContext
|
|
81
|
-
from mcp_wcgw.shared.exceptions import McpError
|
|
82
|
-
from mcp_wcgw.shared.session import RequestResponder
|
|
83
|
-
|
|
84
|
-
logger = logging.getLogger(__name__)
|
|
85
|
-
|
|
86
|
-
request_ctx: contextvars.ContextVar[RequestContext[ServerSession]] = (
|
|
87
|
-
contextvars.ContextVar("request_ctx")
|
|
88
|
-
)
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
class NotificationOptions:
|
|
92
|
-
def __init__(
|
|
93
|
-
self,
|
|
94
|
-
prompts_changed: bool = False,
|
|
95
|
-
resources_changed: bool = False,
|
|
96
|
-
tools_changed: bool = False,
|
|
97
|
-
):
|
|
98
|
-
self.prompts_changed = prompts_changed
|
|
99
|
-
self.resources_changed = resources_changed
|
|
100
|
-
self.tools_changed = tools_changed
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
class Server:
|
|
104
|
-
def __init__(self, name: str):
|
|
105
|
-
self.name = name
|
|
106
|
-
self.request_handlers: dict[
|
|
107
|
-
type, Callable[..., Awaitable[types.ServerResult]]
|
|
108
|
-
] = {
|
|
109
|
-
types.PingRequest: _ping_handler,
|
|
110
|
-
}
|
|
111
|
-
self.notification_handlers: dict[type, Callable[..., Awaitable[None]]] = {}
|
|
112
|
-
self.notification_options = NotificationOptions()
|
|
113
|
-
logger.debug(f"Initializing server '{name}'")
|
|
114
|
-
|
|
115
|
-
def create_initialization_options(
|
|
116
|
-
self,
|
|
117
|
-
notification_options: NotificationOptions | None = None,
|
|
118
|
-
experimental_capabilities: dict[str, dict[str, Any]] | None = None,
|
|
119
|
-
) -> InitializationOptions:
|
|
120
|
-
"""Create initialization options from this server instance."""
|
|
121
|
-
|
|
122
|
-
def pkg_version(package: str) -> str:
|
|
123
|
-
try:
|
|
124
|
-
from importlib.metadata import version
|
|
125
|
-
|
|
126
|
-
v = version(package)
|
|
127
|
-
if v is not None:
|
|
128
|
-
return v
|
|
129
|
-
except Exception:
|
|
130
|
-
pass
|
|
131
|
-
|
|
132
|
-
return "unknown"
|
|
133
|
-
|
|
134
|
-
return InitializationOptions(
|
|
135
|
-
server_name=self.name,
|
|
136
|
-
server_version=pkg_version("mcp"),
|
|
137
|
-
capabilities=self.get_capabilities(
|
|
138
|
-
notification_options or NotificationOptions(),
|
|
139
|
-
experimental_capabilities or {},
|
|
140
|
-
),
|
|
141
|
-
)
|
|
142
|
-
|
|
143
|
-
def get_capabilities(
|
|
144
|
-
self,
|
|
145
|
-
notification_options: NotificationOptions,
|
|
146
|
-
experimental_capabilities: dict[str, dict[str, Any]],
|
|
147
|
-
) -> types.ServerCapabilities:
|
|
148
|
-
"""Convert existing handlers to a ServerCapabilities object."""
|
|
149
|
-
prompts_capability = None
|
|
150
|
-
resources_capability = None
|
|
151
|
-
tools_capability = None
|
|
152
|
-
logging_capability = None
|
|
153
|
-
|
|
154
|
-
# Set prompt capabilities if handler exists
|
|
155
|
-
if types.ListPromptsRequest in self.request_handlers:
|
|
156
|
-
prompts_capability = types.PromptsCapability(
|
|
157
|
-
listChanged=notification_options.prompts_changed
|
|
158
|
-
)
|
|
159
|
-
|
|
160
|
-
# Set resource capabilities if handler exists
|
|
161
|
-
if types.ListResourcesRequest in self.request_handlers:
|
|
162
|
-
resources_capability = types.ResourcesCapability(
|
|
163
|
-
subscribe=False, listChanged=notification_options.resources_changed
|
|
164
|
-
)
|
|
165
|
-
|
|
166
|
-
# Set tool capabilities if handler exists
|
|
167
|
-
if types.ListToolsRequest in self.request_handlers:
|
|
168
|
-
tools_capability = types.ToolsCapability(
|
|
169
|
-
listChanged=notification_options.tools_changed
|
|
170
|
-
)
|
|
171
|
-
|
|
172
|
-
# Set logging capabilities if handler exists
|
|
173
|
-
if types.SetLevelRequest in self.request_handlers:
|
|
174
|
-
logging_capability = types.LoggingCapability()
|
|
175
|
-
|
|
176
|
-
return types.ServerCapabilities(
|
|
177
|
-
prompts=prompts_capability,
|
|
178
|
-
resources=resources_capability,
|
|
179
|
-
tools=tools_capability,
|
|
180
|
-
logging=logging_capability,
|
|
181
|
-
experimental=experimental_capabilities,
|
|
182
|
-
)
|
|
183
|
-
|
|
184
|
-
@property
|
|
185
|
-
def request_context(self) -> RequestContext[ServerSession]:
|
|
186
|
-
"""If called outside of a request context, this will raise a LookupError."""
|
|
187
|
-
return request_ctx.get()
|
|
188
|
-
|
|
189
|
-
def list_prompts(self):
|
|
190
|
-
def decorator(func: Callable[[], Awaitable[list[types.Prompt]]]):
|
|
191
|
-
logger.debug("Registering handler for PromptListRequest")
|
|
192
|
-
|
|
193
|
-
async def handler(_: Any):
|
|
194
|
-
prompts = await func()
|
|
195
|
-
return types.ServerResult(types.ListPromptsResult(prompts=prompts))
|
|
196
|
-
|
|
197
|
-
self.request_handlers[types.ListPromptsRequest] = handler
|
|
198
|
-
return func
|
|
199
|
-
|
|
200
|
-
return decorator
|
|
201
|
-
|
|
202
|
-
def get_prompt(self):
|
|
203
|
-
def decorator(
|
|
204
|
-
func: Callable[
|
|
205
|
-
[str, dict[str, str] | None], Awaitable[types.GetPromptResult]
|
|
206
|
-
],
|
|
207
|
-
):
|
|
208
|
-
logger.debug("Registering handler for GetPromptRequest")
|
|
209
|
-
|
|
210
|
-
async def handler(req: types.GetPromptRequest):
|
|
211
|
-
prompt_get = await func(req.params.name, req.params.arguments)
|
|
212
|
-
return types.ServerResult(prompt_get)
|
|
213
|
-
|
|
214
|
-
self.request_handlers[types.GetPromptRequest] = handler
|
|
215
|
-
return func
|
|
216
|
-
|
|
217
|
-
return decorator
|
|
218
|
-
|
|
219
|
-
def list_resources(self):
|
|
220
|
-
def decorator(func: Callable[[], Awaitable[list[types.Resource]]]):
|
|
221
|
-
logger.debug("Registering handler for ListResourcesRequest")
|
|
222
|
-
|
|
223
|
-
async def handler(_: Any):
|
|
224
|
-
resources = await func()
|
|
225
|
-
return types.ServerResult(
|
|
226
|
-
types.ListResourcesResult(resources=resources)
|
|
227
|
-
)
|
|
228
|
-
|
|
229
|
-
self.request_handlers[types.ListResourcesRequest] = handler
|
|
230
|
-
return func
|
|
231
|
-
|
|
232
|
-
return decorator
|
|
233
|
-
|
|
234
|
-
def list_resource_templates(self):
|
|
235
|
-
def decorator(func: Callable[[], Awaitable[list[types.ResourceTemplate]]]):
|
|
236
|
-
logger.debug("Registering handler for ListResourceTemplatesRequest")
|
|
237
|
-
|
|
238
|
-
async def handler(_: Any):
|
|
239
|
-
templates = await func()
|
|
240
|
-
return types.ServerResult(
|
|
241
|
-
types.ListResourceTemplatesResult(resourceTemplates=templates)
|
|
242
|
-
)
|
|
243
|
-
|
|
244
|
-
self.request_handlers[types.ListResourceTemplatesRequest] = handler
|
|
245
|
-
return func
|
|
246
|
-
|
|
247
|
-
return decorator
|
|
248
|
-
|
|
249
|
-
def read_resource(self):
|
|
250
|
-
def decorator(func: Callable[[AnyUrl], Awaitable[str | bytes]]):
|
|
251
|
-
logger.debug("Registering handler for ReadResourceRequest")
|
|
252
|
-
|
|
253
|
-
async def handler(req: types.ReadResourceRequest):
|
|
254
|
-
result = await func(req.params.uri)
|
|
255
|
-
match result:
|
|
256
|
-
case str(s):
|
|
257
|
-
content = types.TextResourceContents(
|
|
258
|
-
uri=req.params.uri,
|
|
259
|
-
text=s,
|
|
260
|
-
mimeType="text/plain",
|
|
261
|
-
)
|
|
262
|
-
case bytes(b):
|
|
263
|
-
import base64
|
|
264
|
-
|
|
265
|
-
content = types.BlobResourceContents(
|
|
266
|
-
uri=req.params.uri,
|
|
267
|
-
blob=base64.urlsafe_b64encode(b).decode(),
|
|
268
|
-
mimeType="application/octet-stream",
|
|
269
|
-
)
|
|
270
|
-
|
|
271
|
-
return types.ServerResult(
|
|
272
|
-
types.ReadResourceResult(
|
|
273
|
-
contents=[content],
|
|
274
|
-
)
|
|
275
|
-
)
|
|
276
|
-
|
|
277
|
-
self.request_handlers[types.ReadResourceRequest] = handler
|
|
278
|
-
return func
|
|
279
|
-
|
|
280
|
-
return decorator
|
|
281
|
-
|
|
282
|
-
def set_logging_level(self):
|
|
283
|
-
def decorator(func: Callable[[types.LoggingLevel], Awaitable[None]]):
|
|
284
|
-
logger.debug("Registering handler for SetLevelRequest")
|
|
285
|
-
|
|
286
|
-
async def handler(req: types.SetLevelRequest):
|
|
287
|
-
await func(req.params.level)
|
|
288
|
-
return types.ServerResult(types.EmptyResult())
|
|
289
|
-
|
|
290
|
-
self.request_handlers[types.SetLevelRequest] = handler
|
|
291
|
-
return func
|
|
292
|
-
|
|
293
|
-
return decorator
|
|
294
|
-
|
|
295
|
-
def subscribe_resource(self):
|
|
296
|
-
def decorator(func: Callable[[AnyUrl], Awaitable[None]]):
|
|
297
|
-
logger.debug("Registering handler for SubscribeRequest")
|
|
298
|
-
|
|
299
|
-
async def handler(req: types.SubscribeRequest):
|
|
300
|
-
await func(req.params.uri)
|
|
301
|
-
return types.ServerResult(types.EmptyResult())
|
|
302
|
-
|
|
303
|
-
self.request_handlers[types.SubscribeRequest] = handler
|
|
304
|
-
return func
|
|
305
|
-
|
|
306
|
-
return decorator
|
|
307
|
-
|
|
308
|
-
def unsubscribe_resource(self):
|
|
309
|
-
def decorator(func: Callable[[AnyUrl], Awaitable[None]]):
|
|
310
|
-
logger.debug("Registering handler for UnsubscribeRequest")
|
|
311
|
-
|
|
312
|
-
async def handler(req: types.UnsubscribeRequest):
|
|
313
|
-
await func(req.params.uri)
|
|
314
|
-
return types.ServerResult(types.EmptyResult())
|
|
315
|
-
|
|
316
|
-
self.request_handlers[types.UnsubscribeRequest] = handler
|
|
317
|
-
return func
|
|
318
|
-
|
|
319
|
-
return decorator
|
|
320
|
-
|
|
321
|
-
def list_tools(self):
|
|
322
|
-
def decorator(func: Callable[[], Awaitable[list[types.Tool]]]):
|
|
323
|
-
logger.debug("Registering handler for ListToolsRequest")
|
|
324
|
-
|
|
325
|
-
async def handler(_: Any):
|
|
326
|
-
tools = await func()
|
|
327
|
-
return types.ServerResult(types.ListToolsResult(tools=tools))
|
|
328
|
-
|
|
329
|
-
self.request_handlers[types.ListToolsRequest] = handler
|
|
330
|
-
return func
|
|
331
|
-
|
|
332
|
-
return decorator
|
|
333
|
-
|
|
334
|
-
def call_tool(self):
|
|
335
|
-
def decorator(
|
|
336
|
-
func: Callable[
|
|
337
|
-
...,
|
|
338
|
-
Awaitable[
|
|
339
|
-
Sequence[
|
|
340
|
-
types.TextContent | types.ImageContent | types.EmbeddedResource
|
|
341
|
-
]
|
|
342
|
-
],
|
|
343
|
-
],
|
|
344
|
-
):
|
|
345
|
-
logger.debug("Registering handler for CallToolRequest")
|
|
346
|
-
|
|
347
|
-
async def handler(req: types.CallToolRequest):
|
|
348
|
-
try:
|
|
349
|
-
results = await func(req.params.name, (req.params.arguments or {}))
|
|
350
|
-
return types.ServerResult(
|
|
351
|
-
types.CallToolResult(content=list(results), isError=False)
|
|
352
|
-
)
|
|
353
|
-
except Exception as e:
|
|
354
|
-
return types.ServerResult(
|
|
355
|
-
types.CallToolResult(
|
|
356
|
-
content=[types.TextContent(type="text", text=str(e))],
|
|
357
|
-
isError=True,
|
|
358
|
-
)
|
|
359
|
-
)
|
|
360
|
-
|
|
361
|
-
self.request_handlers[types.CallToolRequest] = handler
|
|
362
|
-
return func
|
|
363
|
-
|
|
364
|
-
return decorator
|
|
365
|
-
|
|
366
|
-
def progress_notification(self):
|
|
367
|
-
def decorator(
|
|
368
|
-
func: Callable[[str | int, float, float | None], Awaitable[None]],
|
|
369
|
-
):
|
|
370
|
-
logger.debug("Registering handler for ProgressNotification")
|
|
371
|
-
|
|
372
|
-
async def handler(req: types.ProgressNotification):
|
|
373
|
-
await func(
|
|
374
|
-
req.params.progressToken, req.params.progress, req.params.total
|
|
375
|
-
)
|
|
376
|
-
|
|
377
|
-
self.notification_handlers[types.ProgressNotification] = handler
|
|
378
|
-
return func
|
|
379
|
-
|
|
380
|
-
return decorator
|
|
381
|
-
|
|
382
|
-
def cancellation_notification(self):
|
|
383
|
-
def decorator(
|
|
384
|
-
func: Callable[[Optional[int], Optional[str]], Awaitable[None]],
|
|
385
|
-
):
|
|
386
|
-
logger.debug("Registering handler for ProgressNotification")
|
|
387
|
-
|
|
388
|
-
async def handler(req: types.CancellationNotification):
|
|
389
|
-
await func(req.params.requestId, req.params.reason)
|
|
390
|
-
|
|
391
|
-
self.notification_handlers[types.CancellationNotification] = handler
|
|
392
|
-
return func
|
|
393
|
-
|
|
394
|
-
return decorator
|
|
395
|
-
|
|
396
|
-
def completion(self):
|
|
397
|
-
"""Provides completions for prompts and resource templates"""
|
|
398
|
-
|
|
399
|
-
def decorator(
|
|
400
|
-
func: Callable[
|
|
401
|
-
[
|
|
402
|
-
types.PromptReference | types.ResourceReference,
|
|
403
|
-
types.CompletionArgument,
|
|
404
|
-
],
|
|
405
|
-
Awaitable[types.Completion | None],
|
|
406
|
-
],
|
|
407
|
-
):
|
|
408
|
-
logger.debug("Registering handler for CompleteRequest")
|
|
409
|
-
|
|
410
|
-
async def handler(req: types.CompleteRequest):
|
|
411
|
-
completion = await func(req.params.ref, req.params.argument)
|
|
412
|
-
return types.ServerResult(
|
|
413
|
-
types.CompleteResult(
|
|
414
|
-
completion=completion
|
|
415
|
-
if completion is not None
|
|
416
|
-
else types.Completion(values=[], total=None, hasMore=None),
|
|
417
|
-
)
|
|
418
|
-
)
|
|
419
|
-
|
|
420
|
-
self.request_handlers[types.CompleteRequest] = handler
|
|
421
|
-
return func
|
|
422
|
-
|
|
423
|
-
return decorator
|
|
424
|
-
|
|
425
|
-
async def run(
|
|
426
|
-
self,
|
|
427
|
-
read_stream: MemoryObjectReceiveStream[types.JSONRPCMessage | Exception],
|
|
428
|
-
write_stream: MemoryObjectSendStream[types.JSONRPCMessage],
|
|
429
|
-
initialization_options: InitializationOptions,
|
|
430
|
-
# When False, exceptions are returned as messages to the client.
|
|
431
|
-
# When True, exceptions are raised, which will cause the server to shut down
|
|
432
|
-
# but also make tracing exceptions much easier during testing and when using
|
|
433
|
-
# in-process servers.
|
|
434
|
-
raise_exceptions: bool = False,
|
|
435
|
-
):
|
|
436
|
-
with warnings.catch_warnings(record=True) as w:
|
|
437
|
-
async with ServerSession(
|
|
438
|
-
read_stream, write_stream, initialization_options
|
|
439
|
-
) as session:
|
|
440
|
-
async for message in session.incoming_messages:
|
|
441
|
-
logger.debug(f"Received message: {message}")
|
|
442
|
-
|
|
443
|
-
match message:
|
|
444
|
-
case RequestResponder(request=types.ClientRequest(root=req)):
|
|
445
|
-
logger.info(
|
|
446
|
-
f"Processing request of type {type(req).__name__}"
|
|
447
|
-
)
|
|
448
|
-
if type(req) in self.request_handlers:
|
|
449
|
-
handler = self.request_handlers[type(req)]
|
|
450
|
-
logger.debug(
|
|
451
|
-
f"Dispatching request of type {type(req).__name__}"
|
|
452
|
-
)
|
|
453
|
-
|
|
454
|
-
token = None
|
|
455
|
-
try:
|
|
456
|
-
# Set our global state that can be retrieved via
|
|
457
|
-
# app.get_request_context()
|
|
458
|
-
token = request_ctx.set(
|
|
459
|
-
RequestContext(
|
|
460
|
-
message.request_id,
|
|
461
|
-
message.request_meta,
|
|
462
|
-
session,
|
|
463
|
-
)
|
|
464
|
-
)
|
|
465
|
-
response = await handler(req)
|
|
466
|
-
except McpError as err:
|
|
467
|
-
response = err.error
|
|
468
|
-
except Exception as err:
|
|
469
|
-
if raise_exceptions:
|
|
470
|
-
raise err
|
|
471
|
-
response = types.ErrorData(
|
|
472
|
-
code=0, message=str(err), data=None
|
|
473
|
-
)
|
|
474
|
-
finally:
|
|
475
|
-
# Reset the global state after we are done
|
|
476
|
-
if token is not None:
|
|
477
|
-
request_ctx.reset(token)
|
|
478
|
-
|
|
479
|
-
await message.respond(response)
|
|
480
|
-
else:
|
|
481
|
-
await message.respond(
|
|
482
|
-
types.ErrorData(
|
|
483
|
-
code=types.METHOD_NOT_FOUND,
|
|
484
|
-
message="Method not found",
|
|
485
|
-
)
|
|
486
|
-
)
|
|
487
|
-
|
|
488
|
-
logger.debug("Response sent")
|
|
489
|
-
case types.ClientNotification(root=notify):
|
|
490
|
-
if type(notify) in self.notification_handlers:
|
|
491
|
-
assert type(notify) in self.notification_handlers
|
|
492
|
-
|
|
493
|
-
handler = self.notification_handlers[type(notify)]
|
|
494
|
-
logger.debug(
|
|
495
|
-
f"Dispatching notification of type "
|
|
496
|
-
f"{type(notify).__name__}"
|
|
497
|
-
)
|
|
498
|
-
|
|
499
|
-
try:
|
|
500
|
-
await handler(notify)
|
|
501
|
-
except Exception as err:
|
|
502
|
-
logger.error(
|
|
503
|
-
f"Uncaught exception in notification handler: "
|
|
504
|
-
f"{err}"
|
|
505
|
-
)
|
|
506
|
-
|
|
507
|
-
for warning in w:
|
|
508
|
-
logger.info(
|
|
509
|
-
f"Warning: {warning.category.__name__}: {warning.message}"
|
|
510
|
-
)
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
async def _ping_handler(request: types.PingRequest) -> types.ServerResult:
|
|
514
|
-
return types.ServerResult(types.EmptyResult())
|
mcp_wcgw/server/__main__.py
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import importlib.metadata
|
|
2
|
-
import logging
|
|
3
|
-
import sys
|
|
4
|
-
|
|
5
|
-
import anyio
|
|
6
|
-
|
|
7
|
-
from mcp_wcgw.server.models import InitializationOptions
|
|
8
|
-
from mcp_wcgw.server.session import ServerSession
|
|
9
|
-
from mcp_wcgw.server.stdio import stdio_server
|
|
10
|
-
from mcp_wcgw.types import ServerCapabilities
|
|
11
|
-
|
|
12
|
-
if not sys.warnoptions:
|
|
13
|
-
import warnings
|
|
14
|
-
|
|
15
|
-
warnings.simplefilter("ignore")
|
|
16
|
-
|
|
17
|
-
logging.basicConfig(level=logging.INFO)
|
|
18
|
-
logger = logging.getLogger("server")
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
async def receive_loop(session: ServerSession):
|
|
22
|
-
logger.info("Starting receive loop")
|
|
23
|
-
async for message in session.incoming_messages:
|
|
24
|
-
if isinstance(message, Exception):
|
|
25
|
-
logger.error("Error: %s", message)
|
|
26
|
-
continue
|
|
27
|
-
|
|
28
|
-
logger.info("Received message from client: %s", message)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
async def main():
|
|
32
|
-
version = importlib.metadata.version("mcp")
|
|
33
|
-
async with stdio_server() as (read_stream, write_stream):
|
|
34
|
-
async with (
|
|
35
|
-
ServerSession(
|
|
36
|
-
read_stream,
|
|
37
|
-
write_stream,
|
|
38
|
-
InitializationOptions(
|
|
39
|
-
server_name="mcp",
|
|
40
|
-
server_version=version,
|
|
41
|
-
capabilities=ServerCapabilities(),
|
|
42
|
-
),
|
|
43
|
-
) as session,
|
|
44
|
-
write_stream,
|
|
45
|
-
):
|
|
46
|
-
await receive_loop(session)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
if __name__ == "__main__":
|
|
50
|
-
anyio.run(main, backend="trio")
|
mcp_wcgw/server/models.py
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
This module provides simpler types to use with the server for managing prompts
|
|
3
|
-
and tools.
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
from pydantic import BaseModel
|
|
7
|
-
|
|
8
|
-
from mcp_wcgw.types import (
|
|
9
|
-
ServerCapabilities,
|
|
10
|
-
)
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class InitializationOptions(BaseModel):
|
|
14
|
-
server_name: str
|
|
15
|
-
server_version: str
|
|
16
|
-
capabilities: ServerCapabilities
|