{"record":{"id":"f7d8c5086975fc0b","repo":"micro/go-micro","slug":"registry-is-required","errorCode":null,"errorMessage":"registry is required","messagePattern":"registry is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gateway/mcp/mcp.go","lineNumber":266,"sourceCode":"\n// NewServer creates an MCP gateway server from opts and starts service\n// discovery and registry watching. It does not begin serving; call\n// (*Server).Serve to start a transport and (*Server).Stop to shut down\n// gracefully. This lets callers (e.g. the micro CLI) orchestrate the MCP\n// gateway independently of any other gateway.\nfunc NewServer(opts Options) (*Server, error) {\n\t// Set defaults\n\tif opts.Client == nil {\n\t\topts.Client = client.DefaultClient\n\t}\n\tif opts.Context == nil {\n\t\topts.Context = context.Background()\n\t}\n\tif opts.Logger == nil {\n\t\topts.Logger = log.Default()\n\t}\n\tif opts.Registry == nil {\n\t\treturn nil, fmt.Errorf(\"registry is required\")\n\t}\n\n\tserver := &Server{\n\t\topts:     opts,\n\t\ttools:    make(map[string]*Tool),\n\t\tlimiters: make(map[string]*rateLimiter),\n\t\tbreakers: make(map[string]*circuitBreaker),\n\t}\n\n\t// Discover services and build tool list\n\tif err := server.discoverServices(); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to discover services: %w\", err)\n\t}\n\n\t// Watch for service changes\n\tgo server.watchServices()\n\n\treturn server, nil","sourceCodeStart":248,"sourceCodeEnd":284,"githubUrl":"https://github.com/micro/go-micro/blob/24529f140421a11a33b6999ab7944f2021cfd69c/gateway/mcp/mcp.go#L248-L284","documentation":"NewServer validates its Options before constructing the MCP gateway Server. Since the gateway relies entirely on the registry for service discovery and tool building, a nil Registry makes the server unusable, so construction fails immediately with \"registry is required\" instead of panicking later.","triggerScenarios":"Calling mcp.NewServer (directly or via mcp.Serve/Run) with an Options struct where the Registry field is left as its zero value (nil), e.g. mcp.NewServer(mcp.Options{Address: \":3000\"}) without setting Registry.","commonSituations":"Developers copy the doc example but forget to pass service.Options().Registry; constructing Options programmatically in tests; running the gateway in a binary that never initialized a go-micro service so no registry was available to pass.","solutions":["Set Options.Registry to a registry implementation, e.g. Registry: service.Options().Registry or Registry: registry.DefaultRegistry.","If no service exists, explicitly construct one: reg := registry.NewRegistry(), then pass it in Options.","For tests, pass a memory registry such as memory.NewRegistry()."],"exampleFix":"// before\nsrv, err := mcp.NewServer(mcp.Options{Address: \":3000\"})\n// after\nsrv, err := mcp.NewServer(mcp.Options{\n    Registry: service.Options().Registry,\n    Address:  \":3000\",\n})","handlingStrategy":"validation","validationCode":"if opts.Registry == nil {\n    return fmt.Errorf(\"mcp.Options.Registry must be set before calling NewServer\")\n}","typeGuard":null,"tryCatchPattern":"srv, err := mcp.NewServer(opts)\nif err != nil {\n    log.Fatalf(\"mcp server init failed: %v\", err)\n}","preventionTips":["Always set Options.Registry from an initialized micro service (service.Options().Registry).","Centralize MCP Options construction in one helper so Registry can never be forgotten.","Add a unit test asserting NewServer succeeds with your production Options."],"tags":["mcp","configuration","registry"],"backgroundTag":"missing-required-config","analyzedSha":"24529f140421a11a33b6999ab7944f2021cfd69c","analyzedAt":"2026-09-01T02:52:24.923Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}