MCP Surface Lint

MCP Surface Lint

Static checks over an MCP tool surface to find where a caller could do the wrong thing and get no error back.

Category
Visit Server

README


title: MCP Surface Lint emoji: 🔎 colorFrom: indigo colorTo: gray sdk: gradio sdk_version: 6.20.0 app_file: app.py pinned: false license: mit short_description: Find where an MCP tool surface lets a caller fail silently tags:

  • mcp
  • mcp-server
  • developer-tools
  • static-analysis

MCP Surface Lint

Static checks over an MCP tool surface. Every rule answers one question:

Could a caller do the wrong thing and get no error back?

A tool that crashes on bad input is fine. A tool that accepts bad input and returns something plausible is the expensive kind of broken, because neither the caller nor the person reading the transcript has any signal that it happened.

Paste a tools/list response, get back the specific places that can happen.

This app is also an MCP server, so an agent can lint an agent interface without going through the UI.

Using it as an MCP server

Launched with demo.launch(mcp_server=True). Point a client at:

https://<space-host>/gradio_api/mcp/sse

Two tools are published:

Tool Purpose
lint_tool_surface(surface_json) Run every rule over a surface, return findings with severities
list_rules() Enumerate the checks, their ids, and their severities

The UI event handlers are deliberately excluded with api_name=False. Without that, Gradio also publishes analyse, analyse_1, and explain as tools: a duplicate-name pair plus a handler taking a gr.State that cannot survive a tool call. This linter flags all three patterns, so shipping them would be a poor look.

The rules

Id Severity Catches
MCP001 high Tool has no description
MCP002 low Description too short to distinguish from a neighbour
MCP003 high No inputSchema at all
MCP004 high Parameter with no description
MCP005 high Parameter with no declared type
MCP006 medium String parameter that is really a closed set, with no enum
MCP007 high Properties declared but no required list
MCP008 low Numeric parameter with no bounds
MCP009 medium Unconstrained object parameter
MCP010 medium Description never says what failure looks like
MCP011 high Destructive verb with no guard parameter and no warning
MCP012 medium Two tools a caller cannot choose between by name
MCP013 medium Two tools sharing an identical description

Names are compared after crude stemming, because list_user_records and list_users_record are the same tool as far as a caller is concerned and raw token comparison misses that entirely.

What it found in its own surface

Pointed at its own published schema, the linter returns exactly one finding, and it is not in this repo:

[high] MCP007 lint_tool_surface: Schema declares properties but no 'required' list

Gradio's get_input_schema builds {"type": "object", "properties": {...}} and never emits a required array. The information is already there: the same parameter dicts it iterates carry parameter_has_default, and Gradio's own gradio skills command uses that field to mark a parameter required. The practical effect is that every Gradio MCP server publishes tools whose arguments all look optional, so a caller that omits a mandatory one produces a schema-valid call.

Reported upstream as gradio-app/gradio#13670.

Running locally

pip install -r requirements.txt
python app.py

Tests:

python -m pytest -q

Rules are only worth what their tests are worth, so there is also a mutation matrix. It neuters each rule in turn and records which tests fail. A rule with no failing test is either dead code or unguarded, and you cannot tell which without looking:

python mutation_check.py

It refuses to report anything unless the baseline suite is green first, and it disables bytecode caching, because every mutated file is the same length and CPython validates a cached .pyc on (mtime, size). Inside one second that pair does not change, so the interpreter happily re-imports the previous mutation's bytecode and the whole matrix reports the wrong rule's result.

License

MIT.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured