> ## Documentation Index
> Fetch the complete documentation index at: https://docs.heylua.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# LuaMCPServer

> A remote MCP server whose tools the agent can call, attached by URL over Streamable HTTP or SSE

`LuaMCPServer` declares a remote [MCP server](/concepts/mcp-servers) whose tools the model can call alongside your skills. Register instances on [`LuaAgent`](/reference/sdk/luaagent) under `mcpServers`, push them with `lua push mcp`, and activate them with `lua mcp activate`. Only remote servers over `streamable-http` or `sse` are supported; `stdio` is not.

*Verified against lua-cli 3.33.0.*

```ts theme={null}
import { LuaMCPServer } from 'lua-cli';
```

## Quick example

A Streamable HTTP server whose `Authorization` header is read from the agent's environment at runtime:

```ts src/mcp/DocsServer.ts theme={null}
import { LuaMCPServer, env } from 'lua-cli';

export default new LuaMCPServer({
  name: 'docs',
  transport: 'streamable-http',
  url: 'https://mcp.example.com/mcp',
  headers: () => ({ Authorization: `Bearer ${env('DOCS_MCP_TOKEN')}` }),
  timeout: 30000,
});
```

## Constructor

Creates an MCP server declaration from a `LuaMCPServerConfig`.

```ts theme={null}
new LuaMCPServer(config: LuaMCPServerConfig): LuaMCPServer
```

**Errors**

* `MCP server name is required` when `name` is empty.
* `stdio transport is not supported yet. Please use 'streamable-http' (recommended) or 'sse' transport instead. …` when `transport` is `'stdio'`.
* `URL is required for <transport> transport` when `url` is missing.

## Configuration

The config has five fields. There is no `description` field.

<ParamField path="name" type="string" required>
  Server-side identifier, and the name `lua push mcp --name` and `lua mcp activate` address. Kebab-case, for example `docs`. The model sees the server's tools as `<name>_<tool>`.
</ParamField>

<ParamField path="transport" type="'streamable-http' | 'sse'" required>
  `'streamable-http'` is the MCP standard transport; use it wherever the server supports it. `'sse'` is the legacy Server-Sent Events transport for servers that do not.
</ParamField>

<ParamField path="url" type="string | (() => string)" required>
  The server endpoint. A function is evaluated in the deployed runtime when the server is connected, so `env()` works inside it: `url: () => env('MCP_SERVER_URL') ?? 'https://mcp.example.com/mcp'`.
</ParamField>

<ParamField path="headers" type="Record<string, string> | (() => Record<string, string>)">
  Headers sent with every request. A function is evaluated at connection time like `url`; a static object is stored verbatim in the pushed version, so put secrets behind `env()` in a function.
</ParamField>

<ParamField path="timeout" type="number" default={60000}>
  Timeout in milliseconds for each request to the server, tool calls included. Tool discovery runs under a separate platform budget of a few seconds per server, so a larger value doesn't extend discovery.
</ParamField>

## Instance methods

| Method           | Returns                                                                                                   |
| ---------------- | --------------------------------------------------------------------------------------------------------- |
| `getName()`      | `string`                                                                                                  |
| `getTransport()` | `MCPTransport`                                                                                            |
| `getTimeout()`   | `number \| undefined`, as configured                                                                      |
| `getConfig()`    | The `LuaMCPServerConfig` passed to the constructor                                                        |
| `toJSON()`       | `{ name, transport, url, headers?, timeout? }`; function-valued `url` and `headers` are kept as functions |

## Lifecycle

* `lua push mcp --name <name>` creates or updates the server on the agent and records its id in `lua.skill.yaml`. MCP servers are not versioned: `lua deploy` has no `mcp` type, and a push replaces the configuration in place.
* A pushed server starts inactive. `lua mcp activate <name>` exposes its tools to the model; `lua push mcp --auto-deploy` activates in the same command. `lua mcp deactivate <name>` hides them again without deleting the server.
* Tools are discovered from the server, cached by the platform, and offered to the model as `<name>_<tool>`.
* `lua mcp list` shows every server and its state; `lua mcp delete <name>` removes one.

## Types

All of these are exported from `'lua-cli'`.

```ts theme={null}
type MCPTransport = 'sse' | 'streamable-http';

interface MCPServerBaseConfig {
  name: string;
  timeout?: number;
}

interface MCPStreamableHttpServerConfig extends MCPServerBaseConfig {
  transport: 'streamable-http';
  url: string | (() => string);
  headers?: Record<string, string> | (() => Record<string, string>);
}

interface MCPSSEServerConfig extends MCPServerBaseConfig {
  transport: 'sse';
  url: string | (() => string);
  headers?: Record<string, string> | (() => Record<string, string>);
}

type LuaMCPServerConfig = MCPSSEServerConfig | MCPStreamableHttpServerConfig;
```

## See also

* [MCP servers](/concepts/mcp-servers) — attach, push, activate; integration-provided servers
* [Use an MCP server](/build/use-an-mcp-server) — how-to
* [`lua mcp`](/reference/cli/mcp) — list, activate, deactivate, delete
* [`env`](/reference/sdk/env) — reading secrets inside `url` and `headers` resolvers
* [`LuaAgent`](/reference/sdk/luaagent) — the `mcpServers` field
