Using Composer Path Repositories to Handle Module Dependencies During Development

Sometimes working on a Drupal contributed module requires making changes to the module’s composer.json so that you can update a dependency.

Have you run into this before? You’re working on a Drupal contrib module, and that module has a dependency on either another module or an external Composer package. That dependency is expressed in the module’s composer.json file and likely has a version constraint. So what happens when you want to update the module to use a newer version of the dependency, but the new version is outside the existing version constraint?

This is super common when the contributed module relies on a third-party library, like the Recurly module using the Recurly API SDK, or the OAuth module using the PHP library common to many different projects.

Here’s a recent example. I was working on the drupal/mcp_server module, which currently has a dependency on the modelcontextprotocol/php-sdk (mcp/sdk). I started by installing the module with composer require drupal/mcp_server. This gets the module and any dependencies.

The require section of the drupal/mcp_server module’s composer.json file looks like this:

  "require": {
    "php": "^8.3",
    "drupal/tool": "1.0.0-alpha9",
    "drupal/simple_oauth": "^6",
    "e0ipso/simple_oauth_21": "^1",
    "mcp/sdk": "^0.1.0"
  },

I want to update the module to use the newer 0.3.x version of the mcp/sdk. I can’t just composer update mcp/sdk because the version constraint doesn’t allow the newest release, and composer require mcp/sdk^0.3.0 won’t work because it’ll result in a dependency conflict. I can’t just modify the local composer.json file in the module because, when resolving the dependency tree, Composer will ping Drupal.org (Packagist) and use the version constraint from the hosted package, not from the locally installed module.

So how do I get my project to install mcp/sdk^0.3.0 so that I can work on updating the module’s code to use the new library?

Composer path repositories

One way to accomplish this is using a path repository. Composer installs packages from a repository: a list of packages and versions. By default, only the Packagist.org repository is registered. You can change this by adding repository configuration to your project’s composer.json file and telling Composer to use additional repositories when resolving dependencies.

Drupal actually does this already. If you look at your root composer.json file, you’ll see something like this:

    "repositories": [
        {
            "type": "composer",
            "url": "https://packages.drupal.org/8"
        }
    ],

That configuration tells Composer that, in addition to Packagist.org, it should use packages.drupal.org/8 as a place to search for packages. And that’s why packages like drupal/mcp_server work.

There are a bunch of different types of repositories, including path, which allows you to depend on a local directory. Read more about it here: https://getcomposer.org/doc/05-repositories.md#path

This approach works really well if you’re working on a contributed module within the context of a complete Drupal project. For example, working on adding an MCP server to the Drupalize.Me site and wanting to make (and test) the updates for the mcp/sdk in the context of that site.

Set up a path repository to work on a Drupal module

In the project’s root composer.json (the one that currently requires drupal/mcp_server, or whatever module you want to work on), add the following configuration:

  "repositories": [
    {
      "type": "path",
      "url": "web/modules/contrib/mcp_server",
      "options": {
        "symlink": false
      }
    },
    {
      "type": "composer",
      "url": "https://packages.drupal.org/8"
    }
  ],

This tells Composer to use web/modules/contrib/mcp_server as a repository. So when it goes to resolve drupal/mcp_server, it’ll find web/modules/contrib/mcp_server/composer.json, which has "name": "drupal/mcp_server", and say “Got it!” No more pinging Drupal.org for that specific package. Dependencies are resolved by searching through the repositories top to bottom until a match is found.

After making those changes, we can remove the Composer-managed version, clone the Git repo, and then tell Composer to use the locally cloned package:

# Remove the composer-managed version.
composer remove drupal/mcp_server

# Git clone your module.
cd web/modules/contrib
git clone https://github.com/yourusername/mcp_server.git mcp_server
cd ../../..

# Tell Composer to use the local path.
composer require drupal/mcp_server:@dev

Update the MCP SDK

Finally, we can update the mcp/sdk dependency.

Edit web/modules/contrib/mcp_server/composer.json:

{
  "require": {
    "mcp/sdk": "^0.3.0"
  }
}

Then run:

composer update mcp/sdk --with-all-dependencies

This should result in the 0.3.0 version of the mcp/sdk being downloaded into the vendor/ directory. And you can now begin the work of updating the contributed module’s code to use the latest version of the third-party dependency.

Similar Posts

  • Entity API Course Updated to Cover the Use of PHP Attributes

    As of Drupal 11.1.0, core has support for defining custom entity types (both content and configuration) using PHP attributes instead of annotations. And now, all our Entity API tutorials have been updated to reflect this change. We previously performed extensive updates that rewrote all our tutorials that made use of annotations for Drupal plugins. See…

  • Release Day: The Drupal Recipes API

    We recently completed a new set of tutorials covering the Drupal Recipe API. My interest in Drupal recipes began while I was working on documentation for the Drupal CMS User Guide, which relies heavily on recipes to provide its features. Drupal CMS is just Drupal core plus a curated set of contributed modules, preconfigured to…

  • FBI Warns of UNC6040 and UNC6395 Targeting Salesforce Platforms in Data Theft Attacks

    The U.S. Federal Bureau of Investigation (FBI) has issued a flash alert to release indicators of compromise (IoCs) associated with two cybercriminal groups tracked as UNC6040 and UNC6395 for a string of data theft and extortion attacks. “Both groups have recently been observed targeting organizations’ Salesforce platforms via different initial access mechanisms,” the FBI said….

  • The 15 Best Product Catalog Templates for InDesign in 2025

    A product catalog does more than list what you sell, it can also help shape how people see your brand. A clean, well-structured layout can make your products easier to browse and more appealing to potential buyers. But starting from scratch in InDesign takes time. That’s where these templates come in. These pre-made layouts give…