Smart Tool
A local MCP server that gives coding agents (Claude Code, Codex) cheaper, sharper tools than their built-in search:
Power your agent
คำสั่งของผู้เผยแพร่เอง ไม่ใช่เอนด์พอยต์ของ PlugMCP
Host a copy with our keys and logs.
npx -y @allansantos-dev/[email protected]Claude Code ไม่มีลิงก์ติดตั้งสำหรับคำสั่งแบบโลคัล ให้คัดลอกคำสั่งด้านล่างแล้วรันในเทอร์มินัล
claude mcp add allansantos-dev-smart-tool -- npx -y @allansantos-dev/smart-tool@0.9.75รันในเทอร์มินัล
{ "mcpServers": { "allansantos-dev-smart-tool": { "command": "npx", "args": [ "-y", "@allansantos-dev/[email protected]" ] } }}claude_desktop_config.json
URL แบบรีโมตหรือคำสั่งบนเครื่องของคุณ? การติดตั้งสองแบบต่างกันอย่างไร
รันบน PlugMCP
A new server you create. It is not this listing's official endpoint. Use the publisher install when you want their URL and their credentials.
เปิดจากผู้เผยแพร่
A local MCP server that gives coding agents (Claude Code, Codex) cheaper, sharper tools than their built-in search:
Local MCP server that gives coding agents (Claude Code, Codex) cheaper, sharper tools than their built-in search. Windows.
smart_search / smart_search_result | Semantic + lexical search over an indexed project, results split into code, tests and docs, with the likeliest functions per chunk |
smart_scout | Answers a question about the code with the lines that answer it: reads the candidate files inside Smart Tool and returns path:lines with the literal text, so the files never enter the agent's context; with a scout_model, a small model also writes a short answer and keeps only the lines that support it; a question about why something is as it is (why, reason, decided) also lists up to three decision notes from the notes the project keeps about its intent, as ids with one excerpt each |
web_search / web_search_result | Web search across several sources in parallel, in the query language and in English, with a cache shared across sessions; depth="research" runs a multi-round research loop |
web_fetch | Reads a known URL and returns only the answer to your prompt, written by a small model; pages are cached for 24 h. Pages over 60,000 characters are not cut: the model reads the parts closest to the prompt (needs an embedding_model) |
project_manage | Registers and indexes projects, shows coverage, code maps, duplicated functions and index storage; graph with symbol tells what changing a function touches: callers, calls, the tests that reach it and the files that import it |
Agents that must click, type or log in also get Microsoft's Playwright MCP,
registered as the playwright server where this machine lets a browser be driven (see Set up, step 3).
An optional hook routes the agent's native Grep/Glob/Read/Bash/WebSearch/WebFetch calls to these tools when they are cheaper, or just tells the agent what Smart Tool would do.
Status: 0.9.43 beta. Windows only. What changed in each version: CHANGELOG.md.
A coding agent normally finds code by running grep over the whole project and reads the web by downloading whole
pages. Both fill its context with text it does not need, and every token of it is paid for. Smart Tool is a small
program that runs on your machine and offers the agent better tools for the same jobs, through
MCP, the standard way agents call outside tools.
Claude Code / Codex ──MCP──▶ Smart Tool daemon (127.0.0.1, one per machine)
├─ smart_search ──▶ local index of your project (SQLite)
├─ smart_scout ───▶ the files behind a search, read on disk (small model optional)
├─ web_search ───▶ several search engines at once, shared cache
├─ web_fetch ────▶ the page, read by a small model
└─ project_manage
your model gateway (OpenAI, OpenRouter, Ollama...) ◀── embeddings and small chat calls
Searching code. When a project is registered, a small model looks at its folder structure once and decides what is worth indexing (source, tests, docs; not build output or dependencies). Each file is cut into chunks of up to 200 lines, and each chunk gets an embedding, a list of numbers that captures its meaning. A search runs two ways at once, by meaning (embeddings) and by exact words (SQLite full-text search), merges the two lists and, if you set a rerank model, reorders the best candidates. The agent gets back a few chunks split into code, tests and docs, with the functions most likely to matter, instead of every line that contains a word. The index follows the project: only files whose content changed are processed again, and each Git branch keeps its own view.
Reading code to answer a question. smart_scout takes a question in plain language. It finds the candidates the
same way as smart_search (or by keyword on disk while there is no index yet), reads the current lines of each one
and keeps, per file, the window with most of the question's words. The agent receives path:lines and those lines
verbatim. With a scout_model (the setup screen fills it with Claude Haiku 5.5 when the gateway has it), a small model reads those windows, writes a few lines of answer
and picks which lines to show; without an index it first picks the words and folders to scan (two calls; one with an
index). What the model writes never replaces the literal lines, and when it fails the lines come back with the error.
Searching the web. web_search asks several free search sources in parallel (DuckDuckGo, Wikipedia, Yahoo,
Exa, Google and others), in the language of the question and in English, and merges what comes back. Search APIs with a
free quota (Tavily, Firecrawl) and a real browser are tried only when those results are not enough. Answers are cached and shared by every agent
session on the machine, so the same question asked twice costs nothing the second time.
Reading a page. web_fetch takes a URL and a question. It downloads the page over plain HTTP; when the page only
shows its content with JavaScript, it opens it in a headless browser (Moli
first, Chromium as the fallback), which never reaches this machine or your local network. PDFs are read as text, page
by page. A small model then reads the page and returns only the answer, with the source.
The agent receives a paragraph instead of the whole page.
Steering the agent (optional hook). Agents keep reaching for their built-in tools out of habit. The hook sees each call before it runs: a content search over a project folder is stopped and the agent is told the exact Smart Tool call to make instead; reading a known file, or anything else, runs as usual. The same hook can remind the agent to document functions it edits and warn when it writes a function that already exists in the project.
What stays local. The daemon, the indexes, the caches and the logs live on your machine. Text leaves it only to reach the model gateway you chose (for embeddings and the small model calls) and the web search sources. With a local gateway such as Ollama, nothing about your code leaves the machine.
npx. Python is not needed: the installer brings its own.npx @allansantos-dev/smart-tool@latest install
Updates install themselves, on by default: the tray checks npm when it starts (at logon) and every 24 h, and when there
is a newer version it runs this same command in a visible console (once per version; a failed version is tried again
after 24 h, with the previous version kept). You are told each time: a Windows notification from the tray (newer version,
updating, updated, update failed), and agent sessions get the same line on their first smart_search (and at session
start when the SessionStart report is on, shown to you too) with the link to the changes. The tray menu has "Update to
X" (or "Check for updates") on demand and an "Update automatically" switch; SMART_TOOL_AUTO_UPDATE=off also turns
automatic updates off, and the newer-version notice then carries the command to run. Running the command by hand also updates; ~/.smart-tool is kept. It downloads uv (checksum
verified) and a private Python 3.12 into ~/.smart-tool/runtime, with nothing added to PATH and, in the registry, only two per-user (HKCU) keys that make the notification buttons work, then
copies Smart Tool to %LOCALAPPDATA%\Programs\SmartTool with its own virtual environment,
installs the web runtime, registers a per-user Scheduled Task that starts the tray at logon and starts the daemon on
http://127.0.0.1:8765 (another free port is used, and announced, if 8765 is taken).
State lives in ~/.smart-tool: config.json, your model adapters in adapters/ and indexes, caches and logs in
data/. Secrets (API keys) are encrypted with Windows DPAPI for your user.
The model calls that must return JSON (the deep-research steps, smart_scout, the freshness check of cached
searches, the router's tier and sufficiency decisions, the index profile and the block-pattern review) use the model's structured output instead of a forced tool call: the request carries the JSON Schema, never
temperature, and the answer is validated against the schema before use. A stop other than a normal one (cut at the
token limit, refusal), an empty answer, a missing field or a value outside an enum fails the call with its reason
instead of passing as an empty result. The structured_output object of config.json chooses the format:
mode is auto (default: output_config for the models whose route, the id prefix before the first dot, is in
output_config_routes, which is ["vertex_ai"] by default; response_format, applied on every gateway route, for all
others, Bedrock included), response_format or output_config; output_config for a route outside the list is
refused. unsupported_keywords lists the schema keywords the gateway does not apply (maxItems, minLength...); they
are left out of the request and the code that reads the answer keeps enforcing them.
Open the setup screen from the tray icon ("Open settings") or at http://127.0.0.1:8765/setup. It opens on
Overview: everything Smart Tool needs, checked on this machine, with what needs you first and a button that takes
you to the fix. The side menu groups the rest under Connect (Agents, Models, Web search), Behavior (Agent rules,
Redirects) and Maintenance (Setup audit, Startup).
Model gateway: pick an adapter and fill its fields. The built-in OpenAI-compatible adapter takes a base
URL ending where the API starts, like the OpenAI SDK base_url (https://api.openai.com/v1,
https://openrouter.ai/api/v1, http://localhost:11434/v1), and an optional API key. Saving tests /models first.
Models: embedding, rerank (optional; without it results use the hybrid order), the router model (small, no
reasoning: web search tier order and result checks), the index classification model (also reviews block patterns), the
scout model (the short answer of smart_scout) and the research model. Any id the gateway accepts works; the catalog is
shown as suggestions. Empty roles are filled with the recommended models the gateway offers.
When a new version recommends other models than the ones you use, a Windows notification (Apply now, Don't show again) and the New recommended models card on this page offer them: nothing changes until you apply, the models you had are kept, and Switch back to my previous models undoes it. The Model failures (last 24 h) table groups the failed gateway calls by type (429, 503, other 5xx, timeout, connection, authentication) and role, with the count, the first and last time and one sample, and shows the calls per purpose; a model that fails half of its calls (5 or more) also raises a notification and a tray alert. A failure inside a tool call also comes back as a warning line in the tool answer; calls made by a hook or by background work (index scope and profile, block-pattern proposals) have no answer to carry it, so they show only in the table, the log and the notification. The local embedder is not in that table or in the usage meter: it is a sidecar on your machine with no price, and its state is the Local models section.
Agents: register the MCP server in Claude Code or Codex (runs their official mcp add command), install the
hook and choose its behavior under Agent rules. A hook written by an older Smart Tool shows as outdated, with
what an update changes; updating previews the entry and rewrites only Smart Tool's, after a backup.
Browser control comes with the registration, and with every update for clients where smart-tool is registered:
the official Playwright MCP (pinned in web_adapters/node) is registered as the playwright server, driving the
Chromium Smart Tool installs, headless, with an isolated in-memory profile (no logins of yours) and its files in
~/.smart-tool/data/playwright-mcp. Before registering, Smart Tool starts that server and opens a blank page as an
agent would; where that fails (a corporate policy that forbids remote debugging, a missing browser) nothing is
registered, agents keep reading pages through web_fetch, and the setup screen shows the reason with a retry
button. Pages the agent opens are treated as untrusted: tools a page registers (WebMCP) are never exposed, the
browser cannot open Smart Tool's own pages (every request it makes carries a header the daemon refuses), and
browser_run_code_unsafe, which runs arbitrary JavaScript in the server process, is denied in the client
(permissions.deny in ~/.claude/settings.json, disabled_tools in ~/.codex/config.toml); if it cannot be
denied, the server is not registered. A playwright server you registered yourself is never touched. Remove it with
claude mcp remove playwright -s user / codex mcp remove playwright.
The hook behaviors:
smart_search for a search, web_fetch for WebFetch, web_search for WebSearch
(without allowed_domains/blocked_domains). In Claude Code a PostToolUse entry swaps the output (WebFetch and
WebSearch still run natively, their result is replaced); a shell search whose answer is ready within 10 s runs as a
no-op instead, so a grep with no match does not end in exit 1. In Codex the shell search is rewritten to print the
answer from a file. Coexistence with other PreToolUse hooks on Bash: they run in parallel on the same original
input and the host documents no order between their updatedInput. The Smart Tool rewrite is a constant (true /
$null, whatever the search), carries no permission decision (a rival deny/ask still wins) and only applies to a
content search, so a hook that rewrites other commands never meets it; if a rival rewrite of the same search wins,
its command runs and the PostToolUse still swaps the output for the answer. Two other hooks rewriting the same command
must be resolved in the plugin that owns them (the setup audit lists them). When the Smart Tool call fails or is late, the native call and its output stay as they are; a
deny, with the exact call to make, is left only for a search whose query cannot be read from the command. The
decision is a fixed rule, under a millisecond and the same every time: a content search over a project folder (grep -r,
rg, git grep, the Grep tool on a folder) or over more than 20 listed files goes to smart_search, in Bash and
PowerShell alike and also when it is wrapped (bash -c, powershell -Command, timeout, a subshell), looped
(for f in src/*.py), fed by a listing (find -exec grep, xargs, Get-ChildItem | Select-String) or written
as an inline python/node script that walks a folder and matches text; reading or searching known files,
listings, Glob and commands that change files run. The setup screen counts the redirects and what each session
did next. With Block patterns proposed by a
model on (default), the scope model reviews, in the background, bulk reads the rule could not measure and
proposes regex patterns, each checked against the logged calls; a pattern redirects only after you accept it.Documentation on edit checks the public functions an edit touches (Python docstrings, JSDoc, Javadoc), in
Claude Code edits and Codex patches. Private (_name, #name, private), nested and override (@Override,
@override) functions are exempt, as in pydocstyle, eslint-plugin-jsdoc and Checkstyle, and a JSDoc above a set of
TypeScript overloads documents the implementation:
A documented function edited only in its body is not mentioned. project_manage with action=docs lists the
public functions still without a docstring, for documenting a project that started without them.
Dependency check on edit: an edit of package.json, requirements*.txt or go.mod that adds or changes a dependency lists the OSV advisory IDs of up to 5 of them (exact version, or the lower bound of ^, ~, ~= and >=), answered from a 6 h disk cache or one 2.5 s batch call that sends only package names and versions; when OSV cannot answer, the reminder says the check was skipped and the edit goes on. dependency_mode in config.json: warn (default) or off.
PDFs inside a project are indexed as text with [page N] markers (20 MiB, 300 pages and 20 s per file; a scanned, password-protected or corrupt PDF is skipped with the reason), so smart_search returns the page that holds a passage. Presentations and workbooks (.pptx, .xlsx) are indexed the
same way: text of each slide under [slide N] with the speaker notes under [notes N], each sheet under [sheet NAME] with one
tab-separated line per row (cached formula values; 100,000 rows or 1 MiB of text at most). Older formats (.ppt, .xls,
.xlsm) are not read.
Block patterns waiting for you are shown in one approval panel: 8 per page, the ones that would have blocked the most logged calls first, a filter over pattern, reason and example, and bulk accept or reject of the selected rows; each row opens to its reason and example.
Duplicate functions on edit compares the functions an edit writes with the indexed code. Warn (default) tells the agent when a written function has the same body as an existing one (comments, spacing and docstrings ignored) or a near-identical one (only local names, strings and numbers changed), with the path and lines of the original to reuse; it never blocks. Editing a function in place, overloads, tests, generated files and small functions (under 5 lines or 50 tokens) are not checked. Off disables it.
After editing, project_manage with action=affected_tests lists the tests to run: every test file that imports a
changed file, directly or through other files (git diff against base, default HEAD, untracked files included),
plus changed tests and tests using a pytest fixture whose conftest.py imports the changed code, ordered with the
likeliest failures first, and the command to run them. Changed files are read from disk, so new files and imports
count before the project is reindexed. run_all is true, with
the reason, when a configuration or lockfile changed or a changed code file is outside the import graph. Go is read
by package: a file that imports a package depends on every file of it, so a changed package selects the tests of every
package that imports it (go test ./pkg ...); the Go and Rust documentation and duplicate hooks stay silent.
project_manage with action=setup_audit and a project_root (or python setup_audit.py --project <folder>)
reports what Claude Code and Codex actually load for that folder (settings layers, enabled plugins of both,
hooks, MCP servers, skills, CLAUDE.md and AGENTS.md) and where they collide: several hooks deciding on the same tool in
parallel, hook scripts that do not exist or hide their errors, hooks calling an MCP server that is not configured,
MCP servers that do not start or offer the same tools twice (a gateway re-exposing a server also registered
directly), skills sharing a name or over the description budget, an AGENTS.md only Codex reads, broken @imports
and a Codex instruction chain over 32 KiB. Each finding links the documentation it relies on; nothing is edited,
env and header values never enter the report, and what could not be checked is listed as not verified. A second
run shows what is new and what was resolved. The daemon also runs it on its own for every registered project,
two minutes after it starts and then every 30 minutes (MCP servers shared by several projects are contacted once
and their result reused for 6 hours; Run now always contacts them again), and the setup screen's Setup audit
panel shows each project's last report: findings by severity, what is new, what was resolved, the tokens each MCP
server's tools cost and what was not verified. When a scheduled run finds new errors or warnings, a Windows
notification from the tray names the folder and up to three of them, once per finding, with a button that opens the
panel; manual runs and info findings stay silent.
The agent hears about it without asking for it. setup_audit with mode=last returns the stored report for the
folder (or the nearest audited parent) without auditing again, and fails with what to do when none is stored. On
its first smart_search of a session, and once per folder, the agent also gets one short line (under 100 tokens)
when the stored report holds errors or warnings; a clean report adds nothing. Optionally, Report at session
start on the Setup audit page (Claude Code or Codex) moves that line to the start of every new session: it
previews the exact SessionStart entry, adds it to ~/.claude/settings.json or ~/.codex/hooks.json only after you
confirm (backup first), and Turn off removes only that entry. Codex runs a new hook only after you approve it in
/hooks; until then the page shows "waiting for your approval" and the search keeps repeating the line. It is off by default; while it is on, the search no longer repeats the line. The
hook script (hooks/session_audit.py) only reads the stored report from the running service and prints nothing
when the service is down.
Local models (optional): if the mcp-memory embedding sidecar is installed on the machine, its local embedder can serve as a fallback (or preferred) embedding model.
Web search providers work without keys on their free public tiers; add your own key for more volume. Set your own contact (e-mail or URL) if you want public APIs such as Wikimedia to see it in the User-Agent.
An adapter is a Python file in ~/.smart-tool/adapters/. It appears in the setup screen next to the built-in one.
import json
import urllib.request
NAME = "my_gateway" # unique id
LABEL = "My gateway" # shown in the setup screen
FIELDS = ( # rendered as inputs; secret values are stored with DPAPI
{"name": "url", "label": "Address", "required": True, "placeholder": "http://10.0.0.5"},
{"name": "token", "label": "Token", "secret": True},
)
def request(options, route, body=None, timeout=15):
"""route is OpenAI-style: models, model/info, embeddings, chat/completions, rerank. body None means GET.
Return (parsed JSON, response headers); let urllib.error.HTTPError propagate."""
data = json.dumps(body).encode() if body is not None else None
headers = {"Content-Type": "application/json"}
if options.get("token"):
headers["Authorization"] = "Bearer " + options["token"]
req = urllib.request.Request(f"{options['url']}/v1/{route}", data=data, headers=headers)
with urllib.request.urlopen(req, timeout=timeout) as response:
return json.load(response), response.headers
def verify(options):
"""Raise RuntimeError with a reason a person can act on."""
request(options, "models", timeout=10)
Embeddings and chat use the OpenAI request and response formats; rerank uses the Cohere/Jina format served by
LiteLLM ({"model", "query", "documents", "top_n"} returning results[].index and relevance_score). A file that
fails to load is listed in the setup screen with its error and does not affect the others.
NOTICE. Their free tiers are rate limited per IP address; respect
each service's terms of use.~/.smart-tool/data and never leave the machine. That includes the model failure log
(model, role, tool and the error text, up to 300 characters, which can carry the gateway's error body; never the request).Turn off "Start automatically" in the setup screen, quit from the tray, remove the hook entries from
~/.claude/settings.json / ~/.codex/hooks.json (the setup screen shows them), run claude mcp remove smart-tool -s user / codex mcp remove smart-tool, then delete %LOCALAPPDATA%\Programs\SmartTool and ~/.smart-tool. Turning off "Start automatically" also removes the
two per-user registry keys of the notification buttons (HKCU\Software\Classes\smart-tool-action and
HKCU\Software\Classes\AppUserModelId\SmartTool.Notifications); they come back the next time a notification is shown.
Apache License 2.0. See LICENSE and NOTICE for third-party components.
Local MCP server that gives coding agents (Claude Code, Codex) cheaper, sharper tools than their built-in search. Windows.
{ "mcpServers": { "allansantos-dev-smart-tool": { "command": "npx", "args": [ "-y", "@allansantos-dev/[email protected]" ] } }}เครื่องมือ
ยังไม่มีรายการเครื่องมือ เซิร์ฟเวอร์แบบรีโมตจะได้รายการหลังการตรวจสอบสถานะครั้งแรก
FAQ
คัดลอกคอนฟิก stdio สำหรับ Cursor, Claude Desktop, Claude Code หรือ VS Code ได้ในหน้านี้ คอนฟิกนี้ใช้การติดตั้งของผู้เผยแพร่ ไม่ใช่พร็อกซีของ PlugMCP
ระเบียนนี้ไม่ได้ระบุตัวแปรสภาพแวดล้อมที่จำเป็น
@allansantos Dev/smart Tool ทำงานแบบโลคัลผ่าน stdio
ตรวจสอบล่าสุดเมื่อ 2026-11-14 Local MCP server that gives coding agents (Claude Code, Codex) cheaper, sharper tools than their built-in search. Windows.