MCP & tool configuration for coding agents
The Model Context Protocol turned coding agents into something closer to an operating system. An agent no longer just writes a function — it opens terminals, runs shell commands, installs packages, calls APIs, and reaches into databases through a growing pile of MCP servers. The recurring pain isn't the model. It's everything around it.
New MCP servers ship every week with permissive, demo-grade defaults that are fine for a prototype and dangerous once an agent can read your filesystem. The integrated terminal the agent runs in doesn't load the same PATH or aliases as your real shell, so it picks the wrong node or the wrong DATABASE_URL. Every tool — Claude Code, Cursor, Copilot, Cline, Windsurf, Gemini — reads its rules from a different file, and those files quietly drift across tools and repos until nobody knows which policy is actually in force. And when the agent finishes, there's rarely a trail of which server it called, which command ran, or which file changed.
These are configuration and setup problems, not intelligence problems. This page collects the questions developers keep asking about setting up and hardening MCP and tools for coding agents — with concrete, tool-agnostic answers.
An MCP server has shell access to my whole machine — how do I lock it down without an enterprise security program?
Most MCP servers are prototypes with permissive defaults: fine for a demo, dangerous once an agent can read your filesystem. The failure modes are concrete — silent data exfiltration, an agent running rm -rf somewhere it shouldn't, or API keys ending up in someone's training data. You don't need a SIEM or a threat-model document. Five protections cover solo scale and take about 30 minutes:
- Sandbox untrusted servers. If you can't read every line of a server, it doesn't get host access. Run it in Docker (or a VM/LXC). A baseline is
docker run --rm --network=none --read-only --tmpfs /tmp -v $(pwd)/sandbox:/data <server>. Turn off networking for anything that doesn't legitimately need it; allowlist specific hosts for the ones that do. - Use a tool allowlist, not a denylist. Agents default to "call anything." List the tools you've actually vetted by name, and add a new server's tools one at a time — never a whole namespace via wildcard.
- Move secrets out of the env your agent can see. If the agent has shell access it can read
.env. Fetch secrets at runtime from a secret manager (export TOKEN="$(op read ...)") so nothing sensitive lives in the repo or the environment file. - Log every tool call locally.
teeMCP output to a timestamped file. When a run feels off, yougrepthe log; when it is off, you have evidence of what triggered it. - Keep a kill switch. One alias that
pkills every agent and stops MCP containers, for when a prompt injection from a web page sends an agent off the rails.
The full setup takes about 30 minutes; maintaining it costs roughly a minute per new tool. Skip the enterprise-flavored advice — the right question at solo scale is "what would I regret skipping?"
How 1DevTool solves this
How 1DevTool handles this: MCP Settings gives each project an explicit list of MCP servers and the tools they expose, so you're configuring an allowlist instead of inheriting "call anything," and the Environment Manager keeps per-project secrets out of the shared env an agent can read. See MCP Settings.
MCP made agents way more capable — but how do I know which servers are actually safe to install?
MCP solved capability and created a supply-chain problem. When a citation-verification server, a curated DevOps/SRE list, and an AI gateway for provider fallbacks all show up at once, the base model stops being the whole workflow — and every new server is code you're trusting with tool access. Two habits help.
First, separate trusted tools from experiments, explicitly. Keep a short list of servers you've vetted (ideally pulled from a curated or official catalog) apart from the ones you're just trying out, and don't let an experiment quietly inherit the same permissions as a proven tool. A new server on your machine is a new thing that can edit files, call APIs, or spend budget.
Second, treat verification as a workflow primitive, not an afterthought. Before a server's output becomes part of your work, you want to see what server was invoked, what evidence it returned, and whether a deterministic check passed — not just a confident chat message. The agent's confidence is not evidence. This matters most where verification sits near execution: if a server can edit files, call APIs, or cite sources, the check has to happen before that output lands.
Routing records matter for the same reason. Provider changes affect quality, cost, and risk, so a later review should be able to see which model did the planning, which did the edit, and which verified the result. That compact trail of decisions — which server ran, what it returned, which check passed — is what lets AI-assisted work survive a handoff instead of being reconstructed from memory.
How 1DevTool solves this
How 1DevTool handles this: MCP Settings shows exactly which servers are configured and what tools each one exposes, and the One-Click MCP Diagnostic verifies a server actually connects and responds before you rely on it. See MCP Settings.
My AI editor's terminal doesn't have my aliases and says `nvm: command not found` — why, and how do I fix it?
This shows up in every editor's issue tracker: the integrated terminal's PATH differs from your normal terminal, aliases are missing, nvm use fails. It isn't a bug — it's which kind of shell the editor spawns. A shell is one of three types:
- Login shell — runs
~/.zprofilethen~/.zshrc(Terminal.app, most SSH sessions). - Interactive non-login shell — runs only
~/.zshrc(tmux panes, most editor terminals). - Non-interactive shell — runs neither (scripts, task runners).
If your nvm/pyenv/rbenv or PATH setup lives in .zprofile, an editor terminal that spawns interactive-non-login never loads it — so you see missing aliases and "command not found."
The quick fix is to force login mode. In Cursor/VS Code settings, add a profile with "args": ["-l"] and make it the default; for JetBrains set the shell path to /bin/zsh -l; for tmux, set -g default-command "${SHELL} -l".
The durable fix is putting setup in the right file: environment variables that need to exist everywhere in .zshenv, once-per-login setup in .zprofile, and everything interactive (aliases, nvm/pyenv init) in .zshrc — which every interactive shell loads regardless of login status. Verify with echo $PATH; type nvm in both Terminal.app and the editor terminal; the output should match.
This matters for agents specifically. Claude Code, Codex CLI, and Aider inherit the editor terminal's environment. Wrong PATH means the agent runs the wrong node; a missing direnv/env load means the wrong DATABASE_URL. You get bugs that look like AI hallucinations but are really environment mismatches — an agent making correct decisions from incorrect context.
How 1DevTool solves this
How 1DevTool handles this: its terminals run as login interactive shells by default (the -l flag), so .zprofile always loads and an agent terminal opened in a project has the same environment a real shell would. Per-project variables load explicitly through the Environment Manager, and you can manage your PATH from inside the app instead of relying on direnv magic.
Every coding agent reads its rules from a different file — how do I keep one source of truth across Claude, Cursor, Copilot, Cline and the rest?
The complaint is specific: Claude Code reads CLAUDE.md, Cursor reads .cursorrules, Copilot reads .github/copilot-instructions.md, others read AGENTS.md. Team instructions drift across Claude, Cursor, Copilot, Windsurf, Cline, and Gemini until no two tools carry the same rules. One developer built a sync tool (Nymor) specifically because agent rule files fragment this way and teams want one canonical source.
It's the same problem teams hit moving from single-user AI experiments to shared workflows: agent rules, MCP servers, prompts, and skills all have to line up across the team, or every person re-derives the setup from scratch. The durable pattern isn't picking one tool — it's keeping the rules, routing, and setup in one place and projecting them into each tool's expected file, so a change happens once instead of six times.
Two things make this worth doing early rather than late. Drift is silent: these files are read by tools, not humans, so a section that quietly disappeared two months ago produces wrong agent behavior with no error to catch it. And retrofitting costs more: once the setup has scattered — config in different files, context in dead chats, the "real" rules living only on one person's machine — you're reconstructing the workflow instead of improving it. Build the shared layer up front and a new developer starts from a known setup instead of reverse-engineering the last twenty prompts.
How 1DevTool solves this
How 1DevTool handles this: MCP Settings is one place to configure MCP servers and agents across Claude, Codex, and OpenCode, so the setup doesn't live in a different file per tool — OpenCode joining MCP Settings is an example of the same config surface absorbing another agent. See MCP Settings.
How do I stop my `CLAUDE.md` from silently drifting across all my repos?
CLAUDE.md files drift for four reasons: they're read by tools not humans (so breakage is invisible), they aren't quite "code" (reviewers skim them), they aren't quite "docs" (doc review doesn't apply), and they're template-like (people delete sections they don't understand). The drift is rarely a deletion you notice — it's the security section that quietly vanished during an unrelated change two months ago.
The fix is the same as for any team-wide standard: a CI check. Enforce only cross-repo policy — security ("never commit secrets"), forbidden actions ("no --no-verify", "no force-push to main"), branch/PR rules, the list of authorized AI agents — and leave repo-specific sections (architecture, test commands) alone. The minimal version is a bash script that greps for required section headers and required phrases and exits non-zero if any are missing, wired into a GitHub Action on pull_request.
For 10+ repos, don't copy the script everywhere. Keep the required list in one central policy repo and have each repo's CI curl it and compare — updating policy becomes a single PR that every repo picks up on its next run. Some teams prefer auto-fix (append missing boilerplate) over fail-on-missing; that works for identical boilerplate but not for sections needing repo-specific content, so fail-on-missing is the better default.
This matters more for AI than for humans. An assistant reads the file cover-to-cover and treats every line as authoritative, so a missing "no --no-verify" line means it will happily bypass your pre-commit hooks. A 30-line script in CI is the cheapest team-wide AI policy enforcement you can buy.
How 1DevTool solves this
How 1DevTool handles this: keeping rule files consistent starts with being able to see the one that's actually in play. 1DevTool surfaces each project's configuration folders, so the CLAUDE.md and agent rules in force are visible per project instead of buried. The CI enforcement itself lives in your pipeline; this is the per-project rule visibility that makes drift easy to catch.
How do I wire up MCP for a specific domain like Power BI — and actually see what the agent did with it?
Once you move past generic code generation, MCP setup gets domain-specific fast. A real example from the threads: making Claude useful for Power BI work through MCP — prompts, Skills files, semantic-model cleanup, DAX, and measure creation. But the setup is only half the job; the other half is trusting the result.
Domain work multiplies the action surface: shell commands, package installs, migrations, file deletes, network calls, generated credentials, and test runners that can mutate local state. A chat transcript can't be the control plane for that. Three things make a domain MCP setup usable.
Context has to be searchable, not just present. A big repo is full of old experiments, generated files, and stale docs; giving the agent file access isn't the same as giving it useful context. The workflow should show which folder, file, or prior decision is actually in play, so the agent doesn't spend budget rediscovering what you already know.
Guardrails belong around actions. Distinguish read-only inspection from destructive commands, make approval decisions visible, and let a project declare which tools are allowed and which steps need a human. The point isn't to slow the agent down; it's to stop confusing speed with permission.
Runtime proof beats a polished explanation. Logs, command output, test results, and a link between the final diff and the run that produced it. Without that trail, review turns into archaeology — and false progress (an agent looping the same search, or claiming a test passed without showing the command) stays hidden. The pattern generalizes past Power BI: any domain server you add needs searchable context, action guardrails, and an evidence trail before you can trust its output.
How 1DevTool solves this
How 1DevTool handles this: MCP Tool Activity Badges surface which MCP server a coding agent invoked and when, and AI Activity Logs keep the command output and tool-call record attached to the run — so a domain setup's actions are reviewable instead of invisible. Use MCP Settings to add the domain server itself.
I'm juggling plugins, MCP, and multiple models across tools — how should I route between models and keep the token bill sane?
AI coding has spread from one assistant into a messy toolchain: Claude Code plugins with hooks/MCP/skills, Cursor users tracking whether specific Anthropic models are even available in their IDE, and a broader shift from cloud/model-locked agents toward bring-your-own and local models. Routing everything through the strongest model makes cost unpredictable and feedback slow; routing everything through the cheapest pushes quality failures downstream into debugging.
The practical answer isn't a universal model choice — it's deciding, per task, which one deserves expensive reasoning and where proof of completion has to appear. Two realities make this a config problem rather than a taste problem.
Model switching alone doesn't fix bad execution. A cheap model repeating the wrong tool calls is still expensive; a strong model working from stale context still wastes time. You need to see where tokens, time, and retries are going before you can decide whether the model, the prompt, or the workflow is the bottleneck.
Provider churn shouldn't rewrite your setup. Speed changes, billing changes, and quota 429s all push from different angles, and none is solved by loyalty to one provider. You want a layer above the provider that remembers the project rules and lets you swap engines without changing the whole operating model.
Visible routing also makes model comparisons less theatrical. If you can see which model planned, which edited, and which verified — plus what each one cost — you judge a workflow by operational quality instead of by one impressive answer.
How 1DevTool solves this
How 1DevTool handles this: the AI Agent Orchestrator coordinates work across agents rather than locking you to one, and the AI Usage Dashboard shows where tokens and cost are actually going, so routing decisions are informed instead of guessed.
My coding agent keeps ignoring tool-call results and re-running the same tool — how do I stop the loop?
This is the failure that turns an agentic loop into an expensive no-op: the agent calls a tool, the tool returns a result, and the model acts as if it never arrived — repeating the same call, or answering from memory instead of the data it just fetched. One builder hit all of it at once writing a no-dependency Node/llama.cpp harness: attention drift, ignored tool results, and the same tool called on repeat. Four causes explain almost every case.
The result is buried in a bloated context. A filesystem read that dumps 40k tokens pushes the model's own question out of its effective attention window, so it 'forgets' what it was doing. This is exactly why one filesystem MCP server (SurgicalFS) added response budgets — cap and paginate tool output, and summarize large reads, so the result stays near what the model is actually attending to instead of drowning it.
The result isn't returned in the shape the model expects. If you hand a tool result back as a plain user string instead of a proper tool/function message tied to the originating call id, many models never register it as the answer to their call — so they call again. Return results as structured tool messages, matched to the tool-call id.
There's no dedup or loop guard. Cache identical calls within a run and return the cached value with a note; detect a repeated call signature and stop, rather than letting the agent burn tokens re-asking the same question.
You can't see it happening. Without a log of each call's arguments, its result, and whether the next step referenced that result, 'the agent ignored the tool' is a guess. Make the tool loop observable first — the fix is usually obvious once you can watch a result come back and get dropped.
How 1DevTool solves this
How 1DevTool handles this: AI Activity Logs capture each tool call's arguments and output attached to the run, and MCP Tool Activity Badges show which server the agent actually invoked and when — so a result getting fetched and then dropped is visible instead of a guess. For turning that visibility into enforced checks, see the sibling wiki page on agent guardrails and proof loops.
A Claude Code subagent came back with instructions I never wrote — can tool output, a fetched page, or an installed skill hijack my agent?
Yes, and it is worth separating from the question of whether an MCP server is safe to install. Install-time trust is about what a server can do to your machine. Prompt injection is a runtime attack: untrusted content the agent reads as data gets interpreted as instructions. The channels are everywhere an agent ingests text it did not author — a web page it fetches, the JSON a tool returns, a file in the repo, a README inside a dependency, the output of a subagent you delegated to. If any of that carries "ignore your previous instructions and do X," a naive agent may comply, because to a language model there is no hard boundary between the task and the material.
The sharp version people hit is the subagent that returns a payload instead of doing the work — a review subagent that comes back with embedded directives rather than a review, and the parent agent acts on them without ever making the tool calls it claimed. Nothing in a chat transcript makes this visible; you see a confident answer, not the injected instruction that produced it.
You cannot prompt your way out of this reliably, so treat it structurally:
- Keep untrusted content labeled as data. Fetched pages, tool results, and third-party files are inputs to reason about, never instructions to obey. The higher the privilege of the next action, the more suspicious an unexpected imperative in that content should be.
- Make tool calls and subagent returns inspectable. If you can see exactly which tools ran and what a subagent actually returned, an injected instruction that produced an out-of-band action stops being invisible.
- Vet what you install before it runs. Skills, MCP servers, and repos pulled from strangers are code and prompts you are adopting; scan them, read them, and prefer ones with a real source and history over a convenient copy-paste.
- Bound the blast radius. An agent that can be hijacked should still hit an approval gate before anything destructive, so a successful injection stalls instead of executing.
The model is easy to swap; the trust boundary around what it reads and runs is the part you own.
How 1DevTool solves this
How 1DevTool handles this: The Skills Browser runs security risk scanning on skills and servers you pull in from outside, so an injection hidden in a copy-pasted skill is flagged before it ever reaches an agent. MCP Tool Activity Badges surface exactly which tools an agent called during a run, so an out-of-band action triggered by injected content is visible instead of buried in a summary.
I installed an "official" AI coding tool from a search ad and got malware — how do I keep the toolchain itself from becoming the attack vector?
The AI tools gold rush created a perfect phishing surface. New CLIs ship weekly, everyone's used to downloading installers for tools that didn't exist last month, and attackers noticed: search ads that display a legitimate domain — a real-looking claude.ai link — while routing the click to a lookalike installer. One recent case ended with malware on the machine and a drained rewards account. The victim did nothing unusual; "search for the tool, click the top result" is how most people install everything.
The rules are old, but the reflexes need rebuilding for this ecosystem. Never install from an ad — type the vendor's domain yourself, or use a package manager where the publisher is pinned (npm, brew, an OS store) rather than a downloaded binary from a search result. Check what you're running before you grant it anything: a signed installer from the actual vendor, an official repository, a checksum when one is published. And remember that everything downstream inherits the compromise — a poisoned dev tool runs with your git credentials, your SSH keys, your browser sessions, and every token in your shell environment.
The same skepticism applies to the layers you bolt on after: MCP servers, agent skills, and plugins are executables with your permissions, not configuration. An unofficial "community server" for a popular service deserves the same scrutiny as an installer from an ad. If you suspect you've already run something dirty: rotate tokens first, then check shell rc files, MCP configs, and scheduled tasks for additions you didn't make — that's where persistence hides.
How 1DevTool solves this
How 1DevTool handles this: it can't vouch for an installer, but it shrinks the attack surface by making one workspace the place your existing, verified CLIs run — fewer one-off downloads per task — and it keeps receipts: activity logs and terminal recording give you a reviewable record of what actually executed, which is exactly what you want when you're deciding whether a machine is still trustworthy.
I've got separate fetch, search, crawl, browser and PDF MCP servers. They cost API keys and thousands of tokens of passive context, and the agent still hallucinates off a block page. How do I collapse that?
Two different costs are stacking here. The first is the context tax: every connected server's tool definitions sit in the prompt on every turn, whether or not you use them. Five research servers can be several thousand tokens before you ask anything — paid on every message, all session.
The second is worse: silent failure. When a fetch returns a Cloudflare interstitial or a consent wall, the agent gets text, and text looks like content. That's where confident summaries of pages nobody read come from.
What collapses it:
- Connect only what this project needs. Research tooling doesn't belong in a project that never leaves the repo. Per-project server sets beat one global pile.
- Escalate instead of specialising. Plain HTTP first; only fall back to a browser when the response is obviously a block or a JS shell. Most pages need no browser, and the escalation ladder replaces four separate servers.
- Normalise the output. One shape — URL, final URL after redirects, status, extracted text, and a flag for "this looked like a block page" — lets the agent reason about failure instead of summarising it.
- Make failure loud. A blocked fetch should return an error the agent can't mistake for content. This one change removes most research hallucinations.
- Measure the passive cost. Count the tokens your tool definitions occupy before the first message. It's usually the cheapest optimisation available and nobody looks at it.
How 1DevTool solves this
How 1DevTool handles this: the browser you already have is the fallback — live browser automation lets an agent drive the visible Browser panel with your existing session instead of adding another headless browser server, MCP settings keeps server sets manageable per project, and MCP activity history plus the one-click MCP diagnostic show which calls actually returned content and which quietly returned a block page.
I profiled my transcripts and found a dead MCP server injecting its schema into every request across all my worktrees, plus repeated reads of a 5,600-line file. How do I find and kill context bloat like this?
A dead MCP server is the worst kind of cost because it's invisible and constant: every request silently carries its tool schema whether or not anything ever calls it, and it does this across every worktree that inherited the config. You don't notice because nothing breaks — the bill and the context just run higher than they should, forever, until you go looking.
Profiling your own transcripts is exactly the right instinct; the fixes follow the findings:
- Audit what's actually in the context, per request. A schema for a server you never call is pure overhead. If a tool hasn't been invoked in months, its schema shouldn't be loaded — remove or disable the server, don't just ignore it.
- Kill config that propagated by inheritance. A zombie MCP entry copied into every worktree has to be removed at the source, or it returns on the next clone.
- Find the repeated large reads. A 5,600-line file read on every session is a context tax; split it, summarize it, or point the agent at the section it needs.
- Watch failed tool calls. Hundreds of failed invocations are retries you paid for; a tool that fails constantly is worse than one that's simply missing.
The theme is consistent: context bloat is rarely one big mistake, it's a dozen quiet ones that only a look at the real transcripts surfaces. Cache efficiency improves on its own once the dead weight is gone.
How 1DevTool solves this
How 1DevTool handles this: it makes MCP overhead visible instead of ambient — MCP settings and MCP activity history show which servers actually get called so a zombie is obvious, MCP tool activity badges flag idle servers, and the one-click MCP diagnostic surfaces a server that's loading schema but never running.
My hooks, skills, and MCP servers are scattered across config files and half of them silently do nothing. How do I validate the setup instead of discovering failures mid-run?
Agent configuration is executable behavior living outside your source tree, and it gets none of the checking your code gets. No compiler reads a hook definition. No test fails when a skill's allowed-tools list omits a tool that skill actually uses. The failure mode is silence: the hook never fires, the skill never triggers, the MCP server exits on startup, and the agent carries on as though everything is wired — producing work that looks fine and skipped the guardrail you thought you had.
The checks worth automating split into two groups.
Wiring — does this do anything at all?
- Hooks pointing at a script that doesn't exist, or a matcher that can't match any real event.
- Skills with no trigger, or an allowed-tools list missing a tool the skill's own instructions call.
- MCP servers declared but failing to start, and servers that start but expose zero tools.
- Duplicate definitions across global and project config, where precedence isn't what the author assumed.
Safety — what does this permit?
- Permission rules broad enough to auto-approve destructive commands, and allowlist entries a shell can trivially escape.
- Tool schemas whose descriptions carry instructions rather than descriptions — the injection surface people forget is a surface.
- Self-invoking skills and subagent definitions with no depth bound, which is how one review command becomes a hundred sessions.
- Secrets referenced by literal value instead of an env indirection.
The false positives that make this kind of check unusable are the stylistic ones — flagging a long prompt, or a permission that's broad on purpose. Keep the rules mechanical: something is unreachable, something is undefined, something is unbounded. Those are checkable facts, and they're the ones actually costing you runs.
How 1DevTool solves this
How 1DevTool handles this: the agent surface is inspectable instead of scattered — MCP settings put every server's config in one place, one-click MCP diagnostic tells you whether a server actually starts and what it exposes, MCP activity history shows which tools really got called, and skills browser with skills editor surfaces the skills that exist versus the ones that ever fire.
My MCP server works when I test it by hand and then fails inside Claude Code. How do I test it the way an agent actually calls it?
Manual testing exercises the path you designed. The agent exercises the protocol, and that's where the differences live.
Four gaps produce most "works locally, breaks in the client" reports:
- Transport and lifecycle. You test a function; the client launches your command as a subprocess, speaks JSON-RPC over stdio, and expects a correct initialize handshake. Anything your server prints to stdout that isn't protocol — a stray log line, a startup banner, a leftover debug print — corrupts the stream. Logs belong on stderr, always.
- The schema is the real contract. The agent doesn't read your README; it reads the tool schema and generates arguments from the description. Vague descriptions and loose types mean the model sends plausible-but-wrong input, so schemas need testing as specifications, not documentation.
- Failure paths, which are most of real usage. Happy-path testing skips the cases that dominate live runs: missing required fields, wrong types, IDs that don't exist, timeouts, oversized responses. An error the model can act on —
field 'path' must be absolute— recovers. A stack trace or a silent empty result sends it into a retry loop. - Response size. A tool returning 40k tokens technically works and practically breaks the session it's used in.
So build a harness that launches the real command, completes initialization, lists tools and asserts their schemas, then calls each tool with valid, invalid, and boundary input — asserting that failures come back as structured, readable errors rather than crashes. Run it in CI. The goal isn't coverage of your logic; it's proof that a model driving your server through the protocol can succeed, and can fail informatively when it doesn't.
How 1DevTool solves this
How 1DevTool handles this: you can exercise a server the way a client does and then watch what the agent really did — one-click MCP diagnostic verifies a server starts and enumerates its tools, MCP activity history and MCP tool activity badges show the real calls and returns, and the HTTP request builder covers the HTTP-transport case.
I want a coding agent to answer infrastructure questions across Grafana, NetBox, Kubernetes and our internal APIs. Do I wrap all of that in MCP servers?
Mostly no — and the instinct to wrap everything is what makes these copilots unusable. Every connected MCP server injects its tool schemas into every request, whether or not the task touches it. A handful of broad servers can cost tens of thousands of tokens before you type a word, and tool-selection accuracy drops as the menu grows. The question per system isn't "can I expose this?" but "does the model lack something it needs?"
Three cases, three different answers:
Tools with a well-known CLI — kubectl, the cloud CLIs, git, psql. The model already knows these far more thoroughly than your wrapper's schema will ever teach it. Give it a shell and let it use them. Wrapping kubectl in MCP spends context re-teaching something already learned, and adds a layer where your wrapper's bugs become the model's confusion.
Systems where the gap is organisational, not technical. Which service owns which host, what the naming convention encodes, which cluster is production, who gets paged. This is where curated context earns its keep, and it isn't a tool — it's a service catalogue, a compact document the agent reads. Most complaints of the form "the agent doesn't understand our infrastructure" are this, and no amount of extra API surface fixes it.
Genuinely idiosyncratic internal APIs with no CLI. Worth an MCP server: narrow, with a few purpose-shaped tools ("current alerts for service X"), not a generic HTTP passthrough that hands back 400KB of JSON for the model to parse in-context.
Then the property that makes any of this deployable: default operational access to read-only, with writes as a separate, explicitly granted path. An agent that can describe, correlate and diagnose is enormously useful and cannot cause an outage. The same agent with apply rights is a change-management problem. Keep those as different grants, not as different wording in a prompt.
Finally, attach evidence. An infrastructure recommendation without the query and timestamp behind it can't be verified and shouldn't be acted on — half the value here is that a human can check the reasoning against the same data. And keep token cost attributable per work item, or the copilot quietly becomes the most expensive way to read a dashboard.
How 1DevTool solves this
How 1DevTool handles this: the MCP layer is inspectable and prunable. MCP Control and MCP Settings let you enable only the servers a project needs instead of paying for all of them on every request, MCP Activity History reads back what your agents actually called — tool, status, duration, project, and a safe input/output preview, surviving app restarts — so a recommendation carries its evidence, and the One-Click MCP Diagnostic tells you which layer is broken instead of leaving you bisecting config. For the systems that keep their native CLI, SSH Manager and Remote SSH Projects put the agent on the host with the tools it already knows, and the Context Meter shows what your tool surface costs per turn.
Screen-aware assistants can now hand an agent screenshots, OCR text, and audio transcripts over MCP. Useful — but what stops it becoming an unbounded archive of everything on my screen?
The capability is real and the concern is the right one, because visual context has a property text context doesn't: it captures things you never chose to share. A screenshot taken to show a rendering bug also contains the notification that just arrived, the adjacent tab, the customer name in the window behind. Text context is what you pointed at. Visual context is whatever happened to be there.
What a well-bounded visual surface looks like:
- Scoped to a task, not to a session. Capture attached to a specific question — "why does this layout break" — and released when it's answered. An always-on frame buffer is a different product with a different risk profile, and it should be an explicit choice rather than a side effect of installing an MCP server.
- Expiry by default. Frames age out. A screenshot's usefulness has a half-life measured in minutes; its liability doesn't decay at all.
- Read and act separated. "Look at my screen" and "click things on my screen" are not the same grant. Bundling them is how a debugging aid quietly becomes a remote-control surface.
- Provenance on every frame. When it was taken, from which window, and which agent turn consumed it — so the evidence behind a decision is inspectable afterwards rather than merely implied.
- A visible capture indicator. Ambient capture with no persistent signal that it's running is where trust goes to die, regardless of how good the privacy policy is.
The general test for any MCP server exposing a sensor: can you say exactly what it captured in the last hour, and delete it? If not, you've installed something with a much larger surface than the feature you actually wanted.
How 1DevTool solves this
How 1DevTool handles this: visual context is scoped to a request rather than streamed. The screenshot annotator attaches an annotated image to a specific prompt, and comment on web pages and send to AI bundles numbered comments with element refs, screen position, route, and a screenshot into one deliberate prompt. Live browser automation keeps agent-driven browsing inside the panel you already have open through a defined set of browser_* tools, MCP Control turns individual tools off, and MCP activity history shows after the fact exactly what an agent called and what came back.
Telling the agent which tool to use does not work — it falls back to the CLI or hand-written API calls. Hooks and deny rules do work, but they are specific to one harness and I lose them the moment I open Cursor or Codex. How do I get enforcement that is portable?
You have already found the real distinction, so start by naming it: a rules file is a request and a permission check is a mechanism. Everything in CLAUDE.md, skills, and system prompts competes for attention against the task and loses often enough to be worthless as a guarantee. A deny rule and a PreToolUse hook are not competing with anything — they run whether or not the model agrees. Anything you actually depend on belongs in the second category.
Then the harder half: enforcement points are per-harness by construction. Claude Code has hooks and permissions, Cursor has its own model, Codex another. Writing the policy three times means it drifts, and drift in an enforcement layer is worse than having none, because you believe you are covered.
What travels, in descending order of portability:
- Environment-level denial. A credential the agent does not hold, a network path it cannot reach, a filesystem it cannot write. This works in every harness because it lives in none of them. Push down whatever you can.
- Repo-owned policy as data. One declarative file listing allowed tool paths, denied fallbacks and required preconditions, with a thin adapter per harness reading it. You still write the adapters, but the policy has one home and one diff.
- Verification after the fact. A check that fails when work was produced through a disallowed path. Weaker than prevention, but harness-independent, and it catches the case you did not anticipate.
Two specifics from your situation. Cover the alternate paths — denying a read tool while leaving shell access open denies nothing, and models find the open door quickly. And treat permission changes as code: they regress, and a rule that silently stopped applying looks exactly like a rule that is working. Keep a small test that attempts the forbidden path and asserts it fails, and run it whenever configuration changes.
How 1DevTool solves this
How 1DevTool handles this: policy lives in the workspace rather than inside one agent's config. MCP Control and MCP settings are one place to see and switch off every tool your agents can reach across harnesses, and link controls list every link an agent has — active, broken, and requested but not granted — so access is approved rather than assumed. Project configuration folders keep that configuration with the repo instead of in one machine's dotfiles. For proof the intended path ran, MCP activity history and MCP tool activity badges show which tool served each call, activity logs record the shell commands taken instead, and the one-click MCP diagnostic catches the silent case where a server stopped answering and the agent quietly routed around it.
When a request fails, my agent gets a status code and guesses. It then invents three plausible causes and changes code for all of them. What should a tool hand back instead?
An agent's debugging quality is bounded by the detail in its tool results, and most tools return the shape a human needs — a status line and a body — because a human fills in the rest from the terminal, the network tab, and what they know about the system. An agent has none of that. Give it a bare 401 and it will produce a confident hypothesis, because producing hypotheses is what it does when information runs out.
What a result needs to carry:
- The full exchange. Final URL after redirects, request headers with secrets masked, the body actually sent, response headers, and the response body rather than a truncated preview. Most misdiagnosis traces back to a request that was not the one you thought was sent.
- Which environment resolved, and to what. An empty or unresolved variable is among the most common failures and is completely invisible in a status code.
- Structured assertion failures. Not "test failed" but the field, the expected value, the received value, and the path. That converts a guess into a lookup.
- Timing across the transport layer. DNS, connect, TLS, first byte. It separates "the service rejected it" from "we never reached the service", which are different repairs.
- A failure classification. Network, auth, validation, server error, assertion mismatch. Naming the category stops the agent ranging across all of them.
Two design points matter as much as the content. Run the agent's request through the same engine the interface uses — if the paths differ, you are debugging a request nobody will ever send in production. And keep requests in the repository as files, so a run is reproducible, reviewable in a diff, and the agent discovers what already exists instead of hand-rolling a new call every time.
Tools that return evidence make agents debug. Tools that return verdicts make agents speculate.
How 1DevTool solves this
How 1DevTool handles this: API work sits beside the code and returns the whole exchange. The HTTP request builder runs saved requests through the same engine whether you or an agent triggers them, with full request and response detail rather than a summary, and the env manager makes visible which environment and which values resolved for a given run. MCP activity history records what each tool call sent and returned so a failure can be re-read instead of re-guessed, and activity logs keep that beside the code changes it caused. For the database half of the same problem, multi-database support and the query editor let an agent check the actual row rather than infer it from an API response.
Related features