mcpField
C
Cortex

Cortex

ローカル
github.com/FreePeak開発ツール2776 週間前に更新

Cortex について

Cortex は、ツール、リソース、プロンプトを構造化して公開する MCP サーバーを Golang で宣言的に構築するためのフレームワークです。Go 開発者を対象とし、既存の HTTP サーバーやアプリケーションに組み込むこともできます。

主な機能

  1. 01MCP サーバーの宣言的な定義
  2. 02ツール、リソース、プロンプトのサポート
  3. 03stdio と HTTP/SSE のトランスポート
  4. 04既存の HTTP サーバーや PocketBase への組み込み
  5. 05サーバー機能を拡張するプラグインシステム

活用シーン

  1. 01Go による MCP サーバーの構築
  2. 02既存の Go Web アプリケーションへの MCP 機能の追加
  3. 03関連するツールとリソースのプロバイダーへのまとめ

MCP 対応

Cortex は MCP 仕様を実装しており、開発者はこれを使ってツール、リソース、プロンプトを MCP クライアントに提供する MCP サーバーを構築します。

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

インストール方法は未掲載です

このサーバーのパッケージやリモートエンドポイントはまだ取得できていません。プロジェクトの README の手順に従ってください。

リポジトリ

ツール

ツール一覧はまだ取得されていません

ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。

詳細

main logo
Cortex

Golang で MCP サーバーを宣言的に構築する

Go Reference Go Report Card Go Workflow License: Apache 2.0 Contributors

目次

概要

Model Context Protocol は、アプリケーションが LLM にコンテキストを標準化された方法で提供できるようにし、コンテキストを提供する責務を実際の LLM とのやり取りから分離します。Cortex は MCP 仕様を完全に実装しており、次のことを簡単に行えます。

  • リソースとツールを公開する MCP サーバーを構築する
  • stdio や Server-Sent Events(SSE)などの標準的なトランスポートを使用する
  • すべての MCP プロトコルメッセージとライフサイクルイベントを処理する
  • Go のベストプラクティスとクリーンアーキテクチャの原則に従う
  • Cortex を既存のサーバーやアプリケーションに組み込む

Note: Cortex は常に spec.modelcontextprotocol.io/latest の最新の MCP 仕様に合わせて更新されています。

インストール

go get github.com/FreePeak/cortex

クイックスタート

echo ツールを公開するシンプルな MCP サーバーを作成してみましょう。

package main

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/FreePeak/cortex/pkg/server"
	"github.com/FreePeak/cortex/pkg/tools"
)

func main() {
	// Create a logger that writes to stderr instead of stdout
	// This is critical for STDIO servers as stdout must only contain JSON-RPC messages
	logger := log.New(os.Stderr, "[cortex] ", log.LstdFlags)

	// Create the server
	mcpServer := server.NewMCPServer("Echo Server Example", "1.0.0", logger)

	// Create an echo tool
	echoTool := tools.NewTool("echo",
		tools.WithDescription("Echoes back the input message"),
		tools.WithString("message",
			tools.Description("The message to echo back"),
			tools.Required(),
		),
	)

	// Example of a tool with array parameter
	arrayExampleTool := tools.NewTool("array_example",
		tools.WithDescription("Example tool with array parameter"),
		tools.WithArray("values",
			tools.Description("Array of string values"),
			tools.Required(),
			tools.Items(map[string]interface{}{
				"type": "string",
			}),
		),
	)

	// Add the tools to the server with handlers
	ctx := context.Background()
	err := mcpServer.AddTool(ctx, echoTool, handleEcho)
	if err != nil {
		logger.Fatalf("Error adding tool: %v", err)
	}

	err = mcpServer.AddTool(ctx, arrayExampleTool, handleArrayExample)
	if err != nil {
		logger.Fatalf("Error adding array example tool: %v", err)
	}

	// Write server status to stderr instead of stdout to maintain clean JSON protocol
	fmt.Fprintf(os.Stderr, "Starting Echo Server...\n")
	fmt.Fprintf(os.Stderr, "Send JSON-RPC messages via stdin to interact with the server.\n")
	fmt.Fprintf(os.Stderr, `Try: {"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"echo","parameters":{"message":"Hello, World!"}}}\n`)

	// Serve over stdio
	if err := mcpServer.ServeStdio(); err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}
}

// Echo tool handler
func handleEcho(ctx context.Context, request server.ToolCallRequest) (interface{}, error) {
	// Extract the message parameter
	message, ok := request.Parameters["message"].(string)
	if !ok {
		return nil, fmt.Errorf("missing or invalid 'message' parameter")
	}

	// Return the echo response in the format expected by the MCP protocol
	return map[string]interface{}{
		"content": []map[string]interface{}{
			{
				"type": "text",
				"text": message,
			},
		},
	}, nil
}

// Array example tool handler
func handleArrayExample(ctx context.Context, request server.ToolCallRequest) (interface{}, error) {
	// Extract the values parameter
	values, ok := request.Parameters["values"].([]interface{})
	if !ok {
		return nil, fmt.Errorf("missing or invalid 'values' parameter")
	}

	// Convert values to string array
	stringValues := make([]string, len(values))
	for i, v := range values {
		stringValues[i] = v.(string)
	}

	// Return the array response in the format expected by the MCP protocol
	return map[string]interface{}{
		"content": stringValues,
	}, nil
}

MCP とは?

Model Context Protocol(MCP) は、アプリケーションが安全かつ効率的な方法で LLM にコンテキストを提供できるようにする標準化されたプロトコルです。コンテキストやツールを提供する責務を、実際の LLM とのやり取りから分離します。MCP サーバーは次のことができます。

  • リソース(読み取り専用のデータエンドポイント)を通じてデータを公開する
  • ツール(実行可能な関数)を通じて機能を提供する
  • プロンプト(再利用可能なテンプレート)を通じてインタラクションパターンを定義する
  • さまざまなトランスポート方式(stdio、HTTP/SSE)をサポートする

基本概念

サーバー

MCP サーバーは、MCP プロトコルへの中心的なインターフェースです。接続管理、プロトコル準拠、メッセージルーティングを処理します。

// Create a new MCP server with logger
mcpServer := server.NewMCPServer("My App", "1.0.0", logger)
ツール

ツールを使用すると、LLM はサーバーを通じてアクションを実行できます。リソースとは異なり、ツールは計算を実行し、副作用を持つことが想定されています。

// Define a calculator tool
calculatorTool := tools.NewTool("calculator",
    tools.WithDescription("Performs basic math operations"),
    tools.WithString("operation",
        tools.Description("The operation to perform (add, subtract, multiply, divide)"),
        tools.Required(),
    ),
    tools.WithNumber("a", 
        tools.Description("First operand"),
        tools.Required(),
    ),
    tools.WithNumber("b", 
        tools.Description("Second operand"),
        tools.Required(),
    ),
)

// Add the tool to the server with a handler
mcpServer.AddTool(ctx, calculatorTool, handleCalculator)
プロバイダー

プロバイダーを使用すると、関連するツールとリソースを 1 つのパッケージにグループ化し、サーバーに簡単に登録できます。

// Create a weather provider
weatherProvider, err := weather.NewWeatherProvider(logger)
if err != nil {
    logger.Fatalf("Failed to create weather provider: %v", err)
}

// Register the provider with the server
err = mcpServer.RegisterProvider(ctx, weatherProvider)
if err != nil {
    logger.Fatalf("Failed to register weather provider: %v", err)
}
リソース

リソースは、LLM にデータを公開するための手段です。REST API の GET エンドポイントに似ており、データを提供しますが、重要な計算を実行したり副作用を持ったりするべきではありません。

// Create a resource (Currently using the internal API)
resource := &domain.Resource{
    URI:         "sample://hello-world",
    Name:        "Hello World Resource",
    Description: "A sample resource for demonstration purposes",
    MIMEType:    "text/plain",
}
プロンプト

プロンプトは、LLM がサーバーと効果的にやり取りするための再利用可能なテンプレートです:

// Create a prompt (Currently using the internal API)
codeReviewPrompt := &domain.Prompt{
    Name:        "review-code",
    Description: "A prompt for code review",
    Template:    "Please review this code:\n\n{{.code}}",
    Parameters: []domain.PromptParameter{
        {
            Name:        "code",
            Description: "The code to review",
            Type:        "string",
            Required:    true,
        },
    },
}

// Note: Prompt support is being updated in the public API

サーバーの実行

Go の MCP サーバーは、ユースケースに応じてさまざまなトランスポートに接続できます:

STDIO

コマンドラインツールや直接的な統合に適しています:

// Start a stdio server
if err := mcpServer.ServeStdio(); err != nil {
    fmt.Fprintf(os.Stderr, "Error: %v\n", err)
    os.Exit(1)
}

IMPORTANT: STDIO を使用する場合、stdout 上のクリーンな JSON-RPC プロトコルを維持するために、すべてのログは stderr に出力する必要があります:

// Create a logger that writes to stderr
logger := log.New(os.Stderr, "[cortex] ", log.LstdFlags)

// All debug/status messages should use stderr
fmt.Fprintf(os.Stderr, "Server starting...\n")
SSE を使用した HTTP

Web アプリケーションでは、リアルタイム通信のために Server-Sent Events(SSE)を使用できます:

// Configure the HTTP address
mcpServer.SetAddress(":8080")

// Start an HTTP server with SSE support
if err := mcpServer.ServeHTTP(); err != nil {
    log.Fatalf("HTTP server error: %v", err)
}

// For graceful shutdown
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := mcpServer.Shutdown(ctx); err != nil {
    log.Fatalf("Server shutdown error: %v", err)
}
マルチプロトコル

goroutine を使用して、複数のプロトコルサーバーを同時に実行することもできます:

// Start an HTTP server
go func() {
    if err := mcpServer.ServeHTTP(); err != nil {
        log.Fatalf("HTTP server error: %v", err)
    }
}()

// Start a STDIO server
go func() {
    if err := mcpServer.ServeStdio(); err != nil {
        log.Fatalf("STDIO server error: %v", err)
    }
}()

// Wait for shutdown signal
stop := make(chan os.Signal, 1)
signal.Notify(stop, os.Interrupt, syscall.SIGTERM)
<-stop
テストとデバッグ

Cortex サーバーのテストとデバッグの詳細については、テストガイドを参照してください。

Cortex の埋め込み

Cortex は、別途サーバーを実行することなく、既存のアプリケーションに埋め込んで MCP 機能を追加できます。これは、既存の Web フレームワークや PocketBase のようなアプリケーションとの統合に役立ちます。

HTTP サーバーとの統合

Cortex は、任意の Go HTTP サーバーと簡単に統合できます:

package main

import (
	"log"
	"net/http"
	"os"

	"github.com/FreePeak/cortex/pkg/server"
	"github.com/FreePeak/cortex/pkg/tools"
)

func main() {
	// Create a logger
	logger := log.New(os.Stderr, "[cortex] ", log.LstdFlags)

	// Create an MCP server
	mcpServer := server.NewMCPServer("Embedded MCP Server", "1.0.0", logger)

	// Add some tools
	echoTool := tools.NewTool("echo",
		tools.WithDescription("Echoes back the input message"),
		tools.WithString("message",
			tools.Description("The message to echo back"),
			tools.Required(),
		),
	)

	// Add the tool to the server
	mcpServer.AddTool(context.Background(), echoTool, func(ctx context.Context, request server.ToolCallRequest) (interface{}, error) {
		message := request.Parameters["message"].(string)
		return map[string]interface{}{
			"content": []map[string]interface{}{
				{
					"type": "text",
					"text": message,
				},
			},
		}, nil
	})

	// Create an HTTP adapter for the MCP server
	adapter := server.NewHTTPAdapter(mcpServer, server.WithPath("/api/mcp"))

	// Use the adapter in your HTTP server
	http.Handle("/api/mcp/", adapter.Handler())
	
	// Add your other routes
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("Hello from the main server!"))
	})

	// Start the server
	logger.Println("Starting server on :8080")
	http.ListenAndServe(":8080", nil)
}
PocketBase との統合

Cortex は、データベース、認証、管理 UI を備えたオープンソースのバックエンドである PocketBase と統合できます:

package main

import (
	"log"

	"github.com/pocketbase/pocketbase"
	"github.com/pocketbase/pocketbase/core"
	
	"github.com/FreePeak/cortex/pkg/integration/pocketbase"
	"github.com/FreePeak/cortex/pkg/tools"
)

func main() {
	// Create a new PocketBase app
	app := pocketbase.New()

	// Initialize Cortex plugin
	plugin := pocketbase.NewCortexPlugin(
		pocketbase.WithName("PocketBase MCP Server"),
		pocketbase.WithVersion("1.0.0"),
		pocketbase.WithBasePath("/api/mcp"),
	)

	// Add tools to the plugin
	echoTool := tools.NewTool("echo",
		tools.WithDescription("Echoes back the input message"),
		tools.WithString("message",
			tools.Description("The message to echo back"),
			tools.Required(),
		),
	)

	// Add the tool with a handler
	plugin.AddTool(echoTool, func(ctx context.Context, request pocketbase.ToolCallRequest) (interface{}, error) {
		message := request.Parameters["message"].(string)
		return map[string]interface{}{
			"content": []map[string]interface{}{
				{
					"type": "text",
					"text": message,
				},
			},
		}, nil
	})

	// Register the plugin with PocketBase
	app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
		// Register the plugin
		return plugin.RegisterWithPocketBase(app)
	})

	// Start the PocketBase app
	if err := app.Start(); err != nil {
		log.Fatal(err)
	}
}

Cortex の埋め込みに関するより詳細なドキュメントについては、埋め込みガイドを参照してください。

例

基本的な例

リポジトリには、examples ディレクトリにいくつかの基本的な例が含まれています:

  • STDIO サーバー: STDIO を介して通信するシンプルな MCP サーバー(examples/stdio-server)
  • SSE サーバー: 通信に Server-Sent Events を使用した HTTP を使用するサーバー(examples/sse-server)
  • マルチプロトコル: 複数のプロトコルで同時に実行できるサーバー(examples/multi-protocol)
高度な例

examples ディレクトリには、より高度なユースケースも含まれています:

  • プロバイダー: 関連するツールを整理するためのプロバイダーを作成および使用する方法の例(examples/providers)
    • 天気プロバイダー: 天気関連のツール用のプロバイダーを作成する方法を示します
    • データベースプロバイダー: データベース操作のためのプロバイダーを作成する方法を示します
プラグインシステム

Cortex には、サーバー機能を拡張するためのプラグインシステムが含まれています:

// Create a new provider based on the BaseProvider
type MyProvider struct {
    *plugin.BaseProvider
}

// Create a new provider instance
func NewMyProvider(logger *log.Logger) (*MyProvider, error) {
    info := plugin.ProviderInfo{
        ID:          "my-provider",
        Name:        "My Provider",
        Version:     "1.0.0",
        Description: "A custom provider for my tools",
        Author:      "Your Name",
        URL:         "https://github.com/yourusername/myrepo",
    }
    
    baseProvider := plugin.NewBaseProvider(info, logger)
    provider := &MyProvider{
        BaseProvider: baseProvider,
    }
    
    // Register tools with the provider
    // ...
    
    return provider, nil
}

パッケージ構造

Cortex のコードベースは、いくつかのパッケージに整理されています:

  • pkg/server: コアサーバーの実装
  • pkg/tools: ツールの作成と管理
  • pkg/plugin: サーバー機能を拡張するためのプラグインシステム
  • pkg/types: 共通の型とインターフェース
  • pkg/builder: 複雑なオブジェクトを作成するためのビルダー

コントリビューション

コントリビューションを歓迎します!お気軽に Pull Request を送信してください。

  1. リポジトリをフォークする
  2. 機能ブランチを作成する(git checkout -b feature/amazing-feature)
  3. 変更をコミットする(git commit -m 'Add some amazing feature')
  4. ブランチにプッシュする(git push origin feature/amazing-feature)
  5. Pull Request を開く

ライセンス

このプロジェクトは Apache License 2.0 の下でライセンスされています - 詳細については LICENSE ファイルを参照してください。

サポートと連絡先

  • 質問や問題がある場合は、[email protected] までメールでお問い合わせください
  • 直接 Issue を開く: Issue Tracker
  • Cortex があなたの仕事に役立つ場合は、サポートをご検討ください:

Buy Me A Coffee

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。