MCP-DBLP
by szeider
Verified
import subprocess
import json
import time
import sys
import argparse
import logging
# Set up logging
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler("mcp_dblp_client.log"),
logging.StreamHandler(sys.stderr)
]
)
logger = logging.getLogger("mcp_dblp_client")
def run_mcp_call(tool, arguments, debug=False):
"""
Run an MCP call to the server with the specified tool and arguments.
Args:
tool (str): The name of the tool to call
arguments (dict): The arguments to pass to the tool
debug (bool): Whether to print debug information
"""
process = subprocess.Popen(
["python", "src/mcp_dblp/server.py"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
bufsize=1
)
# Wait for server to start
logger.info("Waiting for server to start...")
time.sleep(0.5)
message = {
"jsonrpc": "2.0",
"id": 1,
"method": "call_tool",
"params": {
"name": tool,
"arguments": arguments
}
}
# Prepare the request with Content-Length header
json_content = json.dumps(message)
content_length = len(json_content)
request = f"Content-Length: {content_length}\r\n\r\n{json_content}"
logger.info(f"Sending request for '{tool}' with arguments: {arguments}")
if debug:
logger.debug(f"Raw request:\n{request}")
try:
# Send the request
process.stdin.write(request)
process.stdin.flush()
# Read the response
headers = {}
header_data = ""
# Read headers
while True:
line = process.stdout.readline()
header_data += line
if debug:
logger.debug(f"Header line: {line!r}")
line = line.strip()
if not line:
break
parts = line.split(':', 1)
if len(parts) == 2:
headers[parts[0].strip().lower()] = parts[1].strip()
if debug:
logger.debug(f"Received headers: {headers}")
content_length = int(headers.get('content-length', 0))
if content_length > 0:
content = process.stdout.read(content_length)
logger.info(f"Response received, length: {len(content)}")
if debug:
logger.debug(f"Raw response content: {content}")
try:
parsed = json.loads(content)
if debug:
logger.debug(f"Parsed JSON: {json.dumps(parsed, indent=2)}")
print("\nParsed Response:")
print(json.dumps(parsed, indent=2))
except json.JSONDecodeError as e:
logger.error(f"Failed to parse JSON: {e}")
print("\nResponse (raw):")
print(content)
else:
logger.warning("No content length specified in response headers")
print("\nNo response content received")
# Check for server errors
stderr_output = process.stderr.read()
if stderr_output:
logger.warning(f"Server stderr output: {stderr_output}")
print("\nServer Error Output:")
print(stderr_output)
except Exception as e:
logger.exception(f"Error during MCP call: {e}")
print(f"Error: {e}")
finally:
# Terminate the server process
process.terminate()
try:
process.wait(timeout=5)
except subprocess.TimeoutExpired:
process.kill()
logger.warning("Had to forcefully kill the server process")
def list_tools():
"""List all available tools on the server"""
process = subprocess.Popen(
["python", "src/mcp_dblp/server.py"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
bufsize=1
)
time.sleep(0.5)
message = {
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {}
}
json_content = json.dumps(message)
content_length = len(json_content)
request = f"Content-Length: {content_length}\r\n\r\n{json_content}"
try:
process.stdin.write(request)
process.stdin.flush()
headers = {}
while True:
line = process.stdout.readline().strip()
if not line:
break
parts = line.split(':', 1)
if len(parts) == 2:
headers[parts[0].strip().lower()] = parts[1].strip()
content_length = int(headers.get('content-length', 0))
content = process.stdout.read(content_length) if content_length > 0 else ""
print("\nAvailable Tools:")
if content:
try:
response = json.loads(content)
tools = response.get("result", {}).get("tools", [])
for tool in tools:
print(f" - {tool['name']}: {tool['description']}")
except json.JSONDecodeError:
print("Error parsing response")
else:
print("No tools returned")
except Exception as e:
print(f"Error: {e}")
finally:
process.terminate()
def main():
parser = argparse.ArgumentParser(description="MCP DBLP Client")
parser.add_argument("--list-tools", action="store_true", help="List available tools")
parser.add_argument("--tool", help="Tool to call")
parser.add_argument("--args", help="JSON string of arguments for the tool")
parser.add_argument("--debug", action="store_true", help="Enable debug output")
args = parser.parse_args()
if args.list_tools:
list_tools()
elif args.tool:
tool_args = {}
if args.args:
try:
tool_args = json.loads(args.args)
except json.JSONDecodeError as e:
print(f"Error parsing arguments JSON: {e}")
return
run_mcp_call(args.tool, tool_args, debug=args.debug)
else:
# Default behavior
print("Running echo tool as a test...")
run_mcp_call("echo", {"message": "Hello, DBLP!"}, debug=args.debug)
if __name__ == "__main__":
main()