Skip to content

Instantly share code, notes, and snippets.

@kuc-arc-f
Last active October 16, 2025 02:54
Show Gist options
  • Save kuc-arc-f/058ff841268ad3a96c0731ce72cf3340 to your computer and use it in GitHub Desktop.
Save kuc-arc-f/058ff841268ad3a96c0731ce72cf3340 to your computer and use it in GitHub Desktop.
GoLang remoto MCP Server , example

mcp_5

Version: 0.9.1

date : 2025/10/16


GoLang remoto MCP Server , example


  • build
go mod init example.com/go-remote-mcp-server5
go mod tidy

go build
go run .
module example.com/go-remote-mcp-server5
go 1.24.4
package main
import (
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"sync"
)
// JSON-RPC 2.0 Request
type JSONRPCRequest struct {
JSONRPC string `json:"jsonrpc"`
Method string `json:"method"`
Params json.RawMessage `json:"params,omitempty"`
ID interface{} `json:"id"`
}
// JSON-RPC 2.0 Response
type JSONRPCResponse struct {
JSONRPC string `json:"jsonrpc"`
Result interface{} `json:"result,omitempty"`
Error *RPCError `json:"error,omitempty"`
ID interface{} `json:"id"`
}
// JSON-RPC 2.0 Error
type RPCError struct {
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data,omitempty"`
}
// MCP Tool Definition
type Tool struct {
Name string `json:"name"`
Description string `json:"description"`
InputSchema map[string]interface{} `json:"inputSchema"`
}
// MCP Server
type MCPServer struct {
tools map[string]Tool
mu sync.RWMutex
}
func NewMCPServer() *MCPServer {
server := &MCPServer{
tools: make(map[string]Tool),
}
// サンプルツールの登録
server.RegisterTool(Tool{
Name: "echo",
Description: "Echo back the input message",
InputSchema: map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"message": map[string]interface{}{
"type": "string",
"description": "The message to echo",
},
},
"required": []string{"message"},
},
})
server.RegisterTool(Tool{
Name: "add",
Description: "Add two numbers",
InputSchema: map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"a": map[string]interface{}{
"type": "number",
"description": "First number",
},
"b": map[string]interface{}{
"type": "number",
"description": "Second number",
},
},
"required": []string{"a", "b"},
},
})
return server
}
func (s *MCPServer) RegisterTool(tool Tool) {
s.mu.Lock()
defer s.mu.Unlock()
s.tools[tool.Name] = tool
}
func (s *MCPServer) HandleRequest(req JSONRPCRequest) JSONRPCResponse {
switch req.Method {
case "tools/list":
return s.handleToolsList(req)
case "tools/call":
return s.handleToolsCall(req)
case "initialize":
return s.handleInitialize(req)
default:
return JSONRPCResponse{
JSONRPC: "2.0",
Error: &RPCError{
Code: -32601,
Message: "Method not found",
},
ID: req.ID,
}
}
}
func (s *MCPServer) handleInitialize(req JSONRPCRequest) JSONRPCResponse {
return JSONRPCResponse{
JSONRPC: "2.0",
Result: map[string]interface{}{
"protocolVersion": "2024-11-05",
"serverInfo": map[string]interface{}{
"name": "sample-mcp-server",
"version": "1.0.0",
},
"capabilities": map[string]interface{}{
"tools": map[string]interface{}{},
},
},
ID: req.ID,
}
}
func (s *MCPServer) handleToolsList(req JSONRPCRequest) JSONRPCResponse {
s.mu.RLock()
defer s.mu.RUnlock()
tools := make([]Tool, 0, len(s.tools))
for _, tool := range s.tools {
tools = append(tools, tool)
}
return JSONRPCResponse{
JSONRPC: "2.0",
Result: map[string]interface{}{
"tools": tools,
},
ID: req.ID,
}
}
func (s *MCPServer) handleToolsCall(req JSONRPCRequest) JSONRPCResponse {
var params struct {
Name string `json:"name"`
Arguments map[string]interface{} `json:"arguments"`
}
if err := json.Unmarshal(req.Params, &params); err != nil {
return JSONRPCResponse{
JSONRPC: "2.0",
Error: &RPCError{
Code: -32602,
Message: "Invalid params",
Data: err.Error(),
},
ID: req.ID,
}
}
// ツールの実行
result, err := s.executeTool(params.Name, params.Arguments)
if err != nil {
return JSONRPCResponse{
JSONRPC: "2.0",
Error: &RPCError{
Code: -32603,
Message: "Internal error",
Data: err.Error(),
},
ID: req.ID,
}
}
return JSONRPCResponse{
JSONRPC: "2.0",
Result: map[string]interface{}{
"content": []map[string]interface{}{
{
"type": "text",
"text": result,
},
},
},
ID: req.ID,
}
}
func (s *MCPServer) executeTool(name string, args map[string]interface{}) (string, error) {
s.mu.RLock()
_, exists := s.tools[name]
s.mu.RUnlock()
if !exists {
return "", fmt.Errorf("tool not found: %s", name)
}
switch name {
case "echo":
message, ok := args["message"].(string)
if !ok {
return "", fmt.Errorf("invalid message parameter")
}
return message, nil
case "add":
a, ok1 := args["a"].(float64)
b, ok2 := args["b"].(float64)
if !ok1 || !ok2 {
return "", fmt.Errorf("invalid number parameters")
}
return fmt.Sprintf("%.2f", a+b), nil
default:
return "", fmt.Errorf("tool execution not implemented: %s", name)
}
}
// HTTP Handler
func (s *MCPServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
body, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, "Failed to read request body", http.StatusBadRequest)
return
}
defer r.Body.Close()
var req JSONRPCRequest
if err := json.Unmarshal(body, &req); err != nil {
resp := JSONRPCResponse{
JSONRPC: "2.0",
Error: &RPCError{
Code: -32700,
Message: "Parse error",
},
ID: nil,
}
s.writeResponse(w, resp)
return
}
resp := s.HandleRequest(req)
s.writeResponse(w, resp)
}
func (s *MCPServer) writeResponse(w http.ResponseWriter, resp JSONRPCResponse) {
w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(resp); err != nil {
log.Printf("Failed to encode response: %v", err)
}
}
func main() {
server := NewMCPServer()
http.Handle("/mcp", server)
port := ":8080"
log.Printf("MCP Server starting on %s", port)
if err := http.ListenAndServe(port, nil); err != nil {
log.Fatal(err)
}
}
const start = async function() {
try{
const item = {
"jsonrpc": "2.0",
"method": "tools/list",
"id": 2
}
const response = await fetch("http://localhost:8080/mcp", {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': '',
},
body: JSON.stringify(item),
});
if (!response.ok) {
const text = await response.text();
console.log(text);
throw new Error('Failed to create item');
}else{
const json = await response.json();
console.log(json);
console.log(json.result.tools);
}
}catch(e){console.log(e)}
}
start();
const start = async function() {
try{
const item = {
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "echo",
"arguments": {
"message": "Hello, MCP!"
}
},
"id": 3
}
const response = await fetch("http://localhost:8080/mcp", {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': '',
},
body: JSON.stringify(item),
});
if (!response.ok) {
const text = await response.text();
console.log(text);
throw new Error('Failed to create item');
}else{
const json = await response.json();
console.log(json);
console.log(json.result.content[0].text);
}
}catch(e){console.log(e)}
}
start();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment