Model Context Protocol (MCP) server¶
Install the optional mcp dependency:
Your lintkit-based linter will now get the mcp command. Start the server with the default stdio transport (you can change it using flags):
Tools¶
The server exposes the same commands as lintkit.cli.main does (check, rules, examples) as tools with the following properties:
- omit
namesto select all rules (default) - each tool has one
namesselector - values must be exact, case-sensitive full names, such as
MYLINTER10; names are not uppercased and the choices are properly typed astyping.Literal checkaccepts explicitfiles; underlintkit mcp, omitting them uses the defaults configured by the linter'slintkit.cli.maincall (we advise to use a recursive one)
You can --enable and/or --disable (takes precedence) tools (by default all tools are enabled):
Server CLI options¶
Start a stateless HTTP server with explicit network and origin controls:
> lintkit mcp --transport http --host 127.0.0.1 --port 8000 --path /mcp \
--host-origin-protection --allowed-host localhost \
--allowed-origin https://example.com
Repeat --allowed-host and --allowed-origin to add values. Use --no-host-origin-protection to disable protection explicitly. HTTP remains stateless unless you add the legacy (since 2026-07-06 specification) --stateful option.
Use --name to replace the default server name, which is the same as linter's name by default (different from randomly generated default of fastmcp):
Server settings¶
Import your project rules before you create the server. Server construction raises lintkit.error.RegistryEmptyError when there are no rules found.
from fastmcp import FastMCP
import lintkit
# Note rules import before server!
import my_linter.rules # noqa: F401
my_linter_server = lintkit.mcp.server()
parent = FastMCP("My project")
parent.mount(my_linter_server, namespace="lint")
- the parent server exposes the tools as
lint_<TOOL>(e.g.lint_check). - each call to
lintkit.mcp.servercreates an independent server
A directly constructed server requires files in every check call (error is raised when these are not provided).
To make that input optional, provide defaults when constructing it:
my_linter_server = lintkit.mcp.server(
# If no files provided go over $CWD/src and $CWD/tests
files_default=("src", "tests"),
# Read all Python files
files_reader=lintkit.cli.files.reader.Recursive(".py"),
)
NOTE: The configured reader processes both the defaults and explicit MCP paths, so clients have their directories and Python files checked.
You can explicitly provide instructions and pass other fastmcp constructor arguments directly:
custom_server = lintkit.mcp.server(
name="Project linter",
instructions="Check project files with the registered project rules.",
strict_input_validation=True,
)
Finally you can run or mount the returned instance: