MCP tools
=========

`MCP <https://modelcontextprotocol.io>`_  (Model Context Protocol) is a standard way for a server to
advertise a set of callable tools. ``aidb.import_mcp_tools()`` registers
an external MCP server and imports the tools it advertises, so your
agents can call them alongside AIDB’s own native and SQL tools:

.. code:: sql

   SELECT aidb.import_mcp_tools(
       name        => weather,
       url         => https://weather.example.com/mcp,
       transport   => streamable_http,  -- optional; streamable_http or sse (see below). Default: streamable_http
       headers     => NULL,               -- optional; request headers to send, for example, an auth token. Mutually exclusive with headers_env. Default: NULL
       tool_filter => NULL,               -- optional; import only these tool names. Default: NULL (import everything the server advertises)
       headers_env => NULL                -- optional; env var holding the headers JSON instead of storing it. Mutually exclusive with headers. Default: NULL
   );

   SELECT aidb.create_agent(trip_planner, Help plan trips, checking weather when useful., my_gpt,
       tools => ARRAY[get_forecast]);  -- a tool the weather server advertised

.. csv-table::
  :header: Parameter,Type,Default,Description
  :widths: 15,12,12,20
  :align: left
  :class: longtable

  `name`,TEXT,Required,Unique name for the server registration.
  `url`,TEXT,Required,The server's MCP endpoint URL.
  `transport`,TEXT,`'streamable_http'`,`'streamable_http'` or `'sse'` — only `'streamable_http'` is fully supported today.
  `headers`,JSONB,`NULL`,"Request headers to send, for example, `{""Authorization"": ""Bearer ...""}`. Mutually exclusive with `headers_env`."
  `tool_filter`,TEXT,`NULL`,Import only these tool names. Omit to import everything the server advertises.
  `headers_env`,TEXT,`NULL`,"Name of an environment variable holding the headers JSON, read fresh on each use instead of storing it. Mutually exclusive with `headers`."

``import_mcp_tools`` validates the server by calling its ``tools/list``
endpoint before registering anything — if it’s unreachable or advertises
nothing matching ``tool_filter`` , nothing is stored. The tools it
returns are cached immediately, so they show up in ``aidb.tools`` right
away rather than after a separate refresh.

Only the ``streamable_http`` transport (the default) actually works
end-to-end today; ``sse`` is accepted as a value but isn’t fully
implemented yet.

Reaching an MCP server is an outbound network call — subject to the same
:ref:`aidb.egress_allowlist <Configuring AIDB>`  restriction as model provider calls and HuggingFace
downloads.

Authentication
--------------

Pass ``headers`` for a server that needs specific request headers (most
commonly an ``Authorization`` bearer token):

.. code:: sql

   SELECT aidb.import_mcp_tools(
       name    => internal_crm,
       url     => https://crm.internal.example.com/mcp,
       headers => {"Authorization": "Bearer sk-..."}::JSONB
   );

``headers`` is stored in ``aidb.mcp_registry`` , but ``aidb_users`` has
no ``SELECT`` access to that column — only AIDB’s own internal calls (to
validate, refresh, or invoke the server’s tools) can read it back.

!!!note Prefer not to store the secret in the table at all? Pass
``headers_env`` instead: name an environment variable (read fresh from
the Postgres process’s own environment on every call) holding a JSON
object of headers, in the same shape ``headers`` would take. ``headers``
and ``headers_env`` are mutually exclusive. The variable’s name must
start with the prefix configured by :ref:`aidb.env_var_allowed_prefix <Configuring AIDB>`  (``AIDB_`` by default)
— the same mechanism and GUC used by :ref:`credentials_env <Pipelines API reference>`  for model
credentials.

Filtering which tools are imported
----------------------------------

By default, every tool the server advertises is imported. Pass
``tool_filter`` to import only specific ones by name:

.. code:: sql

   SELECT aidb.import_mcp_tools(
       name        => weather,
       url         => https://weather.example.com/mcp,
       tool_filter => ARRAY[get_forecast, get_alerts]
   );

Keeping the tool list current
-----------------------------

AIDB doesn’t re-fetch a server’s tool list on every query —
``aidb.tools`` only shows entries cached within the last 60 minutes, so
a ``SELECT`` never has a network side effect. Call
``aidb.refresh_mcp_tools()`` to re-fetch and update the cache on demand
(for example, after the server adds a new tool):

.. code:: sql

   SELECT aidb.refresh_mcp_tools(weather);

It returns the number of tools now cached (after ``tool_filter``
applies). Changing a server’s registration — its ``url`` , ``transport``
, ``headers`` , or ``tool_filter`` , via re-running ``import_mcp_tools``
-equivalent settings — also invalidates its cache automatically.

Removing a server
-----------------

.. code:: sql

   SELECT aidb.delete_tool(weather);

Deleting an MCP server removes every tool it advertised along with it —
there’s no way to remove just one of its tools individually; use
``tool_filter`` to curate which of its tools are exposed instead.

Exposing AIDB’s own tools over MCP
----------------------------------

``aidb.get_mcp_tools()`` returns every tool currently in ``aidb.tools``
(native, SQL, and imported MCP tools alike), reshaped as MCP
``tools/list`` line items — useful if some other system needs AIDB’s
tool catalog in MCP’s own descriptor format:

.. code:: sql

   SELECT * FROM aidb.get_mcp_tools();

This only converts AIDB’s tool catalog into MCP’s descriptor shape —
AIDB doesn’t run an MCP server endpoint of its own that an external MCP
client could connect to and actually invoke these tools over the
network.
