SkillAgentSearch skills...

mcp-client-manager-go

Package mcpmgr provides a high-level manager for connecting to, monitoring, and coordinating multiple Model Context Protocol (MCP) servers from Go applications. The companion mcpgateway package builds on top of mcpmgr to expose every managed server through a single Streamable HTTP endpoint.

Install / Use

claude mcp add VikashLoomba -- npx -y github:VikashLoomba/mcp-client-manager-go

If the server publishes to npm under a different name, use that package instead — check the repo README.

About this skill
🔌

MCP Server

Model Context Protocol server

Quality Score

78/100

Category

Operations

Supported Platforms

Claude Code
Claude Desktop

Tags

Our assessment of mcp-client-manager-go

mcp-client-manager-go scores 78/100 on our quality scale, 680th of 757 Operations skills we index.

Its MCP Server is 14 KB long, well organised into 16 sections with 15 code examples: a thorough specification that gives an agent plenty to work with.

It has 3 GitHub stars, so there is little community track record yet; judge it on its content.

Substance
30/30
Structure
20/20
Description
15/15
Adoption
3/20
Freshness
11/15

Maintenance, license and trust

  • The repository was last updated about 12 months ago. That is recent enough to be usable, but agent tooling moves fast, so check the instructions against your agent's current version.
  • Our last check on 2026-08-12 found the source still online.
  • It is released under the MIT license, a permissive license that allows use, modification and commercial use with attribution.
  • Its trust signals score 86/100, with 2 cautions from licensing, adoption, age or documentation. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.

mcp-client-manager-go compared with similar skills

All 4 of these similar skills score higher than mcp-client-manager-go; compare them before choosing.

SkillScoreStarsUpdatedFormat
mcp-client-manager-go (this skill)by VikashLoomba78312mo agoMCP Server
Agent-Reachby Panniantong100106.6k5d agoCLAUDE.md
headroomby headroomlabs-ai10078.3ktodayCLAUDE.md
CowAgentby zhayujie10047.7ktodayCLAUDE.md
Scraplingby D4Vinci10090.4k1d agoMCP Server

Frequently asked questions

How do I install mcp-client-manager-go?
Run claude mcp add VikashLoomba -- npx -y github:VikashLoomba/mcp-client-manager-go. The install tabs above show the steps for each supported agent.
Which AI agents does mcp-client-manager-go work with?
It is written for Claude Code and Claude Desktop, as a MCP Server file. Other agents that read the same format can often use it too.
Is mcp-client-manager-go safe to use?
It is MIT-licensed and scores 86/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
Is mcp-client-manager-go still maintained?
The repository was last updated about 12 months ago. That is recent enough to be usable, but agent tooling moves fast, so check the instructions against your agent's current version.

MCP Client Manager (Go)

mcpmgr is a lightweight orchestration layer around the modelcontextprotocol/go-sdk client. It keeps multiple MCP transports (stdio or HTTP) alive, fans out events, and exposes ergonomic helpers for listing or invoking tools, prompts, and resources from Go applications. The companion mcpgateway package builds on top of mcpmgr to expose every managed server through a single Streamable HTTP endpoint.

Install

go get github.com/vikashloomba/mcp-client-manager-go/pkg/mcpmgr
go get github.com/vikashloomba/mcp-client-manager-go/pkg/mcp-gateway

Initialize with pre-registered servers

package main

import (
    "context"
    "time"

    "github.com/vikashloomba/mcp-client-manager-go/pkg/mcpmgr"
)

func main() {
    manager := mcpmgr.NewManager(map[string]mcpmgr.ServerConfig{
        "stdio-example": &mcpmgr.StdioServerConfig{
            BaseServerConfig: mcpmgr.BaseServerConfig{Timeout: 30 * time.Second},
            Command:          "npx",
            Args:             []string{"@modelcontextprotocol/server-everything"},
        },
        "streamable-example": &mcpmgr.HTTPServerConfig{
            BaseServerConfig: mcpmgr.BaseServerConfig{Timeout: 30 * time.Second},
            Endpoint:         "https://gitmcp.io/modelcontextprotocol/go-sdk",
        },
    }, &mcpmgr.ManagerOptions{DefaultClientName: "my-app", AutoConnect: true})

    ctx := context.Background()
    // AutoConnect will dial the transports in the background; ensure you close
    // them before exiting.
    defer manager.DisconnectAllServers(ctx)
}

Add a server after initialization

ctx := context.Background()

config := &mcpmgr.HTTPServerConfig{
    BaseServerConfig: mcpmgr.BaseServerConfig{Timeout: 45 * time.Second},
    Endpoint:         "https://gitmcp.io/modelcontextprotocol/go-sdk",
}

if _, err := manager.ConnectToServer(ctx, "docs-server", config); err != nil {
    panic(err)
}

List and call tools

tools, err := manager.ListTools(ctx, "streamable-example", nil)
if err != nil {
    panic(err)
}

for _, tool := range tools.Tools {
    println("Tool:", tool.Name)
}

result, err := manager.ExecuteTool(ctx, "streamable-example", "fetch_url_content", map[string]any{
    "url": "https://example.com",
})
if err != nil {
    panic(err)
}
println("Result:", result.Content)

Read prompts and resources

prompts, err := manager.ListPrompts(ctx, "stdio-example", nil)
if err != nil {
    panic(err)
}
for _, prompt := range prompts.Prompts {
    println("Prompt:", prompt.Name)
}

resources, err := manager.ListResources(ctx, "stdio-example", nil)
if err != nil {
    panic(err)
}
for _, resource := range resources.Resources {
    println("Resource:", resource.URI)
}

details, err := manager.ReadResource(ctx, "stdio-example", &mcp.ReadResourceParams{URI: resources.Resources[0].URI})
if err != nil {
    panic(err)
}
println("First resource size:", len(details.Resource.Data))

Run a Streamable MCP gateway

The mcpgateway package re-exports every tool, prompt, and resource managed by mcpmgr through a single Streamable HTTP endpoint so downstream clients only have to connect once.

package main

import (
    "context"
    "log"
    "time"

    mcpgateway "github.com/vikashloomba/mcp-client-manager-go/pkg/mcp-gateway"
    "github.com/vikashloomba/mcp-client-manager-go/pkg/mcpmgr"
)

func main() {
    manager := mcpmgr.NewManager(map[string]mcpmgr.ServerConfig{
        "stdio-example": &mcpmgr.StdioServerConfig{
            BaseServerConfig: mcpmgr.BaseServerConfig{Timeout: 30 * time.Second},
            Command:          "npx",
            Args:             []string{"@modelcontextprotocol/server-everything"},
        },
    }, &mcpmgr.ManagerOptions{DefaultClientName: "gateway-example", AutoConnect: true})

    gateway, err := mcpgateway.NewGateway(manager, &mcpgateway.Options{Addr: ":8787", Path: "/mcp"})
    if err != nil {
        log.Fatalf("gateway init failed: %v", err)
    }

    ctx := context.Background()
    defer manager.DisconnectAllServers(ctx)

    log.Println("Serving MCP gateway on http://localhost:8787/mcp")
    if err := gateway.ListenAndServe(ctx); err != nil {
        log.Fatalf("gateway stopped: %v", err)
    }
}

Check cmd/gateway-example for a runnable sample and the package docs under pkg/mcp-gateway for customization options like namespace strategies, notification hooks, progress fan-out, and elicitation bridging.

Inspect and serialize server configs

GetServerSummaries() returns a slice of summaries where Config is a ServerConfig interface implemented by *StdioServerConfig or *HTTPServerConfig. To avoid type switches at every call site, use the helper guards and narrowers:

summaries := manager.GetServerSummaries()
for _, s := range summaries {
    switch mcpmgr.TransportOf(s.Config) {
    case mcpmgr.TransportStdio:
        if cfg, ok := mcpmgr.AsStdio(s.Config); ok {
            // Use cfg.Command, cfg.Args, cfg.Env, etc.
        }
    case mcpmgr.TransportHTTP:
        if cfg, ok := mcpmgr.AsHTTP(s.Config); ok {
            // Use cfg.Endpoint, cfg.MaxRetries, cfg.PreferSSE, etc.
        }
    }
}

Note: BaseServerConfig contains function fields (e.g., OnError, RPCLogger) which encoding/json cannot marshal. When building an API that returns summaries as JSON, construct a JSON‑safe DTO instead of marshaling the config directly. For example:

type serverSummaryDTO struct {
    ID     string                 `json:"id"`
    Status mcpmgr.ConnectionStatus `json:"status"`
    Config map[string]any         `json:"config"`
}

func buildSummaryDTOs(m *mcpmgr.Manager) ([]serverSummaryDTO, error) {
    sums := m.GetServerSummaries()
    out := make([]serverSummaryDTO, 0, len(sums))
    for _, s := range sums {
        dto := serverSummaryDTO{ID: s.ID, Status: s.Status, Config: map[string]any{}}
        switch mcpmgr.TransportOf(s.Config) {
        case mcpmgr.TransportStdio:
            if c, ok := mcpmgr.AsStdio(s.Config); ok {
                dto.Config = map[string]any{
                    "type":           "stdio",
                    "command":        c.Command,
                    "args":           c.Args,
                    "env":            c.Env,
                    "timeoutSeconds": int(c.BaseServerConfig.Timeout / time.Second),
                    "version":        c.BaseServerConfig.Version,
                }
            }
        case mcpmgr.TransportHTTP:
            if c, ok := mcpmgr.AsHTTP(s.Config); ok {
                dto.Config = map[string]any{
                    "type":           "http",
                    "endpoint":       c.Endpoint,
                    "maxRetries":     c.MaxRetries,
                    "sessionId":      c.SessionID,
                    "preferSse":      c.PreferSSE,
                    "timeoutSeconds": int(c.BaseServerConfig.Timeout / time.Second),
                    "version":        c.BaseServerConfig.Version,
                }
            }
        }
        out = append(out, dto)
    }
    return out, nil
}

Add custom HTTP routes

If you want to host extra endpoints alongside the MCP gateway (for health checks, metrics, etc.), call ServeMux() to get the underlying mux and register routes before starting the server:

gateway, _ := mcpgateway.NewGateway(manager, &mcpgateway.Options{Addr: ":8787", Path: "/mcp"})

// Add custom routes on the same server.
mux := gateway.ServeMux()
mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(200) })

// Start the gateway's server.
_ = gateway.ListenAndServe(context.Background())

Alternatively, you can run your own http.Server and reuse the gateway's handler and state:

srv := &http.Server{Addr: ":8787"}
// If Handler is nil, ListenAndServeServer will install gateway.Handler().
_ = gateway.ListenAndServeServer(context.Background(), srv)

When bearer-token protection is enabled via Options.TokenVerifier, only the Streamable MCP endpoint is protected by that middleware. Additional routes you register are not automatically wrapped; apply your own auth as needed.

UI Roots mirroring

Some MCP servers restrict access to file resources based on the client's UI "roots". The gateway can mirror the UI's root set to every downstream server. Use the new helpers when your UI learns its effective roots:

// Replace all roots at once (diffed and propagated to all downstream servers):
gateway.SetUIRoots([]*mcp.Root{{URI: "file:///workspace", Name: "Workspace"}})

// Or incrementally add/remove roots:
gateway.AddUIRoots(&mcp.Root{URI: "file:///tmp", Name: "Temp"})
gateway.RemoveUIRoots("file:///tmp")

When a new server is attached via gateway.AttachServer, the current cached roots are pushed to that server's client so it immediately reflects the UI set.

Removing servers cleanly

The gateway now exposes DetachServer and RemoveServer helpers:

// Detach removes a server's tools/prompts/resources from the aggregated view.
_ = gateway.DetachServer(ctx, serverID)

// Remove detaches and then calls manager.RemoveServer to close and delete it.
_ = gateway.RemoveServer(ctx, serverID)

Additionally, mcpmgr.Manager emits a removal event that the gateway subscribes to; calling manager.RemoveServer(ctx, id) automatically prunes the server's features from the gateway so they no longer appear to clients.

Progress notifications

Both mcpmgr and the gateway preserve _meta.progressToken values and forward notifications/progress end-to-end, even when upstream servers emit float tokens or clients omit a token (the gateway auto-generates one per request). Downstream consumers only need to register a handler when they connect:

client := mcp.NewClient(
    &mcp.Implementation{Name: "ui", Version: "1.0.0"},
    &mcp.ClientOptions{
        ProgressNotificationHandler: func(_ context.Context, req *mcp.ProgressNotificationClientRequest) {
            if req == nil || req.Params == nil {
                return
            }
            log.Printf("progress %s %.0f/%.0f", req.Params.Message, req.Params.Progress, req.Params.Total)
        },
    },
)
session, err := client.Connect(ctx, transport, nil)

If you need to observe upstream progress inside your Go service (for metrics or UI relay), set ManagerOptions.DefaultClientOptions.ProgressNotificationHandler or call manager.AddNotificationHandler(serverID, mcpmgr.NotificationSchemaProgress, ...).

Optional OAuth 2.0 protection

mcpgateway can require bearer tokens before it forwards any MCP traffic. To enable this, populate mcpgateway.Options.TokenVerifier with your token inspection logic and provide matching TokenOptions (auth.RequireBearerTokenOptions). When both are present, the gateway wraps the Streamable handler with auth.RequireBearerToken, automatically hosts /.well-known/oauth-protected-resource, replies with the correct WWW-Authenticate: Bearer resource_metadata=… header, and enables CORS on the metadata endpoint. Set Options.AuthorizationServer so the metadata response links to your issuer, and override Options.ResourceURL if the public URL clients will use does not match http://localhost<Addr><Path>.

The sample in cmd/gateway-example toggles this behavior with environment variables so you can opt in without changing code:

| Variable | Description | Example value | | --- | --- | --- | | AUTHORIZATION_SERVER_URL | Base URL of the OAuth 2.0/OIDC authorization server that issues gateway tokens. | https://example-server.modelcontextprotocol.io/ | | OAUTH_RESOURCE_METADATA_URL | Fully-qualified URL where clients discover the gateway's resource metadata. This should usually be your deployed gateway's /.well-known/oauth-protected-resource. | https://example-server.modelcontextprotocol.io/.well-known/oauth-protected-resource |

`

Truncated for display — read the full file on GitHub.

Related Skills

View on GitHub
GitHub Stars3
CategoryOperations
Updated12mo ago
Forks1

Languages

Go

Trust signals

86/100

From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.

2 low