Skip to content

dennisonbertram/mcp-lua

Repository files navigation

Lua Model Context Protocol (MCP) Implementation

A complete Lua implementation of the Model Context Protocol specification, enabling seamless integration between Large Language Models (LLMs) and external systems through a standardized communication protocol.

Overview

The Model Context Protocol (MCP) is an open protocol that standardizes how applications provide context to LLMs. This Lua implementation provides a fully-featured MCP SDK that allows developers to build both MCP clients and servers in Lua, enabling:

  • Tools: Expose functions that LLMs can invoke
  • Resources: Share data and content with LLMs
  • Prompts: Provide reusable prompt templates
  • Standardized Communication: JSON-RPC 2.0 over stdio transport

Features

Core Protocol Support

  • ✅ Full JSON-RPC 2.0 implementation
  • ✅ stdio transport (standard input/output communication)
  • ✅ SSE (Server-Sent Events) transport
  • ✅ Protocol lifecycle management (initialize, shutdown)
  • ✅ Error handling with standard JSON-RPC error codes

MCP Capabilities

  • Tools: Define and execute functions with JSON Schema validation
  • Resources: Expose data with URI-based access and MIME types
  • Prompts: Create reusable prompt templates with arguments
  • Logging: Structured logging support
  • Completion: Auto-completion support for arguments
  • Sampling: LLM sampling configuration

Advanced Features

  • Security Layer: Rate limiting, access control, input validation
  • Async Operations: Promise-based async/await pattern
  • Event System: Event emitter for lifecycle hooks
  • Schema Validation: JSON Schema support for input/output validation
  • Error Tracking: Comprehensive error handling and recovery

Quick Start

Installation

# Clone the repository
git clone https://github.com/yourusername/lua-mcp.git
cd lua-mcp

# Run tests to verify installation
lua tests/run_all_tests.lua

Basic Server Example

#!/usr/bin/env lua

-- Add the library to path
package.path = package.path .. ";./lua-mcp/src/?.lua"

local json = require("mcp.foundation.json")
local json_rpc = require("mcp.protocol.json_rpc")
local StdioTransport = require("mcp.transport.stdio")

-- Create a simple MCP server
local server = {}

function server:new()
    local self = setmetatable({}, {__index = server})
    
    -- Initialize transport
    self.transport = StdioTransport:new()
    self.transport:connect()
    
    -- Define available tools
    self.tools = {
        {
            name = "calculate",
            description = "Perform basic calculations",
            inputSchema = {
                type = "object",
                properties = {
                    operation = { type = "string", enum = {"add", "subtract", "multiply", "divide"} },
                    a = { type = "number" },
                    b = { type = "number" }
                },
                required = {"operation", "a", "b"}
            }
        }
    }
    
    return self
end

function server:handle_message(message)
    local method = json_rpc.get_method(message)
    local params = json_rpc.get_params(message) or {}
    local id = json_rpc.get_id(message)
    
    if method == "initialize" then
        return json_rpc.create_response({
            protocolVersion = "2024-11-05",
            capabilities = {
                tools = { listSupported = true, callSupported = true }
            },
            serverInfo = { name = "my-server", version = "1.0.0" }
        }, id)
    elseif method == "tools/list" then
        return json_rpc.create_response({ tools = self.tools }, id)
    elseif method == "tools/call" then
        -- Handle tool execution
        local result = self:execute_tool(params.name, params.arguments)
        return json_rpc.create_response(result, id)
    else
        return json_rpc.create_error_response(
            json_rpc.create_error(json_rpc.ErrorCodes.METHOD_NOT_FOUND, "Method not found"),
            id
        )
    end
end

function server:run()
    while true do
        local line = io.stdin:read("*l")
        if not line then break end
        
        if line ~= "" then
            local success, message = pcall(json_rpc.parse, line)
            if success then
                local response = self:handle_message(message)
                if response then
                    self.transport:send(response)
                end
            end
        end
    end
end

-- Run the server
local my_server = server:new()
my_server:run()

Testing

Running the Demo Server

The repository includes a fully-featured demo server that showcases all MCP capabilities:

# Run the demo server
lua demo_mcp_server.lua

# In another terminal, test with a single request
echo '{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test-client","version":"1.0.0"}},"id":1}' | lua demo_mcp_server.lua

# Run comprehensive tests
./test_comprehensive.sh

Test Results

The implementation passes all protocol compliance tests:

=== Lua MCP Demo Server Test Suite ===
Testing Initialize... ✓ PASS
Testing List Tools... ✓ PASS
Testing Add Tool (5 + 3)... ✓ PASS
Testing Echo Tool... ✓ PASS
Testing Get Time Tool... ✓ PASS
Testing List Resources... ✓ PASS
Testing Read Welcome Resource... ✓ PASS
Testing Read Config Resource... ✓ PASS
Testing List Prompts... ✓ PASS
Testing Get Greeting Prompt... ✓ PASS
Testing Invalid Method (Error)... ✓ PASS
Testing Invalid Tool (Error)... ✓ PASS
Testing Invalid Resource (Error)... ✓ PASS
Testing Invalid Prompt (Error)... ✓ PASS

Total Tests: 14
Passed: 14
Failed: 0

Protocol Specification Compliance

This implementation follows the Model Context Protocol specification exactly:

Transport Layer (stdio)

  • Messages are newline-delimited JSON-RPC 2.0
  • No embedded newlines in messages
  • stderr used only for logging (clients may ignore)
  • stdout used only for valid MCP messages

JSON-RPC 2.0

  • Request/response pattern with unique IDs
  • Notification support (no ID required)
  • Batch message support
  • Standard error codes:
    • -32700: Parse error
    • -32600: Invalid request
    • -32601: Method not found
    • -32602: Invalid params
    • -32603: Internal error

Core Methods

Lifecycle

  • initialize: Establish protocol version and capabilities
  • shutdown: Clean termination (via transport)

Tools

  • tools/list: List available tools with schemas
  • tools/call: Execute a tool with arguments

Resources

  • resources/list: List available resources
  • resources/read: Read resource content by URI
  • resources/subscribe: Subscribe to resource changes
  • resources/unsubscribe: Unsubscribe from changes

Prompts

  • prompts/list: List available prompt templates
  • prompts/get: Get a prompt with arguments

Architecture

lua-mcp/
├── src/mcp/
│   ├── foundation/       # Core utilities
│   │   ├── json.lua      # JSON encoding/decoding
│   │   ├── logger.lua    # Structured logging
│   │   ├── async.lua     # Async/await implementation
│   │   ├── events.lua    # Event emitter
│   │   ├── errors.lua    # Error handling
│   │   └── schema.lua    # JSON Schema validation
│   ├── protocol/         # Protocol implementation
│   │   ├── json_rpc.lua  # JSON-RPC 2.0
│   │   ├── lifecycle.lua # Protocol lifecycle
│   │   └── router.lua    # Message routing
│   ├── transport/        # Transport layers
│   │   ├── stdio.lua     # Standard I/O transport
│   │   ├── sse.lua       # Server-Sent Events
│   │   └── base.lua      # Base transport class
│   ├── features/         # MCP features
│   │   ├── tools.lua     # Tool management
│   │   ├── resources.lua # Resource management
│   │   ├── prompts.lua   # Prompt templates
│   │   └── completion.lua# Auto-completion
│   ├── security/         # Security layer
│   │   ├── validator.lua # Input validation
│   │   ├── rate_limiter.lua # Rate limiting
│   │   └── access_control.lua # Access control
│   └── core/            # High-level components
│       ├── server.lua    # MCP server
│       └── client.lua    # MCP client
├── examples/            # Example implementations
├── tests/              # Test suite
└── docs/               # Documentation

Security

The implementation includes a comprehensive security layer:

Input Validation

  • JSON Schema validation for all inputs
  • Maximum message size limits
  • Sanitization of outputs

Rate Limiting

  • Configurable request limits per client
  • Sliding window algorithm
  • Burst protection

Access Control

  • Tool/resource access restrictions
  • Path traversal prevention
  • Dangerous pattern blocking

Audit Logging

  • All operations logged with correlation IDs
  • Security events tracked
  • Performance metrics captured

Advanced Usage

Custom Transport

local BaseTransport = require("mcp.transport.base")

local CustomTransport = {}
setmetatable(CustomTransport, {__index = BaseTransport})

function CustomTransport:new(config)
    local self = BaseTransport.new(config)
    setmetatable(self, CustomTransport)
    -- Custom initialization
    return self
end

function CustomTransport:send(message)
    -- Custom send implementation
end

function CustomTransport:receive()
    -- Custom receive implementation
end

Adding Security

local Security = require("mcp.security")

local secure_server = {
    security = Security:new({
        validation = { enabled = true, max_message_size = 1024 * 1024 },
        rate_limiting = { enabled = true, max_requests = 60 },
        access_control = { enabled = true, allowed_tools = {"safe_tool"} }
    })
}

function secure_server:handle_request(message, client_id)
    local valid, err = self.security:validate_message(message, client_id)
    if not valid then
        return json_rpc.create_error_response(err, message.id)
    end
    -- Process validated request
end

Testing Your Implementation

Unit Tests

lua tests/run_all_tests.lua

Integration Tests

lua tests/run_integration_test.lua

Protocol Compliance

./test_comprehensive.sh

Contributing

Contributions are welcome! Please ensure:

  1. All tests pass
  2. New features include tests
  3. Code follows existing patterns
  4. Documentation is updated

License

MIT License - See LICENSE file for details

Acknowledgments

Support

For issues, questions, or contributions:

  • Open an issue on GitHub
  • Check the MCP specification for protocol details
  • Review the test suite for usage examples

About

An implementation of the Model Context Protocol in LUA

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors