मुझे लगता है कि हम एक बिंदु पर हैं जहां मॉडल संदर्भ प्रोटोकॉल (एमसीपी) लगभग जीएनएआई इंजीनियरिंग के समान महसूस करता है। एंथ्रोपिक ने नवंबर 2024 में एमसीपी पेश किया, जो जीएनएआई इंजीनियरिंग को क्रांतिकारी बनाता है। यह हमें उस बिंदु पर लाया है जहां, इंजीनियरों के रूप में, हम अपने उपयोग के मामले के आधार पर विभिन्न उपकरणों को लागू कर सकते हैं, और हमारे पसंद के एलएलएम को अपने पसंदीदा आईडीई या डेस्कटॉप ग्राहकों के आराम से इन उपकरणों का उपयोग करने के लिए निर्देशित कर सकते हैं, जैसे क्लाड। इसके आगमन के बाद से, कई एमसीपी सर्वर उत्साही इंजीनियरों द्वारा विकसित किए , और हाल ही में, मैं देखता हूँ , और मुझे पता था कि मुझे इसे एक स्पिन के लिए लेना होगा! पायथन टाइप गोल्डन एक Golang SDK के लिए इस आधिकारिक प्रस्ताव MCP क्या है, आप पूछते हैं? चलो एमसीपी के लिए एक त्वरित परिचय के साथ शुरू करते हैं, जो . हाल ही में तक, एआई इंजीनियरिंग को विभिन्न एलएलएम की क्षमताओं की सावधानीपूर्वक मूल्यांकन करने की आवश्यकता थी ताकि सही विकल्प चुनें. एमसीपी के साथ, आप अपनी पसंद के एलएलएम का चयन कर सकते हैं, और अनुकूलित उपकरणों को लागू करके इसकी क्षमताओं को बढ़ा सकते हैं और खुद को बाहरी डेटा स्रोतों से कनेक्ट कर सकते हैं! प्रोटोकॉल के मुख्य निर्माण हैं: Model Context Protocol एमसीपी क्लाइंट एमसीपी सर्वर क्षमताएं (उपयोग, संसाधनों, प्रॉम्प्ट्स) एलएलएम एक एमसीपी सर्वर में कुछ क्षमताएं होती हैं जो निर्धारित होती हैं: उपकरण - यह कार्य करता है, जैसे कि एक भेजने वाले से सभी ईमेल सूची, Github पर एक PR खोजें संसाधन - बाहरी डेटा स्रोत, जैसे कि दस्तावेजों की एक सूची जिसे आप एलएलएम को संदर्भित करना चाहते हैं Prompts - टेम्पलेट्स का एक सेट जो उपयोगकर्ताओं को वांछित उत्तरों को जल्दी प्राप्त करने में मदद करता है कई एमसीपी सर्वर पहले से ही उपलब्ध हैं जिन्हें आप अपने अनुप्रयोगों के लिए उपयोग करना शुरू कर सकते हैं. आप इस शानदार एमसीपी सर्वर का संकलन संदर्भित कर सकते हैं: https://github.com/punkpeye/awesome-mcp-servers BYOM (अपने स्वयं के एमसीपी सर्वर लाएं) इस पोस्ट में, मैं इस बारे में जाना चाहता हूं कि हम Golang का उपयोग करके अपने स्वयं के एमसीपी सर्वर को कैसे विकसित कर सकते हैं. कुछ दिनों पहले, किसी भी कारण के लिए, मैं इस सूची में सभी रिकॉर्डर पर जाना चाहता था . Kubernetes GitHub से जुड़ें अब मैं आधिकारिक GitHub MCP सर्वर का उपयोग कर सकता था, लेकिन हालांकि यह रजिस्टर और संगठनों के लिए एक महान टूलसेट प्रदान करता है, इसमें एक संगठन में सभी रजिस्टर को सूचीबद्ध करने के लिए एक प्रत्यक्ष उपकरण नहीं था। Golang में एक MCP सर्वर विकसित करना यह आधिकारिक Golang MCP SDK है: README और उदाहरण / फ़ोल्डर में एक एमसीपी सर्वर और क्लाइंट के विकास के महान उदाहरण हैं। https://github.com/modelcontextprotocol/go-sdk इन उदाहरणों के बाद, मैंने एक एमसीपी सर्वर को निम्नलिखित तरीके से बनाने का फैसला किया: server := mcp.NewServer(&mcp.Implementation{ Name: "demo-github-mcp", Title: "A demo github mcp server", Version: "0.0.1", }, nil) अगला कदम सर्वर को एक GitHub org में सभी रिपोरेटरी को सूचीबद्ध करने की क्षमता प्रदान करना था। type ToolHandlerFor[In, Out any] func(context.Context, *ServerSession, *CallToolParamsFor[In]) (*CallToolResultFor[Out], error) इसके बाद मैंने एक उपकरण, जो इनपुट के रूप में Github org से संबंधित निम्नलिखित तर्क स्वीकार करता है: ListRepositories // User can pass in either the name of the org (example: kubernetes), or its URL (example: https://github.com/kubernetes) type GithubOrgArgs struct { Name string URL string } func ListRepositories(ctx context.Context, ss *mcp.ServerSession, params *mcp.CallToolParamsFor[GithubOrgArgs]) (*mcp.CallToolResultFor[struct{}], error) { Now let's go over the body of ListRepositories step-by-step: इनपुट सत्यापन यह सुनिश्चित करने के लिए कि हम केवल वैध तर्क स्वीकार करते हैं if params == nil { return nil, fmt.Errorf("empty params") } args := params.Arguments if args.Name == "" && args.URL == "" { return nil, fmt.Errorf("empty args") } GitHub API docs पर आधारित इनपुट से GitHub API URL का गठन करना var apiURL string var organization string if args.URL != "" { // If URL is provided, extract org name and build API URL url := strings.TrimPrefix(args.URL, "https://") url = strings.TrimPrefix(url, "http://") url = strings.TrimPrefix(url, "github.com/") url = strings.TrimSuffix(url, "/") orgName := strings.Split(url, "/")[0] apiURL = fmt.Sprintf("https://api.github.com/orgs/%s/repos", orgName) organization = orgName } else { // Use the provided organization name apiURL = fmt.Sprintf("https://api.github.com/orgs/%s/repos", args.Name) organization = args.Name } apiURL = apiURL + "?per_page=100" अनुरोध भेजें और जवाब प्राप्त करें client := &http.Client{Timeout: 10 * time.Second} req, err := http.NewRequestWithContext(ctx, "GET", apiURL, nil) if err != nil { return nil, err } req.Header.Add("Accept", "application/vnd.github.v3+json") resp, err := client.Do(req) if err != nil { return nil, err } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { body, _ := io.ReadAll(resp.Body) return nil, fmt.Errorf("GitHub API error (status %d): %s", resp.StatusCode, string(body)) } GitHub API से प्रतिक्रिया का विश्लेषण करें type repository struct { Name string `json:"name"` FullName string `json:"full_name"` HTMLURL string `json:"html_url"` Private bool `json:"private"` } // Parse the JSON response var repositories []repository if err := json.NewDecoder(resp.Body).Decode(&repositories); err != nil { return nil, fmt.Errorf("failed to parse response: %w", err) } उत्तर को एक पाठ संदर्भ के रूप में वापस करें var result strings.Builder result.WriteString(fmt.Sprintf("Repositories for organization %s:", organization)) for _, repo := range repositories { result.WriteString(fmt.Sprintf("Name: %s, URL: %s", repo.Name, repo.HTMLURL)) } return &mcp.CallToolResultFor[struct{}]{ Content: []mcp.Content{ &mcp.TextContent{Text: result.String()}, }, }, nil उपकरण को परिभाषित करने के बाद, अगला कदम इसे एमसीपी सर्वर के साथ पंजीकरण करना है: mcp.AddTool(server, &mcp.Tool{ Name: "list-repositories", Description: "A tool to list all repositories in a Github org", InputSchema: &jsonschema.Schema{ Type: "object", Properties: map[string]*jsonschema.Schema{ "name": { Type: "string", Description: "GitHub organization name (e.g., kubernetes)", }, "url": { Type: "string", Description: "GitHub organization URL (e.g., https://github.com/kubernetes)", }, }, }, }, ListRepositories) अगला, यह सर्वर शुरू करने का समय है! इस डेमो MCP सर्वर के लिए, मैं स्टडीओ परिवहन का उपयोग कर रहा हूं, जो सर्वर को STDIN और STDOUT के माध्यम से संचार करने की अनुमति देता है। t := mcp.NewLoggingTransport(mcp.NewStdioTransport(), os.Stderr) log.Println("🚀 MCP server starting up...") if err := server.Run(context.Background(), t); err != nil { log.Printf("Server failed: %v", err) } log.Println("🚀 MCP server shutting down...") यह सब एक साथ रखे हुए कोड के साथ कैसा दिखता है: func main() { server := mcp.NewServer(&mcp.Implementation{ Name: "demo-github-mcp", Title: "A demo github mcp server", Version: "0.0.1", }, nil) mcp.AddTool(server, &mcp.Tool{ Name: "list-repositories", Description: "A tool to list all repositories in a Github org", InputSchema: &jsonschema.Schema{ Type: "object", Properties: map[string]*jsonschema.Schema{ "name": { Type: "string", Description: "GitHub organization name (e.g., kubernetes)", }, "url": { Type: "string", Description: "GitHub organization URL (e.g., https://github.com/kubernetes)", }, }, }, }, ListRepositories) t := mcp.NewLoggingTransport(mcp.NewStdioTransport(), os.Stderr) log.Println("🚀 MCP server starting up...") if err := server.Run(context.Background(), t); err != nil { log.Printf("Server failed: %v", err) } log.Println("🚀 MCP server shutting down...") } type GithubOrgArgs struct { Name string URL string } func ListRepositories(ctx context.Context, ss *mcp.ServerSession, params *mcp.CallToolParamsFor[GithubOrgArgs]) (*mcp.CallToolResultFor[struct{}], error) { if params == nil { return nil, fmt.Errorf("empty params") } args := params.Arguments if args.Name == "" && args.URL == "" { return nil, fmt.Errorf("empty args") } var apiURL string var organization string if args.URL != "" { // If URL is provided, extract org name and build API URL url := strings.TrimPrefix(args.URL, "https://") url = strings.TrimPrefix(url, "http://") url = strings.TrimPrefix(url, "github.com/") url = strings.TrimSuffix(url, "/") orgName := strings.Split(url, "/")[0] apiURL = fmt.Sprintf("https://api.github.com/orgs/%s/repos", orgName) organization = orgName } else { // Use the provided organization name apiURL = fmt.Sprintf("https://api.github.com/orgs/%s/repos", args.Name) organization = args.Name } apiURL = apiURL + "?per_page=100" client := &http.Client{Timeout: 10 * time.Second} req, err := http.NewRequestWithContext(ctx, "GET", apiURL, nil) if err != nil { return nil, err } req.Header.Add("Accept", "application/vnd.github.v3+json") resp, err := client.Do(req) if err != nil { return nil, err } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { body, _ := io.ReadAll(resp.Body) return nil, fmt.Errorf("GitHub API error (status %d): %s", resp.StatusCode, string(body)) } type repository struct { Name string `json:"name"` FullName string `json:"full_name"` HTMLURL string `json:"html_url"` Private bool `json:"private"` } // Parse the JSON response var repositories []repository if err := json.NewDecoder(resp.Body).Decode(&repositories); err != nil { return nil, fmt.Errorf("failed to parse response: %w", err) } var result strings.Builder result.WriteString(fmt.Sprintf("Repositories for organization %s:", organization)) for _, repo := range repositories { result.WriteString(fmt.Sprintf("Name: %s, URL: %s", repo.Name, repo.HTMLURL)) } return &mcp.CallToolResultFor[struct{}]{ Content: []mcp.Content{ &mcp.TextContent{Text: result.String()}, }, }, nil } अब अंतिम कदम यह संकलित करना है और निम्नलिखित के साथ संचालित को उत्पन्न करना है: go build Claude जैसे क्लाइंट के साथ MCP सर्वर का उपयोग करना आइए देखें कि इस सर्वर को क्लॉड के डेस्कटॉप पर कैसे जोड़ें। Claude डेस्कटॉप ऐप खोलें, और Claude -> सेटिंग्स -> डेवलपर्स पर जाएं। यहां आप Local MCP Servers नामक एक अनुभाग देखेंगे. Edit Config नामक नीचे दिए गए बटन पर क्लिक करें. यह Claude config फ़ाइल खोल देगा. MCP सर्वर को जोड़ने के लिए फ़ाइल को संपादित करें: { "mcpServers": { "demo-github-mcp": { "command": "/path/to/executable/generated/from/go build", "args": [] } } } क्लाउड ऐप को फिर से शुरू करें (अब, यह क्लाउड के भीतर एमसीपी सर्वर को ताजा करने का एकमात्र तरीका है) और अब यह परीक्षण करने का समय है! ये है मैंने दिया प्रोत्साहन: List all repositories in the Kubernetes github org क्लॉड ने स्थानीय रूप से चलने वाले डेमो-github-mcp सर्वर को पहचाना और पूछा कि क्या यह इसका उपयोग कर सकता है! जैसे ही मैंने इसे अनुमोदित किया, क्लाउड ने org में रिपॉजिटरी सूचीबद्ध की और यहां तक कि जवाब की शुरुआत में उपयोग किए गए टूल (लिस्ट-रिपॉजिटरी) को भी प्रदर्शित किया: हमने देखा कि हम Golang का उपयोग करके एक सरल MCP सर्वर विकसित कर सकते हैं, और इसे Claude जैसे MCP क्लाइंट के माध्यम से उपयोग कर सकते हैं! ‘अहा’ का समय जब मैं इस सर्वर को विकसित कर रहा था, तो मैंने खुद से पूछा: "अगर मैं सूचीबद्ध भंडारण के लिए कोड लिख रहा हूं, तो एलएलएम क्या करेगा? जब क्लाउड सोननेट 4 ने मेरी परामर्श पढ़ी - "Kubernetes GitHub org में सभी भंडारण सूची" - और खुद को पहचाना कि स्थानीय रूप से चलने वाले एमसीपी सर्वर परामर्श के लिए सबसे अच्छा काम करेंगे, मेरे दिमाग को फेंक दिया गया था 😀 उस बिंदु पर, मुझे इसे उपकरण के नाम या इसके अनुमोदित मापदंडों के बारे में कोई जानकारी प्रदान करने की आवश्यकता नहीं थी। उत्पादन विचार जबकि हमारे एमसीपी सर्वर डेमो उद्देश्यों के लिए महान काम करते हैं, उत्पादन उपयोग के लिए कई महत्वपूर्ण विशेषताएं गायब हैं: Pagination handling: GitHub का API paginated results returns, डिफ़ॉल्ट 30 entries per page. In the above code I have increased that to 100 with the per_page query parameter. Production code, you would process the response header Link to get information about the next page and total number of pages. (इसको संदर्भित करें) दर सीमा: उपरोक्त कोड में GitHub API दर सीमाओं को ध्यान में नहीं रखा जाता है सत्यापन: सत्यापित अनुरोधों में असत्यापित अनुरोधों की तुलना में उच्च दर सीमा होती है. निजी GitHub रिपोरेटरीज / उद्यम GitHub के अनुरोधों के लिए सत्यापन भी आवश्यक है. अगला क्या है? यह डेमो GitHub MCP सर्वर एक अच्छा शुरुआत था. लेकिन मुख्य कारण मैं इसे लिख रहा हूं यह दिखाने के लिए है कि आपके पसंदीदा GenAI उपकरण को अपनी पसंद के लिए अनुकूलित करना कितना आसान हो सकता है! यह भी आश्चर्यजनक रूप से सरल है अपने स्वयं के परियोजनाओं के लिए गोलांग में एक MCP सर्वर के साथ शुरू करना! मैं MCP की लचीलापन और गोलांग की उच्च प्रदर्शन प्रकृति के संयोजन से बनाई गई शक्तिशाली सेवाओं को देखने के लिए इंतजार नहीं कर सकता!