LoadMcp
Go · module github.com/muthuishere/toolnexus/golang · SPEC §2 · golang/mcp.go
func LoadMcp(input any, waitFor ...func(Request) (Answer, error)) (*McpSource, error)Reads MCP server configuration (via ParseMcpConfig), connects to
every enabled server — local stdio child processes and remote streamable-HTTP/SSE servers — lists
each one’s tools, and converts each into a uniform Tool. A bad server
never fails the whole load: it is isolated, logged, and marked failed in McpSource.Status.
When to use it
Section titled “When to use it”Reach for LoadMcp when you want tools from an mcp.json without the rest of the toolkit
machinery — no skills, no builtins, no adapters. It is also what CreateToolkit
calls internally for its McpConfig option.
Why this and not the alternative
Section titled “Why this and not the alternative”Examples
Section titled “Examples”All three examples load the shared examples/mcp.json fixture — the same file every port is
tested against. It has one enabled local server (everything, spawned via npx, which is not
reachable in a hermetic CI sandbox) and one disabled remote server (example-remote). Because
npx cannot actually reach the network here, these examples deliberately do not assert that the
enabled server connects — they assert what LoadMcp guarantees regardless: the disabled server is
skipped, a failed connection is isolated rather than fatal, and a malformed config still errors
before any connection is attempted.
1. Load the shared fixture and read per-server status
Section titled “1. Load the shared fixture and read per-server status”package main
import ( "fmt" "log" "os" "path/filepath"
toolnexus "github.com/muthuishere/toolnexus/golang")
func main() { // TOOLNEXUS_REPO is set by the docs test runner; in your own code just use a path. fixture := filepath.Join(os.Getenv("TOOLNEXUS_REPO"), "examples", "mcp.json")
src, err := toolnexus.LoadMcp(fixture) if err != nil { log.Fatal(err) } defer src.Close()
// The disabled remote server never gets a connection attempt. if src.Status["example-remote"] != toolnexus.StatusDisabled { log.Fatalf("expected example-remote disabled, got %v", src.Status["example-remote"]) }
// The enabled local server has SOME status — connected or failed, sandbox-dependent — // but it is never silently absent from Status. status, ok := src.Status["everything"] if !ok { log.Fatal("expected a status entry for 'everything'") }
fmt.Println("ok: example-remote=disabled, everything=", status)}2. A bad server is isolated, not fatal
Section titled “2. A bad server is isolated, not fatal”Two servers in one config: one that can never start (command points at a binary that does not
exist) and one that is disabled. LoadMcp still returns successfully — the failure is reported per
server, not as a returned error.
package main
import ( "fmt" "log"
toolnexus "github.com/muthuishere/toolnexus/golang")
func main() { config := toolnexus.McpConfig{ "broken": toolnexus.ServerConfig{ Type: "local", Command: []string{"toolnexus-docs-does-not-exist"}, }, }
src, err := toolnexus.LoadMcp(config) if err != nil { log.Fatalf("LoadMcp itself should not fail: %v", err) } defer src.Close()
if src.Status["broken"] != toolnexus.StatusFailed { log.Fatalf("expected 'broken' marked failed, got %v", src.Status["broken"]) } // A failed server contributes zero tools — the load degrades, it does not abort. if len(src.Tools) != 0 { log.Fatalf("expected no tools from a failed server, got %d", len(src.Tools)) }
fmt.Println("ok: broken server isolated as", src.Status["broken"])}3. Malformed config fails fast, before any connection
Section titled “3. Malformed config fails fast, before any connection”LoadMcp calls ParseMcpConfig first — a syntax error in the JSON never reaches the network or
spawns a process.
package main
import ( "fmt" "log"
toolnexus "github.com/muthuishere/toolnexus/golang")
func main() { _, err := toolnexus.LoadMcp([]byte(`{not valid json`)) if err == nil { log.Fatal("expected a parse error for malformed config") }
// A well-formed input of an unsupported type is also rejected up front. if _, err := toolnexus.LoadMcp(42); err == nil { log.Fatal("expected an error for an unsupported input type") }
fmt.Println("ok: malformed config rejected before connecting:", err)}Parameters
Section titled “Parameters”| Parameter | Type | What it does |
|---|---|---|
input |
any |
Anything ParseMcpConfig accepts — path, raw bytes, McpConfig, or map[string]any. |
waitFor |
...func(Request) (Answer, error) |
Optional (variadic) host resolver for MCP elicitation (§10). Omit to skip. |
Return value
Section titled “Return value”| Field | Type | What it holds |
|---|---|---|
McpSource.Tools |
[]Tool |
Every tool from every successfully connected server, namespaced server_tool. |
McpSource.Status |
map[string]McpStatus |
Per-server "connected", "disabled", or "failed". |
McpSource.Close() |
func() |
Disconnects every connected client. Always defer this. |
See also
Section titled “See also”LoadMcpWithContext— the ctx-aware load: bound connection time and cancel a slow or hung server without leaking a child process.ListMcpTools— list what each configured server would expose, plus per-server status, without wiring it into a toolkit.ParseMcpConfig— parse and validate config without connecting — the fast fail for a malformed or misspelled server block.ElicitationToRequest— map an MCP server’s elicitation request onto the §10 suspension contract, and map the answer back.CreateToolkit— the aggregator; MCP is one of several sources.