---
title: Tools over MCP
description: Connect an external AI client to your RELKIT tools through the built-in MCP endpoint.
pagination: false
sidebar:
  icon: plug
---

Model Context Protocol (MCP) lets an AI client discover and call the tools you expose from your application. RELKIT serves tools at `/mcp` using **Streamable HTTP**. You do not need to define an agent or write a separate MCP server.

## Pre-setup

MCP needs no provider service or new `defineEnv` fields by itself. Configure a tool's dependencies
through their modules' local Docker setup when required; keep your existing environment contract.

The endpoint is opt-in. First [define a function-backed tool](/docs/modules/ai/function-tools) in your
existing minimal app. From its root, install only the MCP SDK, then set `server.mcp` to `true`
in the existing `relkit.config.ts`, preserving other server settings:

{/* Generated by apps/docs/scripts/generate.ts. Do not edit. */}

From this guide's application/package root, install only its selected requirements:

```sh
bun add @modelcontextprotocol/server@2.3.0
```

Keep these owner-specific versions and the lockfile together. Runtime SDKs belong in `dependencies`; build/type tooling belongs in `devDependencies`. Installing an adapter does not supply its optional SDK peers or enable the feature's configuration.

This tool-only path needs no `@relkit/langchain`, model SDK or model key. Startup validates the
selected SDK before readiness. Ordinary REST/RPC and OpenAPI do not load MCP.

## Choose which tools to expose

When the endpoint is enabled, discovered tools created with `defineTool` or `.asTool()` are eligible
by default. Omitting a tool's `mcp` field is equivalent to `mcp: true`; the server endpoint itself
defaults to disabled. For example, the [greeting tool](/docs/modules/ai/function-tools) appears as
`hello.lookup`, with a `name` argument and a `message` result.

Set an explicit `timeoutMs` on tools you expose through MCP. The current runtime fails MCP calls when this option is omitted; the greeting example uses `2_000` milliseconds.

An agent's `tools` array controls that agent only. It does not limit which tools MCP clients can discover or call.

## Disable MCP for one tool

Set `mcp: false` in either `defineTool` or `.asTool()`:

```ts title="src/services/hello/tools/private-lookup.tool.ts"
import hello from "@app/services/hello/functions/hello.function.js";

export const privateLookup = hello.asTool({
  id: "hello.private-lookup",
  description: "Read a greeting inside this app only",

  sideEffect: "read",
  approval: "never",
  timeoutMs: 2_000,
  mcp: false,
});
```

`hello.private-lookup` will not appear in MCP's tool list or be callable over MCP. You can still add it to a RELKIT agent's `tools` array.

## Disable the MCP endpoint

Set `server.mcp` to `false` in your existing `relkit.config.ts`, preserving your other server settings:

```ts title="relkit.config.ts — inside defineApp()"
server: {
  port: 3000,
  mcp: false,
},
```

This disables `/mcp` for the entire app. It does not disable ordinary tool calls or your agents' declared tools.

## Connect a client

Start your existing app from its root:

```sh
bun run check
bun run dev
```

If the checked graph requires a model binding, supply its named credentials before starting it. Calling the
greeting tool itself does not need a model, so a tool-only app remains key-free. No `RELKIT_ENV` value installs
a hidden model provider.

In a client that supports Streamable HTTP, add your backend's MCP URL. With the default backend port, use `http://localhost:3000/mcp`, not the RELKIT Inspector port `3210`.

You can also list tools with the MCP Inspector CLI. Run this in a second terminal:

```sh
bunx @modelcontextprotocol/inspector@2.3.0 --cli \
  http://localhost:3000/mcp \
  --transport http \
  --method tools/list
```

With the greeting example installed, the response includes `hello.lookup` and its input schema. This command does not call a language model.

## Call a tool

Invoke the greeting tool directly through MCP:

```sh
bunx @modelcontextprotocol/inspector@2.3.0 --cli \
  http://localhost:3000/mcp \
  --transport http \
  --method tools/call \
  --tool-name hello.lookup \
  --tool-arg name=Ada
```

The result includes `structuredContent` with `{ "message": "Hello, Ada!" }`. RELKIT validates the arguments against the function's input schema before calling it.

## Protect access

Before exposing the backend outside your machine, authenticate requests to `/mcp` and authorize actions in each target function. Hiding a tool from an agent is not access control for MCP. Your MCP client must send the credentials your app expects.

> **Approval-required tools cannot run over MCP yet**
>
> MCP currently rejects tools with `approval: "always"`, and tools with `approval: "on-write"` when
> their side effect is `write` or `external`. It returns an approval-required error without running
> the function. A client's confirmation dialog does not satisfy this policy. Do not remove a
> required approval just to make a call succeed.

If no tools appear, check that the files are exported under your domain's `tools` directory, `mcp` is not disabled on the tool or server, and the app has reloaded.
