I craft unique cereal names, stories, and ridiculously cute Cereal Baby images.

cortex
A declarative platform for building Model Context Protocol (MCP) servers in Golang—exposing tools, resources & prompts in a clean, structured way
3 years
Works with Finder
1
Github Watches
1
Github Forks
10
Github Stars
Cortex
Build MCP Servers Declaratively in Golang
Table of Contents
- Overview
- Installation
- Quickstart
- What is MCP?
- Core Concepts
- Running Your Server
- Examples
- Package Structure
- Contributing
- License
- Support & Contact
Overview
The Model Context Protocol allows applications to provide context for LLMs in a standardized way, separating the concerns of providing context from the actual LLM interaction. Cortex implements the full MCP specification, making it easy to:
- Build MCP servers that expose resources and tools
- Use standard transports like stdio and Server-Sent Events (SSE)
- Handle all MCP protocol messages and lifecycle events
- Follow Go best practices and clean architecture principles
Note: Cortex is always updated to align with the latest MCP specification from spec.modelcontextprotocol.io/latest
Installation
go get github.com/FreePeak/cortex
Quickstart
Let's create a simple MCP server that exposes an echo tool:
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
}
What is MCP?
The Model Context Protocol (MCP) is a standardized protocol that allows applications to provide context for LLMs in a secure and efficient manner. It separates the concerns of providing context and tools from the actual LLM interaction. MCP servers can:
- Expose data through Resources (read-only data endpoints)
- Provide functionality through Tools (executable functions)
- Define interaction patterns through Prompts (reusable templates)
- Support various transport methods (stdio, HTTP/SSE)
Core Concepts
Server
The MCP Server is your core interface to the MCP protocol. It handles connection management, protocol compliance, and message routing:
// Create a new MCP server with logger
mcpServer := server.NewMCPServer("My App", "1.0.0", logger)
Tools
Tools let LLMs take actions through your server. Unlike resources, tools are expected to perform computation and have side effects:
// 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)
Providers
Providers allow you to group related tools and resources into a single package that can be easily registered with a server:
// 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)
}
Resources
Resources are how you expose data to LLMs. They're similar to GET endpoints in a REST API - they provide data but shouldn't perform significant computation or have side effects:
// 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",
}
Prompts
Prompts are reusable templates that help LLMs interact with your server effectively:
// 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
Running Your Server
MCP servers in Go can be connected to different transports depending on your use case:
STDIO
For command-line tools and direct integrations:
// Start a stdio server
if err := mcpServer.ServeStdio(); err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
IMPORTANT: When using STDIO, all logs must be directed to stderr to maintain the clean JSON-RPC protocol on stdout:
// 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")
HTTP with SSE
For web applications, you can use Server-Sent Events (SSE) for real-time communication:
// 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)
}
Multi-Protocol
You can also run multiple protocol servers simultaneously by using goroutines:
// 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
Testing and Debugging
For testing and debugging, the Cortex framework provides several utilities:
// You can use the test-call.sh script to send test requests to your STDIO server
// For example:
// ./test-call.sh echo '{"message":"Hello, World!"}'
Examples
Basic Examples
The repository includes several basic examples in the examples
directory:
-
STDIO Server: A simple MCP server that communicates via STDIO (
examples/stdio-server
) -
SSE Server: A server that uses HTTP with Server-Sent Events for communication (
examples/sse-server
) -
Multi-Protocol: A server that can run on multiple protocols simultaneously (
examples/multi-protocol
)
Advanced Examples
The examples directory also includes more advanced use cases:
-
Providers: Examples of how to create and use providers to organize related tools (
examples/providers
)- Weather Provider: Demonstrates how to create a provider for weather-related tools
- Database Provider: Shows how to create a provider for database operations
Plugin System
Cortex includes a plugin system for extending server capabilities:
// 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
}
Package Structure
The Cortex codebase is organized into several packages:
-
pkg/server
: Core server implementation -
pkg/tools
: Tool creation and management -
pkg/plugin
: Plugin system for extending server capabilities -
pkg/types
: Common types and interfaces -
pkg/builder
: Builders for creating complex objects
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
License
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
Support & Contact
- For questions or issues, email mnhatlinh.doan@gmail.com
- Open an issue directly: Issue Tracker
- If Cortex helps your work, please consider supporting:
相关推荐
Confidential guide on numerology and astrology, based of GG33 Public information
Converts Figma frames into front-end code for various mobile frameworks.
Advanced software engineer GPT that excels through nailing the basics.
Take an adjectivised noun, and create images making it progressively more adjective!
Siri Shortcut Finder – your go-to place for discovering amazing Siri Shortcuts with ease
Discover the most comprehensive and up-to-date collection of MCP servers in the market. This repository serves as a centralized hub, offering an extensive catalog of open-source and proprietary MCP servers, complete with features, documentation links, and contributors.
Micropython I2C-based manipulation of the MCP series GPIO expander, derived from Adafruit_MCP230xx
Mirror ofhttps://github.com/agentience/practices_mcp_server
Mirror ofhttps://github.com/bitrefill/bitrefill-mcp-server
An AI chat bot for small and medium-sized teams, supporting models such as Deepseek, Open AI, Claude, and Gemini. 专为中小团队设计的 AI 聊天应用,支持 Deepseek、Open AI、Claude、Gemini 等模型。
Bridge between Ollama and MCP servers, enabling local LLMs to use Model Context Protocol tools
Reviews

user_v4L8elY7
Cortex by FreePeak is an incredible tool that has significantly improved my workflow. Its intuitive design and robust features make it a must-have for anyone looking to streamline their processes. The clear documentation and support make it accessible even for beginners. Highly recommend checking it out on GitHub!