# Cortex

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

- **Type:** MCP server
- **Install:** `agentstack add mcp-freepeak-cortex`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [FreePeak](https://agentstack.voostack.com/s/freepeak)
- **Installs:** 0
- **Category:** [Integrations](https://agentstack.voostack.com/c/integrations)
- **Latest version:** 0.1.0
- **License:** Apache-2.0
- **Upstream author:** [FreePeak](https://github.com/FreePeak)
- **Source:** https://github.com/FreePeak/cortex

## Install

```sh
agentstack add mcp-freepeak-cortex
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## 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](https://spec.modelcontextprotocol.io/latest)

## Installation

```bash
go get github.com/FreePeak/cortex
```

## Quickstart

Let's create a simple MCP server that exposes an echo tool:

```go
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)](https://modelcontextprotocol.io) 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:

```go
// 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:

```go
// 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:

```go
// 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:

```go
// 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:

```go
// 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:

```go
// 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:

```go
// 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:

```go
// 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:

```go
// 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.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-freepeak-cortex
- Seller: https://agentstack.voostack.com/s/freepeak
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
