如何使用SSE实现模型上下文协议(MCP)服务器? 我正在尝试在Python和PHP中创建模型上下文协议(MCP)服务器。目标是通过SSE同时使用Cursorai和MCP-inspector Client Connect,执行初始化调用,然后(

问题描述 投票:0回答:0
import uvicorn import json import logging import asyncio from starlette.applications import Starlette from starlette.requests import Request from starlette.responses import PlainTextResponse, JSONResponse from starlette.routing import Route # MCP Python SDK: lowlevel server + SSE transport from mcp.server.lowlevel import Server from mcp.server.sse import SseServerTransport from mcp.types import Tool, TextContent logging.basicConfig(level=logging.DEBUG) logger = logging.getLogger("mcp-detailed") logger.setLevel(logging.DEBUG) ############################################################################### # MCP-Server ############################################################################### mcp_server = Server("AllInOneDummyServer") # no "logger=..." argument # Define some dummy tools UPCASE_TOOL = Tool( name="upcase", description="Convert text to uppercase", inputSchema={ "type": "object", "properties": { "text": {"type": "string", "description": "Text to uppercase"} }, "required": ["text"] } ) AVAILABLE_TOOLS = [UPCASE_TOOL] @mcp_server.call_tool() async def call_tool(name: str, arguments: dict): logger.info(f"[mcp_server.call_tool] name={name}, arguments={arguments}") if name == "upcase": text = arguments.get("text", "") return [TextContent(type="text", text=text.upper())] else: raise ValueError(f"Unknown tool: {name}") @mcp_server.list_tools() async def list_tools(): logger.info("[mcp_server.list_tools] called") return AVAILABLE_TOOLS ############################################################################### # SSE Endpoint (GET /sse) ############################################################################### async def sse_endpoint(request: Request): logger.info("[SSE] => sse_endpoint called") # SSE transport from the MCP SDK sse_transport = SseServerTransport("/sse/messages") scope = request.scope receive = request.receive send = request._send async with sse_transport.connect_sse(scope, receive, send) as (read_st, write_st): logger.info("[SSE] run mcp_server with SSE transport => calling 'mcp_server.run'") init_opts = mcp_server.create_initialization_options() # Run the server with read/write streams await mcp_server.run(read_st, write_st, init_opts) logger.info("[SSE] => SSE session ended") return ############################################################################### # Keepalive-Task ############################################################################### async def sse_keepalive_loop(): """ Sends periodic keep-alive pings into SSE (just comment lines). """ while True: logger.debug("[KeepAliveLoop] SSE keep-alive ping (no actual method).") await asyncio.sleep(20) ############################################################################### # JSON-RPC Endpoint (POST /sse/messages) ############################################################################### async def post_handler(request: Request): raw = await request.body() body_str = raw.decode("utf-8") logger.info(f"[POST /sse/messages] => {body_str}") if not body_str.strip(): return PlainTextResponse("Empty body\n", 400) try: msg = json.loads(body_str) except Exception as e: logger.error(f"[POST] JSON parse error: {e}") return PlainTextResponse("Invalid JSON\n", 400) if msg.get("jsonrpc") != "2.0": logger.error("[POST] => Missing jsonrpc=2.0") return PlainTextResponse("Missing jsonrpc=2.0\n", 400) id_ = msg.get("id") method = msg.get("method","") params = msg.get("params",{}) logger.debug(f"[POST] method={method}, id={id_}, params={params}") server_info = {"name":"AllInOneDummyServer","version":"1.0.0"} # If no id => it's a notification if id_ is None: logger.info(f"Received NOTIFICATION => method={method}, params={params}") # We do nothing or just debug return PlainTextResponse("", 200) # =============================================================== # The "initialize" method # =============================================================== if method == "initialize": logger.info("Handling 'initialize' in post_handler") # Build capabilities, offerings, etc. result = { "protocolVersion": "2024-11-05", "capabilities": { "tools": {"listChanged": True}, "resources": {"listChanged": True, "subscribe": True}, "prompts": {"listChanged": True}, "logging": True, "roots": {"listChanged": True}, "sampling": True, }, "serverInfo": server_info, "offerings": [ {"name": "upcaseTool", "description": "Tool that upcases text"}, {"name": "fakePrompt", "description": "A dummy prompt"}, {"name": "someResource", "description": "Fake resource for tests"}, ], "tools": [ { "name": "upcase", "description": "Convert text to uppercase", "inputSchema": { "type": "object", "properties": { "text":{"type":"string","description":"Text to uppercase"} }, "required":["text"] } } ] } resp = {"jsonrpc":"2.0","id":id_,"result":result} logger.debug(f"Sending initialize response: {json.dumps(resp)}") return JSONResponse(resp) # =============================================================== # Some other typical methods (ping, listOfferings, tools/list, etc) # =============================================================== if method == "ping": logger.info("Handling 'ping'") resp = {"jsonrpc":"2.0","id":id_,"result":"pong"} return JSONResponse(resp) elif method == "listOfferings": logger.info("Handling 'listOfferings'") result = { "serverInfo": server_info, "capabilities": { "tools": {"listChanged": True}, "resources": {"listChanged": True,"subscribe":True}, "prompts": {"listChanged": True}, "logging": True, "roots": {"listChanged": True}, "sampling": True }, "offerings":[ {"name":"upcaseTool","description":"tool upcase"}, {"name":"fakePrompt","description":"Dummy prompt"}, {"name":"someResource","description":"Fake resource"}, ] } resp = {"jsonrpc":"2.0","id":id_,"result":result} return JSONResponse(resp) elif method == "tools/list": logger.info("Handling 'tools/list'") tools_list = [ { "name":"upcase", "description":"Converts text to uppercase", "inputSchema":{ "type":"object", "properties":{"text":{"type":"string","description":"The text to uppercase"}}, "required":["text"] } } ] resp = {"jsonrpc":"2.0","id":id_,"result":{ "serverInfo":server_info, "tools":tools_list }} return JSONResponse(resp) elif method == "tools/call": logger.info("Handling 'tools/call'") name = params.get("name","") arguments = params.get("arguments",{}) if name=="upcase": text = arguments.get("text","") upper = text.upper() ret = { "jsonrpc":"2.0","id":id_, "result":{"content":[{"type":"text","text":upper}]} } return JSONResponse(ret) else: err = {"jsonrpc":"2.0","id":id_, "error":{"code":-32601,"message":f"Unknown tool: {name}"}} return JSONResponse(err) # === Resources elif method == "resources/list": logger.info("Handling 'resources/list'") resources = [ { "uri":"fake://dummyResource", "name":"Fake Resource", "description":"A test resource" } ] resp = {"jsonrpc":"2.0","id":id_, "result":{"serverInfo": server_info,"resources":resources}} return JSONResponse(resp) elif method == "resources/subscribe": logger.info("Handling 'resources/subscribe'") resp = {"jsonrpc":"2.0","id":id_,"result":{"subscribed":True}} return JSONResponse(resp) elif method == "resources/read": logger.info("Handling 'resources/read'") uri = params.get("uri","fake://dummyResource") resp = { "jsonrpc":"2.0","id":id_, "result":{ "contents":[{"type":"text","text":f"Dummy contents for {uri}"}] } } return JSONResponse(resp) # === Prompts elif method == "prompts/list": logger.info("Handling 'prompts/list'") resp = { "jsonrpc":"2.0","id":id_, "result":{ "prompts":[ { "name":"fakePrompt", "description":"Dummy prompt example", "arguments":[ {"name":"arg1","description":"Example arg","required":True} ] } ] } } return JSONResponse(resp) # Uknown method => error else: logger.warning(f"Unknown method => {method}") err = { "jsonrpc":"2.0","id":id_, "error":{ "code":-32601, "message":f"Method '{method}' not found" } } return JSONResponse(err) # starlette routing routes = [ Route("/sse", sse_endpoint, methods=["GET"]), Route("/sse/messages", post_handler, methods=["POST","OPTIONS"]) ] from starlette.middleware import Middleware from starlette.middleware.cors import CORSMiddleware middleware = [ Middleware(CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"]) ] app = Starlette(debug=True, routes=routes, middleware=middleware) @app.on_event("startup") async def on_startup(): logger.info("App Startup: launching SSE keepalive background task") loop = asyncio.get_event_loop() loop.create_task(sse_keepalive_loop()) if __name__=="__main__": uvicorn.run(app, host="0.0.0.0", port=8000)

我的日志输出您可以在这里看到什么

(venv) root@localhost:/opt/my_mcp_venv# python server.py DEBUG:mcp.server.lowlevel.server:Initializing server 'AllInOneDummyServer' DEBUG:mcp.server.lowlevel.server:Registering handler for CallToolRequest DEBUG:mcp.server.lowlevel.server:Registering handler for ListToolsRequest DEBUG:asyncio:Using selector: EpollSelector INFO: Started server process [1082343] INFO: Waiting for application startup. INFO:mcp-detailed:App Startup: launching SSE keepalive background task DEBUG:mcp-detailed:[KeepAliveLoop] SSE keep-alive ping (no actual method). INFO: Application startup complete. INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit) INFO:mcp-detailed:[SSE] => sse_endpoint called DEBUG:mcp.server.sse:SseServerTransport initialized with endpoint: /sse/messages DEBUG:mcp.server.sse:Setting up SSE connection DEBUG:mcp.server.sse:Created new session with ID: 4ce9e4fa-44f1-4f43-a7a9-026ee59faa3b DEBUG:mcp.server.sse:Starting SSE response task DEBUG:mcp.server.sse:Yielding read and write streams INFO:mcp-detailed:[SSE] run mcp_server with SSE transport => calling 'mcp_server.run' INFO: {IP}:38378 - "GET /sse HTTP/1.1" 200 OK DEBUG:mcp.server.sse:Starting SSE writer DEBUG:mcp.server.sse:Sent endpoint event: /sse/messages?session_id=4ce9e4fa44f14f43a7a9026ee59faa3b DEBUG:sse_starlette.sse:chunk: b'event: endpoint\r\ndata: /sse/messages?session_id=4ce9e4fa44f14f43a7a9026ee59faa3b\r\n\r\n' INFO:mcp-detailed:[SSE] => sse_endpoint called DEBUG:mcp.server.sse:SseServerTransport initialized with endpoint: /sse/messages DEBUG:mcp.server.sse:Setting up SSE connection DEBUG:mcp.server.sse:Created new session with ID: 728fd505-8663-4ea4-bf3e-b1ade3cf812c DEBUG:mcp.server.sse:Starting SSE response task DEBUG:mcp.server.sse:Yielding read and write streams INFO:mcp-detailed:[SSE] run mcp_server with SSE transport => calling 'mcp_server.run' INFO: {IP}:38387 - "GET /sse HTTP/1.1" 200 OK DEBUG:mcp.server.sse:Starting SSE writer DEBUG:mcp.server.sse:Sent endpoint event: /sse/messages?session_id=728fd50586634ea4bf3eb1ade3cf812c DEBUG:sse_starlette.sse:chunk: b'event: endpoint\r\ndata: /sse/messages?session_id=728fd50586634ea4bf3eb1ade3cf812c\r\n\r\n' INFO:mcp-detailed:[SSE] => sse_endpoint called DEBUG:mcp.server.sse:SseServerTransport initialized with endpoint: /sse/messages DEBUG:mcp.server.sse:Setting up SSE connection DEBUG:mcp.server.sse:Created new session with ID: 5340a58c-b0d2-449c-bc37-cb42c555b6ee DEBUG:mcp.server.sse:Starting SSE response task DEBUG:mcp.server.sse:Yielding read and write streams INFO:mcp-detailed:[SSE] run mcp_server with SSE transport => calling 'mcp_server.run' INFO:mcp-detailed:[SSE] => sse_endpoint called DEBUG:mcp.server.sse:SseServerTransport initialized with endpoint: /sse/messages DEBUG:mcp.server.sse:Setting up SSE connection DEBUG:mcp.server.sse:Created new session with ID: 1c108457-e826-4d37-bde9-781f11e4cdb4 DEBUG:mcp.server.sse:Starting SSE response task DEBUG:mcp.server.sse:Yielding read and write streams INFO:mcp-detailed:[SSE] run mcp_server with SSE transport => calling 'mcp_server.run' INFO:mcp-detailed:[SSE] => sse_endpoint called DEBUG:mcp.server.sse:SseServerTransport initialized with endpoint: /sse/messages DEBUG:mcp.server.sse:Setting up SSE connection DEBUG:mcp.server.sse:Created new session with ID: 60c081d1-dc42-461d-be72-c79f0296ed38 DEBUG:mcp.server.sse:Starting SSE response task DEBUG:mcp.server.sse:Yielding read and write streams INFO:mcp-detailed:[SSE] run mcp_server with SSE transport => calling 'mcp_server.run' INFO: {IP}:37888 - "GET /sse HTTP/1.1" 200 OK DEBUG:mcp.server.sse:Starting SSE writer INFO: {IP}:37891 - "GET /sse HTTP/1.1" 200 OK DEBUG:mcp.server.sse:Starting SSE writer INFO: {IP}:38398 - "GET /sse HTTP/1.1" 200 OK DEBUG:mcp.server.sse:Starting SSE writer DEBUG:mcp.server.sse:Sent endpoint event: /sse/messages?session_id=5340a58cb0d2449cbc37cb42c555b6ee DEBUG:mcp.server.sse:Sent endpoint event: /sse/messages?session_id=1c108457e8264d37bde9781f11e4cdb4 DEBUG:mcp.server.sse:Sent endpoint event: /sse/messages?session_id=60c081d1dc42461dbe72c79f0296ed38 DEBUG:sse_starlette.sse:chunk: b'event: endpoint\r\ndata: /sse/messages?session_id=5340a58cb0d2449cbc37cb42c555b6ee\r\n\r\n' DEBUG:sse_starlette.sse:chunk: b'event: endpoint\r\ndata: /sse/messages?session_id=1c108457e8264d37bde9781f11e4cdb4\r\n\r\n' DEBUG:sse_starlette.sse:chunk: b'event: endpoint\r\ndata: /sse/messages?session_id=60c081d1dc42461dbe72c79f0296ed38\r\n\r\n' INFO:mcp-detailed:[SSE] => sse_endpoint called DEBUG:mcp.server.sse:SseServerTransport initialized with endpoint: /sse/messages DEBUG:mcp.server.sse:Setting up SSE connection DEBUG:mcp.server.sse:Created new session with ID: 6427f59a-79f1-4d4a-bd8c-1e1addeb2f90 DEBUG:mcp.server.sse:Starting SSE response task DEBUG:mcp.server.sse:Yielding read and write streams INFO:mcp-detailed:[SSE] run mcp_server with SSE transport => calling 'mcp_server.run' INFO:mcp-detailed:[SSE] => sse_endpoint called DEBUG:mcp.server.sse:SseServerTransport initialized with endpoint: /sse/messages DEBUG:mcp.server.sse:Setting up SSE connection DEBUG:mcp.server.sse:Created new session with ID: 0f929ade-9481-4854-a8c7-2d987c11cd1b DEBUG:mcp.server.sse:Starting SSE response task DEBUG:mcp.server.sse:Yielding read and write streams INFO:mcp-detailed:[SSE] run mcp_server with SSE transport => calling 'mcp_server.run' INFO:mcp-detailed:[SSE] => sse_endpoint called DEBUG:mcp.server.sse:SseServerTransport initialized with endpoint: /sse/messages DEBUG:mcp.server.sse:Setting up SSE connection DEBUG:mcp.server.sse:Created new session with ID: 4eafb787-1712-449a-bf46-5d7dfb6c3390 DEBUG:mcp.server.sse:Starting SSE response task DEBUG:mcp.server.sse:Yielding read and write streams INFO:mcp-detailed:[SSE] run mcp_server with SSE transport => calling 'mcp_server.run' INFO:mcp-detailed:[SSE] => sse_endpoint called DEBUG:mcp.server.sse:SseServerTransport initialized with endpoint: /sse/messages DEBUG:mcp.server.sse:Setting up SSE connection DEBUG:mcp.server.sse:Created new session with ID: 6db64772-fde7-4f8d-8309-43a999647ee0 DEBUG:mcp.server.sse:Starting SSE response task DEBUG:mcp.server.sse:Yielding read and write streams INFO:mcp-detailed:[SSE] run mcp_server with SSE transport => calling 'mcp_server.run' INFO: {IP}:37914 - "GET /sse HTTP/1.1" 200 OK DEBUG:mcp.server.sse:Starting SSE writer INFO: {IP}:37916 - "GET /sse HTTP/1.1" 200 OK DEBUG:mcp.server.sse:Starting SSE writer INFO: {IP}:37915 - "GET /sse HTTP/1.1" 200 OK DEBUG:mcp.server.sse:Starting SSE writer INFO: {IP}:37917 - "GET /sse HTTP/1.1" 200 OK DEBUG:mcp.server.sse:Starting SSE writer DEBUG:mcp.server.sse:Sent endpoint event: /sse/messages?session_id=6427f59a79f14d4abd8c1e1addeb2f90 DEBUG:mcp.server.sse:Sent endpoint event: /sse/messages?session_id=0f929ade94814854a8c72d987c11cd1b DEBUG:mcp.server.sse:Sent endpoint event: /sse/messages?session_id=4eafb7871712449abf465d7dfb6c3390 DEBUG:mcp.server.sse:Sent endpoint event: /sse/messages?session_id=6db64772fde74f8d830943a999647ee0 DEBUG:sse_starlette.sse:chunk: b'event: endpoint\r\ndata: /sse/messages?session_id=6427f59a79f14d4abd8c1e1addeb2f90\r\n\r\n' DEBUG:sse_starlette.sse:chunk: b'event: endpoint\r\ndata: /sse/messages?session_id=0f929ade94814854a8c72d987c11cd1b\r\n\r\n' DEBUG:sse_starlette.sse:chunk: b'event: endpoint\r\ndata: /sse/messages?session_id=4eafb7871712449abf465d7dfb6c3390\r\n\r\n' DEBUG:sse_starlette.sse:chunk: b'event: endpoint\r\ndata: /sse/messages?session_id=6db64772fde74f8d830943a999647ee0\r\n\r\n' INFO:mcp-detailed:[SSE] => sse_endpoint called DEBUG:mcp.server.sse:SseServerTransport initialized with endpoint: /sse/messages DEBUG:mcp.server.sse:Setting up SSE connection DEBUG:mcp.server.sse:Created new session with ID: 4e1e731c-d4be-4ef5-91c5-87dca9c998a0 DEBUG:mcp.server.sse:Starting SSE response task DEBUG:mcp.server.sse:Yielding read and write streams INFO:mcp-detailed:[SSE] run mcp_server with SSE transport => calling 'mcp_server.run' INFO: {IP}:37979 - "GET /sse HTTP/1.1" 200 OK DEBUG:mcp.server.sse:Starting SSE writer DEBUG:mcp.server.sse:Sent endpoint event: /sse/messages?session_id=4e1e731cd4be4ef591c587dca9c998a0 DEBUG:sse_starlette.sse:chunk: b'event: endpoint\r\ndata: /sse/messages?session_id=4e1e731cd4be4ef591c587dca9c998a0\r\n\r\n' INFO:mcp-detailed:[POST /sse/messages] => {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{"sampling":{},"roots":{"listChanged":true}},"clientInfo":{"name":"mcp-inspector","version":"0.0.1"}}} DEBUG:mcp-detailed:[POST] method=initialize, id=0, params={'protocolVersion': '2024-11-05', 'capabilities': {'sampling': {}, 'roots': {'listChanged': True}}, 'clientInfo': {'name': 'mcp-inspector', 'version': '0.0.1'}} INFO:mcp-detailed:Handling 'initialize' in post_handler DEBUG:mcp-detailed:Sending initialize response: {"jsonrpc": "2.0", "id": 0, "result": {"protocolVersion": "2024-11-05", "capabilities": {"tools": {"listChanged": true}, "resources": {"listChanged": true, "subscribe": true}, "prompts": {"listChanged": true}, "logging": true, "roots": {"listChanged": true}, "sampling": true}, "serverInfo": {"name": "AllInOneDummyServer", "version": "1.0.0"}, "offerings": [{"name": "upcaseTool", "description": "Tool that upcases text"}, {"name": "fakePrompt", "description": "A dummy prompt"}, {"name": "someResource", "description": "Fake resource for tests"}], "tools": [{"name": "upcase", "description": "Convert text to uppercase", "inputSchema": {"type": "object", "properties": {"text": {"type": "string", "description": "Text to uppercase"}}, "required": ["text"]}}]}} INFO: {IP}:37995 - "POST /sse/messages?session_id=4e1e731cd4be4ef591c587dca9c998a0 HTTP/1.1" 200 OK DEBUG:sse_starlette.sse:ping: b': ping - 2025-03-13 02:40:20.459813+00:00\r\n\r\n' DEBUG:sse_starlette.sse:ping: b': ping - 2025-03-13 02:40:20.463268+00:00\r\n\r\n' DEBUG:sse_starlette.sse:ping: b': ping - 2025-03-13 02:40:20.517800+00:00\r\n\r\n' DEBUG:sse_starlette.sse:ping: b': ping - 2025-03-13 02:40:20.518266+00:00\r\n\r\n' DEBUG:sse_starlette.sse:ping: b': ping - 2025-03-13 02:40:20.518759+00:00\r\n\r\n' DEBUG:sse_starlette.sse:ping: b': ping - 2025-03-13 02:40:20.531301+00:00\r\n\r\n' DEBUG:sse_starlette.sse:ping: b': ping - 2025-03-13 02:40:20.531763+00:00\r\n\r\n' DEBUG:sse_starlette.sse:ping: b': ping - 2025-03-13 02:40:20.533097+00:00\r\n\r\n' DEBUG:sse_starlette.sse:ping: b': ping - 2025-03-13 02:40:20.533400+00:00\r\n\r\n' DEBUG:mcp-detailed:[KeepAliveLoop] SSE keep-alive ping (no actual method). DEBUG:sse_starlette.sse:ping: b': ping - 2025-03-13 02:40:27.108246+00:00\r\n\r\n' DEBUG:sse_starlette.sse:ping: b': ping - 2025-03-13 02:40:35.462830+00:00\r\n\r\n' DEBUG:sse_starlette.sse:ping: b': ping - 2025-03-13 02:40:35.463590+00:00\r\n\r\n' DEBUG:sse_starlette.sse:ping: b': ping - 2025-03-13 02:40:35.519222+00:00\r\n\r\n' DEBUG:sse_starlette.sse:ping: b': ping - 2025-03-13 02:40:35.519658+00:00\r\n\r\n' DEBUG:sse_starlette.sse:ping: b': ping - 2025-03-13 02:40:35.519876+00:00\r\n\r\n' DEBUG:sse_starlette.sse:ping: b': ping - 2025-03-13 02:40:35.532655+00:00\r\n\r\n' DEBUG:sse_starlette.sse:ping: b': ping - 2025-03-13 02:40:35.533044+00:00\r\n\r\n' DEBUG:sse_starlette.sse:ping: b': ping - 2025-03-13 02:40:35.533501+00:00\r\n\r\n' DEBUG:sse_starlette.sse:ping: b': ping - 2025-03-13 02:40:35.533762+00:00\r\n\r\n'

如果我用cursorai呼叫相同

2025-03-13 10:25:28.169 [info] d0c4: Handling CreateClient action 2025-03-13 10:25:28.169 [info] d0c4: getOrCreateClient for sse server 2025-03-13 10:25:28.169 [info] d0c4: Creating SSE transport 2025-03-13 10:26:28.339 [info] d0c4: Client closed for command 2025-03-13 10:26:28.340 [error] d0c4: Error in MCP: Client closed 2025-03-13 10:26:28.340 [error] d0c4: Client error for command This operation was aborted 2025-03-13 10:26:28.341 [error] d0c4: Error in MCP: This operation was aborted 2025-03-13 10:26:28.341 [error] d0c4: Client error for command Failed to send cancellation: AbortError: This operation was aborted 2025-03-13 10:26:28.341 [error] d0c4: Error in MCP: Failed to send cancellation: AbortError: This operation was aborted 2025-03-13 10:26:28.344 [info] d0c4: Handling ListOfferings action 2025-03-13 10:26:28.345 [error] d0c4: No server info found

我真的没有任何线索,为什么没有将工具或烦恼转移到Inspector或Cursorai。我缺少什么。
我试图创建本机PHP实现,没有工具/没有转移的工具/不转移并在超时
中运行并运行

I试图创建一个LogisCape/MCP-SDK-PHP实现,没有工具/没有传输的工具/它,它会卡住并在超时

中运行 我尝试了使用SDK的Python实现,没有工具/没有传输的工具/没有插座,并且在超时
中运行并运行

有一个关于MCP的目录网站,网站:
Https://mcp.ad

,其中包含许多MPC服务器和客户端的实现以及源代码站点。我希望它可以帮助您

python cursor-ai
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.