Skip to content

MCP Integration

Luna connects to Model Context Protocol (MCP) servers to extend the agent's capabilities beyond built-in tools. MCP servers provide additional tools, resources, and prompt templates through a standardized JSON-RPC protocol.

Overview

Luna Agent
    |
    +-- Built-in tools (bash, read_file, write_file, ...)
    |
    +-- MCP Manager
         +-- MCP Server 1 (stdio) -> filesystem tools
         +-- MCP Server 2 (stdio) -> GitHub tools
         +-- MCP Server 3 (stdio) -> database tools

MCP tools are discovered automatically on connection and merged with built-in tools. The LLM sees all tools (built-in + MCP) in its tool list, prefixed with mcp__.

Protocol Version

Luna implements the Model Context Protocol specification (2025-03-26), supporting:

  • initialize handshake with capability negotiation
  • tools/list for tool discovery
  • tools/call for tool execution
  • resources/read for resource access
  • prompts/get for prompt template retrieval

Transport

stdio Transport

Communication via stdin/stdout JSON-RPC. Each server runs as a separate subprocess.

  • Content-Length header support for framing
  • Multi-server support -- connect to multiple MCP servers simultaneously
  • Best-effort connection model

HTTP Transport

Luna also supports HTTP-based MCP servers for remote tool access. HTTP transport enables connections to MCP servers that are not local processes.

Configuration

Global Config: ~/.luna/mcp.json

json
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/projects"]
    },
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_..."
      }
    }
  }
}

Project-local Config: .luna/mcp.json

Same format as global config. Project-local config is merged with global config. Project-local takes precedence on conflicts.

Config Structure

FieldTypeRequiredDescription
commandstringYesCommand to start the MCP server
argsarrayNoArguments to pass to the command
envobjectNoEnvironment variables for the server process

Tool Discovery

When Luna starts:

  1. Reads MCP config (global + project-local, merged)
  2. Starts each configured server as a subprocess
  3. Sends initialize and tools/list JSON-RPC requests
  4. Merges discovered tools into the agent's tool registry
  5. The LLM sees all tools (built-in + MCP) in its system prompt

Discovered MCP tools are prefixed with mcp__ in the tool registry (e.g., mcp__github_create_issue).

Multi-Server Management

Luna can connect to multiple MCP servers simultaneously. Each server runs as an independent subprocess with its own lifecycle:

  • Servers are started in parallel during initialization
  • Each server's tools are namespaced by server name
  • If one server fails, others continue operating normally
  • Use mcp_read_resource and mcp_get_prompt with the optional server parameter to target a specific server

OAuth PKCE

Luna supports OAuth 2.0 with PKCE (Proof Key for Code Exchange) for MCP servers that require authentication:

  1. Luna generates a code verifier and challenge
  2. Starts a local callback server via FFI raw socket
  3. Opens the authorization URL in the user's browser
  4. Receives the authorization code at the callback URL
  5. Exchanges the code for an access token using the code verifier
  6. Stores the token for subsequent API calls

OAuth configuration is specified per-server in the MCP config.

Luna as MCP Server

Luna can also act as an MCP server, exposing its built-in tools to external MCP clients. This enables other applications to use Luna's file operations, code intelligence, and other capabilities through the standard MCP protocol.

When running as an MCP server, Luna:

  • Responds to initialize and tools/list requests
  • Executes tools via tools/call and returns results
  • Supports the same JSON-RPC message format

Example MCP Servers

Filesystem Access

json
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed/dir"]
    }
  }
}

GitHub Integration

json
{
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_..."
      }
    }
  }
}

PostgreSQL Queries

json
{
  "mcpServers": {
    "postgres": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-postgres", "postgresql://user:pass@localhost/db"]
    }
  }
}

Custom MCP Server

Any MCP-compatible server can be used. The server must:

  1. Accept JSON-RPC requests on stdin
  2. Respond with JSON-RPC responses on stdout
  3. Support initialize and tools/list methods
  4. Follow the MCP specification

Best-Effort Connection

MCP connections are best-effort:

ScenarioBehavior
Server fails to startLuna logs a warning and continues without its tools
Server crashes mid-sessionLuna logs the error and continues with remaining tools
Server restartsManual restart required

Troubleshooting

MCP server not connecting:

  • Check the command path is correct and the binary exists
  • Check args are properly formatted
  • Check environment variables (especially API keys)
  • Look for errors in ~/.luna/logs/

MCP tools not appearing:

  • Ensure the server supports tools/list method
  • Check that the server starts without errors
  • Verify the server responds to initialize request
  • Use /tools-reload to rescan after fixing configuration

Released under the MIT License.