Portable RTL Lint MCP
This package moves the RTL lint engine out of a VS Code extension and exposes one stable service to every client:
Codex / VS Code / Cursor / another MCP IDE
|
MCP protocol
+-----------+------------+
| |
stdio (local) Streamable HTTP (remote)
| |
+------ rtl_lint_mcp ----+
|
shared lint service
|
Verilog / SystemVerilog files
KRutrim can use the same service through its existing custom
/api/mcp/invoke dispatcher or, after it gains a standard MCP registry, by
connecting to the remote /mcp endpoint.
Why this is portable
- The lint engine is a normal Python package, not stored inside an IDE extension.
- The official MCP Python SDK handles protocol messages and tool schemas.
- Local IDEs use
stdio; deployed clients use Streamable HTTP. - CLI, MCP, VS Code, and KRutrim receive the same
rtl-lint-report.v1schema. - File access is restricted by
RTL_LINT_ALLOWED_ROOTS. - There are no repository-specific absolute paths in the implementation.
Tools
list_rtl_lint_ruleslint_rtl_textlint_rtl_filelint_rtl_project
Requirements
- Python 3.10 or newer. KRutrim currently reports Python 3.11.13, so it meets this requirement.
uvis recommended, but a Python virtual environment also works.
Install
With uv
cd tools/rtl-lint-mcp-portable
uv sync
With a virtual environment
cd tools/rtl-lint-mcp-portable
python3 -m venv .venv
. .venv/bin/activate
python3 -m pip install -e .
For the optional KRutrim Flask bridge:
python3 -m pip install -e '.[krutrim]'
Local CLI smoke test
The server rejects file paths outside its allowlist. Set the project root before running a file or project check:
export RTL_LINT_ALLOWED_ROOTS=/path/to/rtl/project
rtl-lint /path/to/rtl/project/rtl/top.sv --fail-on never
JSON output:
rtl-lint /path/to/rtl/project/rtl/top.sv --json --fail-on never
Local MCP for any IDE
Run over stdio:
export RTL_LINT_ALLOWED_ROOTS=/path/to/rtl/project
rtl-lint-mcp
Normally the IDE starts this command itself. Use
configs/generic-stdio.json as the base for any
client that accepts an mcpServers configuration.
Codex
From this directory:
codex mcp add rtl-lint \
--env RTL_LINT_ALLOWED_ROOTS=/path/to/rtl/project \
-- uv run --project /absolute/path/to/rtl-lint-mcp-portable rtl-lint-mcp
Verify:
codex mcp list
Start a new Codex conversation, then ask:
Use the RTL lint MCP to lint /path/to/rtl/project/rtl/top.sv.
VS Code / GitHub Copilot Chat
Copy configs/vscode-mcp.json to
.vscode/mcp.json, replace the package path, and open the folder in VS Code.
Use MCP: List Servers to start and inspect it. In Remote SSH, install/run
the server on the remote host so the MCP process can see the remote RTL path.
Other IDEs
For Cursor, Claude-compatible clients, and other MCP hosts, start from
configs/generic-stdio.json. Replace:
- the absolute package path;
RTL_LINT_ALLOWED_ROOTSwith the RTL workspace;uvwith the environment's full executable path when necessary.
Remote Streamable HTTP server
Run the same MCP as a network service:
export RTL_LINT_ALLOWED_ROOTS=/ws:/auto
rtl-lint-mcp --transport streamable-http \
--host 0.0.0.0 \
--port 8765 \
--allowed-host fpga-vm-bgl002.cisco.com:8765
Endpoint:
http://fpga-vm-bgl002.cisco.com:8765/mcp
If a browser calls the endpoint directly, also allow the KRutrim origin:
--allowed-origin http://fpga-vm-bgl002.cisco.com:5200
Do not expose the service beyond the Cisco network without authentication and TLS. The hostname/origin allowlist prevents DNS-rebinding attacks; it is not user authentication.
KRutrim integration
The inspected KRutrim service is a Flask application. Its front end calls:
POST /api/mcp/invoke
with payloads containing toolId, action, and target. Its output renderer
uses the first available string among response, answer, completion,
output, or text.
The bridge therefore returns:
{
"output": "Markdown report for the KRutrim panel",
"result": {"schema_version": "rtl-lint-report.v1"},
"backend": "rtl-lint-mcp",
"tool_id": "rtl_lint"
}
See integrations/krutrim/README.md for the
two deployment choices, the small Flask dispatcher patch, and a matching
front-end invocation example.
Docker deployment
docker build -t rtl-lint-mcp:0.2.0 .
docker run --rm -p 8765:8765 \
-v /ws:/workspace:ro \
-e RTL_LINT_ALLOWED_ROOTS=/workspace \
-e RTL_LINT_ALLOWED_HOSTS=fpga-vm-bgl002.cisco.com:8765 \
rtl-lint-mcp:0.2.0
Mount RTL read-only. The linter never needs write access.
Report contract
A single-file call returns a direct report, not a project wrapper:
{
"schema_version": "rtl-lint-report.v1",
"server_version": "0.2.0",
"operation": "lint_file",
"file": "/project/rtl/top.sv",
"issue_count": 1,
"summary": {"error": 1, "warning": 0, "info": 0},
"issues": []
}
This avoids the earlier VS Code integration bug where a caller expected
result.issues but the CLI returned result.files[0].issues.
Test
Core tests need only the standard library:
PYTHONPATH=src python3 -m unittest discover -s tests -v
For protocol testing, install the development environment and use the official MCP Inspector:
uv run mcp dev src/rtl_lint_mcp/server.py
Production checklist
- Keep
RTL_LINT_ALLOWED_ROOTSnarrow and explicit. - Mount repositories read-only for the HTTP service.
- Use TLS and authenticated access for any non-local endpoint.
- Keep the MCP sidecar on an internal interface or behind the KRutrim proxy.
- Add the
rtl_lintdispatch case to KRutrim's existing route. - Add a KRutrim UI action that sends
toolId: rtl_lintand the selected path. - Run the included tests and the MCP Inspector before deployment.
Important limitation
This is a lightweight text-pattern linter. It is useful for early feedback and demonstrations, but it does not replace compilation, synthesis, formal checks, or sign-off lint products.
References
- Official MCP Python SDK: https://py.sdk.modelcontextprotocol.io/
- VS Code MCP configuration: https://code.visualstudio.com/docs/agents/reference/mcp-configuration
Metadata
Release files for rtl-lint-mcp 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| rtl_lint_mcp-0.2.0.tar.gz | 92.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| rtl_lint_mcp-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 110.4 kB
Release files / rtl_lint_mcp-0.2.0.tar.gz
| Download URL | rtl_lint_mcp-0.2.0.tar.gz |
|---|---|
| Size | 92.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9a1f61c86e1318d861fbef61f275f9106c45900858c94e2c9593db2528622f74
|
|
BLAKE2b-256 checksum How to use checksums |
3a8fc8c44ac3ae53b7553fee739df306db84e8275126176c0248328e60632c70
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Release files / rtl_lint_mcp-0.2.0-py3-none-any.whl
| Download URL | rtl_lint_mcp-0.2.0-py3-none-any.whl |
|---|---|
| Size | 17.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c77234a7563cc076460d9fe20fed01e42dab8e6a062b73d487bdf1872d02f301
|
|
BLAKE2b-256 checksum How to use checksums |
1a9b98c8fe2b6c394baa0488bde8760a2b8225f93dcc7bed44545430dd670095
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|