SLT
ProjectsWritingContact
All posts
Engineering

MCP Is Becoming the New API Surface

We shipped an MCP server for envpilot.dev so AI assistants can read a team's environment config without ever touching a secret. It changed how I think about what a 'developer tool' has to expose in 2026.

June 19, 2026
8 min read
By Abdul Rafay

Six months ago, if you'd asked me what surfaces a developer tool needs, I'd have said: a web app, a CLI, maybe a VS Code extension if the product justifies the maintenance. Today I'd add a fourth line without hesitating: an MCP server. Not because it's trendy — though it is — but because we shipped one for envpilot.dev and watched it become the surface our power users reach for first.

Model Context Protocol is, at the plumbing level, boring: a standard way for an AI assistant to discover and call tools exposed by a server, over a well-defined transport, with a schema the model can read. The interesting part isn't the protocol. It's what it implies about the shape of a product.

Why we built one

envpilot.dev manages environment variables and secrets for a team, across projects and environments, with values actually stored in WorkOS Vault and Convex holding only the references. The product already had a web app, a CLI, and a REST API. The gap was: if you're sitting in your editor with Claude or Cursor open, asking "what environment variables does the staging deploy for this project expect, and are any of them missing," there was no way for the assistant to answer that without you tabbing over, running the CLI, and pasting the output back.

That's a narrow gap. It's also, once you notice it, everywhere. Any tool that holds structured state a developer needs while coding — feature flags, deploy status, API keys, database schema, CI results — has the same gap. The AI assistant already has the developer's intent, in the conversation, in real time. What it's missing is safe, scoped access to your systems. MCP is the thing that closes that gap without every tool vendor inventing their own bespoke plugin format, which is roughly what was happening before MCP, badly, per-vendor.

What it actually took

The honest build breakdown, because "we added an MCP server" undersells the work by a lot:

Auth, reused, not reinvented. We already had apiKeys — org-scoped, dynamic-scope API keys used by the REST API and the GitHub Action, SHA-256 hashed, never stored in plaintext. The MCP server authenticates the exact same way, through the exact same authorization core (_authorizeRequest in our case) that the REST API and the Action already route through. This was the single most important decision in the whole project: we did not write a second permission model. One enforcement core, three faces. If we'd built MCP auth as its own thing, we'd now have two places that can drift out of sync about who's allowed to read what, and drift in an authorization system is how you get a security incident, not a bug report.

Read-only, on purpose, everywhere. Every tool the MCP server exposes is a read. List projects. List environments. List variable keys — not values, keys — for a project. Check whether a variable is set without ever returning what it's set to. We debated exposing a "get variable value" tool and killed it, because the trust model for "an LLM can read your secrets" is a much scarier sentence than "an LLM can read your secret names and tell you one is missing." The 90% use case — "why is staging broken, is an env var missing" — is fully served by metadata. The 10% use case that needs the actual value is still a deliberate, human action in the CLI or web app, where it belongs.

Scoping that mirrors the human RBAC, not a new one. A member with read-only project access gets the same read-only view through MCP that they'd get in the web app. We didn't build a separate MCP-specific permission tier. This sounds obvious in retrospect and it was not obvious while building it — the instinct when you're wiring up a new surface is to make it maximally capable "for now" and lock it down later. We didn't let ourselves do that, mostly because we've been burned before by "lock it down later" becoming "lock it down after the incident."

Tool descriptions are a UX surface, not documentation. This was the surprise. The schema and description text for each MCP tool is what the model reads to decide when to call it and how to interpret the result — get it vague and the assistant either never calls the tool when it should, or calls it with wrong arguments and produces a confidently wrong answer. We rewrote our tool descriptions probably six times, testing against actual Claude and Cursor sessions, the same way you'd iterate on error message copy for a human. "List the environments for a project" undersold what the tool actually needed (a project slug, not a name, and it needed to know that ambiguity should trigger a clarifying question rather than a guess). Getting this right took longer than the underlying Convex query.

// convex/features/api/mcp/tools.ts (shape, not full source)
const listVariableKeys = {
  name: "list_variable_keys",
  description:
    "List the environment variable KEYS (never values) configured for a " +
    "project + environment. Use this to check whether a variable is set, " +
    "or to see what's expected before a deploy. Returns keys only — this " +
    "tool cannot and will not return secret values.",
  inputSchema: z.object({
    projectSlug: z.string(),
    environment: z.enum(["development", "staging", "production"]),
  }),
  handler: async (ctx, args) => {
    const gate = await checkFeature(ctx, ctx.orgId, "mcp_server");
    if (!gate.allowed) return { error: "mcp_server not available on this plan" };
    return await listKeysForEnvironment(ctx, args); // read-only, bounded
  },
};

Why every dev tool will need one

The pattern generalizes past us. Any product whose users are developers, and whose value is "structured state that's relevant while coding," is going to face the same question envpilot.dev faced: does the AI assistant your user already has open get to see this, or does your product become the thing they have to alt-tab away from. Products that answer "yes, safely" get pulled into the developer's actual workflow. Products that don't become one more tab that gets checked less and less as agentic coding becomes the default way people write software.

I'd extend this past dev tools, cautiously — I think in three to five years "does this SaaS have an MCP server" is a question buyers ask the way "do you have an API" is a question buyers ask today. Not every product needs one now. But the products where the state genuinely matters mid-task — the ones adjacent to writing or shipping code, specifically — are the ones under the most immediate pressure, and we're one of them, which is why we moved on this before it was obviously necessary.

Practical advice if you're building one

Reuse your existing auth. If you're inventing a new permission model for MCP specifically, stop — that's a second attack surface and a second place to get it wrong, and the value of MCP is being one more face on infrastructure you've already hardened.

Default to read-only, and make the write tools, if you build any, require an explicit opt-in scope that's visibly named "this key can write." An assistant that can silently mutate your infrastructure because a prompt injection in some unrelated content told it to is not a hypothetical; it's the actual threat model MCP servers with write access have to defend against, and read-only defaults are most of that defense for free.

Spend real time on tool descriptions. Treat them like you'd treat onboarding copy or error messages — the audience is a model instead of a human, but the standard for "will this be misunderstood" doesn't go down.

Gate it by tier if it costs you anything to run, the same as any other feature — mcp_server is a boolean in our feature registry exactly like public_api is, checked the same way, billed the same way. It's infrastructure, not magic, and it should live in your product's plumbing exactly like every other capability you sell.


envpilot.dev is one of eight products built by the Syntax Lab Technology team. Its MCP server ships alongside a REST API and a GitHub Action, all authorizing through the same core.

On this page

  • Why we built one
  • What it actually took
  • Why every dev tool will need one
  • Practical advice if you're building one

Ask AI

Ask ChatGPTAsk Claude

From Syntax Lab Technology

envpilot.dev →wryte.xyz →ourtrail.xyz →lumocash.com →
All posts

On this page

  • Why we built one
  • What it actually took
  • Why every dev tool will need one
  • Practical advice if you're building one

Ask AI

Ask ChatGPTAsk Claude
Syntax Lab Technology

© 2026 · Independent software organization

ProjectsWritingContactPrivacyTerms
envpilot.dev — live
wryte.xyz — live
ourtrail.xyz — live
LUMO on Google Play — live
support@syntaxlabtechnology.org