2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

MCP Go SDKでHTTP経由のMCPサーバーを構築する方法

2
Last updated at Posted at 2025-12-02

本記事は サムザップ Advent Calendar 2025 3日目の記事です。

自己紹介

はじめまして。

サムザップの新規プロジェクトでバックエンドエンジニアをしている朝倉です。

プロジェクトでは、サムザップとしては初めてGoとGCP(Google Cloud Platform)を採用しています。新しい技術スタックに挑戦しながら、開発効率を向上させるための仕組みづくりにも取り組んでいます。

管理ツールのMCPサーバー化

ゲームプロジェクトの開発・運用において、管理ツールは重要な役割を果たしています。ゲームの管理ツールでは、ユーザー情報の確認、マスターデータの更新、お知らせの配信など、ゲーム運営に必要な様々な機能を提供します。

従来、これらの操作は管理画面のUIから手動で行う必要がありましたが、AIコーディングエージェント(Claude CodeやCursorなど)と連携して管理ツールを操作できるようになれば、開発や運用が楽になるのではないかと考えています。

そこで、Model Context Protocol (MCP) を使用して管理ツールをMCPサーバー化し、AIコーディングエージェントから直接操作できるか検証しています。

Model Context Protocol (MCP) とは

Model Context Protocol (MCP) は、AIコーディングエージェントとローカルツールやサービスを接続するために設計された標準プロトコルです。

MCPサーバーを利用することで、AIコーディングエージェントから既存のシステムやAPIを呼び出すことができ、より高度なオペレーションが可能になります。

この記事では、MCPの公式 Go SDK modelcontextprotocol/go-sdk を使用して、MCPサーバーの実装方法を紹介します。

MCPサーバーの基本構築

まず、MCPサーバーを作成する基本的な方法を紹介します。

mcp.NewServer によるサーバー作成

MCPサーバーは mcp.NewServer 関数を使用して作成します。

package main

import (
	"github.com/modelcontextprotocol/go-sdk/mcp"
)

func main() {
	// MCPサーバーを作成
	mcpServer := mcp.NewServer(
		&mcp.Implementation{
			Name:    "Calculation MCP Server",
			Version: "1.0.0",
		},
		&mcp.ServerOptions{},
	)

	// サーバーの使用...
}

mcp.NewServer 関数は、mcp.Implementationmcp.ServerOptions の2つの引数を受け取ります。

mcp.Implementation には、サーバーの名前とバージョンを指定します。これは、MCPクライアントがMCPサーバーを識別するために使用されます。

mcp.ServerOptions では、サーバーの動作をカスタマイズできます。デフォルトのオプションを使用する場合は、空の構造体を渡します。多くの場合デフォルトオプションで十分です。

ツールの追加

MCPサーバーにツール(機能)を追加するには、mcp.AddTool 関数を使用します。

package main

import (
	"context"

	"github.com/modelcontextprotocol/go-sdk/mcp"
)

func handleSquare(
	ctx context.Context,
	request *mcp.CallToolRequest,
	in *Input,
) (*mcp.CallToolResult, *Output, error) {
	// 通常は第一戻り値をnil、第二戻り値に結果、第三戻り値にエラーを返します
	// 追加のメタ情報を返したい場合などには第一戻り値を使います
	return nil, &Output{
		Answer: in.Value * in.Value,
	}, nil
}

type Input struct {
	Value int `json:"value" jsonschema:"Number to square"`
}

type Output struct {
	Answer int `json:"answer" jsonschema:"Result of squaring"`
}

func main() {
	// MCPサーバーを作成
	mcpServer := mcp.NewServer(
		&mcp.Implementation{
			Name:    "Calculation MCP Server",
			Version: "1.0.0",
		},
		&mcp.ServerOptions{},
	)

	// ツールを追加
	mcp.AddTool(mcpServer, &mcp.Tool{
		Name:        "Square",
		Description: "Returns the square of the given number",
	}, handleSquare)
}

数値の平方を計算するツール Square を追加しています。

ツールハンドラー handleSquare は、context.Context*mcp.CallToolRequest、入力型 *Input を受け取り、*mcp.CallToolResult、出力型 *Outputerror を返します。通常は第一戻り値を nil にし、第二戻り値に実行結果、第三戻り値にエラーを返します。追加のメタ情報を返したい場合などには第一戻り値を使用します。

入力と出力の型は、json タグと jsonschema タグを使用して定義します。これにより、MCPクライアントがツールの引数と戻り値の構造を理解できます。

mcp.AddTool 関数を使用して、ツール名、説明、ハンドラー関数を指定してツールを登録します。登録されたツールは、AIコーディングエージェントから呼び出すことができるようになります。

標準入出力(stdio)での公開

MCPサーバーを最もシンプルに動作させるには、標準入出力(stdio)を使用する方法があります。これは、MCPクライアントがサーバープロセスを起動し、標準入出力を通じて通信する方式です。

package main

import (
	"context"
	"log"

	"github.com/modelcontextprotocol/go-sdk/mcp"
)

func handleSquare(
	ctx context.Context,
	request *mcp.CallToolRequest,
	in *Input,
) (*mcp.CallToolResult, *Output, error) {
	return nil, &Output{
		Answer: in.Value * in.Value,
	}, nil
}

type Input struct {
	Value int `json:"value" jsonschema:"Number to square"`
}

type Output struct {
	Answer int `json:"answer" jsonschema:"Result of squaring"`
}

func main() {
	// MCPサーバーを作成
	mcpServer := mcp.NewServer(
		&mcp.Implementation{
			Name:    "Calculation MCP Server",
			Version: "1.0.0",
		},
		&mcp.ServerOptions{},
	)

	// ツールを追加
	mcp.AddTool(mcpServer, &mcp.Tool{
		Name:        "Square",
		Description: "Returns the square of the given number",
	}, handleSquare)

	// 標準入出力を使用してサーバーを起動
	if err := mcpServer.Run(context.Background(), &mcp.StdioTransport{}); err != nil {
		log.Fatal(err)
	}
}

mcpServer.Run メソッドは、標準入出力(stdio)を使用してMCPサーバーを起動します。第一引数には context.Context を、第二引数には &mcp.StdioTransport{} を渡します。

この方式は、MCPクライアント(Claude CodeやCursorなど)がサーバープロセスを直接起動する場合に使用されます。クライアントは、サーバーの標準入力にリクエストを送信し、標準出力からレスポンスを受け取ります。

この方式のメリットは、実装がシンプルでHTTPサーバーの設定が不要なため、ローカル環境での開発に適しています。一方で、リモートからアクセスできない、複数のクライアントからの同時接続が難しいといったデメリットがあります。そのため、複数のクライアントからのアクセスが必要な場合は、HTTP経由での公開がおすすめします。

HTTP経由での公開

標準入出力(stdio)の実装はシンプルですが、HTTP経由で公開することで、リモートからのアクセスや、複数のクライアントからの同時接続ができるようになります。

管理ツールは既存のHTTPサーバーで動作しています。MCPサーバーをHTTP経由で公開することで、管理ツールと同じサーバー上でMCPエンドポイントを提供できます。

NewStreamableHTTPHandler への置き換え

標準入出力(stdio)での実装から、HTTP経由の実装に置き換えるには、mcp.NewStreamableHTTPHandler を使用します。サーバーの作成部分やツールの追加方法は同じで、通信方式だけが変更になります。

package main

import (
	"context"
	"log"
	"net/http"

	"github.com/modelcontextprotocol/go-sdk/mcp"
)

func handleSquare(
	ctx context.Context,
	request *mcp.CallToolRequest,
	in *Input,
) (*mcp.CallToolResult, *Output, error) {
	return nil, &Output{
		Answer: in.Value * in.Value,
	}, nil
}

type Input struct {
	Value int `json:"value" jsonschema:"Number to square"`
}

type Output struct {
	Answer int `json:"answer" jsonschema:"Result of squaring"`
}

func main() {
	// MCPサーバーを作成
	mcpServer := mcp.NewServer(
		&mcp.Implementation{
			Name:    "Calculation MCP Server",
			Version: "1.0.0",
		},
		&mcp.ServerOptions{},
	)

	// ツールを追加
	mcp.AddTool(mcpServer, &mcp.Tool{
		Name:        "Square",
		Description: "Returns the square of the given number",
	}, handleSquare)

	// StreamableHTTPHandlerを作成
	mcpHttpServer := mcp.NewStreamableHTTPHandler(func(req *http.Request) *mcp.Server {
		return mcpServer
	}, &mcp.StreamableHTTPOptions{Stateless: true})

	serverMux := http.NewServeMux()
	serverMux.Handle("/mcp", mcpHttpServer)

	server := &http.Server{
		Addr:    ":8080",
		Handler: serverMux,
	}

	if err := server.ListenAndServe(); err != nil {
		log.Fatal(err)
	}
}

標準入出力(stdio)との主な違いは、mcpServer.Runの代わりに、mcp.NewStreamableHTTPHandlerを使用してHTTPハンドラーを作成し、HTTPルーターに登録する点です。サーバーの作成部分やツールの追加方法は同じです。

mcp.NewStreamableHTTPHandler 関数は、MCPサーバーをHTTPハンドラーとしてラップします。第一引数には、リクエストごとにMCPサーバーを返す関数を渡します。第二引数には、mcp.StreamableHTTPOptions を指定して、サーバーの動作をカスタマイズできます。

作成されたHTTPハンドラーは、任意のパス(この例では /mcp)でhttp.ServeMux に登録し、HTTPサーバーとして起動します。

mcp.StreamableHTTPOptions には以下のオプションが設定できます:

  • Stateless: true に設定すると、MCPサーバーがステートレスで動作します。各リクエストが独立して処理され、複数のサーバーインスタンスでリクエストを分散させることができるようになります。

  • JSONResponse: true に設定すると、レスポンスがJSON形式で返されます。デフォルトでは、Server-Sent Events(SSE)形式でレスポンスが返されます。SSE形式は、ストリーミングレスポンスに対応しており、リアルタイムでデータを送信できます。一方、JSON形式は単一のレスポンスを返すため、シンプルなリクエスト・レスポンスパターンに適しています。

MCPサーバーの動作確認

MCPサーバーを実装したら、実際に起動してAIコーディングエージェントから利用します。

サーバーの起動

HTTP経由で公開したMCPサーバーを起動するには、通常のGoアプリケーションと同様に実行します。

go run main.go

または、ビルドしてから実行します。

go build -o mcp-server main.go
./mcp-server

サーバーが起動すると、http://localhost:8080/mcp でMCPエンドポイントが利用可能になります。

Cursorでの設定方法

CursorでHTTP経由のMCPサーバーを利用するには、プロジェクトルートに .cursor/mcp.json ファイルを作成し、以下のように設定します。

{
  "mcpServers": {
    "calculation-mcp-server": {
      "url": "http://localhost:8080/mcp"
    }
  }
}

Claude Codeでの設定方法

Claude CodeでHTTP経由のMCPサーバーを利用するには、プロジェクトルートに .mcp.json ファイルを作成し、以下のように設定します。

{
  "mcpServers": {
    "calculation-mcp-server": {
      "url": "http://localhost:8080/mcp"
    }
  }
}

動作確認

実際にツールを実行して動作を確認します。

Squareツールを使って、5の平方を計算してください

AIコーディングエージェントが自動的にツールを呼び出し、結果を返してくれます。

まとめ

MCP Go SDKを使用してHTTP経由でMCPサーバーを公開する方法を紹介しました。

  • mcp.NewServer でMCPサーバーを作成
  • mcp.AddTool でツールを追加
  • 標準入出力(stdio)で公開
  • mcp.NewStreamableHTTPHandler に置き換えてHTTP経由で公開

MCP Go SDKを利用することで簡単にMCPサーバーが構築でき、AIコーディングエージェントと既存のシステムを連携しやすくなります。

本記事が、MCPサーバーを構築する際の参考になれば幸いです。

明日は、 @ishisaka_takumi さんの記事になります。お楽しみに!!

参考リンク

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?