one-tool
This server provides exactly one MCP tool, search_things, which searches THING by free-text query.
Search THING records using a free-text
query(required).Optionally set
limit(1–50, default 10) to control how many matches are returned.Results are returned newest first.
Returns an empty list when nothing matches — this is a valid result, not an error.
The server runs over stdio and can be used with Claude Code, Claude Desktop, or Docker.
It requires a
THING_API_KEYenvironment variable for live API calls; offline tests are included and need no key or network.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@one-toolSearch THING for 'onboarding' and show me the top 3."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
kit-one-tool-mcp
Most MCP examples show you the happy path and then fail on somebody's laptop at 401. This one is the opposite: one tool, a described schema, and 15 tests that are mostly the unhappy paths — missing key, 401, 403, 429, 503, DNS failure, non-JSON body, empty result.
Clone it, rename THING, and you have the shape of a working MCP server. It is a sample of what an
MCP Basic build from Kit looks like when it is handed over.
If you came here looking for a one tool MCP sample, an MCP server example in TypeScript, or a way to test an MCP tool with no API key and no network, this is that.
It is deliberately one tool. A second tool, or a Cloudflare Worker, is a Build Packet, not a bigger version of this.
Want your repo set up for Claude Code first?
This repo is MIT and complete — take it and go. If you want a CLAUDE.md, a tool allowlist and one skill wired for your repo:
Buy Setup Lite — $29 · ~24h, handed back as a PR.
Details: kit.sdvsignal.com/#setup-lite · the same shape as this repo built against your API is MCP Basic $199.
Related MCP server: Things MCP
60-second start — no API key, no network, no Claude
git clone https://github.com/sdvsignal/kit-one-tool-mcp
cd kit-one-tool-mcp && npm install && npm testNo git? The same tracked tree ships as one archive on every release:
latest release. Unzip it, then the
same npm install && npm test.
15 tests, all offline. Three of them stand up a real MCP client against the real server over an in-memory transport and call the tool, so the wiring is tested, not just the function. If those pass, the server works — you have not needed a key yet.
Add it to Claude Code
Today, this is the one that works. Clone it first, then point Claude Code at the local file:
git clone https://github.com/sdvsignal/kit-one-tool-mcp
cd kit-one-tool-mcp && npm install
export THING_API_KEY=...
claude mcp add kit-one-tool -- node "$PWD/src/index.js"Or by hand in .mcp.json, using the absolute path to where you cloned it:
{
"mcpServers": {
"kit-one-tool": {
"command": "node",
"args": ["/absolute/path/to/kit-one-tool-mcp/src/index.js"],
"env": { "THING_API_KEY": "..." }
}
}
}Once it is on npm
@sdvsignal/kit-one-tool-mcp is not published yet, so the two commands below will fail with a
404 if you try them today. They are here so you know what the install becomes, not so you can run
it now:
claude mcp add kit-one-tool-mcp -- npx -y @sdvsignal/kit-one-tool-mcp{ "mcpServers": { "kit-one-tool-mcp": { "command": "npx", "args": ["-y", "@sdvsignal/kit-one-tool-mcp"] } } }Registry name: io.github.sdvsignal/kit-one-tool-mcp (see server.json).
Claude Desktop instead: add this to the config file and restart the app.
{
"mcpServers": {
"one-tool": {
"command": "node",
"args": ["/absolute/path/to/one-tool-mcp/src/index.js"],
"env": { "THING_API_KEY": "..." }
}
}
}Your key lives in your environment. It is not in this repo, and there is no default value that quietly works.
Run it in a container
Same one tool, same stdio, nothing listening on a port:
docker build -t one-tool-mcp .
docker run --rm -i -e THING_API_KEY=... one-tool-mcp-i matters — the server talks over stdin/stdout, so without it there is nothing to talk to. To
point Claude Desktop at the image instead of at node, use "command": "docker" with
"args": ["run", "--rm", "-i", "-e", "THING_API_KEY", "one-tool-mcp"].
Smoke prompt
Type this to Claude. This is the test that it is really wired up:
Search THING for "onboarding" and show me the top 3.
You should get up to 3 results with names and ids. If nothing matches you get No THINGs matched "onboarding", which is correct and not a failure. Telling the model that an empty result is empty is most of why it stops retrying.
What is in here
File | What it is |
| The one tool. Takes its dependencies as an argument, which is why it is testable without a key. |
| Server wiring. Registers exactly one tool. |
| The entrypoint. Connects stdio and nothing else. |
| The 15 tests above. |
| Builds the image above. Copies the lockfile and |
Errors you may see
Message | Means |
| env var missing, or Claude was not restarted after you set it |
| wrong or revoked key |
| wait, then retry |
| their side, not yours |
| network, or |
| usually an HTML error page from a proxy |
None of them return a stack trace. A tool that throws raw errors at the model makes it guess.
Remove it
claude mcp remove one-toolClaude Desktop: delete the one-tool block and restart. The server keeps no state, so nothing is left behind.
Making it yours
Rename
search_thingsfor what it actually does, from the caller's point of view.Write the input schema before the implementation. Every field described, required vs optional explicit.
Keep the description aimed at the model: say when to reach for the tool, not only what it is.
Point
THING_BASE_URLand the auth header at the real API.Run
npm test, then run the smoke prompt in Claude. A passing test is not proof the tool works against the real API.
You did not want to build one, you wanted eight wired
Half the people who land here from an MCP directory are not building a server — they want the common ones connected, and they hit the same wall every time, which is the JSON rather than the server.
MCP Config Pack — $49 is eight ready configs (filesystem, GitHub, Postgres, context7 and four more), each with the smoke prompt and the pass condition that tells you it is actually connected rather than merely listed. Offline, no telemetry, instant download. Two of the eight need no token at all, so you can prove the wiring before you go near a credential.
Details and the full list: kit.sdvsignal.com/#mcp-config-pack. If you would rather have them wired into your repo alongside hooks and skills, that is Setup Sprint $99, not this.
Free here vs. paid
This repo is MIT and complete — the tool, the tests, the error table, the removal path. Nothing is held back. If you are building your own MCP server, take it and go.
Paid is the same shape built against your API and tested against it before delivery, which is the part the offline tests above deliberately cannot do: MCP Basic $199 — one tool, the schema, handoff notes, a smoke prompt and the enable/disable path. Need more than one tool, or a Worker? Build Packet $399. Just want the repo itself set up for Claude Code first? Setup Lite $29 (back as a PR in 24h) or Setup Sprint $99 (48h). Just want other people's servers connected? MCP Config Pack $49, above.
Shipping an iOS app on top of it? Preview Pack $149 is one App Store preview video to Apple's spec, 5 stills and 2 revision rounds, in 72 hours.
→ Scope and order: kit.sdvsignal.com
We use AI tools including Claude; a person reviews every deliverable before it ships. Independent project, not affiliated with Anthropic.
Questions
Writing your first tool description, or want a second read of one? Paste it in Discussions. Real answers, no signup.
Related
kit-claude-code-starter — the full Claude Code setup (CLAUDE.md, allowlist, 3 skills), free
kit-plugins — the same skills as installable Claude Code plugins
kit-ios-worker-template — StoreKit 2 verification on a Cloudflare Worker, with failure logging
License
MIT licensed. Use it for your own work, no attribution needed.
Available Tools
1 toolsearch_thingsSearch thingsA
Search THING by free-text query. Use when the user asks what THINGs exist, or asks about a THING by name. Returns up to limit matches, newest first. Returns an empty list when nothing matches, which is not an error.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | How many to return, 1 to 50. Defaults to 10. | |
| query | Yes | Free-text search. Required. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses useful behavioral traits beyond the schema: returns up to `limit` matches, newest first, and returns an empty list when nothing matches (not an error). However, with no annotations provided, the description carries the full burden, and it doesn't mention whether the operation is read-only, whether results are paginated beyond the limit, or any authentication requirements. The disclosed behaviors are valuable but not exhaustive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with zero waste. The core purpose is front-loaded, and each sentence adds distinct information: what it searches, when to use it, and key behavioral details. No redundancy with the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple 2-parameter search tool with no output schema, the description covers the essential behaviors: result ordering, limit semantics, and empty-result handling. It doesn't describe the return format, but with no output schema and a simple search tool, the description is largely complete. The only minor gap is not explicitly stating the operation is read-only, but the description's wording implies a non-destructive search.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents both parameters. The description adds the meaning of `limit` (up to `limit` matches) and the behavior of an empty result, but doesn't add syntax or format details beyond what the schema provides. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Search') and resource ('THING') and clarifies it is free-text query-based. It distinguishes the tool's purpose by explaining what user intents it serves ('what THINGs exist', 'asks about a THING by name'), though it doesn't name sibling tools because none are provided.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context for when to use the tool: when the user asks what THINGs exist or asks about a THING by name. It doesn't explicitly state when not to use it or name alternatives, but with no sibling tools provided, the usage context is reasonably complete.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
1 tool update
v0.1.0- First observed
search_things
TDQS
Scored across 1 tool
With only one tool, there is no possibility of confusion between tools. The single tool's purpose is clearly defined, so an agent cannot misselect it.
The one tool name follows a clear verb_noun pattern (search_things) in snake_case. With only one tool, there are no conflicting conventions to create inconsistency.
A single tool is borderline thin for a server, but the tool itself is nontrivial and serves a focused search purpose. It does not warrant the 'too few' or 'trivial' lower scores, yet it lacks the breadth of a well-scoped 3-15 tool server.
The server only offers search, with no way to retrieve a specific THING by ID, create, update, or delete. This leaves significant gaps if the domain is intended to cover management of THINGs, making the surface incomplete.
Maintenance
Related MCP Connectors
Search the Claudeers registry of Claude tools, ranked by maintenance and community signals.
Search the HeyClaude directory of Claude Code agents, MCP servers, skills, and tools.
Search verified Claude Code plugins and skills; fetch portable SKILL.md sources. Read-only.
Provides metadata information to AI agents through the search API.
Related MCP Servers
- AlicenseBqualityDmaintenanceFacilitates web search capabilities using Perplexity's API, allowing users to retrieve search results through Claude's interface.18MIT
- AlicenseBqualityDmaintenanceEnables Claude to interact with Things 3 on macOS, allowing users to create, update, and manage to-dos and projects, list tasks, search items, and navigate through Things lists using natural language.2013 npm17ISC
- AlicenseBqualityDmaintenanceExposes the Synthetic API as an MCP tool to enable web searching within Claude and other compatible applications. It provides formatted search results including titles, URLs, and text snippets for enhanced model context.122 npm22MIT
- AlicenseBqualityDmaintenanceEnables Claude to interact with Things 3 task management, allowing creation, analysis, and management of tasks, projects, and tags via natural language.22MIT