mcp-lnav-canbus
MCP lnav CAN bus Server
A Model Context Protocol (MCP) server that exposes lnav log file analysis capabilities to AI assistants, specifically optimized for Kvaser Plain Text Log Frame CAN bus log processing.
Overview
This Python-based MCP server provides session-based access to CAN bus log files with structured JSON output, enabling AI models to analyze, query, and extract insights from Kvaser CAN bus logs through the Model Context Protocol.
Related MCP server: log-mcp
Architecture
┌─────────────────────┐ ┌──────────────────────┐ ┌─────────────────┐
│ MCP Client │────▶│ MCP Server │────▶│ lnav CLI │
│ (Claude, Cursor) │◀────│ (Python, stdio) │◀────│ (v0.12.0+) │
└─────────────────────┘ └──────────────────────┘ └─────────────────┘
│
▼
┌──────────────────────┐
│ Session Manager │
│ (stateful context) │
└──────────────────────┘
│
▼
┌──────────────────────┐
│ Kvaser CAN Logs │
│ (.txt, .log) │
└──────────────────────┘Requirements
Runtime Dependencies
Python: 3.10 or higher
lnav: 0.12.0 or higher (must be installed and available in PATH)
MCP Python SDK: 2.0.0+ (v2 beta) or 1.27+ (v1 stable)
Supported Log Format
Primary Format: Kvaser Plain Text Log Frame
# Column format: Timestamp Channel Type Dir ID DLC Data
0.000000 0 Rx std 0x123 8 00 01 02 03 04 05 06 07
0.001000 0 Tx std 0x456 8 AA BB CC DD EE FF 00 11Also Supported (via lnav auto-detection):
Vector ASC
CANalyzer TRC
Generic CSV with timestamp/channel/id/data columns
Installation
1. Install lnav
# macOS
brew install lnav
# Ubuntu/Debian
sudo apt-get install lnav
# Or download from https://github.com/tstack/lnav/releasesVerify installation:
lnav --version2. Install the MCP Server
# Using pip
pip install mcp-lnav-canbus
# Using uv
uv add mcp-lnav-canbusConfiguration
Claude Desktop
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Linux: ~/.config/claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"lnav-canbus": {
"command": "python",
"args": ["-m", "mcp_lnav_canbus"],
"env": {
"LNAV_PATH": "/usr/local/bin/lnav"
}
}
}
}Cursor
.cursor/mcp.json in project root:
{
"mcpServers": {
"lnav-canbus": {
"command": "python",
"args": ["-m", "mcp_lnav_canbus"],
"cwd": "/path/to/your/project",
"env": {
"LNAV_PATH": "/usr/local/bin/lnav"
}
}
}
}VS Code (with MCP extension)
.vscode/mcp.json:
{
"servers": {
"lnav-canbus": {
"type": "stdio",
"command": "python",
"args": ["-m", "mcp_lnav_canbus"]
}
}
}Tools
open_can_log
Open a Kvaser CAN bus log file in the current session.
Parameters:
file_path(string, required): Path to the Kvaser CAN log filesession_id(string, optional): Session identifier (auto-generated if not provided)
Example:
{
"name": "open_can_log",
"arguments": {
"file_path": "/data/can_trace.txt"
}
}Response:
{
"success": true,
"session_id": "sess_abc123",
"file_info": {
"path": "/data/can_trace.txt",
"format": "kvaser",
"message_count": 15420,
"time_range": {
"start": "2024-01-15T10:00:00.000000",
"end": "2024-01-15T10:05:30.123456"
},
"channel_count": 2,
"unique_ids": 47
}
}query_can_messages
Execute SQL queries against CAN bus log data using lnav's SQL engine.
Parameters:
query(string, required): SQLite query to executelimit(integer, optional, default: 100): Maximum rows to return
Example:
{
"name": "query_can_messages",
"arguments": {
"query": "SELECT can_id, COUNT(*) as count FROM log GROUP BY can_id ORDER BY count DESC LIMIT 10"
}
}Response:
{
"success": true,
"columns": ["can_id", "count"],
"rows": [
["0x123", 1542],
["0x456", 987],
["0x789", 654]
],
"row_count": 3,
"execution_time_ms": 45
}extract_can_frames
Extract specific CAN frames by ID, channel, or time range.
Parameters:
can_id(string, optional): CAN ID to filter (hex format, e.g., '0x123')channel(integer, optional): CAN channel number (0-based)start_time(string, optional): Start timestampend_time(string, optional): End timestamplimit(integer, optional, default: 1000): Maximum frames to return
Example:
{
"name": "extract_can_frames",
"arguments": {
"can_id": "0x123",
"start_time": "0.000000",
"end_time": "1.000000",
"limit": 100
}
}Response:
{
"success": true,
"frames": [
{
"timestamp": "0.000000",
"channel": 0,
"type": "Rx",
"can_id": "0x123",
"dlc": 8,
"data": [0, 1, 2, 3, 4, 5, 6, 7]
}
],
"frame_count": 1,
"total_matching": 154
}get_statistics
Generate statistical analysis of CAN bus traffic.
Parameters:
stat_type(string, required): "frequency", "timing", "load", "errors", or "summary"interval(string, optional): Time interval for aggregation (e.g., '1s', '100ms')can_id(string, optional): CAN ID to filter statistics
Example:
{
"name": "get_statistics",
"arguments": {
"stat_type": "frequency",
"interval": "1s"
}
}Response:
{
"success": true,
"stat_type": "frequency",
"statistics": {
"by_id": [
{"can_id": "0x123", "count": 1542, "rate_hz": 100.0},
{"can_id": "0x456", "count": 987, "rate_hz": 64.2}
],
"total_messages": 15420,
"duration_seconds": 330.123456,
"average_rate_hz": 46.7
}
}find_errors
Find error frames and anomalies in CAN bus logs.
Parameters:
error_type(string, optional, default: "all"): "all", "crc", "bit", "stuff", "form", "ack", "timeout", or "gap"channel(integer, optional): Channel filter
Example:
{
"name": "find_errors",
"arguments": {
"error_type": "crc"
}
}Response:
{
"success": true,
"errors": [
{
"timestamp": "1.234567",
"channel": 0,
"error_type": "crc",
"can_id": "0x123",
"message": "CRC error detected"
}
],
"error_count": 1,
"error_rate_per_minute": 0.18
}analyze_payload_noise
Analyze CAN bus payload repetition to detect noise in logs using MD5 hashes. This tool identifies repeated payloads that may represent noise or meaningless data in the log.
Parameters:
min_repetitions(integer, optional, default: 10): Minimum number of repetitions to consider as noisesession_id(string, optional): Session identifier
Example:
{
"name": "analyze_payload_noise",
"arguments": {
"min_repetitions": 5
}
}Response:
{
"success": true,
"analysis": {
"total_frames": 1000,
"unique_payloads": 25,
"noise_patterns_found": 3,
"total_noisy_frames": 850,
"noise_percentage": 85.0,
"min_repetitions_threshold": 5
},
"noise_patterns": [
{
"payload_md5": "0ee0646c1c77d8131cc8f4ee65c7673b",
"repetition_count": 500,
"payload_hex": "01 02 03 04 05 06 07 08",
"first_timestamp": "0.000000",
"last_timestamp": "10.500000",
"time_span_seconds": 10.5,
"can_ids": ["0x123"],
"channels": [0],
"noise_ratio": 0.5
}
]
}scan_payload_for_value
Scan CAN bus payload bytes for a specific decimal value. Searches for frames where consecutive bytes in the payload match the binary representation of the given decimal value. Supports both big-endian and little-endian byte orders.
Parameters:
byte_value(integer, required): Decimal value to search for (0 to unlimited, auto-calculates byte width)endianness(string, optional, default: "big"): Byte order ("big" or "little")start_offset(integer, optional, default: 0): Start searching from this byte offsetend_offset(integer, optional, default: None): Stop searching at this byte offset (None searches to end)limit(integer, optional, default: 1000): Maximum frames to returnsession_id(string, optional): Session identifier
Example:
{
"name": "scan_payload_for_value",
"arguments": {
"byte_value": 65535,
"endianness": "big",
"limit": 10
}
}Response:
{
"success": true,
"search_criteria": {
"byte_value": 65535,
"endianness": "big",
"start_offset": 0,
"end_offset": null,
"byte_width": 2,
"target_bytes_hex": "FF FF"
},
"matches": [
{
"timestamp": "0.001000",
"channel": 0,
"type": "Tx",
"direction": "std",
"can_id": "0x456",
"dlc": 8,
"data": [170, 187, 255, 255, 238, 239, 0, 17],
"payload_hex": "AA BB FF FF EE EF 00 11",
"match_position": 2,
"match_bytes": [255, 255],
"byte_width": 2
}
],
"match_count": 1,
"frames_scanned": 10,
"frames_skipped_too_short": 0
}Use Cases:
Find frames containing specific sensor values (e.g., temperature = 255)
Search for error codes encoded in payload bytes
Locate frames with specific multi-byte values (e.g., 16-bit counters, 32-bit timestamps)
Debug communication issues by finding frames with unexpected byte patterns
get_session_info
Retrieve information about the current session state.
Parameters: None
Response:
{
"success": true,
"session_id": "sess_abc123",
"files_loaded": [
{
"path": "/data/can_trace.txt",
"format": "kvaser",
"message_count": 15420,
"loaded_at": "2024-01-15T14:30:00Z"
}
],
"active_filters": [],
"lnav_version": "0.12.0",
"session_duration_seconds": 120
}close_session
Close the current session and release resources.
Parameters: None
Response:
{
"success": true,
"session_id": "sess_abc123",
"message": "Session closed successfully"
}Resources
The server provides the following MCP resources:
canbus://session/{session_id}/log
Access the current session's loaded log file content.
Example URI: canbus://session/sess_abc123/log
canbus://session/{session_id}/messages/{can_id}
Access specific CAN ID messages from the session.
Example URI: canbus://session/sess_abc123/messages/0x123
canbus://session/{session_id}/errors
Access error frames from the session's log file.
Example URI: canbus://session/sess_abc123/errors
Prompts
canbus-analyze
Generate a comprehensive analysis of a Kvaser CAN bus log file.
Parameters:
file_path(string, required): Path to the Kvaser CAN log fileanalysis_type(string, optional): "quick", "detailed", "errors", "traffic", or "custom" (default: "detailed")focus_ids(array, optional): List of CAN IDs to focus analysis on
Example:
/canbus-analyze file_path="/data/can_trace.txt" analysis_type="detailed"canbus-decode-frame
Help decode and interpret a specific CAN frame.
Parameters:
can_id(string, required): CAN ID to decodedata_bytes(array, required): Data bytes to decodedbc_file(string, optional): Path to DBC file for signal decoding
Example:
/canbus-decode-frame can_id="0x123" data_bytes=[0,1,2,3,4,5,6,7]Session Lifecycle
Session Creation
Client initiates MCP connection via stdio
Server creates session context with unique session ID
Server spawns lnav process for the session
Session state initialized (empty file list, no filters)
Session Usage
Client calls
open_can_logto load a fileServer loads file into lnav, updates session state
Client makes queries using session context
Server maintains lnav process and state between calls
Session Termination
Client calls
close_sessionor disconnectsServer terminates lnav process
Server releases session resources
Session state cleared
Server Configuration
Transport
Transport Protocol: stdio only
The server communicates via standard input/output streams, suitable for local CLI integration and subprocess spawning.
Session Management
The server maintains session-based state between calls:
Each client connection establishes a session context
Session persists for the lifetime of the MCP connection
Loaded files remain in session memory for subsequent queries
Session state includes: loaded files, active filters, query history, lnav process handle
Path Validation
Pass-through to lnav: The server does not validate file paths. Path validation and error handling is delegated to lnav, which returns appropriate error messages for invalid paths.
Environment Variables
Variable | Description | Default |
| Path to lnav binary |
|
| Default timeout for lnav operations (seconds) |
|
| Maximum concurrent sessions |
|
| Logging verbosity |
|
Server Startup
# Basic usage
python -m mcp_lnav_canbus
# With custom lnav path
LNAV_PATH=/usr/local/bin/lnav python -m mcp_lnav_canbus
# With debug logging
LOG_LEVEL=DEBUG python -m mcp_lnav_canbusError Handling
Error Response Format
{
"success": false,
"error": {
"code": "FILE_NOT_FOUND",
"message": "File not found: /path/to/log.txt",
"details": {
"path": "/path/to/log.txt",
"lnav_error": "Unable to open file"
}
}
}Error Codes
Code | Description |
| Specified file path does not exist |
| Log file format not recognized |
| SQL query syntax error |
| Session not found or expired |
| lnav process error |
| Operation timed out |
| Internal server error |
Usage Examples
Example 1: Basic Log Analysis
// Request
{
"tool": "open_can_log",
"arguments": {
"file_path": "/data/can_trace.txt"
}
}
// Response
{
"success": true,
"session_id": "sess_abc123",
"file_info": {
"path": "/data/can_trace.txt",
"format": "kvaser",
"message_count": 15420,
"time_range": {
"start": "2024-01-15T10:00:00.000000",
"end": "2024-01-15T10:05:30.123456"
},
"channel_count": 2,
"unique_ids": 47
}
}Example 2: Query by CAN ID
// Request
{
"tool": "query_can_messages",
"arguments": {
"query": "SELECT can_id, COUNT(*) as count FROM log GROUP BY can_id ORDER BY count DESC LIMIT 10"
}
}
// Response
{
"success": true,
"columns": ["can_id", "count"],
"rows": [
["0x123", 1542],
["0x456", 987],
["0x789", 654]
],
"row_count": 3
}Example 3: Error Detection
// Request
{
"tool": "find_errors",
"arguments": {
"error_type": "all"
}
}
// Response
{
"success": true,
"errors": [
{
"timestamp": "1.234567",
"channel": 0,
"error_type": "crc",
"can_id": "0x123",
"message": "CRC error detected"
}
],
"error_count": 1,
"error_rate_per_minute": 0.18
}Security Considerations
Server runs with same permissions as host process
File access limited to paths provided in tool calls
No network access performed (stdio transport only)
SQL queries executed in sandboxed lnav session
Session isolation prevents cross-session data access
Command injection prevented via parameterized queries
Troubleshooting
Common Issues
lnav not found:
Error: LNAV_PATH not set or lnav not in PATH
Solution: Set LNAV_PATH environment variable or install lnavInvalid log format:
Error: INVALID_FORMAT
Solution: Ensure log file is Kvaser Plain Text Log Frame formatSession timeout:
Error: SESSION_ERROR
Solution: Check session_id is valid and session hasn't expiredQuery syntax error:
Error: QUERY_ERROR
Solution: Verify SQLite syntax in query parameterPerformance Considerations
Large log files indexed on open (progress reported to client)
SQL queries executed via lnav's SQLite integration
Result limiting prevents memory exhaustion
Timeout enforcement prevents hung operations
Limitations
Binary formats (BLF, MF4) require external conversion tools
Real-time log tailing is not supported (batch processing only)
DBC signal decoding requires external DBC parser integration
Maximum file size recommendations apply for performance
Development
Running in Development Mode
Use the MCP Inspector to test the server:
uv run mcp dev server.pyTesting
# Run tests
pytest tests/
# Run with coverage
pytest --cov=mcp_lnav_canbus tests/Version Compatibility
Component | Minimum Version | Recommended Version |
Python | 3.10 | 3.11+ |
lnav | 0.12.0 | 0.14.0+ |
MCP SDK | 1.27.0 or 2.0.0b1 | 2.0.0b1+ |
Contributing
Contributions are welcome! Please see our Contributing Guide for details.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Acknowledgments
lnav - Log File Navigator by Timothy Stack
Model Context Protocol - MCP specification
MCP Python SDK - Python implementation
Resources
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/baxtheman/mcp-lnav-canbus'
If you have feedback or need assistance with the MCP directory API, please join our Discord server