Build
Connect & operate
Design & teams
Start hereScope a build in one callBring a spec, a wireframe, or a paragraph. You leave with an architecture, a timeline, and a number.Book a scoping call
AI software
LLM & data systems
Vibe coding
Ready to ship?Put AI where the work isAgents, RAG, and private LLMs wired into the systems your team already uses — not a chatbot bolted to a homepage.Discuss an AI project
Domain firstWe learn your workflow before we model itRegulated, operational, or high-volume — the constraints belong in the schema, not in a training doc.Talk about your domain
Plan smarterEstimate before you commitCost ranges, scope templates, and the questions we ask in discovery — free, no form.Open the cost calculator
Real conversationsTalk with a technical leadNo SDR, no discovery gauntlet. The person on the call is the one who scopes the build.Book a call

MCP & WebMCP Development

Make your software callable by AI agents.

We build the Model Context Protocol servers, gateways, and WebMCP browser tools that let agents use your data and your product — with scoped authorization, audit logging, and evals, not a blanket API key and hope.

Built to the 2026-07-28 spec · TypeScript · Python · Go · C# · You own the code

2026-07-28
the MCP spec revision we build against
3–6 wks
typical first production MCP server
100%
code ownership — your repo, your infrastructure
Zero
blanket API keys handed to a model

The integration problem

Every model times every system is a lot of glue code.

For two years the answer to “can the AI see our data?” was a bespoke integration: a function-calling schema here, a plugin manifest there, a scraper held together with retries. Every new model meant rewriting the same connectors, and every new system meant doing it again for each model.

The Model Context Protocol is the standard that collapses that grid. You build one MCP server per system; any compliant host — Claude, ChatGPT, an IDE, a coding agent, or an application you wrote yourself — discovers its tools and calls them over the same wire format. N × M becomes N + M, which is the same trade the industry made with ODBC for databases and the Language Server Protocol for editors.

A server exposes three things: tools the agent can invoke, resources it can read, and prompts the host can offer a user. What it does not expose is your credentials. The server is the only component that holds them, and it decides — per call, per identity — what actually runs.

Model Context Protocol architectureAn AI host application talks to an MCP client, which speaks the Model Context Protocol over HTTP to an MCP server you build. That server is the only component holding credentials for your databases, SaaS platforms, and internal APIs.toolsJSON-RPCSDKAI hostClaude · ChatGPTCursor · VS Codeyour own agentMCP clientdiscovers toolscarries identityroutes each callMCP servertools/listtools/callresourcespromptswe build and run thisYour systemsPostgres · SnowflakeSalesforce · Stripeinternal REST / gRPCMCP 2026-07-28 — stateless request / responseMcp-Method + Mcp-Name headers · OAuth + CIMD · cacheable tool lists
The host never touches your database. It asks an MCP client for a tool; the client speaks MCP to a server you own; the server is where authorization, validation, and auditing happen before anything reaches a system of record.

Current as of the 2026-07-28 revision

The protocol grew up. Most deployed servers have not.

The July 2026 revision is the largest change to MCP since authorization was introduced, and it is mostly good news for anyone who has to run this in production.

A stateless core

Protocol-level sessions are gone, along with the Mcp-Session-Id header. Every request carries its own protocol version, client identity, and capabilities, so any instance behind an ordinary load balancer can answer any request. No sticky sessions, no session store, no bespoke infrastructure.

Routing that gateways can actually read

Method and tool names now travel in the Mcp-Method and Mcp-Name headers, so a gateway can route and authorize a call without parsing the JSON body — which is what makes a central policy layer practical rather than theoretical.

Mid-call conversation

Multi round-trip requests let a server come back mid-call for a missing parameter or an explicit human confirmation, without holding a persistent bidirectional stream open. This is the mechanism we use to gate anything destructive.

And a real deprecation policy

Roots, Sampling, and Logging are deprecated alongside the legacy HTTP+SSE transport, each with a minimum twelve-month support window. Authorization moves to Client ID Metadata Documents and mandatory RFC 9207 issuer validation. If your server predates this, it still runs — but it is now on a clock.

orders-server.ts
// orders-server.ts — one tool, wired the way production needs it
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";

const server = new McpServer({ name: "acme-orders", version: "1.4" });

server.registerTool("refund_order", {
  title: "Refund an order",
  description: "Issues a full or partial refund on a paid order.",
  inputSchema: {
    orderId: z.string(),
    amountCents: z.number().int().positive(),
  },
  annotations: { readOnlyHint: false, destructiveHint: true },
}, async ({ orderId, amountCents }, { authInfo }) => {
  // a scope for this tool — never one blanket key per server
  requireScope(authInfo, "orders:refund");

  const order = await orders.get(orderId);
  if (order.status !== "paid") throw new ToolError("not refundable");

  const receipt = await billing.refund(order, amountCents, {
    idempotencyKey: order.id,
  });
  audit.write({ actor: authInfo.sub, tool: "refund_order", receipt });

  const text = JSON.stringify(receipt);
  return { content: [{ type: "text", text }] };
});

Nine lines of that snippet are the interesting ones: the scope check, the state precondition, the idempotency key, and the audit write. The tool definition itself is the easy part — the reason MCP projects go wrong is everything around it.

WebMCP

Your web app already has an auth system. Let the agent use it.

WebMCP moves the same idea into the browser. Instead of standing up a server with its own credentials, the page registers its own actions on document.modelContext, and an agent running in the browser can list them, call them, and read structured results back.

The consequence is the interesting bit: the agent operates inside the user's existing session. It inherits their cookies, their SSO, and their role — so it can do exactly what that person could do by clicking, and nothing more. There is no new credential to issue, no new blast radius to model, and no integration contract to negotiate with whoever owns the backend.

Be clear-eyed about maturity, though. WebMCP is a Draft Community Group Report from the W3C Web Machine Learning Community Group — not a W3C Standard and not on the Standards Track. Chrome has shipped it and run origin trials, Microsoft co-authors it, and Firefox and Safari are engaged without committed timelines. The API has already moved once, from navigator.modelContext to document.modelContext. We build it behind a thin feature-detected adapter so that when the spec moves again, you change one file.

WebMCP in the browserA web page registers tools on document.modelContext. A browser-side agent lists those tools, calls one of them, and receives a structured result — all inside the user's own logged-in session, with no server-side integration.app.yourcompany.com/ordersRefunddocument.modelContextsearch_orderscreate_orderrefund_orderBrowser agent“Refund order #4417 for the customer.”→ refund_order({ id: "4417" })← { ok: true, amount: "$129.00" }“Done — order #4417 refunded$129.00 to the original card.”no API keys · no backend integrationthe user's own session and permissionssame origin · same cookies · same authorization the human already has
The page publishes its own actions. The agent lists them, calls one, and reads a structured result back — inside the session the human is already authenticated in.
invoices-tools.js
// Published by the page itself. No backend, no API key.
document.modelContext.registerTool({
  name: "filter_invoices",
  description: "Filters the invoice table by status and date.",
  inputSchema: {
    type: "object",
    properties: {
      status: { type: "string", enum: ["paid", "open", "overdue"] },
      since: { type: "string", format: "date" },
    },
    required: ["status"],
  },
  annotations: { readOnlyHint: true, untrustedContentHint: true },
  async execute({ status, since }, { signal }) {
    const rows = await applyTableFilters({ status, since }, signal);
    const text = rows.length + " invoices matched";
    return { content: [{ type: "text", text }] };
  },
});

What that snippet buys you

The agent no longer has to guess at your DOM, invent selectors, or drive the page by simulated clicks. It gets a named action with a typed schema and a structured result — the same contract an MCP server would offer, published by the page.

readOnlyHint tells the agent this tool changes nothing, so a host can run it without a confirmation prompt. untrustedContentHint does the opposite job — it marks the returned rows as third-party text that should never be read as instructions.

And because the tool executes in the page, it can only touch what the signed-in human could already touch. Authorization is a problem you already solved.

MCP server or WebMCP tool layer?

 MCP serverWebMCP tool layer
Where it runsOn your infrastructureIn the page, in the browser
AuthorizationOAuth 2.1, scoped per toolInherits the user's session
Who can reach itAny MCP host, anywhereWhoever is on the page
Best forData, back office, SaaS APIsExisting web products
MaturityStable spec, four Tier 1 SDKsCommunity Group draft, Chrome-first
Typical effort3–6 weeks1–3 weeks

Engagements

What we build.

Six shapes of work, all of them ending with running software in your repository and on your infrastructure.

Server-side

Custom MCP servers

A server that exposes your database, warehouse, or internal service as a set of typed, scoped, audited tools — deployed on your infrastructure, in your language.

Server-side

SaaS product MCP endpoints

Ship MCP as a product surface so your customers' agents can drive your app. Multi-tenant auth, per-plan tool exposure, rate limiting, and usage metering included.

Browser-side

WebMCP tool layers

Register your web app's real actions on document.modelContext so a browser agent can operate the product inside the user's own session — no integration contract required.

Platform

MCP gateways & registries

One authenticated front door for many servers: header-based routing, central policy, a private registry, and the observability to see which tool is actually being called.

Platform

MCP clients & host apps

The other half of the protocol — agents, copilots, and internal chat surfaces that discover tools, negotiate permissions, and hold a coherent conversation across them.

Assurance

Security review & migration

Audit an existing server against the 2026-07-28 revision, retire the deprecated HTTP+SSE transport, move off Dynamic Client Registration, and close the injection paths.

How we work

From tool inventory to audited production.

  1. 1

    Tool inventory, not a tool dump

    We start from the jobs the agent has to finish, then work backwards to the smallest set of tools that finishes them. A model given forty vaguely-named tools performs worse than one given six well-named ones, so the inventory — names, descriptions, schemas, and the boundary of each call — is a design deliverable, not an afterthought.

  2. 2

    Authorization design

    Every tool gets its own scope, and the server never holds a credential broader than the tools it exposes. We map how identity travels from the human, through the host and the client, to your systems — and where a human confirmation has to interrupt the call.

  3. 3

    Build against the current spec

    Stateless request/response core, Mcp-Method and Mcp-Name header routing, cacheable tool lists with ttlMs and cacheScope, and multi round-trip requests where a tool genuinely needs to come back and ask. Written on the Tier 1 SDKs — TypeScript, Python, Go, or C#.

  4. 4

    Evals and adversarial testing

    We build a graded task set the way we build a RAG eval harness: does the agent pick the right tool, pass valid arguments, recover from an error, and refuse when it should? Then we attack it — injected instructions in tool output, argument smuggling, and scope escalation.

  5. 5

    Deploy, observe, and hand over

    Deployed to your infrastructure behind ordinary HTTP load balancers, with structured audit logs, per-tool latency and error rates, and spend caps. You get the repo, the runbook, and thirty days of post-launch support.

Security

The model is untrusted input. Design like it.

Giving an agent tools converts a language problem into an authorization problem. The dangerous deployments are not the sophisticated ones — they are the ones where a single broad API key sits behind a hundred cheerfully-named tools.

Trust boundaries for an MCP deploymentThe model is treated as untrusted input. The MCP server is the policy layer that holds scoped credentials, enforces per-tool authorization, and writes the audit log before anything reaches a system of record.trust boundaryscoped credentialAgent & modelreads whatever your tools returncan be steered by injected textholds no credential of its ownoutput is a request, not a decision!MCP server · policy layerOAuth 2.1 · CIMD · RFC 9207 issuer checkPer-tool scopes, not one blanket keyreadOnlyHint · untrustedContentHintHuman confirmation on writes (MRTR)Audit log · rate + blast-radius capsSystems of recordproduction databasebilling and paymentsCRM and ticketinginternal servicesaudited
The server is the policy layer. Everything to its left is untrusted; everything to its right is reached only through a scoped credential and a written audit record.
  • Treat every tool result as untrusted input

    A support ticket, a web page, or a PDF returned to the model can contain instructions aimed at the model. Tools that surface third-party content get flagged with untrustedContentHint, and privileged tools never sit one hop away from unvetted text.

  • No confused-deputy shortcuts

    The server does not accept a token minted for someone else and replay it downstream. Authorization is verified per request, with RFC 9207 issuer validation, and the newer Client ID Metadata Documents flow instead of Dynamic Client Registration.

  • Least privilege at the tool, not the server

    read_customer and delete_customer do not share a credential. Scopes are declared per tool and enforced server-side, so a jailbroken prompt cannot widen its own reach.

  • Confirmation on anything that costs money or is hard to undo

    Multi round-trip requests let a tool pause mid-call to collect an explicit human approval, so destructive actions are not the outcome of a single confident-sounding sentence.

  • Everything is logged as a first-class event

    Who called which tool, with which arguments, under which identity, and what changed. When someone asks what the agent did last Tuesday, that is a query, not an investigation.

The one that catches people

Indirect prompt injection. A ticket body, a scraped page, or a PDF your tool returns can carry instructions written for the model rather than the human — and a model with a delete_customer tool one hop away will sometimes take them. We test for exactly this before launch, and we keep privileged tools out of reach of unvetted text.

FAQ

Questions we get on the first call.

What is the Model Context Protocol, in one paragraph?

MCP is an open protocol that standardises how AI applications connect to external tools and data. Instead of writing a bespoke integration for every model-and-system pair, you build one MCP server per system and any compliant host — Claude, ChatGPT, an IDE, or your own agent — can discover and call it. It turns an N × M integration problem into an N + M one, which is the same reason people standardised on ODBC, LSP, and OpenAPI before it.

What is WebMCP, and how is it different from MCP?

WebMCP takes the same idea and moves it into the browser. Rather than running a server that an agent connects to over the network, your web page registers tools directly on document.modelContext, and an agent running in the browser can list and call them inside the user's existing session.

The practical difference is authentication and integration cost. An MCP server needs its own credentials and its own deployment. A WebMCP tool inherits the cookies, SSO session, and permissions the human already has on the page — so the agent can only ever do what that person could do by clicking. It is the fastest path to making an existing web app agent-operable.

Is WebMCP an actual web standard yet?

Not yet, and we are direct with clients about that. WebMCP is a Draft Community Group Report from the W3C Web Machine Learning Community Group — explicitly not a W3C Standard and not on the Standards Track. Chrome shipped an implementation and has been running origin trials; Microsoft co-authors the spec; Firefox and Safari are engaged but have not committed to timelines.

The API surface has already moved once — from navigator.modelContext to document.modelContext — which is exactly what you would expect from a spec at this stage. We therefore build WebMCP behind a thin adapter with feature detection and a graceful no-op fallback, so a spec change is a small, contained edit rather than a rewrite.

Which MCP specification version do you build against?

2026-07-28, the current revision. It is the most substantial change to the protocol since authorization was added: the transport became a stateless request/response protocol with no protocol-level sessions and no Mcp-Session-Id, so any instance behind an ordinary load balancer can answer any request.

It also added multi round-trip requests for mid-call confirmations, moved method and tool names into Mcp-Method and Mcp-Name headers so gateways can route and authorize without parsing JSON bodies, made list results cacheable with ttlMs and cacheScope, and formalised Tasks, MCP Apps, and Enterprise Managed Authorization as extensions rather than core features.

We already have an MCP server. What breaks?

Mostly transports and authorization. The legacy HTTP+SSE transport is deprecated, as are Roots, Sampling, and Logging — each with a minimum twelve-month support window, so you have time but not indefinite time. On the auth side, Dynamic Client Registration gives way to Client ID Metadata Documents, and RFC 9207 issuer validation becomes a requirement rather than a good idea.

Our migration engagement is a fixed-scope audit: we run your server against the current spec and the Tier 1 SDKs, produce a prioritised diff, and then do the work. Most servers are a week or two of engineering; the interesting findings are usually in authorization, not transport.

Is it safe to let an agent call our production systems?

It is safe when the MCP server is treated as a policy layer rather than a passthrough. The dangerous pattern is handing a model one broad API key and a hundred tools. The workable pattern is per-tool scopes, verified identity on every request, human confirmation on destructive or costly actions, hard rate and spend caps, and a structured audit log for everything.

The failure mode people underestimate is indirect prompt injection: instructions hidden in content your tools return — a ticket body, a scraped page, a document — that the model then follows. We handle that with the untrustedContentHint and readOnlyHint annotations, by keeping privileged tools away from unvetted text, and by adversarially testing the deployment before it goes live.

How long does a first MCP server take, and what does it cost?

A focused first server — one system, a handful of tools, real authorization, deployed and observable — is typically three to six weeks. A gateway serving several internal servers with a shared policy layer and registry runs longer. WebMCP tool layers on an existing web app are usually faster, because there is no new backend to stand up.

We scope fixed-fee where the boundary is clear and run a discovery sprint first where it is not. Start with the software cost calculator for a rough envelope, then talk to us for a real number.

What languages and stacks do you work in?

The Tier 1 MCP SDKs — TypeScript, Python, Go, and C# — plus Rust where a team is already there. In practice most of our servers are TypeScript or Python, deployed as ordinary containers on whatever you already run: AWS, GCP, Azure, Fly, Cloudflare, or your own Kubernetes. Because the 2026-07-28 core is stateless, no special session-affinity infrastructure is required.

Do we own the code?

Yes, fully, and it lives in your repository from the first commit rather than being handed over at the end. You get the source, the infrastructure definitions, the eval suite, the runbook, and thirty days of post-launch support. We are frequently retained afterwards to extend the tool surface, but nothing about the engagement depends on that.

Should we build an MCP server or a WebMCP tool layer first?

If the value is in your data and back-office systems, and the consumers are AI hosts your team or your customers already use, build the MCP server. If the value is in your web product and you want an agent to be able to operate it the way a person does, start with WebMCP — it is cheaper, requires no credential design, and works within permissions you have already modelled.

Plenty of teams end up wanting both, and they compose cleanly: the same tool inventory and the same authorization model can back a network-facing server and an in-page tool layer.

Give your agents something safe to call.

Bring us a system you want an agent to use and we will come back with a tool inventory, an authorization model, and a fixed-scope plan to get it into production.