AgentStack
MCP verified Apache-2.0 Self-run

Cortex

mcp-freepeak-cortex · by FreePeak

A declarative platform for building Model Context Protocol (MCP) servers in Golang—exposing tools, resources & prompts in a clean, structured way

No reviews yet
0 installs
17 views
0.0% view→install

Install

$ agentstack add mcp-freepeak-cortex

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Cortex? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Cortex

Build MCP Servers Declaratively in Golang

Table of Contents

  • [Overview](#overview)
  • [Installation](#installation)
  • [Quickstart](#quickstart)
  • [What is MCP?](#what-is-mcp)
  • [Core Concepts](#core-concepts)
  • [Server](#server)
  • [Tools](#tools)
  • [Providers](#providers)
  • [Resources](#resources)
  • [Prompts](#prompts)
  • [Running Your Server](#running-your-server)
  • [STDIO](#stdio)
  • [HTTP with SSE](#http-with-sse)
  • [Multi-Protocol](#multi-protocol)
  • [Testing and Debugging](#testing-and-debugging)
  • [Embedding Cortex](#embedding-cortex)
  • [HTTP Server Integration](#http-server-integration)
  • [PocketBase Integration](#pocketbase-integration)
  • [Examples](#examples)
  • [Basic Examples](#basic-examples)
  • [Advanced Examples](#advanced-examples)
  • [Plugin System](#plugin-system)
  • [Package Structure](#package-structure)
  • [Contributing](#contributing)
  • [License](#license)
  • [Support & Contact](#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
  • Embed Cortex into existing servers and applications

> 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)

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [FreePeak](https://github.com/FreePeak)
- **Source:** [FreePeak/cortex](https://github.com/FreePeak/cortex)
- **License:** Apache-2.0

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.