Skip to content

Instantly share code, notes, and snippets.

@pgtwitter
Created June 29, 2025 10:31
Show Gist options
  • Save pgtwitter/e2db6f194960b1d2282742415e256238 to your computer and use it in GitHub Desktop.
Save pgtwitter/e2db6f194960b1d2282742415e256238 to your computer and use it in GitHub Desktop.
Ollamaで動かしたqwen3:14b で MCP クライアント( langchain_openai.ChatOpenAI ) / サーバ( fastmcp.FastMCP ) の実験 (プロンプト: ~/Publicフォルダ下にある,拡張子txtのファイルと拡張子worldのファイルは合わせていくつありますか? 足し算は必ずツールを使ってください.)

ハード

$ system_profiler SPHardwareDataType|grep "Chip\|Memory"
      Chip: Apple M1
      Memory: 16 GB

brewでollamaをインストール

$ brew install ollama

インストールした時に表示されたままに環境変数を設定しておく

$ env|grep OLLAMA
OLLAMA_KV_CACHE_TYPE=q8_0
OLLAMA_FLASH_ATTENTION=1

ollama を起動する

$ ollama serve
…

qwen3:14b があるか確認

$ ollama list
NAME                ID              SIZE      MODIFIED     
qwen3:14b           ------------    9.3 GB    - hours ago     

なければ pull

$ ollama pull qwen3:14b   

MCP サーバの起動

$ python mcp_server.py
DEBUG:mcp.server.lowlevel.server:Initializing server 'mcp_server'
DEBUG:mcp.server.lowlevel.server:Registering handler for ListToolsRequest
DEBUG:mcp.server.lowlevel.server:Registering handler for ListResourcesRequest
DEBUG:mcp.server.lowlevel.server:Registering handler for ListResourceTemplatesRequest
DEBUG:mcp.server.lowlevel.server:Registering handler for PromptListRequest
DEBUG:mcp.server.lowlevel.server:Registering handler for CallToolRequest
DEBUG:mcp.server.lowlevel.server:Registering handler for ReadResourceRequest
DEBUG:mcp.server.lowlevel.server:Registering handler for GetPromptRequest
DEBUG:asyncio:Using selector: KqueueSelector
DEBUG:mcp.server.sse:SseServerTransport initialized with endpoint: /messages/
INFO:FastMCP.fastmcp.server.server:Starting MCP server 'mcp_server' with transport 'sse' on http://127.0.0.1:8080/sse/
…

MCP クライアントの起動

$ python mcp_client.py
INFO:root:~/Publicフォルダ下にある,拡張子txtのファイルと拡張子worldのファイルは合わせていくつありますか?足し算は必ずツールを使ってください.
DEBUG:asyncio:Using selector: KqueueSelector
DEBUG:mcp.client.sse:Connecting to SSE endpoint: http://localhost:8080/sse/
DEBUG:httpcore.connection:connect_tcp.started host='localhost' port=8080 local_address=None timeout=5 socket_options=None
…

ollama の実行状況を確認

$ ollama ps
NAME         ID              SIZE     PROCESSOR    UNTIL              
qwen3:14b    ------------    10 GB    100% GPU     - minutes from now  

MCP サーバ の停止

Ctrl+C

ollama の停止

Ctrl+C

INFO:root:~/Publicフォルダ下にある,拡張子txtのファイルと拡張子worldのファイルは合わせていくつありますか?足し算は必ずツールを使ってください.
DEBUG:asyncio:Using selector: KqueueSelector
DEBUG:mcp.client.sse:Connecting to SSE endpoint: http://localhost:8080/sse/
DEBUG:httpcore.connection:connect_tcp.started host='localhost' port=8080 local_address=None timeout=5 socket_options=None
DEBUG:httpcore.connection:connect_tcp.complete return_value=<httpcore._backends.anyio.AnyIOStream object at 0x10b060a30>
DEBUG:httpcore.http11:send_request_headers.started request=<Request [b'GET']>
DEBUG:httpcore.http11:send_request_headers.complete
DEBUG:httpcore.http11:send_request_body.started request=<Request [b'GET']>
DEBUG:httpcore.http11:send_request_body.complete
DEBUG:httpcore.http11:receive_response_headers.started request=<Request [b'GET']>
DEBUG:httpcore.http11:receive_response_headers.complete return_value=(b'HTTP/1.1', 200, b'OK', [(b'date', b'Sun, 29 Jun 2025 09:56:28 GMT'), (b'server', b'uvicorn'), (b'cache-control', b'no-store'), (b'connection', b'keep-alive'), (b'x-accel-buffering', b'no'), (b'content-type', b'text/event-stream; charset=utf-8'), (b'Transfer-Encoding', b'chunked')])
INFO:httpx:HTTP Request: GET http://localhost:8080/sse/ "HTTP/1.1 200 OK"
DEBUG:mcp.client.sse:SSE connection established
DEBUG:httpcore.http11:receive_response_body.started request=<Request [b'GET']>
DEBUG:mcp.client.sse:Received SSE event: endpoint
DEBUG:mcp.client.sse:Received endpoint URL: http://localhost:8080/messages/?session_id=60bdd940c5924c4c8666198263ec605f
DEBUG:mcp.client.sse:Starting post writer with endpoint URL: http://localhost:8080/messages/?session_id=60bdd940c5924c4c8666198263ec605f
DEBUG:mcp.client.sse:Sending client message: SessionMessage(message=JSONRPCMessage(root=JSONRPCRequest(method='initialize', params={'protocolVersion': '2025-03-26', 'capabilities': {}, 'clientInfo': {'name': 'mcp', 'version': '0.1.0'}}, jsonrpc='2.0', id=0)), metadata=None)
DEBUG:httpcore.connection:connect_tcp.started host='localhost' port=8080 local_address=None timeout=30.0 socket_options=None
DEBUG:httpcore.connection:connect_tcp.complete return_value=<httpcore._backends.anyio.AnyIOStream object at 0x10b062320>
DEBUG:httpcore.http11:send_request_headers.started request=<Request [b'POST']>
DEBUG:httpcore.http11:send_request_headers.complete
DEBUG:httpcore.http11:send_request_body.started request=<Request [b'POST']>
DEBUG:httpcore.http11:send_request_body.complete
DEBUG:httpcore.http11:receive_response_headers.started request=<Request [b'POST']>
DEBUG:httpcore.http11:receive_response_headers.complete return_value=(b'HTTP/1.1', 202, b'Accepted', [(b'date', b'Sun, 29 Jun 2025 09:56:29 GMT'), (b'server', b'uvicorn'), (b'content-length', b'8')])
INFO:httpx:HTTP Request: POST http://localhost:8080/messages/?session_id=60bdd940c5924c4c8666198263ec605f "HTTP/1.1 202 Accepted"
DEBUG:httpcore.http11:receive_response_body.started request=<Request [b'POST']>
DEBUG:httpcore.http11:receive_response_body.complete
DEBUG:httpcore.http11:response_closed.started
DEBUG:httpcore.http11:response_closed.complete
DEBUG:mcp.client.sse:Client message sent successfully: 202
DEBUG:mcp.client.sse:Received SSE event: message
DEBUG:mcp.client.sse:Received server message: root=JSONRPCResponse(jsonrpc='2.0', id=0, result={'protocolVersion': '2025-03-26', 'capabilities': {'experimental': {}, 'prompts': {'listChanged': True}, 'resources': {'subscribe': False, 'listChanged': True}, 'tools': {'listChanged': True}}, 'serverInfo': {'name': 'mcp_server', 'version': '0.0.1'}})
DEBUG:mcp.client.sse:Sending client message: SessionMessage(message=JSONRPCMessage(root=JSONRPCNotification(method='notifications/initialized', params=None, jsonrpc='2.0')), metadata=None)
DEBUG:httpcore.http11:send_request_headers.started request=<Request [b'POST']>
DEBUG:httpcore.http11:send_request_headers.complete
DEBUG:httpcore.http11:send_request_body.started request=<Request [b'POST']>
DEBUG:httpcore.http11:send_request_body.complete
DEBUG:httpcore.http11:receive_response_headers.started request=<Request [b'POST']>
DEBUG:httpcore.http11:receive_response_headers.complete return_value=(b'HTTP/1.1', 202, b'Accepted', [(b'date', b'Sun, 29 Jun 2025 09:56:29 GMT'), (b'server', b'uvicorn'), (b'content-length', b'8')])
INFO:httpx:HTTP Request: POST http://localhost:8080/messages/?session_id=60bdd940c5924c4c8666198263ec605f "HTTP/1.1 202 Accepted"
DEBUG:httpcore.http11:receive_response_body.started request=<Request [b'POST']>
DEBUG:httpcore.http11:receive_response_body.complete
DEBUG:httpcore.http11:response_closed.started
DEBUG:httpcore.http11:response_closed.complete
DEBUG:mcp.client.sse:Client message sent successfully: 202
DEBUG:mcp.client.sse:Sending client message: SessionMessage(message=JSONRPCMessage(root=JSONRPCRequest(method='tools/list', params=None, jsonrpc='2.0', id=1)), metadata=None)
DEBUG:httpcore.http11:send_request_headers.started request=<Request [b'POST']>
DEBUG:httpcore.http11:send_request_headers.complete
DEBUG:httpcore.http11:send_request_body.started request=<Request [b'POST']>
DEBUG:httpcore.http11:send_request_body.complete
DEBUG:httpcore.http11:receive_response_headers.started request=<Request [b'POST']>
DEBUG:httpcore.http11:receive_response_headers.complete return_value=(b'HTTP/1.1', 202, b'Accepted', [(b'date', b'Sun, 29 Jun 2025 09:56:29 GMT'), (b'server', b'uvicorn'), (b'content-length', b'8')])
INFO:httpx:HTTP Request: POST http://localhost:8080/messages/?session_id=60bdd940c5924c4c8666198263ec605f "HTTP/1.1 202 Accepted"
DEBUG:httpcore.http11:receive_response_body.started request=<Request [b'POST']>
DEBUG:httpcore.http11:receive_response_body.complete
DEBUG:httpcore.http11:response_closed.started
DEBUG:httpcore.http11:response_closed.complete
DEBUG:mcp.client.sse:Client message sent successfully: 202
DEBUG:mcp.client.sse:Received SSE event: message
DEBUG:mcp.client.sse:Received server message: root=JSONRPCResponse(jsonrpc='2.0', id=1, result={'tools': [{'name': 'add_integer_numbers', 'description': 'Adds two integers and returns their sum (e.g., 3 + 5).', 'inputSchema': {'properties': {'a': {'description': 'The first number (integer).', 'title': 'A', 'type': 'integer'}, 'b': {'description': 'The second number (integer).', 'title': 'B', 'type': 'integer'}}, 'required': ['a', 'b'], 'type': 'object'}}, {'name': 'search_files', 'description': "Searches files in ~/Public using a single file name pattern (e.g., '*.txt', '*.pdf').\nCall separately for multiple patterns.\nInvalid patterns (e.g., containing '/' or starting with '.') return an empty list.", 'inputSchema': {'properties': {'pattern': {'description': "A single file name pattern (e.g., '*.txt', '*.pdf'). Must not include path components (e.g., '~/Public/*.txt') or '/' nor start with '.' (e.g., '.txt'). Call separately for each pattern.", 'title': 'Pattern', 'type': 'string'}}, 'required': ['pattern'], 'type': 'object'}}]})
DEBUG:httpcore.http11:response_closed.started
DEBUG:httpcore.http11:receive_response_body.failed exception=CancelledError('Cancelled by cancel scope 106fd3ca0')
DEBUG:httpcore.http11:response_closed.complete
DEBUG:httpcore.connection:close.started
DEBUG:httpcore.connection:close.complete
DEBUG:openai._base_client:Request options: {'method': 'post', 'url': '/chat/completions', 'files': None, 'idempotency_key': 'stainless-python-retry-8400386b-1c60-461b-9fb5-e7287fdc0eb4', 'json_data': {'messages': [{'content': '~/Publicフォルダ下にある,拡張子txtのファイルと拡張子worldのファイルは合わせていくつありますか?足し算は必ずツールを使ってください.', 'role': 'user'}], 'model': 'qwen3:14b', 'stream': False, 'tools': [{'type': 'function', 'function': {'name': 'add_integer_numbers', 'description': 'Adds two integers and returns their sum (e.g., 3 + 5).', 'parameters': {'properties': {'a': {'description': 'The first number (integer).', 'type': 'integer'}, 'b': {'description': 'The second number (integer).', 'type': 'integer'}}, 'required': ['a', 'b'], 'type': 'object'}}}, {'type': 'function', 'function': {'name': 'search_files', 'description': "Searches files in ~/Public using a single file name pattern (e.g., '*.txt', '*.pdf').\nCall separately for multiple patterns.\nInvalid patterns (e.g., containing '/' or starting with '.') return an empty list.", 'parameters': {'properties': {'pattern': {'description': "A single file name pattern (e.g., '*.txt', '*.pdf'). Must not include path components (e.g., '~/Public/*.txt') or '/' nor start with '.' (e.g., '.txt'). Call separately for each pattern.", 'type': 'string'}}, 'required': ['pattern'], 'type': 'object'}}}]}}
DEBUG:openai._base_client:Sending HTTP Request: POST http://localhost:11434/v1/chat/completions
DEBUG:httpcore.connection:connect_tcp.started host='localhost' port=11434 local_address=None timeout=None socket_options=None
DEBUG:httpcore.connection:connect_tcp.complete return_value=<httpcore._backends.anyio.AnyIOStream object at 0x10b0609a0>
DEBUG:httpcore.http11:send_request_headers.started request=<Request [b'POST']>
DEBUG:httpcore.http11:send_request_headers.complete
DEBUG:httpcore.http11:send_request_body.started request=<Request [b'POST']>
DEBUG:httpcore.http11:send_request_body.complete
DEBUG:httpcore.http11:receive_response_headers.started request=<Request [b'POST']>
DEBUG:httpcore.http11:receive_response_headers.complete return_value=(b'HTTP/1.1', 200, b'OK', [(b'Content-Type', b'application/json'), (b'Date', b'Sun, 29 Jun 2025 09:57:50 GMT'), (b'Content-Length', b'1716')])
INFO:httpx:HTTP Request: POST http://localhost:11434/v1/chat/completions "HTTP/1.1 200 OK"
DEBUG:httpcore.http11:receive_response_body.started request=<Request [b'POST']>
DEBUG:httpcore.http11:receive_response_body.complete
DEBUG:httpcore.http11:response_closed.started
DEBUG:httpcore.http11:response_closed.complete
DEBUG:openai._base_client:HTTP Response: POST http://localhost:11434/v1/chat/completions "200 OK" Headers({'content-type': 'application/json', 'date': 'Sun, 29 Jun 2025 09:57:50 GMT', 'content-length': '1716'})
DEBUG:openai._base_client:request_id: None
DEBUG:mcp.client.sse:Connecting to SSE endpoint: http://localhost:8080/sse/
DEBUG:mcp.client.sse:Connecting to SSE endpoint: http://localhost:8080/sse/
DEBUG:httpcore.connection:connect_tcp.started host='localhost' port=8080 local_address=None timeout=5 socket_options=None
DEBUG:httpcore.connection:connect_tcp.started host='localhost' port=8080 local_address=None timeout=5 socket_options=None
DEBUG:httpcore.connection:connect_tcp.complete return_value=<httpcore._backends.anyio.AnyIOStream object at 0x10b175b10>
DEBUG:httpcore.http11:send_request_headers.started request=<Request [b'GET']>
DEBUG:httpcore.http11:send_request_headers.complete
DEBUG:httpcore.http11:send_request_body.started request=<Request [b'GET']>
DEBUG:httpcore.http11:send_request_body.complete
DEBUG:httpcore.http11:receive_response_headers.started request=<Request [b'GET']>
DEBUG:httpcore.connection:connect_tcp.complete return_value=<httpcore._backends.anyio.AnyIOStream object at 0x10b175ed0>
DEBUG:httpcore.http11:send_request_headers.started request=<Request [b'GET']>
DEBUG:httpcore.http11:send_request_headers.complete
DEBUG:httpcore.http11:send_request_body.started request=<Request [b'GET']>
DEBUG:httpcore.http11:send_request_body.complete
DEBUG:httpcore.http11:receive_response_headers.started request=<Request [b'GET']>
DEBUG:httpcore.http11:receive_response_headers.complete return_value=(b'HTTP/1.1', 200, b'OK', [(b'date', b'Sun, 29 Jun 2025 09:57:49 GMT'), (b'server', b'uvicorn'), (b'cache-control', b'no-store'), (b'connection', b'keep-alive'), (b'x-accel-buffering', b'no'), (b'content-type', b'text/event-stream; charset=utf-8'), (b'Transfer-Encoding', b'chunked')])
INFO:httpx:HTTP Request: GET http://localhost:8080/sse/ "HTTP/1.1 200 OK"
DEBUG:mcp.client.sse:SSE connection established
DEBUG:httpcore.http11:receive_response_body.started request=<Request [b'GET']>
DEBUG:mcp.client.sse:Received SSE event: endpoint
DEBUG:mcp.client.sse:Received endpoint URL: http://localhost:8080/messages/?session_id=6eac8fa491624d39a9a4fd17ccb7c8cf
DEBUG:mcp.client.sse:Starting post writer with endpoint URL: http://localhost:8080/messages/?session_id=6eac8fa491624d39a9a4fd17ccb7c8cf
DEBUG:httpcore.http11:receive_response_headers.complete return_value=(b'HTTP/1.1', 200, b'OK', [(b'date', b'Sun, 29 Jun 2025 09:57:49 GMT'), (b'server', b'uvicorn'), (b'cache-control', b'no-store'), (b'connection', b'keep-alive'), (b'x-accel-buffering', b'no'), (b'content-type', b'text/event-stream; charset=utf-8'), (b'Transfer-Encoding', b'chunked')])
INFO:httpx:HTTP Request: GET http://localhost:8080/sse/ "HTTP/1.1 200 OK"
DEBUG:mcp.client.sse:SSE connection established
DEBUG:mcp.client.sse:Sending client message: SessionMessage(message=JSONRPCMessage(root=JSONRPCRequest(method='initialize', params={'protocolVersion': '2025-03-26', 'capabilities': {}, 'clientInfo': {'name': 'mcp', 'version': '0.1.0'}}, jsonrpc='2.0', id=0)), metadata=None)
DEBUG:httpcore.http11:receive_response_body.started request=<Request [b'GET']>
DEBUG:mcp.client.sse:Received SSE event: endpoint
DEBUG:mcp.client.sse:Received endpoint URL: http://localhost:8080/messages/?session_id=515beedce7794e88824113ace8149d1b
DEBUG:httpcore.connection:connect_tcp.started host='localhost' port=8080 local_address=None timeout=30.0 socket_options=None
DEBUG:mcp.client.sse:Starting post writer with endpoint URL: http://localhost:8080/messages/?session_id=515beedce7794e88824113ace8149d1b
DEBUG:mcp.client.sse:Sending client message: SessionMessage(message=JSONRPCMessage(root=JSONRPCRequest(method='initialize', params={'protocolVersion': '2025-03-26', 'capabilities': {}, 'clientInfo': {'name': 'mcp', 'version': '0.1.0'}}, jsonrpc='2.0', id=0)), metadata=None)
DEBUG:httpcore.connection:connect_tcp.started host='localhost' port=8080 local_address=None timeout=30.0 socket_options=None
DEBUG:httpcore.connection:connect_tcp.complete return_value=<httpcore._backends.anyio.AnyIOStream object at 0x10b177c70>
DEBUG:httpcore.http11:send_request_headers.started request=<Request [b'POST']>
DEBUG:httpcore.http11:send_request_headers.complete
DEBUG:httpcore.http11:send_request_body.started request=<Request [b'POST']>
DEBUG:httpcore.connection:connect_tcp.complete return_value=<httpcore._backends.anyio.AnyIOStream object at 0x10b1a54e0>
DEBUG:httpcore.http11:send_request_body.complete
DEBUG:httpcore.http11:receive_response_headers.started request=<Request [b'POST']>
DEBUG:httpcore.http11:send_request_headers.started request=<Request [b'POST']>
DEBUG:httpcore.http11:send_request_headers.complete
DEBUG:httpcore.http11:send_request_body.started request=<Request [b'POST']>
DEBUG:httpcore.http11:send_request_body.complete
DEBUG:httpcore.http11:receive_response_headers.started request=<Request [b'POST']>
DEBUG:httpcore.http11:receive_response_headers.complete return_value=(b'HTTP/1.1', 202, b'Accepted', [(b'date', b'Sun, 29 Jun 2025 09:57:49 GMT'), (b'server', b'uvicorn'), (b'content-length', b'8')])
INFO:httpx:HTTP Request: POST http://localhost:8080/messages/?session_id=6eac8fa491624d39a9a4fd17ccb7c8cf "HTTP/1.1 202 Accepted"
DEBUG:httpcore.http11:receive_response_body.started request=<Request [b'POST']>
DEBUG:httpcore.http11:receive_response_body.complete
DEBUG:httpcore.http11:response_closed.started
DEBUG:httpcore.http11:response_closed.complete
DEBUG:mcp.client.sse:Client message sent successfully: 202
DEBUG:httpcore.http11:receive_response_headers.complete return_value=(b'HTTP/1.1', 202, b'Accepted', [(b'date', b'Sun, 29 Jun 2025 09:57:49 GMT'), (b'server', b'uvicorn'), (b'content-length', b'8')])
INFO:httpx:HTTP Request: POST http://localhost:8080/messages/?session_id=515beedce7794e88824113ace8149d1b "HTTP/1.1 202 Accepted"
DEBUG:httpcore.http11:receive_response_body.started request=<Request [b'POST']>
DEBUG:httpcore.http11:receive_response_body.complete
DEBUG:httpcore.http11:response_closed.started
DEBUG:httpcore.http11:response_closed.complete
DEBUG:mcp.client.sse:Client message sent successfully: 202
DEBUG:mcp.client.sse:Received SSE event: message
DEBUG:mcp.client.sse:Received server message: root=JSONRPCResponse(jsonrpc='2.0', id=0, result={'protocolVersion': '2025-03-26', 'capabilities': {'experimental': {}, 'prompts': {'listChanged': True}, 'resources': {'subscribe': False, 'listChanged': True}, 'tools': {'listChanged': True}}, 'serverInfo': {'name': 'mcp_server', 'version': '0.0.1'}})
DEBUG:mcp.client.sse:Received SSE event: message
DEBUG:mcp.client.sse:Received server message: root=JSONRPCResponse(jsonrpc='2.0', id=0, result={'protocolVersion': '2025-03-26', 'capabilities': {'experimental': {}, 'prompts': {'listChanged': True}, 'resources': {'subscribe': False, 'listChanged': True}, 'tools': {'listChanged': True}}, 'serverInfo': {'name': 'mcp_server', 'version': '0.0.1'}})
DEBUG:mcp.client.sse:Sending client message: SessionMessage(message=JSONRPCMessage(root=JSONRPCNotification(method='notifications/initialized', params=None, jsonrpc='2.0')), metadata=None)
DEBUG:httpcore.http11:send_request_headers.started request=<Request [b'POST']>
DEBUG:mcp.client.sse:Sending client message: SessionMessage(message=JSONRPCMessage(root=JSONRPCNotification(method='notifications/initialized', params=None, jsonrpc='2.0')), metadata=None)
DEBUG:httpcore.http11:send_request_headers.complete
DEBUG:httpcore.http11:send_request_body.started request=<Request [b'POST']>
DEBUG:httpcore.http11:send_request_body.complete
DEBUG:httpcore.http11:receive_response_headers.started request=<Request [b'POST']>
DEBUG:httpcore.http11:send_request_headers.started request=<Request [b'POST']>
DEBUG:httpcore.http11:send_request_headers.complete
DEBUG:httpcore.http11:send_request_body.started request=<Request [b'POST']>
DEBUG:httpcore.http11:send_request_body.complete
DEBUG:httpcore.http11:receive_response_headers.started request=<Request [b'POST']>
DEBUG:httpcore.http11:receive_response_headers.complete return_value=(b'HTTP/1.1', 202, b'Accepted', [(b'date', b'Sun, 29 Jun 2025 09:57:49 GMT'), (b'server', b'uvicorn'), (b'content-length', b'8')])
INFO:httpx:HTTP Request: POST http://localhost:8080/messages/?session_id=6eac8fa491624d39a9a4fd17ccb7c8cf "HTTP/1.1 202 Accepted"
DEBUG:httpcore.http11:receive_response_body.started request=<Request [b'POST']>
DEBUG:httpcore.http11:receive_response_body.complete
DEBUG:httpcore.http11:response_closed.started
DEBUG:httpcore.http11:response_closed.complete
DEBUG:mcp.client.sse:Client message sent successfully: 202
DEBUG:mcp.client.sse:Sending client message: SessionMessage(message=JSONRPCMessage(root=JSONRPCRequest(method='tools/call', params={'name': 'search_files', 'arguments': {'pattern': '*.txt'}}, jsonrpc='2.0', id=1)), metadata=None)
DEBUG:httpcore.http11:receive_response_headers.complete return_value=(b'HTTP/1.1', 202, b'Accepted', [(b'date', b'Sun, 29 Jun 2025 09:57:49 GMT'), (b'server', b'uvicorn'), (b'content-length', b'8')])
INFO:httpx:HTTP Request: POST http://localhost:8080/messages/?session_id=515beedce7794e88824113ace8149d1b "HTTP/1.1 202 Accepted"
DEBUG:httpcore.http11:receive_response_body.started request=<Request [b'POST']>
DEBUG:httpcore.http11:receive_response_body.complete
DEBUG:httpcore.http11:response_closed.started
DEBUG:httpcore.http11:response_closed.complete
DEBUG:mcp.client.sse:Client message sent successfully: 202
DEBUG:httpcore.http11:send_request_headers.started request=<Request [b'POST']>
DEBUG:mcp.client.sse:Sending client message: SessionMessage(message=JSONRPCMessage(root=JSONRPCRequest(method='tools/call', params={'name': 'search_files', 'arguments': {'pattern': '*.world'}}, jsonrpc='2.0', id=1)), metadata=None)
DEBUG:httpcore.http11:send_request_headers.complete
DEBUG:httpcore.http11:send_request_body.started request=<Request [b'POST']>
DEBUG:httpcore.http11:send_request_body.complete
DEBUG:httpcore.http11:receive_response_headers.started request=<Request [b'POST']>
DEBUG:httpcore.http11:send_request_headers.started request=<Request [b'POST']>
DEBUG:httpcore.http11:send_request_headers.complete
DEBUG:httpcore.http11:send_request_body.started request=<Request [b'POST']>
DEBUG:httpcore.http11:send_request_body.complete
DEBUG:httpcore.http11:receive_response_headers.started request=<Request [b'POST']>
DEBUG:httpcore.http11:receive_response_headers.complete return_value=(b'HTTP/1.1', 202, b'Accepted', [(b'date', b'Sun, 29 Jun 2025 09:57:49 GMT'), (b'server', b'uvicorn'), (b'content-length', b'8')])
INFO:httpx:HTTP Request: POST http://localhost:8080/messages/?session_id=6eac8fa491624d39a9a4fd17ccb7c8cf "HTTP/1.1 202 Accepted"
DEBUG:httpcore.http11:receive_response_body.started request=<Request [b'POST']>
DEBUG:httpcore.http11:receive_response_body.complete
DEBUG:httpcore.http11:response_closed.started
DEBUG:httpcore.http11:response_closed.complete
DEBUG:mcp.client.sse:Client message sent successfully: 202
DEBUG:httpcore.http11:receive_response_headers.complete return_value=(b'HTTP/1.1', 202, b'Accepted', [(b'date', b'Sun, 29 Jun 2025 09:57:49 GMT'), (b'server', b'uvicorn'), (b'content-length', b'8')])
INFO:httpx:HTTP Request: POST http://localhost:8080/messages/?session_id=515beedce7794e88824113ace8149d1b "HTTP/1.1 202 Accepted"
DEBUG:httpcore.http11:receive_response_body.started request=<Request [b'POST']>
DEBUG:httpcore.http11:receive_response_body.complete
DEBUG:httpcore.http11:response_closed.started
DEBUG:httpcore.http11:response_closed.complete
DEBUG:mcp.client.sse:Client message sent successfully: 202
DEBUG:mcp.client.sse:Received SSE event: message
DEBUG:mcp.client.sse:Received server message: root=JSONRPCResponse(jsonrpc='2.0', id=1, result={'content': [{'type': 'text', 'text': '{\n "files": [\n "HelloWorld.txt",\n "FooBar.txt"\n ]\n}'}], 'isError': False})
DEBUG:mcp.client.sse:Received SSE event: message
DEBUG:mcp.client.sse:Received server message: root=JSONRPCResponse(jsonrpc='2.0', id=1, result={'content': [{'type': 'text', 'text': '{\n "files": [\n "hello.world",\n "Hoge.world"\n ]\n}'}], 'isError': False})
DEBUG:httpcore.http11:response_closed.started
DEBUG:httpcore.http11:receive_response_body.failed exception=CancelledError('Cancelled by cancel scope 10b061780')
DEBUG:httpcore.http11:response_closed.complete
DEBUG:httpcore.connection:close.started
DEBUG:httpcore.http11:response_closed.started
DEBUG:httpcore.connection:close.complete
DEBUG:httpcore.http11:receive_response_body.failed exception=CancelledError('Cancelled by cancel scope 10b174d00')
DEBUG:httpcore.http11:response_closed.complete
DEBUG:httpcore.connection:close.started
DEBUG:httpcore.connection:close.complete
DEBUG:openai._base_client:Request options: {'method': 'post', 'url': '/chat/completions', 'files': None, 'idempotency_key': 'stainless-python-retry-6b2d505f-00f0-4141-827a-64dd0600c734', 'json_data': {'messages': [{'content': '~/Publicフォルダ下にある,拡張子txtのファイルと拡張子worldのファイルは合わせていくつありますか?足し算は必ずツールを使ってください.', 'role': 'user'}, {'content': '<think>\nOkay, the user is asking how many .txt and .world files are in the ~/Public folder. They also specified that addition must be done using a tool. Let me check the available functions.\n\nFirst, the search_files function can be used to find files by pattern. The parameters require a pattern without path components or slashes. So for .txt files, I can use "*.txt" and for .world, "*.world". I need to call the function twice, once for each pattern.\n\nWait, the user mentioned "合わせていくつありますか" which means they want the total number of both types. So after getting the counts from each search, I need to add them. The add_integer_numbers function can be used for that. \n\nSo the steps are: \n1. Call search_files with "*.txt" to get the count of txt files.\n2. Call search_files with "*.world" to get the count of world files.\n3. Use add_integer_numbers to sum the two results.\n\nI need to make sure that the patterns are valid. The function says invalid patterns return empty lists, but as long as the patterns are correct, it should work. Let\'s proceed with those function calls.\n</think>\n\n', 'role': 'assistant', 'tool_calls': [{'type': 'function', 'id': 'call_v4ltn8wd', 'function': {'name': 'search_files', 'arguments': '{"pattern": "*.txt"}'}}, {'type': 'function', 'id': 'call_4uoccx76', 'function': {'name': 'search_files', 'arguments': '{"pattern": "*.world"}'}}]}, {'content': '{\n "files": [\n "HelloWorld.txt",\n "FooBar.txt"\n ]\n}', 'role': 'tool', 'tool_call_id': 'call_v4ltn8wd'}, {'content': '{\n "files": [\n "hello.world",\n "Hoge.world"\n ]\n}', 'role': 'tool', 'tool_call_id': 'call_4uoccx76'}], 'model': 'qwen3:14b', 'stream': False, 'tools': [{'type': 'function', 'function': {'name': 'add_integer_numbers', 'description': 'Adds two integers and returns their sum (e.g., 3 + 5).', 'parameters': {'properties': {'a': {'description': 'The first number (integer).', 'type': 'integer'}, 'b': {'description': 'The second number (integer).', 'type': 'integer'}}, 'required': ['a', 'b'], 'type': 'object'}}}, {'type': 'function', 'function': {'name': 'search_files', 'description': "Searches files in ~/Public using a single file name pattern (e.g., '*.txt', '*.pdf').\nCall separately for multiple patterns.\nInvalid patterns (e.g., containing '/' or starting with '.') return an empty list.", 'parameters': {'properties': {'pattern': {'description': "A single file name pattern (e.g., '*.txt', '*.pdf'). Must not include path components (e.g., '~/Public/*.txt') or '/' nor start with '.' (e.g., '.txt'). Call separately for each pattern.", 'type': 'string'}}, 'required': ['pattern'], 'type': 'object'}}}]}}
DEBUG:openai._base_client:Sending HTTP Request: POST http://localhost:11434/v1/chat/completions
DEBUG:httpcore.http11:send_request_headers.started request=<Request [b'POST']>
DEBUG:httpcore.http11:send_request_headers.complete
DEBUG:httpcore.http11:send_request_body.started request=<Request [b'POST']>
DEBUG:httpcore.http11:send_request_body.complete
DEBUG:httpcore.http11:receive_response_headers.started request=<Request [b'POST']>
DEBUG:httpcore.http11:receive_response_headers.complete return_value=(b'HTTP/1.1', 200, b'OK', [(b'Content-Type', b'application/json'), (b'Date', b'Sun, 29 Jun 2025 09:58:44 GMT'), (b'Content-Length', b'1121')])
INFO:httpx:HTTP Request: POST http://localhost:11434/v1/chat/completions "HTTP/1.1 200 OK"
DEBUG:httpcore.http11:receive_response_body.started request=<Request [b'POST']>
DEBUG:httpcore.http11:receive_response_body.complete
DEBUG:httpcore.http11:response_closed.started
DEBUG:httpcore.http11:response_closed.complete
DEBUG:openai._base_client:HTTP Response: POST http://localhost:11434/v1/chat/completions "200 OK" Headers({'content-type': 'application/json', 'date': 'Sun, 29 Jun 2025 09:58:44 GMT', 'content-length': '1121'})
DEBUG:openai._base_client:request_id: None
DEBUG:mcp.client.sse:Connecting to SSE endpoint: http://localhost:8080/sse/
DEBUG:httpcore.connection:connect_tcp.started host='localhost' port=8080 local_address=None timeout=5 socket_options=None
DEBUG:httpcore.connection:connect_tcp.complete return_value=<httpcore._backends.anyio.AnyIOStream object at 0x10b1749a0>
DEBUG:httpcore.http11:send_request_headers.started request=<Request [b'GET']>
DEBUG:httpcore.http11:send_request_headers.complete
DEBUG:httpcore.http11:send_request_body.started request=<Request [b'GET']>
DEBUG:httpcore.http11:send_request_body.complete
DEBUG:httpcore.http11:receive_response_headers.started request=<Request [b'GET']>
DEBUG:httpcore.http11:receive_response_headers.complete return_value=(b'HTTP/1.1', 200, b'OK', [(b'date', b'Sun, 29 Jun 2025 09:58:44 GMT'), (b'server', b'uvicorn'), (b'cache-control', b'no-store'), (b'connection', b'keep-alive'), (b'x-accel-buffering', b'no'), (b'content-type', b'text/event-stream; charset=utf-8'), (b'Transfer-Encoding', b'chunked')])
INFO:httpx:HTTP Request: GET http://localhost:8080/sse/ "HTTP/1.1 200 OK"
DEBUG:mcp.client.sse:SSE connection established
DEBUG:httpcore.http11:receive_response_body.started request=<Request [b'GET']>
DEBUG:mcp.client.sse:Received SSE event: endpoint
DEBUG:mcp.client.sse:Received endpoint URL: http://localhost:8080/messages/?session_id=11d4624ce3744e24a417893e9bfd8ee1
DEBUG:mcp.client.sse:Starting post writer with endpoint URL: http://localhost:8080/messages/?session_id=11d4624ce3744e24a417893e9bfd8ee1
DEBUG:mcp.client.sse:Sending client message: SessionMessage(message=JSONRPCMessage(root=JSONRPCRequest(method='initialize', params={'protocolVersion': '2025-03-26', 'capabilities': {}, 'clientInfo': {'name': 'mcp', 'version': '0.1.0'}}, jsonrpc='2.0', id=0)), metadata=None)
DEBUG:httpcore.connection:connect_tcp.started host='localhost' port=8080 local_address=None timeout=30.0 socket_options=None
DEBUG:httpcore.connection:connect_tcp.complete return_value=<httpcore._backends.anyio.AnyIOStream object at 0x10b117a30>
DEBUG:httpcore.http11:send_request_headers.started request=<Request [b'POST']>
DEBUG:httpcore.http11:send_request_headers.complete
DEBUG:httpcore.http11:send_request_body.started request=<Request [b'POST']>
DEBUG:httpcore.http11:send_request_body.complete
DEBUG:httpcore.http11:receive_response_headers.started request=<Request [b'POST']>
DEBUG:httpcore.http11:receive_response_headers.complete return_value=(b'HTTP/1.1', 202, b'Accepted', [(b'date', b'Sun, 29 Jun 2025 09:58:44 GMT'), (b'server', b'uvicorn'), (b'content-length', b'8')])
INFO:httpx:HTTP Request: POST http://localhost:8080/messages/?session_id=11d4624ce3744e24a417893e9bfd8ee1 "HTTP/1.1 202 Accepted"
DEBUG:httpcore.http11:receive_response_body.started request=<Request [b'POST']>
DEBUG:httpcore.http11:receive_response_body.complete
DEBUG:httpcore.http11:response_closed.started
DEBUG:httpcore.http11:response_closed.complete
DEBUG:mcp.client.sse:Client message sent successfully: 202
DEBUG:mcp.client.sse:Received SSE event: message
DEBUG:mcp.client.sse:Received server message: root=JSONRPCResponse(jsonrpc='2.0', id=0, result={'protocolVersion': '2025-03-26', 'capabilities': {'experimental': {}, 'prompts': {'listChanged': True}, 'resources': {'subscribe': False, 'listChanged': True}, 'tools': {'listChanged': True}}, 'serverInfo': {'name': 'mcp_server', 'version': '0.0.1'}})
DEBUG:mcp.client.sse:Sending client message: SessionMessage(message=JSONRPCMessage(root=JSONRPCNotification(method='notifications/initialized', params=None, jsonrpc='2.0')), metadata=None)
DEBUG:httpcore.http11:send_request_headers.started request=<Request [b'POST']>
DEBUG:httpcore.http11:send_request_headers.complete
DEBUG:httpcore.http11:send_request_body.started request=<Request [b'POST']>
DEBUG:httpcore.http11:send_request_body.complete
DEBUG:httpcore.http11:receive_response_headers.started request=<Request [b'POST']>
DEBUG:httpcore.http11:receive_response_headers.complete return_value=(b'HTTP/1.1', 202, b'Accepted', [(b'date', b'Sun, 29 Jun 2025 09:58:44 GMT'), (b'server', b'uvicorn'), (b'content-length', b'8')])
INFO:httpx:HTTP Request: POST http://localhost:8080/messages/?session_id=11d4624ce3744e24a417893e9bfd8ee1 "HTTP/1.1 202 Accepted"
DEBUG:httpcore.http11:receive_response_body.started request=<Request [b'POST']>
DEBUG:httpcore.http11:receive_response_body.complete
DEBUG:httpcore.http11:response_closed.started
DEBUG:httpcore.http11:response_closed.complete
DEBUG:mcp.client.sse:Client message sent successfully: 202
DEBUG:mcp.client.sse:Sending client message: SessionMessage(message=JSONRPCMessage(root=JSONRPCRequest(method='tools/call', params={'name': 'add_integer_numbers', 'arguments': {'a': 2, 'b': 2}}, jsonrpc='2.0', id=1)), metadata=None)
DEBUG:httpcore.http11:send_request_headers.started request=<Request [b'POST']>
DEBUG:httpcore.http11:send_request_headers.complete
DEBUG:httpcore.http11:send_request_body.started request=<Request [b'POST']>
DEBUG:httpcore.http11:send_request_body.complete
DEBUG:httpcore.http11:receive_response_headers.started request=<Request [b'POST']>
DEBUG:httpcore.http11:receive_response_headers.complete return_value=(b'HTTP/1.1', 202, b'Accepted', [(b'date', b'Sun, 29 Jun 2025 09:58:44 GMT'), (b'server', b'uvicorn'), (b'content-length', b'8')])
INFO:httpx:HTTP Request: POST http://localhost:8080/messages/?session_id=11d4624ce3744e24a417893e9bfd8ee1 "HTTP/1.1 202 Accepted"
DEBUG:httpcore.http11:receive_response_body.started request=<Request [b'POST']>
DEBUG:httpcore.http11:receive_response_body.complete
DEBUG:httpcore.http11:response_closed.started
DEBUG:httpcore.http11:response_closed.complete
DEBUG:mcp.client.sse:Client message sent successfully: 202
DEBUG:mcp.client.sse:Received SSE event: message
DEBUG:mcp.client.sse:Received server message: root=JSONRPCResponse(jsonrpc='2.0', id=1, result={'content': [{'type': 'text', 'text': '4'}], 'isError': False})
DEBUG:httpcore.http11:response_closed.started
DEBUG:httpcore.http11:receive_response_body.failed exception=CancelledError('Cancelled by cancel scope 10b1a49d0')
DEBUG:httpcore.http11:response_closed.complete
DEBUG:httpcore.connection:close.started
DEBUG:httpcore.connection:close.complete
DEBUG:openai._base_client:Request options: {'method': 'post', 'url': '/chat/completions', 'files': None, 'idempotency_key': 'stainless-python-retry-27be5e0e-e7d9-46ba-a644-3ce15a2e93fe', 'json_data': {'messages': [{'content': '~/Publicフォルダ下にある,拡張子txtのファイルと拡張子worldのファイルは合わせていくつありますか?足し算は必ずツールを使ってください.', 'role': 'user'}, {'content': '<think>\nOkay, the user is asking how many .txt and .world files are in the ~/Public folder. They also specified that addition must be done using a tool. Let me check the available functions.\n\nFirst, the search_files function can be used to find files by pattern. The parameters require a pattern without path components or slashes. So for .txt files, I can use "*.txt" and for .world, "*.world". I need to call the function twice, once for each pattern.\n\nWait, the user mentioned "合わせていくつありますか" which means they want the total number of both types. So after getting the counts from each search, I need to add them. The add_integer_numbers function can be used for that. \n\nSo the steps are: \n1. Call search_files with "*.txt" to get the count of txt files.\n2. Call search_files with "*.world" to get the count of world files.\n3. Use add_integer_numbers to sum the two results.\n\nI need to make sure that the patterns are valid. The function says invalid patterns return empty lists, but as long as the patterns are correct, it should work. Let\'s proceed with those function calls.\n</think>\n\n', 'role': 'assistant', 'tool_calls': [{'type': 'function', 'id': 'call_v4ltn8wd', 'function': {'name': 'search_files', 'arguments': '{"pattern": "*.txt"}'}}, {'type': 'function', 'id': 'call_4uoccx76', 'function': {'name': 'search_files', 'arguments': '{"pattern": "*.world"}'}}]}, {'content': '{\n "files": [\n "HelloWorld.txt",\n "FooBar.txt"\n ]\n}', 'role': 'tool', 'tool_call_id': 'call_v4ltn8wd'}, {'content': '{\n "files": [\n "hello.world",\n "Hoge.world"\n ]\n}', 'role': 'tool', 'tool_call_id': 'call_4uoccx76'}, {'content': '<think>\nOkay, let me see. The user asked for the number of .txt and .world files in the ~/Public folder and wants the sum using the add_integer_numbers tool.\n\nFirst, I called search_files for "*.txt" and got 2 files. Then, I called search_files for "*.world" and got 2 files as well. Now, I need to add these two numbers together. \n\nSo, I\'ll use the add_integer_numbers function with a=2 and b=2. The result should be 4. That\'s the total number of files. I need to make sure I format the tool call correctly in JSON inside the XML tags. Let me check the parameters again to confirm. Yep, both are integers. Alright, time to output the tool call.\n</think>\n\n', 'role': 'assistant', 'tool_calls': [{'type': 'function', 'id': 'call_7zpkjx9q', 'function': {'name': 'add_integer_numbers', 'arguments': '{"a": 2, "b": 2}'}}]}, {'content': '4', 'role': 'tool', 'tool_call_id': 'call_7zpkjx9q'}], 'model': 'qwen3:14b', 'stream': False, 'tools': [{'type': 'function', 'function': {'name': 'add_integer_numbers', 'description': 'Adds two integers and returns their sum (e.g., 3 + 5).', 'parameters': {'properties': {'a': {'description': 'The first number (integer).', 'type': 'integer'}, 'b': {'description': 'The second number (integer).', 'type': 'integer'}}, 'required': ['a', 'b'], 'type': 'object'}}}, {'type': 'function', 'function': {'name': 'search_files', 'description': "Searches files in ~/Public using a single file name pattern (e.g., '*.txt', '*.pdf').\nCall separately for multiple patterns.\nInvalid patterns (e.g., containing '/' or starting with '.') return an empty list.", 'parameters': {'properties': {'pattern': {'description': "A single file name pattern (e.g., '*.txt', '*.pdf'). Must not include path components (e.g., '~/Public/*.txt') or '/' nor start with '.' (e.g., '.txt'). Call separately for each pattern.", 'type': 'string'}}, 'required': ['pattern'], 'type': 'object'}}}]}}
DEBUG:openai._base_client:Sending HTTP Request: POST http://localhost:11434/v1/chat/completions
DEBUG:httpcore.http11:send_request_headers.started request=<Request [b'POST']>
DEBUG:httpcore.http11:send_request_headers.complete
DEBUG:httpcore.http11:send_request_body.started request=<Request [b'POST']>
DEBUG:httpcore.http11:send_request_body.complete
DEBUG:httpcore.http11:receive_response_headers.started request=<Request [b'POST']>
DEBUG:httpcore.http11:receive_response_headers.complete return_value=(b'HTTP/1.1', 200, b'OK', [(b'Content-Type', b'application/json'), (b'Date', b'Sun, 29 Jun 2025 09:59:28 GMT'), (b'Content-Length', b'916')])
INFO:httpx:HTTP Request: POST http://localhost:11434/v1/chat/completions "HTTP/1.1 200 OK"
DEBUG:httpcore.http11:receive_response_body.started request=<Request [b'POST']>
DEBUG:httpcore.http11:receive_response_body.complete
DEBUG:httpcore.http11:response_closed.started
DEBUG:httpcore.http11:response_closed.complete
DEBUG:openai._base_client:HTTP Response: POST http://localhost:11434/v1/chat/completions "200 OK" Headers({'content-type': 'application/json', 'date': 'Sun, 29 Jun 2025 09:59:28 GMT', 'content-length': '916'})
DEBUG:openai._base_client:request_id: None
INFO:root:<think>
Okay, let me recap. The user asked how many .txt and .world files are in the ~/Public folder and wanted the total using the add_integer_numbers tool.
First, I used search_files for "*.txt" and found 2 files. Then, another search for "*.world" also returned 2 files. Adding them with the add_integer_numbers function gave 4. The tool response confirmed the sum is 4. So, the final answer should be 4. I need to make sure I present this clearly in the box.
</think>
~/Publicフォルダ下にある拡張子txtのファイルと拡張子worldのファイルの総数は、**4**個です。
import asyncio
from langchain_mcp_adapters.client import MultiServerMCPClient
from langgraph.prebuilt import create_react_agent
from langchain_openai import ChatOpenAI
import logging
logging.basicConfig(level=logging.DEBUG, handlers=[logging.FileHandler('mcp_client.log'), logging.StreamHandler()])
async def run_agent(message):
ollama_client = ChatOpenAI(base_url="http://localhost:11434/v1", api_key="not-needed", model="qwen3:14b")
mcp_client = MultiServerMCPClient({"mcp_server": {"url": "http://localhost:8080/sse/", "transport": "sse"}})
tools = await mcp_client.get_tools()
agent = create_react_agent(ollama_client, tools)
response = await agent.ainvoke({"messages": [{"role": "user", "content": message}]})
return response["messages"][-1].content
if __name__ == "__main__":
prompt = "~/Publicフォルダ下にある,拡張子txtのファイルと拡張子worldのファイルは合わせていくつありますか?足し算は必ずツールを使ってください."
logging.info(prompt)
result = asyncio.run(run_agent(prompt))
logging.info(result)
DEBUG:mcp.server.lowlevel.server:Initializing server 'mcp_server'
DEBUG:mcp.server.lowlevel.server:Registering handler for ListToolsRequest
DEBUG:mcp.server.lowlevel.server:Registering handler for ListResourcesRequest
DEBUG:mcp.server.lowlevel.server:Registering handler for ListResourceTemplatesRequest
DEBUG:mcp.server.lowlevel.server:Registering handler for PromptListRequest
DEBUG:mcp.server.lowlevel.server:Registering handler for CallToolRequest
DEBUG:mcp.server.lowlevel.server:Registering handler for ReadResourceRequest
DEBUG:mcp.server.lowlevel.server:Registering handler for GetPromptRequest
DEBUG:asyncio:Using selector: KqueueSelector
DEBUG:mcp.server.sse:SseServerTransport initialized with endpoint: /messages/
INFO:FastMCP.fastmcp.server.server:Starting MCP server 'mcp_server' with transport 'sse' on http://127.0.0.1:8080/sse/
DEBUG:mcp.server.sse:Setting up SSE connection
DEBUG:mcp.server.sse:Created new session with ID: 60bdd940-c592-4c4c-8666-198263ec605f
DEBUG:mcp.server.sse:Starting SSE response task
DEBUG:mcp.server.sse:Yielding read and write streams
DEBUG:mcp.server.sse:Starting SSE writer
DEBUG:mcp.server.sse:Sent endpoint event: /messages/?session_id=60bdd940c5924c4c8666198263ec605f
DEBUG:sse_starlette.sse:chunk: b'event: endpoint\r\ndata: /messages/?session_id=60bdd940c5924c4c8666198263ec605f\r\n\r\n'
DEBUG:mcp.server.sse:Handling POST message
DEBUG:mcp.server.sse:Parsed session ID: 60bdd940-c592-4c4c-8666-198263ec605f
DEBUG:mcp.server.sse:Received JSON: b'{"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"mcp","version":"0.1.0"}},"jsonrpc":"2.0","id":0}'
DEBUG:mcp.server.sse:Validated client message: root=JSONRPCRequest(method='initialize', params={'protocolVersion': '2025-03-26', 'capabilities': {}, 'clientInfo': {'name': 'mcp', 'version': '0.1.0'}}, jsonrpc='2.0', id=0)
DEBUG:mcp.server.sse:Sending session message to writer: SessionMessage(message=JSONRPCMessage(root=JSONRPCRequest(method='initialize', params={'protocolVersion': '2025-03-26', 'capabilities': {}, 'clientInfo': {'name': 'mcp', 'version': '0.1.0'}}, jsonrpc='2.0', id=0)), metadata=ServerMessageMetadata(related_request_id=None, request_context=<starlette.requests.Request object at 0x107371570>))
DEBUG:mcp.server.sse:Sending message via SSE: SessionMessage(message=JSONRPCMessage(root=JSONRPCResponse(jsonrpc='2.0', id=0, result={'protocolVersion': '2025-03-26', 'capabilities': {'experimental': {}, 'prompts': {'listChanged': True}, 'resources': {'subscribe': False, 'listChanged': True}, 'tools': {'listChanged': True}}, 'serverInfo': {'name': 'mcp_server', 'version': '0.0.1'}})), metadata=None)
DEBUG:sse_starlette.sse:chunk: b'event: message\r\ndata: {"jsonrpc":"2.0","id":0,"result":{"protocolVersion":"2025-03-26","capabilities":{"experimental":{},"prompts":{"listChanged":true},"resources":{"subscribe":false,"listChanged":true},"tools":{"listChanged":true}},"serverInfo":{"name":"mcp_server","version":"0.0.1"}}}\r\n\r\n'
DEBUG:mcp.server.sse:Handling POST message
DEBUG:mcp.server.sse:Parsed session ID: 60bdd940-c592-4c4c-8666-198263ec605f
DEBUG:mcp.server.sse:Received JSON: b'{"method":"notifications/initialized","jsonrpc":"2.0"}'
DEBUG:mcp.server.sse:Validated client message: root=JSONRPCNotification(method='notifications/initialized', params=None, jsonrpc='2.0')
DEBUG:mcp.server.sse:Sending session message to writer: SessionMessage(message=JSONRPCMessage(root=JSONRPCNotification(method='notifications/initialized', params=None, jsonrpc='2.0')), metadata=ServerMessageMetadata(related_request_id=None, request_context=<starlette.requests.Request object at 0x107371b70>))
DEBUG:mcp.server.lowlevel.server:Received message: root=InitializedNotification(method='notifications/initialized', params=None, jsonrpc='2.0')
DEBUG:mcp.server.sse:Handling POST message
DEBUG:mcp.server.sse:Parsed session ID: 60bdd940-c592-4c4c-8666-198263ec605f
DEBUG:mcp.server.sse:Received JSON: b'{"method":"tools/list","jsonrpc":"2.0","id":1}'
DEBUG:mcp.server.sse:Validated client message: root=JSONRPCRequest(method='tools/list', params=None, jsonrpc='2.0', id=1)
DEBUG:mcp.server.sse:Sending session message to writer: SessionMessage(message=JSONRPCMessage(root=JSONRPCRequest(method='tools/list', params=None, jsonrpc='2.0', id=1)), metadata=ServerMessageMetadata(related_request_id=None, request_context=<starlette.requests.Request object at 0x107371f90>))
DEBUG:mcp.server.lowlevel.server:Received message: <mcp.shared.session.RequestResponder object at 0x107371e40>
INFO:mcp.server.lowlevel.server:Processing request of type ListToolsRequest
DEBUG:mcp.server.lowlevel.server:Dispatching request of type ListToolsRequest
DEBUG:mcp.server.lowlevel.server:Response sent
DEBUG:mcp.server.sse:Sending message via SSE: SessionMessage(message=JSONRPCMessage(root=JSONRPCResponse(jsonrpc='2.0', id=1, result={'tools': [{'name': 'add_integer_numbers', 'description': 'Adds two integers and returns their sum (e.g., 3 + 5).', 'inputSchema': {'properties': {'a': {'description': 'The first number (integer).', 'title': 'A', 'type': 'integer'}, 'b': {'description': 'The second number (integer).', 'title': 'B', 'type': 'integer'}}, 'required': ['a', 'b'], 'type': 'object'}}, {'name': 'search_files', 'description': "Searches files in ~/Public using a single file name pattern (e.g., '*.txt', '*.pdf').\nCall separately for multiple patterns.\nInvalid patterns (e.g., containing '/' or starting with '.') return an empty list.", 'inputSchema': {'properties': {'pattern': {'description': "A single file name pattern (e.g., '*.txt', '*.pdf'). Must not include path components (e.g., '~/Public/*.txt') or '/' nor start with '.' (e.g., '.txt'). Call separately for each pattern.", 'title': 'Pattern', 'type': 'string'}}, 'required': ['pattern'], 'type': 'object'}}]})), metadata=None)
DEBUG:sse_starlette.sse:chunk: b'event: message\r\ndata: {"jsonrpc":"2.0","id":1,"result":{"tools":[{"name":"add_integer_numbers","description":"Adds two integers and returns their sum (e.g., 3 + 5).","inputSchema":{"properties":{"a":{"description":"The first number (integer).","title":"A","type":"integer"},"b":{"description":"The second number (integer).","title":"B","type":"integer"}},"required":["a","b"],"type":"object"}},{"name":"search_files","description":"Searches files in ~/Public using a single file name pattern (e.g., \'*.txt\', \'*.pdf\').\\nCall separately for multiple patterns.\\nInvalid patterns (e.g., containing \'/\' or starting with \'.\') return an empty list.","inputSchema":{"properties":{"pattern":{"description":"A single file name pattern (e.g., \'*.txt\', \'*.pdf\'). Must not include path components (e.g., \'~/Public/*.txt\') or \'/\' nor start with \'.\' (e.g., \'.txt\'). Call separately for each pattern.","title":"Pattern","type":"string"}},"required":["pattern"],"type":"object"}}]}}\r\n\r\n'
DEBUG:sse_starlette.sse:Got event: http.disconnect. Stop streaming.
DEBUG:root:Client session disconnected 60bdd940-c592-4c4c-8666-198263ec605f
DEBUG:mcp.server.sse:Setting up SSE connection
DEBUG:mcp.server.sse:Created new session with ID: 6eac8fa4-9162-4d39-a9a4-fd17ccb7c8cf
DEBUG:mcp.server.sse:Starting SSE response task
DEBUG:mcp.server.sse:Yielding read and write streams
DEBUG:mcp.server.sse:Starting SSE writer
DEBUG:mcp.server.sse:Setting up SSE connection
DEBUG:mcp.server.sse:Created new session with ID: 515beedc-e779-4e88-8241-13ace8149d1b
DEBUG:mcp.server.sse:Starting SSE response task
DEBUG:mcp.server.sse:Yielding read and write streams
DEBUG:mcp.server.sse:Sent endpoint event: /messages/?session_id=6eac8fa491624d39a9a4fd17ccb7c8cf
DEBUG:sse_starlette.sse:chunk: b'event: endpoint\r\ndata: /messages/?session_id=6eac8fa491624d39a9a4fd17ccb7c8cf\r\n\r\n'
DEBUG:mcp.server.sse:Starting SSE writer
DEBUG:mcp.server.sse:Sent endpoint event: /messages/?session_id=515beedce7794e88824113ace8149d1b
DEBUG:sse_starlette.sse:chunk: b'event: endpoint\r\ndata: /messages/?session_id=515beedce7794e88824113ace8149d1b\r\n\r\n'
DEBUG:mcp.server.sse:Handling POST message
DEBUG:mcp.server.sse:Parsed session ID: 6eac8fa4-9162-4d39-a9a4-fd17ccb7c8cf
DEBUG:mcp.server.sse:Received JSON: b'{"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"mcp","version":"0.1.0"}},"jsonrpc":"2.0","id":0}'
DEBUG:mcp.server.sse:Validated client message: root=JSONRPCRequest(method='initialize', params={'protocolVersion': '2025-03-26', 'capabilities': {}, 'clientInfo': {'name': 'mcp', 'version': '0.1.0'}}, jsonrpc='2.0', id=0)
DEBUG:mcp.server.sse:Sending session message to writer: SessionMessage(message=JSONRPCMessage(root=JSONRPCRequest(method='initialize', params={'protocolVersion': '2025-03-26', 'capabilities': {}, 'clientInfo': {'name': 'mcp', 'version': '0.1.0'}}, jsonrpc='2.0', id=0)), metadata=ServerMessageMetadata(related_request_id=None, request_context=<starlette.requests.Request object at 0x107373910>))
DEBUG:mcp.server.sse:Handling POST message
DEBUG:mcp.server.sse:Parsed session ID: 515beedc-e779-4e88-8241-13ace8149d1b
DEBUG:mcp.server.sse:Received JSON: b'{"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"mcp","version":"0.1.0"}},"jsonrpc":"2.0","id":0}'
DEBUG:mcp.server.sse:Validated client message: root=JSONRPCRequest(method='initialize', params={'protocolVersion': '2025-03-26', 'capabilities': {}, 'clientInfo': {'name': 'mcp', 'version': '0.1.0'}}, jsonrpc='2.0', id=0)
DEBUG:mcp.server.sse:Sending session message to writer: SessionMessage(message=JSONRPCMessage(root=JSONRPCRequest(method='initialize', params={'protocolVersion': '2025-03-26', 'capabilities': {}, 'clientInfo': {'name': 'mcp', 'version': '0.1.0'}}, jsonrpc='2.0', id=0)), metadata=ServerMessageMetadata(related_request_id=None, request_context=<starlette.requests.Request object at 0x107373c40>))
DEBUG:mcp.server.sse:Sending message via SSE: SessionMessage(message=JSONRPCMessage(root=JSONRPCResponse(jsonrpc='2.0', id=0, result={'protocolVersion': '2025-03-26', 'capabilities': {'experimental': {}, 'prompts': {'listChanged': True}, 'resources': {'subscribe': False, 'listChanged': True}, 'tools': {'listChanged': True}}, 'serverInfo': {'name': 'mcp_server', 'version': '0.0.1'}})), metadata=None)
DEBUG:sse_starlette.sse:chunk: b'event: message\r\ndata: {"jsonrpc":"2.0","id":0,"result":{"protocolVersion":"2025-03-26","capabilities":{"experimental":{},"prompts":{"listChanged":true},"resources":{"subscribe":false,"listChanged":true},"tools":{"listChanged":true}},"serverInfo":{"name":"mcp_server","version":"0.0.1"}}}\r\n\r\n'
DEBUG:mcp.server.sse:Sending message via SSE: SessionMessage(message=JSONRPCMessage(root=JSONRPCResponse(jsonrpc='2.0', id=0, result={'protocolVersion': '2025-03-26', 'capabilities': {'experimental': {}, 'prompts': {'listChanged': True}, 'resources': {'subscribe': False, 'listChanged': True}, 'tools': {'listChanged': True}}, 'serverInfo': {'name': 'mcp_server', 'version': '0.0.1'}})), metadata=None)
DEBUG:sse_starlette.sse:chunk: b'event: message\r\ndata: {"jsonrpc":"2.0","id":0,"result":{"protocolVersion":"2025-03-26","capabilities":{"experimental":{},"prompts":{"listChanged":true},"resources":{"subscribe":false,"listChanged":true},"tools":{"listChanged":true}},"serverInfo":{"name":"mcp_server","version":"0.0.1"}}}\r\n\r\n'
DEBUG:mcp.server.sse:Handling POST message
DEBUG:mcp.server.sse:Parsed session ID: 6eac8fa4-9162-4d39-a9a4-fd17ccb7c8cf
DEBUG:mcp.server.sse:Received JSON: b'{"method":"notifications/initialized","jsonrpc":"2.0"}'
DEBUG:mcp.server.sse:Validated client message: root=JSONRPCNotification(method='notifications/initialized', params=None, jsonrpc='2.0')
DEBUG:mcp.server.sse:Sending session message to writer: SessionMessage(message=JSONRPCMessage(root=JSONRPCNotification(method='notifications/initialized', params=None, jsonrpc='2.0')), metadata=ServerMessageMetadata(related_request_id=None, request_context=<starlette.requests.Request object at 0x1073c44f0>))
DEBUG:mcp.server.sse:Handling POST message
DEBUG:mcp.server.sse:Parsed session ID: 515beedc-e779-4e88-8241-13ace8149d1b
DEBUG:mcp.server.sse:Received JSON: b'{"method":"notifications/initialized","jsonrpc":"2.0"}'
DEBUG:mcp.server.sse:Validated client message: root=JSONRPCNotification(method='notifications/initialized', params=None, jsonrpc='2.0')
DEBUG:mcp.server.sse:Sending session message to writer: SessionMessage(message=JSONRPCMessage(root=JSONRPCNotification(method='notifications/initialized', params=None, jsonrpc='2.0')), metadata=ServerMessageMetadata(related_request_id=None, request_context=<starlette.requests.Request object at 0x1073c4850>))
DEBUG:mcp.server.lowlevel.server:Received message: root=InitializedNotification(method='notifications/initialized', params=None, jsonrpc='2.0')
DEBUG:mcp.server.lowlevel.server:Received message: root=InitializedNotification(method='notifications/initialized', params=None, jsonrpc='2.0')
DEBUG:mcp.server.sse:Handling POST message
DEBUG:mcp.server.sse:Parsed session ID: 6eac8fa4-9162-4d39-a9a4-fd17ccb7c8cf
DEBUG:mcp.server.sse:Received JSON: b'{"method":"tools/call","params":{"name":"search_files","arguments":{"pattern":"*.txt"}},"jsonrpc":"2.0","id":1}'
DEBUG:mcp.server.sse:Validated client message: root=JSONRPCRequest(method='tools/call', params={'name': 'search_files', 'arguments': {'pattern': '*.txt'}}, jsonrpc='2.0', id=1)
DEBUG:mcp.server.sse:Sending session message to writer: SessionMessage(message=JSONRPCMessage(root=JSONRPCRequest(method='tools/call', params={'name': 'search_files', 'arguments': {'pattern': '*.txt'}}, jsonrpc='2.0', id=1)), metadata=ServerMessageMetadata(related_request_id=None, request_context=<starlette.requests.Request object at 0x1073c4d30>))
DEBUG:mcp.server.sse:Handling POST message
DEBUG:mcp.server.sse:Parsed session ID: 515beedc-e779-4e88-8241-13ace8149d1b
DEBUG:mcp.server.sse:Received JSON: b'{"method":"tools/call","params":{"name":"search_files","arguments":{"pattern":"*.world"}},"jsonrpc":"2.0","id":1}'
DEBUG:mcp.server.sse:Validated client message: root=JSONRPCRequest(method='tools/call', params={'name': 'search_files', 'arguments': {'pattern': '*.world'}}, jsonrpc='2.0', id=1)
DEBUG:mcp.server.sse:Sending session message to writer: SessionMessage(message=JSONRPCMessage(root=JSONRPCRequest(method='tools/call', params={'name': 'search_files', 'arguments': {'pattern': '*.world'}}, jsonrpc='2.0', id=1)), metadata=ServerMessageMetadata(related_request_id=None, request_context=<starlette.requests.Request object at 0x107372f20>))
DEBUG:mcp.server.lowlevel.server:Received message: <mcp.shared.session.RequestResponder object at 0x1073700a0>
INFO:mcp.server.lowlevel.server:Processing request of type CallToolRequest
DEBUG:mcp.server.lowlevel.server:Dispatching request of type CallToolRequest
DEBUG:root:Calling tool: search_files, arguments: *.txt
DEBUG:root:Search path: /Users/Work/Public/*.txt
DEBUG:mcp.server.lowlevel.server:Response sent
DEBUG:mcp.server.lowlevel.server:Received message: <mcp.shared.session.RequestResponder object at 0x1073722c0>
DEBUG:mcp.server.sse:Sending message via SSE: SessionMessage(message=JSONRPCMessage(root=JSONRPCResponse(jsonrpc='2.0', id=1, result={'content': [{'type': 'text', 'text': '{\n "files": [\n "HelloWorld.txt",\n "FooBar.txt"\n ]\n}'}], 'isError': False})), metadata=None)
INFO:mcp.server.lowlevel.server:Processing request of type CallToolRequest
DEBUG:mcp.server.lowlevel.server:Dispatching request of type CallToolRequest
DEBUG:root:Calling tool: search_files, arguments: *.world
DEBUG:root:Search path: /Users/Work/Public/*.world
DEBUG:mcp.server.lowlevel.server:Response sent
DEBUG:sse_starlette.sse:chunk: b'event: message\r\ndata: {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"{\\n \\"files\\": [\\n \\"HelloWorld.txt\\",\\n \\"FooBar.txt\\"\\n ]\\n}"}],"isError":false}}\r\n\r\n'
DEBUG:mcp.server.sse:Sending message via SSE: SessionMessage(message=JSONRPCMessage(root=JSONRPCResponse(jsonrpc='2.0', id=1, result={'content': [{'type': 'text', 'text': '{\n "files": [\n "hello.world",\n "Hoge.world"\n ]\n}'}], 'isError': False})), metadata=None)
DEBUG:sse_starlette.sse:chunk: b'event: message\r\ndata: {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"{\\n \\"files\\": [\\n \\"hello.world\\",\\n \\"Hoge.world\\"\\n ]\\n}"}],"isError":false}}\r\n\r\n'
DEBUG:sse_starlette.sse:Got event: http.disconnect. Stop streaming.
DEBUG:root:Client session disconnected 6eac8fa4-9162-4d39-a9a4-fd17ccb7c8cf
DEBUG:sse_starlette.sse:Got event: http.disconnect. Stop streaming.
DEBUG:root:Client session disconnected 515beedc-e779-4e88-8241-13ace8149d1b
DEBUG:mcp.server.sse:Setting up SSE connection
DEBUG:mcp.server.sse:Created new session with ID: 11d4624c-e374-4e24-a417-893e9bfd8ee1
DEBUG:mcp.server.sse:Starting SSE response task
DEBUG:mcp.server.sse:Yielding read and write streams
DEBUG:mcp.server.sse:Starting SSE writer
DEBUG:mcp.server.sse:Sent endpoint event: /messages/?session_id=11d4624ce3744e24a417893e9bfd8ee1
DEBUG:sse_starlette.sse:chunk: b'event: endpoint\r\ndata: /messages/?session_id=11d4624ce3744e24a417893e9bfd8ee1\r\n\r\n'
DEBUG:mcp.server.sse:Handling POST message
DEBUG:mcp.server.sse:Parsed session ID: 11d4624c-e374-4e24-a417-893e9bfd8ee1
DEBUG:mcp.server.sse:Received JSON: b'{"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"mcp","version":"0.1.0"}},"jsonrpc":"2.0","id":0}'
DEBUG:mcp.server.sse:Validated client message: root=JSONRPCRequest(method='initialize', params={'protocolVersion': '2025-03-26', 'capabilities': {}, 'clientInfo': {'name': 'mcp', 'version': '0.1.0'}}, jsonrpc='2.0', id=0)
DEBUG:mcp.server.sse:Sending session message to writer: SessionMessage(message=JSONRPCMessage(root=JSONRPCRequest(method='initialize', params={'protocolVersion': '2025-03-26', 'capabilities': {}, 'clientInfo': {'name': 'mcp', 'version': '0.1.0'}}, jsonrpc='2.0', id=0)), metadata=ServerMessageMetadata(related_request_id=None, request_context=<starlette.requests.Request object at 0x107373340>))
DEBUG:mcp.server.sse:Sending message via SSE: SessionMessage(message=JSONRPCMessage(root=JSONRPCResponse(jsonrpc='2.0', id=0, result={'protocolVersion': '2025-03-26', 'capabilities': {'experimental': {}, 'prompts': {'listChanged': True}, 'resources': {'subscribe': False, 'listChanged': True}, 'tools': {'listChanged': True}}, 'serverInfo': {'name': 'mcp_server', 'version': '0.0.1'}})), metadata=None)
DEBUG:sse_starlette.sse:chunk: b'event: message\r\ndata: {"jsonrpc":"2.0","id":0,"result":{"protocolVersion":"2025-03-26","capabilities":{"experimental":{},"prompts":{"listChanged":true},"resources":{"subscribe":false,"listChanged":true},"tools":{"listChanged":true}},"serverInfo":{"name":"mcp_server","version":"0.0.1"}}}\r\n\r\n'
DEBUG:mcp.server.sse:Handling POST message
DEBUG:mcp.server.sse:Parsed session ID: 11d4624c-e374-4e24-a417-893e9bfd8ee1
DEBUG:mcp.server.sse:Received JSON: b'{"method":"notifications/initialized","jsonrpc":"2.0"}'
DEBUG:mcp.server.sse:Validated client message: root=JSONRPCNotification(method='notifications/initialized', params=None, jsonrpc='2.0')
DEBUG:mcp.server.sse:Sending session message to writer: SessionMessage(message=JSONRPCMessage(root=JSONRPCNotification(method='notifications/initialized', params=None, jsonrpc='2.0')), metadata=ServerMessageMetadata(related_request_id=None, request_context=<starlette.requests.Request object at 0x107372aa0>))
DEBUG:mcp.server.lowlevel.server:Received message: root=InitializedNotification(method='notifications/initialized', params=None, jsonrpc='2.0')
DEBUG:mcp.server.sse:Handling POST message
DEBUG:mcp.server.sse:Parsed session ID: 11d4624c-e374-4e24-a417-893e9bfd8ee1
DEBUG:mcp.server.sse:Received JSON: b'{"method":"tools/call","params":{"name":"add_integer_numbers","arguments":{"a":2,"b":2}},"jsonrpc":"2.0","id":1}'
DEBUG:mcp.server.sse:Validated client message: root=JSONRPCRequest(method='tools/call', params={'name': 'add_integer_numbers', 'arguments': {'a': 2, 'b': 2}}, jsonrpc='2.0', id=1)
DEBUG:mcp.server.sse:Sending session message to writer: SessionMessage(message=JSONRPCMessage(root=JSONRPCRequest(method='tools/call', params={'name': 'add_integer_numbers', 'arguments': {'a': 2, 'b': 2}}, jsonrpc='2.0', id=1)), metadata=ServerMessageMetadata(related_request_id=None, request_context=<starlette.requests.Request object at 0x107372680>))
DEBUG:mcp.server.lowlevel.server:Received message: <mcp.shared.session.RequestResponder object at 0x1073724d0>
INFO:mcp.server.lowlevel.server:Processing request of type CallToolRequest
DEBUG:mcp.server.lowlevel.server:Dispatching request of type CallToolRequest
DEBUG:root:Calling tool: add_numbers, arguments: a:2 b:2
DEBUG:mcp.server.lowlevel.server:Response sent
DEBUG:mcp.server.sse:Sending message via SSE: SessionMessage(message=JSONRPCMessage(root=JSONRPCResponse(jsonrpc='2.0', id=1, result={'content': [{'type': 'text', 'text': '4'}], 'isError': False})), metadata=None)
DEBUG:sse_starlette.sse:chunk: b'event: message\r\ndata: {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"4"}],"isError":false}}\r\n\r\n'
DEBUG:sse_starlette.sse:Got event: http.disconnect. Stop streaming.
DEBUG:root:Client session disconnected 11d4624c-e374-4e24-a417-893e9bfd8ee1
from fastmcp import FastMCP
from pydantic import Field
from typing import Annotated
import logging
import glob
import os
import re
logging.basicConfig(level=logging.DEBUG, handlers=[logging.FileHandler('mcp_server.log'), logging.StreamHandler()])
mcp = FastMCP("mcp_server", version="0.0.1")
@mcp.tool
def add_integer_numbers(
a: Annotated[int, Field(description="The first number (integer).")],
b: Annotated[int, Field(description="The second number (integer).")],
) -> int:
"""
Adds two integers and returns their sum (e.g., 3 + 5).
"""
logging.debug(f"Calling tool: add_numbers, arguments: a:{a} b:{b}")
return a + b
@mcp.tool
def search_files(
pattern: Annotated[str, Field(description="A single file name pattern (e.g., '*.txt', '*.pdf'). Must not include path components (e.g., '~/Public/*.txt') or '/' nor start with '.' (e.g., '.txt'). Call separately for each pattern.")],
) -> dict:
"""
Searches files in ~/Public using a single file name pattern (e.g., '*.txt', '*.pdf').
Call separately for multiple patterns.
Invalid patterns (e.g., containing '/' or starting with '.') return an empty list.
"""
target = "~/Public"
logging.debug(f"Calling tool: search_files, arguments: {pattern}")
try:
if not re.match(r'^[a-zA-Z0-9*?.]+$', pattern) or "/" in pattern or pattern.startswith("."):
logging.debug(f"Invalid pattern detected: {pattern}. Returning error.")
return {
"error": f"Invalid pattern: {pattern}. Pattern must not include '/' or start with '.'. Call search_files one pattern at a time."
}
search_path = os.path.join(os.path.expanduser(target), pattern)
logging.debug(f"Search path: {search_path}")
files = glob.glob(search_path, recursive=False)
return {"files": [os.path.basename(f) for f in files]}
except Exception as e:
logging.error(f"Error in search_files: {str(e)}")
return {
"error": f"Failed to process search_files: {str(e)}. Call search_files one pattern at a time with valid arguments (e.g., {'pattern': '*.txt'})."
}
if __name__ == "__main__":
mcp.run(transport="sse", host="127.0.0.1", port=8080)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment