PHPackages                             ferdiunal/larapanda - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. ferdiunal/larapanda

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

ferdiunal/larapanda
===================

This is my package larapanda

v1.0.1(2w ago)23218↓20.8%MITPHPPHP ^8.4CI passing

Since Apr 10Pushed 2w agoCompare

[ Source](https://github.com/ferdiunal/larapanda)[ Packagist](https://packagist.org/packages/ferdiunal/larapanda)[ Docs](https://github.com/ferdiunal/larapanda)[ GitHub Sponsors](https://github.com/ferdiunal)[ Patreon](https://www.patreon.com/ferdiunal)[ RSS](/packages/ferdiunal-larapanda/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (2)Dependencies (13)Versions (3)Used By (0)

Larapanda
=========

[](#larapanda)

[![Latest Version on Packagist](https://camo.githubusercontent.com/fff1c5919c2249a4407d13de395feed1fc44e998c30a4b4fa77e0134830f3e97/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6665726469756e616c2f6c61726170616e64612e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/ferdiunal/larapanda)[![GitHub Tests Action Status](https://camo.githubusercontent.com/a39802ea184d15ca32df94db5577199b78ea64b11a513b9059ffefd43e235c77/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6665726469756e616c2f6c61726170616e64612f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/ferdiunal/larapanda/actions?query=workflow%3Arun-tests+branch%3Amain)[![GitHub Code Style Action Status](https://camo.githubusercontent.com/41e5a72badc76e88b48df3dc667b940fc89662e401b820718b559fa1a82ebc6d/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6665726469756e616c2f6c61726170616e64612f6669782d7068702d636f64652d7374796c652d6973737565732e796d6c3f6272616e63683d6d61696e266c6162656c3d636f64652532307374796c65267374796c653d666c61742d737175617265)](https://github.com/ferdiunal/larapanda/actions?query=workflow%3A%22Fix+PHP+code+style+issues%22+branch%3Amain)[![Total Downloads](https://camo.githubusercontent.com/fbf83336057ae75e60a2b0b3d3f3c66e2c4a13c46b6fc466e32fa7ffff61b51f/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6665726469756e616c2f6c61726170616e64612e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/ferdiunal/larapanda)

[![Larapanda](larapanda.png)](larapanda.png)

Language versions: [English](README.md) | [Türkçe](README.TR.md)

Larapanda is a type-safe Lightpanda SDK for Laravel and plain PHP applications. It provides named instance profiles, runtime resolution (`auto`, `cli`, `docker`), and immutable method-scoped option objects for `fetch`, `serve`, and `mcp`.

Installation
------------

[](#installation)

### Prerequisites

[](#prerequisites)

Larapanda uses a runtime resolver (`auto`, `cli`, `docker`). CLI execution (and `auto` mode when CLI is selected) requires a valid Lightpanda binary. Install Lightpanda from the official source: [lightpanda.io](https://lightpanda.io/).

```
curl -fsSL https://pkg.lightpanda.io/install.sh | bash
```

Install the Larapanda SDK package:

```
composer require ferdiunal/larapanda
```

For Laravel applications, publish the package configuration:

```
php artisan vendor:publish --tag="larapanda-config"
```

Optional integration dependencies:

```
composer require laravel/ai laravel/mcp
```

Configuration
-------------

[](#configuration)

Configuration is profile-based. Each client resolves an instance profile by name, and each profile may override the global defaults.

```
return [
    'default_instance' => 'default',

    'defaults' => [
        'runtime' => 'auto',
        'binary_path' => env('LARAPANDA_BINARY_PATH'),
        'docker' => [
            'command' => 'docker',
            'image' => 'lightpanda/browser:nightly',
            'container_name' => 'larapanda-lightpanda',
            'remove' => true,
            'extra_args' => [],
        ],
    ],

    'instances' => [
        'default' => [],
        'crawler' => [
            // For strict CLI mode:
            // 'runtime' => 'cli',
            // 'binary_path' => '/absolute/path/to/lightpanda',
        ],
        'mcp' => [
            // For strict Docker mode:
            // 'runtime' => 'docker',
        ],
    ],
];
```

- `default_instance` selects the instance profile used when no explicit profile name is provided.
- `defaults` defines baseline runtime settings shared by all instances unless overridden.
- `instances.` contains per-profile overrides for runtime mode, binary path, Docker parameters, and process options.
- In `auto` runtime mode, Larapanda prefers CLI execution when `binary_path` is available and executable; otherwise it falls back to Docker.
- `integrations.ai` configures AI SDK tool adapters (`instance`, `tool_prefix`, `exposed_tools`, session settings).
- `integrations.mcp` configures Laravel MCP server tool adapters (`instance`, `exposed_tools`, session settings).

Usage
-----

[](#usage)

### Scenario 1: Quickstart Fetch

[](#scenario-1-quickstart-fetch)

Resolve the manager, select an instance profile, and execute a markdown fetch.

```
use Ferdiunal\Larapanda\Contracts\LarapandaManagerInterface;
use Ferdiunal\Larapanda\Enums\FetchDumpFormat;

$manager = app(LarapandaManagerInterface::class);
$client = $manager->instance('default');

$fetch = $client->fetchRequest('https://example.com')
    ->withOptions(
        dump: FetchDumpFormat::Markdown,
        obeyRobots: true,
        waitMs: 2000,
    )
    ->run();

$markdown = $fetch->asMarkdown();
```

### Scenario 2: Output Modes

[](#scenario-2-output-modes)

Use strict typed accessors based on the selected dump format.

```
use Ferdiunal\Larapanda\Enums\FetchDumpFormat;

$markdownResult = $client->fetchRequest('https://example.com')
    ->withOptions(
        dump: FetchDumpFormat::Markdown,
    )
    ->run();

$semanticTreeResult = $client->fetchRequest('https://example.com')
    ->withOptions(
        dump: FetchDumpFormat::SemanticTree,
    )
    ->run();

$semanticTreeTextResult = $client->fetchRequest('https://example.com')
    ->withOptions(
        dump: FetchDumpFormat::SemanticTreeText,
    )
    ->run();

$markdown = $markdownResult->asMarkdown();
$semanticTree = $semanticTreeResult->asSemanticTree();        // array
$semanticTreeText = $semanticTreeTextResult->asSemanticTreeText();
$rawOutput = $semanticTreeTextResult->output();               // raw stdout fallback
```

`FetchResult` throws `UnexpectedFetchOutputFormatException` when a strict accessor does not match the selected dump format.

### Scenario 3: Named Instance Profiles

[](#scenario-3-named-instance-profiles)

Select the profile according to runtime intent:

- `default`: baseline fetch workloads.
- `crawler`: stricter crawl profile (for example, dedicated CLI runtime settings).
- `mcp`: MCP-oriented profile for long-running interactive sessions.

```
$defaultClient = $manager->instance('default');
$crawlerClient = $manager->instance('crawler');
$mcpClient = $manager->instance('mcp');
```

### Scenario 4: Proxy-Aware Fetch

[](#scenario-4-proxy-aware-fetch)

Use request-level proxy settings for one fetch operation:

```
use Ferdiunal\Larapanda\Enums\FetchDumpFormat;

$fetch = $client->fetchRequest('https://example.com')
    ->withOptions(
        dump: FetchDumpFormat::Markdown,
        httpProxy: 'http://127.0.0.1:3000',
        proxyBearerToken: 'MY-TOKEN',
    )
    ->run();
```

Use integration-level proxy settings for AI SDK and MCP server tool sessions:

```
// config/larapanda.php
'integrations' => [
    'ai' => [
        'http_proxy' => 'http://127.0.0.1:3000',
        'proxy_bearer_token' => 'MY-TOKEN',
    ],
    'mcp' => [
        'http_proxy' => 'http://127.0.0.1:3000',
        'proxy_bearer_token' => 'MY-TOKEN',
    ],
],
```

### Scenario 5: Long-Running Serve and MCP Modes

[](#scenario-5-long-running-serve-and-mcp-modes)

Use `RunningInstanceHandle` lifecycle methods for process-safe execution:

```
$serveHandle = $client->serveRequest()
    ->withOptions(host: '127.0.0.1', port: 9222)
    ->run();

try {
    if ($serveHandle->isRunning()) {
        // connect with CDP client
    }
} finally {
    $serveHandle->stop();
    $serveHandle->wait(2.0);
}

$mcpHandle = $client->mcpRequest()->run();

try {
    if ($mcpHandle->isRunning()) {
        // attach MCP host/client
    }
} finally {
    $mcpHandle->stop();
    $mcpHandle->wait(2.0);
}
```

Common Patterns
---------------

[](#common-patterns)

```
// Robots-compliant fetch
$result = $client->fetchRequest('https://example.com')
    ->withOptions(obeyRobots: true, dump: FetchDumpFormat::Markdown)
    ->run();

// Strict accessor mismatch raises UnexpectedFetchOutputFormatException
$result->asSemanticTreeText();
```

Laravel AI SDK Tools
--------------------

[](#laravel-ai-sdk-tools)

Install optional dependencies before using adapter features:

```
composer require laravel/ai laravel/mcp
```

Larapanda exposes AI SDK-compatible tools via `LarapandaAiTools`. The adapter is MCP-backed, session-aware, and config-driven.

### Scenario 1: Full Tool Catalog

[](#scenario-1-full-tool-catalog)

```
use Ferdiunal\Larapanda\Integrations\Ai\LarapandaAiTools;
use Illuminate\Support\Facades\AI;

$response = AI::provider('openai')
    ->model('gpt-5-mini')
    ->prompt('Open laravel.com and return the main headings.')
    ->tools(app(LarapandaAiTools::class)->make())
    ->text();
```

Tool naming uses the configured prefix (default `lightpanda_`), for example: `lightpanda_markdown`, `lightpanda_semantic_tree`, `lightpanda_click`.

### Scenario 2: Restrict Exposed AI Tools

[](#scenario-2-restrict-exposed-ai-tools)

Limit model access to a subset of tool surfaces:

```
// config/larapanda.php
'integrations' => [
    'ai' => [
        'exposed_tools' => ['goto', 'markdown', 'semantic_tree'],
    ],
],
```

### Scenario 3: Session-Aware AI Tool Continuity

[](#scenario-3-session-aware-ai-tool-continuity)

For multi-step browsing tasks, guide the model to reuse a stable `session_id` across tool calls.

```
$response = AI::provider('openai')
    ->model('gpt-5-mini')
    ->prompt('Use lightpanda tools with session_id=\"docs-session\". First goto laravel.com, then return markdown.')
    ->tools(app(LarapandaAiTools::class)->make())
    ->text();
```

Laravel MCP Server (Optional / Advanced)
----------------------------------------

[](#laravel-mcp-server-optional--advanced)

Use this layer when you want Laravel-managed MCP registration, container wiring, config-based tool filtering, and shared session/proxy policies.
If you only need a standalone MCP binary host, native `lightpanda mcp` can be used directly without Larapanda adapter classes.

### Native vs Adapter Decision Matrix

[](#native-vs-adapter-decision-matrix)

Use caseRecommended pathLowest-level MCP host integration over stdioNative `lightpanda mcp`Laravel container wiring + profile-based runtime resolutionLarapanda MCP adapterConfig-driven tool exposure (`integrations.mcp.exposed_tools`)Larapanda MCP adapterShared session pool and proxy policy reused by AI SDK toolsLarapanda MCP adapterDirect protocol troubleshooting against Lightpanda itselfNative `lightpanda mcp`### Scenario 1: Register MCP Tools in `routes/ai.php`

[](#scenario-1-register-mcp-tools-in-routesaiphp)

```
use Ferdiunal\Larapanda\Integrations\Mcp\LarapandaMcpServer;

LarapandaMcpServer::registerLocal(name: 'lightpanda');
```

### Scenario 2: Restrict MCP Tool Exposure

[](#scenario-2-restrict-mcp-tool-exposure)

By default, all Lightpanda MCP tools are exposed. To reduce tool surface:

```
// config/larapanda.php
'integrations' => [
    'mcp' => [
        'exposed_tools' => ['goto', 'markdown', 'semantic_tree'],
    ],
],
```

### Scenario 3: Session and Proxy Policy for MCP Adapter

[](#scenario-3-session-and-proxy-policy-for-mcp-adapter)

Session and proxy behavior are controlled from config:

- Each integration path (AI and MCP server) maintains an isolated in-memory session pool.
- Sessions map to long-running `lightpanda mcp` processes.
- Sessions expire using `session_ttl_seconds` and are capped by `max_sessions`.
- `session_id` can be passed in tool arguments to preserve page context across calls.

```
// config/larapanda.php
'integrations' => [
    'mcp' => [
        'session_ttl_seconds' => 300,
        'max_sessions' => 32,
        'obey_robots' => true,
        'http_proxy' => 'http://127.0.0.1:3000',
        'proxy_bearer_token' => 'MY-TOKEN',
    ],
],
```

### Scenario 4: Interactive MCP Argument Model (Native-Aligned)

[](#scenario-4-interactive-mcp-argument-model-native-aligned)

Interactive tools use backend-node-driven arguments. The typical flow is:

1. Navigate and discover target nodes (`goto` + `waitForSelector` or `interactiveElements`).
2. Extract `backendNodeId` from the response payload.
3. Execute interaction tools with that node id on the same `session_id`.

```
// Example argument shapes (canonical tool contracts):
// goto|navigate:      ['url' => 'https://example.com', 'timeout' => 10000, 'waitUntil' => 'done']
// waitForSelector:    ['selector' => '#submit', 'timeout' => 5000]
// click|hover:        ['backendNodeId' => 123]
// fill:               ['backendNodeId' => 123, 'text' => 'Ferdi']
// press:              ['key' => 'Enter', 'backendNodeId' => 123] // backendNodeId optional
// selectOption:       ['backendNodeId' => 123, 'value' => 'tr']
// setChecked:         ['backendNodeId' => 123, 'checked' => true]
// scroll:             ['y' => 400, 'backendNodeId' => 123] // backendNodeId optional
```

Testing
-------

[](#testing)

Run the full test suite:

```
composer test
```

Run opt-in live CLI + MCP smoke tests (native MCP and Larapanda bridge):

```
LIGHTPANDA_LIVE_TESTS=1 \
LIGHTPANDA_BINARY_PATH=/Users/ferdiunal/Web/larapanda/lightpanda \
php vendor/bin/pest --group=live
```

Run MCP-focused live smoke tests only:

```
LIGHTPANDA_LIVE_TESTS=1 \
LIGHTPANDA_BINARY_PATH=/Users/ferdiunal/Web/larapanda/lightpanda \
php vendor/bin/pest --filter=Mcp --group=live
```

Live suite policy:

- Live tests are opt-in and are not required in the default CI pipeline.
- In constrained environments, DNS/port limitations result in deterministic `skip`, not flaky `fail`.
- Real protocol and argument contract mismatches continue to fail.

Prerequisites for live tests:

- `LIGHTPANDA_BINARY_PATH` points to a valid executable Lightpanda binary.
- The environment permits internet access and local port binding.
- Optional proxy smoke test requires `LIGHTPANDA_HTTP_PROXY` (and optional `LIGHTPANDA_PROXY_BEARER_TOKEN`).

Optional proxy smoke run:

```
LIGHTPANDA_LIVE_TESTS=1 \
LIGHTPANDA_BINARY_PATH=/Users/ferdiunal/Web/larapanda/lightpanda \
LIGHTPANDA_HTTP_PROXY=http://127.0.0.1:3000 \
LIGHTPANDA_PROXY_BEARER_TOKEN=YOUR_TOKEN \
php vendor/bin/pest --group=live
```

Credits
-------

[](#credits)

- [Ferdi ÜNAL](https://github.com/ferdiunal)

License
-------

[](#license)

This package is licensed under the MIT License. See [LICENSE.md](LICENSE.md) for details.

###  Health Score

48

—

FairBetter than 94% of packages

Maintenance97

Actively maintained with recent releases

Popularity24

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity52

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 75% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~45 days

Total

2

Last Release

15d ago

PHP version history (2 changes)v1.0.0PHP ^8.5

v1.0.1PHP ^8.4

### Community

Maintainers

![](https://www.gravatar.com/avatar/51f5bc45a8653e16229499476a51988197350c7648ec3b961c62c45cc92d8872?d=identicon)[ferdiunal](/maintainers/ferdiunal)

---

Top Contributors

[![ferdiunal](https://avatars.githubusercontent.com/u/5059851?v=4)](https://github.com/ferdiunal "ferdiunal (6 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (1 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (1 commits)")

---

Tags

aicrawlerlaravellightpandamcplaravelferdiunallarapanda

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/ferdiunal-larapanda/health.svg)

```
[![Health](https://phpackages.com/badges/ferdiunal-larapanda/health.svg)](https://phpackages.com/packages/ferdiunal-larapanda)
```

###  Alternatives

[spatie/laravel-data

Create unified resources and data transfer objects

1.8k33.0M871](/packages/spatie-laravel-data)[spatie/laravel-pdf

Create PDFs in Laravel apps

1.0k4.3M41](/packages/spatie-laravel-pdf)[codewithdennis/filament-select-tree

The multi-level select field enables you to make single selections from a predefined list of options that are organized into multiple levels or depths.

327482.0k25](/packages/codewithdennis-filament-select-tree)[nativephp/desktop

NativePHP for Desktop

37833.6k8](/packages/nativephp-desktop)[worksome/exchange

Check Exchange Rates for any currency in Laravel.

124581.3k](/packages/worksome-exchange)[rawilk/profile-filament-plugin

Profile &amp; MFA starter kit for filament.

3913.7k](/packages/rawilk-profile-filament-plugin)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
