MCP for business systems.

The Model Context Protocol lets any compatible AI client use your systems through one governed interface. This guide covers the current spec, a reference integration, and the permission model that keeps it safe.

Engineering guide8 min readUpdated 19 October 2026

Short answer

An MCP server exposes a business system’s tools and data to any Model Context Protocol client, such as Claude, ChatGPT or an in-house agent, through one standard JSON-RPC interface. Under the current 2026-07-28 specification, servers are stateless, authorise with OAuth, and can pause a tool call to ask the user for confirmation. For New Zealand businesses, Xero and HubSpot already publish remote MCP servers.

  • MCP 2026-07-28 removed sessions and the initialize handshake; every request is self-describing.
  • Gateways can authorise per tool using the required Mcp-Method and Mcp-Name headers.
  • Token passthrough is forbidden: validate audience and use the server’s own downstream credentials.
  • Xero’s remote MCP tools do not ask for confirmation before writes, per its FAQ.
  • Expose narrow tools with minimal scopes; keep approvals in your own layer.

When a business system needs an MCP server

An MCP server is worth building when more than one AI client needs governed access to the same system. The Model Context Protocol defines hosts (AI applications), clients (connectors inside them) and servers (services offering tools, resources and prompts), all speaking JSON-RPC 2.0. Build the server once, and Claude, ChatGPT, Copilot and your own agents can all use it under the same scopes and logs.

If one application owns its tools, skip MCP and use native function calling; the contract rules in our guide to AI tool calling in production apply either way. If a vendor already publishes a server, start there:

Vendor server (as documented on 19 October 2026) Status What matters for design
Xero Remote MCP Available to developer apps; real organisations need the Core plan or above OAuth 2.0 with PKCE; each call runs against one organisation; V1 tools do not ask the user to confirm writes; only API calls are logged, not prompts or tool calls; 1,000 calls per day per organisation on Starter, 5,000 on Core and above
HubSpot remote MCP server Generally available since 13 April 2026 OAuth 2.1 with PKCE; reads and writes CRM records and activities; respects existing user permissions; activity objects blocked when sensitive data is turned on
Microsoft MCP Server for Enterprise Public preview Read-only Microsoft Graph queries over Entra identity and directory data, honouring user roles and granted scopes

The Xero FAQ is explicit that its server does not confirm before changing data and that you must log the agent’s reasoning yourself. That gap is the usual reason NZ firms put their own server or approval layer in front. Our Xero integration guide and HubSpot integration guide cover the vendor options in more depth.

What changed in the 2026-07-28 specification

The 2026-07-28 revision turned MCP into a stateless request and response protocol, which makes servers ordinary HTTP workloads. These are the changes that affect a business-system server most:

Change What it means for your server
No initialize handshake and no Mcp-Session-Id; version and client capabilities travel in each request’s _meta Run several instances behind a plain round-robin load balancer; no sticky sessions or shared session store
server/discover is a mandatory RPC Use it for version negotiation and health checks
Mcp-Method and Mcp-Name headers required on Streamable HTTP POSTs Your gateway can authorise, rate-limit and meter per tool without parsing bodies
Cross-call state uses explicit handles passed as tool arguments Check the caller’s authorisation against the handle on every call
Multi Round-Trip Requests: a tool can return resultType: "input_required" Ask the user to confirm a write mid-call without holding a stream open
List results carry ttlMs and cacheScope; tools/list SHOULD be in deterministic order Stable tool catalogues keep clients’ prompt caches warm
Roots, Sampling and Logging deprecated (twelve-month minimum window) Pass paths as parameters, call model APIs directly, log to stderr or OpenTelemetry
Dynamic Client Registration deprecated in favour of Client ID Metadata Documents; clients MUST validate the iss parameter (RFC 9207) Plan client registration on CIMD; closes authorisation-server mix-up attacks

A reference integration

Illustrative example: a Christchurch trades business runs jobs in a field-service system and accounts in Xero. Staff want to ask Claude or ChatGPT about jobs, log notes, prepare quotes and raise draft invoices. The design puts one MCP server in front of both systems:

  1. Identity. Staff sign in through the firm’s identity provider. The MCP server accepts only tokens whose audience is the MCP server itself.
  2. Gateway. A gateway reads Mcp-Name, checks the token’s scopes against that tool, applies per-user and per-tool rate limits, and forwards to any stateless server instance.
  3. Server. Each tool is a narrow verb with a strict inputSchema. The server calls the downstream APIs with its own credentials, scoped to what the tool needs.
  4. Confirmation. Tools with external effects return input_required with a plain summary (recipient, amount, line items) and a signed requestState, then execute only on an accepted retry.
  5. Audit. Every call records user, client, tool, argument hash, decision and the downstream request ID, so you can answer “who did this, through which AI app” later.

The permission model is the part to agree with the business owner first:

Tool Scope Side-effect class Approval
search_jobs, get_job jobs:read Read None
add_job_note jobs:notes.write Reversible write None; logged
draft_quote quotes:draft Reversible write None; stays a draft
create_draft_invoice invoices:draft Reversible write None; stays a draft in Xero
send_quote_to_customer quotes:send External effect User confirms each send
Approve or pay invoices Not exposed Irreversible Stays in Xero, done by a person

Not exposing a capability is the strongest control you have. The MCP security guidance lists the common scope mistakes: publishing every scope in scopes_supported, wildcard scopes such as files:*, and bundling unrelated privileges up front.

A tool handler with scope checks and confirmation

The sketch below is framework-neutral. Field names follow the 2026-07-28 tools specification; error code -32020 is the specification’s HeaderMismatch code.

import hmac, hashlib, json

def handle_tools_call(req, principal, tools, secret: bytes):
    params = req.json["params"]
    tool = tools.get(params["name"])
    if tool is None or req.headers.get("Mcp-Name") != params["name"]:
        return rpc_error(req, -32020, "Mcp-Name header does not match the tool name")
    if tool.scope not in principal.scopes:
        return tool_error(f"Missing scope {tool.scope}. Ask an administrator.")
    args = tool.validate(params["arguments"])          # strict inputSchema, raises on failure
    for handle in tool.handles(args):                   # e.g. quote_id minted earlier
        if not owns(principal, handle):
            return tool_error("Unknown or inaccessible handle.")
    if tool.side_effect == "external":
        digest = hashlib.sha256(json.dumps(args, sort_keys=True).encode()).hexdigest()
        expected = hmac.new(secret, f"{principal.sub}|{tool.name}|{digest}".encode(),
                            hashlib.sha256).hexdigest()
        reply = (params.get("inputResponses") or {}).get("confirm")
        if not reply or params.get("requestState") != expected or reply["action"] != "accept":
            return {"resultType": "input_required",
                    "inputRequests": {"confirm": {"method": "elicitation/create", "params": {
                        "mode": "form", "message": tool.summary(args),
                        "requestedSchema": {"type": "object", "properties": {},
                                            "additionalProperties": False}}}},
                    "requestState": expected}
    result = tool.run(args, credentials=tool.downstream_credentials())
    audit(principal, req, tool, args, result)
    return {"resultType": "complete", "content": result.content,
            "structuredContent": result.data, "isError": False}

Binding requestState to the user, tool and exact arguments means a confirmation for one quote cannot be replayed to send a different one. Confirmation through elicitation only works when a person is at the client; for headless agents, route the same summary to an approval queue instead, as described in our guide to agent permissions and approvals.

Security rules that are easy to get wrong

Most MCP security problems are OAuth and authorisation problems, not model problems. The specification’s security best practices call out these, among others:

  • Token passthrough is forbidden. Accepting a token issued for another service and forwarding it downstream breaks audience validation and audit trails. Validate the audience, then use the server’s own credentials.
  • State handle hijacking. A handle is a name, not a capability. Validate authorisation against it on every call; for unauthenticated servers, use high-entropy handles with a bounded lifetime.
  • Annotations are untrusted. Clients MUST treat hints such as readOnlyHint and destructiveHint as untrusted unless the server is trusted, so never let a third-party server’s annotation decide whether a write needs confirmation.
  • Tool results carry injected instructions. A customer email returned by get_job can contain text aimed at the model. Test this deliberately with the cases in our prompt injection testing guide.
  • Confused deputy. Proxy servers that use a static client ID with a third-party authorisation server need per-client consent, or an attacker can obtain codes without the user’s agreement.

Where MCP integrations go wrong

The protocol is now stable enough that failures come from design choices:

  • Wrapping the whole API. A server that exposes every endpoint as a tool gives the model too much choice and too much authority. Expose the ten verbs the workflow needs.
  • Trusting vendor defaults for writes. Xero’s FAQ says its V1 tools do not elicit confirmation. If your process needs a check, it has to live in your client, server or approval layer.
  • Missing the reasoning in the log. Vendor logs record API calls, not the prompt or the tool call that caused them. Keep your own AI audit log joined on request IDs.
  • Session-era code. Servers that stored state against Mcp-Session-Id need migrating to explicit handles; the old HTTP+SSE transport is deprecated.
  • Unstable tool lists. Reordering or rewording tool definitions on every deploy breaks client prompt caches and changes model behaviour. Version tool definitions and test changes against an evaluation set.

For teams starting out, our lesson on connecting AI to your CRM covers the non-technical decisions, and our AI integration service builds and runs servers like the one above.

  • The server targets protocol version 2026-07-28 and implements server/discover
  • No state depends on sessions; handles are checked against the caller on every call
  • The gateway authorises and rate-limits on Mcp-Name before the request reaches a server
  • Tokens are audience-validated; nothing is passed through to downstream APIs
  • Scopes are per tool, with no wildcards and no unused scopes advertised
  • External-effect tools require confirmation bound to user, tool and arguments
  • Irreversible actions are not exposed at all unless a person approves each one
  • Tool lists are deterministic and versioned, with ttlMs and cacheScope set
  • Annotations from third-party servers never decide whether a write is confirmed
  • Every call is logged with user, client, tool, argument hash and downstream request ID
  • Injection tests run against tools that return customer or third-party text

Sources

  1. Model Context Protocol specification, version 2026-07-28, Model Context Protocol (LF Projects), 28 July 2026
  2. Key changes in 2026-07-28, Model Context Protocol (LF Projects), 28 July 2026
  3. Tools (server features), Model Context Protocol (LF Projects), 28 July 2026
  4. Security Best Practices, Model Context Protocol (LF Projects), accessed 19 October 2026
  5. The 2026-07-28 Specification, Model Context Protocol Blog, 28 July 2026
  6. MCP joins the Agentic AI Foundation, Model Context Protocol Blog, 9 December 2025
  7. Remote MCP FAQs, Xero Developer, accessed 19 October 2026
  8. Remote HubSpot MCP server is now generally available, HubSpot Developer Changelog, 13 April 2026
  9. Overview of Microsoft MCP Server for Enterprise, Microsoft Learn, 27 June 2026

Written by the Levy Street team in Wellington. Last updated 19 October 2026.

Questions people ask

What is an MCP server?

An MCP server is a service that offers tools, resources and prompts to AI applications using the Model Context Protocol, an open standard governed through the Agentic AI Foundation under the Linux Foundation since December 2025. A client such as Claude or ChatGPT connects to it, lists its tools, and calls them on the user’s behalf. One server can serve many AI clients, which is the main reason to build one.

Should we build our own MCP server or use the vendor’s?

Use the vendor’s server when its tools match your workflow and its permission model is acceptable, as with HubSpot’s server, which respects existing user permissions. Build your own when you need narrower tools, business rules, approvals, cross-system actions or audit detail the vendor does not provide. Many teams do both: vendor servers for reads, their own for governed writes.

Is MCP secure enough for finance or customer data?

The protocol gives you the mechanisms (OAuth with PKCE, audience-bound tokens, scoped tools, user confirmation) but cannot enforce them. Security depends on the server design: minimal scopes, no token passthrough, authorisation on every state handle, confirmations for external effects and full audit logs. Treat tool descriptions and annotations from servers you do not control as untrusted.

What changed in MCP in 2026?

The 2026-07-28 revision made the protocol stateless: no initialize handshake and no session header, a mandatory server/discover call, routing headers on every HTTP request, cacheable list results, a multi round-trip pattern for mid-call user input, and a formal extensions framework. Roots, Sampling and Logging are deprecated, as is Dynamic Client Registration in favour of Client ID Metadata Documents.

Do we need MCP for one internal agent?

Usually not. If a single application owns its tools, native function calling in the model API is simpler and has fewer moving parts. MCP pays off when several AI clients need the same governed access, when staff want to use the systems from Claude or ChatGPT directly, or when you want one place to enforce scopes and logging.

Building something that has to hold up?

We design, evaluate and run AI systems in production. Tell us what you are building and where it hurts.