magector 2.3.1 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +5 -5
- package/src/mcp-server.js +183 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "magector",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"description": "Semantic code search for Magento 2 — index, search, MCP server",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/mcp-server.js",
|
|
@@ -33,10 +33,10 @@
|
|
|
33
33
|
"ruvector": "^0.1.96"
|
|
34
34
|
},
|
|
35
35
|
"optionalDependencies": {
|
|
36
|
-
"@magector/cli-darwin-arm64": "2.
|
|
37
|
-
"@magector/cli-linux-x64": "2.
|
|
38
|
-
"@magector/cli-linux-arm64": "2.
|
|
39
|
-
"@magector/cli-win32-x64": "2.
|
|
36
|
+
"@magector/cli-darwin-arm64": "2.4.0",
|
|
37
|
+
"@magector/cli-linux-x64": "2.4.0",
|
|
38
|
+
"@magector/cli-linux-arm64": "2.4.0",
|
|
39
|
+
"@magector/cli-win32-x64": "2.4.0"
|
|
40
40
|
},
|
|
41
41
|
"keywords": [
|
|
42
42
|
"magento",
|
package/src/mcp-server.js
CHANGED
|
@@ -32,6 +32,8 @@ import {
|
|
|
32
32
|
} from 'ruvector/dist/analysis/complexity.js';
|
|
33
33
|
import { resolveBinary } from './binary.js';
|
|
34
34
|
import { resolveModels } from './model.js';
|
|
35
|
+
import { createRequire } from 'module';
|
|
36
|
+
const __pkg = createRequire(import.meta.url)('../package.json');
|
|
35
37
|
|
|
36
38
|
const config = {
|
|
37
39
|
dbPath: process.env.MAGECTOR_DB || './.magector/index.db',
|
|
@@ -2816,7 +2818,7 @@ async function traceCallChain(startClass, startMethod, maxDepth = 3) {
|
|
|
2816
2818
|
const server = new Server(
|
|
2817
2819
|
{
|
|
2818
2820
|
name: 'magector',
|
|
2819
|
-
version:
|
|
2821
|
+
version: __pkg.version
|
|
2820
2822
|
},
|
|
2821
2823
|
{
|
|
2822
2824
|
capabilities: {
|
|
@@ -3086,7 +3088,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
3086
3088
|
},
|
|
3087
3089
|
{
|
|
3088
3090
|
name: 'magento_find_db_schema',
|
|
3089
|
-
description: 'Find database table definitions, columns, indexes, and constraints declared in db_schema.xml (Magento declarative schema). See also:
|
|
3091
|
+
description: 'Find database table definitions, columns, indexes, and constraints declared in db_schema.xml (Magento declarative schema) AND legacy Setup scripts (InstallSchema, UpgradeSchema). Covers both modern declarative schema and legacy $setup->newTable() / addColumn() table definitions. See also: magento_find_trigger (DB triggers), magento_find_table_usage (cross-module table references).',
|
|
3090
3092
|
inputSchema: {
|
|
3091
3093
|
type: 'object',
|
|
3092
3094
|
properties: {
|
|
@@ -3098,6 +3100,37 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
3098
3100
|
required: ['tableName']
|
|
3099
3101
|
}
|
|
3100
3102
|
},
|
|
3103
|
+
{
|
|
3104
|
+
name: 'magento_find_trigger',
|
|
3105
|
+
description: 'Find MySQL database trigger definitions in Magento Setup scripts. Detects triggers created via TriggerFactory (setName, setTable, setEvent, setTime, addStatement, createTrigger). Returns trigger name, target table, event type (INSERT/UPDATE/DELETE), timing (BEFORE/AFTER), and SQL statements. Use when investigating DB-level automation, trigger chains, or performance issues caused by cascading triggers.',
|
|
3106
|
+
inputSchema: {
|
|
3107
|
+
type: 'object',
|
|
3108
|
+
properties: {
|
|
3109
|
+
triggerName: {
|
|
3110
|
+
type: 'string',
|
|
3111
|
+
description: 'Optional trigger name or pattern to search for. If omitted, finds all triggers in the codebase.'
|
|
3112
|
+
},
|
|
3113
|
+
tableName: {
|
|
3114
|
+
type: 'string',
|
|
3115
|
+
description: 'Optional table name to find triggers targeting this table.'
|
|
3116
|
+
}
|
|
3117
|
+
}
|
|
3118
|
+
}
|
|
3119
|
+
},
|
|
3120
|
+
{
|
|
3121
|
+
name: 'magento_find_table_usage',
|
|
3122
|
+
description: 'Find all code that references a database table — across db_schema.xml, Setup scripts (InstallSchema/UpgradeSchema), raw SQL (Zend_Db_Expr, $connection->query), getTable() calls, and resource model definitions. Builds a cross-module dependency map showing who reads/writes/creates a given table. Essential for impact analysis of schema changes.',
|
|
3123
|
+
inputSchema: {
|
|
3124
|
+
type: 'object',
|
|
3125
|
+
properties: {
|
|
3126
|
+
tableName: {
|
|
3127
|
+
type: 'string',
|
|
3128
|
+
description: 'Database table name to find all references for. Examples: "salesrule_ordered", "catalog_product_entity", "quote_item"'
|
|
3129
|
+
}
|
|
3130
|
+
},
|
|
3131
|
+
required: ['tableName']
|
|
3132
|
+
}
|
|
3133
|
+
},
|
|
3101
3134
|
{
|
|
3102
3135
|
name: 'magento_module_structure',
|
|
3103
3136
|
description: 'Get the complete structure of a Magento module — lists all controllers, models, blocks, plugins, observers, API classes, XML configs, and templates. Provides an overview of module architecture.',
|
|
@@ -3807,17 +3840,160 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
3807
3840
|
}
|
|
3808
3841
|
|
|
3809
3842
|
case 'magento_find_db_schema': {
|
|
3810
|
-
|
|
3811
|
-
const
|
|
3812
|
-
|
|
3843
|
+
// Search both declarative schema (db_schema.xml) and legacy Setup scripts
|
|
3844
|
+
const declQuery = `db_schema.xml table ${args.tableName} column declarative schema`;
|
|
3845
|
+
const legacyQuery = `create_table ${args.tableName} legacy_schema table_created ${args.tableName} setup install schema newTable addColumn`;
|
|
3846
|
+
const [declRaw, legacyRaw] = await Promise.all([
|
|
3847
|
+
rustSearchAsync(declQuery, 40),
|
|
3848
|
+
rustSearchAsync(legacyQuery, 30)
|
|
3849
|
+
]);
|
|
3850
|
+
|
|
3851
|
+
let declResults = declRaw.map(normalizeResult).filter(r =>
|
|
3813
3852
|
r.path?.includes('db_schema.xml')
|
|
3814
3853
|
);
|
|
3815
|
-
|
|
3854
|
+
declResults = rerank(declResults, { fileType: 'xml', pathContains: ['db_schema.xml'] });
|
|
3855
|
+
|
|
3856
|
+
let legacyResults = legacyRaw.map(normalizeResult).filter(r => {
|
|
3857
|
+
const p = r.path || '';
|
|
3858
|
+
return (p.includes('/Setup/') || p.includes('InstallSchema') ||
|
|
3859
|
+
p.includes('UpgradeSchema') || p.includes('/Patch/')) &&
|
|
3860
|
+
(r.snippet?.toLowerCase().includes(args.tableName.toLowerCase()) ||
|
|
3861
|
+
r.searchText?.toLowerCase().includes(args.tableName.toLowerCase()));
|
|
3862
|
+
});
|
|
3863
|
+
|
|
3864
|
+
// Deduplicate by path
|
|
3865
|
+
const seen = new Set(declResults.map(r => r.path));
|
|
3866
|
+
for (const r of legacyResults) {
|
|
3867
|
+
if (!seen.has(r.path)) {
|
|
3868
|
+
seen.add(r.path);
|
|
3869
|
+
declResults.push(r);
|
|
3870
|
+
}
|
|
3871
|
+
}
|
|
3872
|
+
|
|
3873
|
+
// Add section headers
|
|
3874
|
+
let output = '';
|
|
3875
|
+
const xmlResults = declResults.filter(r => r.path?.includes('db_schema.xml'));
|
|
3876
|
+
const setupResults = declResults.filter(r => !r.path?.includes('db_schema.xml'));
|
|
3877
|
+
|
|
3878
|
+
if (xmlResults.length > 0) {
|
|
3879
|
+
output += formatSearchResults(xmlResults.slice(0, 10));
|
|
3880
|
+
}
|
|
3881
|
+
if (setupResults.length > 0) {
|
|
3882
|
+
output += `\n\n### Legacy Setup Scripts (InstallSchema/UpgradeSchema)\n`;
|
|
3883
|
+
output += formatSearchResults(setupResults.slice(0, 10));
|
|
3884
|
+
}
|
|
3816
3885
|
|
|
3817
3886
|
return {
|
|
3818
3887
|
content: [{
|
|
3819
3888
|
type: 'text',
|
|
3820
|
-
text: formatSearchResults(
|
|
3889
|
+
text: output || formatSearchResults([])
|
|
3890
|
+
}]
|
|
3891
|
+
};
|
|
3892
|
+
}
|
|
3893
|
+
|
|
3894
|
+
case 'magento_find_trigger': {
|
|
3895
|
+
// Search for DB trigger definitions in Setup scripts
|
|
3896
|
+
const triggerTerm = args.triggerName || args.tableName || '';
|
|
3897
|
+
const query = `db_trigger create_trigger sql_trigger TriggerFactory createTrigger setName setEvent ${triggerTerm} setup database_trigger trigger`;
|
|
3898
|
+
const raw = await rustSearchAsync(query, 50);
|
|
3899
|
+
let results = raw.map(normalizeResult).filter(r => {
|
|
3900
|
+
const p = r.path || '';
|
|
3901
|
+
const s = (r.searchText || '') + ' ' + (r.snippet || '');
|
|
3902
|
+
// Must be a Setup file that contains trigger-related terms
|
|
3903
|
+
return (p.includes('/Setup/') || p.includes('InstallSchema') ||
|
|
3904
|
+
p.includes('UpgradeSchema') || p.includes('/Patch/')) &&
|
|
3905
|
+
(s.toLowerCase().includes('trigger') || s.includes('db_trigger') || s.includes('create_trigger'));
|
|
3906
|
+
});
|
|
3907
|
+
|
|
3908
|
+
// If searching for specific trigger/table, filter further
|
|
3909
|
+
if (triggerTerm) {
|
|
3910
|
+
const term = triggerTerm.toLowerCase();
|
|
3911
|
+
const filtered = results.filter(r => {
|
|
3912
|
+
const s = ((r.searchText || '') + ' ' + (r.snippet || '')).toLowerCase();
|
|
3913
|
+
return s.includes(term);
|
|
3914
|
+
});
|
|
3915
|
+
if (filtered.length > 0) results = filtered;
|
|
3916
|
+
}
|
|
3917
|
+
|
|
3918
|
+
results = rerank(results, { pathContains: ['/Setup/', 'UpgradeSchema', 'InstallSchema'] });
|
|
3919
|
+
|
|
3920
|
+
return {
|
|
3921
|
+
content: [{
|
|
3922
|
+
type: 'text',
|
|
3923
|
+
text: results.length > 0
|
|
3924
|
+
? `### DB Trigger Definitions\n\n` + formatSearchResults(results.slice(0, 15)) +
|
|
3925
|
+
`\n\n**Tip:** Read the matched Setup files to see trigger names, target tables, events (INSERT/UPDATE/DELETE), timing (BEFORE/AFTER), and SQL statements.`
|
|
3926
|
+
: `No database triggers found${triggerTerm ? ` matching "${triggerTerm}"` : ''}. Triggers are defined in Setup scripts using TriggerFactory.`
|
|
3927
|
+
}]
|
|
3928
|
+
};
|
|
3929
|
+
}
|
|
3930
|
+
|
|
3931
|
+
case 'magento_find_table_usage': {
|
|
3932
|
+
const table = args.tableName;
|
|
3933
|
+
// Multi-query strategy: search declarative schema, setup scripts, and inline SQL references
|
|
3934
|
+
const queries = [
|
|
3935
|
+
`table ${table} db_schema.xml declarative schema column`,
|
|
3936
|
+
`sql_table ${table} table_reference ${table} Zend_Db_Expr getTable`,
|
|
3937
|
+
`create_table ${table} legacy_schema setup trigger ${table}`,
|
|
3938
|
+
`${table.replace(/_/g, ' ')} resource model collection`,
|
|
3939
|
+
];
|
|
3940
|
+
|
|
3941
|
+
const rawResults = await Promise.all(queries.map(q => rustSearchAsync(q, 25)));
|
|
3942
|
+
const allResults = rawResults.flat().map(normalizeResult);
|
|
3943
|
+
|
|
3944
|
+
// Deduplicate by path
|
|
3945
|
+
const pathMap = new Map();
|
|
3946
|
+
for (const r of allResults) {
|
|
3947
|
+
if (!r.path) continue;
|
|
3948
|
+
const s = ((r.searchText || '') + ' ' + (r.snippet || '')).toLowerCase();
|
|
3949
|
+
if (s.includes(table.toLowerCase()) || r.path.includes('db_schema.xml')) {
|
|
3950
|
+
if (!pathMap.has(r.path) || (r.score || 0) > (pathMap.get(r.path).score || 0)) {
|
|
3951
|
+
pathMap.set(r.path, r);
|
|
3952
|
+
}
|
|
3953
|
+
}
|
|
3954
|
+
}
|
|
3955
|
+
const unique = Array.from(pathMap.values());
|
|
3956
|
+
|
|
3957
|
+
// Categorize results
|
|
3958
|
+
const categories = {
|
|
3959
|
+
'Declarative Schema (db_schema.xml)': unique.filter(r => r.path?.includes('db_schema.xml')),
|
|
3960
|
+
'Setup Scripts (InstallSchema/UpgradeSchema/Patch)': unique.filter(r => {
|
|
3961
|
+
const p = r.path || '';
|
|
3962
|
+
return !p.includes('db_schema.xml') &&
|
|
3963
|
+
(p.includes('/Setup/') || p.includes('InstallSchema') ||
|
|
3964
|
+
p.includes('UpgradeSchema') || p.includes('/Patch/'));
|
|
3965
|
+
}),
|
|
3966
|
+
'PHP Code (raw SQL, getTable, Zend_Db_Expr)': unique.filter(r => {
|
|
3967
|
+
const p = r.path || '';
|
|
3968
|
+
return p.endsWith('.php') && !p.includes('db_schema.xml') &&
|
|
3969
|
+
!p.includes('/Setup/') && !p.includes('InstallSchema') &&
|
|
3970
|
+
!p.includes('UpgradeSchema') && !p.includes('/Patch/');
|
|
3971
|
+
}),
|
|
3972
|
+
'XML Config': unique.filter(r => {
|
|
3973
|
+
const p = r.path || '';
|
|
3974
|
+
return p.endsWith('.xml') && !p.includes('db_schema.xml');
|
|
3975
|
+
}),
|
|
3976
|
+
};
|
|
3977
|
+
|
|
3978
|
+
let output = `### Table Usage: \`${table}\`\n\n`;
|
|
3979
|
+
output += `Found ${unique.length} file(s) referencing this table.\n\n`;
|
|
3980
|
+
|
|
3981
|
+
for (const [category, items] of Object.entries(categories)) {
|
|
3982
|
+
if (items.length > 0) {
|
|
3983
|
+
output += `#### ${category} (${items.length})\n`;
|
|
3984
|
+
output += formatSearchResults(items.slice(0, 8));
|
|
3985
|
+
output += '\n';
|
|
3986
|
+
}
|
|
3987
|
+
}
|
|
3988
|
+
|
|
3989
|
+
if (unique.length === 0) {
|
|
3990
|
+
output += `No references found for table "${table}". Try a broader search with magento_search.`;
|
|
3991
|
+
}
|
|
3992
|
+
|
|
3993
|
+
return {
|
|
3994
|
+
content: [{
|
|
3995
|
+
type: 'text',
|
|
3996
|
+
text: output
|
|
3821
3997
|
}]
|
|
3822
3998
|
};
|
|
3823
3999
|
}
|