Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Loop Laravel Package

kirschbaum-development/laravel-loop

Laravel Loop by Kirschbaum Development provides a simple, expressive way to iterate over large Eloquent/query results in chunks, avoiding memory issues. Its loop helper keeps batch processing and bulk updates concise and readable.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and publish config

composer require kirschbaum-development/laravel-loop --dev
php artisan vendor:publish --tag="loop-config"

The package ships a config file (typically config/loop.php) that controls which tools, resources, and prompts are exposed, plus transport settings. Read that file first — it is the map of everything the package can do, and it lists the built-in tools you get for free (artisan command runner, route listing, database schema inspection, log reading, etc.).

Wire it into an MCP client

Loop runs as a stdio MCP server. Add it to your assistant's config — e.g. Claude Desktop's claude_desktop_config.json, or Cursor's .cursor/mcp.json:

{
  "mcpServers": {
    "laravel-loop": {
      "command": "php",
      "args": ["/absolute/path/to/artisan", "loop:serve"],
      "env": { "APP_ENV": "local" }
    }
  }
}

Use an absolute path to artisan (or to the PHP binary) — MCP clients don't inherit your shell's working directory. Confirm the command name with php artisan list | grep -i loop if your version differs.

First use case

Restart the client, then ask something that would otherwise cost you three terminal commands:

"List the registered routes matching api/orders, then show me the columns and indexes on the orders table."

That single round-trip — routes + schema, no copy-paste, no context switching — is the whole value proposition. Get that working before writing a single custom tool.

Implementation Patterns

Custom tools are the real payoff

Built-in tools are generic (run artisan, read logs). The leverage comes from encoding your domain: get_order_status(order_id), find_feature_flags(environment), tail_deploy_log(service). A custom tool is a small class with a name, a description, a JSON-schema input, and a handle() method, registered in the tools array of config/loop.php. Keep the handler thin — call an existing service class or action, don't reimplement business logic inside it:

class OrderStatusTool extends Tool
{
    public function name(): string { return 'get_order_status'; }

    public function description(): string
    {
        return 'Returns fulfillment status and last tracking event for a single order.';
    }

    public function schema(): array
    {
        return ['order_id' => ['type' => 'integer', 'required' => true]];
    }

    public function handle(array $arguments): mixed
    {
        return OrderStatus::for($arguments['order_id'])->toAgentPayload();
    }
}

Invest in descriptions, not schemas

The model picks tools by reading one-line descriptions, not by parsing your JSON schema carefully. Vague descriptions ("Gets data") cause the assistant to guess wrong or chain five calls when one would do. Write descriptions the way you'd write @param docs for a new hire: what it returns, what it doesn't return, and when to prefer it over a sibling tool.

Resources for standing context, tools for actions

If the assistant needs to know your schema, route list, or domain conventions on every conversation, expose it as an MCP resource rather than a tool call. Resources are read like files — the client can pull them in up front instead of spending a tool call each time. A laravel://conventions resource containing "we use ULIDs, money is stored in cents, soft deletes are the default" pays for itself across every session.

Scope servers per environment

Run one Loop instance pointed at your local SQLite/MySQL, and consider a second, narrower one for staging with only read-only tools. Pointing the client at staging when you meant to debug locally is a common and expensive mistake — name the servers laravel-loop-local and laravel-loop-staging so the assistant's tool calls are visible in the transcript.

Pair it with a project instruction file

Loop gives the assistant hands; CLAUDE.md / AGENTS.md gives it judgment. Cross-reference them: "Use get_order_status rather than querying the orders table directly." The combination of tool access plus written conventions is dramatically better than either alone.

Use the package's own tools to build your tools

When writing a custom tool, ask the assistant to use Loop's route-listing and schema tools to inspect the relevant models and endpoints first. It arrives at a correct implementation faster, and it validates the built-ins are wired correctly.

Gotchas and Tips

Never expose this in production. A tinker/artisan-executing MCP server is remote code execution with a friendly interface. Keep it --dev, gate registration on app()->isLocal(), and check config/loop.php isn't enabling tools you don't want before any environment with real data. If you need something in staging, build narrow read-only tools — don't enable the generic artisan runner.

stdout is the protocol channel. Anything your application writes to stdout — dump(), echo, a chatty Log::info() with a stdout driver, a package's progress bar — corrupts the JSON-RPC stream and the client will silently drop the connection or report a parse error. Log to stderr or a file. If a tool "works in tinker but not over MCP," stray output is the first suspect.

Restart the client after every change. MCP clients hold the stdio process open and cache the tool list. Editing config/loop.php or a tool class does nothing until you restart the assistant. If a new tool doesn't appear, that's almost always the cause — not your registration.

config:cache will bite you. A cached config means your newly registered tool class doesn't show up. Run php artisan config:clear when iterating locally.

Watch output size. A SELECT * on a large table or a full route dump can blow the model's context budget and get truncated mid-JSON. Always cap results in custom tools (->limit(50)), summarize rather than dump, and return counts plus samples instead of raw collections.

Debug with a lower-level client first. When the assistant reports a tool error, bypass the client and connect directly — the MCP Inspector, or a plain echo of a JSON-RPC initialize + tools/list into php artisan loop:serve. It tells you instantly whether the problem is your tool or the client integration.

Extension points worth knowing: custom tool/resource/prompt classes for domain coverage; authorizing tools against Laravel gates or policies inside handle() so permissions live in one place; and wrapping tools in your own logging so you can see, after the fact, what the assistant actually called — invaluable for tuning descriptions and spotting misuse.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo