Skip to content

MCP clients

Marie asks Claude Code: "What is waiting for me in Orchestra?" Claude Code calls the orchestra_list_my_tasks tool on the workflow site, and answers with her two open leave requests. The first time, Claude Code opened the site in her browser, and she signed in there with her own account. So the tool ran as Marie, with her permissions, and nobody else's.

This page shows how to set that up, from installing the modules to the first call. It uses Claude Code, but any MCP client that signs in with OAuth works the same way.

How it works

An MCP client calls the Orchestra tools through three modules:

Module What it adds
MCP Server (mcp_server) The MCP endpoint, /mcp, and the Access MCP server permission.
MCP Server Tool Bridge (mcp_server_tool_bridge) A Tool API tool reaches MCP clients only through an MCP tool configuration, under Configuration > Web services > MCP Server > Tools.
MCP Server OAuth (mcp_server_oauth) Each tool configuration asks for an OAuth scope. It brings Simple OAuth, the server metadata a client reads to find how to sign in, and the registration a client signs up with on its own.

Every call is made for the person who signed in:

  • The client holds an OAuth token. Each person gets their own, by signing in on the site.
  • A tool runs as that person. Orchestra checks their own permissions, as its pages do.
  • The token's scope caps what it can do. A token with the orchestra_mcp scope carries only the permissions the Orchestra tools need, however much more the person may do on the site.

Setting up the site

The modules

composer require drupal/mcp_server_tool_bridge drupal/mcp_server_oauth
drush pm:install mcp_server_tool_bridge mcp_server_oauth

The two modules bring MCP Server with them. None of the three has a stable release yet: a project that accepts only stable releases has to allow theirs in its composer.json.

Orchestra Tool ships what the tools need, and Drupal installs it once these modules are there:

  • one MCP tool configuration per Orchestra tool, enabled, with its Authentication mode set to Required and the orchestra_mcp scope;
  • the orchestra_mcp scope.

A site without the MCP modules gets none of it.

On a site where Orchestra Tool and the MCP modules were already installed, nothing is added. Install what Orchestra Tool ships, and nothing else:

drush php:eval '$directory = \Drupal::service("extension.list.module")->getPath("orchestra_tool") . "/config/optional";
\Drupal::service("config.installer")->installOptionalConfig(new \Drupal\Core\Config\FileStorage($directory));'

Called without the directory, the same method would also bring back the optional configuration of every other module, such as a view you deleted.

A tool configuration you made by hand keeps its settings: Drupal never replaces one that exists. Delete it first to get the shipped one.

The scope

The orchestra_mcp scope groups one scope for each permission the tools need:

Scope Permission
orchestra_mcp_access_server Access MCP server
orchestra_mcp_access_tools Access Orchestra tools
orchestra_mcp_access_instances Access Orchestra process instances
orchestra_mcp_administer Administer Orchestra
orchestra_mcp_process_tasks Process Orchestra tasks
orchestra_mcp_view_own_instances View own Orchestra process instances

A token's permissions are the person's own, kept to those its scope names. So the scope never gives Marie a permission she does not have. It only keeps the client's token away from everything else she may do on the site.

No role comes with the scope, and none is needed: the scope names permissions, and the person's own roles grant them.

Required, for every tool

Required means a tool call needs a token holding the orchestra_mcp scope:

  • a call without a token is refused with a 401, and the client asks the person to sign in;
  • a call with a token for other scopes is refused with a 403.

A browser session alone does not open a tool.

The site lists a scope to clients only while an enabled tool configuration names it. A client asks for the scopes the site lists when it signs in.

The people

Marie needs these permissions, in one of her roles:

  • Grant OAuth2 codes, from Simple OAuth, to approve her client on the site's authorize page. It grants nothing else. Out of the box only administrators have it, and no scope can give it: the site checks it at the authorize step, on her own session, before any token exists;
  • Access MCP server, to reach /mcp;
  • Access Orchestra tools, the gate of every Orchestra tool;
  • the permission each tool asks for, as on the pages of the site: Process Orchestra tasks for her own tasks, View own Orchestra process instances for the requests she started, Access Orchestra process instances to start and follow workflows. See the table of the tools.

The token carries Administer Orchestra for a person who has it, because setting a variable needs it. Her client may then do what that permission allows, on the tools and on the pages it opens. Grant it only to people you trust to hand it to an MCP client.

Her client lists a tool when she has the permission the tool declares, and the tool checks the rest when she calls it. So orchestra_get_instance is listed to anyone with Access Orchestra tools, and refused to a person who may not see instances. See Permissions.

User 1

While core's super-user policy is on, user 1 has every permission, whatever the token's scopes say. Sign in with another account, or turn the policy off with the security.enable_super_user parameter set to false.

Connecting Claude Code

Add the site:

claude mcp add --transport http orchestra https://workflows.example.com/mcp

Then, in Claude Code:

  1. Type /mcp, pick orchestra, and choose Authenticate.
  2. The browser opens the site. Sign in, and grant access if the site asks.
  3. Back in Claude Code, the Orchestra tools are listed as mcp__orchestra__tool_api__orchestra_list_my_tasks and so on.

Ask "What is waiting for me in Orchestra?" and Claude Code calls orchestra_list_my_tasks as Marie.

Claude Code registers itself on the site the first time, so you add no consumer by hand. Each person who connects signs in once, with their own account.

HTTP and STDIO

MCP Server also runs over STDIO, with drush mcp:server <account>. The difference matters:

  • HTTP (/mcp) checks a token on every call. Each person signs in, and each tool runs as the person who did.
  • STDIO runs as the account its command line names, and checks nobody. Whoever can run the command acts as that account.

So only HTTP makes each person use their own account. Use STDIO for a command you run yourself on the server, never to share an account.

Troubleshooting

What you see Why What to do
The authorize page says The 'grant simple_oauth codes' permission is required., or the client is refused at sign-in The person lacks Grant OAuth2 codes. Grant it to one of their roles.
A 400 when the client signs in The site lists no scope: no enabled tool configuration names one. Install the shipped configuration, or enable the tools.
A 401, Authentication required The call had no token, or one that has expired or was revoked. Authenticate again in the client.
A 403, Insufficient scope The token holds other scopes, not orchestra_mcp. Authenticate again, and approve orchestra_mcp.
A 403 on every call to /mcp The person lacks Access MCP server. Grant it to one of their roles.
A tool is missing from the list The person lacks the permission it declares, or its configuration is disabled. Grant the permission, or enable the tool.
A listed tool is refused The person lacks the permission of its action on the pages, such as Administer Orchestra to set a variable. Grant it, if they should have it.