Skip to content

Latest commit

 

History

History
1063 lines (790 loc) · 30.8 KB

File metadata and controls

1063 lines (790 loc) · 30.8 KB

MCP (Model Context Protocol) Integration

The Inference Gateway CLI supports direct integration with MCP (Model Context Protocol) servers, allowing you to extend the LLM's capabilities with custom tools from external services.

MCP servers must speak MCP 2026-07-28. infer uses the stateless 2026-07-28 revision only: there is no initialize handshake, no session, and no fallback to older revisions. A server on an earlier revision is shown as unavailable with an error naming the versions it supports. Current SDKs serve 2026-07-28: TypeScript SDK v2 (createMcpHandler), Go go-sdk v1.7+ with StreamableHTTPOptions{Stateless: true}, and Python mcp 2.x. The Inference Gateway's own /mcp endpoint speaks it too, so one entry can expose every server behind the gateway (see Example 4).

Table of Contents

Overview

What is MCP?

Model Context Protocol (MCP) is a standardized protocol for connecting AI models to external tools and data sources. It enables:

  • Stateless tool execution: Each request is independent - no handshake, no session
  • Streamable HTTP transport: Each request is one HTTP POST, answered with JSON or a per-request SSE stream
  • Dynamic tool discovery: Tools are discovered at runtime
  • Schema-based validation: JSON Schema for tool parameters

Architecture

┌──────────────────────────────────────────────────────────────────┐
│                         Inference CLI                            │
│                                                                  │
│  ┌────────────────┐              ┌─────────────────┐             │
│  │ MCP            │              │  Tool Registry  │             │
│  │ Supervisor     │──register──▶ │                 │             │
│  │                │   tools      │  • Bash         │             │
│  │ • Discovery    │              │  • Read         │             │
│  │ • Execution    │              │  • MCP_*        │             │
│  └────────┬───────┘              └─────────────────┘             │
│           │                                                      │
└───────────┼──────────────────────────────────────────────────────┘
            │
            │ Streamable HTTP, MCP 2026-07-28 (stateless)
            │
            ├────────────────────┬────────────────────┐
            │                    │                    │
            ▼                    ▼                    ▼
   ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐
   │  MCP Server     │  │  MCP Server     │  │  MCP Server     │
   │  (Filesystem)   │  │  (Database)     │  │  (Custom API)   │
   │                 │  │                 │  │                 │
   │  Tools:         │  │  Tools:         │  │  Tools:         │
   │  • read_file    │  │  • query        │  │  • fetch_data   │
   │  • write_file   │  │  • list_tables  │  │  • process      │
   │  • list_dir     │  │  • describe     │  │  • transform    │
   └─────────────────┘  └─────────────────┘  └─────────────────┘

Key Features

  • Direct connections: CLI connects directly to MCP servers, or to the gateway's /mcp as a single entry
  • Stateless design: No handshake or session; every request carries its protocol version
  • Auto-start servers: Automatically start and manage MCP servers in OCI/Docker containers
  • Automatic port assignment: No need to manually configure ports for auto-started servers
  • Per-server configuration: Enable/disable servers independently
  • Tool filtering: Include/exclude specific tools per server
  • Concurrent discovery: Servers are queried in parallel
  • Resilient: Failed servers don't prevent CLI startup
  • Mode-aware: MCP tools automatically excluded from Plan mode

Quick Start

1. Initialize Project

cd your-project
infer init

This seeds ~/.infer/mcp.yaml with example configuration. Manage MCP servers with infer mcp ..., which writes to that userspace file unless --project sends the change to ./.infer/mcp.yaml instead.

2. Configure MCP Server

Edit ~/.infer/mcp.yaml:

enabled: true
connection_timeout: 30
discovery_timeout: 30

servers:
  - name: "filesystem"
    host: "localhost"
    port: 3000
    path: "/mcp"
    enabled: true
    description: "File system operations"

3. Start MCP Server

Option A: Auto-start with OCI container (recommended)

Configure the server to start automatically when the CLI launches:

servers:
  - name: "demo-server"
    enabled: true
    run: true  # Auto-start in container
    oci: "mcp-demo-server:latest"
    description: "Demo MCP server"

The CLI will automatically:

  • Pull the OCI image if needed
  • Start the container in the background
  • Assign an available port (starting from 3000)
  • Configure healthchecks
  • Connect to the server

Option B: Manual start with Docker Compose

Run the included demo MCP server manually:

cd examples/mcp
docker compose up -d

Then configure the server URL:

servers:
  - name: "demo-server"
    host: "localhost"
    port: 3000
    path: "/mcp"
    enabled: true

The demo server provides four example tools: get_time, calculate, list_files, and get_env.

4. Verify Tools

infer chat

Type /help to see available tools. MCP tools appear as MCP_<server>_<tool>.

Outside of chat, infer mcp status dials each enabled server once and reports the same connected/total (tools) counts the status bar shows; infer mcp status <server> probes one server and --format json prints a machine-readable report (total_servers, connected_servers, total_tools, per-server connected, tools, error).

Configuration

Global Settings

Located in ~/.infer/mcp.yaml (or ./.infer/mcp.yaml for a project override):

Setting Type Default Description
enabled boolean false Global MCP enable/disable toggle
connection_timeout integer 30 Default connection timeout (seconds)
discovery_timeout integer 30 Tool discovery timeout (seconds)
liveness_probe_enabled boolean true Enable health monitoring
liveness_probe_interval integer 10 Health check interval (seconds)
max_retries integer 10 Maximum retry attempts before marking server as permanently failed
servers array [] List of MCP server configurations

Per-Server Configuration

Each server in the servers array supports:

Field Required Type Description
name ✅ string Unique server identifier
enabled ✅ boolean Enable/disable this server
timeout ❌ integer Override global timeout
description ❌ string Human-readable description
include_tools ❌ array Include specific tools
exclude_tools ❌ array Exclude specific tools
run ❌ boolean Auto-start server in OCI container (default: false)
host ❌ string Container host (default: localhost)
scheme ❌ string URL scheme (default: http)
port ❌ integer Simple port mapping (auto-assigned if omitted)
ports ❌ array Advanced Docker-compose style port mappings
path ❌ string HTTP path (default: /mcp)
oci ❌* string OCI/Docker image (*required if run=true)
args ❌ array Container startup arguments
env ❌ object Environment variables for container
volumes ❌ array Docker volume mounts
startup_timeout ❌ integer Container startup timeout in seconds (default: 30)
health_cmd ❌ string Custom Docker healthcheck command

Manual servers (run: false): set host / port / path to point at the running server's MCP endpoint. The URL is built as {scheme}://{host}:{port}{path} (defaults: http, localhost, /mcp).

Tool Filtering

Include Tools

When include_tools is specified, only these tools are exposed:

servers:
  - name: "database"
    host: "localhost"
    port: 3001
    path: "/mcp"
    enabled: true
    include_tools:
      - "query"
      - "describe_table"
      - "list_tables"

Exclude Tools (Blacklist)

When exclude_tools is specified, these tools are hidden:

servers:
  - name: "filesystem"
    host: "localhost"
    port: 3000
    path: "/mcp"
    enabled: true
    exclude_tools:
      - "delete_file"  # Exclude dangerous operations
      - "format_disk"

Precedence

  • If include_tools is set, it takes precedence (strict allowed list)
  • If only exclude_tools is set, all tools except excluded ones are available
  • If neither is set, all tools from the server are available

Environment Variables

All configuration values support environment variable expansion:

servers:
  - name: "filesystem"
    host: "${MCP_FILESYSTEM_HOST}"
    port: 3000
    path: "/mcp"
    enabled: true

Override via environment:

export INFER_MCP_ENABLED=true
export INFER_MCP_CONNECTION_TIMEOUT=60
export MCP_FILESYSTEM_HOST=localhost

Tool Discovery

Discovery Process

  1. CLI startup: The MCP supervisor starts
  2. Concurrent discovery: Each enabled server is queried in parallel
  3. Protocol check: server/discover must list 2026-07-28; a server that doesn't is marked unavailable
  4. Tool listing: tools/list, following pagination cursors
  5. Tool registration: Discovered tools are registered in the tool registry
  6. Filtering applied: Include/exclude rules are enforced
  7. Naming: Tools are prefixed with MCP_<server>_<tool>

Discovery Timeout

Configure discovery timeout to prevent slow servers from delaying startup:

discovery_timeout: 30  # seconds

Failed Servers

If a server fails during discovery:

  • A warning is logged
  • Other servers continue normally
  • CLI starts successfully
  • Failed server's tools are not available

Failures are logged at debug level per retry attempt, with an error once retries are exhausted:

{"level":"debug","msg":"mCP server health check failed (tool discovery failed)","server":"filesystem","error":"connection refused"}
{"level":"error","msg":"mCP server permanently failed after max retries","server":"filesystem","error":"connection refused"}

Successful discovery is logged with server and toolCount fields:

{"level":"info","msg":"mCP server tools discovered successfully","server":"database","toolCount":5}

Liveness Probes

The CLI includes health monitoring for MCP servers to detect disconnections and display real-time connection status in the UI.

Health Monitoring

  1. Background Monitoring: Goroutines periodically send server/discover to each enabled MCP server
  2. Status Updates: Connection changes trigger UI updates via event channels
  3. Real-time Display: Status bar shows "MCP: X/Y" (connected/total)
  4. Auto-reconnection: When server reconnects, tools become available immediately

Probe Configuration

liveness_probe_enabled: true   # Enable health monitoring
liveness_probe_interval: 10    # Seconds between health checks
max_retries: 10                # Maximum retry attempts before permanent failure

Status Display

The status bar displays current MCP server health:

MCP: 0/1    # 0 connected, 1 total (server down)
MCP: 1/1    # 1 connected, 1 total (server healthy)
MCP: 2/3    # 2 connected, 3 total (1 server down)

infer mcp status reports the same counts from outside a chat session.

Detached Servers

A run: true server is normally started when a session begins and stopped when it ends. To keep it running across sessions (for example when the desktop app starts one infer headless process per message), start it detached:

infer mcp start            # every enabled run: true server
infer mcp start demo       # one server
infer mcp stop demo

Detached containers are named inference-mcp-<server>-shared. A session that finds one running connects to it instead of starting its own copy and leaves it running on exit.

Probe Behavior

  • Initial State: Shows total servers, all marked disconnected
  • First Connect: When the server answers server/discover and tools/list, status updates to connected
  • Disconnection: A failed probe marks the server as disconnected
  • Reconnection: A successful probe after failure marks the server as connected
  • Event-Driven: UI updates only when status actually changes (no polling)

Disabling Probes

To disable health monitoring:

liveness_probe_enabled: false

With probes disabled, the MCP status will not appear in the status bar. Servers are still checked during initial tool discovery at startup.

Tool Execution

Execution Flow

  1. LLM requests tool: MCP_filesystem_read_file
  2. Tool lookup: Registry finds MCP tool wrapper
  3. Server call: One tools/call POST carrying the protocol version (no session)
  4. Result formatting: Content blocks flattened to text for LLM/UI

Timeouts

Per-server timeout configuration:

servers:
  - name: "slow-server"
    host: "slow-service"
    port: 8080
    path: "/mcp"
    timeout: 120  # Override global timeout

Timeout precedence:

  1. Server-specific timeout
  2. Global connection_timeout
  3. Default: 30 seconds

Error Handling

Common errors and handling:

Error Behavior
Server unreachable Tool execution fails, error returned to LLM
Timeout exceeded Connection closed, timeout error returned
Invalid arguments Validation error before server call
Server error Error response passed to LLM
Tool result with isError Execution fails, the tool's message is passed to LLM
Tool asks for input (input_required) Execution fails; elicitation and sampling are not supported

Examples

Example 1: Filesystem MCP Server

# .infer/mcp.yaml
enabled: true
connection_timeout: 30
discovery_timeout: 30

servers:
  - name: "filesystem"
    host: "localhost"
    port: 3000
    path: "/mcp"
    enabled: true
    description: "Sandboxed file system operations"
    exclude_tools:
      - "delete_file"
      - "delete_directory"

Available tools:

  • MCP_filesystem_read_file
  • MCP_filesystem_write_file
  • MCP_filesystem_list_directory
  • MCP_filesystem_create_directory
  • MCP_filesystem_get_file_info

Example 2: Multiple Servers

enabled: true

servers:
  # Filesystem access
  - name: "filesystem"
    host: "localhost"
    port: 3000
    path: "/mcp"
    enabled: true
    timeout: 60

  # Database queries
  - name: "postgres"
    host: "localhost"
    port: 3001
    path: "/mcp"
    enabled: true
    include_tools:
      - "query"
      - "describe_table"

  # External API (disabled)
  - name: "weather-api"
    host: "localhost"
    port: 3002
    path: "/mcp"
    enabled: false

Example 3: Environment-Based Configuration

# .infer/mcp.yaml
enabled: ${MCP_ENABLED:-false}
connection_timeout: ${MCP_TIMEOUT:-30}

servers:
  - name: "production-db"
    scheme: "https"
    host: "${PROD_DB_MCP_HOST}"
    path: "/mcp"
    enabled: ${PROD_DB_ENABLED:-false}
# .env
MCP_ENABLED=true
MCP_TIMEOUT=60
PROD_DB_MCP_HOST=mcp.production.example.com
PROD_DB_ENABLED=true

Example 4: The Gateway as One MCP Server

The Inference Gateway serves every server in its MCP_SERVERS behind one MCP 2026-07-28 endpoint, POST /mcp. Point one entry at it instead of configuring each server in infer:

# gateway environment
MCP_ENABLED=true
MCP_EXPOSE=true
MCP_SERVERS=http://filesystem:3000/mcp,http://database:3000/mcp
# .infer/mcp.yaml
enabled: true
servers:
  - name: "gateway"
    host: "localhost"
    port: 8080
    path: "/mcp"
    enabled: true

The gateway namespaces its tools as mcp_<alias>_<tool>, so they surface in infer as MCP_gateway_mcp_<alias>_<tool>. Server entries cannot send an Authorization header yet, so this needs a gateway without auth enabled on /mcp.

Troubleshooting

MCP Tools Not Appearing

Check 1: Is MCP enabled?

enabled: true  # Must be true

Check 2: Are servers enabled?

servers:
  - name: "my-server"
    enabled: true  # Must be true

Check 3: Check CLI logs

There is no --log-level flag; debug logging is enabled with the INFER_LOGGING_DEBUG=true environment variable or the global -v/--verbose flag. Logs are written to ~/.infer/logs/app-<date>.log, not to the terminal:

INFER_LOGGING_DEBUG=true infer chat
grep "tools discovered successfully" ~/.infer/logs/app-*.log

Successful discovery is logged as:

{"level":"info","msg":"mCP server tools discovered successfully","server":"filesystem","toolCount":8}

Connection Errors

Error: connection refused

Causes:

  • MCP server not running
  • Wrong URL/port
  • Firewall blocking connection

Solutions:

  • Verify the server answers: infer mcp status <server>
  • Check URL in config
  • Check network connectivity

Server Must Speak MCP 2026-07-28

Error: MCP server must speak protocol version 2026-07-28 ...

The server is on an earlier MCP revision (it expects an initialize handshake or a session). The error names the versions it supports when it says. Upgrade the server to an SDK that serves 2026-07-28 (see the note at the top); Go servers on go-sdk also need StreamableHTTPOptions{Stateless: true}.

Timeout Issues

Error: context deadline exceeded

Causes:

  • Server response too slow
  • Network latency
  • Timeout too short

Solutions:

  • Increase timeout:

    servers:
      - name: "slow-server"
        timeout: 120  # Increase from default 30
  • Check server performance

  • Verify network connection

Tool Filtering Not Working

Issue: Excluded tools still appear

Check: Verify exact tool names:

infer mcp status <server> --format json

The JSON report lists each server's tools. You can also check the discovery log - debug logging goes to ~/.infer/logs/app-<date>.log (see Check 3 above):

grep "tools discovered successfully" ~/.infer/logs/app-*.log

Fix: Match exact tool names:

exclude_tools:
  - "delete_file"  # Exact match required

Plan Mode Still Shows MCP Tools

This is a bug - MCP tools should be automatically filtered in Plan mode. Please file an issue.

Security Considerations

1. Tool Filtering

Always use exclude_tools to block dangerous operations:

servers:
  - name: "filesystem"
    exclude_tools:
      - "delete_file"
      - "delete_directory"
      - "format_disk"
      - "execute_command"

2. Network Security

  • Use HTTPS for production MCP servers
  • Configure firewall rules
  • Use VPN for remote servers
  • Limit server access with authentication (if supported by MCP server)

3. Timeout Enforcement

Set reasonable timeouts to prevent hanging:

connection_timeout: 30
discovery_timeout: 30

4. Input Validation

MCP tool wrappers validate arguments before sending to server. Invalid arguments are rejected before network calls.

5. Sandboxing

Run MCP servers in sandboxed environments:

  • Docker containers
  • Virtual machines
  • Restricted user accounts

MCP vs A2A

When to Use MCP

  • Stateless operations: Read data, query APIs, simple transformations
  • Fast execution: Operations complete in seconds
  • Direct tool calls: Single request/response
  • External services: Databases, APIs, file systems

When to Use A2A

  • Long-running tasks: Operations taking minutes to hours
  • Complex workflows: Multi-step processes
  • Background processing: Async task execution
  • Agent delegation: Specialized AI agents for specific domains

Comparison

Feature MCP A2A
Connection Stateless Streamable HTTP Persistent
Duration Seconds Minutes to hours
Use case Tool execution Task delegation
Polling N/A Background monitoring
Mode availability Standard, Auto-Accept All modes

Auto-Starting MCP Servers

Auto-Start Overview

The CLI can automatically start and manage MCP servers as OCI/Docker containers. This provides:

  • Zero-configuration startup: Servers start automatically when CLI launches
  • Automatic port assignment: No need to manually configure ports
  • Container lifecycle management: Start, stop, and health monitoring
  • Background execution: Non-blocking startup, CLI ready immediately
  • Automatic healthchecks: Container healthchecks with an MCP server/discover request

Auto-Start Quick Start

Add a server with auto-start:

infer mcp add my-server \
  --description="My MCP server" \
  --run \
  --oci=my-mcp-server:latest

This automatically:

  1. Creates server configuration with run: true
  2. Assigns the next available port, starting at 3001
  3. Configures container with defaults (localhost, http, /mcp path)
  4. Adds a container healthcheck using an MCP server/discover request

Auto-Start Configuration

Auto-start servers use component-based URL configuration instead of a single URL field:

servers:
  - name: "my-server"
    enabled: true
    run: true                           # Enable auto-start
    oci: "my-mcp-server:latest"         # OCI/Docker image
    host: localhost                     # Default: localhost
    scheme: http                        # Default: http
    port: 3000                          # Auto-assigned if omitted
    path: /mcp                          # Default: /mcp
    startup_timeout: 60                 # Default: 30 seconds

The URL is constructed as: {scheme}://{host}:{port}{path}

Port Assignment

Automatic (recommended):

When adding servers without specifying --port, the CLI automatically:

  1. Finds the highest port currently used by MCP servers
  2. Assigns basePort + 1 (starting from 3000)
infer mcp add server-1 --run --oci=image:latest  # Gets port 3000
infer mcp add server-2 --run --oci=image:latest  # Gets port 3001
infer mcp add server-3 --run --oci=image:latest  # Gets port 3002

Manual:

Specify a custom port:

infer mcp add my-server --run --oci=image:latest --port=8080

Advanced port mappings:

For complex scenarios, use ports array (Docker-compose style):

servers:
  - name: "multi-port-server"
    run: true
    oci: "my-server:latest"
    ports:
      - "3000:8080"    # Host:Container
      - "3001:8081"

Container Configuration

Environment variables:

servers:
  - name: "api-server"
    run: true
    oci: "api-mcp:latest"
    env:
      API_KEY: "${MY_API_KEY}"          # Supports variable expansion
      LOG_LEVEL: "debug"
      DATABASE_URL: "postgres://..."

Volume mounts:

servers:
  - name: "filesystem-server"
    run: true
    oci: "fs-mcp:latest"
    volumes:
      - "/host/path:/container/path"
      - "/data:/mnt/data:ro"            # Read-only

Startup arguments:

servers:
  - name: "custom-server"
    run: true
    oci: "custom-mcp:latest"
    args:
      - "--verbose"
      - "--config=/etc/config.yaml"

Custom healthcheck:

servers:
  - name: "api-server"
    run: true
    oci: "api-mcp:latest"
    health_cmd: 'sh -c "curl -f http://localhost:8080/health || exit 1"'

Default healthcheck (MCP server/discover):

sh -c 'curl -fsS -X POST http://localhost:3000/mcp \
  -H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" \
  -H "MCP-Protocol-Version: 2026-07-28" -H "Mcp-Method: server/discover" \
  -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"server/discover\",\"params\":{\"_meta\":{\"io.modelcontextprotocol/protocolVersion\":\"2026-07-28\",\"io.modelcontextprotocol/clientCapabilities\":{}}}}"\
  > /dev/null || exit 1'

Lifecycle Management

Container naming: inference-mcp-{server-name}-{session-id}, or inference-mcp-{server-name}-shared for a detached infer mcp start container

Network: All containers join the infer-network Docker network

Restart policy: none. The CLI passes no --restart flag, so the container follows the Docker daemon default when it restarts. Detached infer mcp start containers are the ones meant to outlive the session.

Startup behavior:

  1. CLI checks if container already running (reuses if exists)
  2. Pulls image if not cached locally
  3. Starts container in background goroutine
  4. Waits for healthcheck to pass (with timeout)
  5. Logs success or failure (non-fatal)

Shutdown: Containers are stopped and removed when CLI exits

CLI Commands

Add server with auto-start:

infer mcp add <name> [flags]
  --run                    # Enable auto-start
  --oci <image>            # OCI/Docker image (required if --run)
  --port <port>            # Optional: specific port
  --startup-timeout <sec>  # Optional: startup timeout (default: 60)
  --description <text>     # Optional: description
  --enabled                # Optional: enable immediately (default: true)

Examples:

# Minimal - automatic port assignment
infer mcp add demo --run --oci=mcp-demo:latest

# With custom port
infer mcp add api --run --oci=api-mcp:latest --port=8080

# With startup timeout
infer mcp add slow --run --oci=slow-mcp:latest --startup-timeout=120

# Complete configuration
infer mcp add custom \
  --run \
  --oci=custom-mcp:latest \
  --port=3000 \
  --startup-timeout=60 \
  --description="Custom MCP server" \
  --enabled

Managing servers:

# List servers
infer mcp list

# Add a manual server alongside an auto-started one
infer mcp add filesystem http://localhost:3000/sse
infer mcp add demo --run --oci=mcp-demo-server:latest --port=3000

# Change an existing server
infer mcp update filesystem --url=http://localhost:3002/sse
infer mcp update filesystem --timeout=60 --include=read_file,list_directory

# Remove server (stops container if running)
infer mcp remove <name>

# Enable or disable a server, or all of MCP
infer mcp enable <name>
infer mcp disable <name>
infer mcp enable-global
infer mcp disable-global

# Probe each enabled server and report its state and tool count
infer mcp status
infer mcp status filesystem --format json

Every write lands in ~/.infer/mcp.yaml unless --project is passed, which writes to ./.infer/mcp.yaml instead. infer init seeds the userspace file.

update flags: --url, --description, --enabled, --timeout <seconds> (-1 leaves it unchanged, 0 falls back to the global timeout), --include <tools> and --exclude <tools> (an empty value leaves the filters unchanged).

add flags: --description, --enabled, --timeout <seconds>, --include <tools>, --exclude <tools> and the container set --run, --oci <image>, --port <port>, --startup-timeout <seconds>.

A run: true server can override the image's startup with the entrypoint and command keys in mcp.yaml, alongside args, env and volumes.

Auto-Start Troubleshooting

Container won't start:

Check container logs:

docker logs inference-mcp-<name>

Check if port is already in use:

lsof -i :<port>

Healthcheck failing:

Verify the server's healthcheck endpoint:

curl -v http://localhost:<port>/health

Test the MCP endpoint (it must list 2026-07-28 in supportedVersions):

curl -X POST http://localhost:<port>/mcp \
  -H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" \
  -H "MCP-Protocol-Version: 2026-07-28" -H "Mcp-Method: server/discover" \
  -d '{"jsonrpc":"2.0","id":1,"method":"server/discover","params":{"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28","io.modelcontextprotocol/clientCapabilities":{}}}}'

Image not found:

Build or pull the image manually:

docker pull <image>
# or
docker build -t <image> .

Startup timeout:

Increase timeout for slow-starting servers:

servers:
  - name: "slow-server"
    startup_timeout: 120  # 2 minutes

Advanced Topics

Custom MCP Server

Create a custom MCP server with the official Go SDK. The stateless Streamable HTTP handler serves MCP 2026-07-28 (a complete version lives in examples/mcp/mcp-server):

server := mcp.NewServer(&mcp.Implementation{Name: "my-custom-server", Version: "1.0.0"}, nil)
mcp.AddTool(server, &mcp.Tool{Name: "my_tool", Description: "My custom tool"},
    func(_ context.Context, _ *mcp.CallToolRequest, in struct {
        Input string `json:"input"`
    }) (*mcp.CallToolResult, any, error) {
        return &mcp.CallToolResult{Content: []mcp.Content{&mcp.TextContent{Text: "Processed: " + in.Input}}}, nil, nil
    })

// 2026-07-28 requests are only served in stateless mode.
handler := mcp.NewStreamableHTTPHandler(func(*http.Request) *mcp.Server { return server },
    &mcp.StreamableHTTPOptions{Stateless: true})
http.Handle("/mcp", handler)
log.Fatal(http.ListenAndServe(":3000", nil))

Monitoring

Monitor MCP tool usage:

# Count MCP tool calls
cat ~/.infer/logs/*.log | grep "MCP_" | wc -l

# Failed MCP calls
cat ~/.infer/logs/*.log | grep "MCP.*failed"

References

Support

For issues or questions: