Skip to content

Using the MCP server

Gungner exposes an MCP (Model Context Protocol) server so an AI agent can call the same data the REST API serves, using tools instead of raw HTTP. It isn’t a separate product or a separate grant of authority — every tool maps onto one or more REST routes, uses the exact same bearer token, and is subject to the exact same scopes and tenant isolation as a direct REST call. If you can’t reach something over REST with your token, you can’t reach it over MCP with the same token either.

The MCP server is hosted inside the API itself — there’s no separate server or port to stand up. It’s reachable at:

POST /mcp

on the same origin as the REST API, so it’s https://api.gungner.ai/mcp; see Getting started and Getting access for how to get a token.

The transport is streamable HTTP: stateless, no persistent connection to manage, and every response is a plain JSON body — Gungner’s server never actually streams an event. The Streamable HTTP spec still requires the client to accept both media types on every request, so every call needs this header:

Accept: application/json, text/event-stream

Leaving it out (or sending only application/json) gets you 406 Not Acceptable — the server is checking what you’re willing to receive, not deciding to stream.

Use the exact same bearer token you’d use for REST — see Authentication and delegation for how to mint one. Send it as a standard Authorization header on every MCP request:

Authorization: Bearer <your token>

There’s no separate MCP-specific credential to manage.

A few things to expect from the transport itself:

  • Calling initialize or tools/list without a valid bearer token returns 401.
  • GET and DELETE on /mcp return 405 — the endpoint only accepts POST.

tools/list only returns the tools your token’s scopes actually permit — you won’t see tools you can’t call. If you force a call to a tool outside your granted scopes anyway, you get the same 403 the REST API would give you for the equivalent route, returned as an error result rather than a silent failure or an empty response.

Each tool maps onto one or more REST routes — the same data, the same authorization, reached through an agent-friendly protocol instead of raw HTTP. A representative handful, with the same status the country coverage matrix gives the data each one reaches:

  • lookup_company — resolve and fetch a company by org.nr — live
  • get_company_profile — full canonical company profile — live
  • get_beneficial_owners — beneficial ownership for a company — gated: upstream agreement pending, enabled on completion. Calling it today isn’t refused by a permission check the way a SPAR call is (below) — Bolagsverket’s paid tier has no per-tenant gate — so until the tier is enabled, it answers an error rather than data. get_officers, get_signatories, and get_person_engagements are gated the same way, for the same reason.
  • get_person_profile / lookup_person — SPAR person lookup — gated: requires the tenant’s own SPAR permit. Calling either without an active permit is refused before any upstream call is made, returned as 403 spar_permit_required (or 403 spar_permit_suspended for a withdrawn one) — see errors.md.
  • get_subject — a subject record by its opaque ID — live
  • list_events — page through the event log — live
  • subscribe_monitoring — start an ongoing-monitoring subscription — live
  • screen_subject — run a screening check — live

For the full list — every tool’s name, description, input schema, and which REST route(s) it maps onto — see the MCP tool reference. That page is generated directly from the same source the server itself uses, so it’s always the source of truth, never this page.

Every tool result carries three parts:

  • a short, human-readable summary, for quick agent context;
  • the verbatim underlying REST response body, so nothing is lost in translation;
  • structured content matching the tool’s declared output shape, for a caller that wants to parse the result programmatically rather than re-parsing free text.

If you’re using an MCP-compatible client (an agent tool that speaks MCP natively), point it at the endpoint with your bearer token in the request headers. A typical client configuration looks like this:

{
"mcpServers": {
"gungner": {
"url": "https://api.gungner.ai/mcp",
"headers": {
"Authorization": "Bearer <your token>"
}
}
}
}

(The exact configuration format varies by client — check your client’s own MCP documentation for the precise field names it expects. The shape above is illustrative.)

If you’re integrating without an off-the-shelf MCP client library, MCP over streamable HTTP is just JSON-RPC over POST. A minimal tool call in TypeScript:

const response = await fetch("https://api.gungner.ai/mcp", {
method: "POST",
headers: {
"content-type": "application/json",
accept: "application/json, text/event-stream",
authorization: `Bearer ${token}`,
},
body: JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "tools/call",
params: {
name: "lookup_company",
arguments: { orgnr: "YOUR_ORGNR" }, // the org.nr to look up
},
}),
});
const result = await response.json();

MCP doesn’t grant any extra authority beyond what your token already has over REST — it’s an alternate way to call the same API. See the API reference for the underlying REST routes and the MCP tool reference for the full tool catalogue.