Available for rolesPiotr Czerwiński

Writing · September 11, 2026 · 8 min read

MCP in daily engineering: lean sessions, heavy servers on demand

MCP · Claude Code · AI agents · developer tooling · observability

TL;DR: MCP, the Model Context Protocol, is the open protocol a coding agent uses to connect to outside tools and data. In my daily work five kinds of server earn their place: platform logs, platform data bindings, local or test database access, browser automation, and product analytics. Every connected server costs something in every session, so only two load by default and the heavy ones are added per profile when a session starts. Deferred tool schemas keep the standing cost down to tool names. The risk side is non-negotiable: read-only grants, test databases, and no production writes from an agent session. I use MCP servers every day; I have not published one of my own.

Every server is a tax on every session

The problem showed up as sessions that felt slow for several days in a row. The cause was the list of MCP servers attached to the project. Each one costs something in every session, whether the session uses it or not: a connection at startup, its tool names in the context window, and for some servers more. One analytics server ships a large block of usage instructions that lands in the prompt. One keyword-data server is a local process launched through npx on every start, and on a cold package cache it was slow enough that I had to raise the MCP startup timeout. The three heaviest servers were needed in a minority of conversations and paid for in all of them.

There is a physical cost too. Leftover server processes from earlier sessions, especially a browser automation instance, accumulate on the machine until something kills them. On a laptop that shows up as heat and fan noise long before it shows up anywhere else.

Which MCP servers are actually worth connecting?

These are the kinds of server I keep, in the order I reach for them. None of them is exotic; they are the official or widely used servers for the platforms I already run on.

  • Platform observability. Logs and request analytics for my Cloudflare Workers, queried from the session instead of a dashboard. Incidents are urgent, so this one is always loaded.
  • Platform bindings. Queries against the edge SQL database and key-value stores of the app I am working on. It replaces a lot of copy and paste between a terminal and the conversation.
  • Local and test databases. In a different product the agent gets a local Postgres and a test project of the hosted database, which is enough to read schemas and run the provider's advisors for missing indexes and slow queries. Production is not on that list.
  • Browser automation. Playwright over MCP is how I verify behaviour empirically. When I needed to know whether a page still prefetched dozens of routes, the agent opened a production build, scrolled to the bottom and listed the network requests filtered to the prefetch calls. An empty list meant the fix worked.
  • Product analytics. PostHog over MCP for alerts, SQL over events and project settings. One setting change made through it, a minimum session length for recordings, stopped scanner visits from burning recording quota immediately, with no deploy.
  • Marketing data. A keyword data API and an ads platform. Useful in marketing sessions, dead weight everywhere else.

One server I removed entirely was a documentation server. The agent reads official docs through a plain web fetch well enough, and if that ever stops being true, adding it back is one line.

Global, per repo, or per session?

I tried three ways of deciding which servers a session gets.

  • Global configuration. Everything available everywhere, nothing to remember. The cost is that every session in every project pays for every server, including ones the project never touches. When I audited this, two of the servers loading into one project belonged to platforms that project did not use at all.
  • Per repo, committed with the code. The right servers for the project, reviewed like any other config. But heavy servers that one kind of session needs still load in all sessions of that repo.
  • Per repo default plus per-session profiles. A small default in the repo and profile files that add servers when the session starts. This is what I run.

The default for the product where this started is just the observability server and the bindings server. Profiles add the SEO data server, the ads server or the analytics server. The mechanics rely on two CLI behaviours: passing extra MCP config files adds them on top of the repo config, and a strict flag with no extra files starts a session with zero servers, for work that needs none. A small launcher reads the task description I type, picks a profile by keywords and starts the session with the matching servers, model and effort.

# illustrative shape of the launch flow
agent "fix the bug in the scan"     # default: logs + bindings
agent "keyword volumes for a page"  # default + SEO data server
agent --no-mcp "fix a typo"         # zero servers

There is no hot-plugging: the server list is fixed when the process starts. Two patterns cover that gap. The first is to exit and restart with the right profile and the flag that resumes the last conversation, which costs about twenty seconds and keeps the full context. The second is a fallback for servers whose credentials already live on my machine: with a short written primer of the vendor's HTTP API, a single query goes through curl in a lean session with no restart at all. Servers that authenticate through a hosted OAuth flow have no such fallback.

Two consequences I learned by tripping over them. Subagents inherit the servers of the session they run in, so an agent that needs analytics must run inside a session started with that profile. And a second CLI I use alongside Claude Code gets the same servers mirrored in its own config, disabled by default and switched on per profile, so both tools see the same world.

Deferred tool schemas and tool curation

The other half of keeping MCP cheap is how tool definitions reach the model. With deferred tool schemas, which is the default in current Claude Code, the context holds only tool names, and the full JSON schema of a tool is fetched the moment the agent decides to use it. Across the eight servers I have configured in different projects, that is a difference in the tens of thousands of tokens per session. I wrote about what else loads at startup in context architecture per project.

Deferral does not fix a badly curated tool set. A rule I took from Anthropic's guidance on writing tools for agents holds up in practice: if a person cannot say which of two tools to use in a given situation, the model cannot either, and you pay for both attempts.

How do you use MCP servers for incident triage?

This is where MCP paid for itself most clearly. The first time I reviewed a burst of alert emails through the agent, it took one long session and roughly 400 thousand tokens, because every step had to be discovered. The second time followed a written runbook and stopped at the first section that answered the question.

The rules of engagement come first: the session diagnoses and does not restart or deploy anything until I say so, and every claim it makes is backed by a log line or an HTTP check. The pre-flight runs in parallel: fix the time window, list the Workers and run one grouped count per service, get the analytics grant, and check the status of the critical pages together with the stylesheet they reference.

The query shapes against the logs server took trial and error, and they are the most reusable part:

  • Use the aggregated view with group-bys. The event-level views threw schema errors whenever the result contained log-only rows, which was most of the time.
  • Ask for a count only. Adding min or max of the timestamp next to the count returned empty aggregations; first and last occurrence come from the time buckets the tool prints anyway.
  • Rows with a response status of zero are console log lines, not responses. Filter to rows that have an outcome to count real requests.
  • A multi-value filter did not behave; one query per value did.

With that, triage becomes five questions, one query each: any 5xx? any resource limits or crashes? what errored? what warned? who caused the spike? A single deploy version across the window also rules out a release before anyone blames one.

Why logs and product analytics in the same pass: streaming server rendering can turn a crash into a 200. The framework streams an error boundary inside a response that has already started, so the platform log shows a successful request. Only an error event sent from the server's error hook to the analytics tool sees it. Logs alone would have told me the site was healthy while a page was broken. The reverse blind spot exists too: a page that answers 404 for content that exists raises no error anywhere, and only a synthetic check or a crawler finds it.

What is the risk side of giving an agent MCP access?

MCP turns a model into something that can act on real systems, so the permission model matters more than the tool list.

  • OAuth per session, read-only by choice. The analytics server needs a fresh grant in every session and starts in whatever project was active last, so the first command switches project. The consent page asks for write access to everything by default; I pick read-only every time. The callback has to arrive while the flow is still pending, so before any unattended run the grant is the first thing I do.
  • Bindings to a production database are a lot of power. Read queries are the point. Point-in-time restore is the safety net for the edge database; it does not make writes safe. Production writes do not go through an agent session.
  • Test databases where possible. In the product with database servers, the agent sees a local instance and a test project.
  • Hard blocks outside the conversation. Deny rules stop CLI commands that delete databases or Workers, and the MCP config file itself is a protected path the agent cannot rewrite silently. I described that layered setup in the guardrails I run.
  • Credentials never in the repo. The committed MCP config names servers; any key a local server needs comes from my shell environment.

What I have not done, and what I would tell you

I consume MCP servers; I have not written and published my own. So far every gap was covered by an official server or by a documented HTTP API plus a one-page primer, which is the curl fallback above. If I build one first, it will be for exactly that case: a vendor API I already query with local credentials, wrapped as a thin read-only server so a session can use it without a restart and without me pointing it at a primer.

  • Keep the default tiny. The servers you need during an incident, and nothing else.
  • Add heavy servers per session at start, and learn the resume flag so adding one mid-task costs seconds.
  • Leave tool schemas deferred and curate tools so no two do the same job.
  • Write down the query shapes that work. They are the difference between a 400 thousand token triage and a short one.
  • Read logs and product analytics together, because each one is blind to failures the other sees.
  • Grant read-only, point write-capable servers at test data, and keep production writes out of agent sessions.

Questions this post answers

Which MCP servers are most useful for software engineers?
In my daily work the servers that earn their place are platform logs and observability, platform data bindings, local or test database access, browser automation such as Playwright, and product analytics. Marketing data servers are useful only in marketing sessions and should not load everywhere.
Do MCP servers slow down Claude Code sessions?
Each connected server costs something in every session: a connection at startup, its tool names in the context, and sometimes a block of instructions or a local process. Keeping a small default and adding heavy servers per session at start avoids paying for servers a session never uses. Deferred tool schemas keep only tool names in context until a tool is actually used.
Is it safe to give an AI agent MCP access to a production database?
Treat it as read access only. Choose read-only on OAuth grants, point any write-capable server at a local or test database, block destructive CLI commands with deny rules, and keep production writes out of agent sessions.