MCP Servers

August 2, 2026 · View on GitHub

MCP (Model Context Protocol) servers add third-party tools to LLxprt Code. They let you connect to external services, databases, APIs, or custom tooling that goes beyond the built-in tools.

This page walks through the tasks you perform with MCP servers, in order: add a server, authenticate to it, verify the connection, use what it exposes, restrict how much you trust it, troubleshoot, and remove it.

Add a server

You can add an MCP server two ways: with the llxprt mcp add command, or by editing your settings.json directly. Both write to the same configuration.

Via the CLI

llxprt mcp add my-server -- npx -y @example/mcp-server

This adds the server to your project configuration by default. To add it to your user configuration (available in every project), pass --scope user.

The add command writes to either the user settings.json or the project .llxprt/settings.json — see Application Directories.

Command:

llxprt mcp add [options] <name> <commandOrUrl> [args...]
  • <name> — a unique name for the server.
  • <commandOrUrl> — the command to run (for stdio) or the URL (for http, streamable-http, or sse).
  • [args...] — optional arguments for a stdio command. Use -- to separate flags that belong to the server command itself.

Options:

FlagDescriptionDefault
-s, --scopeConfiguration scope: user or project.project
-t, --transportTransport type: stdio, sse, http, streamable-http.stdio
-e, --envEnvironment variable, as KEY=value. Repeatable.
-H, --headerHTTP header, as Key: Value. For SSE and HTTP transports. Repeatable.
--timeoutConnection timeout in milliseconds.
--trustTrust the server (skip per-tool-call confirmation prompts).
--descriptionDescription for the server.
--include-toolsComma-separated list of tools to include.
--exclude-toolsComma-separated list of tools to exclude.

Examples

# stdio server with environment variables
llxprt mcp add -e API_KEY=123 -e DEBUG=true my-stdio-server /path/to/server arg1 arg2

# stdio server, separating server-specific args with --
llxprt mcp add python-server python server.py -- --server-arg my-value

# HTTP (Streamable HTTP) server
llxprt mcp add --transport http http-server https://api.example.com/mcp/

# HTTP server with an authentication header
llxprt mcp add --transport http secure-http https://api.example.com/mcp/ --header "Authorization: Bearer abc123"

# SSE server
llxprt mcp add --transport sse sse-server https://api.example.com/sse/

Via settings.json

Add entries under the mcpServers key:

{
  "mcpServers": {
    "my-server": {
      "command": "npx",
      "args": ["-y", "@example/mcp-server"],
      "env": {
        "API_KEY": "your-key"
      }
    }
  }
}

Transport types

stdio (default) — runs a local process:

{
  "my-server": {
    "command": "npx",
    "args": ["-y", "@example/mcp-server"]
  }
}

Streamable HTTP — preferred transport for remote MCP servers. Set the url and optionally type:

{
  "my-http": {
    "url": "https://mcp.example.com/mcp",
    "type": "http"
  }
}

"type": "streamable-http" is accepted as an alias for "type": "http" — both select the Streamable HTTP transport. If you omit type on a URL-based server, Streamable HTTP is used by default.

SSE — legacy remote transport for servers that have not migrated to Streamable HTTP:

{
  "my-remote": {
    "url": "https://mcp.example.com/sse",
    "type": "sse"
  }
}

The httpUrl field is deprecated. Use url with "type": "http" instead. If both httpUrl and url are present, httpUrl is used and a deprecation warning is logged.

Tool filtering

Limit which tools a server exposes with includeTools and excludeTools:

{
  "filteredServer": {
    "command": "python",
    "args": ["-m", "my_mcp_server"],
    "includeTools": ["safe_tool", "file_reader", "data_processor"],
    "excludeTools": ["dangerous_tool"]
  }
}

excludeTools takes precedence over includeTools.

Authenticate

Remote MCP servers may require authentication. LLxprt Code supports OAuth and custom HTTP headers, and can impersonate a service account for Google Cloud IAP-protected services.

OAuth

Remote servers that require OAuth are supported through an authorization-code flow with PKCE and a loopback redirect. Whether OAuth activates, and when you must step in manually, depends on how the server is configured and how it responds at connect time.

Pre-configured OAuth (oauth.enabled: true). When a server entry sets oauth.enabled to true, LLxprt Code treats that server as OAuth-protected on every connect. It loads any stored access token; if none is stored (or the stored token is expired and cannot be refreshed), the connect fails with a message directing you to run /mcp auth <server>:

MCP server '<server>' requires OAuth authentication.
Please authenticate using the /mcp auth command.

OAuth does not start automatically for a oauth.enabled: true server at connect time — you must complete the interactive flow once via /mcp auth.

Discovery-driven OAuth (no oauth block). When a server has no explicit OAuth configuration, LLxprt Code first tries to connect directly. If the server responds with a 401 and supplies OAuth metadata (via a WWW-Authenticate header or /.well-known/oauth-authorization-server), LLxprt Code attempts the full flow automatically: discover the endpoints, register a client if needed, open the browser for authorization, and store the token. This automatic path only succeeds when the server's OAuth metadata is discoverable; if discovery or the flow fails, LLxprt Code reports that you must authenticate manually with /mcp auth <server>.

Dynamic client registration (RFC 7591) is conditional, not unconditional. During the flow, registration is skipped when you already provide a clientId in the oauth block. When no clientId is configured, LLxprt Code looks for a registration endpoint in the server's authorization-server metadata. If the server exposes one, it registers dynamically; if the server exposes no registration endpoint and no clientId was supplied, registration fails with an error and the flow does not proceed.

Browser-based authorization. The authorization step always opens a browser to the provider's consent page. The OAuth configuration displayed in the terminal includes the full authorization URL so you can copy and paste it manually if the browser does not launch on its own. There is no MCP-specific headless or manual-paste OAuth mode.

You can pre-configure OAuth explicitly. Set enabled: true to activate OAuth for the server; the remaining fields are optional and, if omitted, are discovered automatically via /.well-known/oauth-authorization-server:

{
  "my-oauth-server": {
    "url": "https://mcp.example.com/mcp",
    "type": "http",
    "oauth": {
      "enabled": true,
      "clientId": "your-client-id",
      "authorizationUrl": "https://auth.example.com/authorize",
      "tokenUrl": "https://auth.example.com/token",
      "scopes": ["read", "write"]
    }
  }
}

If a server's OAuth discovery or registration does not work with the built-in flow, fall back to the mcp-remote stdio bridge:

{
  "mcpServers": {
    "webflow": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://mcp.webflow.com/mcp"],
      "type": "stdio"
    }
  }
}

To authenticate or re-authenticate a server during a session:

/mcp auth <server-name>

This runs the interactive OAuth flow (discovery, optional registration, browser authorization, token storage) and then re-discovers that server's tools. Running /mcp auth with no argument lists the servers that are configured with OAuth or have reported an authentication requirement.

Custom headers

For servers that use static API keys or bearer tokens, pass headers directly:

{
  "mcpServers": {
    "httpServerWithAuth": {
      "url": "http://localhost:3000/mcp",
      "type": "http",
      "headers": {
        "Authorization": "Bearer your-api-token",
        "X-Custom-Header": "custom-value"
      }
    }
  }
}

Service-account impersonation

For Google Cloud IAP-protected services, you can impersonate a service account:

{
  "mcpServers": {
    "myIapProtectedServer": {
      "url": "https://my-iap-service.run.app/sse",
      "type": "sse",
      "authProviderType": "service_account_impersonation",
      "targetAudience": "YOUR_IAP_CLIENT_ID.apps.googleusercontent.com",
      "targetServiceAccount": "your-sa@your-project.iam.gserviceaccount.com"
    }
  }
}

Verify it worked

After adding a server, check that it connected successfully.

With /mcp

/mcp

This lists every configured server, its connection status, and a count of tools, prompts, and resources it exposes. A server entry looks like:

[READY] my-server - Ready (3 tools, 1 prompt, 2 resources)

Status indicators:

  • [READY] — connected and available.
  • [STARTING] — connecting; first startup may take longer.
  • [DISCONNECTED] — not connected or failed.

You can show tool descriptions and parameter schemas:

/mcp desc      # show server and tool descriptions
/mcp schema    # show tool parameter schemas (also shows descriptions)
/mcp nodesc    # hide descriptions

If no servers are configured, /mcp links you to this documentation.

With llxprt mcp list

Outside a session, test whether each server is reachable:

llxprt mcp list

This attempts a live connection to each server and prints its name, configuration, and whether the connection succeeded.

Connection states

Each server tracks one of these states:

  • Disconnected — not connected, or a connection error occurred.
  • Connecting — a connection attempt is in progress.
  • Connected — the server is connected and ready.

Apply configuration changes

After editing settings.json or running llxprt mcp add or llxprt mcp remove in another terminal, apply the persisted changes to the current session:

/mcp reload

Reloading adds newly configured servers, disconnects removed servers, and reconnects servers whose configuration changed. Use /mcp refresh when you only want to restart the servers already loaded, without rereading configuration.

Changing OAuth settings may still require /mcp auth <server>. Installing or removing an extension still requires the extension reload flow or a new session.

Use it

Once a server is connected, its tools, prompts, and resources become available.

Tools

MCP tools work like built-in tools. The model selects them based on your request, asks for confirmation before running each call (unless the server is trusted — see Restrict trust), executes them, and displays the results.

Tool names are namespaced as mcp__<server-name>__<tool-name> so tools from different servers never collide.

Prompts as slash commands

MCP servers can define prompts — reusable templates that appear as / commands in LLxprt Code. Each prompt becomes a slash command you can invoke by name.

/poem-writer --title="LLxprt Code" --mood="reverent"

Or, using positional arguments:

/poem-writer "LLxprt Code" reverent

When you invoke a prompt, LLxprt Code calls the prompts/get method on the MCP server with the arguments you provide. The server substitutes the arguments into the prompt template and returns the final text, which is sent to the model.

Use <prompt-name> help to see the arguments a prompt accepts, or /help to see all available commands.

Defining prompts on the server

Here is a minimal stdio MCP server that defines a prompt using the @modelcontextprotocol/sdk:

import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { z } from 'zod';

const server = new McpServer({
  name: 'prompt-server',
  version: '1.0.0',
});

server.registerPrompt(
  'poem-writer',
  {
    title: 'Poem Writer',
    description: 'Write a nice haiku',
    argsSchema: { title: z.string(), mood: z.string().optional() },
  },
  ({ title, mood }) => ({
    messages: [
      {
        role: 'user',
        content: {
          type: 'text',
          text: `Write a haiku${mood ? ` with the mood ${mood}` : ''} called ${title}. Note that a haiku is 5 syllables followed by 7 syllables followed by 5 syllables.`,
        },
      },
    ],
  }),
);

const transport = new StdioServerTransport();
await server.connect(transport);

Resources

MCP servers can expose resources — readable content you can pull into your conversation. You reference a resource with the @ syntax:

@serverName:resourceUri

For example:

@docs:file:///workspace/README.md

When this pattern matches a discovered resource, LLxprt Code reads it via resources/read and injects the content into the request. Binary resources are shown as a safe placeholder summary (MIME type and size) rather than raw bytes.

Resources also appear in /mcp output, which lists each server's discovered resource names and URIs.

Rich content from tools

MCP tools can return rich, multi-part content in a single response — text, images, audio, and embedded resources. To return rich content, your tool's response must follow the MCP specification for a CallToolResult: the content field is an array of content blocks.

Supported block types:

  • text
  • image
  • audio
  • resource (embedded content)
  • resource_link
{
  "content": [
    {
      "type": "text",
      "text": "Here is the logo you requested."
    },
    {
      "type": "image",
      "data": "BASE64_ENCODED_IMAGE_DATA_HERE",
      "mimeType": "image/png"
    },
    {
      "type": "text",
      "text": "The logo was created in 2025."
    }
  ]
}

LLxprt Code extracts text blocks and combines them into the model's context, presents images and audio as separate parts, and shows a readable summary in the CLI.

Restrict trust

MCP servers run code and make network requests. Control how much trust each server gets.

Confirmation prompts

By default, every MCP tool call asks for confirmation before it runs. When prompted, you can choose to:

  • Proceed once — run this call only.
  • Always allow this tool — skip confirmation for this specific tool going forward.
  • Always allow this server — skip confirmation for every tool from this server.
  • Cancel — abort the call.

The trust option

The trust option bypasses all confirmation dialogs for a server. Use it only for servers you completely control:

{
  "my-server": {
    "command": "npx",
    "args": ["-y", "@example/mcp-server"],
    "trust": true
  }
}

You can also set trust when adding a server:

llxprt mcp add --trust my-server /path/to/server

Trust bypasses confirmation only when the working directory is a trusted folder. In an untrusted folder, confirmation is still required.

Security considerations

  • Access tokens. Be careful when configuring environment variables or headers that contain API keys or tokens.
  • Personal access tokens. Broadly scoped tokens can leak information between repositories or projects.
  • Sandboxing. When running in a sandbox, MCP servers must be available inside the container. If your server uses npx, the npm package must be installable within the sandbox environment.

Lazy MCP schema loading

When you have many MCP servers with large tool schemas, every tool schema is sent to the model on each request. The mcp.lazy setting defers those schemas so only the servers you actually need are published.

  • Servers stay connected. Discovery, connection, tool registration, prompts, and resources all work as before. Only model-facing schema publication is deferred.
  • The model gets an activate_mcp_server tool. Its description lists each deferred server's name, tool count, and up to 12 tool names — never full parameter schemas. The model calls it with a server name to activate that server.
  • Activation is session-scoped. Once activated, a server's full schemas are published for the rest of the session. There is no automatic deactivation; to restart, create a new session.
  • Eager exceptions. Use mcp.eagerServers to keep specific servers always-eager even when lazy mode is on.

Scope: ephemeral (also persistable to a profile). Default: false (eager). Persistable: yes.

Enable lazy mode:

/set mcp.lazy true

Keep specific servers eager:

/set mcp.eagerServers ["my-important-server","another-server"]

/set updates ephemeral settings but does not republish tools in an already-initialized chat. To apply lazy mode, save and reload a named profile (/profile save lazy-mcp, then /profile load lazy-mcp) or start a new session with that profile.

Tradeoffs

Lazy mode reduces token overhead for sessions with large MCP tool sets, but the model must spend a turn calling activate_mcp_server before it can use a deferred server's tools. For sessions where you always use every MCP tool, eager mode (the default) is better.

Troubleshoot

Server won't connect

  • Verify the command, args, and cwd are correct in your configuration.

  • For stdio servers, run the command manually to see startup errors.

  • Check the server's dependencies are installed.

  • Enable debug logging for detailed connection output:

    llxprt --debug llxprt:mcp:*
    

    You can also use LLXPRT_DEBUG=llxprt:mcp:*. Debug output is written to a JSONL file in your log directory and to stderr. Use F12 to open the debug console in an interactive session.

No tools discovered

  • Run /mcp to confirm the server is connected.
  • The server may need time to start — tools appear after the connection is established.
  • If tool names conflict with built-in tools, the built-in tool takes precedence.
  • Verify the server actually registers tools and implements the MCP tool-listing protocol correctly.

Tools not executing

  • Ensure your tool accepts the parameters the model sends.
  • Verify your input schemas are valid JSON Schema.
  • Check whether the tool is throwing unhandled exceptions (review server logs).
  • If calls time out, increase the timeout setting.

OAuth failures

  • Ensure the OAuth URLs and client ID are correct.
  • Check whether the server's OAuth flow requires specific scopes.
  • Try re-authenticating: /mcp auth <server>.
  • Remove cached tokens from your OS-standard data directory and reconnect.

"SSE is no longer supported" error

Some MCP providers have deprecated their SSE endpoint in favor of Streamable HTTP. Switch your configuration from the SSE endpoint to the Streamable HTTP endpoint with "type": "http":

{
  "mcpServers": {
    "webflow": {
      "url": "https://mcp.webflow.com/mcp",
      "type": "http"
    }
  }
}

If the provider's OAuth flow does not work with the automatic mode, fall back to the mcp-remote stdio bridge as shown in Authenticate.

Environment variables not reaching the server

  • Variables in the env block are passed to the server process.
  • A stdio server inherits the full parent environment (the environment LLxprt Code itself runs with). Entries in the env block are applied on top of, and override, any inherited value with the same name.

Security implication. Because a stdio server inherits the parent environment, the server process can see every variable in it — including API keys, tokens, and other secrets. The env block is not an allowlist: it only adds or overrides entries on top of the inherited environment. It cannot remove or hide inherited variables such as an API key that LLxprt Code itself uses. To prevent a server from seeing secrets it should not, do one of the following:

  • Launch LLxprt Code from a sanitized environment where the secrets are not set, then pass only what the server needs via its env block.
  • Wrap the server command in a script that unsets the sensitive variables before starting the server process.
  • Run the server (and LLxprt Code) inside a sandbox so the inherited environment is already bounded.

Sandbox compatibility

When sandboxing is enabled, MCP servers must be available inside the container:

  • Use Docker-based servers that include all dependencies.
  • Ensure server executables are reachable from inside the sandbox.
  • Configure the sandbox to allow any network connections the server needs.
  • Verify required environment variables are passed through.

Remove a server

llxprt mcp remove my-server

By default this removes the server from your project configuration. To remove it from your user configuration, pass --scope user:

llxprt mcp remove --scope user my-server

If the server is not found in the specified scope, the command reports that and makes no change.

You can also remove a server by deleting its entry from mcpServers in your settings.json, then running /mcp reload to apply the change to a running session.