aem-mcp-server 1.3.0 → 1.3.2
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/README.md +4 -4
- package/dist/aem/aem.connector.js +1 -1
- package/dist/cli.js +1 -1
- package/dist/utils/logger.js +2 -2
- package/package.json +1 -3
- package/docs/API.md +0 -286
- package/docs/CHANGELOG.md +0 -147
- package/docs/CODE_OF_CONDUCT.md +0 -74
- package/docs/CONTRIBUTING.md +0 -25
- package/docs/cursor.png +0 -0
package/README.md
CHANGED
|
@@ -29,7 +29,7 @@ This project is designed for non-technical persons who want to manage AEM via na
|
|
|
29
29
|
- Access to an AEM instance (local or remote)
|
|
30
30
|
|
|
31
31
|
### Add AEM MCP to AI IDE
|
|
32
|
-
[](https://cursor.com/en/install-mcp?name=
|
|
32
|
+
[](https://cursor.com/en/install-mcp?name=AEM&config=eyJ1cmwiOiJodHRwOi8vMTI3LjAuMC4xOjg1MDIvbWNwIn0%3D)
|
|
33
33
|
|
|
34
34
|
OR:
|
|
35
35
|
|
|
@@ -51,7 +51,7 @@ Options:
|
|
|
51
51
|
-P, --publisher Publisher instance URL [string] [default: "http://localhost:4503"]
|
|
52
52
|
-u, --user Username for authentication [string] [default: "admin"]
|
|
53
53
|
-p, --pass Password for authentication [string] [default: "admin"]
|
|
54
|
-
-m, --mcpPort Port for MCP server [number] [default:
|
|
54
|
+
-m, --mcpPort Port for MCP server [number] [default: 8502]
|
|
55
55
|
-h, --help Show help [boolean]
|
|
56
56
|
|
|
57
57
|
```
|
|
@@ -82,7 +82,7 @@ AEM MCP Server is compatible with modern AI IDEs and code editors that support M
|
|
|
82
82
|
- Open your IDE's MCP server settings.
|
|
83
83
|
- Add a new server with:
|
|
84
84
|
- **Type:** Custom MCP
|
|
85
|
-
- **url:** `http://127.0.0.1:
|
|
85
|
+
- **url:** `http://127.0.0.1:8502/mcp`
|
|
86
86
|
|
|
87
87
|
3. **Restart your IDE** if needed. The IDE will now be able to:
|
|
88
88
|
- List, search, and manage AEM content
|
|
@@ -94,7 +94,7 @@ Sample for AI-based code editors or custom clients:
|
|
|
94
94
|
{
|
|
95
95
|
"mcpServers": {
|
|
96
96
|
"AEM": {
|
|
97
|
-
"url": "http://127.0.0.1:
|
|
97
|
+
"url": "http://127.0.0.1:8502/mcp"
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
100
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{getAEMConfig as P,isValidContentPath as u,isValidLocale as b}from"./aem.config.js";import{AEM_ERROR_CODES as h,createAEMError as d,createSuccessResponse as i,handleAEMHttpError as y,safeExecute as p,validateComponentOperation as w}from"./aem.errors.js";import{AEMFetch as C}from"./aem.fetch.js";import{LOGGER as g}from"../utils/logger.js";export class AEMConnector{isInitialized;isAEMaaCS;config;aemConfig;fetch;constructor(e){this.isInitialized=!1,this.config=this.loadConfig(e),this.aemConfig=P({}),this.isAEMaaCS=this.isConfigAEMaaCS(),this.fetch=new C({host:this.config.aem.host,auth:this.config.aem.auth,timeout:this.aemConfig.queries.timeoutMs})}async init(){try{await this.fetch.init(),this.isInitialized=!0}catch{this.isInitialized=!1}}isConfigAEMaaCS(){return!!(this.config.aem.auth.clientId&&this.config.aem.auth.clientSecret)}loadConfig(e={}){return{aem:{host:e.host||"http://localhost:4502",author:e.host||"http://localhost:4502",publish:"http://localhost:4503",auth:{username:e.user||"admin",password:e.pass||"admin"},endpoints:{content:"/content",dam:"/content/dam",query:"/bin/querybuilder.json",crxde:"/crx/de",jcr:""}},mcp:{name:"NAEM MCP Server",version:"1.0.0"}}}async testConnection(){const e=await this.testAEMConnection(),t=e?await this.testAuthConnection():!1;return{aem:e,auth:t}}async testAEMConnection(){try{this.isInitialized||await this.init(),g.log("Testing AEM connection to:",this.config.aem.host);const e=`${this.config.aem.host}/libs/granite/core/content/login.html`,t=await this.fetch.get(e,{timeout:5e3});return g.log("\u2705 AEM connection successful! Status:",t.status),!0}catch(e){return g.error("\u274C AEM connection failed:",e.message),!1}}async testAuthConnection(){try{this.isInitialized||await this.init();const e=`${this.config.aem.host}/libs/granite/security/content/userinfo.json`;g.log("Testing AEM authentication connection to:",this.config.aem.host);const t=await this.fetch.get(e,{timeout:5e3});return g.log("\u2705 AEM authentication connection successful! Status:",t.status),!0}catch(e){return g.error("\u274C AEM authentication connection failed:",e.message),!1}}async validateComponent(e){return p(async()=>{const t=e.pagePath||e.page_path,{locale:n,component:s,props:a}=e;if(w(n,t,s,a),!b(n,this.aemConfig))throw d(h.INVALID_LOCALE,`Locale '${n}' is not supported`,{locale:n,allowedLocales:this.aemConfig.validation.allowedLocales});if(!u(t,this.aemConfig))throw d(h.INVALID_PATH,`Path '${t}' is not within allowed content roots`,{path:t,allowedRoots:Object.values(this.aemConfig.contentPaths)});const o=`${t}.json`,r=await this.fetch.get(o,{params:{":depth":"2"},timeout:this.aemConfig.queries.timeoutMs}),c=this.validateComponentProps(r.data,s,a);return i({message:"Component validation completed successfully",pageData:r.data,component:s,locale:n,validation:c,configUsed:{allowedLocales:this.aemConfig.validation.allowedLocales}},"validateComponent")},"validateComponent")}validateComponentProps(e,t,n){const s=[],a=[];return t==="text"&&!n.text&&!n.richText&&s.push("Text component should have text or richText property"),t==="image"&&!n.fileReference&&!n.src&&a.push("Image component requires fileReference or src property"),{valid:a.length===0,errors:a,warnings:s,componentType:t,propsValidated:Object.keys(n).length}}async updateComponent(e){return p(async()=>{if(!e.componentPath||typeof e.componentPath!="string")throw d(h.INVALID_PARAMETERS,"Component path is required and must be a string");if(!e.properties||typeof e.properties!="object")throw d(h.INVALID_PARAMETERS,"Properties are required and must be an object");if(!u(e.componentPath,this.aemConfig))throw d(h.INVALID_PATH,`Component path '${e.componentPath}' is not within allowed content roots`,{path:e.componentPath,allowedRoots:Object.values(this.aemConfig.contentPaths)});const t=`${e.componentPath}.json`,n=await this.fetch.get(t);try{await n.json()}catch(r){throw r.response?.status===404?d(h.COMPONENT_NOT_FOUND,`Component not found at path: ${e.componentPath}`,{componentPath:e.componentPath}):y(r,"updateComponent")}const s=new URLSearchParams;Object.entries(e.properties).forEach(([r,c])=>{c==null?s.append(`${r}@Delete`,""):Array.isArray(c)?c.forEach(l=>{s.append(`${r}`,l.toString())}):typeof c=="object"?s.append(r,JSON.stringify(c)):s.append(r,c.toString())});const a=await this.fetch.post(e.componentPath,s),o=await this.fetch.get(`${e.componentPath}.json`);return i({message:"Component updated successfully",path:e.componentPath,properties:e.properties,updatedProperties:o.data,response:a.data,verification:{success:!0,propertiesChanged:Object.keys(e.properties).length,timestamp:new Date().toISOString()}},"updateComponent")},"updateComponent")}async undoChanges(e){return i({message:"undoChanges is not implemented. Please use AEM version history for undo/rollback.",request:e,timestamp:new Date().toISOString()},"undoChanges")}async scanPageComponents(e){return p(async()=>{const t=`${e}.infinity.json`,n=await this.fetch.get(t),s=[],a=(o,r)=>{!o||typeof o!="object"||(o["sling:resourceType"]&&s.push({path:r,resourceType:o["sling:resourceType"],properties:{...o}}),Object.entries(o).forEach(([c,l])=>{if(typeof l=="object"&&l!==null&&!c.startsWith("rep:")&&!c.startsWith("oak:")){const m=r?`${r}/${c}`:c;a(l,m)}}))};return n.data["jcr:content"]?a(n.data["jcr:content"],"jcr:content"):a(n.data,e),i({pagePath:e,components:s,totalComponents:s.length},"scanPageComponents")},"scanPageComponents")}async fetchSites(){return p(async()=>{const t=await this.fetch.get("/content.json",{":depth":"2"}),n=[];return Object.entries(t).forEach(([s,a])=>{s.startsWith("jcr:")||s.startsWith("sling:")||a&&typeof a=="object"&&a["jcr:content"]&&n.push({name:s,path:`/content/${s}`,title:a["jcr:content"]["jcr:title"]||s,template:a["jcr:content"]["cq:template"],lastModified:a["jcr:content"]["cq:lastModified"]})}),i({sites:n,totalCount:n.length},"fetchSites")},"fetchSites")}async fetchLanguageMasters(e){return p(async()=>{const t=`/content/${e}.json`,n=await this.fetch.get(t,{":depth":"3"}),s=[];return Object.entries(n).forEach(([a,o])=>{a.startsWith("jcr:")||a.startsWith("sling:")||o&&typeof o=="object"&&o["jcr:content"]&&s.push({name:a,path:`/content/${a}`,title:o["jcr:content"]["jcr:title"]||a,language:o["jcr:content"]["jcr:language"]||"en"})}),i({site:e,languageMasters:s},"fetchLanguageMasters")},"fetchLanguageMasters")}async fetchAvailableLocales(e,t){return p(async()=>{const n=`${t}.json`,s=await this.fetch.get(n,{":depth":"2"}),a=[];return Object.entries(s).forEach(([o,r])=>{o.startsWith("jcr:")||o.startsWith("sling:")||r&&typeof r=="object"&&a.push({name:o,title:r["jcr:content"]?.["jcr:title"]||o,language:r["jcr:content"]?.["jcr:language"]||o})}),i({site:e,languageMasterPath:t,availableLocales:a},"fetchAvailableLocales")},"fetchAvailableLocales")}async replicateAndPublish(e,t,n){return p(async()=>i({message:"Replication simulated",selectedLocales:e,componentData:t,localizedOverrides:n},"replicateAndPublish"),"replicateAndPublish")}async getAllTextContent(e){return p(async()=>{const t=`${e}.infinity.json`,n=await this.fetch.get(t),s=[],a=(o,r)=>{!o||typeof o!="object"||((o.text||o["jcr:title"]||o["jcr:description"])&&s.push({path:r,title:o["jcr:title"],text:o.text,description:o["jcr:description"]}),Object.entries(o).forEach(([c,l])=>{if(typeof l=="object"&&l!==null&&!c.startsWith("rep:")&&!c.startsWith("oak:")){const m=r?`${r}/${c}`:c;a(l,m)}}))};return n["jcr:content"]?a(n["jcr:content"],"jcr:content"):a(n,e),i({pagePath:e,textContent:s},"getAllTextContent")},"getAllTextContent")}async getPageTextContent(e){return p(async()=>this.getAllTextContent(e),"getPageTextContent")}async getPageImages(e){return p(async()=>{const t=`${e}.infinity.json`,n=await this.fetch.get(t),s=[],a=(o,r)=>{!o||typeof o!="object"||((o.fileReference||o.src)&&s.push({path:r,fileReference:o.fileReference,src:o.src,alt:o.alt||o.altText,title:o["jcr:title"]||o.title}),Object.entries(o).forEach(([c,l])=>{if(typeof l=="object"&&l!==null&&!c.startsWith("rep:")&&!c.startsWith("oak:")){const m=r?`${r}/${c}`:c;a(l,m)}}))};return n["jcr:content"]?a(n["jcr:content"],"jcr:content"):a(n,e),i({pagePath:e,images:s},"getPageImages")},"getPageImages")}async updateImagePath(e,t){return p(async()=>this.updateComponent({componentPath:e,properties:{fileReference:t}}),"updateImagePath")}async getPageContent(e){return p(async()=>{const t=`${e}.infinity.json`,n=await this.fetch.get(t);return i({pagePath:e,content:n},"getPageContent")},"getPageContent")}async listChildren(e,t=1){return p(async()=>{try{const n=await this.fetch.get(`${e}.${t}.json`),s=[];return n&&typeof n=="object"&&Object.entries(n).forEach(([a,o])=>{if(!(a.startsWith("jcr:")||a.startsWith("sling:")||a.startsWith("cq:")||a.startsWith("rep:")||a.startsWith("oak:")||a==="jcr:content")&&o&&typeof o=="object"){const r=`${e}/${a}`;s.push({name:a,path:r,primaryType:o["jcr:primaryType"]||"nt:unstructured",title:o["jcr:content"]?.["jcr:title"]||o["jcr:title"]||a,lastModified:o["jcr:content"]?.["cq:lastModified"]||o["cq:lastModified"],resourceType:o["jcr:content"]?.["sling:resourceType"]||o["sling:resourceType"]})}}),s}catch(n){if(n.response?.status===404||n.response?.status===403)return((await this.fetch.get("/bin/querybuilder.json",{path:e,type:"cq:Page","p.nodedepth":"1","p.limit":"1000","p.hits":"full"})).hits||[]).map(a=>({name:a.name||a.path?.split("/").pop(),path:a.path,primaryType:a["jcr:primaryType"]||"cq:Page",title:a["jcr:content/jcr:title"]||a.title||a.name,lastModified:a["jcr:content/cq:lastModified"],resourceType:a["jcr:content/sling:resourceType"]}));throw n}},"listChildren")}async listPages(e,t=1,n=20){return p(async()=>{try{const s=await this.fetch.get(`${e}.${t}.json`),a=[],o=(r,c,l)=>{l>t||a.length>=n||Object.entries(r).forEach(([m,f])=>{if(!(a.length>=n)&&!(m.startsWith("jcr:")||m.startsWith("sling:")||m.startsWith("cq:")||m.startsWith("rep:")||m.startsWith("oak:"))&&f&&typeof f=="object"){const j=`${c}/${m}`;f["jcr:primaryType"]==="cq:Page"&&a.push({name:m,path:j,primaryType:"cq:Page",title:f["jcr:content"]?.["jcr:title"]||m,template:f["jcr:content"]?.["cq:template"],lastModified:f["jcr:content"]?.["cq:lastModified"],lastModifiedBy:f["jcr:content"]?.["cq:lastModifiedBy"],resourceType:f["jcr:content"]?.["sling:resourceType"],type:"page"}),l<t&&o(f,j,l+1)}})};return s&&typeof s=="object"&&o(s,e,0),i({siteRoot:e,pages:a,pageCount:a.length,depth:t,limit:n,totalChildrenScanned:a.length},"listPages")}catch(s){if(g.warn("JSON API failed, falling back to QueryBuilder:",s.message),s.response?.status===404||s.response?.status===403){const a=await this.fetch.get("/bin/querybuilder.json",{path:e,type:"cq:Page","p.nodedepth":t.toString(),"p.limit":n.toString(),"p.hits":"full"}),o=(a.hits||[]).map(r=>({name:r.name||r.path?.split("/").pop(),path:r.path,primaryType:"cq:Page",title:r["jcr:content/jcr:title"]||r.title||r.name,template:r["jcr:content/cq:template"],lastModified:r["jcr:content/cq:lastModified"],lastModifiedBy:r["jcr:content/cq:lastModifiedBy"],resourceType:r["jcr:content/sling:resourceType"],type:"page"}));return i({siteRoot:e,pages:o,pageCount:o.length,depth:t,limit:n,totalChildrenScanned:a.total||o.length,fallbackUsed:"QueryBuilder"},"listPages")}throw s}},"listPages")}async executeJCRQuery(e,t=20){return p(async()=>{if(!e||e.trim().length===0)throw new Error("Query is required and must be a non-empty string. Note: Only QueryBuilder fulltext is supported, not JCR SQL2.");const n=e.toLowerCase();if(/drop|delete|update|insert|exec|script|\.|<script/i.test(n)||e.length>1e3)throw new Error("Query contains potentially unsafe patterns or is too long");const s=await this.fetch.get("/bin/querybuilder.json",{path:"/content",type:"cq:Page",fulltext:e,"p.limit":t});return{query:e,results:s.hits||[],total:s.total||0,limit:t}},"executeJCRQuery")}async getPageProperties(e){return p(async()=>{const t=`${e}/jcr:content.json`,n=await this.fetch.get(t),s={title:n["jcr:title"],description:n["jcr:description"],template:n["cq:template"],lastModified:n["cq:lastModified"],lastModifiedBy:n["jcr:createdBy"],created:n["jcr:created"],createdBy:n["jcr:createdBy"],primaryType:n["jcr:primaryType"],resourceType:n["sling:resourceType"],tags:n["cq:tags"]||[],properties:n};return i({pagePath:e,properties:s},"getPageProperties")},"getPageProperties")}async searchContent(e){return p(async()=>{const t=await this.fetch.get(this.config.aem.endpoints.query,e);return i({params:e,results:t.hits||[],total:t.total||0,rawResponse:t},"searchContent")},"searchContent")}async getAssetMetadata(e){return p(async()=>{const t=`${e}.json`,n=await this.fetch.get(t),s=n["jcr:content"]?.metadata||{};return i({assetPath:e,metadata:s,fullData:n},"getAssetMetadata")},"getAssetMetadata")}async createPage(e){return p(async()=>{const{parentPath:t,title:n,template:s,name:a,properties:o}=e;if(!u(t,this.aemConfig))throw d(h.INVALID_PARAMETERS,`Invalid parent path: ${String(t)}`,{parentPath:t});const r=a||n.replace(/\s+/g,"-").toLowerCase(),c=`${t}/${r}`;return await this.fetch.post(c,{"jcr:primaryType":"cq:Page","jcr:title":n,"cq:template":s,...o}),i({success:!0,pagePath:c,title:n,template:s,properties:o,timestamp:new Date().toISOString()},"createPage")},"createPage")}async deletePage(e){return p(async()=>{const{pagePath:t}=e;if(!u(t,this.aemConfig))throw d(h.INVALID_PARAMETERS,`Invalid page path: ${String(t)}`,{pagePath:t});let n=!1;try{await this.fetch.delete(t),n=!0}catch{try{await this.fetch.post("/bin/wcmcommand",{cmd:"deletePage",path:t,force:e.force?"true":"false"}),n=!0}catch{try{await this.fetch.post(t,{":operation":"delete"}),n=!0}catch(o){throw o}}}return i({success:n,deletedPath:t,timestamp:new Date().toISOString()},"deletePage")},"deletePage")}async createComponent(e){return p(async()=>{const{pagePath:t,componentPath:n,componentType:s,resourceType:a,properties:o={},name:r}=e;if(!u(t,this.aemConfig))throw d(h.INVALID_PARAMETERS,`Invalid page path: ${String(t)}`,{pagePath:t});const c=r||`${s}_${Date.now()}`,l=n||`${t}/jcr:content/${c}`;return await this.fetch.post(l,{"jcr:primaryType":"nt:unstructured","sling:resourceType":a,...o,":operation":"import",":contentType":"json",":replace":"true"}),i({success:!0,componentPath:l,componentType:s,resourceType:a,properties:o,timestamp:new Date().toISOString()},"createComponent")},"createComponent")}async deleteComponent(e){return p(async()=>{const{componentPath:t}=e;if(!u(t,this.aemConfig))throw d(h.INVALID_PARAMETERS,`Invalid component path: ${String(t)}`,{componentPath:t});let n=!1;try{await this.fetch.delete(t),n=!0}catch{try{await this.fetch.post(t,{":operation":"delete"}),n=!0}catch(a){throw a}}return i({success:n,deletedPath:t,timestamp:new Date().toISOString()},"deleteComponent")},"deleteComponent")}async unpublishContent(e){return p(async()=>{const{contentPaths:t,unpublishTree:n=!1}=e;if(!t||Array.isArray(t)&&t.length===0)throw d(h.INVALID_PARAMETERS,"Content paths array is required and cannot be empty",{contentPaths:t});const s=[];for(const a of Array.isArray(t)?t:[t])try{const o=new URLSearchParams;o.append("cmd","Deactivate"),o.append("path",a),o.append("ignoredeactivated","false"),o.append("onlymodified","false"),n&&o.append("deep","true");const r=await this.fetch.post("/bin/replicate.json",o);s.push({path:a,success:!0,response:r})}catch(o){s.push({path:a,success:!1,error:o.message})}return i({success:s.every(a=>a.success),results:s,unpublishedPaths:t,unpublishTree:n,timestamp:new Date().toISOString()},"unpublishContent")},"unpublishContent")}async activatePage(e){return p(async()=>{const{pagePath:t,activateTree:n=!1}=e;if(!u(t,this.aemConfig))throw d(h.INVALID_PARAMETERS,`Invalid page path: ${String(t)}`,{pagePath:t});try{const s=new URLSearchParams;s.append("cmd","Activate"),s.append("path",t),s.append("ignoredeactivated","false"),s.append("onlymodified","false"),n&&s.append("deep","true");const a=await this.fetch.post("/bin/replicate.json",s);return i({success:!0,activatedPath:t,activateTree:n,response:a,timestamp:new Date().toISOString()},"activatePage")}catch(s){try{const a=await this.fetch.post("/bin/wcmcommand",{cmd:"activate",path:t,ignoredeactivated:!1,onlymodified:!1});return i({success:!0,activatedPath:t,activateTree:n,response:a,fallbackUsed:"WCM Command",timestamp:new Date().toISOString()},"activatePage")}catch{throw y(s,"activatePage")}}},"activatePage")}async deactivatePage(e){return p(async()=>{const{pagePath:t,deactivateTree:n=!1}=e;if(!u(t,this.aemConfig))throw d(h.INVALID_PARAMETERS,`Invalid page path: ${String(t)}`,{pagePath:t});try{const s=new URLSearchParams;s.append("cmd","Deactivate"),s.append("path",t),s.append("ignoredeactivated","false"),s.append("onlymodified","false"),n&&s.append("deep","true");const a=await this.fetch.post("/bin/replicate.json",s);return i({success:!0,deactivatedPath:t,deactivateTree:n,response:a,timestamp:new Date().toISOString()},"deactivatePage")}catch(s){try{const a=await this.fetch.post("/bin/wcmcommand",{cmd:"deactivate",path:t,ignoredeactivated:!1,onlymodified:!1});return i({success:!0,deactivatedPath:t,deactivateTree:n,response:a,fallbackUsed:"WCM Command",timestamp:new Date().toISOString()},"deactivatePage")}catch{throw y(s,"deactivatePage")}}},"deactivatePage")}async uploadAsset(e){return p(async()=>{const{parentPath:t,fileName:n,fileContent:s,mimeType:a,metadata:o={}}=e;if(!u(t,this.aemConfig))throw d(h.INVALID_PARAMETERS,`Invalid parent path: ${String(t)}`,{parentPath:t});const r=`${t}/${n}`;try{const c=new URLSearchParams;typeof s=="string"?c.append("file",s):c.append("file",s.toString()),c.append("fileName",n),c.append(":operation","import"),c.append(":contentType","json"),c.append(":replace","true"),c.append("jcr:primaryType","dam:Asset"),a&&c.append("jcr:content/jcr:mimeType",a),Object.entries(o).forEach(([f,j])=>{c.append(`jcr:content/metadata/${f}`,String(j))});const l=await this.fetch.post(r,c),m=await this.fetch.get(`${r}.json`);return i({success:!0,assetPath:r,fileName:n,mimeType:a,metadata:o,uploadResponse:l,assetData:m,timestamp:new Date().toISOString()},"uploadAsset")}catch(c){try{const l=await this.fetch.post("/api/assets"+t,{fileName:n,fileContent:s,mimeType:a,metadata:o});return i({success:!0,assetPath:r,fileName:n,mimeType:a,metadata:o,uploadResponse:l,fallbackUsed:"DAM API",timestamp:new Date().toISOString()},"uploadAsset")}catch{throw y(c,"uploadAsset")}}},"uploadAsset")}async updateAsset(e){return p(async()=>{const{assetPath:t,metadata:n,fileContent:s,mimeType:a}=e;if(!u(t,this.aemConfig))throw d(h.INVALID_PARAMETERS,`Invalid asset path: ${String(t)}`,{assetPath:t});const o=new URLSearchParams;s&&(o.append("file",s),a&&o.append("jcr:content/jcr:mimeType",a)),n&&typeof n=="object"&&Object.entries(n).forEach(([r,c])=>{o.append(`jcr:content/metadata/${r}`,String(c))});try{const r=await this.fetch.post(t,o),c=await this.fetch.get(`${t}.json`);return i({success:!0,assetPath:t,updatedMetadata:n,updateResponse:r,assetData:c,timestamp:new Date().toISOString()},"updateAsset")}catch(r){throw y(r,"updateAsset")}},"updateAsset")}async deleteAsset(e){return p(async()=>{const{assetPath:t,force:n=!1}=e;if(!u(t,this.aemConfig))throw d(h.INVALID_PARAMETERS,`Invalid asset path: ${String(t)}`,{assetPath:t});return await this.fetch.delete(t),i({success:!0,deletedPath:t,force:n,timestamp:new Date().toISOString()},"deleteAsset")},"deleteAsset")}async getTemplateStructure(e){return p(async()=>{try{const t=await this.fetch.get(`${e}.infinity.json`),n={path:e,properties:t["jcr:content"]||{},policies:t["jcr:content"]?.policies||{},structure:t["jcr:content"]?.structure||{},initialContent:t["jcr:content"]?.initial||{},allowedComponents:[],allowedPaths:t["jcr:content"]?.allowedPaths||[]},s=(a,o="")=>{if(!(!a||typeof a!="object")){if(a.components){const r=Object.keys(a.components);n.allowedComponents.push(...r)}Object.entries(a).forEach(([r,c])=>{typeof c=="object"&&c!==null&&!r.startsWith("jcr:")&&s(c,o?`${o}/${r}`:r)})}};return s(n.policies),n.allowedComponents=[...new Set(n.allowedComponents)],i({templatePath:e,structure:n,fullData:t},"getTemplateStructure")}catch(t){throw y(t,"getTemplateStructure")}},"getTemplateStructure")}async bulkUpdateComponents(e){return p(async()=>{const{updates:t,validateFirst:n=!0,continueOnError:s=!1}=e;if(!Array.isArray(t)||t.length===0)throw d(h.INVALID_PARAMETERS,"Updates array is required and cannot be empty");const a=[];if(n)for(const r of t)try{await this.fetch.get(`${r.componentPath}.json`)}catch(c){if(c.response?.status===404&&(a.push({componentPath:r.componentPath,success:!1,error:`Component not found: ${r.componentPath}`,phase:"validation"}),!s))return i({success:!1,message:"Bulk update failed during validation phase",results:a,totalUpdates:t.length,successfulUpdates:0},"bulkUpdateComponents")}let o=0;for(const r of t)try{const c=await this.updateComponent({componentPath:r.componentPath,properties:r.properties});a.push({componentPath:r.componentPath,success:!0,result:c,phase:"update"}),o++}catch(c){if(a.push({componentPath:r.componentPath,success:!1,error:c.message,phase:"update"}),!s)break}return i({success:o===t.length,message:`Bulk update completed: ${o}/${t.length} successful`,results:a,totalUpdates:t.length,successfulUpdates:o,failedUpdates:t.length-o},"bulkUpdateComponents")},"bulkUpdateComponents")}async getNodeContent(e,t=1){return p(async()=>{const n=`${e}.json`,s=await this.fetch.get(n,{":depth":t.toString()});return{path:e,depth:t,content:s,timestamp:new Date().toISOString()}},"getNodeContent")}}
|
|
1
|
+
"use strict";import{getAEMConfig as P,isValidContentPath as m,isValidLocale as b}from"./aem.config.js";import{AEM_ERROR_CODES as h,createAEMError as d,createSuccessResponse as i,handleAEMHttpError as y,safeExecute as p,validateComponentOperation as w}from"./aem.errors.js";import{AEMFetch as C}from"./aem.fetch.js";import{LOGGER as g}from"../utils/logger.js";export class AEMConnector{isInitialized;isAEMaaCS;config;aemConfig;fetch;constructor(e){this.isInitialized=!1,this.config=this.loadConfig(e),this.aemConfig=P({}),this.isAEMaaCS=this.isConfigAEMaaCS(),this.fetch=new C({host:this.config.aem.host,auth:this.config.aem.auth,timeout:this.aemConfig.queries.timeoutMs})}async init(){try{await this.fetch.init(),this.isInitialized=!0}catch{this.isInitialized=!1}}isConfigAEMaaCS(){return!!(this.config.aem.auth.clientId&&this.config.aem.auth.clientSecret)}loadConfig(e={}){let t;return e.id&&e.secret?t={clientId:e.id,clientSecret:e.secret}:t={username:e.user||"admin",password:e.pass||"admin"},{aem:{host:e.host||"http://localhost:4502",author:e.host||"http://localhost:4502",publish:"http://localhost:4503",auth:t,endpoints:{content:"/content",dam:"/content/dam",query:"/bin/querybuilder.json",crxde:"/crx/de",jcr:""}},mcp:{name:"NAEM MCP Server",version:"1.0.0"}}}async testConnection(){const e=await this.testAEMConnection(),t=e?await this.testAuthConnection():!1;return{aem:e,auth:t}}async testAEMConnection(){try{this.isInitialized||await this.init(),g.log("Testing AEM connection to:",this.config.aem.host);const e=`${this.config.aem.host}/libs/granite/core/content/login.html`,t=await this.fetch.get(e,{timeout:5e3});return g.log("\u2705 AEM connection successful! Status:",t.status),!0}catch(e){return g.error("\u274C AEM connection failed:",e.message),!1}}async testAuthConnection(){try{this.isInitialized||await this.init();const e=`${this.config.aem.host}/libs/granite/security/content/userinfo.json`;g.log("Testing AEM authentication connection to:",this.config.aem.host);const t=await this.fetch.get(e,{timeout:5e3});return g.log("\u2705 AEM authentication connection successful! Status:",t.status),!0}catch(e){return g.error("\u274C AEM authentication connection failed:",e.message),!1}}async validateComponent(e){return p(async()=>{const t=e.pagePath||e.page_path,{locale:n,component:s,props:a}=e;if(w(n,t,s,a),!b(n,this.aemConfig))throw d(h.INVALID_LOCALE,`Locale '${n}' is not supported`,{locale:n,allowedLocales:this.aemConfig.validation.allowedLocales});if(!m(t,this.aemConfig))throw d(h.INVALID_PATH,`Path '${t}' is not within allowed content roots`,{path:t,allowedRoots:Object.values(this.aemConfig.contentPaths)});const o=`${t}.json`,r=await this.fetch.get(o,{params:{":depth":"2"},timeout:this.aemConfig.queries.timeoutMs}),c=this.validateComponentProps(r.data,s,a);return i({message:"Component validation completed successfully",pageData:r.data,component:s,locale:n,validation:c,configUsed:{allowedLocales:this.aemConfig.validation.allowedLocales}},"validateComponent")},"validateComponent")}validateComponentProps(e,t,n){const s=[],a=[];return t==="text"&&!n.text&&!n.richText&&s.push("Text component should have text or richText property"),t==="image"&&!n.fileReference&&!n.src&&a.push("Image component requires fileReference or src property"),{valid:a.length===0,errors:a,warnings:s,componentType:t,propsValidated:Object.keys(n).length}}async updateComponent(e){return p(async()=>{if(!e.componentPath||typeof e.componentPath!="string")throw d(h.INVALID_PARAMETERS,"Component path is required and must be a string");if(!e.properties||typeof e.properties!="object")throw d(h.INVALID_PARAMETERS,"Properties are required and must be an object");if(!m(e.componentPath,this.aemConfig))throw d(h.INVALID_PATH,`Component path '${e.componentPath}' is not within allowed content roots`,{path:e.componentPath,allowedRoots:Object.values(this.aemConfig.contentPaths)});const t=`${e.componentPath}.json`,n=await this.fetch.get(t);try{await n.json()}catch(r){throw r.response?.status===404?d(h.COMPONENT_NOT_FOUND,`Component not found at path: ${e.componentPath}`,{componentPath:e.componentPath}):y(r,"updateComponent")}const s=new URLSearchParams;Object.entries(e.properties).forEach(([r,c])=>{c==null?s.append(`${r}@Delete`,""):Array.isArray(c)?c.forEach(l=>{s.append(`${r}`,l.toString())}):typeof c=="object"?s.append(r,JSON.stringify(c)):s.append(r,c.toString())});const a=await this.fetch.post(e.componentPath,s),o=await this.fetch.get(`${e.componentPath}.json`);return i({message:"Component updated successfully",path:e.componentPath,properties:e.properties,updatedProperties:o.data,response:a.data,verification:{success:!0,propertiesChanged:Object.keys(e.properties).length,timestamp:new Date().toISOString()}},"updateComponent")},"updateComponent")}async undoChanges(e){return i({message:"undoChanges is not implemented. Please use AEM version history for undo/rollback.",request:e,timestamp:new Date().toISOString()},"undoChanges")}async scanPageComponents(e){return p(async()=>{const t=`${e}.infinity.json`,n=await this.fetch.get(t),s=[],a=(o,r)=>{!o||typeof o!="object"||(o["sling:resourceType"]&&s.push({path:r,resourceType:o["sling:resourceType"],properties:{...o}}),Object.entries(o).forEach(([c,l])=>{if(typeof l=="object"&&l!==null&&!c.startsWith("rep:")&&!c.startsWith("oak:")){const f=r?`${r}/${c}`:c;a(l,f)}}))};return n.data["jcr:content"]?a(n.data["jcr:content"],"jcr:content"):a(n.data,e),i({pagePath:e,components:s,totalComponents:s.length},"scanPageComponents")},"scanPageComponents")}async fetchSites(){return p(async()=>{const t=await this.fetch.get("/content.json",{":depth":"2"}),n=[];return Object.entries(t).forEach(([s,a])=>{s.startsWith("jcr:")||s.startsWith("sling:")||a&&typeof a=="object"&&a["jcr:content"]&&n.push({name:s,path:`/content/${s}`,title:a["jcr:content"]["jcr:title"]||s,template:a["jcr:content"]["cq:template"],lastModified:a["jcr:content"]["cq:lastModified"]})}),i({sites:n,totalCount:n.length},"fetchSites")},"fetchSites")}async fetchLanguageMasters(e){return p(async()=>{const t=`/content/${e}.json`,n=await this.fetch.get(t,{":depth":"3"}),s=[];return Object.entries(n).forEach(([a,o])=>{a.startsWith("jcr:")||a.startsWith("sling:")||o&&typeof o=="object"&&o["jcr:content"]&&s.push({name:a,path:`/content/${a}`,title:o["jcr:content"]["jcr:title"]||a,language:o["jcr:content"]["jcr:language"]||"en"})}),i({site:e,languageMasters:s},"fetchLanguageMasters")},"fetchLanguageMasters")}async fetchAvailableLocales(e,t){return p(async()=>{const n=`${t}.json`,s=await this.fetch.get(n,{":depth":"2"}),a=[];return Object.entries(s).forEach(([o,r])=>{o.startsWith("jcr:")||o.startsWith("sling:")||r&&typeof r=="object"&&a.push({name:o,title:r["jcr:content"]?.["jcr:title"]||o,language:r["jcr:content"]?.["jcr:language"]||o})}),i({site:e,languageMasterPath:t,availableLocales:a},"fetchAvailableLocales")},"fetchAvailableLocales")}async replicateAndPublish(e,t,n){return p(async()=>i({message:"Replication simulated",selectedLocales:e,componentData:t,localizedOverrides:n},"replicateAndPublish"),"replicateAndPublish")}async getAllTextContent(e){return p(async()=>{const t=`${e}.infinity.json`,n=await this.fetch.get(t),s=[],a=(o,r)=>{!o||typeof o!="object"||((o.text||o["jcr:title"]||o["jcr:description"])&&s.push({path:r,title:o["jcr:title"],text:o.text,description:o["jcr:description"]}),Object.entries(o).forEach(([c,l])=>{if(typeof l=="object"&&l!==null&&!c.startsWith("rep:")&&!c.startsWith("oak:")){const f=r?`${r}/${c}`:c;a(l,f)}}))};return n["jcr:content"]?a(n["jcr:content"],"jcr:content"):a(n,e),i({pagePath:e,textContent:s},"getAllTextContent")},"getAllTextContent")}async getPageTextContent(e){return p(async()=>this.getAllTextContent(e),"getPageTextContent")}async getPageImages(e){return p(async()=>{const t=`${e}.infinity.json`,n=await this.fetch.get(t),s=[],a=(o,r)=>{!o||typeof o!="object"||((o.fileReference||o.src)&&s.push({path:r,fileReference:o.fileReference,src:o.src,alt:o.alt||o.altText,title:o["jcr:title"]||o.title}),Object.entries(o).forEach(([c,l])=>{if(typeof l=="object"&&l!==null&&!c.startsWith("rep:")&&!c.startsWith("oak:")){const f=r?`${r}/${c}`:c;a(l,f)}}))};return n["jcr:content"]?a(n["jcr:content"],"jcr:content"):a(n,e),i({pagePath:e,images:s},"getPageImages")},"getPageImages")}async updateImagePath(e,t){return p(async()=>this.updateComponent({componentPath:e,properties:{fileReference:t}}),"updateImagePath")}async getPageContent(e){return p(async()=>{const t=`${e}.infinity.json`,n=await this.fetch.get(t);return i({pagePath:e,content:n},"getPageContent")},"getPageContent")}async listChildren(e,t=1){return p(async()=>{try{const n=await this.fetch.get(`${e}.${t}.json`),s=[];return n&&typeof n=="object"&&Object.entries(n).forEach(([a,o])=>{if(!(a.startsWith("jcr:")||a.startsWith("sling:")||a.startsWith("cq:")||a.startsWith("rep:")||a.startsWith("oak:")||a==="jcr:content")&&o&&typeof o=="object"){const r=`${e}/${a}`;s.push({name:a,path:r,primaryType:o["jcr:primaryType"]||"nt:unstructured",title:o["jcr:content"]?.["jcr:title"]||o["jcr:title"]||a,lastModified:o["jcr:content"]?.["cq:lastModified"]||o["cq:lastModified"],resourceType:o["jcr:content"]?.["sling:resourceType"]||o["sling:resourceType"]})}}),s}catch(n){if(n.response?.status===404||n.response?.status===403)return((await this.fetch.get("/bin/querybuilder.json",{path:e,type:"cq:Page","p.nodedepth":"1","p.limit":"1000","p.hits":"full"})).hits||[]).map(a=>({name:a.name||a.path?.split("/").pop(),path:a.path,primaryType:a["jcr:primaryType"]||"cq:Page",title:a["jcr:content/jcr:title"]||a.title||a.name,lastModified:a["jcr:content/cq:lastModified"],resourceType:a["jcr:content/sling:resourceType"]}));throw n}},"listChildren")}async listPages(e,t=1,n=20){return p(async()=>{try{const s=await this.fetch.get(`${e}.${t}.json`),a=[],o=(r,c,l)=>{l>t||a.length>=n||Object.entries(r).forEach(([f,u])=>{if(!(a.length>=n)&&!(f.startsWith("jcr:")||f.startsWith("sling:")||f.startsWith("cq:")||f.startsWith("rep:")||f.startsWith("oak:"))&&u&&typeof u=="object"){const j=`${c}/${f}`;u["jcr:primaryType"]==="cq:Page"&&a.push({name:f,path:j,primaryType:"cq:Page",title:u["jcr:content"]?.["jcr:title"]||f,template:u["jcr:content"]?.["cq:template"],lastModified:u["jcr:content"]?.["cq:lastModified"],lastModifiedBy:u["jcr:content"]?.["cq:lastModifiedBy"],resourceType:u["jcr:content"]?.["sling:resourceType"],type:"page"}),l<t&&o(u,j,l+1)}})};return s&&typeof s=="object"&&o(s,e,0),i({siteRoot:e,pages:a,pageCount:a.length,depth:t,limit:n,totalChildrenScanned:a.length},"listPages")}catch(s){if(g.warn("JSON API failed, falling back to QueryBuilder:",s.message),s.response?.status===404||s.response?.status===403){const a=await this.fetch.get("/bin/querybuilder.json",{path:e,type:"cq:Page","p.nodedepth":t.toString(),"p.limit":n.toString(),"p.hits":"full"}),o=(a.hits||[]).map(r=>({name:r.name||r.path?.split("/").pop(),path:r.path,primaryType:"cq:Page",title:r["jcr:content/jcr:title"]||r.title||r.name,template:r["jcr:content/cq:template"],lastModified:r["jcr:content/cq:lastModified"],lastModifiedBy:r["jcr:content/cq:lastModifiedBy"],resourceType:r["jcr:content/sling:resourceType"],type:"page"}));return i({siteRoot:e,pages:o,pageCount:o.length,depth:t,limit:n,totalChildrenScanned:a.total||o.length,fallbackUsed:"QueryBuilder"},"listPages")}throw s}},"listPages")}async executeJCRQuery(e,t=20){return p(async()=>{if(!e||e.trim().length===0)throw new Error("Query is required and must be a non-empty string. Note: Only QueryBuilder fulltext is supported, not JCR SQL2.");const n=e.toLowerCase();if(/drop|delete|update|insert|exec|script|\.|<script/i.test(n)||e.length>1e3)throw new Error("Query contains potentially unsafe patterns or is too long");const s=await this.fetch.get("/bin/querybuilder.json",{path:"/content",type:"cq:Page",fulltext:e,"p.limit":t});return{query:e,results:s.hits||[],total:s.total||0,limit:t}},"executeJCRQuery")}async getPageProperties(e){return p(async()=>{const t=`${e}/jcr:content.json`,n=await this.fetch.get(t),s={title:n["jcr:title"],description:n["jcr:description"],template:n["cq:template"],lastModified:n["cq:lastModified"],lastModifiedBy:n["jcr:createdBy"],created:n["jcr:created"],createdBy:n["jcr:createdBy"],primaryType:n["jcr:primaryType"],resourceType:n["sling:resourceType"],tags:n["cq:tags"]||[],properties:n};return i({pagePath:e,properties:s},"getPageProperties")},"getPageProperties")}async searchContent(e){return p(async()=>{const t=await this.fetch.get(this.config.aem.endpoints.query,e);return i({params:e,results:t.hits||[],total:t.total||0,rawResponse:t},"searchContent")},"searchContent")}async getAssetMetadata(e){return p(async()=>{const t=`${e}.json`,n=await this.fetch.get(t),s=n["jcr:content"]?.metadata||{};return i({assetPath:e,metadata:s,fullData:n},"getAssetMetadata")},"getAssetMetadata")}async createPage(e){return p(async()=>{const{parentPath:t,title:n,template:s,name:a,properties:o}=e;if(!m(t,this.aemConfig))throw d(h.INVALID_PARAMETERS,`Invalid parent path: ${String(t)}`,{parentPath:t});const r=a||n.replace(/\s+/g,"-").toLowerCase(),c=`${t}/${r}`;return await this.fetch.post(c,{"jcr:primaryType":"cq:Page","jcr:title":n,"cq:template":s,...o}),i({success:!0,pagePath:c,title:n,template:s,properties:o,timestamp:new Date().toISOString()},"createPage")},"createPage")}async deletePage(e){return p(async()=>{const{pagePath:t}=e;if(!m(t,this.aemConfig))throw d(h.INVALID_PARAMETERS,`Invalid page path: ${String(t)}`,{pagePath:t});let n=!1;try{await this.fetch.delete(t),n=!0}catch{try{await this.fetch.post("/bin/wcmcommand",{cmd:"deletePage",path:t,force:e.force?"true":"false"}),n=!0}catch{try{await this.fetch.post(t,{":operation":"delete"}),n=!0}catch(o){throw o}}}return i({success:n,deletedPath:t,timestamp:new Date().toISOString()},"deletePage")},"deletePage")}async createComponent(e){return p(async()=>{const{pagePath:t,componentPath:n,componentType:s,resourceType:a,properties:o={},name:r}=e;if(!m(t,this.aemConfig))throw d(h.INVALID_PARAMETERS,`Invalid page path: ${String(t)}`,{pagePath:t});const c=r||`${s}_${Date.now()}`,l=n||`${t}/jcr:content/${c}`;return await this.fetch.post(l,{"jcr:primaryType":"nt:unstructured","sling:resourceType":a,...o,":operation":"import",":contentType":"json",":replace":"true"}),i({success:!0,componentPath:l,componentType:s,resourceType:a,properties:o,timestamp:new Date().toISOString()},"createComponent")},"createComponent")}async deleteComponent(e){return p(async()=>{const{componentPath:t}=e;if(!m(t,this.aemConfig))throw d(h.INVALID_PARAMETERS,`Invalid component path: ${String(t)}`,{componentPath:t});let n=!1;try{await this.fetch.delete(t),n=!0}catch{try{await this.fetch.post(t,{":operation":"delete"}),n=!0}catch(a){throw a}}return i({success:n,deletedPath:t,timestamp:new Date().toISOString()},"deleteComponent")},"deleteComponent")}async unpublishContent(e){return p(async()=>{const{contentPaths:t,unpublishTree:n=!1}=e;if(!t||Array.isArray(t)&&t.length===0)throw d(h.INVALID_PARAMETERS,"Content paths array is required and cannot be empty",{contentPaths:t});const s=[];for(const a of Array.isArray(t)?t:[t])try{const o=new URLSearchParams;o.append("cmd","Deactivate"),o.append("path",a),o.append("ignoredeactivated","false"),o.append("onlymodified","false"),n&&o.append("deep","true");const r=await this.fetch.post("/bin/replicate.json",o);s.push({path:a,success:!0,response:r})}catch(o){s.push({path:a,success:!1,error:o.message})}return i({success:s.every(a=>a.success),results:s,unpublishedPaths:t,unpublishTree:n,timestamp:new Date().toISOString()},"unpublishContent")},"unpublishContent")}async activatePage(e){return p(async()=>{const{pagePath:t,activateTree:n=!1}=e;if(!m(t,this.aemConfig))throw d(h.INVALID_PARAMETERS,`Invalid page path: ${String(t)}`,{pagePath:t});try{const s=new URLSearchParams;s.append("cmd","Activate"),s.append("path",t),s.append("ignoredeactivated","false"),s.append("onlymodified","false"),n&&s.append("deep","true");const a=await this.fetch.post("/bin/replicate.json",s);return i({success:!0,activatedPath:t,activateTree:n,response:a,timestamp:new Date().toISOString()},"activatePage")}catch(s){try{const a=await this.fetch.post("/bin/wcmcommand",{cmd:"activate",path:t,ignoredeactivated:!1,onlymodified:!1});return i({success:!0,activatedPath:t,activateTree:n,response:a,fallbackUsed:"WCM Command",timestamp:new Date().toISOString()},"activatePage")}catch{throw y(s,"activatePage")}}},"activatePage")}async deactivatePage(e){return p(async()=>{const{pagePath:t,deactivateTree:n=!1}=e;if(!m(t,this.aemConfig))throw d(h.INVALID_PARAMETERS,`Invalid page path: ${String(t)}`,{pagePath:t});try{const s=new URLSearchParams;s.append("cmd","Deactivate"),s.append("path",t),s.append("ignoredeactivated","false"),s.append("onlymodified","false"),n&&s.append("deep","true");const a=await this.fetch.post("/bin/replicate.json",s);return i({success:!0,deactivatedPath:t,deactivateTree:n,response:a,timestamp:new Date().toISOString()},"deactivatePage")}catch(s){try{const a=await this.fetch.post("/bin/wcmcommand",{cmd:"deactivate",path:t,ignoredeactivated:!1,onlymodified:!1});return i({success:!0,deactivatedPath:t,deactivateTree:n,response:a,fallbackUsed:"WCM Command",timestamp:new Date().toISOString()},"deactivatePage")}catch{throw y(s,"deactivatePage")}}},"deactivatePage")}async uploadAsset(e){return p(async()=>{const{parentPath:t,fileName:n,fileContent:s,mimeType:a,metadata:o={}}=e;if(!m(t,this.aemConfig))throw d(h.INVALID_PARAMETERS,`Invalid parent path: ${String(t)}`,{parentPath:t});const r=`${t}/${n}`;try{const c=new URLSearchParams;typeof s=="string"?c.append("file",s):c.append("file",s.toString()),c.append("fileName",n),c.append(":operation","import"),c.append(":contentType","json"),c.append(":replace","true"),c.append("jcr:primaryType","dam:Asset"),a&&c.append("jcr:content/jcr:mimeType",a),Object.entries(o).forEach(([u,j])=>{c.append(`jcr:content/metadata/${u}`,String(j))});const l=await this.fetch.post(r,c),f=await this.fetch.get(`${r}.json`);return i({success:!0,assetPath:r,fileName:n,mimeType:a,metadata:o,uploadResponse:l,assetData:f,timestamp:new Date().toISOString()},"uploadAsset")}catch(c){try{const l=await this.fetch.post("/api/assets"+t,{fileName:n,fileContent:s,mimeType:a,metadata:o});return i({success:!0,assetPath:r,fileName:n,mimeType:a,metadata:o,uploadResponse:l,fallbackUsed:"DAM API",timestamp:new Date().toISOString()},"uploadAsset")}catch{throw y(c,"uploadAsset")}}},"uploadAsset")}async updateAsset(e){return p(async()=>{const{assetPath:t,metadata:n,fileContent:s,mimeType:a}=e;if(!m(t,this.aemConfig))throw d(h.INVALID_PARAMETERS,`Invalid asset path: ${String(t)}`,{assetPath:t});const o=new URLSearchParams;s&&(o.append("file",s),a&&o.append("jcr:content/jcr:mimeType",a)),n&&typeof n=="object"&&Object.entries(n).forEach(([r,c])=>{o.append(`jcr:content/metadata/${r}`,String(c))});try{const r=await this.fetch.post(t,o),c=await this.fetch.get(`${t}.json`);return i({success:!0,assetPath:t,updatedMetadata:n,updateResponse:r,assetData:c,timestamp:new Date().toISOString()},"updateAsset")}catch(r){throw y(r,"updateAsset")}},"updateAsset")}async deleteAsset(e){return p(async()=>{const{assetPath:t,force:n=!1}=e;if(!m(t,this.aemConfig))throw d(h.INVALID_PARAMETERS,`Invalid asset path: ${String(t)}`,{assetPath:t});return await this.fetch.delete(t),i({success:!0,deletedPath:t,force:n,timestamp:new Date().toISOString()},"deleteAsset")},"deleteAsset")}async getTemplateStructure(e){return p(async()=>{try{const t=await this.fetch.get(`${e}.infinity.json`),n={path:e,properties:t["jcr:content"]||{},policies:t["jcr:content"]?.policies||{},structure:t["jcr:content"]?.structure||{},initialContent:t["jcr:content"]?.initial||{},allowedComponents:[],allowedPaths:t["jcr:content"]?.allowedPaths||[]},s=(a,o="")=>{if(!(!a||typeof a!="object")){if(a.components){const r=Object.keys(a.components);n.allowedComponents.push(...r)}Object.entries(a).forEach(([r,c])=>{typeof c=="object"&&c!==null&&!r.startsWith("jcr:")&&s(c,o?`${o}/${r}`:r)})}};return s(n.policies),n.allowedComponents=[...new Set(n.allowedComponents)],i({templatePath:e,structure:n,fullData:t},"getTemplateStructure")}catch(t){throw y(t,"getTemplateStructure")}},"getTemplateStructure")}async bulkUpdateComponents(e){return p(async()=>{const{updates:t,validateFirst:n=!0,continueOnError:s=!1}=e;if(!Array.isArray(t)||t.length===0)throw d(h.INVALID_PARAMETERS,"Updates array is required and cannot be empty");const a=[];if(n)for(const r of t)try{await this.fetch.get(`${r.componentPath}.json`)}catch(c){if(c.response?.status===404&&(a.push({componentPath:r.componentPath,success:!1,error:`Component not found: ${r.componentPath}`,phase:"validation"}),!s))return i({success:!1,message:"Bulk update failed during validation phase",results:a,totalUpdates:t.length,successfulUpdates:0},"bulkUpdateComponents")}let o=0;for(const r of t)try{const c=await this.updateComponent({componentPath:r.componentPath,properties:r.properties});a.push({componentPath:r.componentPath,success:!0,result:c,phase:"update"}),o++}catch(c){if(a.push({componentPath:r.componentPath,success:!1,error:c.message,phase:"update"}),!s)break}return i({success:o===t.length,message:`Bulk update completed: ${o}/${t.length} successful`,results:a,totalUpdates:t.length,successfulUpdates:o,failedUpdates:t.length-o},"bulkUpdateComponents")},"bulkUpdateComponents")}async getNodeContent(e,t=1){return p(async()=>{const n=`${e}.json`,s=await this.fetch.get(n,{":depth":t.toString()});return{path:e,depth:t,content:s,timestamp:new Date().toISOString()}},"getNodeContent")}}
|
package/dist/cli.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
"use strict";import
|
|
2
|
+
"use strict";import t from"yargs";import{hideBin as a}from"yargs/helpers";import{startServer as e}from"./index.js";const s=t(a(process.argv)).options({host:{type:"string",default:"http://localhost:4502",alias:"H"},user:{type:"string",default:"admin",alias:"u"},pass:{type:"string",default:"admin",alias:"p"},id:{type:"string",default:"",alias:"i"},secret:{type:"string",default:"",alias:"s"},mcpPort:{type:"number",default:8502,alias:"m"}}).help().alias("h","help").parseSync();s.help&&process.exit(0);const{host:r,user:i,pass:p,mcpPort:l,id:o,secret:n}=s;e({host:r,user:i,pass:p,mcpPort:l,id:o,secret:n});
|
package/dist/utils/logger.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";function o(){const
|
|
2
|
-
`)||[])[3]||"",
|
|
1
|
+
"use strict";const a=(n,t)=>`\x1B]8;;${t}\x07${n}\x1B]8;;\x07`;function o(){const s=(new Error().stack?.split(`
|
|
2
|
+
`)||[])[3]||"",c=s.match(/\(([^)]+)\)/),e=c?c[1]:s.trim(),i=e.split("/").pop()||"unknown";return a(`${i}`,`${e}`)}const r=!!process.env.MCP_LOGGER;export const LOGGER={log:(...n)=>{r&&console.log(`[${o()}]`,...n)},info:(...n)=>{r&&console.info(`[${o()}]`,...n)},warn:(...n)=>{r&&console.warn(`[${o()}]`,...n)},error:(...n)=>{r&&console.error(`[${o()}]`,...n)}};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aem-mcp-server",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.2",
|
|
4
4
|
"description": "AEM Model Context Protocol (MCP) server",
|
|
5
5
|
"private": false,
|
|
6
6
|
"publishConfig": {
|
|
@@ -25,8 +25,6 @@
|
|
|
25
25
|
},
|
|
26
26
|
"files": [
|
|
27
27
|
"dist/**/*.js",
|
|
28
|
-
"build/**/*.d.ts",
|
|
29
|
-
"docs/",
|
|
30
28
|
"README.md",
|
|
31
29
|
"LICENSE"
|
|
32
30
|
],
|
package/docs/API.md
DELETED
|
@@ -1,286 +0,0 @@
|
|
|
1
|
-
```json
|
|
2
|
-
{
|
|
3
|
-
"methods": [
|
|
4
|
-
{
|
|
5
|
-
"name": "validateComponent",
|
|
6
|
-
"description": "Validate component changes before applying them",
|
|
7
|
-
"parameters": [
|
|
8
|
-
"locale",
|
|
9
|
-
"page_path",
|
|
10
|
-
"component",
|
|
11
|
-
"props"
|
|
12
|
-
]
|
|
13
|
-
},
|
|
14
|
-
{
|
|
15
|
-
"name": "updateComponent",
|
|
16
|
-
"description": "Update component properties in AEM",
|
|
17
|
-
"parameters": [
|
|
18
|
-
"componentPath",
|
|
19
|
-
"properties"
|
|
20
|
-
]
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
"name": "undoChanges",
|
|
24
|
-
"description": "Undo the last component changes",
|
|
25
|
-
"parameters": [
|
|
26
|
-
"job_id"
|
|
27
|
-
]
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
"name": "scanPageComponents",
|
|
31
|
-
"description": "Scan a page to discover all components and their properties",
|
|
32
|
-
"parameters": [
|
|
33
|
-
"pagePath"
|
|
34
|
-
]
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
"name": "fetchSites",
|
|
38
|
-
"description": "Get all available sites in AEM",
|
|
39
|
-
"parameters": []
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
"name": "fetchLanguageMasters",
|
|
43
|
-
"description": "Get language masters for a specific site",
|
|
44
|
-
"parameters": [
|
|
45
|
-
"site"
|
|
46
|
-
]
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
"name": "fetchAvailableLocales",
|
|
50
|
-
"description": "Get available locales for a site and language master",
|
|
51
|
-
"parameters": [
|
|
52
|
-
"site",
|
|
53
|
-
"languageMasterPath"
|
|
54
|
-
]
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
"name": "replicateAndPublish",
|
|
58
|
-
"description": "Replicate and publish content to selected locales",
|
|
59
|
-
"parameters": [
|
|
60
|
-
"selectedLocales",
|
|
61
|
-
"componentData",
|
|
62
|
-
"localizedOverrides"
|
|
63
|
-
]
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
"name": "getAllTextContent",
|
|
67
|
-
"description": "Get all text content from a page including titles, text components, and descriptions",
|
|
68
|
-
"parameters": [
|
|
69
|
-
"pagePath"
|
|
70
|
-
]
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
"name": "getPageTextContent",
|
|
74
|
-
"description": "Get text content from a specific page",
|
|
75
|
-
"parameters": [
|
|
76
|
-
"pagePath"
|
|
77
|
-
]
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
"name": "getPageImages",
|
|
81
|
-
"description": "Get all images from a page, including those within Experience Fragments",
|
|
82
|
-
"parameters": [
|
|
83
|
-
"pagePath"
|
|
84
|
-
]
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
"name": "updateImagePath",
|
|
88
|
-
"description": "Update the image path for an image component and verify the update",
|
|
89
|
-
"parameters": [
|
|
90
|
-
"componentPath",
|
|
91
|
-
"newImagePath"
|
|
92
|
-
]
|
|
93
|
-
},
|
|
94
|
-
{
|
|
95
|
-
"name": "getPageContent",
|
|
96
|
-
"description": "Get all content from a page including Experience Fragments and Content Fragments",
|
|
97
|
-
"parameters": [
|
|
98
|
-
"pagePath"
|
|
99
|
-
]
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
"name": "listPages",
|
|
103
|
-
"description": "List all pages under a site root",
|
|
104
|
-
"parameters": [
|
|
105
|
-
"siteRoot",
|
|
106
|
-
"depth",
|
|
107
|
-
"limit"
|
|
108
|
-
]
|
|
109
|
-
},
|
|
110
|
-
{
|
|
111
|
-
"name": "getNodeContent",
|
|
112
|
-
"description": "Legacy: Get JCR node content",
|
|
113
|
-
"parameters": [
|
|
114
|
-
"path",
|
|
115
|
-
"depth"
|
|
116
|
-
]
|
|
117
|
-
},
|
|
118
|
-
{
|
|
119
|
-
"name": "listChildren",
|
|
120
|
-
"description": "Legacy: List child nodes",
|
|
121
|
-
"parameters": [
|
|
122
|
-
"path"
|
|
123
|
-
]
|
|
124
|
-
},
|
|
125
|
-
{
|
|
126
|
-
"name": "getPageProperties",
|
|
127
|
-
"description": "Get page properties",
|
|
128
|
-
"parameters": [
|
|
129
|
-
"pagePath"
|
|
130
|
-
]
|
|
131
|
-
},
|
|
132
|
-
{
|
|
133
|
-
"name": "searchContent",
|
|
134
|
-
"description": "Search content using Query Builder",
|
|
135
|
-
"parameters": [
|
|
136
|
-
"type",
|
|
137
|
-
"fulltext",
|
|
138
|
-
"path",
|
|
139
|
-
"limit"
|
|
140
|
-
]
|
|
141
|
-
},
|
|
142
|
-
{
|
|
143
|
-
"name": "executeJCRQuery",
|
|
144
|
-
"description": "Execute JCR query",
|
|
145
|
-
"parameters": [
|
|
146
|
-
"query",
|
|
147
|
-
"limit"
|
|
148
|
-
]
|
|
149
|
-
},
|
|
150
|
-
{
|
|
151
|
-
"name": "getAssetMetadata",
|
|
152
|
-
"description": "Get asset metadata",
|
|
153
|
-
"parameters": [
|
|
154
|
-
"assetPath"
|
|
155
|
-
]
|
|
156
|
-
},
|
|
157
|
-
{
|
|
158
|
-
"name": "getStatus",
|
|
159
|
-
"description": "Get workflow status by ID",
|
|
160
|
-
"parameters": [
|
|
161
|
-
"workflowId"
|
|
162
|
-
]
|
|
163
|
-
},
|
|
164
|
-
{
|
|
165
|
-
"name": "listMethods",
|
|
166
|
-
"description": "Get list of available MCP methods",
|
|
167
|
-
"parameters": []
|
|
168
|
-
},
|
|
169
|
-
{
|
|
170
|
-
"name": "enhancedPageSearch",
|
|
171
|
-
"description": "Intelligent page search with comprehensive fallback strategies and cross-section search",
|
|
172
|
-
"parameters": [
|
|
173
|
-
"searchTerm",
|
|
174
|
-
"basePath",
|
|
175
|
-
"includeAlternateLocales"
|
|
176
|
-
]
|
|
177
|
-
},
|
|
178
|
-
{
|
|
179
|
-
"name": "createPage",
|
|
180
|
-
"description": "Create a new page in AEM",
|
|
181
|
-
"parameters": [
|
|
182
|
-
"parentPath",
|
|
183
|
-
"title",
|
|
184
|
-
"template",
|
|
185
|
-
"name",
|
|
186
|
-
"properties"
|
|
187
|
-
]
|
|
188
|
-
},
|
|
189
|
-
{
|
|
190
|
-
"name": "deletePage",
|
|
191
|
-
"description": "Delete a page from AEM",
|
|
192
|
-
"parameters": [
|
|
193
|
-
"pagePath",
|
|
194
|
-
"force"
|
|
195
|
-
]
|
|
196
|
-
},
|
|
197
|
-
{
|
|
198
|
-
"name": "createComponent",
|
|
199
|
-
"description": "Create a new component on a page",
|
|
200
|
-
"parameters": [
|
|
201
|
-
"pagePath",
|
|
202
|
-
"componentType",
|
|
203
|
-
"resourceType",
|
|
204
|
-
"properties",
|
|
205
|
-
"name"
|
|
206
|
-
]
|
|
207
|
-
},
|
|
208
|
-
{
|
|
209
|
-
"name": "deleteComponent",
|
|
210
|
-
"description": "Delete a component from AEM",
|
|
211
|
-
"parameters": [
|
|
212
|
-
"componentPath",
|
|
213
|
-
"force"
|
|
214
|
-
]
|
|
215
|
-
},
|
|
216
|
-
{
|
|
217
|
-
"name": "unpublishContent",
|
|
218
|
-
"description": "Unpublish content from the publish environment",
|
|
219
|
-
"parameters": [
|
|
220
|
-
"contentPaths",
|
|
221
|
-
"unpublishTree"
|
|
222
|
-
]
|
|
223
|
-
},
|
|
224
|
-
{
|
|
225
|
-
"name": "activatePage",
|
|
226
|
-
"description": "Activate (publish) a single page",
|
|
227
|
-
"parameters": [
|
|
228
|
-
"pagePath",
|
|
229
|
-
"activateTree"
|
|
230
|
-
]
|
|
231
|
-
},
|
|
232
|
-
{
|
|
233
|
-
"name": "deactivatePage",
|
|
234
|
-
"description": "Deactivate (unpublish) a single page",
|
|
235
|
-
"parameters": [
|
|
236
|
-
"pagePath",
|
|
237
|
-
"deactivateTree"
|
|
238
|
-
]
|
|
239
|
-
},
|
|
240
|
-
{
|
|
241
|
-
"name": "uploadAsset",
|
|
242
|
-
"description": "Upload a new asset to AEM DAM",
|
|
243
|
-
"parameters": [
|
|
244
|
-
"parentPath",
|
|
245
|
-
"fileName",
|
|
246
|
-
"fileContent",
|
|
247
|
-
"mimeType",
|
|
248
|
-
"metadata"
|
|
249
|
-
]
|
|
250
|
-
},
|
|
251
|
-
{
|
|
252
|
-
"name": "updateAsset",
|
|
253
|
-
"description": "Update an existing asset in AEM DAM",
|
|
254
|
-
"parameters": [
|
|
255
|
-
"assetPath",
|
|
256
|
-
"metadata",
|
|
257
|
-
"fileContent",
|
|
258
|
-
"mimeType"
|
|
259
|
-
]
|
|
260
|
-
},
|
|
261
|
-
{
|
|
262
|
-
"name": "deleteAsset",
|
|
263
|
-
"description": "Delete an asset from AEM DAM",
|
|
264
|
-
"parameters": [
|
|
265
|
-
"assetPath",
|
|
266
|
-
"force"
|
|
267
|
-
]
|
|
268
|
-
},
|
|
269
|
-
{
|
|
270
|
-
"name": "getTemplates",
|
|
271
|
-
"description": "Get available page templates",
|
|
272
|
-
"parameters": [
|
|
273
|
-
"sitePath"
|
|
274
|
-
]
|
|
275
|
-
},
|
|
276
|
-
{
|
|
277
|
-
"name": "getTemplateStructure",
|
|
278
|
-
"description": "Get detailed structure of a specific template",
|
|
279
|
-
"parameters": [
|
|
280
|
-
"templatePath"
|
|
281
|
-
]
|
|
282
|
-
}
|
|
283
|
-
],
|
|
284
|
-
"total": 35
|
|
285
|
-
}
|
|
286
|
-
```
|
package/docs/CHANGELOG.md
DELETED
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
# [1.3.0](https://github.com/easingthemes/aem-mcp-server/compare/v1.2.0...v1.3.0) (2025-08-10)
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
### Features
|
|
5
|
-
|
|
6
|
-
* add logger, change port ([f4ee48b](https://github.com/easingthemes/aem-mcp-server/commit/f4ee48b32fde2034b53f29fb2efa3aef9ba20f39))
|
|
7
|
-
|
|
8
|
-
# [1.2.0](https://github.com/easingthemes/aem-mcp-server/compare/v1.1.5...v1.2.0) (2025-08-10)
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
### Features
|
|
12
|
-
|
|
13
|
-
* add AEMaaCS OAuth support, add fetch retry on 401 ([0f53d1a](https://github.com/easingthemes/aem-mcp-server/commit/0f53d1a4bc8bc622f018f68c021d95e4a0791e78))
|
|
14
|
-
|
|
15
|
-
## [1.1.5](https://github.com/easingthemes/aem-mcp-server/compare/v1.1.4...v1.1.5) (2025-08-08)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
### Bug Fixes
|
|
19
|
-
|
|
20
|
-
* remove invalid empty `prompts` ([92c64d3](https://github.com/easingthemes/aem-mcp-server/commit/92c64d3d2db3ff32ce0e2b651b22697940761dd0))
|
|
21
|
-
|
|
22
|
-
## [1.1.4](https://github.com/easingthemes/aem-mcp-server/compare/v1.1.3...v1.1.4) (2025-07-19)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
### Bug Fixes
|
|
26
|
-
|
|
27
|
-
* [docs] simplify Readme ([6e00bef](https://github.com/easingthemes/aem-mcp-server/commit/6e00bef7a498d872573549cc7d35206affe98bba))
|
|
28
|
-
|
|
29
|
-
## [1.1.3](https://github.com/easingthemes/aem-mcp-server/compare/v1.1.2...v1.1.3) (2025-07-19)
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
### Bug Fixes
|
|
33
|
-
|
|
34
|
-
* [docs] simplify Readme ([12d6753](https://github.com/easingthemes/aem-mcp-server/commit/12d6753d214de6eb49451595025de95df170f66b))
|
|
35
|
-
|
|
36
|
-
## [1.1.2](https://github.com/easingthemes/aem-mcp-server/compare/v1.1.1...v1.1.2) (2025-07-19)
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
### Bug Fixes
|
|
40
|
-
|
|
41
|
-
* [docs] simplify Readme ([c9af9e6](https://github.com/easingthemes/aem-mcp-server/commit/c9af9e67043ced9e54a6bbf83cd1527026ae0c69))
|
|
42
|
-
|
|
43
|
-
## [1.1.1](https://github.com/easingthemes/aem-mcp-server/compare/v1.1.0...v1.1.1) (2025-07-19)
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
### Bug Fixes
|
|
47
|
-
|
|
48
|
-
* [docs] simplify Readme ([3d70ee2](https://github.com/easingthemes/aem-mcp-server/commit/3d70ee2acbdc7cdca291adc326bacf804fd7700c))
|
|
49
|
-
|
|
50
|
-
# [1.1.0](https://github.com/easingthemes/aem-mcp-server/compare/v1.0.12...v1.1.0) (2025-07-19)
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
### Features
|
|
54
|
-
|
|
55
|
-
* [deps] remove swagger ([6cfa01a](https://github.com/easingthemes/aem-mcp-server/commit/6cfa01ac1d8336fb2a5de300cedcc5581726512f))
|
|
56
|
-
|
|
57
|
-
## [1.0.12](https://github.com/easingthemes/aem-mcp-server/compare/v1.0.11...v1.0.12) (2025-07-18)
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
### Bug Fixes
|
|
61
|
-
|
|
62
|
-
* [aem] remove component type check ([6dbf89c](https://github.com/easingthemes/aem-mcp-server/commit/6dbf89c39f78b24e33b3e34992f886c761e6f572))
|
|
63
|
-
|
|
64
|
-
## [1.0.11](https://github.com/easingthemes/aem-mcp-server/compare/v1.0.10...v1.0.11) (2025-07-18)
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
### Bug Fixes
|
|
68
|
-
|
|
69
|
-
* [build] minify ([4760bdc](https://github.com/easingthemes/aem-mcp-server/commit/4760bdcccf6c38b10df4f472c6900279bc09cacb))
|
|
70
|
-
|
|
71
|
-
## [1.0.10](https://github.com/easingthemes/aem-mcp-server/compare/v1.0.9...v1.0.10) (2025-07-18)
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
### Bug Fixes
|
|
75
|
-
|
|
76
|
-
* [docs] add docs dir ([d8e6f04](https://github.com/easingthemes/aem-mcp-server/commit/d8e6f04dc8963d559d258d1491d5ea81e4b9d9e0))
|
|
77
|
-
|
|
78
|
-
## [1.0.9](https://github.com/easingthemes/aem-mcp-server/compare/v1.0.8...v1.0.9) (2025-07-18)
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
### Bug Fixes
|
|
82
|
-
|
|
83
|
-
* [docs] add params info ([b4f128d](https://github.com/easingthemes/aem-mcp-server/commit/b4f128db6aed5d159cd18aa93692e2948c99ffb0))
|
|
84
|
-
|
|
85
|
-
## [1.0.8](https://github.com/easingthemes/aem-mcp-server/compare/v1.0.7...v1.0.8) (2025-07-18)
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
### Bug Fixes
|
|
89
|
-
|
|
90
|
-
* [config] remove dotenv ([2c0ddcd](https://github.com/easingthemes/aem-mcp-server/commit/2c0ddcdb9b5b2c60bb27bfad8dcfeebe39275510))
|
|
91
|
-
|
|
92
|
-
## [1.0.7](https://github.com/easingthemes/aem-mcp-server/compare/v1.0.6...v1.0.7) (2025-07-18)
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
### Bug Fixes
|
|
96
|
-
|
|
97
|
-
* [cli] npm pkg fix ([34dc243](https://github.com/easingthemes/aem-mcp-server/commit/34dc243d1064120b595bc0eb242e3c446bb4c54c))
|
|
98
|
-
|
|
99
|
-
## [1.0.6](https://github.com/easingthemes/aem-mcp-server/compare/v1.0.5...v1.0.6) (2025-07-18)
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
### Bug Fixes
|
|
103
|
-
|
|
104
|
-
* [cli] add node bin ([50d73f4](https://github.com/easingthemes/aem-mcp-server/commit/50d73f4a1ee1ee037366aa8a0d42639c8602a2fe))
|
|
105
|
-
|
|
106
|
-
## [1.0.5](https://github.com/easingthemes/aem-mcp-server/compare/v1.0.4...v1.0.5) (2025-07-18)
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
### Bug Fixes
|
|
110
|
-
|
|
111
|
-
* [cli] remove test script ([e9d2325](https://github.com/easingthemes/aem-mcp-server/commit/e9d2325e46976965df6fa4e04bfda2047a0927d5))
|
|
112
|
-
* [cli] use es6 ([ef3327c](https://github.com/easingthemes/aem-mcp-server/commit/ef3327c9c6f78e459e756c0f41c13b6002c19193))
|
|
113
|
-
|
|
114
|
-
## [1.0.4](https://github.com/easingthemes/aem-mcp-server/compare/v1.0.3...v1.0.4) (2025-07-18)
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
### Bug Fixes
|
|
118
|
-
|
|
119
|
-
* [cli] fix cli params ([6405d05](https://github.com/easingthemes/aem-mcp-server/commit/6405d0584586bf2e06c6333757ccee292dceac38))
|
|
120
|
-
|
|
121
|
-
## [1.0.3](https://github.com/easingthemes/aem-mcp-server/compare/v1.0.2...v1.0.3) (2025-07-18)
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
### Bug Fixes
|
|
125
|
-
|
|
126
|
-
* [build] fix build path ([683b87f](https://github.com/easingthemes/aem-mcp-server/commit/683b87fb3cad42867baa851cce766ec956c1c637))
|
|
127
|
-
|
|
128
|
-
## [1.0.2](https://github.com/easingthemes/aem-mcp-server/compare/v1.0.1...v1.0.2) (2025-07-18)
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
### Bug Fixes
|
|
132
|
-
|
|
133
|
-
* [cli] add cli params ([59c6a5e](https://github.com/easingthemes/aem-mcp-server/commit/59c6a5ef72ea2fe5f16278655af433b3a17843fc))
|
|
134
|
-
|
|
135
|
-
## [1.0.1](https://github.com/easingthemes/aem-mcp-server/compare/v1.0.0...v1.0.1) (2025-07-18)
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
### Bug Fixes
|
|
139
|
-
|
|
140
|
-
* [cli] simplify usage ([3e5981c](https://github.com/easingthemes/aem-mcp-server/commit/3e5981c49a8a843eda16482f041a2c291051d68e))
|
|
141
|
-
|
|
142
|
-
# 1.0.0 (2025-07-17)
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
### Bug Fixes
|
|
146
|
-
|
|
147
|
-
* [npm] enable npm release ([3165378](https://github.com/easingthemes/aem-mcp-server/commit/3165378659357d060c03e0798ad50eb44328d429))
|
package/docs/CODE_OF_CONDUCT.md
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
# Netcentric Code of Conduct
|
|
2
|
-
|
|
3
|
-
## Our Pledge
|
|
4
|
-
|
|
5
|
-
In the interest of fostering an open and welcoming environment, we as
|
|
6
|
-
contributors and maintainers pledge to making participation in our project and
|
|
7
|
-
our community a harassment-free experience for everyone, regardless of age, body
|
|
8
|
-
size, disability, ethnicity, gender identity and expression, level of experience,
|
|
9
|
-
nationality, personal appearance, race, religion, or sexual identity and
|
|
10
|
-
orientation.
|
|
11
|
-
|
|
12
|
-
## Our Standards
|
|
13
|
-
|
|
14
|
-
Examples of behavior that contributes to creating a positive environment
|
|
15
|
-
include:
|
|
16
|
-
|
|
17
|
-
* Using welcoming and inclusive language
|
|
18
|
-
* Being respectful of differing viewpoints and experiences
|
|
19
|
-
* Gracefully accepting constructive criticism
|
|
20
|
-
* Focusing on what is best for the community
|
|
21
|
-
* Showing empathy towards other community members
|
|
22
|
-
|
|
23
|
-
Examples of unacceptable behavior by participants include:
|
|
24
|
-
|
|
25
|
-
* The use of sexualized language or imagery and unwelcome sexual attention or
|
|
26
|
-
advances
|
|
27
|
-
* Trolling, insulting/derogatory comments, and personal or political attacks
|
|
28
|
-
* Public or private harassment
|
|
29
|
-
* Publishing others' private information, such as a physical or electronic
|
|
30
|
-
address, without explicit permission
|
|
31
|
-
* Other conduct which could reasonably be considered inappropriate in a
|
|
32
|
-
professional setting
|
|
33
|
-
|
|
34
|
-
## Our Responsibilities
|
|
35
|
-
|
|
36
|
-
Project maintainers are responsible for clarifying the standards of acceptable
|
|
37
|
-
behavior and are expected to take appropriate and fair corrective action in
|
|
38
|
-
response to any instances of unacceptable behavior.
|
|
39
|
-
|
|
40
|
-
Project maintainers have the right and responsibility to remove, edit, or
|
|
41
|
-
reject comments, commits, code, wiki edits, issues, and other contributions
|
|
42
|
-
that are not aligned to this Code of Conduct, or to ban temporarily or
|
|
43
|
-
permanently any contributor for other behaviors that they deem inappropriate,
|
|
44
|
-
threatening, offensive, or harmful.
|
|
45
|
-
|
|
46
|
-
## Scope
|
|
47
|
-
|
|
48
|
-
This Code of Conduct applies both within project spaces and in public spaces
|
|
49
|
-
when an individual is representing the project or its community. Examples of
|
|
50
|
-
representing a project or community include using an official project e-mail
|
|
51
|
-
address, posting via an official social media account, or acting as an appointed
|
|
52
|
-
representative at an online or offline event. Representation of a project may be
|
|
53
|
-
further defined and clarified by project maintainers.
|
|
54
|
-
|
|
55
|
-
## Enforcement
|
|
56
|
-
|
|
57
|
-
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
58
|
-
reported by contacting the project team at Grp-opensourceoffice@adobe.com. All
|
|
59
|
-
complaints will be reviewed and investigated and will result in a response that
|
|
60
|
-
is deemed necessary and appropriate to the circumstances. The project team is
|
|
61
|
-
obligated to maintain confidentiality with regard to the reporter of an incident.
|
|
62
|
-
Further details of specific enforcement policies may be posted separately.
|
|
63
|
-
|
|
64
|
-
Project maintainers who do not follow or enforce the Code of Conduct in good
|
|
65
|
-
faith may face temporary or permanent repercussions as determined by other
|
|
66
|
-
members of the project's leadership.
|
|
67
|
-
|
|
68
|
-
## Attribution
|
|
69
|
-
|
|
70
|
-
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
|
71
|
-
available at [http://contributor-covenant.org/version/1/4][version]
|
|
72
|
-
|
|
73
|
-
[homepage]: https://contributor-covenant.org
|
|
74
|
-
[version]: https://contributor-covenant.org/version/1/4/
|
package/docs/CONTRIBUTING.md
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# Contributing
|
|
2
|
-
|
|
3
|
-
Thanks for choosing to contribute!
|
|
4
|
-
|
|
5
|
-
The following are a set of guidelines to follow when contributing to this project.
|
|
6
|
-
|
|
7
|
-
## Code Of Conduct
|
|
8
|
-
|
|
9
|
-
This project adheres to the <COMPANY> [code of conduct](CODE_OF_CONDUCT.md). By participating,
|
|
10
|
-
you are expected to uphold this code.
|
|
11
|
-
|
|
12
|
-
## Have A Question?
|
|
13
|
-
|
|
14
|
-
Start by filing an issue. The existing committers on this project work to reach
|
|
15
|
-
consensus around project direction and issue solutions within issue threads
|
|
16
|
-
(when appropriate).
|
|
17
|
-
|
|
18
|
-
## Code Reviews
|
|
19
|
-
|
|
20
|
-
All submissions should come in the form of pull requests and need to be reviewed
|
|
21
|
-
by project committers. Read [GitHub's pull request documentation](https://help.github.com/articles/about-pull-requests/)
|
|
22
|
-
for more information on sending pull requests.
|
|
23
|
-
|
|
24
|
-
Lastly, please follow the [pull request template](../.github/PULL_REQUEST_TEMPLATE.md) when
|
|
25
|
-
submitting a pull request!
|
package/docs/cursor.png
DELETED
|
Binary file
|