# https://github.com/apify/apify-mcp-server Project Manual

Generated on: 2026-05-22 10:52:06 UTC

## Table of Contents

- [Project Overview](#overview)
- [Core Architecture](#architecture-details)
- [Transport Layer](#transport-layer)
- [Tool System](#tool-system)
- [Actor Tools](#actor-tools)
- [Storage Access Tools](#storage-tools)
- [Agentic Payments System](#payments-overview)
- [Widget System](#widget-system)
- [UI Components Library](#ui-components)
- [Development Setup](#development-setup)

<a id='overview'></a>

## Project Overview

### Related Pages

Related topics: [Core Architecture](#architecture-details), [Tool System](#tool-system)

<details>
<summary>Relevant source files</summary>

The following source files were used to generate this page:

- [README.md](https://github.com/apify/apify-mcp-server/blob/main/README.md)
- [manifest.json](https://github.com/apify/apify-mcp-server/blob/main/manifest.json)
- [CONTRIBUTING.md](https://github.com/apify/apify-mcp-server/blob/main/CONTRIBUTING.md)
- [DEVELOPMENT.md](https://github.com/apify/apify-mcp-server/blob/main/DEVELOPMENT.md)
- [res/algolia.md](https://github.com/apify/apify-mcp-server/blob/main/res/algolia.md)
- [res/mcp_resources_analysis.md](https://github.com/apify/apify-mcp-server/blob/main/res/mcp_resources_analysis.md)
- [res/index.md](https://github.com/apify/apify-mcp-server/blob/main/res/index.md)
</details>

# 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:

| Directory | Purpose |
|-----------|---------|
| `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.

```mermaid
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 Category | Description |
|---------------|-------------|
| `actors` | Search and discover Actors on the Apify platform |
| `docs` | Search Apify and Crawlee documentation |
| `apify/rag-web-browser` | RAG-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 Method | Example |
|----------------------|---------|
| Hosted server URL | `https://mcp.apify.com?tools=actors,docs,apify/rag-web-browser` |
| CLI flag | `npx @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 Tool | Description |
|--------------|-------------|
| `search-actors` | Search Actors without authentication |
| `fetch-actor-details` | Get Actor details without authentication |
| `search-apify-docs` | Search Apify docs without authentication |
| `fetch-apify-docs` | Get 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:

```bash
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:

```bash
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:

```json
{
  "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:

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `apify_token` | string | Yes* | - | Apify API token from console.apify.com |
| `tools` | string | No | `actors,docs,apify/rag-web-browser` | Comma-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:

```mermaid
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:

| Source | URL Fragments | Content Field |
|--------|---------------|---------------|
| Apify docs | Supported | Always populated |
| Crawlee docs | Not supported | Not available |

Source: [res/algolia.md:1-50]()

### URL Fragment Handling

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

```typescript
// 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 Type | URI Pattern | Description |
|---------------|-------------|-------------|
| Skyfire usage guide | `file://readme.md` | Enabled when `skyfireMode` is true |
| UI widgets | `ui://widget/*` | React widgets for OpenAI MCP Apps |

Source: [res/mcp_resources_analysis.md:15-30]()

## Development Setup

### Prerequisites

| Requirement | Version |
|-------------|---------|
| Node.js | >=20.0.0 |
| pnpm | 11+ |

Source: [DEVELOPMENT.md:25-30]()

### Installation

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

Source: [DEVELOPMENT.md:30-35]()

### Building

```bash
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 Layer | Command | Coverage |
|------------|---------|----------|
| Unit tests | `pnpm run test:unit` | Individual modules in isolation |
| Integration tests | `pnpm run test:integration` | Full server over all transports |
| LLM evals | CI only (apply `validated` label) | Multiple AI models via OpenRouter |

Source: [DEVELOPMENT.md:8-20]()

### Test Configuration

| Environment Variable | Purpose |
|---------------------|---------|
| `APIFY_TOKEN` | Required 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:

| Property | Token Pattern | Example |
|----------|---------------|---------|
| Text color | `theme.color.{cat}.{prop}` | `theme.color.neutral.text` |
| Background | `theme.color.{cat}.{prop}` | `theme.color.primary.background` |
| Spacing | `theme.space.space{N}` | `theme.space.space16` |
| Border radius | `theme.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

```text
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

| Platform | Claude Desktop Version | Node.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:

| Repository | Purpose |
|------------|---------|
| `apify-mcp-server` (this repo) | Core MCP logic and public code |
| `apify-mcp-server-internal` | Hosted 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]()

---

<a id='architecture-details'></a>

## Core Architecture

### Related Pages

Related topics: [Project Overview](#overview), [Transport Layer](#transport-layer)

<details>
<summary>Relevant source files</summary>

The following source files were used to generate this page:

- [src/mcp/server.ts](https://github.com/apify/apify-mcp-server/blob/main/src/mcp/server.ts)
- [src/mcp/actors.ts](https://github.com/apify/apify-mcp-server/blob/main/src/mcp/actors.ts)
- [src/mcp/client.ts](https://github.com/apify/apify-mcp-server/blob/main/src/mcp/client.ts)
- [src/mcp/resources/resource_service.ts](https://github.com/apify/apify-mcp-server/blob/main/src/mcp/resources/resource_service.ts)
- [src/types.ts](https://github.com/apify/apify-mcp-server/blob/main/src/types.ts)
- [src/mcp/proxy.ts](https://github.com/apify/apify-mcp-server/blob/main/src/mcp/proxy.ts)
</details>

# 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](https://github.com/apify/apify-mcp-server/blob/main/src/mcp/server.ts)

```mermaid
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:

| Property | Type | Purpose |
|----------|------|---------|
| `server` | `Server` | Low-level MCP SDK server instance |
| `tools` | `Map<string, ToolEntry>` | Tool registry for all registered tools |
| `taskStore` | `TaskStore` | Tracks running and completed tasks |
| `actorStore` | `ActorStore` | Caches Actor metadata and input schemas |
| `serverMode` | `ServerMode` | Resolved server mode (default/apps) |
| `options` | `ActorsMcpServerOptions` | Server configuration options |

Source: [src/mcp/server.ts:280-320](https://github.com/apify/apify-mcp-server/blob/main/src/mcp/server.ts)

### Tool Entry Types

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

```typescript
type ToolEntry = HelperTool | ActorTool | ActorMcpTool;
```

| Tool Type | Type Discriminator | Purpose | Source |
|-----------|-------------------|---------|--------|
| `HelperTool` | `type: 'internal'` | Built-in server tools (search, docs) | [src/types.ts:135-145](https://github.com/apify/apify-mcp-server/blob/main/src/types.ts) |
| `ActorTool` | `type: 'actor'` | Dynamic Actor-based tools | [src/types.ts:147-153](https://github.com/apify/apify-mcp-server/blob/main/src/types.ts) |
| `ActorMcpTool` | `type: 'actor-mcp'` | External MCP server proxy via Actor | [src/types.ts:155-162](https://github.com/apify/apify-mcp-server/blob/main/src/types.ts) |

Source: [src/types.ts:130-175](https://github.com/apify/apify-mcp-server/blob/main/src/types.ts)

## 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](https://github.com/apify/apify-mcp-server/blob/main/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](https://github.com/apify/apify-mcp-server/blob/main/src/mcp/server.ts)

| Transport | Use Case | Entry Point |
|-----------|----------|-------------|
| stdio | Local CLI, MCP Inspector | `stdio.ts` |
| HTTP Streamable | Hosted server, remote clients | `dev_server.ts` |

## Request Handler Architecture

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

### Handler Registration Pattern

```typescript
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](https://github.com/apify/apify-mcp-server/blob/main/src/mcp/server.ts)

### Central Tool Dispatcher

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

```mermaid
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](https://github.com/apify/apify-mcp-server/blob/main/src/mcp/server.ts)

## 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](https://github.com/apify/apify-mcp-server/blob/main/src/mcp/actors.ts)

### Tool Registration Flow

```mermaid
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:

| Mode | Trigger | Behavior |
|------|---------|----------|
| `default` | Non-MCP Apps clients | Standard tool responses |
| `apps` | MCP Apps clients (`uiMode === 'openai'`) | Enhanced responses with widget metadata |

Source: [src/mcp/server.ts:300-340](https://github.com/apify/apify-mcp-server/blob/main/src/mcp/server.ts)

### Mode Auto-Detection

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

```typescript
// Preliminary value at construction
public serverMode: ServerMode;

// Finalized inside initialize handler
private serverModeResolved: boolean;
```

Source: [src/mcp/server.ts:310-325](https://github.com/apify/apify-mcp-server/blob/main/src/mcp/server.ts)

## Resource System

The server implements MCP resources for UI widgets and documentation:

### Resource Types

| Resource Type | URI Pattern | Condition | Source |
|---------------|-------------|-----------|--------|
| Skyfire Guide | `file://readme.md` | `skyfireMode === true` | [src/mcp/resources/resource_service.ts](https://github.com/apify/apify-mcp-server/blob/main/src/mcp/resources/resource_service.ts) |
| UI Widgets | `ui://widget/*.html` | `uiMode === 'openai'` | [src/mcp/resources/resource_service.ts](https://github.com/apify/apify-mcp-server/blob/main/src/mcp/resources/resource_service.ts) |

### Resource Handler Implementation

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

Source: [src/mcp/resources/resource_service.ts](https://github.com/apify/apify-mcp-server/blob/main/src/mcp/resources/resource_service.ts)

## Actor-MCP Proxy Architecture

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

```mermaid
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](https://github.com/apify/apify-mcp-server/blob/main/src/mcp/proxy.ts)

## Task Management

### TaskStore

The `TaskStore` class manages long-running task execution:

| Method | Purpose |
|--------|---------|
| `createTask()` | Initialize a new task |
| `updateTask()` | Update task status/progress |
| `getTask()` | Retrieve task details |
| `listTasks()` | List all tasks |

Source: [src/mcp/server.ts](https://github.com/apify/apify-mcp-server/blob/main/src/mcp/server.ts)

### Progress Tracking

Long-running operations support progress notifications via `createProgressTracker`:

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

Source: [src/mcp/server.ts](https://github.com/apify/apify-mcp-server/blob/main/src/mcp/server.ts)

## Client Configuration

### ApifyClient Integration

The server uses the Apify JavaScript client for API communication:

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

Source: [src/mcp/client.ts](https://github.com/apify/apify-mcp-server/blob/main/src/mcp/client.ts)

### Token Propagation

| Location | Mechanism |
|----------|------------|
| HTTP Headers | `Authorization: Bearer <token>` |
| MCP Meta | `_meta.apifyToken` in tool call |

Source: [src/mcp/server.ts:630-650](https://github.com/apify/apify-mcp-server/blob/main/src/mcp/server.ts)

## Configuration Options

The `ActorsMcpServerOptions` interface defines server configuration:

| Option | Type | Default | Purpose |
|--------|------|---------|---------|
| `apifyToken` | `string` | Required | Apify API authentication |
| `tools` | `string \| string[]` | `default` | Tool categories/Actors to load |
| `serverMode` | `ServerModeOption` | `'auto'` | Server mode override |
| `skyfireMode` | `boolean` | `false` | Enable Skyfire-specific resources |
| `uiMode` | `UiMode` | `'default'` | UI response format |

Source: [src/mcp/server.ts:200-280](https://github.com/apify/apify-mcp-server/blob/main/src/mcp/server.ts)

## Capability Advertisement

The server advertises the following MCP capabilities during initialization:

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

Source: [src/mcp/server.ts:210-218](https://github.com/apify/apify-mcp-server/blob/main/src/mcp/server.ts)

## Entry Points

| Entry Point | Transport | File |
|-------------|-----------|------|
| `dist/stdio.js` | stdio | `src/stdio.ts` |
| `dist/index.js` (HTTP) | Streamable HTTP | `src/dev_server.ts` |

Source: [README.md](https://github.com/apify/apify-mcp-server/blob/main/README.md)

---

<a id='transport-layer'></a>

## Transport Layer

### Related Pages

Related topics: [Core Architecture](#architecture-details), [Development Setup](#development-setup)

<details>
<summary>Relevant source files</summary>

The following source files were used to generate this page:

- [src/stdio.ts](https://github.com/apify/apify-mcp-server/blob/main/src/stdio.ts)
- [src/server_card.ts](https://github.com/apify/apify-mcp-server/blob/main/src/server_card.ts)
- [src/index_internals.ts](https://github.com/apify/apify-mcp-server/blob/main/src/index_internals.ts)
- [src/mcp/server.ts](https://github.com/apify/apify-mcp-server/blob/main/src/mcp/server.ts)
- [src/dev_server.ts](https://github.com/apify/apify-mcp-server/blob/main/src/dev_server.ts)
- [src/index.ts](https://github.com/apify/apify-mcp-server/blob/main/src/index.ts)
</details>

# 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 Mode | Entry Point | Use Case | Protocol |
|---------------|-------------|----------|----------|
| **Stdio** | `stdio.ts` | Local CLI clients, Claude Code, MCP Inspector | Standard I/O via process stdin/stdout |
| **HTTP Streamable** | `dev_server.ts` | Remote clients, hosted deployment at mcp.apify.com | Streamable HTTP with Server-Sent Events |

Source: [src/index.ts](https://github.com/apify/apify-mcp-server/blob/main/src/index.ts) · [README.md](https://github.com/apify/apify-mcp-server/blob/main/README.md)

## Architecture Diagram

```mermaid
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`:

```typescript
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](https://github.com/apify/apify-mcp-server/blob/main/src/stdio.ts)

### Connection Flow

```mermaid
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:

| Parameter | Source | Description |
|-----------|--------|-------------|
| `APIFY_TOKEN` | Environment | Apify API authentication token |
| `serverMode` | Constructor | `"default"`, `"apps"`, or `"auto"` |
| `skyfireMode` | Constructor | Enables Skyfire usage guide resource |

Source: [src/stdio.ts](https://github.com/apify/apify-mcp-server/blob/main/src/stdio.ts) · [src/mcp/server.ts](https://github.com/apify/apify-mcp-server/blob/main/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`:

```typescript
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](https://github.com/apify/apify-mcp-server/blob/main/src/dev_server.ts)

### HTTP Endpoints

| Endpoint | Method | Purpose |
|----------|--------|---------|
| `/mcp` | POST | JSON-RPC requests (tools, resources, tasks) |
| `/mcp` | GET | Server-Sent Events for notifications |
| `/health` | GET | Health check endpoint |

Source: [src/dev_server.ts](https://github.com/apify/apify-mcp-server/blob/main/src/dev_server.ts)

### Session Management

```mermaid
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](https://github.com/apify/apify-mcp-server/blob/main/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

```typescript
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](https://github.com/apify/apify-mcp-server/blob/main/src/server_card.ts)

### Capability Declaration

The server advertises its capabilities during the MCP `initialize` handshake:

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

Source: [src/mcp/server.ts:146](https://github.com/apify/apify-mcp-server/blob/main/src/mcp/server.ts#L146)

## Internal Exports

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

| Export | Type | Purpose |
|--------|------|---------|
| `ActorsMcpServer` | Class | Core MCP server implementation |
| `createResourceService` | Function | Resource service factory |
| `ToolEntry` | Type | Union type for all tool variants |
| `ServerMode` | Enum | Server operating mode |

Source: [src/index_internals.ts](https://github.com/apify/apify-mcp-server/blob/main/src/index_internals.ts)

## Server Modes

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

| Mode | Description | Transport Impact |
|------|-------------|------------------|
| `default` | Standard Apify tools | All tools available |
| `apps` | OpenAI UI widgets mode | Additional UI widget resources |
| `auto` | Capability-based detection | Mode resolved during initialize |

Source: [src/mcp/server.ts](https://github.com/apify/apify-mcp-server/blob/main/src/mcp/server.ts)

## Request Handler Wiring

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

```mermaid
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](https://github.com/apify/apify-mcp-server/blob/main/src/mcp/server.ts) · [src/dev_server.ts](https://github.com/apify/apify-mcp-server/blob/main/src/dev_server.ts)

## Integration with MCP SDK

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

| SDK Component | Usage |
|--------------|-------|
| `Server` | Low-level MCP protocol server |
| `StreamableHTTPServerTransport` | HTTP transport implementation |
| `createStdioServer` | Stdio transport factory |
| `RequestHandlerExtra` | Request context wrapper |

Source: [src/stdio.ts](https://github.com/apify/apify-mcp-server/blob/main/src/stdio.ts) · [src/dev_server.ts](https://github.com/apify/apify-mcp-server/blob/main/src/dev_server.ts)

## Testing Transport Layers

The project includes transport-specific integration tests:

| Test File | Transport | Coverage |
|-----------|-----------|----------|
| `tests/integration/suite.ts` | All transports | Main test suite |
| `stdio.ts` (in integration) | Stdio | Stdin/stdout messaging |
| `http.ts` (in integration) | HTTP Streamable | REST endpoints |
| `sse.ts` (in integration) | Server-Sent Events | Notification streaming |

Source: [DEVELOPMENT.md](https://github.com/apify/apify-mcp-server/blob/main/DEVELOPMENT.md) · [tests/integration/](https://github.com/apify/apify-mcp-server/blob/main/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.

---

<a id='tool-system'></a>

## Tool System

### Related Pages

Related topics: [Actor Tools](#actor-tools), [Storage Access Tools](#storage-tools)

<details>
<summary>Relevant source files</summary>

The following source files were used to generate this page:

- [src/mcp/server.ts](https://github.com/apify/apify-mcp-server/blob/main/src/mcp/server.ts) (primary server implementation)
- [src/types.ts](https://github.com/apify/apify-mcp-server/blob/main/src/types.ts) (tool type definitions)
- [src/tools/common/search_apify_docs.ts](https://github.com/apify/apify-mcp-server/blob/main/src/tools/common/search_apify_docs.ts) (tool implementation example)
- [src/mcp/proxy.ts](https://github.com/apify/apify-mcp-server/blob/main/src/mcp/proxy.ts) (Actor-MCP proxy tools)
- [res/mcp_server_refactor_analysis.md](https://github.com/apify/apify-mcp-server/blob/main/res/mcp_server_refactor_analysis.md) (architecture analysis)
- [res/mcp_resources_analysis.md](https://github.com/apify/apify-mcp-server/blob/main/res/mcp_resources_analysis.md) (resources and tools overview)
</details>

# 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]()

```mermaid
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 Type | Description | Execution Mode |
|-----------|-------------|-----------------|
| `HelperTool` | Internal server tools with direct callback execution | Synchronous |
| `ActorTool` | Apify Actor-based tools for scalable execution | Asynchronous via Actor API |
| `ActorMcpTool` | External MCP server tools proxied through Apify | Delegated to origin server |

### HelperTool

Internal tools that execute directly within the server process:

```typescript
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:

```typescript
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:

```typescript
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:

```mermaid
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:

```typescript
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]()

```mermaid
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:

```typescript
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:

| Tool | Category | Description |
|------|----------|-------------|
| `actors` | Category | Actor discovery and invocation tools |
| `docs` | Category | Apify and Crawlee documentation search |
| `apify/rag-web-browser` | Specific | RAG-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:

```typescript
// 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:

```bash
# 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 Level | Coverage |
|------------|----------|
| Unit tests | Individual tool execution, schema validation, registration patterns |
| Integration tests | Full tool lifecycle, dynamic loading/removal, notifications |
| Manual testing | MCP 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:

| Change | Impact |
|--------|--------|
| Replace `Server` with `McpServer` | Automatic tool management |
| Remove central dispatcher | ~300 lines removed |
| Convert JSON Schema to Zod | Native schema conversion via Zod v4 |
| Callback-per-tool pattern | Self-contained execution logic |

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

---

<a id='actor-tools'></a>

## Actor Tools

### Related Pages

Related topics: [Tool System](#tool-system), [Storage Access Tools](#storage-tools)

<details>
<summary>Relevant source files</summary>

The following source files were used to generate this page:

- [src/tools/actor_executor.ts](https://github.com/apify/apify-mcp-server/blob/main/src/tools/actor_executor.ts)
- [src/tools/core/actor_tools_factory.ts](https://github.com/apify/apify-mcp-server/blob/main/src/tools/core/actor_tools_factory.ts)
- [src/tools/core/call_actor_common.ts](https://github.com/apify/apify-mcp-server/blob/main/src/tools/core/call_actor_common.ts)
- [src/tools/apps/call_actor.ts](https://github.com/apify/apify-mcp-server/blob/main/src/tools/apps/call_actor.ts)
- [src/tools/default/call_actor.ts](https://github.com/apify/apify-mcp-server/blob/main/src/tools/default/call_actor.ts)
- [src/utils/actor.ts](https://github.com/apify/apify-mcp-server/blob/main/src/utils/actor.ts)
</details>

# 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 Type | Description | Type Discriminator |
|-----------|-------------|-------------------|
| **Internal Tools** | Built-in helper tools (e.g., `search-actors`, `fetch-actor-details`) | `'internal'` |
| **Actor Tools** | Wrappers around Apify Actors | `'actor'` |
| **Actor-MCP Tools** | Proxies to external MCP servers hosted as Actors | `'actor-mcp'` |

Source: [src/types.ts](https://github.com/apify/apify-mcp-server/blob/main/src/types.ts)

## Architecture

### Tool Classification Hierarchy

```mermaid
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

```mermaid
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](https://github.com/apify/apify-mcp-server/blob/main/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:**

| Responsibility | Description |
|---------------|-------------|
| `callActor()` | Initiates an Actor run with provided input |
| `getActorOutput()` | Retrieves output from completed runs |
| `abortActorRun()` | Terminates a running Actor |
| Result formatting | Converts raw results to MCP-compatible responses |

Source: [src/tools/actor_executor.ts](https://github.com/apify/apify-mcp-server/blob/main/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:**

| Output | Purpose |
|--------|---------|
| `name` | Tool identifier (e.g., `apify/web-scraper`) |
| `description` | Human-readable tool description |
| `inputSchema` | JSON Schema for tool arguments |
| `ajvValidate` | Compiled AJV validator function |
| `annotations` | MCP tool hints (readOnlyHint, openWorldHint, etc.) |

Source: [src/tools/core/actor_tools_factory.ts](https://github.com/apify/apify-mcp-server/blob/main/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:

```mermaid
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](https://github.com/apify/apify-mcp-server/blob/main/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:**

| Property | Value |
|----------|-------|
| Mode | Default server mode |
| Output | Limited preview (first 5 items) |
| Widget support | None |
| Use case | General-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:**

| Property | Value |
|----------|-------|
| Mode | Apps server mode (`ui=true`) |
| Output | Full results with widget rendering |
| Widget support | Actor Run widgets, progress tracking |
| Use case | MCP Apps-enabled clients |

**Widget annotations applied:**

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

Source: [src/tools/apps/call_actor_widget.ts](https://github.com/apify/apify-mcp-server/blob/main/src/tools/apps/call_actor_widget.ts)

### Execution Modes Comparison

| Feature | Default | Widget (Apps) |
|---------|---------|---------------|
| Server mode | `default` | `apps` |
| Output preview | Limited | Full |
| Progress notifications | Via logs | Via widget |
| Run status tracking | Manual | Automatic |
| UI rendering | Text only | Interactive widgets |

## Actor Resolution

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

```mermaid
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](https://github.com/apify/apify-mcp-server/blob/main/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:

| Annotation | Description | Applied Value |
|------------|-------------|---------------|
| `title` | Short display name | Actor name (e.g., "Call Actor") |
| `readOnlyHint` | Indicates read-only operation | `false` for call-actor |
| `openWorldHint` | Indicates external network access | `true` (executes Actors) |
| `destructiveHint` | Indicates destructive operation | `true` for call-actor |
| `idempotentHint` | Indicates idempotent operation | `false` for call-actor |

Source: [src/tools/apps/call_actor_widget.ts](https://github.com/apify/apify-mcp-server/blob/main/src/tools/apps/call_actor_widget.ts)

## Input Schema Handling

Actor tools dynamically generate input schemas from Actor definitions:

```mermaid
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 Type | Included | Reason |
|------------|----------|--------|
| Required fields | Yes | Necessary for execution |
| Optional fields with defaults | No | Server applies defaults |
| Hidden fields | No | Internal use only |

Source: [src/utils/actor.ts](https://github.com/apify/apify-mcp-server/blob/main/src/utils/actor.ts)

## Error Handling

Actor tools implement robust error handling for various failure scenarios:

| Error Type | Handling | Response |
|------------|----------|----------|
| Invalid input schema | AJV validation failure | Formatted error message |
| Actor not found | Resolution returns error | Early response with error |
| Payment required | Payment validation fails | Error with payment instructions |
| Run timeout | Wait exceeds timeout | Partial results with warning |
| Actor execution error | Run fails | Error details in response |

Source: [src/tools/core/call_actor_common.ts](https://github.com/apify/apify-mcp-server/blob/main/src/tools/core/call_actor_common.ts)

## Dynamic Tool Loading

The system supports dynamic loading of Actors as tools:

```mermaid
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:**

| Method | Description |
|--------|-------------|
| `loadActorsAsTools()` | Load by actor IDs |
| `loadToolsByName()` | Load by tool names |
| `loadToolsFromUrl()` | Load from MCP server URL |

Source: [src/mcp/server.ts](https://github.com/apify/apify-mcp-server/blob/main/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

- [Internal Tools](./internal-tools.md) - Built-in helper tools
- [Actor-MCP Proxy](./actor-mcp-proxy.md) - External MCP server integration
- [Tool Annotations](./tool-annotations.md) - MCP tool metadata
- [Server Modes](./server-modes.md) - Default vs Apps modes

---

<a id='storage-tools'></a>

## Storage Access Tools

### Related Pages

Related topics: [Actor Tools](#actor-tools)

<details>
<summary>Relevant source files</summary>

The following source files were used to generate this page:

- [src/tools/common/get_dataset.ts](https://github.com/apify/apify-mcp-server/blob/main/src/tools/common/get_dataset.ts)
- [src/tools/common/get_dataset_items.ts](https://github.com/apify/apify-mcp-server/blob/main/src/tools/common/get_dataset_items.ts)
- [src/tools/common/get_dataset_schema.ts](https://github.com/apify/apify-mcp-server/blob/main/src/tools/common/get_dataset_schema.ts)
- [src/tools/common/get_key_value_store.ts](https://github.com/apify/apify-mcp-server/blob/main/src/tools/common/get_key_value_store.ts)
- [src/tools/common/get_key_value_store_record.ts](https://github.com/apify/apify-mcp-server/blob/main/src/tools/common/get_key_value_store_record.ts)
- [src/tools/common/get_actor_run_log.ts](https://github.com/apify/apify-mcp-server/blob/main/src/tools/common/get_actor_run_log.ts)
- [src/tools/common/run_collection.ts](https://github.com/apify/apify-mcp-server/blob/main/src/tools/common/run_collection.ts)
</details>

# 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:

```mermaid
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

```mermaid
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'`:

```typescript
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]()

---

## Dataset Tools

Dataset tools provide access to Apify's structured data storage. Datasets store results from Actor runs as JSON objects, supporting pagination, field selection, and schema inference.

### Get Dataset

Retrieves metadata about a specific dataset including item count, field statistics, and storage usage.

**Tool Name:** `get-dataset`

**Input Schema:**
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `datasetId` | string | Yes | Dataset ID or name |

**Response Format:**
```json
{
  "content": [{
    "type": "text",
    "text": "```json\n{...dataset metadata...}\n```"
  }]
}
```

**Implementation Details:**

The tool first validates the `datasetId` parameter, then calls the Apify dataset API to fetch metadata. If the dataset is empty, it returns a friendly message rather than an error.

```typescript
if (datasetItems.length === 0) {
    return { content: [{ type: 'text', text: `Dataset '${parsed.datasetId}' is empty.` }] };
}
```

Source: [src/tools/common/get_dataset.ts:1-1]()

### Get Dataset Items

Retrieves actual data items from a dataset with support for pagination and field selection.

**Tool Name:** `get-dataset-items`

**Input Schema:**
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `datasetId` | string | Yes | Dataset ID or name |
| `offset` | integer | No | Number of items to skip (default: 0) |
| `limit` | integer | No | Maximum items to return (default: 20, max: 10000) |
| `fields` | string[] | No | Specific fields to return (supports dot notation) |
| `clean` | boolean | No | Return clean data without metadata (default: true) |

**Key Features:**

- **Dot notation support**: Fields like `crawl.statusCode` extract nested values
- **Auto-flattening**: Dot-notation fields are automatically flattened in output
- **Metadata stripping**: Clean mode removes `_id`, `_createdAt`, `_index` fields

**Output Schema:**

The tool returns dataset items with the following structure:

```typescript
const datasetItemsOutputSchema = {
    type: 'array' as const,
    items: { type: 'object' as const }
};
```

Source: [src/tools/common/get_dataset_items.ts:1-50]()

### Get Dataset Schema

Infers a JSON Schema from dataset items, useful for understanding data structure and enabling type-safe integrations.

**Tool Name:** `get-dataset-schema`

**Input Schema:**
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `datasetId` | string | Yes | Dataset ID or name |
| `limit` | integer | No | Max items to analyze (default: 100) |
| `clean` | boolean | No | Exclude metadata fields (default: true) |

**Implementation Details:**

The schema generation uses a shared utility that samples dataset items to infer field types:

```typescript
const schema = generateSchemaFromItems(datasetItems, {
    limit: parsed.limit,
    clean: parsed.clean,
});

if (!schema) {
    return buildMCPResponse({
        texts: [`Failed to generate schema for dataset '${parsed.datasetId}'.`],
        isError: true,
        telemetry: { toolStatus: TOOL_STATUS.FAILED },
    });
}
```

**Output:** Returns a JSON Schema document describing all discovered fields and their types.

Source: [src/tools/common/get_dataset_schema.ts:1-50]()

---

## Key-Value Store Tools

Key-Value Store tools provide access to Apify's NoSQL storage for arbitrary data items, commonly used for Actor input/output, screenshots, and state persistence.

### Get Key-Value Store

Retrieves metadata and record listings from a key-value store.

**Tool Name:** `get-key-value-store`

**Input Schema:**
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `storeId` | string | Yes | Key-value store ID or name |

**Metadata Returned:**
- Store name and ID
- Created timestamp
- Modified timestamp
- Item count
- Available record keys

**Use Cases:**

- Listing available records before fetching specific items
- Checking if a store exists
- Auditing store contents

Source: [src/tools/common/get_key_value_store.ts:1-1]()

### Get Key-Value Store Record

Retrieves a specific record from a key-value store by its key.

**Tool Name:** `get-key-value-store-record`

**Input Schema:**
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `storeId` | string | Yes | Key-value store ID or name |
| `key` | string | Yes | Record key to retrieve |
| `filename` | string | No | If record is a file, specify the filename for proper MIME type handling |

**Response Handling:**

The tool handles different MIME types appropriately:
- **JSON**: Parsed and pretty-printed
- **Images**: Base64 encoded with data URI
- **Other**: Raw content or appropriate representation

Source: [src/tools/common/get_key_value_store_record.ts:1-1]()

---

## Run Log Tools

Run Log tools provide access to Actor execution logs and run collection management.

### Get Actor Run Log

Retrieves the console output and log entries from a specific Actor run.

**Tool Name:** `get-actor-run-log`

**Input Schema:**
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `runId` | string | Yes | Actor run ID |

**Output Format:**

Returns log content with timestamps and log levels preserved:

```json
{
  "content": [{
    "type": "text",
    "text": "[2024-01-15T10:30:00.000Z] INFO: Starting crawl...\n[2024-01-15T10:30:01.000Z] DEBUG: Found 50 items"
  }]
}
```

**Implementation Details:**

The tool fetches log data from the Apify Run Logs API and formats it for readability. Large logs are truncated with a warning message.

Source: [src/tools/common/get_actor_run_log.ts:1-1]()

### Run Collection

Manages collections of Actor runs, enabling listing and filtering of historical executions.

**Tool Name:** `run-collection`

**Input Schema:**
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `action` | string | Yes | Action to perform: `list`, `get`, or `stats` |
| `datasetId` | string | No | Filter by associated dataset |
| `status` | string | No | Filter by run status |
| `limit` | integer | No | Maximum results (default: 20) |

**Supported Actions:**

| Action | Description |
|--------|-------------|
| `list` | List runs matching filters |
| `get` | Get details of a specific run |
| `stats` | Get aggregate statistics |

**Status Filter Values:**
- `READY` - Run completed successfully
- `RUNNING` - Run currently executing
- `FAILED` - Run terminated with errors
- `ABORTED` - Run manually cancelled

Source: [src/tools/common/run_collection.ts:1-1]()

---

## Common Patterns

### Input Validation

All storage tools use Zod for input validation, ensuring type safety and user-friendly error messages:

```typescript
const getDatasetArgs = z.object({
    datasetId: z.string().min(1, 'Dataset ID is required'),
});

const parsed = getDatasetArgs.parse(args);
```

Source: [src/tools/common/get_dataset.ts:1-1]()

### Response Building

Tools use `buildMCPResponse()` for consistent output formatting:

```typescript
return buildMCPResponse({
    texts: [`Dataset '${parsed.datasetId}' has ${itemCount} items.`],
    telemetry: { toolStatus: TOOL_STATUS.SUCCESS },
});
```

### Error Handling

Errors are caught and transformed into user-friendly messages:

```typescript
try {
    // API call
} catch (error) {
    log.softFail(`[get-dataset] Failed: ${error.message}`);
    return buildMCPResponse({
        texts: [`Error: ${error.message}`],
        isError: true,
        telemetry: { toolStatus: TOOL_STATUS.FAILED },
    });
}
```

---

## Tool Annotations

Storage tools include standardized annotations for MCP client UI rendering:

```typescript
annotations: {
    title: 'Get Dataset Items',
    readOnlyHint: true,      // Read-only operation
    destructiveHint: false,  // Does not delete data
    idempotentHint: true,    // Safe to retry
    openWorldHint: false,    // Apify internal data
},
```

| Annotation | Purpose |
|------------|---------|
| `title` | Display name in MCP client UI |
| `readOnlyHint` | Indicates read-only operations |
| `destructiveHint` | Warns about destructive operations |
| `idempotentHint` | Confirms safe retry behavior |
| `openWorldHint` | Indicates external data access |

Source: [src/tools/common/get_dataset_items.ts:55-60]()

---

## Integration with Apify Client

Storage tools use the shared Apify client utility rather than calling the API directly:

```typescript
import { getApifyDatasetClient } from '../../utils/apify_client.js';

const datasetClient = getApifyDatasetClient();
const dataset = await datasetClient.getDataset({ datasetId: parsed.datasetId });
```

This ensures:
- Consistent authentication handling
- Proper error transformation
- Caching where applicable
- Telemetry integration

Source: [src/tools/common/get_dataset.ts:1-1]()

---

## Configuration

Storage tools respect the server's tool loading configuration. By default, storage tools are loaded unless explicitly excluded:

```bash
# CLI configuration
npx @apify/actors-mcp-server --tools actors,docs,storage

# Or explicitly exclude
npx @apify/actors-mcp-server --tools actors,docs
```

Source: [README.md:1-1]()

---

## Summary

Storage Access Tools provide comprehensive access to Apify's cloud storage infrastructure through the MCP protocol. Key characteristics:

| Aspect | Implementation |
|--------|----------------|
| **Dataset Access** | 3 tools for metadata, items, and schema |
| **Key-Value Store** | 2 tools for store and record access |
| **Run Logs** | 2 tools for log retrieval and run management |
| **Validation** | Zod schemas with AJV compilation |
| **Response Format** | Standard MCP content blocks |
| **Error Handling** | User-friendly messages with telemetry |
| **Configuration** | Respects global tool loading settings |

These tools enable AI assistants to interact with Apify storage data without requiring direct API integration, making it simple to build workflows that consume Actor output or manage storage resources.

---

<a id='payments-overview'></a>

## Agentic Payments System

<details>
<summary>Relevant source files</summary>

The following source files were used to generate this page:

- [src/payments/types.ts](https://github.com/apify/apify-mcp-server/blob/main/src/payments/types.ts)
- [src/payments/x402.ts](https://github.com/apify/apify-mcp-server/blob/main/src/payments/x402.ts)
- [src/utils/payment_errors.ts](https://github.com/apify/apify-mcp-server/blob/main/src/utils/payment_errors.ts)
- [src/payments/helpers.ts](https://github.com/apify/apify-mcp-server/blob/main/src/payments/helpers.ts)
</details>

# 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 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.

```mermaid
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](https://github.com/apify/apify-mcp-server/blob/main/src/payments/types.ts)

## Core Types and Interfaces

### PaymentProviderId

The system defines two supported payment provider identifiers:

```typescript
export type PaymentProviderId = 'skyfire' | 'x402';
```

| Provider | Description |
|----------|-------------|
| `skyfire` | Skyfire agentic payments using PAY tokens in tool arguments |
| `x402` | x402 protocol using HTTP 402 with PAYMENT-SIGNATURE header |

Source: [src/payments/types.ts:14-19](https://github.com/apify/apify-mcp-server/blob/main/src/payments/types.ts)

### PaymentProvider Interface

Every payment provider must implement the `PaymentProvider` interface:

| Method | Return Type | Purpose |
|--------|-------------|---------|
| `id` | `PaymentProviderId` (readonly) | Provider identifier |
| `decorateToolSchema(tool)` | `ToolEntry` | Add payment fields to tool definitions |
| `validatePayment(args, meta, headers)` | `string \| null` | Validate credentials before execution |
| `getPaymentHeaders(args, meta, headers)` | `PaymentHeaders` | Extract headers for Apify API |
| `removePaymentFields(args)` | `Record<string, unknown>` | Clean args before Actor input |
| `allowsUnauthenticated` | `boolean` | Whether token-less access is permitted |
| `getPaymentRequiredData?()` | `unknown` | Optional x402 structured payment data |
| `getUsageGuide?()` | `string \| null` | Optional payment usage documentation |

Source: [src/payments/types.ts:45-87](https://github.com/apify/apify-mcp-server/blob/main/src/payments/types.ts)

### Supporting Types

```typescript
// 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](https://github.com/apify/apify-mcp-server/blob/main/src/payments/types.ts)

## Payment-Aware Tool Call Context

The `PrepareToolCallContextResult` type centralizes payment processing for tool calls:

```typescript
export type PrepareToolCallContextResult = {
    paymentRequiredResult?: ReturnType<typeof buildPaymentRequiredResponse>;
    toolArgsWithoutPayment: Record<string, unknown>;
    toolArgsRedacted: unknown;
    apifyClient: ApifyClient;
};
```

| Field | Type | Purpose |
|-------|------|---------|
| `paymentRequiredResult` | `MCPResponse \| undefined` | Structured 402 error response if payment fails |
| `toolArgsWithoutPayment` | `Record<string, unknown>` | Args stripped of payment fields for AJV validation |
| `toolArgsRedacted` | `unknown` | Args with sensitive fields masked for logging |
| `apifyClient` | `ApifyClient` | Client configured with payment headers or standard token |

Source: [src/payments/helpers.ts:7-16](https://github.com/apify/apify-mcp-server/blob/main/src/payments/helpers.ts)

## x402 Payment Provider

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

### Payment Flow

```mermaid
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

```typescript
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](https://github.com/apify/apify-mcp-server/blob/main/src/payments/x402.ts)

### 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

```typescript
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](https://github.com/apify/apify-mcp-server/blob/main/src/payments/x402.ts)

### Caching Mechanism

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

| Parameter | Value |
|-----------|-------|
| Cache TTL | 30 minutes |
| Cached Item | `Promise<X402PaymentRequirements \| undefined>` |

```typescript
let cachedRequirementsPromise: Promise<X402PaymentRequirements | undefined> | null = null;
let lastFetchTime = 0;
const CACHE_TTL_MS = 30 * 60 * 1000;
```

Source: [src/payments/x402.ts:35-41](https://github.com/apify/apify-mcp-server/blob/main/src/payments/x402.ts)

### x402 Provider Constants

| Constant | Value | Purpose |
|----------|-------|---------|
| `X402_META_KEY` | `x402/payment` | Key for MCP `_meta` field |
| `PAYMENT_SIGNATURE_HEADER` | `PAYMENT-SIGNATURE` | HTTP header for Apify API |
| `PAYMENT_PROTOCOL_HEADER` | `x-apify-payment-protocol` | Protocol identification |
| `PAYMENT_REQUIRED_HEADER` | `payment-required` | Response header for 402 |
| `FETCH_TIMEOUT_MS` | `8000` | Timeout for payment requirements fetch |

Source: [src/payments/x402.ts:52-63](https://github.com/apify/apify-mcp-server/blob/main/src/payments/x402.ts)

## Payment Error Handling

### 402 Response Building

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

```typescript
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](https://github.com/apify/apify-mcp-server/blob/main/src/utils/payment_errors.ts)

### Payment Data Extraction

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

| Priority | Source | Access Method |
|----------|--------|---------------|
| 1 | Captured HTTP header | Axios interceptor stores `payment-required` response header |
| 2 | API response body | `ApifyApiError.data` field |

```typescript
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](https://github.com/apify/apify-mcp-server/blob/main/src/utils/payment_errors.ts)

### Axios Interceptor

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

```typescript
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](https://github.com/apify/apify-mcp-server/blob/main/src/utils/payment_errors.ts)

## Tool Call Processing Workflow

```mermaid
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:

```typescript
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](https://github.com/apify/apify-mcp-server/blob/main/src/resources/resource_service.ts)

## Configuration Reference

| Configuration Option | Provider | Description |
|---------------------|----------|-------------|
| `APIFY_TOKEN` | Standard | Apify API token for traditional authentication |
| `payment=x402` | x402 | Query parameter to enable x402 payments |
| `--x402` | x402 | CLI flag to enable x402 protocol |

Source: [README.md](https://github.com/apify/apify-mcp-server/blob/main/README.md)

## Security Considerations

### Field Redaction

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

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

### Field Removal

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

```typescript
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

---

<a id='widget-system'></a>

## Widget System

### Related Pages

Related topics: [UI Components Library](#ui-components)

<details>
<summary>Relevant source files</summary>

The following source files were used to generate this page:

- [src/web/src/widgets/actor-detail-widget.tsx](https://github.com/apify/apify-mcp-server/blob/main/src/web/src/widgets/actor-detail-widget.tsx)
- [src/web/src/widgets/actor-run-widget.tsx](https://github.com/apify/apify-mcp-server/blob/main/src/web/src/widgets/actor-run-widget.tsx)
- [src/web/src/widgets/search-actors-widget.tsx](https://github.com/apify/apify-mcp-server/blob/main/src/web/src/widgets/search-actors-widget.tsx)
- [src/web/src/utils/init-widget.tsx](https://github.com/apify/apify-mcp-server/blob/main/src/web/src/utils/init-widget.tsx)
- [src/web/src/context/mcp-app-context.tsx](https://github.com/apify/apify-mcp-server/blob/main/src/web/src/context/mcp-app-context.tsx)
- [src/resources/resource_service.ts](https://github.com/apify/apify-mcp-server/blob/main/src/resources/resource_service.ts)
- [src/web/src/pages/ActorSearch/ActorSearch.skeleton.tsx](https://github.com/apify/apify-mcp-server/blob/main/src/web/src/pages/ActorSearch/ActorSearch.skeleton.tsx)
- [res/web-widget-bundle-size.md](https://github.com/apify/apify-mcp-server/blob/main/res/web-widget-bundle-size.md)
- [DEVELOPMENT.md](https://github.com/apify/apify-mcp-server/blob/main/DEVELOPMENT.md)
</details>

# 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

```mermaid
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

```mermaid
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:

| Widget | File | Purpose |
|--------|------|---------|
| Actor Search Widget | `search-actors-widget.tsx` | Search and browse Actors in Apify Store |
| Actor Detail Widget | `actor-detail-widget.tsx` | Display Actor information, pricing, input schema |
| Actor Run Widget | `actor-run-widget.tsx` | Show Actor execution progress and results |

## Core Components

### Widget Initialization (`init-widget.tsx`)

The `renderWidget` function is the entry point for all widgets:

```typescript
// 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:

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

The hook interface:

| Property | Type | Description |
|----------|------|-------------|
| `details` | `ActorDetails \| undefined` | Actor information from tool call |
| `input` | `Record<string, unknown>` | Input parameters |
| `meta` | `WidgetMeta` | Metadata about the widget session |

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

Provides global state and utilities for widgets:

```typescript
interface McpAppContextValue {
    // Context methods and state
}
```

### Widget Wrapper Pattern

Each widget follows a consistent wrapper pattern:

```typescript
// 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

```typescript
// 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

```typescript
// ❌ 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

| Widget | Before | After | Reduction |
|--------|--------|-------|-----------|
| actor-run-widget | ~1.86 MB | ~1.16 MB | 38% |
| actor-detail-widget | ~1.86 MB | ~1.52 MB | 18% |
| search-actors-widget | ~1.87 MB | ~1.53 MB | 18% |

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:

```bash
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:

```typescript
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 Category | Usage | Example |
|---------------|-------|---------|
| Colors | Use `theme.color.*` | `theme.color.neutral.text` |
| Spacing | Use `theme.space.*` | `theme.space.space16` |
| Shadows | Use `theme.shadow.*` | `theme.shadow.shadow2` |

### Component Structure

```typescript
// 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:

```typescript
// 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.

---

<a id='ui-components'></a>

## UI Components Library

### Related Pages

Related topics: [Widget System](#widget-system)

<details>
<summary>Relevant source files</summary>

The following source files were used to generate this page:

- [DESIGN_SYSTEM_AGENT_INSTRUCTIONS.md](https://github.com/apify/apify-mcp-server/blob/main/DESIGN_SYSTEM_AGENT_INSTRUCTIONS.md)
- [src/web/package.json](https://github.com/apify/apify-mcp-server/blob/main/src/web/package.json)
- [res/web-widget-bundle-size.md](https://github.com/apify/apify-mcp-server/blob/main/res/web-widget-bundle-size.md)
- [src/tools/structured_output_schemas.ts](https://github.com/apify/apify-mcp-server/blob/main/src/tools/structured_output_schemas.ts)
- [src/resources/resource_service.ts](https://github.com/apify/apify-mcp-server/blob/main/src/resources/resource_service.ts)
- [src/utils/server-instructions/index.ts](https://github.com/apify/apify-mcp-server/blob/main/src/utils/server-instructions/index.ts)
</details>

# 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](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](DESIGN_SYSTEM_AGENT_INSTRUCTIONS.md)

### Widget Rendering Pipeline

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

```mermaid
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](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](res/web-widget-bundle-size.md)

**Bundle size improvements achieved:**

| Widget | Before | After | Reduction |
|--------|--------|-------|-----------|
| actor-run-widget | ~1.86 MB | ~1.16 MB | 37.6% |
| actor-detail-widget | ~1.86 MB | ~1.52 MB | 18.3% |
| search-actors-widget | ~1.87 MB | ~1.53 MB | 18.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_SYSTEM_AGENT_INSTRUCTIONS.md)

### Design Tokens

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

```typescript
// ❌ 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:**

| Category | Examples | Purpose |
|----------|----------|---------|
| Colors | `theme.color.primary.action`, `theme.color.neutral.textMuted` | Brand colors and semantic variants |
| Spacing | `theme.space.space8`, `theme.space.space16`, `theme.space.space40` | Padding, margins, gaps |
| Border Radius | `theme.radius.radius2`, `theme.radius.radius3` | Component corners |
| Shadows | `theme.shadow1`, `theme.shadow3`, `theme.shadowActive` | Elevation and depth |

Source: [DESIGN_SYSTEM_AGENT_INSTRUCTIONS.md](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.

```typescript
// ✅ 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](DESIGN_SYSTEM_AGENT_INSTRUCTIONS.md)

**Component file organization:**

```typescript
// 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:

```typescript
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](DESIGN_SYSTEM_AGENT_INSTRUCTIONS.md)

### Typography Components

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

```typescript
// ✅ 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](DESIGN_SYSTEM_AGENT_INSTRUCTIONS.md)

## Spacing System

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

| Token | Usage | Example |
|-------|-------|---------|
| `space4` | Inline elements, icon gaps | `gap: ${theme.space.space4}` |
| `space8` | Button padding, small gaps | `padding: ${theme.space.space8}` |
| `space12` | Component internal spacing | `padding: ${theme.space.space12}` |
| `space16` | Standard component padding | `padding: ${theme.space.space16}` |
| `space24` | Section margins | `margin: ${theme.space.space24}` |
| `space32` | Section separators | `margin: ${theme.space.space32}` |
| `space40`, `space64`, `space80` | Large layouts | Container margins |

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

Source: [DESIGN_SYSTEM_AGENT_INSTRUCTIONS.md](DESIGN_SYSTEM_AGENT_INSTRUCTIONS.md)

## Common Pitfalls

### Token Misuse

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

```typescript
// ❌ 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:

```typescript
// ❌ 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](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

```typescript
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](src/tools/structured_output_schemas.ts)

### Actor Search Widget Schema

```typescript
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](src/tools/structured_output_schemas.ts)

## Widget Configuration

### Server Mode Detection

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

| Mode | Behavior | Widget Tools Available |
|------|----------|------------------------|
| `DEFAULT` | Standard MCP response | No widget tools exposed |
| `APPS` | Widget rendering enabled | `search-actors-widget`, `fetch-actor-details-widget`, `actor-run-widget` |

Source: [src/utils/server-instructions/index.ts](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](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:

| Check | Command/Method | Expected Result |
|-------|----------------|-----------------|
| Color audit | Regex `['"]#[0-9a-fA-F]{3,8}['"]` | Zero matches |
| Spacing audit | Regex `['"][0-9]+px['"]` | Zero matches |
| Import check | All styled-components import `theme` | 100% compliance |
| Pattern match | Compare to 1-3 similar components | Consistent structure |

Source: [DESIGN_SYSTEM_AGENT_INSTRUCTIONS.md](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:

```typescript
// ❌ 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/Feature | Bundle Impact | Notes |
|-------------------|---------------|-------|
| Floating UI | High | Heavy transitive dependency |
| Markdown rendering | High | Special cost center - measure impact on changes |
| Convenience components | Medium | Prefer narrow imports |
| Primitive components | Low | Direct module imports sufficient |

Source: [res/web-widget-bundle-size.md](res/web-widget-bundle-size.md)

## Dependencies

### Core UI Dependencies

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

### Build Dependencies

| Package | Version | Purpose |
|---------|---------|---------|
| `esbuild` | ^0.28.0 | Fast bundler for widgets |
| `typescript` | ^5.6.3 | Type safety |
| `tailwindcss` | ^3.4.17 | Utility CSS (used sparingly) |

Source: [src/web/package.json](src/web/package.json)

---

<a id='development-setup'></a>

## Development Setup

<details>
<summary>Relevant source files</summary>

The following source files were used to generate this page:

- [DEVELOPMENT.md](https://github.com/apify/apify-mcp-server/blob/main/DEVELOPMENT.md)
- [CONTRIBUTING.md](https://github.com/apify/apify-mcp-server/blob/main/CONTRIBUTING.md)
- [README.md](https://github.com/apify/apify-mcp-server/blob/main/README.md)
- [manifest.json](https://github.com/apify/apify-mcp-server/blob/main/manifest.json)
- [src/dev_server.ts](https://github.com/apify/apify-mcp-server/blob/main/src/dev_server.ts)
</details>

# Development Setup

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

## Prerequisites

### System Requirements

| Requirement | Minimum Version | Notes |
|-------------|-----------------|-------|
| Node.js | 20.0.0+ | Required runtime |
| pnpm | 11+ | Package manager |
| Claude Desktop | 0.2.16+ | For desktop integration |

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

Source: [manifest.json:15-24](https://github.com/apify/apify-mcp-server/blob/main/manifest.json)

### 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](https://github.com/apify/apify-mcp-server/blob/main/DEVELOPMENT.md)

## 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:

```bash
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:

```bash
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](https://github.com/apify/apify-mcp-server/blob/main/DEVELOPMENT.md)

## Environment Configuration

### APIFY_TOKEN Setup

The `APIFY_TOKEN` is required for most server operations.

#### For Claude Code

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

```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:

```text
APIFY_TOKEN="your-apify-token"
```

Source: [DEVELOPMENT.md:14-24](https://github.com/apify/apify-mcp-server/blob/main/DEVELOPMENT.md)

### Environment Variables Reference

| Variable | Required | Description |
|----------|----------|-------------|
| `APIFY_TOKEN` | Yes | Apify API authentication token |
| `APIFY_META_ORIGIN` | No | Meta origin for tracking (e.g., `STANDBY`) |
| `UI_MODE` | No | Enable UI mode for widget rendering (`true`/`false`) |

## Building the Project

### Production Build

To build the MCP server for production:

```bash
pnpm run build
```

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

Source: [DEVELOPMENT.md:64-68](https://github.com/apify/apify-mcp-server/blob/main/DEVELOPMENT.md)

### 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:

```bash
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](https://github.com/apify/apify-mcp-server/blob/main/README.md)

### Standard I/O (stdio) Mode

For use with the MCP Inspector or local clients:

```bash
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](https://github.com/apify/apify-mcp-server/blob/main/README.md)

## Testing

### Testing Layers

The project implements a multi-layer testing strategy:

| Layer | Command | Coverage |
|-------|---------|----------|
| Unit Tests | `pnpm run test:unit` | Individual modules in isolation |
| Integration Tests | `pnpm run test:integration` | Full server over all transports against real Apify API |
| Interactive Verification | `mcpc @stdio tools-call ...` | End-to-end during development |
| LLM Evaluations | CI only | Multiple models via OpenRouter |

Source: [DEVELOPMENT.md:26-36](https://github.com/apify/apify-mcp-server/blob/main/DEVELOPMENT.md)

### Unit Tests

Unit tests verify individual modules without external dependencies:

```bash
pnpm run test:unit
```

No credentials are required for unit tests.

### Integration Tests

Integration tests verify the complete MCP server functionality:

```bash
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:

```bash
mcpc @stdio tools-call ...
```

### LLM Evaluations

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

```bash
# 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](https://github.com/apify/apify-mcp-server/blob/main/DEVELOPMENT.md)

## Development Workflow

### Mermaid: Development Workflow

```mermaid
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:

| Type | Use Case |
|------|----------|
| `feat` | New features |
| `fix` | Bug fixes |
| `chore` | Maintenance tasks |
| `refactor` | Code refactoring |
| `docs` | Documentation updates |

**Examples:**
- `feat/add-dataset-tool`
- `fix/connection-timeout`
- `chore/update-dependencies`

Source: [CONTRIBUTING.md:8-13](https://github.com/apify/apify-mcp-server/blob/main/CONTRIBUTING.md)

### Commit Messages

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

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

| Component | Required | Description |
|-----------|----------|-------------|
| type | Yes | feat, fix, chore, refactor, docs, etc. |
| scope | Yes | The affected component/module |
| `!` | No | Indicates breaking change |
| description | Yes | Brief 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](https://github.com/apify/apify-mcp-server/blob/main/CONTRIBUTING.md)

## 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:**
```bash
export UI_MODE=true
```

**Via CLI Flag:**
```bash
npx @apify/actors-mcp-server --ui true
```

### Widget Preview

Preview widgets during development:

```bash
# 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](https://github.com/apify/apify-mcp-server/blob/main/DEVELOPMENT.md)

## Code Quality Standards

### Naming Conventions

| Element | Convention | Example |
|---------|------------|---------|
| Types/Interfaces | PascalCase | `ActorDetails`, `ToolConfig` |
| Variables/Functions | camelCase | `actorName`, `fetchActorDetails()` |
| Constants | SCREAMING_SNAKE_CASE | `MAX_RETRIES`, `WIDGET_REGISTRY` |
| Zod Validators | Suffix with `Validator` | `ActorValidator` |

### String Formatting

**Single-line strings:** Use single quotes
```typescript
const message = 'Operation completed';
```

**Multi-line strings:** Use `dedent` for LLM-facing content
```typescript
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](https://github.com/apify/apify-mcp-server/blob/main/CONTRIBUTING.md)

## Troubleshooting

### Common Issues

| Issue | Solution |
|-------|----------|
| `pnpm install` fails | Ensure Node.js 20+ is installed |
| Wrong pnpm version | Run `corepack enable` |
| Tests fail with "Token required" | Set `APIFY_TOKEN` environment variable |
| Widgets not rendering | Verify `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.

```bash
# 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:

```bash
# 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.

---

---

## Doramagic Pitfall Log

Project: apify/apify-mcp-server

Summary: Found 22 potential pitfall items; 5 are high/blocking. Highest priority: installation - 来源证据：fix: Allow calling MCP server actors in normal (one-shot) mode.

## 1. installation · 来源证据：fix: Allow calling MCP server actors in normal (one-shot) mode

- Severity: high
- Evidence strength: source_linked
- Finding: GitHub 社区证据显示该项目存在一个安装相关的待验证问题：fix: Allow calling MCP server actors in normal (one-shot) mode
- User impact: 可能增加新用户试用和生产接入成本。
- Suggested check: 来源问题仍为 open，Pack Agent 需要复核是否仍影响当前版本。
- Guardrail action: 不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。
- Evidence: community_evidence:github | cevd_be82315ed0f441ba9d942931d846d78c | https://github.com/apify/apify-mcp-server/issues/857 | 来源类型 github_issue 暴露的待验证使用条件。

## 2. configuration · 来源证据：Remove the flat-fields back-compat shim from `_meta.x402` once all consumers read `accepts[]`

- Severity: high
- Evidence strength: source_linked
- Finding: GitHub 社区证据显示该项目存在一个配置相关的待验证问题：Remove the flat-fields back-compat shim from `_meta.x402` once all consumers read `accepts[]`
- User impact: 可能影响升级、迁移或版本选择。
- Suggested check: 来源问题仍为 open，Pack Agent 需要复核是否仍影响当前版本。
- Guardrail action: 不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。
- Evidence: community_evidence:github | cevd_8ec6ff22f24a4bb18b439177f4a8c270 | https://github.com/apify/apify-mcp-server/issues/892 | 来源类型 github_issue 暴露的待验证使用条件。

## 3. security_permissions · 来源证据：Do not include the rag web browser when ?payment=x402

- Severity: high
- Evidence strength: source_linked
- Finding: GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：Do not include the rag web browser when ?payment=x402
- User impact: 可能影响授权、密钥配置或安全边界。
- Suggested check: 来源问题仍为 open，Pack Agent 需要复核是否仍影响当前版本。
- Guardrail action: 不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。
- Evidence: community_evidence:github | cevd_23bafe4901554148896241f0a1e183b0 | https://github.com/apify/apify-mcp-server/issues/875 | 来源类型 github_issue 暴露的待验证使用条件。

## 4. security_permissions · 来源证据：Perf: `search-actors` tools returns huuuge `inputFields` object

- Severity: high
- Evidence strength: source_linked
- Finding: GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：Perf: `search-actors` tools returns huuuge `inputFields` object
- User impact: 可能影响授权、密钥配置或安全边界。
- Suggested check: 来源问题仍为 open，Pack Agent 需要复核是否仍影响当前版本。
- Guardrail action: 不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。
- Evidence: community_evidence:github | cevd_af51cb3cbcb3479fbbdf27cedef734aa | https://github.com/apify/apify-mcp-server/issues/888 | 来源类型 github_issue 暴露的待验证使用条件。

## 5. security_permissions · 来源证据：feat(telemetry): track tool result size in bytes

- Severity: high
- Evidence strength: source_linked
- Finding: GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：feat(telemetry): track tool result size in bytes
- User impact: 可能影响授权、密钥配置或安全边界。
- Suggested check: 来源问题仍为 open，Pack Agent 需要复核是否仍影响当前版本。
- Guardrail action: 不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。
- Evidence: community_evidence:github | cevd_9c2ef77c88914458910ae67d9f903931 | https://github.com/apify/apify-mcp-server/issues/838 | 来源类型 github_issue 暴露的待验证使用条件。

## 6. identity · 仓库名和安装名不一致

- Severity: medium
- Evidence strength: runtime_trace
- Finding: 仓库名 `apify-mcp-server` 与安装入口 `@apify/actors-mcp-server` 不完全一致。
- User impact: 用户照着仓库名搜索包或照着包名找仓库时容易走错入口。
- Suggested check: 在 npm/PyPI/GitHub 上确认包名映射和官方 README 说明。
- Reproduction command: `npx @apify/actors-mcp-server`
- Guardrail action: 页面必须同时展示 repo 名和真实安装入口，避免用户搜索错包。
- Evidence: identity.distribution | github_repo:911256711 | https://github.com/apify/apify-mcp-server | repo=apify-mcp-server; install=@apify/actors-mcp-server

## 7. installation · 来源证据：chore(core): collapse array indices in dataset fields to prevent nextStep schema bloat

- Severity: medium
- Evidence strength: source_linked
- Finding: GitHub 社区证据显示该项目存在一个安装相关的待验证问题：chore(core): collapse array indices in dataset fields to prevent nextStep schema bloat
- User impact: 可能增加新用户试用和生产接入成本。
- Suggested check: 来源问题仍为 open，Pack Agent 需要复核是否仍影响当前版本。
- Guardrail action: 不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。
- Evidence: community_evidence:github | cevd_9c05c17621e3443dad6175f21db31a34 | https://github.com/apify/apify-mcp-server/issues/894 | 来源类型 github_issue 暴露的待验证使用条件。

## 8. installation · 来源证据：feat: Add structured output to remaining storage tools

- Severity: medium
- Evidence strength: source_linked
- Finding: GitHub 社区证据显示该项目存在一个安装相关的待验证问题：feat: Add structured output to remaining storage tools
- User impact: 可能增加新用户试用和生产接入成本。
- Suggested check: 来源问题仍为 open，Pack Agent 需要复核是否仍影响当前版本。
- Guardrail action: 不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。
- Evidence: community_evidence:github | cevd_c9b7c39f3e8f43e88ee52c2c8ae94b01 | https://github.com/apify/apify-mcp-server/issues/884 | 来源类型 github_issue 暴露的待验证使用条件。

## 9. installation · 来源证据：feat: migrate direct actor tools to canonical RunResponse shape

- Severity: medium
- Evidence strength: source_linked
- Finding: GitHub 社区证据显示该项目存在一个安装相关的待验证问题：feat: migrate direct actor tools to canonical RunResponse shape
- User impact: 可能阻塞安装或首次运行。
- Suggested check: 来源问题仍为 open，Pack Agent 需要复核是否仍影响当前版本。
- Guardrail action: 不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。
- Evidence: community_evidence:github | cevd_6b304ff2763849fe9b4678cc7bf9f5b2 | https://github.com/apify/apify-mcp-server/issues/852 | 来源类型 github_issue 暴露的待验证使用条件。

## 10. installation · 来源证据：test: Consolidate duplicated MCP server test fixtures

- Severity: medium
- Evidence strength: source_linked
- Finding: GitHub 社区证据显示该项目存在一个安装相关的待验证问题：test: Consolidate duplicated MCP server test fixtures
- User impact: 可能增加新用户试用和生产接入成本。
- Suggested check: 来源问题仍为 open，Pack Agent 需要复核是否仍影响当前版本。
- Guardrail action: 不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。
- Evidence: community_evidence:github | cevd_5a7a24d9e8ce42468a7775a54dfa8ca6 | https://github.com/apify/apify-mcp-server/issues/847 | 来源类型 github_issue 暴露的待验证使用条件。

## 11. configuration · 来源证据：feat: Dataset tools correctness and coverage

- Severity: medium
- Evidence strength: source_linked
- Finding: GitHub 社区证据显示该项目存在一个配置相关的待验证问题：feat: Dataset tools correctness and coverage
- User impact: 可能阻塞安装或首次运行。
- Suggested check: 来源问题仍为 open，Pack Agent 需要复核是否仍影响当前版本。
- Guardrail action: 不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。
- Evidence: community_evidence:github | cevd_3fa86b498f66434a8f247c1b63fb56c9 | https://github.com/apify/apify-mcp-server/issues/784 | 来源类型 github_issue 暴露的待验证使用条件。

## 12. capability · 能力判断依赖假设

- Severity: medium
- Evidence strength: source_linked
- Finding: README/documentation is current enough for a first validation pass.
- User impact: 假设不成立时，用户拿不到承诺的能力。
- Suggested check: 将假设转成下游验证清单。
- Guardrail action: 假设必须转成验证项；没有验证结果前不能写成事实。
- Evidence: capability.assumptions | github_repo:911256711 | https://github.com/apify/apify-mcp-server | README/documentation is current enough for a first validation pass.

## 13. runtime · 来源证据：chore: Add mixpanel analytics for storage tools + error rates

- Severity: medium
- Evidence strength: source_linked
- Finding: GitHub 社区证据显示该项目存在一个运行相关的待验证问题：chore: Add mixpanel analytics for storage tools + error rates
- User impact: 可能增加新用户试用和生产接入成本。
- Suggested check: 来源问题仍为 open，Pack Agent 需要复核是否仍影响当前版本。
- Guardrail action: 不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。
- Evidence: community_evidence:github | cevd_03dbd8daa0c840d690bddb1d52e189c1 | https://github.com/apify/apify-mcp-server/issues/887 | 来源类型 github_issue 暴露的待验证使用条件。

## 14. maintenance · 维护活跃度未知

- Severity: medium
- Evidence strength: source_linked
- Finding: 未记录 last_activity_observed。
- User impact: 新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。
- Suggested check: 补 GitHub 最近 commit、release、issue/PR 响应信号。
- Guardrail action: 维护活跃度未知时，推荐强度不能标为高信任。
- Evidence: evidence.maintainer_signals | github_repo:911256711 | https://github.com/apify/apify-mcp-server | last_activity_observed missing

## 15. security_permissions · 下游验证发现风险项

- Severity: medium
- Evidence strength: source_linked
- Finding: no_demo
- User impact: 下游已经要求复核，不能在页面中弱化。
- Suggested check: 进入安全/权限治理复核队列。
- Guardrail action: 下游风险存在时必须保持 review/recommendation 降级。
- Evidence: downstream_validation.risk_items | github_repo:911256711 | https://github.com/apify/apify-mcp-server | no_demo; severity=medium

## 16. security_permissions · 存在评分风险

- Severity: medium
- Evidence strength: source_linked
- Finding: no_demo
- User impact: 风险会影响是否适合普通用户安装。
- Suggested check: 把风险写入边界卡，并确认是否需要人工复核。
- Guardrail action: 评分风险必须进入边界卡，不能只作为内部分数。
- Evidence: risks.scoring_risks | github_repo:911256711 | https://github.com/apify/apify-mcp-server | no_demo; severity=medium

## 17. security_permissions · 来源证据：[Bug]: Inconsistent `search-actors` schema and results

- Severity: medium
- Evidence strength: source_linked
- Finding: GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：[Bug]: Inconsistent `search-actors` schema and results
- User impact: 可能影响授权、密钥配置或安全边界。
- Suggested check: 来源问题仍为 open，Pack Agent 需要复核是否仍影响当前版本。
- Guardrail action: 不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。
- Evidence: community_evidence:github | cevd_364bc036f84b42e8b7be6534cb76381e | https://github.com/apify/apify-mcp-server/issues/889 | 来源讨论提到 node 相关条件，需在安装/试用前复核。

## 18. security_permissions · 来源证据：design: Calibrate get-dataset-schema output detail

- Severity: medium
- Evidence strength: source_linked
- Finding: GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：design: Calibrate get-dataset-schema output detail
- User impact: 可能影响授权、密钥配置或安全边界。
- Suggested check: 来源问题仍为 open，Pack Agent 需要复核是否仍影响当前版本。
- Guardrail action: 不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。
- Evidence: community_evidence:github | cevd_8b7a4266d8eb4298919b5cb2a58fa420 | https://github.com/apify/apify-mcp-server/issues/882 | 来源类型 github_issue 暴露的待验证使用条件。

## 19. security_permissions · 来源证据：refactor: Extract storage tool helpers

- Severity: medium
- Evidence strength: source_linked
- Finding: GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：refactor: Extract storage tool helpers
- User impact: 可能影响授权、密钥配置或安全边界。
- Suggested check: 来源问题仍为 open，Pack Agent 需要复核是否仍影响当前版本。
- Guardrail action: 不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。
- Evidence: community_evidence:github | cevd_496f0061952341728e4222b961251325 | https://github.com/apify/apify-mcp-server/issues/890 | 来源类型 github_issue 暴露的待验证使用条件。

## 20. security_permissions · 来源证据：tools/list response contains `type: "unknown"` in an input schema — rejected by ajv-based MCP clients (LibreChat)

- Severity: medium
- Evidence strength: source_linked
- Finding: GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：tools/list response contains `type: "unknown"` in an input schema — rejected by ajv-based MCP clients (LibreChat)
- User impact: 可能影响授权、密钥配置或安全边界。
- Suggested check: 来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。
- Guardrail action: 不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。
- Evidence: community_evidence:github | cevd_77fae88d35e2486d8125a2ecea9abdc7 | https://github.com/apify/apify-mcp-server/issues/738 | 来源讨论提到 node 相关条件，需在安装/试用前复核。

## 21. maintenance · issue/PR 响应质量未知

- Severity: low
- Evidence strength: source_linked
- Finding: issue_or_pr_quality=unknown。
- User impact: 用户无法判断遇到问题后是否有人维护。
- Suggested check: 抽样最近 issue/PR，判断是否长期无人处理。
- Guardrail action: issue/PR 响应未知时，必须提示维护风险。
- Evidence: evidence.maintainer_signals | github_repo:911256711 | https://github.com/apify/apify-mcp-server | issue_or_pr_quality=unknown

## 22. maintenance · 发布节奏不明确

- Severity: low
- Evidence strength: source_linked
- Finding: release_recency=unknown。
- User impact: 安装命令和文档可能落后于代码，用户踩坑概率升高。
- Suggested check: 确认最近 release/tag 和 README 安装命令是否一致。
- Guardrail action: 发布节奏未知或过期时，安装说明必须标注可能漂移。
- Evidence: evidence.maintainer_signals | github_repo:911256711 | https://github.com/apify/apify-mcp-server | release_recency=unknown

<!-- canonical_name: apify/apify-mcp-server; human_manual_source: deepwiki_human_wiki -->
