The mcp-server-adapter
is a Go package designed to simplify the integration of Model Context Protocol (MCP) servers with LangChain Go applications. It acts as an intermediary, allowing LangChain agents to seamlessly discover, use, and manage tools exposed by various MCP servers. This adapter handles server lifecycle management, configuration watching, and the conversion of MCP tools into a format consumable by LangChain.
Note: This project is currently a work in progress. While functional, it may undergo significant changes, including breaking API changes, as it evolves.
- Seamless LangChain Integration: Exposes MCP server tools as native LangChain
tools.Tool
objects. - MCP Server Lifecycle Management: Start, stop, and monitor the status of multiple MCP servers.
- Dynamic Configuration: Supports loading server configurations from a JSON file and hot-reloading changes.
- Server Status and Configuration Access: Easily check if a server is disabled or retrieve its full configuration.
- File Watcher: Automatically detects and reacts to changes in the configuration file, restarting affected servers.
- Multiple Transport Support: Connects to MCP servers via standard I/O (stdio), Server-Sent Events (SSE), and HTTP transports.
- Robust Error Handling: Includes mechanisms for safely closing server connections and handling common errors.
- Extensible: Designed with interfaces for easy extension and testing (e.g., custom client factories).
This project requires Go 1.21 or higher.
- Clone the repository:
git clone https://github.com/denkhaus/mcp-server-adapter.git cd mcp-server-adapter
- Install dependencies:
go mod tidy
- Build the project:
go build ./...
The examples can be built and run using the provided Makefile
. Navigate to the project root and use make
commands.
For instance, to build all examples:
make build-examples
To run a specific example, like the demo:
make run-demo
The mcp-server-adapter
is typically used within a Go application to manage connections to MCP servers and integrate their tools into an LLM agent.
-
Define your MCP server configuration: Create a JSON file (e.g.,
config.json
) specifying the MCP servers your application needs to connect to. Seeexamples/mcp-spec-config.json
for a practical example.{ "mcpServers": { "fetcher": { "command": "npx", "args": ["-y", "fetcher-mcp"], "transport": "stdio" }, "tavily-mcp": { "command": "npx", "args": ["-y", "tavily-mcp@0.1.3"], "transport": "stdio" } } }
-
Initialize the adapter:
package main import ( "context" "log" "time" "github.com/denkhaus/mcp-server-adapter" ) func main() { adapter, err := mcpadapter.New( mcpadapter.WithConfigPath("./config.json"), mcpadapter.WithLogLevel("info"), mcpadapter.WithFileWatcher(true), // Enable hot-reloading of config ) if err != nil { log.Fatalf("Failed to create MCP adapter: %v", err) } defer adapter.Close() ctx := context.Background() // Start all configured MCP servers if err := adapter.StartAllServers(ctx); err != nil { log.Fatalf("Failed to start all MCP servers: %v", err) } // Wait for servers to be ready if err := adapter.WaitForServersReady(ctx, 30*time.Second); err != nil { log.Fatalf("Servers not ready: %v", err) } // Get all available tools from all running servers allTools, err := adapter.GetAllTools(ctx) if err != nil { log.Fatalf("Failed to get LangChain tools: %v", err) } log.Printf("Available tools: %d", len(allTools)) for _, tool := range allTools { log.Printf("- %s: %s", tool.Name(), tool.Description()) } // Example: Check if a server is disabled isDisabled, err := adapter.IsServerDisabled("fetcher") if err != nil { log.Printf("Error checking if server is disabled: %v", err) } else if isDisabled { log.Printf("Server 'fetcher' is disabled.") } else { log.Printf("Server 'fetcher' is enabled.") } // Example: Get server configuration serverConfig, err := adapter.GetServerConfig("tavily-mcp") if err != nil { log.Printf("Error getting server config: %v", err) } else { log.Printf("Server 'tavily-mcp' command: %s", serverConfig.Command) } // Example: Using a tool (replace with actual tool usage) // If you have a "fetcher.fetch_url" tool, you could call it like this: // if len(allTools) > 0 { // ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) // defer cancel() // result, err := allTools[0].Call(ctx, `{"url": "https://example.com"}`) // if err != nil { // log.Printf("Tool call failed: %v", err) // } else { // log.Printf("Tool result: %s", result) // } // } }
To improve clarity and consistency, the following API functions have been renamed:
GetServerStatus(serverName string) ServerStatus
is nowGetServerStatusByName(serverName string) ServerStatus
.GetLangChainTools(ctx context.Context, serverName string) ([]tools.Tool, error)
is nowGetToolsByServerName(ctx context.Context, serverName string) ([]tools.Tool, error)
.GetAllLangChainTools(ctx context.Context) ([]tools.Tool, error)
is nowGetAllTools(ctx context.Context) ([]tools.Tool, error)
.
The mcp-server-adapter
includes several examples to demonstrate its capabilities and integration with LangChain applications. For detailed usage, code, and technical specifications, please refer to the examples/
directory, and especially the examples/EXAMPLES_SUMMARY.md
file.
Here's a summary of the key examples:
This project uses a Makefile
to automate various tasks, including building, testing, linting, and running examples. Below is a comprehensive list of available make
targets:
make build-all
: Build all binaries.make build-examples
: Build all example binaries.make build-demo
: Build demo example.make build-agent
: Build agent example.make build-server
: Build server example.make build-simple-demo
: Build simple demo example.
make test
: Run all tests.make test-examples
: Run all example tests with timeout.make test-demo
: Test demo example (with timeout).make test-agent
: Test agent example (with timeout).make test-simple-demo
: Test simple demo example (with timeout).make test-servers
: Test individual MCP servers.make test-config
: Validate configuration files.
make lint
: Run golangci-lint.make lint-fix
: Run golangci-lint with auto-fix.make fmt
: Format Go code.make vet
: Run go vet.make check
: Run all code quality checks.make ci
: Complete CI pipeline.
make run-demo
: Build and run demo.make run-agent
: Build and run agent.make run-simple-demo
: Build and run simple demo.
make clean
: Clean build artifacts.
make help
: Show this help message.
- Purpose: Demonstrates how to create a basic MCP server using
mark3labs/mcp-go
. - Features: Implements a
fetch_url
tool for web content retrieval via stdio transport.
- Purpose: Shows how to integrate MCP tools with LangChain agents.
- Features: Supports multi-LLM (OpenAI, Google AI, Anthropic), combines MCP tools with standard LangChain tools, and manages MCP server lifecycle automatically.
- Purpose: A basic demonstration without requiring LLM API keys.
- Features: Shows MCP adapter creation and tool discovery, tests tool execution with real HTTP requests, and has no external dependencies beyond Go.
- Purpose: Provides simple MCP servers implemented in different languages (Node.js, Python) for testing purposes.
5. ⚙️ Configuration Files (examples/config.json
, examples/enhanced-config.json
, examples/mcp-spec-config.json
)
- Purpose: Illustrates various configurations for MCP servers, including
stdio
andsse
transports, and different command arguments.
The mcp-server-adapter
is configured via a JSON file. The Config
struct (defined in config.go
and types.go
) outlines the expected structure.
Key configuration options include:
mcpServers
: A map where keys are server names and values areServerConfig
objects.ServerConfig
:command
: (Required forstdio
transport) The command to execute the MCP server.args
: (Optional) Arguments to pass to the command.cwd
: (Optional) The working directory for the server process.env
: (Optional) Environment variables for the server process.disabled
: (Optional,true
/false
) Iftrue
, the server will not be started.transport
: (Optional, defaultstdio
) The communication transport (stdio
,sse
,http
).url
: (Required forsse
,http
transports) The URL of the MCP server.headers
: (Optional) HTTP headers forsse
orhttp
transports.timeout
: (Optional) Timeout for server operations.Method
: (Optional, defaultPOST
forhttp
transport) The HTTP method forhttp
transport (e.g.,GET
,POST
).tool_prefix
: (Optional, default empty string) A custom prefix for resolved tool names. When specified, the tool name format changes fromserverName.toolName
totool_prefix/toolname
. Example:"tool_prefix": "magic-prefix"
alwaysAllow
: (Optional) A list of tool names that are always permitted, usable for permissions or access control.
This project was inspired by langchaingo-mcp-adapter
.
Contributions are welcome! Please refer to the project's issue tracker for open tasks, or submit pull requests with improvements and bug fixes. Ensure your code adheres to the existing style and conventions.
This project is licensed under the MIT License. See the LICENSE
file for details.