Drupal Code Query
REMOTE · MCP.TRESBIEN.TECH
Drupal core API changes, contrib usage, upgrade checks, patches, code search, SQL, WordPal themes.
Available components
Last scanned (3 hours ago)
Scores higher than 85% of remote servers
Reachable. Last reached 5 Nov 2026.
Category Code Search and Documentation
How this component scores in each security and reliability category. Every signal is checked automatically against the live server, and we only credit what we can confirm. How we score → Why this is hard to score →
Endpoint Security74
- The endpoint's TLS certificate is valid, in date, and uses a strong key. View diagnostics → Pass
- No authorisation is required to call this server. Every tool declares its destructiveHint and none is destructive, so open access doesn't expose one. See how to fix → View diagnostics → Partial
- HTTPS is enforced; there's no plaintext access path. View diagnostics → Pass
- HSTS check failed: the Strict-Transport-Security header is absent. See how to fix → View diagnostics → Fail
- DNSSEC check failed: signatures are present but failed validation. See how to fix → View diagnostics → Fail
Transport & Reachability100
- Verified streamable-http transport via a live MCP handshake. View diagnostics → Pass
Schema Quality & AI Usability58
- AI-judged instruction clarity (excellent).Pass
- Context-footprint check failed: tool/resource definitions use about 10443 tokens (~614/item across 17 items; 17 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
- Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management100
- No destabilizing schema changes in the last 30 days.Pass
Tool Coverage100
- 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
- 100% of tool parameters carry a description.Pass
Tool Safety100
- No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
- We read all 17 captured tool definition(s), and no name or description among them implies an irreversible operation.Pass
- An AI judge read all 18 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
- Implements a current MCP spec version (2026-07-28).Pass
Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.
- 5 Nov 26 0
- DNSSEC: DNSSEC check failed: signatures are present but failed validation. security
- 22 Oct 26 0
- Authorization: unverified → partial ▲ security
- Injection markers: unverified → pass ▲ security
- Stability: unverified → pass ▲ security
- Endpoint reachability: unreachable → reachable ▲ functional
- Tool coverage: unverified → 100 ▲ functional
- MCP protocol: unverified → pass ▲ functional
- 21 Oct 26 0
- Endpoint reachability: reachable → unreachable ▼ security
- Stability: pass → unverified ▼ security
- Tool safety: pass → unverified ▼ security
- Authorization: partial → unverified ▼ security
- Capabilities: pass → unverified ▼ functional
- Tool coverage: 100 → unverified ▼ functional
- First check of Schema quality: unverified functional
- 19 Oct 26 0
- Tool “wordpal_theme” rewrote its description, which is the text the model reads security
- Server version: 0.47.0 → 0.48.0 functional
- 15 Oct 26 0
- Tool “query_dataset” rewrote its description, which is the text the model reads security
- Tool “wordpal_theme” rewrote its description, which is the text the model reads security
- Server version: 0.46.0 → 0.47.0 functional
- 14 Oct 26 0
- Tool “wordpal_theme” rewrote its description, which is the text the model reads security
- Server version: 0.45.1 → 0.46.0 functional
- 13 Oct 26 0
- Tool “wordpal_theme” rewrote its description, which is the text the model reads security
- Server version: 0.45.0 → 0.45.1 functional
- 12 Oct 26 0
- The server rewrote its instructions, which are the text every model session reads security
- Tool “query_dataset” rewrote its description, which is the text the model reads security
- Server version: 0.43.0 → 0.45.0 functional
- New tool “wordpal_theme” functional
Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.
Captured 5 Nov 2026 · Probed https://mcp.tresbien.tech/mcp
TLS valid
Negotiated TLS 1.3 with TLS_AES_128_GCM_SHA256 .
| Subject | Issuer | Valid from | Valid until | Key | Signature | Serial |
|---|---|---|---|---|---|---|
| CN=mcp.tresbien.tech | CN=YE1,O=Let's Encrypt,C=US | 16 Oct 2026 | 14 Jan 2027 | ECDSA 384 | ECDSA-SHA384 | 6c467278ef9dacc7b983f89851b19caca26 |
| SANs: mcp.tresbien.tech | ||||||
| CN=YE1,O=Let's Encrypt,C=US (CA) | CN=Root YE,O=ISRG,C=US | 3 Sept 2025 | 2 Sept 2028 | ECDSA 384 | ECDSA-SHA384 | 5ddd70dd31f801c85c186a7a04b80afe |
| CN=Root YE,O=ISRG,C=US (CA) | CN=ISRG Root X2,O=Internet Security Research Group,C=US | 13 May 2026 | 2 Sept 2032 | ECDSA 384 | ECDSA-SHA384 | 872165fc34b6e5fba8add5b3705fb53a |
| CN=ISRG Root X2,O=Internet Security Research Group,C=US (CA) | CN=ISRG Root X1,O=Internet Security Research Group,C=US | 13 May 2026 | 2 Sept 2032 | ECDSA 384 | SHA256-RSA | 6c8f1dc727c7117f7baf853ac980f9cd |
Background: What to check on a remote MCP endpoint →
DNSSEC bogus
Validation of mcp.tresbien.tech. — Bogus
| Zone | DS | Keys | Algorithms | Outcome |
|---|---|---|---|---|
| . | trust_anchor | 20326, 38696 | 8, 8 | Verified |
| tech. | present | 2185 | 13 | Verified |
| tresbien.tech. | present | 58994 | 13 | Verified |
| mcp.tresbien.tech. | Bogus address RRset signature failed verification |
Authentication No authorisation required
The endpoint answered without asking for a token. Anyone who knows the URL can reach it.
| Result | No authorisation required |
|---|---|
| HTTP status | 200 |
| Header | Value |
|---|---|
| x-content-type-options | nosniff |
| x-frame-options | DENY |
Background: How OAuth 2.1 works in the 2026 MCP spec →
Transports 2 probes
| Transport | URL | Outcome | Status | Location |
|---|---|---|---|---|
| streamable-http | https://mcp.tresbien.tech/mcp | Verified | 200 | |
| http (plaintext) | http://mcp.tresbien.tech/mcp | HTTPS enforced | 301 | https://mcp.tresbien.tech/mcp |
The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →
check_patches Check composer patches against a release ~1,199
Does each composer patch still apply to the release the site installed, and is its fix already in that release? - Send composer_json and composer_lock after composer update. Add patch_files for every patch, a local one read from disk and a URL one fetched by you. Every extra.patches entry is checked at its installed version in one call. - Do not download releases. Do not run patch --dry-run. - Send a package's patches together, in the order composer.json lists them. - items: up to 50 of {project, version, patch, title}, in place of the composer files. project: the drupal.org machine name (webform) or composer name (drupal/webform); drupal or core for Drupal core. version: the installed composer version (1.13.0, 2.0.0-beta4, 11.4.5). patch: the diff text, or its URL on www.drupal.org/files/issues or a git.drupalcode.org merge request or commit, ending .patch or .diff. - Per item. tag: the release tag matched, or unknown_version. applies_at: the -p level at which git apply passes, null when none. fuzzy: true when it applied only with reduced context and whitespace ignored; review it. hunks_failed: [{file, line, reason}]. reverse_applies: true when the patched lines are already in the tag. mr: the merge request state when the patch is an MR URL. merged_in_version. suggested. failure_mode: set when a patch applies and a file it touches no longer parses; keep the patch and fix the file. syntax_errors: the files behind it, one per file, path then the parser's message. - suggested: the verdict. merged: the fix is in the release; drop the patch. applies: keep the patch. conflicts: call reroll_patch with that item. unknown: see error. - next_step: the follow-up calls and the row count the report must have. counts: the verdict tally; check the report's table against it. An item that could not be judged comes back unknown with the reason in error. Report it as unclear. Never leave the row out. - hunks_shipped, files_shipped: the parts of a patch already in the release verbati…
| Name | Type | Req | Description |
|---|---|---|---|
| composer_json | string | – | The contents of composer.json. Send the text; this server cannot read your filesystem. Its extra.patches becomes the item list, one item per patch. |
| composer_lock | string | – | The contents of composer.lock. It gives the installed version of each patched package. |
| items | null|array | – | Up to 50 patches to check. Each item has project, version, patch and title. project: webform or drupal/webform; drupal or core for Drupal core. version: the installed composer version, 1.13.0 or 11.4… |
| patch_files | object | – | The text of every patch the site declares, keyed by the source as written: a path (patches/x.patch) or its base name, or the URL. Fetch a URL patch yourself and send its text under that URL. For a me… |
| patches_file | string | – | The text of the patches file, for a site on cweagans/composer-patches 2.x that keeps its patches out of composer.json. The path is in its own extra.composer-patches.patches-file, patches.json by defa… |
| patches_lock | string | – | The text of patches.lock.json, which 2.x of the patch manager writes and applies from. Send it to judge what the site actually applies: it answers alone, over extra.patches and the patches file. |
| target_core | string | – | Core the added code is checked against: a minor (11.4 or 11.4.x) or a release (11.4.5). A minor with no core release in the data is refused, and so is a major alone. latest checks no references. Defa… |
No output schema declared.
No examples provided.
describe_dataset Describe the dataset ~290
Learn the dataset before writing SQL for query_dataset. Call it with no arguments first. Returns text. Prefer a typed tool when one answers the question. - No arguments: one line per view, the join map, the four invariants, the causes of empty results, and the recipe index. The invariants: dev-branch isolation, no SUM(usage), *_seq compares, adoption polarity. Empty results come from fqn forms, placeholders and machine name forms. - view=<name>, or views=[…] for several in one call. Returns the columns with types and descriptions, an example filter that returns rows, and the joins into the view. - recipe=<id>: a ready-to-run statement for a common question. Fill in the placeholders and run it with query_dataset. Recipes cover who uses a symbol, deprecated symbols per project, and a change record's adoption. Others cover symbols deprecated between minors, one project's deprecated uses, and change records between minors.
| Name | Type | Req | Description |
|---|---|---|---|
| recipe | string | – | One recipe id from the overview's index. Returns a ready-to-run query_dataset statement with its placeholders explained. |
| view | string | – | One view name. Returns its columns with types and descriptions, an example filter, and the joins into it. Leave empty for the overview. |
| views | null|array | – | Up to 8 views at once, documented one after the other in one call. |
No output schema declared.
No examples provided.
get_change_record One change record ~260
Return one core change record in full: title, flavour, target version, machine-checkable tracks, linked issues, linked core symbols, and contrib adoption counts. To find records, use list_change_records or the change_record_nids from what_changed. For one symbol's detail, use lookup_core_symbol. - flavour: coming-break (an API going away), coming-new-API (an API added), landed-but-still-relevant (shipped), policy-only (no code target, no adoption). - Adoption counts contrib development branches only. legacy: still calls the going-away side. migrated: moved to the new side. - Returns counts across every affected project plus a ranked head, outstanding first. For one project, use project_upgrade_report; do not raise top_projects. - symbols: the core API the record is about. role: from (going away) or to (replacement). Use the fqn with lookup_core_symbol. Empty means the catalog links no symbol; that is common.
| Name | Type | Req | Description |
|---|---|---|---|
| nid | integer | yes | The change record's drupal.org node id, for example 3581981. |
| top_projects | integer | – | How many impacted projects to return in the ranked head. Defaults to 10, capped at 40. |
No output schema declared.
No examples provided.
list_change_records Change records in a version range ~314
List the core change records (the human write-ups) that target a range of core versions, tagged by flavour and ranked, with counts. For the symbol-level diff, use what_changed. For one record in full, use get_change_record. - Bounds are inclusive. Forms: 11.2, 11.2.x, 11.2.0, 11, 11.x. A bare major covers every minor of it. - Flavours: coming-break (an API going away), coming-new-API (an API added), landed-but-still-relevant (already shipped). policy-only records target no version and never appear here. - project: one machine name. Each record then has the count of that project's development branches still on the legacy side. - Returns the count of every record in range plus a ranked head. Each entry has its nid for get_change_record.
| Name | Type | Req | Description |
|---|---|---|---|
| from | string | yes | Lower core version bound, inclusive: 11.2, 11.2.x, 11.2.0, 11, or 11.x. A bare major (11) covers every minor of it. |
| limit | integer | – | Records in the head, 1 to 40 (default 15). Above the cap the call is refused. |
| project | string | – | Optional contrib project machine name. Narrows the list to records a development branch of that project still matches. |
| to | string | yes | Upper core version bound, inclusive. Same forms as from. |
No output schema declared.
No examples provided.
list_class_relations Contrib classes extending a core class ~355
List the contrib classes that extend, implement or use a core class, interface or trait, one row per edge with file and line, paged. Example: "who subclasses FormBase". Call-site counts: list_symbol_users. The symbol's status: lookup_core_symbol. - target: with or without the leading backslash. An unknown target is refused with a pointer at lookup_core_symbol; a fragment there lists candidates. rel_kind: one of extends, implements, uses_trait. project: one machine name. - Development branches only. edge_count: every edge. project_count: projects. count: edges after the per_project cap. project_edges on each row: the project's full count. per_project=50 with project= lists one project in full. - Rows are ordered by project installs, project, source_fqn. Each row: project, branch, installs, source_fqn, rel_kind, file, line, project_edges. limit ≤ 100. next_offset is absent on the last page.
| Name | Type | Req | Description |
|---|---|---|---|
| limit | integer | – | Rows per page, 1 to 100 (default 50). |
| offset | integer | – | Skip this many rows in the same ranked order. Pass the previous page's next_offset. |
| per_project | integer | – | Edges shown per project on a page, 1 to 50 (default 3). Each row has project_edges, the project's full count. |
| project | string | – | Restrict to one project machine name. |
| rel_kind | string | – | extends, implements, or uses_trait; any when absent. |
| target | string | yes | The core class, interface or trait, with or without the leading backslash: Drupal\Core\Form\FormBase. |
No output schema declared.
No examples provided.
list_projects List projects by filters ~567
List drupal.org projects after filters, largest install base first, paged. Examples: "top modules without an 11.4 branch", "themes over 10k installs without security coverage". One project: project_profile. Its pending records: project_upgrade_report. - Filters combine: type, min_installs, security (covered, not-covered, revoked), core_minor (+ missing), era (d8plus, pre_d8), member_of (+ max_depth). All apply to count and rows. - core_minor reads the composer constraint of the newest release on each development branch. A minor counts when any patch of it satisfies the constraint. An unreleased tip change is not seen. missing=true keeps projects with no branch declaring it: the upgrade gap list. - member_of keeps one root's members, direct and transitive; max_depth (needs member_of) drops members past that many requires away. A filtered list adds membership: root_release, complete, unread_count and unread (up to 20, package + cause). - Row: machine_name, title, type, installs, security, status, dev_branches (branch, installs, core_minors, era), latest_release, cms_depth, member_of_count. cms_depth is the row's membership depth under the cms root; member_of_count is how many roots include it. A project in no root has neither; a project that is not a cms member has member_of_count alone. count: projects. next_offset is absent on the last page.
| Name | Type | Req | Description |
|---|---|---|---|
| core_minor | string | – | Filter: a core minor in 11.4.x form. Keeps projects where the newest release on some development branch declares support for it. With missing=true, keeps projects with no such branch. |
| era | string | – | Filter: d8plus (Drupal 8+ code) or pre_d8, on any development branch. |
| limit | integer | – | Projects per page, 1 to 100 (default 50). |
| max_depth | null|integer | – | With member_of: drop members further than this many requires away, 1 or more. |
| member_of | string | – | Filter: keep only members of this root project's composer requires walk, for example cms. |
| min_installs | integer | – | Filter: reported install base at or above this. |
| missing | boolean | – | Invert core_minor: keep projects whose development branches do not declare it. |
| offset | integer | – | Skip this many projects in the same ranked order. Pass the previous page's next_offset. |
| security | string | – | Filter: security advisory coverage: covered, not-covered, revoked. |
| type | string | – | Filter: project_module, project_theme, project_distribution, project_general, project_theme_engine, project_translation. |
No output schema declared.
No examples provided.
list_symbol_users Projects using core symbols ~495
List every contrib project using one core symbol, or any symbol in a class of symbols, one row per project, paged, with the matched symbols. lookup_core_symbol answers one symbol with a head of 30. - Pass fqn, or filters: kind, status (deprecated, scheduled_removal, removed), subsystem, removal_in (13.0), deprecated_in (11.4). Example: "top modules still calling a method going away in 13.0" is kind=method, status=scheduled_removal, removal_in=13.0. Filters take public symbols only. - Development branches only, from the evidence rollup as of evidence_built_at. count: projects. symbol_count: matched symbols. symbols_matched: those symbols, up to matched, most used first, each with stamps, projects_using and change_record_nids. - Rows are ordered by installs, occurrences, name. Each row: project, title, installs, branch, branches, symbol_count, occurrences, symbols. symbols: heaviest first, each with fqn, kind, removal_in, occurrences, files and change_record_nids for get_change_record. next_offset is absent on the last page.
| Name | Type | Req | Description |
|---|---|---|---|
| deprecated_in | string | – | Filter: symbols deprecated in this core minor (11.4). |
| fqn | string | – | One core symbol, as lookup_core_symbol takes it. Pass this or a filter. |
| kind | string | – | Filter: one symbol kind (function, method, class, library, hook, service …). |
| limit | integer | – | Projects per page, 1 to 100 (default 50). |
| matched | integer | – | Matched symbols listed on the envelope, 1 to 50 (default 20). |
| offset | integer | – | Skip this many projects. Pass the previous next_offset. |
| removal_in | string | – | Filter: removal stamp in this core minor (13.0). With status=scheduled_removal: still present, going away then. |
| status | string | – | Filter: deprecated | scheduled_removal (still present) | removed (gone). |
| subsystem | string | – | Filter: a core subsystem (Entity API, Views), case-insensitive. subsystem_coupling with no arguments lists them. |
| symbols | integer | – | Symbols per project row, 1 to 30 (default 10), heaviest first. |
No output schema declared.
No examples provided.
lookup_core_symbol One core symbol: status and users ~528
Answer "is this core symbol safe to use, and who still uses it" for one symbol. A name that resolves to nothing returns the catalog entries containing it instead. Every user in pages: list_symbol_users. Changed between versions: what_changed. Code text: search_code. - fqn forms: a namespaced name with or without the leading backslash, a bare function or constant name, a prefixed pseudo-symbol, or a fragment. Pseudo-symbols: fn:check_markup, core:hook:preprocess_page, core:library:claro/drupal.shortcut. Fragments: fromRoute, EntityInterface. - Resolved (found true): symbol, with status flags. removed: gone. scheduled_removal: still present, @deprecated gives the removal version. deprecated, internal. placeholder: a catalog row no scanner located. audience: contrib, test_support, test or theme. usage: contrib development branches only, from the evidence rollup as of evidence_built_at. It has projects and branches counts, plus top_projects (≤ 30) by install base. change_records: records that touched the symbol, each with nid for get_change_record. - Not resolved (found false): count: catalog entries containing the fragment, case-insensitive, public symbols only; kind narrows. candidates: a head of up to candidates entries, each with fqn, kind, subsystem, stamps, projects_using, change_record_nids. Entries starting with the fragment come first, then by projects_using. Call again with one fqn.
| Name | Type | Req | Description |
|---|---|---|---|
| candidates | integer | – | When the name resolves to no symbol: how many catalog entries containing it to return, 1 to 50 (default 10). |
| fqn | string | yes | Core symbol name, or part of one. A namespaced name with or without the leading backslash (Drupal\Core\Entity\EntityInterface, Drupal\Core\Recipe\RecipeRunner::installModule). A bare function or cons… |
| kind | string | – | Restrict candidates to one symbol kind (class, method, function, hook, library, service …). |
| top_projects | integer | – | How many using projects to return in the ranked head. Defaults to 10, capped at 30. |
No output schema declared.
No examples provided.
project_profile Project profile ~611
Answer "what is this contrib project, how big is it, which core versions does it support, what moves with it" for one drupal.org project. Pending change records: project_upgrade_report. Core symbols it calls: list_symbol_users. - project: title, type, status, security, installs. installs_by_version: install base per contrib version. - dev_branches: each scanned development branch, with installs, core_constraint, core_minors, latest commit date and era. core_constraint: the composer constraint of the newest release on that line, as drupal.org publishes it. The unreleased tip is excluded. core_minors: the minors it admits; a minor counts when any patch satisfies. latest_core_minor: the newest admitted. - releases: newest first, up to releases, each with core_compatibility and security. release_count, supported_branches. missing_sections: what the bundle could not fill. - related (summary): requires and required_by counts with the top 3, co_installed top 3 or a note, delta_12m per release line ("*" is the total). - member_of: how many roots pull this project in (count), and up to 10 {root, depth}, shallowest and alphabetical first. - include=["related"]: related becomes the full report. requires: every dependency, via info_yml or composer, core modules left out. required_by: paged by installs, with count and next_offset; page with dependents and dependents_offset. co_installed: rho, rank, method residual_spearman, or a note. - include=["trend"]: trend has months (oldest first), series per release_line aligned with months (null: no count, "*": total), and lines. Each line: installs_now, share, delta_3m, delta_12m, delta_36m, peak, first_seen, last_seen. Counts are drupal.org month-end installs. - Unknown project: error. An included section refuses when the bundle predates its view.
| Name | Type | Req | Description |
|---|---|---|---|
| dependents | integer | – | With include related: dependents per page in required_by, 1 to 100 (default 20). |
| dependents_offset | integer | – | With include related: dependents to skip. Pass required_by.next_offset from the previous call. |
| include | null|array | – | Optional sections: trend (monthly install series per release line) and related (full requires / required_by / co_installed lists, replacing the related summary). |
| months | integer | – | With include trend: months of history, 1 to 120 (default 36), ending at the latest month in the data. |
| project | string | yes | drupal.org project machine name, e.g. webform. The composer name drupal/webform is accepted. |
| releases | integer | – | Releases to list, newest first, 1 to 30 (default 10). release_count says how many exist. |
No output schema declared.
No examples provided.
project_upgrade_report Project upgrade readiness ~363
Answer "is this contrib project ready for a target core version, and what work is left". For one record's detail, use get_change_record. For a symbol's users, use list_symbol_users. - A record applies when it targets the target version or earlier, and a development branch of the project matched one of its tracks. - Verdict per record: outstanding (a branch still calls the going-away side), in_progress (some branches moved), adopted (all moved). - Returns counts by verdict, then a ranked head of outstanding records with file and line evidence from the project's own code. - Each entry has the count of other projects outstanding on the same record, and its nid for get_change_record. - removed_symbols: core symbols removed by the target, or scheduled for removal at or before it, that the project's development branches still reference. Each has occurrences, files, and the replacement when the catalog lists one. They need no change record: a class moved to another module, a service dropped. removed_symbol_count: the whole set. The head is newest removal first, then by occurrences. Test and test-support symbols are left out.
| Name | Type | Req | Description |
|---|---|---|---|
| limit | integer | – | Outstanding records to return with evidence, 1 to 15 (default 8). Above the cap the call is refused. |
| project | string | yes | Contrib project machine name as it appears on drupal.org, for example webform. The composer name drupal/webform is accepted. Packages from other vendors are not in the dataset. |
| target_version | string | yes | Target core version: 11.2, 11.2.x, 11.2.0, 11, or 11.x. A bare major (11) covers every minor of it. |
No output schema declared.
No examples provided.
query_dataset Run SQL over the dataset ~472
Run read-only DuckDB SELECTs over the dataset behind the other tools, for a question none of them asks. Call describe_dataset first; it lists the 36 views, their columns, joins and recipes. Prefer a typed tool when one fits. - statements=[…]: up to 5 statements in one call, one result or error each. - Result: columns, and rows as arrays, up to max_rows (≤ 500, default 100) and 16 KB. When truncated is true: aggregate, filter, or use LIMIT and OFFSET. One SELECT (or SHOW, DESCRIBE, FROM-first), no semicolon, 15 s limit, nothing outside the bundle. - Dev-branch isolation: JOIN contrib_branch and filter kind = 'dev_branch' AND project <> 'drupal' before counting projects. change_record_adoption, symbol_usage and core_symbol_evidence hold release tags too. core_symbol_evidence is the full rollup; symbol_usage is its string-scan subset. - Adoption polarity: legacy is still on the old API (not adopted); migrated is adopted. Versions are text: compare *_seq integers (major*1000+minor). Never SUM(usage) across branch rows. - Errors list the views, the columns of the views you used, or the join map. An empty result over an fqn without a leading backslash gets a hint. - The same views are downloadable as parquet under https://api.tresbien.tech/data/docs. Its cookbook targets api.duckdb plus prelude views this mirror does not have, so take recipes from describe_dataset.
| Name | Type | Req | Description |
|---|---|---|---|
| max_rows | integer | – | Rows to return per statement, 1 to 500 (default 100). The result byte budget may cut a wide result sooner. truncated says so either way. |
| sql | string | – | One DuckDB SELECT over the views describe_dataset lists. SHOW TABLES, DESCRIBE <view> and FROM-first syntax also work. No semicolon, one statement. Use statements for several at once. |
| statements | null|array | – | Up to 5 statements in one call. Results come back in order under results, each with its own rows or error. The byte budget is shared. Use this instead of sql for more than one statement. |
No output schema declared.
No examples provided.
reroll_patch Re-roll one patch against a release ~1,283
Re-roll one composer patch that check_patches reported conflicts or fuzzy: a new diff that applies to the installed release. Call check_patches first for the whole list. Call this once per patch that came back conflicts or fuzzy. - Input: project, version, patch, title, base. patch is the diff text; this service downloads nothing, so fetch a URL patch yourself and send what came back. base is the release the site had before the upgrade. One patch per call. A hand-made patch without index lines is merged from base when it applies there, else from the newest tag it applies to. reroll.base is the tag used. - drop_tests: leave it out and the re-roll drops every file the release package omits. false keeps every hunk, for a site installed from source. reroll.dropped_paths lists what went. - reroll.verified true: the service already ran the check. reroll.verified_by: the command, the -p level and the tag. Write reroll.patch to the patch file and move on. Do not run git apply --check or patch --dry-run. Do not diff against a copy of the release. composer install is the test. - After a conflicts result, send the same project, version and patch again with resolutions, one per region of reroll.conflicts[].hunks. A resolution is {file, region, choice: release|patch}, {file, region, text}, or {file, region, delete: true}. The service re-merges with your decisions and apply-checks the diff. What comes back is the finished patch file: write it and run composer install. Do not read the release files, edit the patch by hand, or dry-run it. - reroll.status clean: every file merged, or GNU patch applied every hunk, and the diff apply-checked against the release, reroll.verified true. Write reroll.patch as the new patch file; no re-test needed. An empty reroll.patch with reroll.note means the release already has the change; suggested is merged. - reroll.status conflicts: reroll.patch holds the hunks that merged cleanly, apply-checked when reroll.verified is true. Each file in reroll.c…
| Name | Type | Req | Description |
|---|---|---|---|
| base | string | – | Optional. The release the site had before the upgrade. Its commit sha from composer.lock (source.reference), or its composer version: 6.1.0 when version is 6.2.0. A patch without index lines is merge… |
| drop_tests | null|boolean | – | Optional. Leave it out and the re-roll drops every file the release package omits, read from the release's own archive. false keeps every hunk, for a site installed from source. |
| patch | string | yes | Unified diff text. This service downloads nothing, so fetch a URL patch yourself and send what came back. With the index lines git diff writes, it is merged onto the release. Without them (hand-made)… |
| project | string | yes | drupal.org machine name (webform) or composer name (drupal/webform); drupal or core for Drupal core. |
| resolutions | null|array | – | Decisions for the conflicted regions of a previous call on the same project, version and patch, one entry per region. region: the index in that file's conflicts[].hunks. {file, region, choice}: choic… |
| target_core | string | – | Core the added code is checked against: a minor (11.4 or 11.4.x) or a release (11.4.5). A minor with no core release in the data is refused, and so is a major alone. latest checks no references. Defa… |
| title | string | – | Optional, echoed back. |
| version | string | yes | The composer version installed, e.g. 1.13.0 or 11.4.5. |
No output schema declared.
No examples provided.
scan_composer Scan a site's composer files for a core upgrade ~1,281
Which of a site's drupal/* packages need a new release for a target core, and which have none? Send composer.lock and composer.json once; do not query one package at a time. The answer is the release scan for every package, plus extra.patches as check_patches items. Constraints are read by composer's own semver library. - composer_lock: the whole file, or its path to get the upload command. A real lock does not fit a call. With the path, the files go from disk to the api by curl and only the plan comes back. composer_json: adds constraints and extra.patches. patches_file and patches_lock: the two documents a site on cweagans/composer-patches 2.x keeps its patches in, since such a site declares none under extra.patches. Sent as text with a lock path, the command lists every patch to send. target_core: 11.4, 11.4.5, or latest for the newest core the site's constraint allows. Without patches, target_from holds the package whose constraint decided latest. When the site requires no core package, latest is the installed core and target_from says so. Empty scans against the installed core (target_is_installed): what can be updated without a core upgrade. - installed_unknown: the release data does not have the installed version; the row offers no older release. installed_from_tag: the project's git tag answered instead. Neither is a finding about the site. - A sub-module has no releases of its own; drupal.org packages it as a metapackage built from its project's release. Its row says submodule_of and has that project's answer. The lock's type, require and extra.drupal.datestamp fields pair a metapackage with its project. - rows, problems first. no_release: no published release supports the target; latest_any and dev_branch say what exists. update: a compatible release the site does not have; latest, latest_core. unknown: not a drupal.org project in the bundle; note says where its releases are. current: installed_supports and nothing newer needed; such a row has package, in…
| Name | Type | Req | Description |
|---|---|---|---|
| composer_json | string | – | The contents of composer.json (require, require-dev, extra.patches). Send the text; this server cannot read your filesystem. Optional; without it there are no constraints and no patches. |
| composer_lock | string | yes | The text of composer.lock. A real lock is too big to paste: send its path (composer.lock) instead. The answer is then the curl command that uploads the files from the site root. |
| installed_core | object | – | What each installed release requires of core, keyed by composer name. Read it from the site's own vendor directory: composer show -f json <pkg>, or the drupal/core entry of its composer.json. Send it… |
| patch_files | object | – | The text of every patch the site declares, keyed by the source as written: a path (patches/x.patch) or its base name, or the URL. Only needed with patches:true. Fetch a URL patch yourself and send it… |
| patches | boolean | – | Judge the site's patches in the same call: each one against the release its package would install for target_core. Returns a verdict per patch instead of items to check yourself. |
| patches_file | string | – | The text of the patches file, for a site on cweagans/composer-patches 2.x that keeps its patches out of composer.json. The path is in its own extra.composer-patches.patches-file, patches.json by defa… |
| patches_lock | string | – | The text of patches.lock.json, which 2.x of the patch manager writes and applies from. Send it to judge what the site actually applies: it answers alone, over extra.patches and the patches file. |
| target_core | string | – | Core to move to: a minor (11.4), a release (11.4.5), or latest for the newest core the site's own constraint allows. Leave empty to scan against the core the site already runs: which packages have a… |
No output schema declared.
No examples provided.
search_code Search contrib and core code ~444
Search the source of every indexed contrib project, plus core, for a code pattern: which files, or with by_repo which projects. Who-uses-a-core-symbol counts: list_symbol_users or lookup_core_symbol. - query is a regex. Set literal for exact text with ( [ ] . $ : or a space, and put r: f: lang: case: sym: b: terms in filters. repos: project machine name list. The index runs RE2, which has no lookaround or backreferences. - .module, .install, .theme, .engine, .profile and .inc count as PHP: lang:php includes them and sym: resolves inside them. No language filter is applied for you. - Returns total_matches and total_files plus a head of files (repo, path, matching lines), limit ≤ 50. by_repo: (repo, file_count) rows from a pull of up to 1000 files; total_files is the ceiling; truncated when cut. A parse error returns the index's own message. - not_indexed: the repos the index lacks. A project with no installs and no recent release is not indexed.
| Name | Type | Req | Description |
|---|---|---|---|
| by_repo | boolean | – | Return repos as (repo, file_count) instead of files. Pulls up to 1000 files; total_files is the ceiling. |
| filters | string | – | Zoekt filters appended as written: r:<repo regex> f:<path regex> lang:<language> b:<branch> sym:<symbol> case:yes. |
| limit | integer | – | Files to return, default 20, cap 50. Ignored with by_repo. |
| literal | boolean | – | true: query is matched as exact text. Use it for text with ( [ ] $ . such as #[Hook(. With literal, filters go in filters. |
| query | string | yes | Code to find, a regex unless literal is true. Filters may be inline when literal is false, else in filters. Example: hook_form_alter f:\.module$ |
| repos | null|array | – | Restrict to these projects, by machine name, in one query. |
No output schema declared.
No examples provided.
subsystem_coupling Subsystem co-failure graph ~397
Answer "what else tends to fail when a merge request touches this core subsystem" from CI history over about 9,000 core merge requests. With issue_nid: "which subsystems does this issue touch, and what co-fails with them". No arguments: the list of subsystems, the same one core_symbol.subsystem and list_symbol_users subsystem= use. - subsystem: a name (Views, case-insensitive) or a bucket (module:views, core_lib:Entity). An unknown one is refused, with the nearest matches. - Edge: touched_bucket → failing_bucket (+ subsystem), lift, co_fail_count, touched_count, failed_count, total_mrs. lift = P(fail | touched) − P(fail | any MR). Self edges are left out. - Floors min_lift (0.05) and min_co_fail (3) drop noise. count: edges above them. edges: up to limit (≤ 50), by lift. When nothing clears the floors, the strongest edges are listed with a note. - issue_nid: touched_subsystems first. A note explains an issue with no MR file data.
| Name | Type | Req | Description |
|---|---|---|---|
| issue_nid | integer | – | A drupal.org core issue nid: reports the subsystems its merge request touches, then the coupling edges from each. |
| limit | integer | – | Edges to return, 1 to 50 (default 20). count says how many pass the floors. |
| min_co_fail | integer | – | Keep edges seen in at least this many merge requests (default 3). |
| min_lift | number | – | Keep edges with lift at or above this (default 0.05). |
| subsystem | string | – | A core subsystem (Views, Entity API) or a path bucket (module:views, core_lib:Entity). Leave both subsystem and issue_nid empty to get the list of subsystems. |
No output schema declared.
No examples provided.
what_changed Core API diff between versions ~742
Answer "what changed in the core API between two core versions": symbols added, deprecated and removed, as ranked groups with counts. One symbol: lookup_core_symbol. Human write-ups: list_change_records. Every row of one bucket: flat=true with bucket, paged. Every row of the whole diff: the result's bulk block, with attach and sql for the published catalog. Write those rows to a file, so they stay out of the context window. - Bounds are inclusive. Forms: 11.2, 11.2.x, 11.2.0, 11, 11.x. The same version twice is one minor. Upgrading 11.2 → 11.4 means from=11.3. Buckets are independent. - Grouped (default): a head entry is a symbol group; grouped_by is change_record, name_prefix or singleton. head: groups, up to 5. count: symbols. group_count: groups. members: up to 3 per group, highest usage first. Group fields appear only when every member agrees. Rank: max_projects_using desc, then member_count magnitude, tier, count, key; ranked_by states it. When head_covers_all_callers is false, narrow with kind or min_projects_using, or page with offset. - Flat (flat=true, bucket=added, deprecated, removed): rows by projects_using then fqn. Each row: fqn, kind, subsystem, stamp, projects_using, removal_in, removal_kind, replacement when the catalog lists one, change_record_nids. count: public symbols in the bucket after filters. limit ≤ 100. next_offset is absent on the last page. - Filters apply to every count. internal_excluded and test_theme_excluded are counted apart and left out. unplaceable_symbols have no minor in their stamp. - Usage: contrib development branches only, from the evidence rollup as of usage_evidence_built_at. 0 means no caller observed. - change_record_nids: for get_change_record. removal_kind observed: gone. removal_kind scheduled: promised and still present; say "scheduled for removal in 13.0".
| Name | Type | Req | Description |
|---|---|---|---|
| bucket | string | – | With flat: which side of the diff to list, added, deprecated, or removed. One bucket per call. |
| flat | boolean | – | true: one bucket as flat symbol rows, paged, instead of three buckets of ranked groups. Needs bucket. |
| from | string | yes | Lower core version bound, inclusive: 11.2, 11.2.x, 11.2.0, 11, 11.x. Upgrading from 11.2 means from=11.3. |
| head | integer | – | Groups per bucket, 1 to 5 (default 5). Ignored when flat is true. |
| kind | string | – | Restrict to one symbol kind (method, class, function, hook, service, library …). Applies to counts too. |
| limit | integer | – | With flat: rows per page, 1 to 100 (default 50). A page of very long fqns may come back shorter. next_offset always says where the next page starts. |
| min_projects_using | integer | – | Drop symbols fewer than this many contrib projects call on a development branch. Applies to counts too. |
| offset | integer | – | Skip this many groups per bucket (grouped) or rows (flat), in ranked order. Flat: pass the previous page's next_offset. |
| to | string | yes | Upper bound, inclusive, same forms. |
No output schema declared.
No examples provided.
wordpal_theme WordPress theme conversion status ~567
Answer "does this WordPress block theme convert to Drupal with WordPal". The WordPal gallery converts every block theme on wordpress.org each night. With slug: one theme and its routes. Without slug: counts by status and the most installed themes. - version: the theme version wordpress.org lists now. run: the run the gallery shows. run.theme_version is the version it converted, which can be older. - run.status (exact, diff, failed) is a verdict on the home page only. exact: its markup has no difference and its screenshot matches the WordPress screenshot. diff: the markup differs, the screenshots differ, or the two pages could not be compared. failed: no pair of home page screenshots, as when the conversion fails. - Filters combine: status (run.status), tag, q. count: themes that pass all three. by_status: themes that pass tag and q, per status. - Row: slug, name, installs, version, and run with status, routes_measured, routes_matching, markup_diffs_total. Up to eight pages are compared per theme. markup_diffs_total sums their markup differences. - theme: the row, plus author, tags and page_url. Its run adds plugins to install first, convert_command, reason when failed, wordpal_release and image links. - run.routes: route, markup_outcome (match, diff, skipped, error) and markup_diffs. A markup difference is an element, a class, an attribute or an inline style that differs. - A route whose screenshots were compared also has visual_outcome (match, diff, unstable, error), visual_bands, visual_changed, wp_height and drupal_height. - wp_only_rows and drupal_only_rows: pixel rows that one screenshot alone has. visual_bands and visual_changed count the rows both screenshots have. - history: every run the gallery has shown for the theme, newest first, home page only. direction (improved, regressed, same, changed) compares a run with the run before. - next_offset is absent on the last page.
| Name | Type | Req | Description |
|---|---|---|---|
| limit | integer | – | Themes to return, 1 to 50 (default 20). |
| offset | integer | – | Skip this many themes in the same ranked order. Pass the previous page's next_offset. |
| q | string | – | Filter: part of a slug or of a theme name, in any case. |
| slug | string | – | A wordpress.org theme slug, for example twentytwentyfive. Returns that theme and its routes. The filters do not apply. |
| status | string | – | Filter: exact, diff or failed. |
| tag | string | – | Filter: a wordpress.org tag slug, for example blog. |
No output schema declared.
No examples provided.
How do I install the Drupal Code Query MCP server?
Drupal Code Query is a hosted endpoint at https://mcp.tresbien.tech/mcp, so there is nothing to install locally. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.
remote · mcp.tresbien.tech
claude mcp add --transport http tech-tresbien-drupal-code-query 'https://mcp.tresbien.tech/mcp'
What is the Drupal Code Query MCP server?
Drupal Code Query is an MCP server listed in the public MCP registry as tech.tresbien/drupal-code-query. Drupal core API changes, contrib usage, upgrade checks, patches, code search, SQL, WordPal themes. This page covers its hosted endpoint (https://mcp.tresbien.tech/mcp).
Is the Drupal Code Query MCP server safe to use?
Drupal Code Query scores 82 out of 100 on VerifyMCP. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.
What tools does the Drupal Code Query MCP server expose?
Drupal Code Query exposes 17 tools: check_patches, describe_dataset, get_change_record, list_change_records, list_class_relations, and 12 more. Their descriptions and schemas cost roughly 10,168 tokens of context every time the server is loaded.
Does the Drupal Code Query MCP server require authentication?
No. We connected to Drupal Code Query without credentials and it answered, so anything it exposes is reachable by anyone who knows the address.
Is the Drupal Code Query MCP server still maintained?
Drupal Code Query is still listed as active in the MCP registry. We last reached this channel on 5 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.