A Python client for the Model Context Protocol (MCP), using the official MCP library and langchain-mcp-adapters.
Project description
MCP Python Client
A Python client library for interacting with servers implementing the Model Context Protocol (MCP). This library simplifies communication with AI models and agents that expose an MCP interface.
Version: 0.4.1
Features
- Official MCP Implementation: Starting with version 0.4.1, this library uses the official MCP library and langchain-mcp-adapters.
- Backward Compatibility: Maintains the same API structure as before, but now uses async methods.
- Send Prompts: Easily send conversation history to get responses from MCP servers.
- Tool Support: Access tools provided by MCP servers and convert them to LangChain tools.
- MultiServerMCPClient: Connect to multiple MCP servers and access their tools.
- Configuration File: Load server connection details (
base_url,api_key,timeout) from anmcp.jsonfile. - Robust Error Handling: Differentiates between connection errors, timeouts, API errors, and data validation errors.
- Authentication: Supports API Key authentication via the
Authorization: Bearerheader. - Context Manager: Supports use as an async context manager.
Installation
# From PyPI (once published)
pip install mcpwire
# Development dependencies
pip install mcpwire[dev]
# Or directly from GitHub
pip install git+https://github.com/anukchat/mcpwire.git
# Or for development
git clone https://github.com/anukchat/mcpwire.git
cd mcpwire
pip install -e .
Configuration (mcp.json)
The client can be configured using an mcp.json file. This allows you to define multiple server environments and easily switch between them using MCPClient.from_config().
The client searches for mcp.json in the following order:
- An explicit path provided to
MCPClient.from_config(config_path=...). - mcp.json in the current working directory.
.mcp.jsonin your home directory (~/.mcp.json)..config/mcp/mcp.jsonin your home directory (~/.config/mcp/mcp.json).
Example mcp.json:
{
"default_server": "local",
"servers": {
"local": {
"base_url": "http://localhost:8000",
"api_key": null,
"timeout": 60,
"transport": "sse",
"description": "Local development server (e.g., fast-agent)"
},
"stdio_server": {
"transport": "stdio",
"command": "python",
"args": ["-m", "mcp.server.cli"],
"timeout": 60,
"description": "Local stdio server"
},
"remote_dev": {
"base_url": "https://dev-mcp.example.com",
"api_key": "dev-secret-key-abc",
"timeout": 90,
"transport": "sse",
"description": "Remote development/testing server"
},
"production": {
"base_url": "https://mcp.example.com",
"api_key": "env:MCP_PROD_API_KEY",
"timeout": 120,
"transport": "sse",
"description": "Production MCP server"
}
}
}
default_server: (Optional) The key of the server to use if server_name is omitted in from_config().servers: Dictionary of named server configurations.base_url: (Required for http/sse) Server URL.api_key: (Optional) API key string, null, or "env:YOUR_ENV_VAR".timeout: (Optional) Request timeout in seconds (defaults to 60).transport: (Required) The transport protocol to use ("sse" or "stdio").command: (Required for stdio) The command to execute.args: (Required for stdio) Arguments for the command.description: (Optional) Description.
Quickstart (Async)
import asyncio
import logging
from mcpwire import (
MCPClient,
MultiServerMCPClient,
StdioConnection,
SSEConnection,
MCPAPIError,
MCPConnectionError,
MCPDataError
)
logging.basicConfig(level=logging.INFO)
async def main():
# --- Option 1: Initialize directly ---
# Note: The official MCP library supports "sse" transport, not "http"
client = MCPClient(base_url="http://localhost:8000", transport="sse")
try:
# Initialize and use the client
async with client as mcp:
# Get server metadata
metadata = await mcp.get_server_metadata()
logging.info(f"Connected to MCP server: {metadata.name} v{metadata.version}")
# List available tools
tools = await mcp.list_tools()
for tool in tools:
logging.info(f"Available tool: {tool.name}")
# Get a prompt
prompt_messages = await mcp.get_prompt("hello_world", {})
for msg in prompt_messages:
logging.info(f"[{msg.type}] {msg.content}")
# Call a tool
tool_result = await mcp.call_tool("search", {"query": "MCP protocol"})
logging.info(f"Tool result: {tool_result}")
except (MCPAPIError, MCPConnectionError, MCPDataError) as e:
logging.error(f"MCP Error: {e}")
except Exception as e:
logging.error(f"An unexpected error occurred: {e}", exc_info=True)
# --- Option 2: Initialize from mcp.json ---
try:
# Load 'local' config from mcp.json
client_from_config = MCPClient.from_config(server_name="local")
async with client_from_config as mcp:
logging.info(f"Using server configured as 'local'")
tools = await mcp.list_tools()
logging.info(f"Found {len(tools)} tools")
except (FileNotFoundError, ValueError, KeyError, MCPDataError) as e:
logging.error(f"Configuration Error: {e}")
except Exception as e:
logging.error(f"An unexpected error occurred: {e}", exc_info=True)
# --- Option 3: Use MultiServerMCPClient ---
try:
# Connect to multiple servers
connections = {
"math": {
"transport": "stdio",
"command": "python",
"args": ["-m", "mcp.server.cli"],
},
"web": {
"transport": "sse",
"url": "http://localhost:8000/sse",
}
}
async with MultiServerMCPClient(connections) as multi_client:
# Get tools from all servers
all_tools = multi_client.get_tools()
logging.info(f"Total tools from all servers: {len(all_tools)}")
# Get a prompt from a specific server
messages = await multi_client.get_prompt("math", "calculate", {"expression": "2+2"})
for msg in messages:
logging.info(f"Message: {msg.content}")
except Exception as e:
logging.error(f"MultiServerMCPClient error: {e}", exc_info=True)
# Run the async main function
if __name__ == "__main__":
asyncio.run(main())
Migration from v0.3.0 to v0.4.1
Version 0.4.1 introduces significant changes by migrating to the official MCP library and langchain-mcp-adapters. Key differences:
- Async API: Methods are now async and require
awaitand an async context manager. - Transport Change: The "http" transport is no longer supported; use "sse" instead.
- MultiServerMCPClient: A new class for connecting to multiple MCP servers.
- LangChain Integration: Tools are now LangChain tools.
Development
- Clone:
git clone https://github.com/anukchat/mcpwire.git - Setup Env: Create and activate a virtual environment
- Install Dev Dependencies:
pip install -e ".[dev]"
Contributing
Contributions are welcome! Here's how you can contribute to the project:
- Fork the Repository: Create your own fork of the project
- Create a Branch: Create a branch for your changes
- Make Changes: Implement your changes, following the coding style
- Run Tests: Make sure the tests pass by running
pytest - Submit a Pull Request: Open a PR with a clear description of your changes
Testing
Run the tests using pytest:
# Install test dependencies
pip install -e ".[dev]"
# Run tests
pytest
Continuous Integration
This project uses GitHub Actions for continuous integration:
- Tests: Automatically run on each push and pull request to main/master branches
- Builds: Package is built and validated to ensure it will install correctly
- Publishing: When a new version tag is pushed (e.g., v0.4.1), the package is automatically published to PyPI
Creating a Release
To release a new version:
- Update the version in
pyproject.tomlandmcpwire/__init__.py - Update the CHANGELOG.md file with the changes
- Commit the changes and push to GitHub
- Create and push a new tag that matches the version:
git tag -a v0.4.1 -m "Release v0.4.1"
git push origin v0.4.1
The GitHub Actions workflow will automatically build and publish the package to PyPI.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mcpwire-0.4.1.tar.gz.
File metadata
- Download URL: mcpwire-0.4.1.tar.gz
- Upload date:
- Size: 23.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
22591c059ffedd7e42c4de3280b6a21e5aba2e7382af3163f3e366b0101f52e1
|
|
| MD5 |
57d5063b48024193fabef60f44571ffa
|
|
| BLAKE2b-256 |
ed2e85452c94e27002bcc2e22130ba8f7abb60f3665f0275bba4176f8eb07c5b
|
File details
Details for the file mcpwire-0.4.1-py3-none-any.whl.
File metadata
- Download URL: mcpwire-0.4.1-py3-none-any.whl
- Upload date:
- Size: 16.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
febfa5b8eb7a52f382bb8a50a47ffc1ca91d00be94b0db23ae9d0b6b95c2dec1
|
|
| MD5 |
1927f84663858be1c025fbfc74aa563c
|
|
| BLAKE2b-256 |
f9db5bd51ee7f3a4cd37e78f996519d8f713933c8f965df91b737d8e7a727046
|