🇬🇪Georgia @gagosha

Account created on 8 November 2016, almost 9 years ago
  • Senior Drupal developer at Omedia 
#

Recent comments

🇬🇪Georgia gagosha

Just for information, patches need to be merged to support MCP OAuth 2.1 in the simple_oauth module.

1. https://www.drupal.org/project/simple_oauth/issues/3547743 Dynamic Client Registration Protocol (RFC7591) Active
2. https://www.drupal.org/project/simple_oauth/issues/3033472 [PP-1] Support OpenID Connect Discovery Needs review
3. https://www.drupal.org/project/simple_oauth/issues/3182421 🐛 Implement nonce in OIDC Needs work

🇬🇪Georgia gagosha

gagosha created an issue.

🇬🇪Georgia gagosha

Hey @michaellander, thanks for bringing this up. I agree, it's one of the must-have features and will be added to the top of the roadmap.

🇬🇪Georgia gagosha

Ty @loureirodev, merged.

🇬🇪Georgia gagosha

And after this comment it's your name unchecked again :/

🇬🇪Georgia gagosha

This new "Contribution record" is harder than the previous one :/ I clicked your name and saved. Still nothing?

🇬🇪Georgia gagosha

@ankitv18 I like "SiteInformation", but I don't have a clear idea of what to expose so that it doesn't become a security issue while still being a little bit more helpful. 😅

🇬🇪Georgia gagosha

gagosha made their first commit to this issue’s fork.

🇬🇪Georgia gagosha

gagosha made their first commit to this issue’s fork.

🇬🇪Georgia gagosha

gagosha made their first commit to this issue’s fork.

🇬🇪Georgia gagosha

Hey @askibinski, great to see someone interested in making it work.

As I remember, when I researched the auth implementation, there were the following requirements → Version 2025-06-18:

* OAuth 2.0 Authorization Server Metadata (RFC8414) → MUST
* OAuth 2.0 Dynamic Client Registration Protocol (RFC7591) → SHOULD
* OAuth 2.0 Protected Resource Metadata (RFC9728) → MUST

And Dynamic Client Registration is a MUST if we want to work with Claude Web or any other web-based clients. So I'd actually consider it a MUST.

I had a conversation with @bojan_dev, maintainer of the simple_oauth module, and:

For RFC8414, these need to be done:
https://www.drupal.org/project/simple_oauth/issues/3174705 Implement JWKs (RFC 7517) and OAuth metadata (RFC 8414) Needs work
https://www.drupal.org/project/simple_oauth/issues/3033472 [PP-1] Support OpenID Connect Discovery Needs review

RFC7591 and RFC9728 - nothing has been done yet.

As you pointed out, the previous version supported the PKCE Flow without these requirements. It’s interesting if the latest version also supports this as is (I got these requirements from the latest version, as I mentioned, and never checked the old one :D).

🇬🇪Georgia gagosha

This can't be fixed for now. It's because of the JSON-RPC module, which we use to handle RPC requests.

🇬🇪Georgia gagosha

Ah, you are right. Fix already pushed, thanks @jurgenhaas 🙌

🇬🇪Georgia gagosha

Hey @jurgenhaas, I think this is due to the latest change that added granular access to the plugins.

By default, they’re only accessible to the authenticated role. Could you try editing the plugin configuration and checking "Anonymous user"? I think the plugin tools should appear again after that.

🇬🇪Georgia gagosha

Hey @wjackson, thanks for the contribution!

Could you adjust it to work with the latest dev changes? The schema has changed a lot after the plugin configuration updates, so I think it will need some adjustments.

🇬🇪Georgia gagosha

Pushed the change. Updated the logic for ID generation, no longer using MD5 for everything.

From now on, IDs are generated as: `[plugin name]_[tool name]`, and if the result exceeds the 64-character limit, it’s truncated and a 6-character MD5 hash suffix is added.

🇬🇪Georgia gagosha

gagosha changed the visibility of the branch 3531816-make-mcp-plugin to hidden.

🇬🇪Georgia gagosha

gagosha changed the visibility of the branch 3531816-configurable-plugins to active.

🇬🇪Georgia gagosha

gagosha changed the visibility of the branch 3531816-configurable-plugins to hidden.

🇬🇪Georgia gagosha

"AI Function Calling" is not the plugin, it's the plugin manager.

For the MCP module, its plugin: https://git.drupalcode.org/project/mcp/-/blob/1.x/modules/mcp_extra/src/...

The MCP module requires these plugins to wrap/proxy the actual plugins/plugin managers in its format and expose them. When exposing tools, the first part is the MCP plugin ID, and the second part is the tool name. For example, if there is no MD5, the tool name will be:
`aif_action_plugin__entity__unpublish_action__menu_link_content`

🇬🇪Georgia gagosha

Hey @jibla @jurgenhaas,

For now, tool IDs are generated using two distinct parts: the plugin ID and the tool name. The plugin ID comes from the custom Drupal plugin. So for @Jurgenhaas photo, `aif` is the plugin ID, which stands for "AI Function Calling".

The second part is the MD5-hashed tool name, so there will be as many `aif_*` tools as the "AI Function Calling" plugin exposes.

We use MD5 for two reasons:
1. The Claude desktop application imposes a 64-character limit, and there might be other clients with similar restrictions.
2. Tools need to be discoverable. During the discovery phase, we use the first part (`aif`) to locate the plugin, and the second part, the MD5 hash, to locate the plugin's specific tool. Truncation wouldn’t work in this case, as it could lead to hash collisions (i.e. different tools ending up with the same name).

🇬🇪Georgia gagosha

Hey @askibinski, this is related to: https://www.drupal.org/project/mcp/issues/3539318 Improve tools naming Active . You can also propose the general solutions in the parent issue.

🇬🇪Georgia gagosha

@jibla @grasmash fixed and merged on dev

🇬🇪Georgia gagosha

Hey, thanks for bringing this up. We will do that for the next release

🇬🇪Georgia gagosha

Hey, @juc1

Just saw this catalog, it could be part of the roadmap, as it makes things easier, I guess. Will check

🇬🇪Georgia gagosha

Hey @mpotter, thanks for the patch, but I don't think the module itself should handle CORS, as there's already a way to handle it within Drupal.

If it’s configured correctly, the module will also use those CORS settings, since it intercepts all of Drupal’s request/response flow.

🇬🇪Georgia gagosha

Hey @askibinski, you’re not missing anything and you are right.

We need to change that part in the documentation. Thanks for mentioning it. The MD5 conversion is not part of the security in any case, and originally I wanted the tool names to stay original, but I couldn’t because of limitations with some clients.

🇬🇪Georgia gagosha

@jibla, just update the above comment for DrushCaller. Since the allowlist categorization doesn’t seem so stable, I decided to make it a text area where the user can opt-in to allowed commands or use the * wildcard.

🇬🇪Georgia gagosha

Summary

The MCP Content plugin's search-content tool consistently fails with an "Unknown field: status" error when attempting to search for any content, even with empty filters. This affects all content searches through the MCP interface.

Steps to Reproduce

  1. Install MCP module (tested with latest dev version)
  2. Enable the Content plugin in MCP Extra
  3. Attempt to search for any content using the MCP content search tool:
    {
      "contentType": "YOUR_CONTENT_TYPE",
      "filters": [],
      "limit": 10
    }
  4. Error occurs: "Unknown field: status"

Expected Behavior

Content search should work without errors and return matching nodes.

Actual Behavior

All content searches fail with "Unknown field: status" error, making the MCP content search functionality unusable.

Root Cause Analysis

The issue is in web/modules/contrib/mcp/modules/mcp_extra/src/Plugin/Mcp/Content.php in the searchContent() method around line 430:

$query = $this->entityTypeManager->getStorage('node')->getQuery()
  ->accessCheck(TRUE)
  ->condition('type', $contentType)
  ->condition('status', 1)  // <-- This line adds a status condition
  ->range($offset, $limit)
  ->sort('created', 'DESC'); // <-- This line sorts by created field

The method automatically adds conditions for status (to show only published content) and sorts by created, but the isSupportedField() method only recognizes title, body, and custom fields starting with field_. Core Drupal fields like status, created, nid, etc. are not included in the supported fields list.

Later in the code, when processing user filters, it validates all fields (including the automatically added ones) against isSupportedField(), causing the error.

Proposed Solution

Modify the isSupportedField() method to include core Drupal node fields that are used by the system:

private function isSupportedField(
  FieldDefinitionInterface $fieldDefinition,
): bool {
  $supportedTypes = [
    'string',
    'string_long',
    'list_string',
    'datetime',
    'boolean',
    'text_long',
  ];
  $fieldName = $fieldDefinition->getName();

  // Core fields that are used by the system automatically
  if (in_array($fieldName, ['title', 'body', 'status', 'created', 'changed', 'nid', 'uid', 'type'])) {
    return TRUE;
  }

  if (str_starts_with($fieldName, 'field_')
    && in_array(
      $fieldDefinition->getType(), $supportedTypes
    )
  ) {
    return TRUE;
  }

  return FALSE;
}

Additional Notes

  • This affects the latest dev version as of the time of this report
  • The issue makes the entire MCP content search functionality unusable
  • The fix is minimal and only adds recognition for core Drupal fields that the system already uses
  • Core fields added: status, created, changed, nid, uid, type

Environment

  • Drupal version: 10.4.3
  • MCP module: Latest dev version
  • PHP version: 8.3

Patch

The fix involves changing line ~560 in Content.php from:

if (in_array($fieldName, ['title', 'body'])) {

to:

if (in_array($fieldName, ['title', 'body', 'status', 'created', 'changed', 'nid', 'uid', 'type'])) {

This ensures that core Drupal fields used by the search system are recognized as supported fields.

🇬🇪Georgia gagosha

There are multiple ways the MCP config can be misconfigured. Some of them can’t be handled, as they don’t even hit the MCP route. Can you drop your MCP config so we can check, and add the error handling if something is missing and can be added?

🇬🇪Georgia gagosha

It’s part of the module roadmap and a work in progress. Right now I’m in the research phase, so I’m open to conversation about how we can implement it.

🇬🇪Georgia gagosha

This is a strange one, as the spec itself is model agnostic. Will check.

🇬🇪Georgia gagosha

1. Add 'use mcp server' permission and access checks

  • Added new permission use mcp server for basic MCP access
  • Updated routing to require this permission for the /mcp/post endpoint
  • Implemented hasAccess() checks in plugin base class with support for administrative override
  • Added permission validation in JSON-RPC methods (ResourcesRead, ToolsCall)

2. Token authentication user selection

  • Added user selection field in authentication settings form
  • Token authentication can now be configured to use any user account
  • Updated McpAuthProvider to load the configured user instead of hardcoded user 1
  • Added validation to ensure configured user exists and is active
  • Improved flood protection to use correct user ID

3. Content plugin opt-in behavior

  • Changed default behavior to opt-in (all content types disabled by default)
  • Updated form to clearly indicate opt-in behavior with description
  • Modified isContentTypeEnabled() to return FALSE by default
  • Added test updates to reflect new behavior

4. DrushCaller security improvements

  • Implemented command allowlist system with categorization by risk level:
    • Safe commands (read-only, enabled by default)
    • Moderate risk (cache operations, disabled by default)
    • Dangerous commands (database/file modifications, disabled by default with warnings)
  • Added form-based configuration for granular command control
  • Implemented strict mode for exact command matching
  • Added ability to configure custom commands
  • Command validation in both getTools() and executeTool() methods
  • Clear security warnings in UI for dangerous commands
🇬🇪Georgia gagosha

Closing this for now, as I can’t reproduce the issue. If any reproducible criteria come up, I’ll reopen it.

🇬🇪Georgia gagosha

Agreed — we're on the way to releasing a stable version, and documentation is part of that release.

🇬🇪Georgia gagosha

Hey @cosmicdreams,

Yep, why not — we can definitely add Claude.md. Also, for the future, we might consider adding Cursor rules for the same purpose - to make plugin development even easier.

🇬🇪Georgia gagosha

gagosha changed the visibility of the branch 3501988-create-mcp-plugin to active.

🇬🇪Georgia gagosha

gagosha changed the visibility of the branch 3501988-create-mcp-plugin to hidden.

🇬🇪Georgia gagosha

Hey @marcus_johansson,

I’ve pushed the initial version and placed the plugin in the right spot, under ai_agents_extra. This plugin exposes all accessible agents as tools and allows users to execute them.

🇬🇪Georgia gagosha

gagosha changed the visibility of the branch 3501988-create-mcp-plugin to active.

🇬🇪Georgia gagosha

Hey @dan_metille,

Sorry for any inconvenience. We have our first release today, which should clarify the definition of 'soon'.

🇬🇪Georgia gagosha

gagosha changed the visibility of the branch 3501988-create-mcp-plugin to hidden.

🇬🇪Georgia gagosha

gagosha made their first commit to this issue’s fork.

🇬🇪Georgia gagosha

Hey, what do you think about the following suggestion, @ejb503 @jibla?

As a baseline, we all agree with what @marcus_johansson posted in the Slack channel: “It should be hostable by a normal webserver/PHP stack, without any additional layers needed.” Based on this, we can proceed as follows:

Requirement:

To implement an MCP server that directly connects to MCP clients, we need the following (simplified):

  1. An SSE endpoint that allows clients to establish a connection and receive messages from the server. Method: GET.
  2. A regular HTTP POST endpoint that enables clients to send messages to the server. Method: POST.

With this setup, the POST endpoint would run the operation and queue the result, which the GET request could then check and return.

Proposal:

What if we add a configuration form with just one checkbox (defaulted to true) that determines whether the POST request should queue the operation result or return it directly?

This approach would allow us to maintain both implementations without any additional work. The core of MCP would return results compatible with the specification, creating a win-win situation. By default, no additional layer is needed, and everything would be standard, straightforward, and directly hostable by Drupal.

Production build 0.71.5 2024