# How to Run Code-Graph-RAG as an MCP Server: STDIO and HTTP Setup Guide

> Learn to run Code-Graph-RAG as an MCP server with STDIO for local clients or HTTP for REST API access. Follow this setup guide for vitali87/code-graph-rag.

- Repository: [Vitali Avagyan/code-graph-rag](https://github.com/vitali87/code-graph-rag)
- Tags: how-to-guide
- Published: 2026-08-11

---

**Code-Graph-RAG can run as an MCP server in either STDIO mode for local client integration or HTTP mode for REST API access, using the embedded server implementation in [`codebase_rag/mcp/server.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/mcp/server.py).**

The `vitali87/code-graph-rag` repository ships with a built-in MCP (Model Context Protocol) server that exposes graph-aware code intelligence capabilities to compatible clients. Whether you need direct stdin/stdout communication for IDE integrations or a standalone HTTP endpoint for remote access, the server supports both transport modes with minimal configuration. This guide covers the exact steps to launch and configure the server based on the source implementation.

## What Is the Code-Graph-RAG MCP Server?

The MCP server implementation resides in [`codebase_rag/mcp/server.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/mcp/server.py) and wraps the repository's core services—specifically the `MemgraphIngestor` for graph database operations and the `CypherGenerator` for query translation—behind a standardized RPC interface. When running, the server exposes two primary handlers: `list_tools` (returning available tool schemas) and `call_tool` (dispatching requests to the appropriate handler).

The server supports two distinct transport modes:
- **STDIO mode**: Attaches to the current process's stdin/stdout for direct client communication
- **HTTP mode**: Runs as a Starlette application via uvicorn, exposing REST-like endpoints

## Prerequisites and Installation

Before starting the server, ensure you have installed the required dependencies including the MCP runtime, `loguru`, `uvicorn`, and `starlette`.

```bash
pip install -r requirements.txt

```

The server also requires access to a target repository path. Set this via environment variable before launching:

```bash
export MCP_TARGET_REPO_PATH=/path/to/your/repository

```

If omitted, the server attempts to resolve the path from `CLAUDE_PROJECT_ROOT`, `PWD`, or falls back to the current working directory.

## Running the MCP Server in STDIO Mode

STDIO mode is the default entry point and is ideal for local AI assistants or IDE plugins that communicate over process pipes.

### How STDIO Mode Works

In [`codebase_rag/mcp/server.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/mcp/server.py), the `serve_stdio()` function initializes logging via `setup_logging` from `codebase_rag.constants`, validates the target repository path, creates service instances (`MemgraphIngestor` and `CypherGenerator`), and enters the MCP STDIO loop. This lifecycle management ensures graph services stay alive for the duration of the session and shut down gracefully on exit.

### Starting the Server

Run the module directly to start STDIO mode:

```bash
python -m codebase_rag.mcp.server

```

Alternatively, import and invoke the function programmatically:

```python
import asyncio
from codebase_rag.mcp.server import serve_stdio

asyncio.run(serve_stdio())

```

The server reads from stdin and writes JSON-RPC responses to stdout until the process terminates.

## Running the MCP Server in HTTP Mode

HTTP mode exposes the MCP functionality as a web service, suitable for remote clients or microservice architectures.

### HTTP Configuration Options

The HTTP server reads configuration from [`codebase_rag/config.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/config.py) settings:
- `MCP_HTTP_HOST`: Interface to bind (default: localhost)
- `MCP_HTTP_PORT`: Port number (default: 8000)
- `MCP_HTTP_AUTH_TOKEN`: Optional bearer token for authentication

### Starting the HTTP Server

Launch the HTTP server using the `serve_http()` entry point:

```bash
python -c "import asyncio; from codebase_rag.mcp.server import serve_http; asyncio.run(serve_http())"

```

This spins up a Starlette application wrapped by uvicorn, listening on the configured host and port.

### Securing the Endpoint

To protect the server when exposing it beyond localhost, set the authentication token:

```bash
export MCP_HTTP_HOST=0.0.0.0
export MCP_HTTP_PORT=8080
export MCP_HTTP_AUTH_TOKEN=your-secret-token
python -c "import asyncio; from codebase_rag.mcp.server import serve_http; asyncio.run(serve_http())"

```

When `MCP_HTTP_AUTH_TOKEN` is set and the host is not localhost, the server enforces bearer token authentication on all requests.

## Understanding the Server Architecture

The server initialization follows a specific workflow defined in lines 42-112 of [`codebase_rag/mcp/server.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/mcp/server.py).

### Project Root Resolution

The server determines which codebase to serve by checking `MCPEnvVar.TARGET_REPO_PATH` (or the fallback `TARGET_REPO_PATH` setting). If the environment variable is unset, it defaults to the current working directory. The implementation validates that the path exists and is a directory, raising errors if validation fails.

### Service Initialization

During startup, the server instantiates:
- A `MemgraphIngestor` for graph database interactions
- A `CypherGenerator` for translating natural language queries to Cypher
- A tools registry via `create_mcp_tools_registry` (defined in [`codebase_rag/mcp/tools.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/mcp/tools.py))

These services persist for the server's lifetime and handle tool invocations from the `call_tool` RPC handler.

### RPC Handlers and Tools

The `mcp.Server` instance exposes:
- **`list_tools`**: Returns schemas for all registered tools including file editing, graph updates, and semantic search
- **`call_tool`**: Dispatches incoming requests to the appropriate tool handler and serializes JSON results

Tools are registered in [`codebase_rag/mcp/tools.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/mcp/tools.py), which wires concrete implementations to the MCP RPC layer.

## Querying the Server

Once running, you can interact with the server using the client utilities or direct HTTP requests.

### STDIO Client Example

Use the helper from [`codebase_rag/mcp/client.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/mcp/client.py) to communicate with a running STDIO server:

```python
from codebase_rag.mcp.client import query_mcp_server

result = query_mcp_server({
    "method": "call_tool",
    "params": {
        "name": "search_code",
        "arguments": {"query": "list files", "path": "."}
    }
})
print(result)

```

### HTTP cURL Example

Query the HTTP endpoint directly:

```bash
curl -X POST http://localhost:8000/mcp \
     -H "Content-Type: application/json" \
     -H "Authorization: Bearer your-secret-token" \
     -d '{"method":"call_tool","params":{"name":"search_code","arguments":{"query":"list files","path":"."}}}'

```

## Summary

- **Code-Graph-RAG provides an embedded MCP server** in [`codebase_rag/mcp/server.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/mcp/server.py) supporting both STDIO and HTTP transports
- **STDIO mode** starts via `python -m codebase_rag.mcp.server` and communicates over stdin/stdout using the `serve_stdio()` function
- **HTTP mode** runs via `serve_http()` as a Starlette/uvicorn application, configurable via `MCP_HTTP_HOST`, `MCP_HTTP_PORT`, and optional `MCP_HTTP_AUTH_TOKEN`
- **Project targeting** uses the `MCP_TARGET_REPO_PATH` environment variable (or `TARGET_REPO_PATH` fallback) to determine which codebase to index
- **Core services** include `MemgraphIngestor` for graph operations and `CypherGenerator` for query translation, initialized during server startup
- **Client libraries** in [`codebase_rag/mcp/client.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/mcp/client.py) provide convenient wrappers for both transport modes

## Frequently Asked Questions

### What is the difference between STDIO and HTTP mode in Code-Graph-RAG?

STDIO mode attaches the MCP server to the current process's stdin/stdout streams, making it ideal for local AI assistants or IDE integrations that spawn the process directly. HTTP mode runs the server as a standalone web service using Starlette and uvicorn, exposing REST-like endpoints suitable for remote clients or microservice deployments. Both modes use the same underlying tool registry and graph services.

### How do I specify which repository the MCP server should analyze?

Set the `MCP_TARGET_REPO_PATH` environment variable to the absolute path of your target repository before starting the server. If this variable is unset, the server checks `CLAUDE_PROJECT_ROOT`, then `PWD`, and finally falls back to the current working directory. The path must exist and be a valid directory, or the server will raise a configuration error during startup in [`codebase_rag/mcp/server.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/mcp/server.py).

### Can I secure the HTTP MCP server with authentication?

Yes, set the `MCP_HTTP_AUTH_TOKEN` environment variable to a secret token before starting the server. When this token is present and the server binds to a non-loopback interface (anything other than localhost), the server enforces bearer token authentication on all incoming requests. Requests must include the header `Authorization: Bearer your-token` to access the MCP endpoint.

### Which tools are available when running Code-Graph-RAG as an MCP server?

The server exposes tools registered via `create_mcp_tools_registry` in [`codebase_rag/mcp/tools.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/mcp/tools.py), including capabilities for semantic code search, file editing, graph updates, and natural language querying of the codebase. The `list_tools` RPC handler returns the complete schema of available tools, while `call_tool` dispatches requests to the appropriate implementation based on the tool name provided.