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_mcpscope 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_mcpscope; - the
orchestra_mcpscope.
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:
- Type
/mcp, pickorchestra, and choose Authenticate. - The browser opens the site. Sign in, and grant access if the site asks.
- Back in Claude Code, the Orchestra tools are listed as
mcp__orchestra__tool_api__orchestra_list_my_tasksand 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. |