MCP server

Give AI assistants read-only access to Nistor through the Model Context Protocol.

The MCP server lets an AI assistant query Nistor through the Model Context Protocol. It is a client of the backend's REST API that only reads: every tool sends GET requests and nothing else, so an assistant can search the graph and read lineage, incidents, runs and rules, but never change them.

The package nistor-mcp has two commands, which serve the same tools:

Command Transport Use it for
nistor-mcp stdio: one JSON-RPC 2.0 message per line on stdin and stdout An assistant on your machine, which starts the server itself
nistor-mcp-remote MCP Streamable HTTP A shared endpoint that assistants reach over the network (see Remote gateway)

Install#

From a clone of the repository, make dev installs nistor-mcp into .venv, with the extra the gateway needs:

git clone https://gitlab.com/nistor-io/nistor.git
cd nistor
make dev
.venv/bin/nistor-mcp --list-tools

--list-tools prints the tool catalogue as JSON and exits. It needs no backend and no network.

Once released, the package is on PyPI as nistor-mcp, and nistor-mcp[remote] adds what the gateway needs. Until then, install from a clone. The package needs Python 3.10 or later.

Run it#

An MCP client starts nistor-mcp itself and talks to it over stdin and stdout. Run it by hand only to check that it starts:

NISTOR_MCP_BASE_URL=https://nistor.example.com NISTOR_MCP_TOKEN=<token> .venv/bin/nistor-mcp

It prints nistor-mcp <version> ready (backend: https://nistor.example.com/api/v1) on stderr and waits for messages. Everything it logs goes to stderr, because stdout carries the protocol.

The server answers initialize, ping, tools/list and tools/call. When a tool cannot reach the backend, or the backend refuses the call, the error comes back as the tool's result, marked isError. A missing required argument is a JSON-RPC error (-32602).

Configure#

The server reads its settings from the environment when it starts:

Variable Default Meaning
NISTOR_MCP_BASE_URL http://localhost:8000 The backend's URL, without the API prefix.
NISTOR_MCP_API_PREFIX /api/v1 The API prefix.
NISTOR_MCP_TOKEN none The token sent with every request. It is never logged.
NISTOR_MCP_AUTH_HEADER Authorization The header that carries the token.
NISTOR_MCP_AUTH_SCHEME Bearer The word before the token. Set it to an empty value to send the token alone.
NISTOR_MCP_TIMEOUT 30 The timeout of one request, in seconds.
NISTOR_MCP_EMBEDDED_UI_ENABLED true Add an HTML view to the results of three tools (see Tools). Only 1, true, yes and on count as true.
NISTOR_MCP_FRONTEND_BASE_URL none The web shell's URL, which makes the "open in Nistor" links of those views absolute.
NISTOR_MCP_BACKEND_AUDIENCE none For the remote gateway only (see Remote gateway).

Add it to a client#

Most MCP clients that start a local server read a block like this one:

{
  "mcpServers": {
    "nistor": {
      "command": "nistor-mcp",
      "env": {
        "NISTOR_MCP_BASE_URL": "https://nistor.example.com",
        "NISTOR_MCP_TOKEN": "<token>"
      }
    }
  }
}

If the client cannot find nistor-mcp on its PATH, give the full path to .venv/bin/nistor-mcp in your clone.

The stdio server sends the token in a single header, so it works against a backend that accepts that token directly, such as the Quickstart stack. In the reference Google Cloud deployment (Install on GCP), only the web shell's proxy and Nistor's own service accounts may call the backend's Cloud Run service. Connect assistants to such a deployment through the remote gateway.

Agent tokens#

An agent token is a credential that Nistor issues for one assistant. It does not carry the identity of the person who registered it. Every agent token acts as one fixed identity that may only read (GET, HEAD and OPTIONS requests) and holds the permissions listed in the backend setting MCP_AGENT_PERMISSION_CODES: by default graph:view, catalog:view, finops:view and dataquality:view. You can add other *:view codes to that setting, as a JSON list.

The backend needs two settings before it accepts agent tokens:

  • AGENT_GOVERNANCE_ENABLED=true. While it is off, the backend refuses every agent token.
  • A signing key in AGENT_MCP_TOKEN_SIGNING_KEY: at least 32 characters of random data, for example from openssl rand -base64 48. The backend refuses a short or predictable key. In a local environment (ENVIRONMENT=local), it falls back to EXTENSION_TOKEN_SIGNING_KEY.

With the reference Terraform root, enable_agent_governance = true sets the first, creates the secret agent-mcp-token-signing-key-<env> and passes it to the backend as the second. Add a version holding the random value to that secret yourself: Terraform never sees it.

To register an assistant, call the API as a person who holds agents:manage:

curl -X POST "$NISTOR_API_URL/api/v1/agent-governance/agents" \
  -H "Authorization: Bearer $NISTOR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "acme-assistant"}'

The response carries the token in token, once: Nistor keeps only its identifier and first characters. A token lasts AGENT_MCP_TOKEN_TTL_DAYS days (90 by default). POST /api/v1/agent-governance/agents/{id}/rotate-token issues a new one, and POST /api/v1/agent-governance/agents/{id}/revoke revokes the agent for good. Listing agents needs agents:view.

A registration also stores allowed tools, a rate limit and a daily budget for the agent. The AI module of Nistor Enterprise enforces them, and its console has a page to register agents. Without that module, these settings have no effect, and you register agents through the API.

Tools#

Results are shaped for a model's context window. A node loses its DDL, schema, column lineage and query text, and long lists are cut (100 nodes per lineage direction, 50 affected nodes, 50 runs), with counts or a marker that say so.

Several tools read the routes of an Enterprise module (Nistor Enterprise). The stdio server lists every tool; without the module, such a tool returns an error from the backend. The remote gateway hides the tools of a capability that an administrator has switched off.

Tool What it returns Needs
nistor_search Full-text search over nodes, incidents and rules, and, with the Catalog module, columns, assets and glossary terms. Use it to find the ids the other tools take. Open source
nistor_get_node One node. Open source
nistor_get_lineage The upstream and downstream nodes of a node, or its direct neighbours only. Open source
nistor_impact_analysis What a failure of a node affects downstream: nodes, rules, data-quality checks, scheduled actions and cost at risk. Open source. The checks come from the Data quality module, the cost from the FinOps module.
nistor_list_incidents Incidents, newest first, by status, severity, type and environment. Open source
nistor_get_incident One incident. Open source
nistor_cost_summary Nodes ranked by cost over a number of days (30 by default). Open source. Without the FinOps module the nodes carry no cost.
nistor_finops_costs BigQuery spend over a date range, by project, writer, log type or node. FinOps module (capability finops)
nistor_cost_anomalies Detected cost spikes. FinOps module (finops)
nistor_cost_to_produce A node's cost, including its share of the cost of its upstream nodes. FinOps module (finops)
nistor_list_runs Recent runs, newest first, by state, action, trigger and time. Open source
nistor_get_run One run. Open source
nistor_run_stats Counts of running, completed and failed runs. Open source
nistor_list_on_hold The actions the scheduler is holding, and why. Open source, capability scheduler
nistor_lookup_term The glossary definition of a business term. Catalog module. Without it, there are no matches.
nistor_get_catalog_asset A node's catalog entry: description, owner, tags, certification and columns. Catalog module (catalog)
nistor_get_catalog_columns One column: description, flags, type and the columns that hold the same field. Catalog module (catalog)
nistor_recommend_dq_rules The data-quality monitors the Advisor proposes for a node. Advisor module (advisor)
nistor_list_dq_checks The data-quality checks on a node, with their latest result. Data quality module (data_quality)
nistor_get_dq_check One check: its configuration and its last 10 runs. Data quality module (data_quality)
nistor_dq_check_history One check's measured value over its recent runs. Data quality module (data_quality)
nistor_list_rules The scheduling rules that target a node. Open source, capability scheduler
nistor_get_rule One scheduling rule. Open source, capability scheduler
nistor_node_health A node's health: trust verdict, freshness, data-quality summary, run reliability, open incidents and neighbours. Open source
nistor_node_usage Who reads and writes a node, over a number of days (30 by default). Open source
nistor_node_activity A node's runs, data-quality runs, incidents and writes over a number of days (14 by default, 90 at most). Open source. The data-quality runs need the Data quality module.

nistor_get_lineage, nistor_dq_check_history and nistor_node_activity also return a self-contained HTML view (a ui://nistor/… resource) for clients that display one. NISTOR_MCP_EMBEDDED_UI_ENABLED=false turns it off.

Permissions#

With a person's token, a tool sees what that person may see. The open-source tools need only a signed-in user.

With an agent token, a tool sees what the agent identity may see (see Agent tokens). That identity does not hold advisor:view, which the Advisor's routes require, so nistor_recommend_dq_rules fails with an agent token unless you add that code to MCP_AGENT_PERMISSION_CODES.

Remote gateway#

nistor-mcp-remote serves the same tools over MCP Streamable HTTP, at https://<gateway-host>/mcp/ (/mcp redirects there). An assistant connects to it with an agent token and runs nothing on its own machine. The gateway also answers /healthz and /health/live (liveness), /health/ready and /health/installed.

The gateway reads the caller's Authorization: Bearer <token> header and calls the backend in one of two ways:

  • With NISTOR_MCP_BACKEND_AUDIENCE set (to the backend's URL), it calls the backend with a Google identity token of its own service account, and forwards the caller's token in X-Nistor-Agent-Token. The backend accepts that header only from the account named in its MCP_GATEWAY_SERVICE_ACCOUNT setting, only while AGENT_GOVERNANCE_ENABLED is on, and only for read requests. It then treats the call as the agent's.
  • Without it, the gateway forwards the caller's token in Authorization, as the stdio server would.

To run it yourself, start .venv/bin/nistor-mcp-remote with NISTOR_MCP_BASE_URL set. It listens on PORT (8080 by default) on every interface. In the runtime image, nistor serve mcp starts the same app.

On Google Cloud, the reference Terraform root (deployments/gcp) deploys it when you ask for it:

Input Effect
enable_mcp = true Creates the Cloud Run service <prefix>-mcp-<env>, which runs nistor serve mcp with NISTOR_MCP_BASE_URL and NISTOR_MCP_BACKEND_AUDIENCE set to the backend's URL. Its ingress is public and anyone may invoke it: the agent token is the access control. The output mcp_uri is its URL. Off by default.
role_service_accounts.mcp The gateway's own service account, required with enable_mcp. The root makes it the backend's MCP_GATEWAY_SERVICE_ACCOUNT and a trusted caller. The account also needs roles/run.invoker on the backend's service, which the root does not grant.
enable_agent_governance = true Turns agent tokens on, with their signing key (see Agent tokens).

A client that connects to a remote MCP server with a fixed header takes a block like the one below. Clients name these keys differently: check your client's documentation.

{
  "mcpServers": {
    "nistor": {
      "url": "https://<gateway-host>/mcp/",
      "headers": { "Authorization": "Bearer <token>" }
    }
  }
}

Edit this page on GitLab

↑ ↓ to moveEnter to openEsc to close