MCP server integration
Goal: connect the MCP client of your choice to your site’s MCP server, and know what the server exposes before you point an agent at it.
What you’ll have when you’re done
Section titled “What you’ll have when you’re done”- Your MCP client connected and authorized: Claude Code, Claude Desktop, Cursor, VS Code, GitHub Copilot, OpenCode, Codex, or MCP Inspector.
- A working map of the server:
drupal://andcanvas://resource URIs, the tool catalog by domain, and the limits to design around.
Prerequisites
Section titled “Prerequisites”- The
MCP Serverexperimental feature enabled on your site; the MCP quickstart covers enabling it and the fastest path to a first tool call with Claude Code. - An MCP-capable client installed; the MCP quickstart sets one up (Claude Code) if you don’t have one yet.
-
Copy the connection details from your site
Section titled “Copy the connection details from your site”In the site admin UI:
Configurations > Experimental features > MCP Server > Configure. The panel gives you everything a client needs:MCP client configuration: the server URL and parameters to paste intoclaude_desktop_config.jsonor Cursor.MCP Inspector: a ready-made command to launch the debug environment.OAuth configuration: the scopes and authentication parameters the server accepts.
You typically don’t change anything here; copy the connection URL and move on.
-
Understand how credentials reach the server
Section titled “Understand how credentials reach the server”The server speaks MCP over streamable HTTP at
{DRUPAL_SITE_URL}/mcp, and every request is authorized by OAuth 2.0: a bearer token on each HTTP request. There is no API key to paste. In practice: the client registers itself with the site and opens your browser; you sign in (if you aren’t already) and clickAllow; from then on the client attaches and refreshes its token without your involvement.How the handshake works, step by step
An unauthenticated request gets a
401whoseWWW-Authenticateheader carries onlyBearer realm="mcp_server"(captured 2026-07-03): no scope list, no metadata URL. The client therefore derives the discovery locations from the server URL itself: the resource metadata at{DRUPAL_SITE_URL}/.well-known/oauth-protected-resource/mcplists the scopes the server accepts, and the site’s/.well-known/oauth-authorization-serverdocument names the endpoints. From there the client registers itself at theregistration_endpoint(/oauth/register, dynamic client registration; this is how Claude Code and other MCP clients self-register), then opens the browser window where you approve the connection. The resulting access token rides on every subsequent request.The whole exchange, from the challenge to authorized tool calls: an unauthenticated request is refused, the client discovers the OAuth metadata and self-registers, and you approve in the browser. The token then rides every request until it expires and the client silently re-authorizes.
Three consequences worth knowing:
- The agent acts as you. Tool calls carry your authorization, so what the agent can read and write is bounded by what you approved.
- Tokens expire after 300 seconds. Clients re-authorize silently, but a long-idle session may drop you back into the browser flow.
- Headless setups don’t need the browser: tokens minted by the site’s existing API clients also work, a
client_credentialsgrant against{DRUPAL_SITE_URL}/oauth/token(no scope parameter needed). Pass the token as anAuthorizationheader in the client’s server configuration, e.g.claude mcp add acquia-source-mcp {DRUPAL_SITE_URL}/mcp --transport http --header "Authorization: Bearer <token>"; remember it expires after 300 seconds, so CI mints one per run.
The OAuth machinery (grants, scopes, token lifetimes) is the same one behind the Content API; the authentication guide covers it in depth.
-
Configure your client
Section titled “Configure your client”The canonical client, documented end to end in the quickstart:
Terminal window claude mcp add acquia-source-mcp <URL> \--transport http --scope projectThen inside Claude Code:
/mcp→ selectacquia-source-mcp→Authenticate→ complete the browser flow.--scope projectwrites the server to.mcp.jsonin the project root so the whole team shares it; use--scope userinstead if the server should follow you across projects rather than live in one repo.For a site reachable over the public internet, add a custom connector:
Customize > Connectors,+,Add custom connector, paste the MCP URL, clickAdd, thenConnectto authorize. Custom connectors reach the server from Anthropic’s cloud, not from your machine; on Team and Enterprise plans an Owner adds the connector underOrganization settings > Connectorsfirst.Alternatively, paste the parameters from the
MCP client configurationpanel intoclaude_desktop_config.json(macOS:~/Library/Application Support/Claude/claude_desktop_config.json; Windows:%APPDATA%\Claude\claude_desktop_config.json), then restart Claude Desktop and complete the authorization prompt. The panel’s snippet is authoritative for the exact parameter names.Add the server to
.cursor/mcp.jsonin your project (or the global~/.cursor/mcp.json), pasting the URL from theMCP client configurationpanel:{"mcpServers": {"acquia-source-mcp": {"url": "PASTE_MCP_URL_FROM_CONFIGURE_PANEL"}}}Cursor picks the server up on reload and walks you through the same browser OAuth flow.
Add the server to
.vscode/mcp.jsonin your project (or runMCP: Add Serverfrom the Command Palette;MCP: Open User Configurationtargets your user profile instead):{"servers": {"acquia-source-mcp": {"type": "http","url": "PASTE_MCP_URL_FROM_CONFIGURE_PANEL"}}}VS Code asks you to confirm that you trust the server when it first starts, then opens a browser window to complete the authorization.
Copilot Chat in VS Code reads MCP servers from the repository’s
.vscode/mcp.json(the configuration under VS Code) or from your personalsettings.json;MCP: List Serversconfirms the server registered. On Copilot Business and Enterprise plans, theMCP servers in Copilotpolicy must be enabled for the organization. JetBrains, Visual Studio, Eclipse, and Xcode carry their own MCP configuration files: see Extending Copilot Chat with MCP.Add the server to
opencode.jsonat the project root:{"$schema": "https://opencode.ai/config.json","mcp": {"acquia-source-mcp": {"type": "remote","url": "PASTE_MCP_URL_FROM_CONFIGURE_PANEL"}}}OpenCode prompts for the OAuth flow on the server’s first use;
opencode mcp auth acquia-source-mcptriggers it manually.Register the server and log in:
Terminal window codex mcp add acquia-source-mcp --url PASTE_MCP_URL_FROM_CONFIGURE_PANELcodex mcp login acquia-source-mcpCodex stores the server in
~/.codex/config.toml(user-wide, not per project);codex mcp listshows its auth status.MCP Inspector (for debugging, not day-to-day use):
Terminal window npx @modelcontextprotocol/inspector --transport httpThe command starts a local web UI and prints its address (
http://localhost:6274/…); open it in a browser. In the Inspector UI: paste the site’s MCP server URL, set connection type toDirect, clickConnect, complete the OAuth flow for dynamic client registration, and clickAllow. You can then browseList Resources,List Templates, andTools: the fastest way to see exactly what your server exposes, live. -
Browse what the server exposes as resources
Section titled “Browse what the server exposes as resources”Resources are read-only data, addressed by URI. The server uses two schemes:
drupal://for the content model and content entities,canvas://for Drupal Canvas pages and components. Reading one takes no special syntax: in Claude Code, just ask (Read drupal://content-types and summarize the fields); in MCP Inspector, useList Resourcesand click through.Fixed resources list things:
URI Returns drupal://content-typesThe site’s content types, each with its workflow and schema URI drupal://media-typesMedia types drupal://vocabulariesTaxonomy vocabularies drupal://filter-formatsText formats drupal://content-types/fieldsContent-type field storages drupal://field-typesAvailable field types, by category drupal://menusThe site’s menus, each with an items_urifor its item treedrupal://site-infoSite name and configured home page canvas://componentsDrupal Canvas components canvas://pagesDrupal Canvas pages, with live and draft metadata canvas://page-regionsGlobal page regions (header, footer, …) for the active theme canvas://auto-savesPending auto-saved drafts, with the keys the publish/discard tools need Resource templates take parameters for point lookups:
URI template Returns drupal://entity/{entity_type_id}/{id}One entity (e.g. drupal://entity/node/17)drupal://content-types/{bundle}JSON Schema for a content type (e.g. drupal://content-types/article)drupal://content-types/{bundle}/fields/{field_name}One field’s instance and storage configuration drupal://media-types/{bundle}JSON Schema for a media type drupal://vocabularies/{vid}JSON Schema for a vocabulary drupal://menus/{menu_name}One menu’s item tree, with the item IDs the menu tools take canvas://components/{id}One Canvas component’s detail So “what fields does an article have?” is one read of
drupal://content-types/article, and “what components can I place on a page?” is one read ofcanvas://components. Response shapes for each are specified in the MCP server reference. -
Call tools from the catalog
Section titled “Call tools from the catalog”Tools are the operations that change state (plus a few parameterized reads), 38 in all. Each name links to its entry in the reference, which specifies inputs, responses, and errors:
Content management, read and write content entities:
create_node·update_node·batch_create_nodes·list_entitiesContent modeling, define and evolve content structure:
create_content_type·add_field_to_content_type·batch_add_fields_to_content_type·update_field_configTaxonomy and menus, vocabularies, terms, menus, and menu items:
create_vocabulary·get_or_create_term·create_menu·update_menu·create_menu_item·update_menu_item·delete_menu_itemMedia, file uploads, remote video, and DAM references:
create_media·create_remote_video·create_dam_mediaSite settings, site name, logo, and homepage:
update_site_settings·update_site_logo·set_homepageDrupal Canvas pages and components, pages, component-based layouts, and the global page regions:
create_canvas_page·update_canvas_page·delete_canvas_page·get_page_layout·set_page_layout·add_component_to_page·batch_add_components_to_page·move_component·remove_component·update_component_props·get_page_region_layout·set_page_region_layout·add_component_to_page_regionDrafts and publishing, make drafts live, or throw them away:
publish_canvas_page·publish_auto_saves·discard_auto_saves·get_canvas_preview_signed_urlThe combination is where the value is: an agent reads
drupal://content-types/articleto learn the shape, then callsbatch_create_nodesto generate structured content in bulk; or readscanvas://componentsand composes a landing page withcreate_canvas_page,batch_add_components_to_page, andpublish_canvas_page. -
Work within the known limits
Section titled “Work within the known limits”- Experimental. The server may change or be removed without notice, and it is off by default, per-site opt-in under
Configurations > Experimental features. - Your permissions are the ceiling. Every tool call runs with the authorization you granted in the OAuth flow; the server grants agents no access you don’t have.
- Content types need a workflow that already exists, and no tool creates one.
create_content_typerequires aworkflowparameter naming an existing workflow (empty or null is rejected), the catalog has no workflow-creation tool, and a fresh Source CMS site ships with none. On a fresh site the call fails withWorkflow "…" does not exist.until an administrator creates a workflow in the admin UI (content workflows, on docs.acquia.com). Check what exists first:drupal://content-typesshows each content type’s workflow. - No content deletion. The catalog has create and update tools for content entries, media, and terms, but no delete: the only delete tools are
delete_menu_itemanddelete_canvas_page. Deleting content stays a human job in the admin UI or JSON:API. - Batch creation covers nodes, fields, and components (
batch_create_nodes,batch_add_fields_to_content_type,batch_add_components_to_page); media and terms are created one call at a time. - Many writes land as drafts, not live changes. Canvas layout edits, menu items, and staged site settings go to the auto-save channel; nothing is visible until you publish via
publish_auto_saves(orpublish_canvas_pagefor a whole page). Pending drafts are listed atcanvas://auto-saves. - No fixed numeric limits; the timeout is the bound. Verification surfaced no request rate limit, no maximum
batch_create_nodesbatch size, and no request payload cap. The only ceiling is the per-request timeout, so very large batches or queries fail by timing out (-32001) rather than by hitting a documented cap. Split or narrow them: see the failure entries below.
- Experimental. The server may change or be removed without notice, and it is off by default, per-site opt-in under
-
Govern the agent’s access
Section titled “Govern the agent’s access”Least privilege lives on the credential, not the connection. Give each agent its own API client with the fewest
Allowed Scopesits job needs (the scope catalog); a browser-authorized agent’s ceiling is the person who clickedAllow. One verified caution: scope gating was not observable in MCP server verification (Connection). Treat scopes as the control you set deliberately, and lean on the permission layer, which still refuses and names the missing permission (scopes are not team roles).Revocation has two levers and one clock:
- Toggle
Enable MCP Serveroff. This invalidates the endpoint for every agent on that site, reversibly. - Delete the agent’s client at
API > API clients. The next token request fails withinvalid_client; for zero-downtime swaps, use the rotation order.
Either way, no already-issued token outlives its 300 seconds.
Attribution follows the credential: a browser-authorized agent acts as its approver, a
client_credentialstoken acts as the client’s own identity, so per-agent clients are per-agent accountability. And most agent writes land as drafts first: inspect pending work atcanvas://auto-saves, thenpublish_auto_savesordiscard_auto_savesbefore anything reaches readers. - Toggle
When something goes wrong
Section titled “When something goes wrong”401 Unauthorized on every request, or the client reports the server needs authentication
the OAuth handshake never completed, or the token expired (tokens last 300 seconds) and silent refresh failed. The 401 itself says little: its WWW-Authenticate header carries only Bearer realm="mcp_server", so when diagnosing by hand read the resource metadata at {DRUPAL_SITE_URL}/.well-known/oauth-protected-resource/mcp directly for the scopes and endpoints the server accepts. Re-run your client’s authenticate action (in Claude Code: /mcp → select the server → Authenticate) and finish the browser flow through Allow. If the browser step itself fails, confirm you are signed in to the site in that browser, and that the MCP Server feature is still enabled; disabling it invalidates the endpoint. Deeper OAuth diagnostics: the auth guide’s troubleshooting.
MCP error -32601: Method not found on a tool the reference says exists
your client cached the server’s capabilities from an earlier session, or client and server negotiated mismatched protocol versions. Restart the client; if the tool list is still stale, remove and re-add the server, and update the client; MCP clients pin the protocol versions they support.
Tools are missing from the client’s list even though MCP Inspector shows them
client-side caching. The Inspector talks to the server directly, so if it lists the tool and your client doesn’t, the client’s cached capability list is stale: restart the client or re-add the server. If the Inspector doesn’t show the tool either, the server genuinely doesn’t expose it: check the reference for what’s actually in the catalog.
MCP error -32001: Request timed out
the call was too big: a list_entities sweep over a large site, or a batch_create_nodes payload with too many nodes. Narrow the query (filter by content type, request fewer entities) or split the batch into smaller calls and let the agent iterate.
Next steps
Section titled “Next steps”- MCP server reference: the connection spec and every tool’s inputs, responses, and errors.
- Authentication guide: the OAuth machinery this server authorizes with.
Was this page helpful?
What went wrong?
Still stuck? Contact Acquia Support (opens in a new tab)