Using the App¶
This document describes common use-cases and scenarios for this App.
General Usage¶
The app holds two registries under one AI Tools menu.
- AI Tools → AI Models lists AI Providers and AI Models, the LLM endpoints and the models each one offers.
- AI Tools → MCP Models lists MCP Servers and MCP Tools, the MCP servers and what each one advertises.
Neither registry calls anything. Both record what exists so that other apps read one place.
AI providers and models¶
Add a provider¶
- Go to AI Tools → AI Models → AI Providers, then select Add.
- Enter a Name.
- Choose an External Integration. If the one you need does not exist yet, select the + button beside the field. A modal opens, you create the External Integration in place, and the new record is selected for you. You never leave the provider form.
- Leave OpenAI-compatible checked if the endpoint serves
GET /v1/models. - Optionally set a default num_predict and temperature.
The + button beside the field opens this modal. Fill it in, select Create, and the new External Integration is selected on the provider form behind it.
Discover the models a provider offers¶
Run Jobs → AI Models → Discover AI Models.
The job reads GET <remote_url>/v1/models from each OpenAI-compatible provider and syncs the
result. It is safe to run repeatedly:
- A model in the response that is not in the database is created.
- A model already in the database keeps its
enabled,num_predict, andtemperaturevalues. A user may have set them by hand, so the job never overwrites them. - A model in the database that the provider no longer offers is logged and kept. The job never deletes a record.
Leave AI Provider empty to run against every provider. Uncheck Enable new models to create new records in the disabled state for review.
A provider that is not OpenAI-compatible is skipped, and the job says so. No standard discovery endpoint exists for those.
The provider detail view lists everything the job found.
Override an inference parameter for one model¶
num_predict and temperature exist on both models. The provider value is the default. The model
value is an override. Leave the model value empty to inherit.
Read the effective value from the ORM:
Retire a model without deleting it¶
Clear the Enabled checkbox. The record stays, its history stays, and the discovery job leaves the flag alone. Consumers should skip a disabled model.
Record what a model costs¶
Set Input cost per million tokens and Output cost per million tokens on the model, so that a consumer can price a call before it makes one, or account for one afterwards. Output is usually several times dearer than input, which is why the two are separate fields.
An empty price means nobody has recorded one. Treat it as unknown, not as free.
Browse every model at once¶
The AI Models list shows every model across every provider. Filter it by provider, by enabled state, or by name.
MCP servers and tools¶
Register a server¶
- Go to AI Tools → MCP Models → MCP Servers and select Add.
-
Give the server a name and pick its External Integration.
If the integration does not exist yet, select the + button beside the field. The External Integration form opens in a modal over the page. Save it, and the new integration is selected without losing anything already typed. This needs the
extras.add_externalintegrationpermission; without it, Nautobot hides the button. -
Choose the Transport. Almost every remote server is
streamable-http, which is the only transport discovery reads. Astdioserver runs as a subprocess of its client, so a worker cannot reach one;sseis deprecated by the MCP specification and this app speaks none of it. Discovery skips both and says so, and their tools are entered by hand. - Save.
Discover what a server offers¶
Open the server and select Run Discovery, or run Jobs → MCP Models → MCP Server Discovery directly. Leave the server blank to discover every enabled server, which is the form to schedule.
Discovery writes down what the server said. It never enables a tool and never sets writable.
A discovered server shows what the operator set, what the server reported about itself, its advertised capabilities, its own instructions, and every tool it offers:
Review the tools¶
A newly discovered tool arrives enabled and marked writable=True. Assume it writes until somebody
has read what it does.
Go to AI Tools → MCP Models → MCP Tools, read each new tool's description and input schema, select
the ones that only read, and use Edit Selected to clear writable on all of them at once.
The Advertised Read Only column shows what the server itself claimed. Treat it as a hint from an unverified party: the MCP specification requires that a client not decide from it. It is there so a reviewer can compare the claim against the description.
Opening a tool shows both JSON Schemas the server advertised, and the fingerprint that says whether its contract has moved since the review:
Register a server Nautobot cannot reach¶
A stdio server has no endpoint for a worker to open. Register the server, then add its tools by
hand from AI Tools → MCP Models → MCP Tools → Add. Everything else about the record works normally.
Reading a registry from another app¶
This is what the app exists for. Both registries are plain Nautobot models, so another app reads them through the ORM or the REST API.
The AI registry¶
from nautobot_ai_models.models import AIModel
# Every model on offer, with its provider and endpoint ready to read.
available = AIModel.objects.filter(
enabled=True,
).select_related("provider__external_integration")
# The effective inference parameters, with the provider default filled in.
for ai_model in available:
print(ai_model.name, ai_model.resolved_num_predict, ai_model.resolved_temperature)
# What a million tokens cost. None means nobody recorded a price, not that it is free.
priced = available.exclude(input_cost_per_million=None)
The MCP registry¶
from nautobot_ai_models.models import MCPTool
# Every tool that is on offer, with its server and endpoint ready to read.
available = MCPTool.objects.filter(
enabled=True,
mcp_server__enabled=True,
).select_related("mcp_server__external_integration")
# The read-only subset, for a caller that runs without approval.
read_only = available.filter(writable=False)
Build the connection from the server's integration. Render the templated fields rather than reading them raw, because all three support Jinja2:
integration = tool.mcp_server.external_integration
url = integration.render_remote_url({"obj": tool.mcp_server})
headers = integration.render_headers({"obj": tool.mcp_server})
Notice that a tool's contract changed¶
definition_fingerprint is a digest of the tool's title, description, and both schemas. Record it
alongside whatever approval you granted. When it differs from the current value, the server changed
what the tool is after somebody reviewed it, and the review is stale.























