add-mcp-tool
Skill1 starsChanged 24 days agoMITView on GitHub
How to add, change, or document an MCP tool in msmcp, including its wire schema, annotations, registration, and tests.
12 other projects use a version of this.
Adopted by
Most recently taken up by
- skillist-io/skillisttheir own version, first seen Oct 11, 2026
- james5101/jobtracktheir own version, first seen Oct 11, 2026
- Locker-Room-Tools/synapsetheir own version, first seen Oct 11, 2026
- letehaha/moneymattertheir own version, first seen Oct 11, 2026
- openfootmanager/openfootmanagertheir own version, first seen Oct 8, 2026
- dragoscv/axiomtheir own version, first seen Sep 21, 2026
Other versions12 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 12
- openfootmanager/openfootmanager★ 1.2ksame name
- letehaha/moneymatter★ 221same name
- dylanroscover/Embody★ 213same name
- tacticlaunch/mcp-linear★ 147same name
- radimsem/remindb★ 125same name
- paulieb89/property-shared★ 16same name
- plumbkit/plumb★ 4same name
- james5101/jobtrack★ 2same name
- Locker-Room-Tools/synapse★ 2same name
- skillist-io/skillist★ 1same name
2 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository6 other files it gives its agents.
- AGENTS.mdAGENTS.md
- data-referencesSkill
- instrument-class-defaultsSkill
- ms-data-ingestionSkill
- quality-gateSkill
- security-boundarySkill
The file
We split this skill into the rules it gives an agent
7 rules. 0 are common, 1 is distinctive, and 6 are very specific to this project.
0
Common
Most of the 11 edited versions we read keep these.
1
Distinctive
This author's own choices. Worth a look.
6
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 10
Use this when adding a tool, changing a parameter, or editing a tool's description.
- Very specific: line 66
Every tool must declare ToolAnnotations.
- Very specific: line 77
If a tool's result is a demonstration rather than a real identification (as search_library is for a synthetic library), say so in both the …
- Very specific: line 83
Add behavioural tests next to the module's existing tests (tests/test_io.py, etc.).
- Very specific: line 87
Update MODEL_FOR_TOOL in tests/test_tool_schemas.py with the new tool and its validating model.
- Very specific: line 89
Update EXPECTED_TOOLS in tests/test_smoke_stdio.py.
- Very specific: line 91
Add new tools to WRITING_TOOLS in the schema test only if they mutate server-side state.
“Common” is measured: kept by at least 6 in 10 of the 11 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Adding or changing an MCP tool
Use this when adding a tool, changing a parameter, or editing a tool's description. The wire contract is what the host LLM sees, and the test suite enforces it, so get the schema right the first time.
Where tools live
One module per logical group under src/msmcp/tools/:
| Module | Tools |
io.py | load_mzml_summary, list_spectra, load_spectrum, summarise_reference, release_reference |
chem.py | predict_adduct_offset, annotate_isotopes |
similarity.py | validate_precursor, compute_cosine |
qc.py | generate_qc_summary |
search.py | search_library, check_search_status, cancel_search |
server.py owns ping and the MCPServer instance.
The pattern
Each module exposes register_tools(mcp); tools are closures inside it:
def register_tools(mcp: Any) -> None:
@mcp.tool(
title="Short display title",
annotations=ToolAnnotations(read_only_hint=True, open_world_hint=False),
)
def my_tool(
file_path: Annotated[
str,
Field(description="Shown to the host on the wire."),
],
) -> str:
"""Docstring becomes the tool description."""
_ = MyToolInput(file_path=file_path) # validate in the body
...Register a new module in server.py by importing its register_tools as
_register_*_tools and calling it alongside the existing ones.
Two rules that are easy to get wrong
- Parameter descriptions must live on the signature, not only on the
Pydantic model. The MCP SDK builds
inputSchemafrom the function signature; a description that exists only on the validating model never reaches the host.tests/test_tool_schemas.pyfails if a parameter has no wire description. - Numeric constraints must be duplicated. Declare bounds with
Annotated[..., Field(ge=..., le=...)]on the signature and on the Pydantic model that validates in the body. The model is the enforcement; the signature is the advertisement. The same test asserts they match.
Annotations
Every tool must declare ToolAnnotations. Set open_world_hint=False always:
the server makes no network calls. Set read_only_hint=False only for the
state-mutating tools, which are exactly release_reference and
cancel_search. Do not mark a read-only tool as writing.
Description hygiene
Tool descriptions are prose for a model choosing a tool. Do not leak internal
symbols (asyncio., _run_scan, PathEscapeError, ...); the schema test
rejects several of them. State behaviour and caveats, not implementation.
If a tool's result is a demonstration rather than a real identification (as
search_library is for a synthetic library), say so in both the description
and the result. Truthfulness of the result is a tested property.
Tests
- Add behavioural tests next to the module's existing tests (
tests/test_io.py, etc.). Tests exercise raw callables captured by theFakeMCPfixtures intests/conftest.py(io_tools,chem_tools,sim_tools,search_tools,qc_tools). - Update
MODEL_FOR_TOOLintests/test_tool_schemas.pywith the new tool and its validating model. - Update
EXPECTED_TOOLSintests/test_smoke_stdio.py; that set must match the registered surface exactly. - Add new tools to
WRITING_TOOLSin the schema test only if they mutate server-side state.
Checklist
- Module defines
register_tools(mcp)with the tool as a closure. - Every parameter has an
Annotated[..., Field(description=...)]. - Constraints appear on both the signature and the model.
ToolAnnotationsset, withopen_world_hint=False.- Module registered in
server.py. MODEL_FOR_TOOLandEXPECTED_TOOLSupdated.make testandmake lintpass.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

