aem-mcp-server 1.6.0 → 1.6.1

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 CHANGED
@@ -124,16 +124,19 @@ All tools will get an `instance` parameter to target a specific instance.
124
124
 
125
125
  ## Features
126
126
 
127
- - **AEM Page & Asset Management**: Create, update, delete, activate, deactivate, and replicate pages and assets
127
+ - **57 MCP Tools** covering pages, components, assets, workflows, content fragments, and experience fragments
128
+ - **MCP Resources** — agents discover components, sites, templates, and workflow models upfront via `resources/list`, eliminating discovery roundtrips
129
+ - **Tool Annotations** — every tool tagged with `group`, `readOnly`, and `complexity` so agents can make smarter tool selection decisions
130
+ - **Response Verbosity** — `verbosity` parameter (`summary`/`standard`/`full`) on content-reading tools strips JCR internals and truncates long text
131
+ - **Actionable Errors** — error responses include `suggestion` and `alternatives` fields for self-healing agent workflows
128
132
  - **Component Operations**: Update, scan, add, convert, and bulk-manage AEM components (including Experience Fragments)
133
+ - **Content & Experience Fragments**: Full CRUD + variation management for both CF and XF
129
134
  - **Advanced Search**: QueryBuilder, fulltext, fuzzy, and enhanced page search
130
- - **Replication & Rollout**: Publish/unpublish content, roll out changes to language copies
135
+ - **Replication & Workflows**: Publish/unpublish content, start/advance/delegate workflow stages
131
136
  - **Text & Image Extraction**: Extract all text and images from pages, including fragments
132
137
  - **Template & Structure Discovery**: List templates, analyze page/component structure
133
- - **Workflow and Inbox Operations**: List, start, advance, suspend, and delegate workflow stages
134
- - **JCR Node Access**: Legacy and modern node/content access
135
- - **AI/LLM Integration**: Natural language interface for AEM via any MCP-compatible client
136
- - **Security**: Auth, environment-based config, and safe operation defaults
138
+ - **Multi-instance**: Connect to multiple AEM instances simultaneously; tools and resources are instance-aware
139
+ - **Security**: Basic auth and OAuth S2S, environment-based config, safe operation defaults
137
140
 
138
141
  ---
139
142
 
@@ -145,6 +148,19 @@ Once configured in your AI IDE, just ask in natural language:
145
148
  List all components on MyPage
146
149
  ```
147
150
 
151
+ ## MCP Resources
152
+
153
+ The server exposes read-only MCP resources so agents can discover AEM catalogs without tool calls:
154
+
155
+ | Resource URI | Description |
156
+ |---|---|
157
+ | `aem://{instance}/components` | All components (name, resourceType, title, group) |
158
+ | `aem://{instance}/sites` | Site roots and language structure under /content |
159
+ | `aem://{instance}/templates` | Available page templates (path, title) |
160
+ | `aem://{instance}/workflow-models` | Workflow models (ID, title, description) |
161
+
162
+ Resources return summary data only. In multi-instance mode, each instance gets its own set of resource URIs.
163
+
148
164
  ## API Documentation
149
165
 
150
166
  For detailed API documentation, please refer to the [API Docs](docs/API.md).
@@ -1 +1 @@
1
- "use strict";import{MCPRequestHandler as h}from"./mcp.aem-handler.js";import{LOGGER as c}from"../utils/logger.js";export class InstanceRegistry{handlers=new Map;defaultInstance;constructor(e){const a=this.parseInstances(e);for(const s of a){const n={host:s.host,user:s.user,pass:s.pass,id:s.id,secret:s.secret};this.handlers.set(s.name,new h(n)),c.log(`Registered AEM instance: "${s.name}" \u2192 ${s.host}`)}this.defaultInstance=a[0].name,c.log(`Default instance: "${this.defaultInstance}"`)}parseInstances(e){if(e.instances){const a=e.instances.split(",").map(n=>n.trim()).filter(Boolean),s=[];for(const n of a){const t=n.split(":");if(t.length<4){c.error(`Invalid instance format: "${n}" \u2014 expected "name:host:user:pass" or "name:https://host:user:pass"`);continue}let i,r,o,l;t[1]?.startsWith("//")||t[2]?.startsWith("//")?(i=t[0],r=t[1]+":"+t[2],o=t[3],l=t.slice(4).join(":")):(i=t[0],r=t[1],o=t[2],l=t.slice(3).join(":"),r.startsWith("http")||(r=`http://${r}`)),s.push({name:i,host:r,user:o||"admin",pass:l||"admin"})}if(s.length===0)throw new Error("No valid instances parsed from --instances flag");return s}return[{name:"default",host:e.host||"http://localhost:4502",user:e.user||"admin",pass:e.pass||"admin",id:e.id,secret:e.secret}]}getHandler(e){const a=e||this.defaultInstance,s=this.handlers.get(a);if(!s){const n=Array.from(this.handlers.keys()).join(", ");throw new Error(`Unknown AEM instance: "${a}". Available: ${n}`)}return s}getDefaultName(){return this.defaultInstance}getInstanceNames(){return Array.from(this.handlers.keys())}}
1
+ "use strict";import{MCPRequestHandler as d}from"./mcp.aem-handler.js";import{LOGGER as h}from"../utils/logger.js";export class InstanceRegistry{handlers=new Map;defaultInstance;constructor(e){const a=this.parseInstances(e);for(const t of a){const n={host:t.host,user:t.user,pass:t.pass,id:t.id,secret:t.secret};this.handlers.set(t.name,new d(n)),h.log(`Registered AEM instance: "${t.name}" \u2192 ${t.host}`)}this.defaultInstance=a[0].name,h.log(`Default instance: "${this.defaultInstance}"`)}parseInstances(e){if(e.instances){const a=e.instances.split(",").map(n=>n.trim()).filter(Boolean),t=[];for(const n of a){const s=n.split(":");if(s.length<4){h.error(`Invalid instance format: "${n}" \u2014 expected "name:host:user:pass" or "name:https://host:user:pass"`);continue}let o,r,l,c;if(s[1]?.startsWith("//")||s[2]?.startsWith("//")){o=s[0],r=s[1]+":"+s[2];let i=3;s[i]&&/^\d+$/.test(s[i])&&(r+=":"+s[i],i++),l=s[i]||"admin",c=s.slice(i+1).join(":")||"admin"}else o=s[0],r=s[1],l=s[2],c=s.slice(3).join(":"),r.startsWith("http")||(r=`http://${r}`);t.push({name:o,host:r,user:l||"admin",pass:c||"admin"})}if(t.length===0)throw new Error("No valid instances parsed from --instances flag");return t}return[{name:"default",host:e.host||"http://localhost:4502",user:e.user||"admin",pass:e.pass||"admin",id:e.id,secret:e.secret}]}getHandler(e){const a=e||this.defaultInstance,t=this.handlers.get(a);if(!t){const n=Array.from(this.handlers.keys()).join(", ");throw new Error(`Unknown AEM instance: "${a}". Available: ${n}`)}return t}getDefaultName(){return this.defaultInstance}getInstanceNames(){return Array.from(this.handlers.keys())}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aem-mcp-server",
3
- "version": "1.6.0",
3
+ "version": "1.6.1",
4
4
  "description": "AEM MCP server. Chat with your AEM instance for content, component, and asset operations.",
5
5
  "license": "AGPL-3.0-only",
6
6
  "private": false,