Doramagic Project Pack · Human Manual

apify-mcp-server

Related topics: Core Architecture, Tool System

Project Overview

Related topics: Core Architecture, Tool System

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Server Components

Continue reading this section for the full explanation and source context.

Section Default Tools

Continue reading this section for the full explanation and source context.

Section Tool Configuration

Continue reading this section for the full explanation and source context.

Related topics: Core Architecture, Tool System

Project Overview

Apify MCP Server is a Model Context Protocol (MCP) server that provides AI assistants with access to Apify's platform capabilities. The server acts as a bridge between AI models and Apify's cloud infrastructure, enabling AI assistants to search and interact with Actors, documentation, and web content.

Source: README.md:1

What is the Apify MCP Server?

The Apify MCP Server implements the MCP specification to expose Apify platform features as tools that AI assistants can invoke. This allows AI models to:

  • Search and discover Actors on the Apify platform
  • Fetch detailed information about specific Actors
  • Search Apify and Crawlee documentation
  • Execute web scraping and automation tasks through the RAG web browser tool

Source: README.md:22-30

Architecture Overview

The project follows a monorepo structure with the following key directories:

DirectoryPurpose
src/Core MCP server implementation
src/web/React UI widgets for MCP Apps (ChatGPT integration)
tests/unit/Unit tests for individual modules
tests/integration/Integration tests for full server functionality
res/Technical documentation and analysis

Source: DEVELOPMENT.md:1-20

Server Components

The MCP server is built around the ActorsMcpServer class in src/mcp/server.ts, which wraps the low-level MCP Server API. The server exposes tools through request handlers for tool listing and tool calling.

graph TD
    A[AI Assistant] -->|MCP Protocol| B[ActorsMcpServer]
    B -->|Tool Requests| C[Tool Registry]
    C -->|Actors Tools| D[Actor Discovery & Execution]
    C -->|Docs Tools| E[Algolia Search API]
    C -->|RAG Tools| F[RAG Web Browser]
    D -->|API Calls| G[Apify API]
    E -->|Search Queries| H[Algolia]
    F -->|Browser Actions| I[Crawlee/Puppeteer]

Source: res/mcp_resources_analysis.md:1-15

Available Tools

The server provides the following tool categories and individual tools:

Default Tools

When no query parameters are provided, the MCP server loads these tools by default:

Tool CategoryDescription
actorsSearch and discover Actors on the Apify platform
docsSearch Apify and Crawlee documentation
apify/rag-web-browserRAG-enabled web browsing for AI consumption

Source: README.md:48-52

Tool Configuration

Tools can be configured via query parameters or command-line flags:

Configuration MethodExample
Hosted server URLhttps://mcp.apify.com?tools=actors,docs,apify/rag-web-browser
CLI flagnpx @apify/actors-mcp-server --tools actors,docs
Minimal (single Actor)https://mcp.apify.com?tools=apify/my-actor

Source: README.md:55-75

Unauthenticated Access

The hosted server allows access without an API token when only specific tools are requested:

Allowed ToolDescription
search-actorsSearch Actors without authentication
fetch-actor-detailsGet Actor details without authentication
search-apify-docsSearch Apify docs without authentication
fetch-apify-docsGet doc pages without authentication

Source: README.md:33-35

Deployment Modes

The Apify MCP Server supports multiple deployment configurations:

HTTP Streamable Mode

Runs as an HTTP server compatible with the streamable HTTP transport:

export APIFY_TOKEN="your-apify-token"
export APIFY_META_ORIGIN=STANDBY
apify run -p

The server exposes endpoints at http://localhost:3001 by default.

Source: README.md:14-20

Standard Input/Output (stdio) Mode

Runs as a subprocess communicating via stdin/stdout, suitable for local development and debugging:

npx @modelcontextprotocol/inspector node ./dist/stdio.js

Source: README.md:22-30

Claude Desktop Integration

The server can be configured as a Claude Desktop MCP tool:

{
  "mcpServers": {
    "apify": {
      "command": "node",
      "args": ["${__dirname}/dist/stdio.js", "--tools", "${user_config.tools}"],
      "env": {
        "APIFY_TOKEN": "${user_config.apify_token}"
      }
    }
  }
}

Source: manifest.json:35-45

User Configuration

The server accepts the following user configuration options:

ParameterTypeRequiredDefaultDescription
apify_tokenstringYes*-Apify API token from console.apify.com
toolsstringNoactors,docs,apify/rag-web-browserComma-separated list of tool categories or specific Actors

*Required unless using unauthenticated access with specific tools.

Source: manifest.json:47-65

Documentation Search Architecture

The docs tool integrates with Algolia to provide search across Apify and Crawlee documentation:

graph LR
    A[Search Query] -->|Algolia API| B[Algolia Index]
    B -->|Results| C[processAlgoliaResponse]
    C -->|URLs with fragments| D[LLM Response]
    
    E[Fetch Tool] -->|URL Request| F[Documentation Site]
    F -->|HTML Content| E

Algolia Response Processing

The server processes Algolia responses differently based on the documentation source:

SourceURL FragmentsContent Field
Apify docsSupportedAlways populated
Crawlee docsNot supportedNot available

Source: res/algolia.md:1-50

URL Fragment Handling

The server embeds page anchors directly in returned URLs for section-specific navigation:

// Returns ready-to-use URLs with anchors
{ url: "https://docs.apify.com/actors#build-actors", content: "..." }

This approach simplifies the LLM's ability to navigate to specific sections without complex URL reconstruction logic.

Source: res/algolia.md:55-70

MCP Resources

The server exposes MCP resources for specific use cases:

Resource TypeURI PatternDescription
Skyfire usage guidefile://readme.mdEnabled when skyfireMode is true
UI widgetsui://widget/*React widgets for OpenAI MCP Apps

Source: res/mcp_resources_analysis.md:15-30

Development Setup

Prerequisites

RequirementVersion
Node.js>=20.0.0
pnpm11+

Source: DEVELOPMENT.md:25-30

Installation

corepack enable     # enables pnpm via corepack
pnpm install        # installs root + src/web workspace packages

Source: DEVELOPMENT.md:30-35

Building

pnpm run build

Builds the TypeScript source to JavaScript in the dist/ directory.

Source: DEVELOPMENT.md:60-65

Testing

The project maintains multiple testing layers:

Test LayerCommandCoverage
Unit testspnpm run test:unitIndividual modules in isolation
Integration testspnpm run test:integrationFull server over all transports
LLM evalsCI only (apply validated label)Multiple AI models via OpenRouter

Source: DEVELOPMENT.md:8-20

Test Configuration

Environment VariablePurpose
APIFY_TOKENRequired for integration tests
PHOENIX_*Phoenix evaluation secrets
OPENROUTER_*OpenRouter API secrets

Source: DEVELOPMENT.md:15-20

UI Widgets

For OpenAI MCP Apps integration, the server supports React-based UI widgets located in src/web/. Widgets are rendered based on tool output and require the server to run in UI mode:

https://mcp.apify.com?ui=true

Or set the environment variable UI_MODE=true.

Source: DEVELOPMENT.md:50-55

Widget Configuration

Widgets must use the Apify design system tokens:

PropertyToken PatternExample
Text colortheme.color.{cat}.{prop}theme.color.neutral.text
Backgroundtheme.color.{cat}.{prop}theme.color.primary.background
Spacingtheme.space.space{N}theme.space.space16
Border radiustheme.radius.radius{N}theme.radius.radius8

Source: DESIGN_SYSTEM_AGENT_INSTRUCTIONS.md:1-20

Contribution Guidelines

The project follows conventional commits for versioning and changelog generation:

Branch Naming

feat/add-dataset-tool
fix/connection-timeout
chore/update-dependencies

Commit Format

<type>(<scope>): <description>

Types: feat, fix, refactor, chore, docs, test, etc.

Breaking changes are indicated with ! after the scope.

Source: CONTRIBUTING.md:1-30

Compatibility

PlatformClaude Desktop VersionNode.js
macOS (darwin)>=0.2.16>=20.0.0
Windows (win32)>=0.2.16>=20.0.0
Linux>=0.2.16>=20.0.0

Source: manifest.json:20-28

Repository Structure

The codebase is split across two repositories:

RepositoryPurpose
apify-mcp-server (this repo)Core MCP logic and public code
apify-mcp-server-internalHosted server deployment

Changes must be synchronized between both repositories. Canary releases are created by adding the beta tag to a PR branch.

Source: README.md:38-42

Source: https://github.com/apify/apify-mcp-server / Human Manual

Core Architecture

Related topics: Project Overview, Transport Layer

Section Related Pages

Continue reading this section for the full explanation and source context.

Section ActorsMcpServer (Central Coordinator)

Continue reading this section for the full explanation and source context.

Section Tool Entry Types

Continue reading this section for the full explanation and source context.

Section Stdio Transport

Continue reading this section for the full explanation and source context.

Related topics: Project Overview, Transport Layer

Core Architecture

The Apify MCP Server implements a Model Context Protocol (MCP) server that exposes Apify platform capabilities as tools for Large Language Models (LLMs). The architecture uses the low-level MCP Server SDK with a custom tool management system, supporting both stdio and HTTP Streamable transports.

System Overview

The server acts as a bridge between LLMs and the Apify platform, enabling AI assistants to:

  • Search and discover Actors on the Apify platform
  • Execute Actors programmatically
  • Access Apify documentation
  • Manage Actor runs and retrieve results
  • Proxy external MCP servers through Actorized deployments

Source: src/mcp/server.ts:1-50

graph TD
    subgraph "Transport Layer"
        STDIO[stdio.ts<br/>Standard I/O]
        HTTP[dev_server.ts<br/>HTTP Streamable]
    end
    
    subgraph "Core Server"
        AMS[ActorsMcpServer]
        TM[Tool Manager<br/>Map&lt;string, ToolEntry&gt;]
        TS[TaskStore]
        AS[ActorStore]
    end
    
    subgraph "Tool Registry"
        HT[Helper Tools]
        AT[Actor Tools]
        AMT[Actor-MCP Proxy Tools]
    end
    
    subgraph "External Services"
        APIFY[Apify API]
        APIClient[ApifyClient]
    end
    
    STDIO --> AMS
    HTTP --> AMS
    AMS --> TM
    AMS --> TS
    AMS --> AS
    TM --> HT
    TM --> AT
    TM --> AMT
    AMS --> APIClient
    APIClient --> APIFY

High-Level Component Architecture

ActorsMcpServer (Central Coordinator)

The ActorsMcpServer class is the core component that orchestrates all MCP functionality:

PropertyTypePurpose
serverServerLow-level MCP SDK server instance
toolsMap<string, ToolEntry>Tool registry for all registered tools
taskStoreTaskStoreTracks running and completed tasks
actorStoreActorStoreCaches Actor metadata and input schemas
serverModeServerModeResolved server mode (default/apps)
optionsActorsMcpServerOptionsServer configuration options

Source: src/mcp/server.ts:280-320

Tool Entry Types

The server manages three distinct tool types defined in the discriminated union:

type ToolEntry = HelperTool | ActorTool | ActorMcpTool;
Tool TypeType DiscriminatorPurposeSource
HelperTooltype: 'internal'Built-in server tools (search, docs)src/types.ts:135-145
ActorTooltype: 'actor'Dynamic Actor-based toolssrc/types.ts:147-153
ActorMcpTooltype: 'actor-mcp'External MCP server proxy via Actorsrc/types.ts:155-162

Source: src/types.ts:130-175

Transport Architecture

The server supports two transport mechanisms, selected based on deployment context:

Stdio Transport

Used for local CLI clients and the MCP Inspector. Communication occurs through standard input/output streams.

Source: src/index.ts

HTTP Streamable Transport

Used for hosted deployments at mcp.apify.com. Enables remote client connections with streaming response support.

Source: src/mcp/server.ts

TransportUse CaseEntry Point
stdioLocal CLI, MCP Inspectorstdio.ts
HTTP StreamableHosted server, remote clientsdev_server.ts

Request Handler Architecture

The server uses low-level MCP SDK request handlers for all protocol operations:

Handler Registration Pattern

server.setRequestHandler(ListToolsRequestSchema, async () => { ... });
server.setRequestHandler(CallToolRequestSchema, async (request) => { ... });
server.setRequestHandler(ListResourcesRequestSchema, async () => { ... });
server.setRequestHandler(ReadResourceRequestSchema, async (request) => { ... });

Source: src/mcp/server.ts:200-250

Central Tool Dispatcher

All tool calls flow through a central dispatcher that routes based on tool type:

graph LR
    A[CallTool Request] --> B{Extract toolName}
    B --> C{Lookup in tools Map}
    C -->|HelperTool| D[Execute call function]
    C -->|ActorTool| E[Call Apify API]
    C -->|ActorMcpTool| F[Proxy to Actor-MCP]
    D --> G[Return result]
    E --> G
    F --> G

Source: src/mcp/server.ts:400-500

Tool Lifecycle Management

Dynamic Tool Loading

Actors are loaded as tools through the loadActorsAsTools() method:

  1. Fetch Actor list from Apify API or configured Actor IDs
  2. Transform Actor metadata into ActorTool entries
  3. Upsert tools into the registry Map
  4. Send notifications/tools/list_changed to connected clients

Source: src/mcp/actors.ts

Tool Registration Flow

sequenceDiagram
    participant Client
    participant Server as ActorsMcpServer
    participant API as Apify API
    participant Store as tools Map
    
    Client->>Server: initialize (capabilities)
    Server->>Server: resolveServerMode()
    Server->>API: fetchActors() / getActorDetails()
    API-->>Server: Actor metadata
    Server->>Store: upsertTools()
    Server-->>Client: tools/list response
    Client->>Server: notifications/tools/list_changed

Server Mode System

The server supports automatic mode detection based on client capabilities:

ModeTriggerBehavior
defaultNon-MCP Apps clientsStandard tool responses
appsMCP Apps clients (uiMode === 'openai')Enhanced responses with widget metadata

Source: src/mcp/server.ts:300-340

Mode Auto-Detection

The serverMode property transitions from 'auto' to either 'default' or 'apps' during the initialize request handler:

// Preliminary value at construction
public serverMode: ServerMode;

// Finalized inside initialize handler
private serverModeResolved: boolean;

Source: src/mcp/server.ts:310-325

Resource System

The server implements MCP resources for UI widgets and documentation:

Resource Types

Resource TypeURI PatternConditionSource
Skyfire Guidefile://readme.mdskyfireMode === truesrc/mcp/resources/resource_service.ts
UI Widgetsui://widget/*.htmluiMode === 'openai'src/mcp/resources/resource_service.ts

Resource Handler Implementation

return {
    listResources,
    readResource,
    listResourceTemplates: async () => ({ resourceTemplates: [] }),
};

Source: src/mcp/resources/resource_service.ts

Actor-MCP Proxy Architecture

External MCP servers can be proxied through the Apify platform using the ActorMcpTool type:

graph LR
    subgraph "This Server"
        A[ActorMcpTool] --> B[proxy.ts]
    end
    
    subgraph "Apify Platform"
        B -->|callActor| C[Actor Container]
    end
    
    subgraph "Remote MCP Server"
        C -->|HTTP| D[External Server]
        D -->|MCP Response| C
    end
    
    C -->|Actor Result| B

Source: src/mcp/proxy.ts

Task Management

TaskStore

The TaskStore class manages long-running task execution:

MethodPurpose
createTask()Initialize a new task
updateTask()Update task status/progress
getTask()Retrieve task details
listTasks()List all tasks

Source: src/mcp/server.ts

Progress Tracking

Long-running operations support progress notifications via createProgressTracker:

const tracker = createProgressTracker(taskId, totalSteps);
tracker.report(progress, total, message);

Source: src/mcp/server.ts

Client Configuration

ApifyClient Integration

The server uses the Apify JavaScript client for API communication:

const apifyClient = new ApifyClient({
    token: apifyToken,
});

Source: src/mcp/client.ts

Token Propagation

LocationMechanism
HTTP HeadersAuthorization: Bearer <token>
MCP Meta_meta.apifyToken in tool call

Source: src/mcp/server.ts:630-650

Configuration Options

The ActorsMcpServerOptions interface defines server configuration:

OptionTypeDefaultPurpose
apifyTokenstringRequiredApify API authentication
tools`string \string[]`defaultTool categories/Actors to load
serverModeServerModeOption'auto'Server mode override
skyfireModebooleanfalseEnable Skyfire-specific resources
uiModeUiMode'default'UI response format

Source: src/mcp/server.ts:200-280

Capability Advertisement

The server advertises the following MCP capabilities during initialization:

capabilities: {
    logging: {},
    prompts: { listChanged: false },
    resources: options.skyfireMode ? { listChanged: false } : undefined,
    tools: { listChanged: true },
}

Source: src/mcp/server.ts:210-218

Entry Points

Entry PointTransportFile
dist/stdio.jsstdiosrc/stdio.ts
dist/index.js (HTTP)Streamable HTTPsrc/dev_server.ts

Source: README.md

Source: https://github.com/apify/apify-mcp-server / Human Manual

Transport Layer

Related topics: Core Architecture, Development Setup

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Entry Point

Continue reading this section for the full explanation and source context.

Section Connection Flow

Continue reading this section for the full explanation and source context.

Section Configuration

Continue reading this section for the full explanation and source context.

Related topics: Core Architecture, Development Setup

Transport Layer

The Apify MCP Server implements a dual-transport architecture that supports both local command-line clients and remote HTTP clients. This design allows the same core server logic to operate in different deployment scenarios while maintaining a consistent MCP protocol implementation.

Overview

The transport layer handles the communication between MCP clients and the ActorsMcpServer core. The server supports two primary transport mechanisms:

Transport ModeEntry PointUse CaseProtocol
Stdiostdio.tsLocal CLI clients, Claude Code, MCP InspectorStandard I/O via process stdin/stdout
HTTP Streamabledev_server.tsRemote clients, hosted deployment at mcp.apify.comStreamable HTTP with Server-Sent Events

Source: src/index.ts · README.md

Architecture Diagram

graph TB
    subgraph "Client Layer"
        CLI[CLI Client]
        HTTP_CLIENT[HTTP Client]
        MCP_INSPECTOR[MCP Inspector]
    end

    subgraph "Transport Layer"
        STDIO[Stdio Transport<br/>stdio.ts]
        HTTP[HTTP Transport<br/>dev_server.ts]
        WEBSOCKET[WebSocket Support<br/>mcp/server.ts]
    end

    subgraph "Core Server"
        SERVER[ActorsMcpServer<br/>server.ts]
        TOOLS[Tool Handlers]
        RESOURCES[Resource Handlers]
        TASKS[Task Store]
    end

    CLI --> STDIO
    HTTP_CLIENT --> HTTP
    MCP_INSPECTOR -->|stdio mode| STDIO
    MCP_INSPECTOR -->|http mode| HTTP

    STDIO --> SERVER
    HTTP --> SERVER
    WEBSOCKET --> SERVER

    SERVER --> TOOLS
    SERVER --> RESOURCES
    SERVER --> TASKS

Stdio Transport

The Standard I/O transport is designed for local development and CLI-based clients. It communicates via process stdin and stdout using JSON-RPC messages.

Entry Point

The stdio transport is initialized in src/stdio.ts:

import { createStdioServer } from '@modelcontextprotocol/sdk/server/stdio';

// Server initialization with transport
const server = new ActorsMcpServer(options);
const transport = createStdioServer();
await server.connect(transport);

Source: src/stdio.ts

Connection Flow

sequenceDiagram
    participant Client as MCP Client
    participant Stdio as Stdio Transport
    participant Server as ActorsMcpServer

    Note over Client,Stdio: Process startup
    Stdio->>Server: Initialize connection
    Server->>Stdio: MCP handshake (initialize)
    Client->>Stdio: Initialize response
    Stdio->>Server: Handshake complete

    loop Message Loop
        Client->>Stdio: JSON-RPC Request
        Stdio->>Server: Forward request
        Server->>Server: Process tool/resource/task
        Server->>Stdio: JSON-RPC Response
        Stdio->>Client: Response output
    end

    Note over Client,Stdio: Process termination
    Client->>Stdio: SIGINT
    Stdio->>Server: Cleanup

Configuration

The stdio transport inherits server configuration from environment variables and constructor options:

ParameterSourceDescription
APIFY_TOKENEnvironmentApify API authentication token
serverModeConstructor"default", "apps", or "auto"
skyfireModeConstructorEnables Skyfire usage guide resource

Source: src/stdio.ts · src/mcp/server.ts

HTTP Streamable Transport

The HTTP transport enables remote client connections using the MCP Streamable HTTP specification. This is used for the hosted deployment at mcp.apify.com.

Server Implementation

The HTTP server is implemented using Express in src/dev_server.ts:

import express from 'express';
import { createServer } from 'http';
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/http';

const app = express();
const server = createServer(app);

// Streamable HTTP transport with session management
const transport = new StreamableHTTPServerTransport({
    sessionIdGenerator: () => crypto.randomUUID(),
    onSession: initializeSession,
});

Source: src/dev_server.ts

HTTP Endpoints

EndpointMethodPurpose
/mcpPOSTJSON-RPC requests (tools, resources, tasks)
/mcpGETServer-Sent Events for notifications
/healthGETHealth check endpoint

Source: src/dev_server.ts

Session Management

graph LR
    A[Client] -->|1. POST /mcp| B{Has Session ID?}
    B -->|No| C[Create New Session]
    B -->|Yes| D[Find Existing Session]
    C --> E[Initialize MCP]
    D --> E
    E --> F[Store in Map]
    F --> G[Process Request]
    G --> H[Return Response]

The transport uses UUID-based session identifiers to maintain separate server instances per client connection.

Source: src/dev_server.ts

Server Card

The ServerCard component provides metadata and capability information about the MCP server for discovery and documentation purposes.

ServerCard Structure

export interface ServerCard {
    name: string;
    version: string;
    description: string;
    homepageUrl: string;
    repositoryUrl: string;
    documentationUrl: string;
    capabilities: ServerCapabilities;
    auth?: AuthConfig;
    configSchema?: Record<string, unknown>;
}

Source: src/server_card.ts

Capability Declaration

The server advertises its capabilities during the MCP initialize handshake:

const capabilities = {
    tools: { listChanged: true },
    tasks: { list: true, cancel: true, requests: { tools: { call: true } } },
    resources: {},
    prompts: {},
    logging: {},
};

Source: src/mcp/server.ts:146

Internal Exports

The index_internals.ts module exposes internal components for testing and advanced usage scenarios:

ExportTypePurpose
ActorsMcpServerClassCore MCP server implementation
createResourceServiceFunctionResource service factory
ToolEntryTypeUnion type for all tool variants
ServerModeEnumServer operating mode

Source: src/index_internals.ts

Server Modes

The transport layer operates differently based on the selected server mode:

ModeDescriptionTransport Impact
defaultStandard Apify toolsAll tools available
appsOpenAI UI widgets modeAdditional UI widget resources
autoCapability-based detectionMode resolved during initialize

Source: src/mcp/server.ts

Request Handler Wiring

All transports delegate to the same core request handlers registered in ActorsMcpServer:

graph TD
    T1[Stdio Transport] --> S[ActorsMcpServer]
    T2[HTTP Transport] --> S
    T3[WebSocket Transport] --> S

    S --> H1[ListToolsRequestHandler]
    S --> H2[CallToolRequestHandler]
    S --> H3[ListResourcesRequestHandler]
    S --> H4[ReadResourceRequestHandler]
    S --> H5[ListTasksRequestHandler]
    S --> H6[GetTaskRequestHandler]

    H1 --> T[Tool Execution]
    H2 --> T

Source: src/mcp/server.ts · src/dev_server.ts

Integration with MCP SDK

The transport layer uses the official @modelcontextprotocol/sdk package for protocol implementation:

SDK ComponentUsage
ServerLow-level MCP protocol server
StreamableHTTPServerTransportHTTP transport implementation
createStdioServerStdio transport factory
RequestHandlerExtraRequest context wrapper

Source: src/stdio.ts · src/dev_server.ts

Testing Transport Layers

The project includes transport-specific integration tests:

Test FileTransportCoverage
tests/integration/suite.tsAll transportsMain test suite
stdio.ts (in integration)StdioStdin/stdout messaging
http.ts (in integration)HTTP StreamableREST endpoints
sse.ts (in integration)Server-Sent EventsNotification streaming

Source: DEVELOPMENT.md · tests/integration/

Summary

The Apify MCP Server implements a transport-agnostic architecture where:

  1. Stdio Transport handles local CLI clients through stdin/stdout JSON-RPC messaging
  2. HTTP Transport enables remote access via Streamable HTTP with session management
  3. Core Server (ActorsMcpServer) remains independent of transport implementation
  4. Capability negotiation occurs during MCP initialize handshake
  5. All transports delegate to the same request handlers for tools, resources, and tasks

This separation allows the server to serve both local development needs and production hosted deployments while maintaining a single, testable codebase.

Source: https://github.com/apify/apify-mcp-server / Human Manual

Tool System

Related topics: Actor Tools, Storage Access Tools

Section Related Pages

Continue reading this section for the full explanation and source context.

Section HelperTool

Continue reading this section for the full explanation and source context.

Section ActorTool

Continue reading this section for the full explanation and source context.

Section ActorMcpTool

Continue reading this section for the full explanation and source context.

Related topics: Actor Tools, Storage Access Tools

Tool System

The Tool System is the core component of the Apify MCP Server, enabling AI assistants to interact with Apify's platform capabilities through a standardized Model Context Protocol (MCP) interface. The system provides dynamic tool loading, registration, execution, and removal capabilities for three distinct tool types: internal helper tools, Actor tools, and Actor-MCP proxy tools.

Architecture Overview

The Tool System follows a centralized registration model where ActorsMcpServer manages all tool lifecycle operations. Tools are stored in a Map<string, ToolEntry> and exposed to MCP clients via request handlers. Source: src/mcp/server.ts

graph TD
    subgraph "MCP Client"
        A[Claude / VS Code]
    end
    
    subgraph "ActorsMcpServer"
        B[Server Instance]
        C[Tool Registry Map]
        D[setupToolHandlers]
        E[Central Dispatcher]
    end
    
    subgraph "Tool Types"
        F[HelperTool]
        G[ActorTool]
        H[ActorMcpTool]
    end
    
    A -->|tools/call| B
    B --> D
    D -->|route by type| E
    E -->|internal| F
    E -->|actor| G
    E -->|actor-mcp| H
    
    C -.->|stores| F
    C -.->|stores| G
    C -.->|stores| H

Tool Type Definitions

The system defines three tool types through discriminated unions in src/types.ts. Source: src/types.ts:135-174

Tool TypeDescriptionExecution Mode
HelperToolInternal server tools with direct callback executionSynchronous
ActorToolApify Actor-based tools for scalable executionAsynchronous via Actor API
ActorMcpToolExternal MCP server tools proxied through ApifyDelegated to origin server

HelperTool

Internal tools that execute directly within the server process:

type HelperTool = ToolBase & {
    type: 'internal';
    call: (toolArgs: InternalToolArgs) => Promise<object>;
};

Examples include search-actors, fetch-actor-details, search-apify-docs, and fetch-apify-docs. Source: README.md

ActorTool

Tools that invoke Apify Actors on the platform:

type ActorTool = ToolBase & {
    type: 'actor';
    actorFullName: string;
    memoryMbytes?: number;
};

These tools launch Actors with configurable memory allocation for scalable cloud execution.

ActorMcpTool

Proxied tools from external MCP servers, enabling the Apify platform to bridge between MCP implementations:

type ActorMcpTool = ToolBase & {
    type: 'actor-mcp';
    originToolName: string;
    actorId: string;
    serverId: string;
    serverUrl: string;
};

Tool Registration Flow

Tools are loaded and registered through a multi-stage process:

sequenceDiagram
    participant Client
    participant Server as ActorsMcpServer
    participant Loader as tools_loader.ts
    participant Registry as Tool Registry
    
    Client->>Server: loadActorsAsTools()
    Server->>Loader: loadToolsByCategory(tools)
    Loader-->>Server: Tool definitions
    Server->>Server: upsertTools(toolDefs)
    Server->>Registry: Map.set(name, entry)
    Server->>Client: sendToolListChanged()

Dynamic Loading

The loadActorsAsTools() method handles dynamic tool loading based on configuration. When called, it:

  1. Resolves tool categories or specific Actor names from configuration
  2. Loads tool definitions from src/utils/tools_loader.ts
  3. Calls upsertTools() to register each tool
  4. Broadcasts tools/list_changed notification to connected clients Source: res/mcp_server_refactor_analysis.md

Tool Removal

The removeToolsByName() method removes tools from the registry and notifies clients:

removeToolsByName(toolNames: string[]): void

This operation:

  • Deletes tools from the internal Map
  • Calls sendToolListChanged() to update clients
  • Validates that tools exist before removal

Central Dispatcher Pattern

The current implementation uses a central dispatcher in setupToolHandlers() to route tool execution based on tool.type. Source: src/mcp/server.ts

graph LR
    A[Request] --> B{tool.type}
    B -->|internal| C[Execute callback]
    B -->|actor| D[Create Actor client]
    B -->|actor-mcp| E[Connect to MCP proxy]
    
    C --> F[Return result]
    D --> G[Run Actor]
    G --> F
    E --> H[Forward request]
    H --> F

Tool Input Validation

Tool arguments are validated using JSON Schema with AJV before execution:

const validate = compileSchema(inputSchema);
const valid = validate(toolArgs);

The compileSchema utility from src/utils/ajv.js provides schema compilation with custom error messages. Source: src/tools/common/search_apify_docs.ts:12

Actor-MCP Proxy Integration

The proxy subsystem in src/mcp/proxy.ts enables tools from external MCP servers to be exposed through the Apify MCP interface. Source: src/mcp/proxy.ts

When an ActorMcpTool is called:

  1. The server connects to the origin MCP server
  2. The request is forwarded with original arguments
  3. Responses are transformed and returned to the client
  4. Progress notifications are propagated

Default Tools Configuration

The server loads default tools when no specific configuration is provided:

ToolCategoryDescription
actorsCategoryActor discovery and invocation tools
docsCategoryApify and Crawlee documentation search
apify/rag-web-browserSpecificRAG-enabled web browser for data extraction

Source: README.md

Unauthenticated Access

Certain tools are explicitly enabled for unauthenticated access:

  • search-actors
  • fetch-actor-details
  • search-apify-docs
  • fetch-apify-docs

Access is granted when the tools query parameter includes only these tools. Source: README.md

Tool Registration Factory (Target Architecture)

An upcoming refactor will replace the central dispatcher with callback-per-tool registration patterns:

// Internal tools
registerInternalTool(tool: InternalToolDefinition): RegisteredTool

// Actor tools  
registerActorTool(actorDef: ActorDefinition): RegisteredTool

// Actor-MCP proxy tools
registerActorMcpTool(mcpTool: ExternalTool, serverUrl: string, actorId: string): RegisteredTool

Each tool will be self-contained with its own callback, eliminating the need for type-checking in the dispatcher. Source: res/mcp_server_refactor_analysis.md

CLI Configuration

Tools can be configured via command-line flags:

# Load default tools
npx @apify/actors-mcp-server --tools actors,docs,apify/rag-web-browser

# Minimal single-Actor configuration
npx @apify/actors-mcp-server --tools apify/my-actor

Source: README.md

Testing Strategy

The tool system is tested at multiple levels:

Test LevelCoverage
Unit testsIndividual tool execution, schema validation, registration patterns
Integration testsFull tool lifecycle, dynamic loading/removal, notifications
Manual testingMCP client verification, protocol compliance

Source: DEVELOPMENT.md

Key Integration Tests

Integration tests in tests/integration/suite.ts verify:

  • tools/list returns correct tools with proper metadata
  • tools/call executes each tool type correctly
  • tools/call returns proper validation errors
  • notifications/tools/list_changed are sent on changes
  • notifications/progress work for long-running operations

Source: res/integration_test_coverage_audit.md

Future Refactoring

The Tool System is scheduled for migration from the low-level Server API to the high-level McpServer API:

ChangeImpact
Replace Server with McpServerAutomatic tool management
Remove central dispatcher~300 lines removed
Convert JSON Schema to ZodNative schema conversion via Zod v4
Callback-per-tool patternSelf-contained execution logic

This refactor will reduce complexity while preserving all existing functionality. Source: res/mcp_server_refactor_analysis.md

Source: https://github.com/apify/apify-mcp-server / Human Manual

Actor Tools

Related topics: Tool System, Storage Access Tools

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Tool Classification Hierarchy

Continue reading this section for the full explanation and source context.

Section Actor Tool Execution Flow

Continue reading this section for the full explanation and source context.

Section ActorExecutor

Continue reading this section for the full explanation and source context.

Related topics: Tool System, Storage Access Tools

Actor Tools

Actor Tools are the primary mechanism by which the Apify MCP Server enables AI assistants and MCP clients to execute Apify Actors. These tools bridge the gap between the Model Context Protocol (MCP) and Apify's Actor platform, allowing LLMs to programmatically invoke cloud programs, monitor their execution, and retrieve results.

Overview

Actor Tools serve as wrappers around Apify Actors, exposing them as callable MCP tools with proper input schema validation, result formatting, and execution tracking. The system supports three distinct tool types within the MCP server architecture:

Tool TypeDescriptionType Discriminator
Internal ToolsBuilt-in helper tools (e.g., search-actors, fetch-actor-details)'internal'
Actor ToolsWrappers around Apify Actors'actor'
Actor-MCP ToolsProxies to external MCP servers hosted as Actors'actor-mcp'

Source: src/types.ts

Architecture

Tool Classification Hierarchy

graph TD
    A[Tools in MCP Server] --> B[Internal Tools]
    A --> C[Actor Tools]
    A --> D[Actor-MCP Tools]
    
    C --> C1[call-actor]
    C --> C2[call-actor-widget]
    C --> C3[Dynamic Actor Tools]
    
    D --> D1[Proxy MCP Tools]

Actor Tool Execution Flow

sequenceDiagram
    participant Client as MCP Client
    participant Server as ActorsMcpServer
    participant Factory as ActorToolsFactory
    participant Executor as ActorExecutor
    participant Apify as Apify Platform
    
    Client->>Server: Tool call request
    Server->>Factory: Create/retrieve Actor tool
    Factory->>Executor: Execute with input
    Executor->>Apify: Start Actor run
    Apify-->>Executor: Run metadata
    Executor->>Apify: Wait for completion
    Apify-->>Executor: Run results
    Executor-->>Server: Formatted response
    Server-->>Client: MCP response

Source: src/tools/actor_executor.ts

Core Components

ActorExecutor

The ActorExecutor class is responsible for the actual execution of Apify Actors. It handles:

  • Actor invocation with input validation
  • Run lifecycle management (start, wait, abort)
  • Result retrieval from datasets or key-value stores
  • Error handling and response formatting

Key responsibilities:

ResponsibilityDescription
callActor()Initiates an Actor run with provided input
getActorOutput()Retrieves output from completed runs
abortActorRun()Terminates a running Actor
Result formattingConverts raw results to MCP-compatible responses

Source: src/tools/actor_executor.ts

ActorToolsFactory

The ActorToolsFactory creates Actor tool definitions based on Actor metadata. It transforms Actor input schemas into MCP-compatible tool definitions with proper validation.

Factory outputs include:

OutputPurpose
nameTool identifier (e.g., apify/web-scraper)
descriptionHuman-readable tool description
inputSchemaJSON Schema for tool arguments
ajvValidateCompiled AJV validator function
annotationsMCP tool hints (readOnlyHint, openWorldHint, etc.)

Source: src/tools/core/actor_tools_factory.ts

Call Actor Common Module

The call_actor_common.ts module provides shared execution logic used by all call-actor variants. It implements the pre-execution phase:

graph LR
    A[Input Validation] --> B[Actor Resolution]
    B --> C[MCP Tool Name Parsing]
    C --> D[Tool Call Execution]
    D --> E[Response Formatting]

Pre-execution steps:

  1. Input parsing: Validates and extracts actor name, input, and call options
  2. Actor resolution: Resolves actor name to stable ID via Apify API
  3. MCP tool routing: Handles routing for Actor-MCP servers
  4. Payment validation: Checks if Actor requires payment before execution

Source: src/tools/core/call_actor_common.ts

Call Actor Implementations

The MCP server provides multiple implementations of the call-actor functionality, optimized for different client environments.

Default Call Actor

The default implementation (src/tools/default/call_actor.ts) provides standard execution with result previews. It is used by most MCP clients.

Characteristics:

PropertyValue
ModeDefault server mode
OutputLimited preview (first 5 items)
Widget supportNone
Use caseGeneral-purpose Actor invocation

Call Actor Widget (Apps Mode)

The widget variant (src/tools/apps/call_actor.ts) renders interactive MCP App widgets in the response, providing enhanced UX for clients that support it.

Characteristics:

PropertyValue
ModeApps server mode (ui=true)
OutputFull results with widget rendering
Widget supportActor Run widgets, progress tracking
Use caseMCP Apps-enabled clients

Widget annotations applied:

{
    title: 'Call Actor (widget)',
    readOnlyHint: false,
    destructiveHint: true,
    idempotentHint: false,
    openWorldHint: true,
}

Source: src/tools/apps/call_actor_widget.ts

Execution Modes Comparison

FeatureDefaultWidget (Apps)
Server modedefaultapps
Output previewLimitedFull
Progress notificationsVia logsVia widget
Run status trackingManualAutomatic
UI renderingText onlyInteractive widgets

Actor Resolution

The resolution process maps human-readable actor names to stable actor IDs.

graph TD
    A[Input: Actor Name] --> B{User has rented Actor?}
    B -->|Yes| C[Check rentedActorsIds]
    B -->|No| D[Search Apify Store]
    C --> E[Return rented Actor ID]
    D --> F[Match by name/version]
    F --> G[Return store Actor ID]
    E --> H[Resolved Actor]
    G --> H

Source: src/utils/actor.ts

Resolution Strategy

  1. User rented Actors: Check if the actor name matches any Actor rented by the user
  2. Apify Store: Search public Actors for matching name
  3. Version matching: Support both explicit (actorName@version) and implicit versioning

Tool Annotations

Actor tools include MCP-compliant annotations to help clients and LLMs understand tool behavior:

AnnotationDescriptionApplied Value
titleShort display nameActor name (e.g., "Call Actor")
readOnlyHintIndicates read-only operationfalse for call-actor
openWorldHintIndicates external network accesstrue (executes Actors)
destructiveHintIndicates destructive operationtrue for call-actor
idempotentHintIndicates idempotent operationfalse for call-actor

Source: src/tools/apps/call_actor_widget.ts

Input Schema Handling

Actor tools dynamically generate input schemas from Actor definitions:

graph TD
    A[Actor Input Schema] --> B[Pruned Definition]
    B --> C[JSON Schema]
    C --> D[AJV Validator]
    D --> E[MCP Tool Schema]

Schema Pruning

The schema is pruned to include only fields the LLM needs to provide:

Field TypeIncludedReason
Required fieldsYesNecessary for execution
Optional fields with defaultsNoServer applies defaults
Hidden fieldsNoInternal use only

Source: src/utils/actor.ts

Error Handling

Actor tools implement robust error handling for various failure scenarios:

Error TypeHandlingResponse
Invalid input schemaAJV validation failureFormatted error message
Actor not foundResolution returns errorEarly response with error
Payment requiredPayment validation failsError with payment instructions
Run timeoutWait exceeds timeoutPartial results with warning
Actor execution errorRun failsError details in response

Source: src/tools/core/call_actor_common.ts

Dynamic Tool Loading

The system supports dynamic loading of Actors as tools:

graph TD
    A[Tool Configuration] --> B[Load Actors]
    B --> C[Fetch Actor Definitions]
    C --> D[Register Tools]
    D --> E[Notify Tools Changed]
    E --> F[MCP Client Updated]

Loading methods:

MethodDescription
loadActorsAsTools()Load by actor IDs
loadToolsByName()Load by tool names
loadToolsFromUrl()Load from MCP server URL

Source: src/mcp/server.ts

Configuration

Actor tools respect the server's tools configuration parameter:

?tools=actors,docs,apify/rag-web-browser

When the actors category is included, all Actor-related tools become available, including the base call-actor tool and any dynamically loaded Actor tools.

See Also

Source: https://github.com/apify/apify-mcp-server / Human Manual

Storage Access Tools

Related topics: Actor Tools

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Tool Classification

Continue reading this section for the full explanation and source context.

Section Data Flow

Continue reading this section for the full explanation and source context.

Section Tool Entry Structure

Continue reading this section for the full explanation and source context.

Related topics: Actor Tools

Storage Access Tools

Storage Access Tools provide MCP (Model Context Protocol) clients with programmatic access to Apify's cloud storage infrastructure. These tools enable AI assistants and automated workflows to read datasets, key-value stores, and Actor run logs without requiring direct API integration.

Overview

The Apify MCP Server exposes storage resources through a collection of specialized tools that wrap the Apify API's storage endpoints. These tools follow the repository's established patterns:

  • Input validation via Zod schemas
  • Consistent response formatting via buildMCPResponse()
  • Payment-required guards for premium operations
  • Comprehensive error handling with user-friendly messages

Source: src/tools/common/get_dataset.ts:1-1

Architecture

Tool Classification

Storage Access Tools fall into three categories based on the underlying Apify storage type:

graph TD
    A[Storage Access Tools] --> B[Dataset Tools]
    A --> C[Key-Value Store Tools]
    A --> D[Run Log Tools]
    
    B --> B1[get-dataset]
    B --> B2[get-dataset-items]
    B --> B3[get-dataset-schema]
    
    C --> C1[get-key-value-store]
    C --> C2[get-key-value-store-record]
    
    D --> D1[get-actor-run-log]
    D --> D2[run-collection]

Data Flow

sequenceDiagram
    participant Client as MCP Client
    participant Server as ActorsMcpServer
    participant Tool as Storage Tool
    participant Apify as Apify API
    
    Client->>Server: Tool Request
    Server->>Tool: call(toolArgs)
    Tool->>Tool: Validate input with Zod
    Tool->>Apify: API Request
    Apify-->>Tool: Raw Storage Data
    Tool->>Tool: Transform & Format
    Tool-->>Server: MCP Response
    Server-->>Client: Formatted Result

Tool Entry Structure

Each storage tool implements the ToolEntry interface with type: 'internal':

export const exampleTool: ToolEntry = Object.freeze({
    type: 'internal',
    name: HelperTools.DATASET_GET_ITEMS,
    description: 'Tool description...',
    inputSchema: z.toJSONSchema(inputSchema),
    outputSchema: datasetItemsOutputSchema,
    ajvValidate: compileSchema(z.toJSONSchema(inputSchema)),
    annotations: { /* tool annotations */ },
    call: async (toolArgs: InternalToolArgs) => { /* implementation */ },
});

Source: src/tools/common/get_dataset_items.ts:39-62

Source: https://github.com/apify/apify-mcp-server / Human Manual

Agentic Payments System

The Agentic Payments System is a payment abstraction layer within the Apify MCP Server that enables AI agents and MCP clients to pay for Actor executions using alternative payment methods ...

Section PaymentProviderId

Continue reading this section for the full explanation and source context.

Section PaymentProvider Interface

Continue reading this section for the full explanation and source context.

Section Supporting Types

Continue reading this section for the full explanation and source context.

Section Payment Flow

Continue reading this section for the full explanation and source context.

The Agentic Payments System is a payment abstraction layer within the Apify MCP Server that enables AI agents and MCP clients to pay for Actor executions using alternative payment methods beyond traditional API tokens. The system supports multiple payment schemes including x402 (blockchain-based payments via HTTP 402) and Skyfire (agentic payment tokens), allowing autonomous agents to pay for compute without requiring pre-configured API credentials.

Architecture Overview

The payment system follows a provider-based architecture where a unified PaymentProvider interface abstracts the specifics of each payment scheme. This design allows the MCP server to remain agnostic to payment implementation details while providing a consistent interface for payment validation, credential extraction, and header forwarding.

graph TD
    subgraph "MCP Client"
        A[Tool Call with Payment]
    end
    
    subgraph "Apify MCP Server"
        B[Payment Provider Resolution]
        C[validatePayment]
        D[removePaymentFields]
        E[getPaymentHeaders]
        F[decorateToolSchema]
    end
    
    subgraph "Payment Providers"
        G[x402 Provider]
        H[Skyfire Provider]
    end
    
    subgraph "Apify API"
        I[Actor Execution]
        J[Payment Verification]
    end
    
    A --> B
    B --> G
    B --> H
    C --> D
    D --> E
    E --> I
    F -.->|Decorates| A
    I --> J

Source: src/payments/types.ts:45-87

Core Types and Interfaces

PaymentProviderId

The system defines two supported payment provider identifiers:

export type PaymentProviderId = 'skyfire' | 'x402';
ProviderDescription
skyfireSkyfire agentic payments using PAY tokens in tool arguments
x402x402 protocol using HTTP 402 with PAYMENT-SIGNATURE header

Source: src/payments/types.ts:14-19

PaymentProvider Interface

Every payment provider must implement the PaymentProvider interface:

MethodReturn TypePurpose
idPaymentProviderId (readonly)Provider identifier
decorateToolSchema(tool)ToolEntryAdd payment fields to tool definitions
validatePayment(args, meta, headers)`string \null`Validate credentials before execution
getPaymentHeaders(args, meta, headers)PaymentHeadersExtract headers for Apify API
removePaymentFields(args)Record<string, unknown>Clean args before Actor input
allowsUnauthenticatedbooleanWhether token-less access is permitted
getPaymentRequiredData?()unknownOptional x402 structured payment data
getUsageGuide?()`string \null`Optional payment usage documentation

Source: src/payments/types.ts:45-87

Supporting Types

// Headers forwarded to Apify API requests
export type PaymentHeaders = Record<string, string>;

// MCP request _meta field for payment schemes like x402
export type PaymentMeta = Record<string, unknown> | undefined;

// HTTP headers from MCP transport layer
export type RequestHeaders = Record<string, string | string[] | undefined> | undefined;

Source: src/payments/types.ts:22-35

Payment-Aware Tool Call Context

The PrepareToolCallContextResult type centralizes payment processing for tool calls:

export type PrepareToolCallContextResult = {
    paymentRequiredResult?: ReturnType<typeof buildPaymentRequiredResponse>;
    toolArgsWithoutPayment: Record<string, unknown>;
    toolArgsRedacted: unknown;
    apifyClient: ApifyClient;
};
FieldTypePurpose
paymentRequiredResult`MCPResponse \undefined`Structured 402 error response if payment fails
toolArgsWithoutPaymentRecord<string, unknown>Args stripped of payment fields for AJV validation
toolArgsRedactedunknownArgs with sensitive fields masked for logging
apifyClientApifyClientClient configured with payment headers or standard token

Source: src/payments/helpers.ts:7-16

x402 Payment Provider

The x402 provider enables blockchain-based payments using EIP-3009 TransferWithAuthorization on Base network.

Payment Flow

sequenceDiagram
    participant Client
    participant MCP_Server
    participant Apify_API
    
    Client->>Client: Sign EIP-3009 TransferWithAuthorization
    Client->>MCP_Server: Tool call with _meta["x402/payment"]
    MCP_Server->>MCP_Server: validatePayment()
    MCP_Server->>MCP_Server: getPaymentHeaders()
    MCP_Server->>Apify_API: Forward PAYMENT-SIGNATURE header
    Apify_API->>Apify_API: Verify signature & settle payment
    Apify_API-->>MCP_Server: Actor execution result
    MCP_Server-->>Client: Response

x402 Payment Types

export type X402PaymentAccept = {
    scheme?: string;
    network?: string;
    amount?: string;
    asset?: string;
    payTo?: string;
    maxTimeoutSeconds?: number;
    extra?: Record<string, unknown>;
};

export type X402PaymentRequirements = {
    x402Version?: number;
    resource?: Record<string, unknown>;
    accepts?: X402PaymentAccept[];
};

Source: src/payments/x402.ts:18-28

Payment Data Extraction

The x402 provider reads payment data from two sources in priority order:

  1. MCP _meta field (preferred): meta["x402/payment"] contains the decoded JSON payment object
  2. HTTP PAYMENT-SIGNATURE header (fallback): Base64-encoded payment data from HTTP transport
function getEncodedPaymentSignature(
    meta?: PaymentMeta, 
    requestHeaders?: RequestHeaders
): string | undefined {
    const metaPayment = meta?.[X402_META_KEY];
    if (metaPayment) {
        return Buffer.from(JSON.stringify(metaPayment)).toString('base64');
    }
    return getPaymentSignatureFromHeader(requestHeaders);
}

Source: src/payments/x402.ts:75-86

Caching Mechanism

The x402 provider caches payment requirements at module level to prevent thundering herd during server startup:

ParameterValue
Cache TTL30 minutes
Cached Item`Promise<X402PaymentRequirements \undefined>`
let cachedRequirementsPromise: Promise<X402PaymentRequirements | undefined> | null = null;
let lastFetchTime = 0;
const CACHE_TTL_MS = 30 * 60 * 1000;

Source: src/payments/x402.ts:35-41

x402 Provider Constants

ConstantValuePurpose
X402_META_KEYx402/paymentKey for MCP _meta field
PAYMENT_SIGNATURE_HEADERPAYMENT-SIGNATUREHTTP header for Apify API
PAYMENT_PROTOCOL_HEADERx-apify-payment-protocolProtocol identification
PAYMENT_REQUIRED_HEADERpayment-requiredResponse header for 402
FETCH_TIMEOUT_MS8000Timeout for payment requirements fetch

Source: src/payments/x402.ts:52-63

Payment Error Handling

402 Response Building

The buildPaymentRequiredResponse function constructs MCP responses for payment failures following the x402 MCP transport spec:

export function buildPaymentRequiredResponse(
    errorOrMessage: unknown, 
    precomputedPaymentData?: unknown
) {
    const paymentData = precomputedPaymentData ?? extractPaymentRequiredData(errorOrMessage);
    const message = errorOrMessage instanceof Error ? errorOrMessage.message : String(errorOrMessage);

    const texts = paymentData
        ? [
            JSON.stringify(paymentData),
            'Payment required to run this Actor or access this resource.',
        ]
        : [message];

    return buildMCPResponse({ texts, isError: true, structuredContent: paymentData });
}

Source: src/utils/payment_errors.ts:44-60

Payment Data Extraction

Payment-required data is extracted from two sources in priority order:

PrioritySourceAccess Method
1Captured HTTP headerAxios interceptor stores payment-required response header
2API response bodyApifyApiError.data field
function extractPaymentRequiredData(error: unknown): Record<string, unknown> | undefined {
    // Source 1: Captured payment-required header
    const captured = (error as ErrorWithPaymentData)[PAYMENT_REQUIRED_DATA];
    if (captured && typeof captured === 'object') return captured;

    // Source 2: ApifyApiError.data (API response body)
    if (error instanceof ApifyApiError) {
        const { data } = error;
        if (typeof data === 'object' && data !== null) return data as Record<string, unknown>;
    }

    return undefined;
}

Source: src/utils/payment_errors.ts:66-87

Axios Interceptor

An axios interceptor captures the payment-required response header from Apify API responses:

apifyClient.addInterceptorResponseError(async (error) => {
    const response = (error as AxiosError<{ response?: { headers?: Record<string, string> } }>)
        ?.response;
    const paymentData = response?.status === HTTP_PAYMENT_REQUIRED
        ? decodePaymentRequiredHeader(response.headers?.[PAYMENT_REQUIRED_HEADER])
        : undefined;

    if (paymentData) {
        Object.defineProperty(error as object, PAYMENT_REQUIRED_DATA, { 
            value: paymentData, 
            enumerable: false 
        });
    }

    return Promise.reject(error);
});

Source: src/utils/payment_errors.ts:18-31

Tool Call Processing Workflow

graph TD
    A[Tool Call Received] --> B{Pre-process payment}
    B --> C[validatePayment]
    C -->|Valid| D[removePaymentFields]
    C -->|Invalid| E[Return 402 Response]
    D --> F[Redact sensitive fields]
    F --> G[Create ApifyClient with payment headers]
    G --> H[AJV validation on clean args]
    H -->|Valid| I[Execute Actor]
    H -->|Invalid| J[Return validation error]
    I --> K[Return result]
    
    style E fill:#ff6b6b
    style K fill:#51cf66

Usage Guide Integration

Payment providers can optionally expose usage guides as MCP resources:

const listResources = async (): Promise<ListResourcesResult> => {
    const resources: Resource[] = [];

    if (paymentProvider?.getUsageGuide?.()) {
        resources.push({
            uri: 'file://readme.md',
            name: 'readme',
            description: 'Apify MCP Server usage guide...',
            mimeType: 'text/markdown',
        });
    }
    // ...
};

Source: src/resources/resource_service.ts:27-38

Configuration Reference

Configuration OptionProviderDescription
APIFY_TOKENStandardApify API token for traditional authentication
payment=x402x402Query parameter to enable x402 payments
--x402x402CLI flag to enable x402 protocol

Source: README.md

Security Considerations

Field Redaction

Sensitive payment fields are redacted before logging to prevent credential exposure:

// From PaymentProvider interface
redactForLogging(args: unknown): unknown;

Field Removal

Payment-specific fields are stripped from tool arguments before passing to Actor input:

removePaymentFields(args: Record<string, unknown>): Record<string, unknown>;

This ensures:

  1. AJV validation operates on clean schema without payment-specific fields
  2. Actor input does not contain provider-specific payment data
  3. Logging contains redacted versions only

Source: https://github.com/apify/apify-mcp-server / Human Manual

Widget System

Related topics: UI Components Library

Section Related Pages

Continue reading this section for the full explanation and source context.

Section High-Level Architecture

Continue reading this section for the full explanation and source context.

Section Widget Loading Flow

Continue reading this section for the full explanation and source context.

Section Widget Initialization (init-widget.tsx)

Continue reading this section for the full explanation and source context.

Related topics: UI Components Library

Widget System

Overview

The Widget System provides interactive, self-contained UI components that render inside MCP (Model Context Protocol) clients, specifically optimized for MCP Apps. Widgets enable rich visual experiences for Actor discovery, details viewing, and run monitoring without requiring the client to implement custom rendering logic.

Architecture

High-Level Architecture

graph TD
    subgraph "MCP Client"
        A[MCP Apps SDK]
    end
    
    subgraph "Apify MCP Server"
        B[Resource Handler]
        C[Tool Handlers]
        D[Available Widgets Registry]
    end
    
    subgraph "Widget Bundle"
        E[Actor Search Widget]
        F[Actor Detail Widget]
        G[Actor Run Widget]
    end
    
    subgraph "UI Library"
        H[@apify/ui-library]
        I[@apify/ui-icons]
    end
    
    A -->|ui://widget/*| B
    B -->|Lookup| D
    D -->|Return Widget Path| B
    B -->|Read JS Bundle| E
    B -->|Read JS Bundle| F
    B -->|Read JS Bundle| G
    E -->|Import| H
    F -->|Import| H
    G -->|Import| H
    C -->|Tool Output| A

Widget Loading Flow

sequenceDiagram
    participant Client as MCP Client
    participant Server as MCP Server
    participant FS as File System
    participant Widget as Widget Bundle

    Client->>Server: resources/read with ui://widget/actor-detail.html
    Server->>Server: Check getMode() === ServerMode.APPS
    Server->>Server: Lookup widget in availableWidgets
    Server->>FS: Read widget.jsPath
    FS-->>Server: widgetJs content
    Server->>Server: Wrap in HTML template
    Server-->>Client: HTML resource with MIME type
    Client->>Widget: Execute module script
    Widget->>Widget: useWidgetProps() reads tool output
    Widget->>Widget: renderWidget() mounts component

Widget Types

The system implements three primary widget types:

WidgetFilePurpose
Actor Search Widgetsearch-actors-widget.tsxSearch and browse Actors in Apify Store
Actor Detail Widgetactor-detail-widget.tsxDisplay Actor information, pricing, input schema
Actor Run Widgetactor-run-widget.tsxShow Actor execution progress and results

Core Components

Widget Initialization (`init-widget.tsx`)

The renderWidget function is the entry point for all widgets:

// src/web/src/utils/init-widget.tsx
renderWidget(WidgetComponent);

This function:

  1. Creates a root container element
  2. Renders the widget component into the container
  3. Injects the necessary styles and context providers
  4. Returns cleanup functions for hot-reload scenarios

Widget Props Hook (`use-widget-props.ts`)

Widgets receive tool output data through the useWidgetProps hook:

// src/web/src/widgets/actor-detail-widget.tsx
const toolOutput = useWidgetProps<WidgetToolOutput>();
const details = toolOutput?.details;

The hook interface:

PropertyTypeDescription
details`ActorDetails \undefined`Actor information from tool call
inputRecord<string, unknown>Input parameters
metaWidgetMetaMetadata about the widget session

MCP App Context (`mcp-app-context.tsx`)

Provides global state and utilities for widgets:

interface McpAppContextValue {
    // Context methods and state
}

Widget Wrapper Pattern

Each widget follows a consistent wrapper pattern:

// src/web/src/widgets/actor-detail-widget.tsx
const ActorDetailWrapper = () => {
    const toolOutput = useWidgetProps<WidgetToolOutput>();
    const details = toolOutput?.details;

    if (!details) {
        return <div>No actor details available</div>;
    }

    return <ActorSearchDetail details={details} />;
};

(async () => {
    if (IS_DEV_BUILD) {
        const { setupActorDetailWidgetDev } = await import("./actor-detail-widget.dev");
        setupActorDetailWidgetDev();
    }
    renderWidget(ActorDetailWrapper);
})();

Resource Service Integration

URI Scheme

Widgets are exposed as MCP resources using the ui://widget/ URI scheme:

ui://widget/actor-search.html
ui://widget/actor-detail.html
ui://widget/actor-run.html

Source: src/resources/resource_service.ts

Resource Handler Logic

// src/resources/resource_service.ts
if (getMode() === ServerMode.APPS && uri.startsWith('ui://widget/')) {
    const widget = getAvailableWidgets().get(uri);

    if (!widget || !widget.exists) {
        return {
            contents: [{
                uri,
                mimeType: 'text/plain',
                text: `Widget ${uri} is not available. ${!widget ? 'Not found in registry.' : `File not found at ${widget.jsPath}`}`,
            }],
        };
    }

    try {
        const fs = await import('node:fs');
        const widgetJs = fs.readFileSync(widget.jsPath, 'utf-8');

        const widgetHtml = `<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>${widget.title}</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module">${widgetJs}</script>
  </body>
</html>`;

        const widgetContent: ExtendedResourceContents = {
            uri,
            mimeType: RESOURCE_MIME_TYPE,
            text: widgetHtml,
            html: widgetHtml,
            _meta: widget.meta,
        };
        return { contents: [widgetContent] };
    } catch (error) {
        return {
            contents: [{
                uri,
                mimeType: 'text/plain',
                text: `Failed to load widget: ${errorMessage}`,
            }],
        };
    }
}

Bundle Size Optimization

Optimization Strategy

Widget bundles are optimized through narrow imports from @apify/ui-library. The top-level barrel import pulls in heavy transitive dependencies (floating UI, markdown helpers), which are avoided by importing specific modules.

Import Patterns

// ❌ AVOID - Pulls entire library
import { Button } from '@apify/ui-library';

// ✅ PREFER - Narrow import
import { Button } from '@apify/ui-library/dist/src/...';

Source: res/web-widget-bundle-size.md

Verified Bundle Sizes

WidgetBeforeAfterReduction
actor-run-widget~1.86 MB~1.16 MB38%
actor-detail-widget~1.86 MB~1.52 MB18%
search-actors-widget~1.87 MB~1.53 MB18%

Source: res/web-widget-bundle-size.md

Special Cost Center: Markdown

Markdown rendering is treated as a special cost center. Changes to markdown processing require re-measuring bundle size impact.

Development Workflow

Hot-Reload Development

The development server supports hot-reload for widgets:

APIFY_TOKEN='your-apify-token' pnpm run dev

This starts:

  1. Web widget builder in watch mode
  2. MCP server in standby mode on port 3001
  3. Local esbuild dev server at http://localhost:3226

Source: DEVELOPMENT.md

Preview Widgets

Widgets can be previewed locally via:

http://localhost:3226/index.html

The preview page links to:

  • Actor Search Widget: /index-actor-search.html
  • Actor Run Widget: /index-actor-run.html

UI Mode Requirement

Widget rendering requires the server to run in UI mode. Enable via:

  • Query parameter: /mcp?ui=true
  • Environment variable: UI_MODE=true

Widget Tool Output Interface

Each widget expects a specific output structure from the invoking tool:

interface WidgetToolOutput extends Record<string, unknown> {
    details?: ActorDetails;
}

interface ActorDetails {
    name: string;
    description: string;
    pricing: PricingInfo;
    inputSchema: InputSchema;
    // ... other properties
}

Design System Compliance

Widgets must follow the Apify design system rules defined in DESIGN_SYSTEM_AGENT_INSTRUCTIONS.md:

Token Usage

Token CategoryUsageExample
ColorsUse theme.color.*theme.color.neutral.text
SpacingUse theme.space.*theme.space.space16
ShadowsUse theme.shadow.*theme.shadow.shadow2

Component Structure

// 1. Imports
import styled from 'styled-components';
import { theme } from '@apify/ui-library';

// 2. Constants & Types
export const COMPONENT_VARIANTS = { ... } as const;

// 3. Styled Components
const StyledWrapper = styled.div`...`;

// 4. Component Implementation
export const Component = forwardRef<HTMLElement, Props>((props, ref) => {
    // implementation
});

// 5. Display Name
Component.displayName = 'Component';

Skeleton Loading States

Widgets implement skeleton loading states for async content:

// src/web/src/pages/ActorSearch/ActorSearch.skeleton.tsx
const SectionHeaderSkeleton: React.FC = () => {
    return (
        <SectionHeaderWrapper px="space16" py="space12">
            <SkeletonBlock style={{ height: '24px', width: '96px' }} />
            <SkeletonBlock style={{ height: '16px', width: '64px' }} />
        </SectionHeaderWrapper>
    );
};

Configuration

Widget Registry

Widgets are registered in the availableWidgets registry, which tracks:

  • Widget URI path
  • JavaScript file path
  • Title for HTML template
  • Existence status
  • Metadata

Server Mode

Widget resources are only available when getMode() === ServerMode.APPS. In default mode, requests to ui://widget/* URIs return an error message.

Source: https://github.com/apify/apify-mcp-server / Human Manual

UI Components Library

Related topics: Widget System

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Component Location and Structure

Continue reading this section for the full explanation and source context.

Section Widget Rendering Pipeline

Continue reading this section for the full explanation and source context.

Section Bundle Optimization Strategy

Continue reading this section for the full explanation and source context.

Related topics: Widget System

UI Components Library

Overview

The Apify MCP Server utilizes a dedicated UI Components Library to render interactive widgets within the MCP Apps environment. These components enable the server to deliver rich, styled user interfaces for displaying Actor information, search results, and run progress directly within AI assistant applications.

The UI components are built using React 18.3.1 and styled-components 6.3.8, with design tokens sourced from the @apify/ui-library package. Source: src/web/package.json

Architecture

Component Location and Structure

UI widgets reside in src/web/src/widgets/ and leverage shared components from src/web/src/components/ui/. The component library follows a consistent pattern where all styled components import the theme object from @apify/ui-library to ensure design consistency across the application. Source: DESIGN_SYSTEM_AGENT_INSTRUCTIONS.md

Widget Rendering Pipeline

The following diagram illustrates how UI components integrate with the MCP server:

graph TD
    A[MCP Client Request] --> B[Server Handler]
    B --> C{Server Mode}
    C -->|APPS| D[Widget Registry]
    C -->|DEFAULT| E[Standard Response]
    D --> F[Read Widget JS Bundle]
    F --> G[Wrap in HTML Template]
    G --> H[Return HTML via Resource]
    H --> I[MCP Apps Renderer]
    I --> J[React Components Mount]

Source: src/resources/resource_service.ts

Bundle Optimization Strategy

The widget bundles must remain self-contained while minimizing payload size. The system uses direct module imports from @apify/ui-library/dist/src/... instead of top-level imports to avoid pulling in heavy transitive dependencies. Source: res/web-widget-bundle-size.md

Bundle size improvements achieved:

WidgetBeforeAfterReduction
actor-run-widget~1.86 MB~1.16 MB37.6%
actor-detail-widget~1.86 MB~1.52 MB18.3%
search-actors-widget~1.87 MB~1.53 MB18.2%

Design System Compliance

All UI components must adhere to strict design system rules defined in DESIGN_SYSTEM_AGENT_INSTRUCTIONS.md. These rules ensure visual consistency and maintainability across all widgets. Source: DESIGN_SYSTEM_AGENT_INSTRUCTIONS.md

Design Tokens

Components must use theme.* tokens exclusively for all styling values. Hardcoded values are strictly forbidden.

// ❌ FORBIDDEN
color: '#1976d2'
padding: '8px'
border-radius: '4px'

// ✅ REQUIRED
color: ${theme.color.primary.action}
padding: ${theme.space.space8}
border-radius: ${theme.radius.radius2}

Available token categories:

CategoryExamplesPurpose
Colorstheme.color.primary.action, theme.color.neutral.textMutedBrand colors and semantic variants
Spacingtheme.space.space8, theme.space.space16, theme.space.space40Padding, margins, gaps
Border Radiustheme.radius.radius2, theme.radius.radius3Component corners
Shadowstheme.shadow1, theme.shadow3, theme.shadowActiveElevation and depth

Source: DESIGN_SYSTEM_AGENT_INSTRUCTIONS.md

Component Import Pattern

All shared UI components should be imported from @apify/ui-library. Components must never be duplicated locally or imported from arbitrary relative paths.

// ✅ Correct
import { Button, Badge, Chip, Text, Heading } from '@apify/ui-library';

// ❌ Never create duplicate implementations

Component Patterns

Styled Components Structure

The project follows a standardized component structure to ensure consistency across all UI elements. Source: DESIGN_SYSTEM_AGENT_INSTRUCTIONS.md

Component file organization:

// 1. Imports (grouped)
import { forwardRef } from 'react';
import styled from 'styled-components';
import { theme } from '@apify/ui-library';

// 2. Constants & Types
export const COMPONENT_VARIANTS = { ... } as const;
type ComponentVariants = ValueOf<typeof COMPONENT_VARIANTS>;

// 3. Styled Components
const StyledWrapper = styled.div`...`;

// 4. Component Implementation
export const Component = forwardRef<HTMLElement, Props>((props, ref) => {
    // implementation
});

// 5. Display Name
Component.displayName = 'Component';

Transient Props Convention

Component props that should not be passed to the underlying DOM element must use the $ prefix:

const StyledButton = styled.button<{ $variant?: string }>`
    background: ${({ $variant }) => 
        $variant === 'primary' 
            ? theme.color.primary.action 
            : theme.color.neutral.background
    };
`;

Common transient props: $variant, $isActive, $size

Source: DESIGN_SYSTEM_AGENT_INSTRUCTIONS.md

Typography Components

Typography must use the Text and Heading components from @apify/ui-library rather than direct styling:

// ✅ Correct
import { Text, Heading } from '@apify/ui-library';

<Text type="body" size="regular" weight="normal">Content here</Text>
<Heading type="titleL">Title here</Heading>

// ❌ Never style text elements directly
// ❌ Never use typography tokens

Source: DESIGN_SYSTEM_AGENT_INSTRUCTIONS.md

Spacing System

The design system defines a consistent spacing scale that must be used for all layout measurements:

TokenUsageExample
space4Inline elements, icon gapsgap: ${theme.space.space4}
space8Button padding, small gapspadding: ${theme.space.space8}
space12Component internal spacingpadding: ${theme.space.space12}
space16Standard component paddingpadding: ${theme.space.space16}
space24Section marginsmargin: ${theme.space.space24}
space32Section separatorsmargin: ${theme.space.space32}
space40, space64, space80Large layoutsContainer margins

Rule: Never use arbitrary values like gap: 10px — always round to the nearest design token.

Source: DESIGN_SYSTEM_AGENT_INSTRUCTIONS.md

Common Pitfalls

Token Misuse

Avoid mixing hardcoded values with design tokens in the same property:

// ❌ WRONG
padding: ${theme.space.space16} 10px;

// ✅ CORRECT
padding: ${theme.space.space16} ${theme.space.space10};

Non-existent Token Properties

Always verify token property names exist in the theme object:

// ❌ WRONG - These properties don't exist
theme.color.neutral.textLight
theme.color.primary.main

// ✅ CORRECT - Use actual property names
theme.color.neutral.textMuted
theme.color.primary.action

Source: DESIGN_SYSTEM_AGENT_INSTRUCTIONS.md

Widget Output Schemas

UI components receive data through structured output schemas that define the expected data format:

Actor Details Widget Schema

export const actorDetailsWidgetOutputSchema = {
    type: 'object',
    properties: {
        actorDetails: {
            type: 'object',
            properties: {
                actorInfo: { 
                    type: 'object', 
                    description: 'Widget-formatted Actor info (tier-aware pricing, widget display fields).' 
                },
                actorCard: { 
                    type: 'string', 
                    description: 'Rendered Actor card markdown for widget display.' 
                },
                readme: { 
                    type: 'string', 
                    description: 'Formatted Actor README for widget display.' 
                },
            },
            required: ['actorInfo', 'actorCard', 'readme'],
        },
    },
    required: ['actorDetails'],
};

Source: src/tools/structured_output_schemas.ts

Actor Search Widget Schema

export const actorSearchOutputSchema = {
    type: 'object',
    properties: {
        actors: {
            type: 'array',
            items: actorInfoSchema,
            description: 'List of Actor cards matching the search query',
        },
        query: { type: 'string', description: 'The search query used' },
        count: { type: 'number', description: 'Number of Actors returned' },
        instructions: { type: 'string', description: 'Additional instructions for the LLM.' },
    },
    required: ['actors', 'query', 'count'],
};

Source: src/tools/structured_output_schemas.ts

Widget Configuration

Server Mode Detection

The UI components library operates differently based on the server mode:

ModeBehaviorWidget Tools Available
DEFAULTStandard MCP responseNo widget tools exposed
APPSWidget rendering enabledsearch-actors-widget, fetch-actor-details-widget, actor-run-widget

Source: src/utils/server-instructions/index.ts

Resource URI Scheme

Widgets are accessed via the ui://widget/ URI scheme in APPS mode:

ui://widget/search-actors.html
ui://widget/actor-detail.html
ui://widget/actor-run.html

Source: src/resources/resource_service.ts

Development Workflow

Pre-Work Checklist

Before any UI component work, developers should:

  1. Check MCP availability — Search for mcp__storybook__* and mcp__figma__* tools
  2. Load design context — Call mcp__storybook__get-ui-building-instructions if available
  3. Read existing patterns — Find 1-3 similar components in src/web/src/**/*{keyword}*.{tsx,ts}
  4. Use Grep for patterns — Search for theme\.color\.|theme\.space\.|theme\.radius\.

Verification Protocol

Before submitting UI changes, verify:

CheckCommand/MethodExpected Result
Color auditRegex ['"]#[0-9a-fA-F]{3,8}['"]Zero matches
Spacing auditRegex ['"][0-9]+px['"]Zero matches
Import checkAll styled-components import theme100% compliance
Pattern matchCompare to 1-3 similar componentsConsistent structure

Source: DESIGN_SYSTEM_AGENT_INSTRUCTIONS.md

Bundle Optimization Guidelines

Import Optimization

The @apify/ui-library package uses a barrel export pattern. Direct module imports significantly reduce bundle size:

// ❌ Heavy - pulls entire library
import { Button } from '@apify/ui-library';

// ✅ Optimized - only includes Button
import { Button } from '@apify/ui-library/dist/src/primitives/Button';

Cost Centers

Component/FeatureBundle ImpactNotes
Floating UIHighHeavy transitive dependency
Markdown renderingHighSpecial cost center - measure impact on changes
Convenience componentsMediumPrefer narrow imports
Primitive componentsLowDirect module imports sufficient

Source: res/web-widget-bundle-size.md

Dependencies

Core UI Dependencies

PackageVersionPurpose
react^18.3.1UI framework
react-dom^18.3.1React DOM rendering
styled-components^6.3.8CSS-in-JS styling
@apify/ui-library^1.124.0Design system tokens and primitives
@apify/ui-icons^1.27.2Icon components

Build Dependencies

PackageVersionPurpose
esbuild^0.28.0Fast bundler for widgets
typescript^5.6.3Type safety
tailwindcss^3.4.17Utility CSS (used sparingly)

Source: src/web/package.json

Source: https://github.com/apify/apify-mcp-server / Human Manual

Development Setup

This guide covers everything needed to set up a local development environment for the Apify MCP Server project.

Section System Requirements

Continue reading this section for the full explanation and source context.

Section Repository Architecture

Continue reading this section for the full explanation and source context.

Section 1. Enable Corepack

Continue reading this section for the full explanation and source context.

Section 2. Install Dependencies

Continue reading this section for the full explanation and source context.

Prerequisites

System Requirements

RequirementMinimum VersionNotes
Node.js20.0.0+Required runtime
pnpm11+Package manager
Claude Desktop0.2.16+For desktop integration

Supported Platforms: macOS (darwin), Windows (win32), Linux (linux)

Source: manifest.json:15-24

Repository Architecture

The project uses a monorepo structure with the following key directories:

apify-mcp-server/
├── src/                    # Main MCP server source code
│   ├── mcp/               # MCP protocol implementation
│   └── web/               # React widgets for MCP Apps UI
├── tests/
│   ├── unit/              # Unit tests
│   └── integration/       # Integration tests
└── res/                   # Resource documentation

Source: DEVELOPMENT.md:50-57

Installation

1. Enable Corepack

The project uses pnpm 11+ as specified in package.json#packageManager. Corepack (bundled with Node 16+) automatically manages the pnpm version:

corepack enable

This is a one-time setup that makes pnpm available system-wide.

2. Install Dependencies

Install all project dependencies in a single command:

pnpm install

This command installs dependencies for both the root workspace and the src/web workspace package simultaneously.

Note: The devEngines.packageManager is pinned with onFail: "error", which means running npm install or yarn install will fail. This ensures lockfile consistency.

Source: DEVELOPMENT.md:41-45

Environment Configuration

APIFY_TOKEN Setup

The APIFY_TOKEN is required for most server operations.

#### For Claude Code

Create or edit .claude/settings.local.json:

{
  "env": {
    "APIFY_TOKEN": "<YOUR_APIFY_API_TOKEN>"
  }
}

Restart Claude Code for the changes to take effect. The token is automatically picked up by both Claude Code MCP servers (defined in .mcp.json) and mcpc.

#### For Local Development

Create an environment file .env in the project root:

APIFY_TOKEN="your-apify-token"

Source: DEVELOPMENT.md:14-24

Environment Variables Reference

VariableRequiredDescription
APIFY_TOKENYesApify API authentication token
APIFY_META_ORIGINNoMeta origin for tracking (e.g., STANDBY)
UI_MODENoEnable UI mode for widget rendering (true/false)

Building the Project

Production Build

To build the MCP server for production:

pnpm run build

This compiles the TypeScript source and produces output in the dist/ directory.

Source: DEVELOPMENT.md:64-68

Development Server

For active development with hot-reload capabilities, the project includes a development server at src/dev_server.ts. This server provides:

  • Automatic recompilation on file changes
  • Debugging endpoints for MCP protocol inspection
  • Live widget preview at http://localhost:3001

Running the Server

HTTP Streamable Mode

Run the server as an HTTP server using Apify CLI:

export APIFY_TOKEN="your-apify-token"
export APIFY_META_ORIGIN=STANDBY
apify run -p

The server will be exposed at http://localhost:3001.

Source: README.md:28-34

Standard I/O (stdio) Mode

For use with the MCP Inspector or local clients:

export APIFY_TOKEN="your-apify-token"
npx @modelcontextprotocol/inspector node ./dist/stdio.js

The Inspector will display a URL for browser-based debugging.

Source: README.md:40-46

Testing

Testing Layers

The project implements a multi-layer testing strategy:

LayerCommandCoverage
Unit Testspnpm run test:unitIndividual modules in isolation
Integration Testspnpm run test:integrationFull server over all transports against real Apify API
Interactive Verificationmcpc @stdio tools-call ...End-to-end during development
LLM EvaluationsCI onlyMultiple models via OpenRouter

Source: DEVELOPMENT.md:26-36

Unit Tests

Unit tests verify individual modules without external dependencies:

pnpm run test:unit

No credentials are required for unit tests.

Integration Tests

Integration tests verify the complete MCP server functionality:

pnpm run test:integration

Requirements:

  • Valid APIFY_TOKEN environment variable
  • Compiled production build (pnpm run build)

Interactive Probing with mcpc

For manual verification during development:

mcpc @stdio tools-call ...

LLM Evaluations

LLM evaluations run in CI and require the validated label on the PR:

# Trigger eval workflow
# 1. Apply the 'validated' label to your PR

# Environment variables required in CI:
PHOENIX_*        # Phoenix evaluation platform credentials
OPENROUTER_*     # OpenRouter API credentials

Evaluations run automatically:

  • When validated label is applied to a PR
  • On every merge to the master branch

Results are posted to Phoenix for analysis.

Source: DEVELOPMENT.md:35-38

Development Workflow

Mermaid: Development Workflow

graph TD
    A[Clone Repository] --> B[Enable corepack]
    B --> C[pnpm install]
    C --> D[Configure APIFY_TOKEN]
    D --> E{Development Mode}
    
    E -->|HTTP Stream| F[apify run -p]
    E -->|stdio| G[node ./dist/stdio.js]
    E -->|Widget Dev| H[src/web dev server]
    
    F --> I[Debug with MCP Inspector]
    G --> I
    H --> J[Browser Preview: localhost:3001]
    
    I --> K{Testing}
    K -->|Unit| L[pnpm run test:unit]
    K -->|Integration| M[pnpm run test:integration]
    K -->|Manual| N[mcpc probing]
    
    L --> O[Validate & Submit PR]
    M --> O
    N --> O

Branch Naming

All feature branches must follow the format:

<type>/<short-description>

Where <type> matches conventional commit types:

TypeUse Case
featNew features
fixBug fixes
choreMaintenance tasks
refactorCode refactoring
docsDocumentation updates

Examples:

  • feat/add-dataset-tool
  • fix/connection-timeout
  • chore/update-dependencies

Source: CONTRIBUTING.md:8-13

Commit Messages

All commits and PR titles must follow the Conventional Commits format:

<type>(<scope>)!: <description>
ComponentRequiredDescription
typeYesfeat, fix, chore, refactor, docs, etc.
scopeYesThe affected component/module
!NoIndicates breaking change
descriptionYesBrief summary of changes

Examples:

feat: Add new tool for fetching actor details
feat!: Migrate to new MCP SDK version
fix: Handle connection errors gracefully
chore: Update dependencies

Source: CONTRIBUTING.md:17-35

UI Widget Development

Widget Architecture

The MCP Apps (ChatGPT Apps) UI widgets are built as a separate React project within src/web/. Widgets are rendered based on tool output—modifying widget data requires changing the corresponding tool's return value.

UI Mode

Widget rendering requires the server to run in UI mode:

Via Query Parameter:

/mcp?ui=true

Via Environment Variable:

export UI_MODE=true

Via CLI Flag:

npx @apify/actors-mcp-server --ui true

Widget Preview

Preview widgets during development:

# Actor Search Widget
# Open: http://localhost:3001/index-actor-search.html

# Actor Run Widget  
# Open: http://localhost:3001/index-actor-run.html

Source: DEVELOPMENT.md:58-62

Code Quality Standards

Naming Conventions

ElementConventionExample
Types/InterfacesPascalCaseActorDetails, ToolConfig
Variables/FunctionscamelCaseactorName, fetchActorDetails()
ConstantsSCREAMING_SNAKE_CASEMAX_RETRIES, WIDGET_REGISTRY
Zod ValidatorsSuffix with ValidatorActorValidator

String Formatting

Single-line strings: Use single quotes

const message = 'Operation completed';

Multi-line strings: Use dedent for LLM-facing content

import dedent from 'dedent';

const description = dedent`
    Line 1
    Line 2
`;

Avoid:

  • [].join('\n') for multiline strings
  • Hardcoded hex colors or pixel values in UI code

Source: CONTRIBUTING.md:56-75

Troubleshooting

Common Issues

IssueSolution
pnpm install failsEnsure Node.js 20+ is installed
Wrong pnpm versionRun corepack enable
Tests fail with "Token required"Set APIFY_TOKEN environment variable
Widgets not renderingVerify UI_MODE=true is set

Node Version Management

The .nvmrc file pins the development tooling Node version (currently 24). This is intentionally higher than the published floor to support modern tooling features.

# Check current Node version
node --version

# Switch to project-required version (requires nvm)
nvm use

Verifying Installation

Run the following commands to verify your setup:

# Verify pnpm version
pnpm --version  # Should be 11+

# Verify Node version
node --version  # Should be 20+

# Run unit tests
pnpm run test:unit

# Build project
pnpm run build

If all commands succeed, your development environment is properly configured.

Source: https://github.com/apify/apify-mcp-server / Human Manual

Doramagic Pitfall Log

Source-linked risks stay visible on the manual page so the preview does not read like a recommendation.

high fix: Allow calling MCP server actors in normal (one-shot) mode

First-time setup may fail or require extra isolation and rollback planning.

high Remove the flat-fields back-compat shim from `_meta.x402` once all consumers read `accepts[]`

Users may get misleading failures or incomplete behavior unless configuration is checked carefully.

high Do not include the rag web browser when ?payment=x402

The project may affect permissions, credentials, data exposure, or host boundaries.

high Perf: `search-actors` tools returns huuuge `inputFields` object

The project may affect permissions, credentials, data exposure, or host boundaries.

Doramagic Pitfall Log

Doramagic extracted 16 source-linked risk signals. Review them before installing or handing real data to the project.

1. Installation risk: fix: Allow calling MCP server actors in normal (one-shot) mode

  • Severity: high
  • Finding: Installation risk is backed by a source signal: fix: Allow calling MCP server actors in normal (one-shot) mode. Treat it as a review item until the current version is checked.
  • User impact: First-time setup may fail or require extra isolation and rollback planning.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: Source-linked evidence: https://github.com/apify/apify-mcp-server/issues/857

2. Configuration risk: Remove the flat-fields back-compat shim from `_meta.x402` once all consumers read `accepts[]`

  • Severity: high
  • Finding: Configuration risk is backed by a source signal: Remove the flat-fields back-compat shim from _meta.x402 once all consumers read accepts[]. Treat it as a review item until the current version is checked.
  • User impact: Users may get misleading failures or incomplete behavior unless configuration is checked carefully.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: Source-linked evidence: https://github.com/apify/apify-mcp-server/issues/892

3. Security or permission risk: Do not include the rag web browser when ?payment=x402

  • Severity: high
  • Finding: Security or permission risk is backed by a source signal: Do not include the rag web browser when ?payment=x402. Treat it as a review item until the current version is checked.
  • User impact: The project may affect permissions, credentials, data exposure, or host boundaries.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: Source-linked evidence: https://github.com/apify/apify-mcp-server/issues/875

4. Security or permission risk: Perf: `search-actors` tools returns huuuge `inputFields` object

  • Severity: high
  • Finding: Security or permission risk is backed by a source signal: Perf: search-actors tools returns huuuge inputFields object. Treat it as a review item until the current version is checked.
  • User impact: The project may affect permissions, credentials, data exposure, or host boundaries.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: Source-linked evidence: https://github.com/apify/apify-mcp-server/issues/888

5. Security or permission risk: feat(telemetry): track tool result size in bytes

  • Severity: high
  • Finding: Security or permission risk is backed by a source signal: feat(telemetry): track tool result size in bytes. Treat it as a review item until the current version is checked.
  • User impact: The project may affect permissions, credentials, data exposure, or host boundaries.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: Source-linked evidence: https://github.com/apify/apify-mcp-server/issues/838

6. Project risk: Project risk needs validation

  • Severity: medium
  • Finding: Project risk is backed by a source signal: Project risk needs validation. Treat it as a review item until the current version is checked.
  • User impact: The project should not be treated as fully validated until this signal is reviewed.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: identity.distribution | github_repo:911256711 | https://github.com/apify/apify-mcp-server | repo=apify-mcp-server; install=@apify/actors-mcp-server

7. Installation risk: chore(core): collapse array indices in dataset fields to prevent nextStep schema bloat

  • Severity: medium
  • Finding: Installation risk is backed by a source signal: chore(core): collapse array indices in dataset fields to prevent nextStep schema bloat. Treat it as a review item until the current version is checked.
  • User impact: First-time setup may fail or require extra isolation and rollback planning.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: Source-linked evidence: https://github.com/apify/apify-mcp-server/issues/894

8. Installation risk: feat: Add structured output to remaining storage tools

  • Severity: medium
  • Finding: Installation risk is backed by a source signal: feat: Add structured output to remaining storage tools. Treat it as a review item until the current version is checked.
  • User impact: First-time setup may fail or require extra isolation and rollback planning.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: Source-linked evidence: https://github.com/apify/apify-mcp-server/issues/884

9. Installation risk: feat: migrate direct actor tools to canonical RunResponse shape

  • Severity: medium
  • Finding: Installation risk is backed by a source signal: feat: migrate direct actor tools to canonical RunResponse shape. Treat it as a review item until the current version is checked.
  • User impact: First-time setup may fail or require extra isolation and rollback planning.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: Source-linked evidence: https://github.com/apify/apify-mcp-server/issues/852

10. Installation risk: test: Consolidate duplicated MCP server test fixtures

  • Severity: medium
  • Finding: Installation risk is backed by a source signal: test: Consolidate duplicated MCP server test fixtures. Treat it as a review item until the current version is checked.
  • User impact: First-time setup may fail or require extra isolation and rollback planning.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: Source-linked evidence: https://github.com/apify/apify-mcp-server/issues/847

11. Configuration risk: feat: Dataset tools correctness and coverage

  • Severity: medium
  • Finding: Configuration risk is backed by a source signal: feat: Dataset tools correctness and coverage. Treat it as a review item until the current version is checked.
  • User impact: Users may get misleading failures or incomplete behavior unless configuration is checked carefully.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: Source-linked evidence: https://github.com/apify/apify-mcp-server/issues/784

12. Capability assumption: README/documentation is current enough for a first validation pass.

  • Severity: medium
  • Finding: README/documentation is current enough for a first validation pass.
  • User impact: The project should not be treated as fully validated until this signal is reviewed.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: capability.assumptions | github_repo:911256711 | https://github.com/apify/apify-mcp-server | README/documentation is current enough for a first validation pass.

Source: Doramagic discovery, validation, and Project Pack records

Community Discussion Evidence

These external discussion links are review inputs, not standalone proof that the project is production-ready.

Sources 12

Count of project-level external discussion links exposed on this manual page.

Use Review before install

Open the linked issues or discussions before treating the pack as ready for your environment.

Community Discussion Evidence

Doramagic exposes project-level community discussion separately from official documentation. Review these links before using apify-mcp-server with real data or production workflows.

Source: Project Pack community evidence and pitfall evidence