Spec Driven Development
MCP Server that facilitates spec-driven development workflows, not just Vibe Coding.
Descripción del creador (original en inglés)
Full-CRUD server for AEP, Journey Optimizer and CJA. 61 tools from one OAuth credential.
Estos tres nunca se combinan en una sola puntuación: las opiniones, las mediciones y la popularidad son cosas distintas.
Todavía no escribimos un resumen sencillo para este. Abajo están los datos que leímos del registro.
Elige la app de IA que usas y copia la configuración.
AEP_CLIENT_ID, AEP_CLIENT_SECRET, AEP_ORG_ID, AEP_SANDBOX_NAME, AEP_MODE, LOG_LEVELLos valores marcados como secretos son llaves de tu cuenta. Nunca los compartas ni los pegues en un chat.
Necesitas
¿Qué app usas?
Elige tu app arriba. La recordamos, así que la próxima vez el botón dirá “Instalar en …”.
Abre Claude Desktop → Settings → Developer → Edit Config y pega esto en claude_desktop_config.json
{
"mcpServers": {
"aep": {
"command": "npx",
"args": [
"-y",
"@focusgts/aep-mcp-server"
],
"env": {
"AEP_CLIENT_ID": "your-value",
"AEP_CLIENT_SECRET": "your-value",
"AEP_ORG_ID": "your-value",
"AEP_SANDBOX_NAME": "your-value",
"AEP_MODE": "your-value",
"LOG_LEVEL": "your-value"
}
}
}
}Ejecuta esto en tu terminal
claude mcp add aep --env AEP_CLIENT_ID=your-value --env AEP_CLIENT_SECRET=your-value --env AEP_ORG_ID=your-value --env AEP_SANDBOX_NAME=your-value --env AEP_MODE=your-value --env LOG_LEVEL=your-value -- npx -y @focusgts/aep-mcp-serverCompleta los valores vacíos antes de ejecutarlo.
Pégalo en .cursor/mcp.json de tu proyecto, o en ~/.cursor/mcp.json
{
"mcpServers": {
"aep": {
"command": "npx",
"args": [
"-y",
"@focusgts/aep-mcp-server"
],
"env": {
"AEP_CLIENT_ID": "your-value",
"AEP_CLIENT_SECRET": "your-value",
"AEP_ORG_ID": "your-value",
"AEP_SANDBOX_NAME": "your-value",
"AEP_MODE": "your-value",
"LOG_LEVEL": "your-value"
}
}
}
}Tu navegador te pide permiso para abrir la app; luego la app muestra la configuración y te pide confirmar. Los valores de las claves quedan vacíos para que los completes tú.
Pégalo en .vscode/mcp.json de tu proyecto
{
"servers": {
"aep": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"@focusgts/aep-mcp-server"
],
"env": {
"AEP_CLIENT_ID": "your-value",
"AEP_CLIENT_SECRET": "your-value",
"AEP_ORG_ID": "your-value",
"AEP_SANDBOX_NAME": "your-value",
"AEP_MODE": "your-value",
"LOG_LEVEL": "your-value"
}
}
}
}Tu navegador te pide permiso para abrir la app; luego la app muestra la configuración y te pide confirmar. Los valores de las claves quedan vacíos para que los completes tú.
Este se ejecuta en tu computadora, y ChatGPT solo puede conectarse a servidores en internet. Elige otra app.
Tu elección se guarda en una cookie en este dispositivo; no necesitas cuenta.
AEP_SANDBOX_NAME envAEP_MODE envLOG_LEVEL envEsta configuración se genera a partir de la ficha del creador en el registro. Si el README dice otra cosa, sigue el README.
Se ejecuta en tu computadora; la lista de herramientas aparece en tu app de IA después de instalarlo.
Revisamos información que cualquiera puede ver; no hemos leído el código. Las revisiones que no aplican no se cuentan. · Revisado el 6 nov 2026
El nombre en el registro se verificó con el dominio focusgts.com (el registro comprueba quién es dueño del dominio)
Todavía no hemos leído este repo en GitHub
Todavía no hemos leído este repo en GitHub
Este se ejecuta en tu computadora; no hay endpoint en internet
Se ejecuta en tu computadora y usa ajustes locales en su lugar
Se ejecuta en tu computadora; solo podemos leer listas de herramientas de endpoints en internet
Comparado con todos los servidores activos de esta categoría en el registro. Las estrellas solo cuentan cuando quien lo publica es dueño del repo.
Superó 1 de 1 revisiones básicas aplicables. No hemos leído el código. Antes de agregar una clave o un token, revisa qué acceso pide el servidor y usa una clave que tenga solo los permisos que necesitas.
Debes completar: AEP_CLIENT_ID, AEP_CLIENT_SECRET, AEP_ORG_ID
Se ejecuta en tu computadora. Tu app de IA lo inicia cuando hace falta, y los datos no pasan por los servidores del creador (a menos que el propio servidor llame a un servicio en línea).
El repo de GitHub cambió por última vez –, y la última versión (0.11.1) llegó al registro hace 2 meses.
Las apps compatibles con MCP, como Claude Desktop, Claude Code, Cursor y VS Code. También necesitas Node.js en tu computadora.
En la misma categoría: Spec Driven Development, Remote Desktop Commander, Recta
Servidores de la misma categoría hechos por otros creadores, ordenados por estrellas.
Cómo leer una tarjeta:★ Estrellas de GitHubiTres pilares: reseñas · revisiones · usoiActualizado = fecha en que se publicó la última versión en el registroi
MCP Server that facilitates spec-driven development workflows, not just Vibe Coding.
Remote Desktop Commander: use files, terminal and processes on your own computers from any AI app.
Cheaper cross-chain stablecoin routes for AI agents; 5 % of the verified saving, nothing if none.
Copiado tal cual del repo del creador. PopNx MCP no lo ha revisado ni lo respalda. Se quitaron HTML, imágenes y scripts. Los enlaces llevan fuera de este sitio.
61 tools across 14 categories. Full read AND write. Self-hosted, Apache-2.0, no invitation required. Experience Platform, Journey Optimizer and Customer Journey Analytics — from one OAuth credential.
Ingest a batch → compose a schema → activate an audience → honour an erasure. Every mutation gated by a fail-closed write guard that asks Adobe what kind of sandbox it's in.
claude mcp add aep \
-e AEP_CLIENT_ID=... -e AEP_CLIENT_SECRET=... \ -e AEP_ORG_ID=...@AdobeOrg -e AEP_SANDBOX_NAME=your-dev-sandbox \ -- npx -y @focusgts/aep-mcp-server
Then just ask your agent:
*"Create a schema with the Demographic Details field group, then a dataset on it."*
*"Ingest this NDJSON file and tell me when the batch lands."*
*"Build an audience of customers who bought twice this quarter and activate it."*
*"Delete every record for this email address — dry run first."*
Writes are off until you ask for them, and safe mode only unlocks sandboxes Adobe classifies as development.
flowchart LR
A["📐 Compose schema from field groups"] --> B["🗂️ Create dataset"] B --> C["📥 Ingest batch · upload · complete"] C --> D["🎯 Activate segment → destination"] D --> E["🧹 Govern erasure · expiration · quota"] E -. "re-audit the tenant" .-> A
Adobe's first-party gateway can *tell you* what's in your Experience Platform tenant. It cannot create a dataset, land a batch, activate an audience, or submit an erasure. This does — and does it behind a guard that fails closed.
flowchart LR
A["AI agent (Claude · Cursor · Copilot)"] -- MCP / stdio --> B["aep-mcp-server 61 tools"] B --> W{{"write guard fail-closed"}} W --> C["Schema Registry · Catalog Ingestion · Lifecycle · Privacy"] C --> F["Your AEP sandbox platform.adobe.io"] B --> J["Journey Optimizer read-only"] J --> K["ajo campaigns"] B --> Q["Customer Journey Analytics read-only, no sandbox"] Q --> L["cja.adobe.io"]
The agent calls tools; the server talks to live Adobe APIs over OAuth Server-to-Server. The write guard sits in the HTTP client, not in each tool, so all 61 inherit it and none can forget it. Blocked calls never reach Adobe.
Three postures. Reads are never restricted in any mode.
AEP_MODE | Writes permitted | Use it when |
|---|---|---|
read-only | Never, in any sandbox | Handing the server to someone to explore an environment you don't want touched |
| `safe` *(default)* | Only where Adobe classifies the sandbox development | Evaluating, or letting an agent work without risking production |
production | Anywhere, including production | You run your own change control and don't want the server second-guessing you |
How `safe` decides — and why it's not the sandbox name.
A production sandbox can be called anything, and a sandbox called
prodmight not be production. Only Adobe'stypefield from the Sandbox Management API decides.
It fails closed. If the type can't be determined — the credential can't read sandbox metadata, the API errors, startup hasn't finished — writes are blocked. A credential must not earn write access by being *less* capable. An unrecognised
AEP_MODEfalls back tosafe, so a typo can never grant production writes.
A sandbox literally named `prod` is refused unconditionally, before mode resolution — so
AEP_MODE=productiondoes not lift it. Override withAEP_I_UNDERSTAND_THIS_WRITES_TO_PROD=trueonly if that really is your sandbox's name. The inference is deliberately asymmetric: trusting a name to *allow* a write is unsafe, trusting one to *deny* a write is safe, because the worst case is a refusal you can override on purpose.
Mutations are off entirely unless
AEP_ALLOW_MUTATIONS=true. That is separate fromAEP_MODEon purpose: choosing a write mode should not also mean "yes, you may change my data".
Startup always states the active posture:
SAFE MODE — sandbox is a development sandbox, so writes are ENABLED.
SAFE MODE — sandbox is PRODUCTION, so writes are BLOCKED. Reads work normally. SAFE MODE — sandbox type could not be confirmed, so writes are BLOCKED (fail-closed). READ-ONLY MODE — no write, update, or delete will be performed in any sandbox. PRODUCTION MODE — writes permitted against ANY sandbox, including production.
Writes are not *uniformly* gated — uniform gating makes an agent useless. Gates sit where an action is irreversible and wide-reaching, and every one is checked before any network call:
| Tool | Gate |
|---|---|
aep_create_record_delete | dryRun defaults true. Real submission needs confirm: "DELETE RECORDS " — bound to the dataset and a SHA-256 digest of the exact identity set, so a confirmation can't be reused for a different deletion. ALL and multi-dataset targets are refused. |
aep_delete_segment | confirm: "DELETE SEGMENT " — segments were create-only until 0.9.1, so every one an agent made was permanent |
aep_delete_dataset | confirm: "DELETE DATASET ", escalating to "DELETE PROFILE-ENABLED DATASET " when the dataset feeds Profile |
aep_complete_batch | confirm: "COMPLETE BATCH " — the point of no return for ingestion |
aep_revert_batch | confirm: "REVERT BATCH " |
aep_create_dataset_expiration | confirm: "CREATE DATASET EXPIRATION " — unless dryRun: true |
aep_update_dataset_expiration | confirm: "UPDATE DATASET EXPIRATION " |
aep_cancel_dataset_expiration | confirm: "CANCEL DATASET EXPIRATION " |
aep_delete_profile | confirm: "I understand this is irreversible" *(deprecated — prefer Data Hygiene)* |
Confirmations name their target. A phrase carrying the dataset id — and for record delete, a hash of the identities too — cannot be copied from one call to another. A generic "I understand this is irreversible" approves *any* deletion once you've typed it once.
Identity values never leave the process.
aep_create_record_deletereturns a count, the namespace names, and a digest — never the email addresses or device IDs you passed it. A record-delete request is by nature a list of real people; a tool that echoes them copies them into every transcript and log sink it touches.
Batch creation and file upload are ungated on purpose: those writes are additive and recoverable. An unwanted batch can be left uncompleted, and data that did land can be removed with the Data Hygiene tools.
Every tool ships MCP annotations — readOnlyHint, destructiveHint, idempotentHint, openWorldHint — derived from the same metadata that builds its description, so the two cannot drift.
| Count | |
|---|---|
readOnlyHint: true | 39 |
destructiveHint: true | 8 |
| Un-annotated | 0 |
These are hints *for the client*, not enforcement — the guards above enforce. Their value is that a client like Claude Desktop uses destructiveHint to decide when to interrupt and ask a human. Without them aep_delete_profile looks identical to aep_list_schemas. A test asserts the destructive list exactly, so a ninth is a deliberate act rather than an oversight.
All prefixed aep_, verb_noun naming. 🔒 changes state · 🔥 destructive.
Schemas (4)
list_schemasget_schemacreate_schema 🔒update_schema 🔒Datasets (4)
list_datasetsget_datasetcreate_dataset 🔒delete_dataset 🔥Ingestion (7)
create_batch 🔒upload_batch_file 🔒complete_batch 🔥get_batch_statuslist_batchesabort_batch 🔥revert_batch 🔥Sources (2)
list_sourceslist_dataflowsQuery Service (3)
run_query 🔒get_query_statuslist_queriesIdentities (2)
list_identity_namespacesget_identity_graphProfiles (4)
get_profileget_profile_by_identitypreview_profiledelete_profile 🔥Segments (5)
list_segmentsget_segmentcreate_segment 🔒estimate_segment_sizedelete_segment 🔥Destinations (3)
list_destinationscreate_destination_connection 🔒activate_segment 🔒Privacy Service (6)
create_privacy_job 🔒get_privacy_joblist_privacy_jobscancel_privacy_job 🔒get_privacy_job_resultslist_privacy_namespacesData Hygiene (9)
create_record_delete 🔥get_work_order_statuslist_work_ordersget_data_lifecycle_quotacreate_dataset_expiration 🔥get_dataset_expirationlist_dataset_expirationsupdate_dataset_expiration 🔥cancel_dataset_expiration 🔥Workflows these unlock
Ingest end to end —
create_schema→create_dataset→create_batch→upload_batch_file→complete_batch→get_batch_status
Build and activate an audience —
create_segment→estimate_segment_size→list_destinations→create_destination_connection→activate_segment
Honour an erasure request —
get_profile_by_identity→create_record_delete→get_work_order_status
Retire data on a schedule —
create_dataset_expiration→list_dataset_expirations→update_dataset_expiration→cancel_dataset_expiration
What's actually been run against a live tenant is recorded per tool in docs/VALIDATION-MATRIX.md — including the surfaces that are documented-and-mocked but deliberately never executed, and why.
AJO is a separate Adobe product, licensed separately — hence the ajo_ prefix, so an entitlement failure reads as one.
Campaigns
ajo_list_campaignsajo_get_campaignCampaigns is the only AJO surface reachable on our tenant. Journeys, messages, channel surfaces, content templates, fragments, offers and decisions all return an HTML 404 — the gateway has no such route — so they are deliberately not implemented.
Writes are absent on purpose. The routes exist, but shipping an unva
Solo se muestra el principio; lee el resto en el repo