Ciltress/sap-abap-mcp
SAP ABAP MCP - ADT y JSON RPC
Documentación
Estado: experimental. Úsese con precaución en sistemas productivos.
Servidor MCP ABAP ADT
Un servidor MCP que da a un agente de IA acceso completo de lectura/escritura a un sistema SAP ABAP a través de ADT (ABAP Development Tools), autenticado con inicio de sesión único SPNEGO/Kerberos, un certificado de cliente X.509 o un token portador OAuth 2.0 — sin contraseña en ningún lugar de la configuración. Usuario y contraseña siguen disponibles como respaldo, ¡pero no se recomienda!
Envuelve abap-adt-api y añade una cosa que ADT por sí mismo no puede hacer: llamar módulos de función habilitados para RFC, a través del servicio JSON-RPC 2.0 de SAP Gateway.
128 herramientas — CRUD de objetos, edición de código fuente, bloqueos, transportes, activación, comprobaciones de sintaxis, autocompletado de código, ABAP Unit, ATC, DDIC, abapGit, refactorización, trazas, el depurador y llamadas RFC.
Cuántas ve realmente un cliente es menor, por partida doble. Los perfiles (ABAP_MCP_PROFILE) intercambian superficie por contexto: core lista 9 herramientas mientras que all lista 129, lo que supone ~2.700 tokens frente a ~17.800 en cada turno para un cliente que no puede obtener esquemas de herramientas bajo demanda. Y el servidor pregunta al sistema qué soporta antes de listar nada, de modo que una versión sin el plugin de abapGit nunca recibe las 10 herramientas que responderían 400. En DEV eso deja 116.
Este es el fork SSO de
mcp-abap-abap-adt-apide mario-andreschak. Las principales diferencias: SSO Kerberos en lugar de Basic Auth, las herramientas JSON-RPC/RFC, un router derivado de las definiciones de herramientas y una referencia de herramientas documentada.
Documentación
| Documento | Qué cubre |
|---|---|
AGENTS.md | Trabajar en este repositorio: estructura, convenciones, cómo probar. Léelo antes de cambiar código. |
docs/Tool-Router.md | Lo que quieres hacer → la herramienta que lo hace. Escrito a mano, con las palabras que usa la gente. Empieza aquí si conoces la tarea pero no la herramienta. |
docs/Tool-Reference.md | Las 128 herramientas con sus argumentos, agrupadas por familia. Generado a partir de las definiciones de herramientas, por lo que no puede desviarse del código. |
docs/MCP-Tools.md | Cómo se comporta el servidor. Los perfiles, flujos de trabajo de ruta dorada, semántica de URI y bloqueos de ADT, el modelo de respuesta/error y una matriz de resolución de problemas. Escrito para humanos y para agentes que manejan el servidor. |
docs/ABAP-Skills.md | Las 20 habilidades SAP/ABAP y cómo se asignan a estas herramientas. |
docs/Development-Skills.md | Las 35 habilidades generales de ingeniería incluidas. |
docs/JSON-RPC.md | Notas de diseño y protocolo para las herramientas JSON-RPC / RFC, leídas del código fuente ABAP de /IWBEP/CL_JSRPC_*: el protocolo de red, la garantía LUW detrás de los lotes y las trampas. |
docs/Authentication.md | Los dos modos de inicio de sesión sin contraseña: SSO Kerberos y certificados X.509 para usuarios de servicio y técnicos. Qué necesita SAP configurado y por qué esto es TLS mutuo en lugar de SNC. |
Características
- Dos modos de inicio de sesión sin contraseña — SPNEGO/Kerberos con el ticket del usuario de Windows con sesión iniciada, o un certificado de cliente X.509 para un usuario de servicio o técnico que no tiene identidad Kerberos. No se almacena ni envía ninguna contraseña SAP en ninguno de los dos casos, y ambos se auto-reparan cuando la sesión expira.
- Leer cualquier objeto por nombre —
readAbapObjectresuelve un nombre a su código fuente en una sola llamada; sin URL ADT que descubrir o construir a mano. - Describir una tabla —
describeAbapTabledevuelve campos, tipos DDIC, indicadores de clave y tablas de verificación. - Gestión de objetos — buscar, leer, crear, modificar, eliminar y activar objetos ABAP.
- Examinar una convención de nombres —
searchPackagesencuentra paquetes por patrón (["ZPP_*","Z_PP*"]) y expande cada uno en sus objetos agrupados por tipo, en una sola llamada. - Flujo de trabajo de código fuente — bloquear → editar → comprobar sintaxis → activar → desbloquear, con gestión de transportes.
- Inteligencia de código — autocompletado, definiciones, referencias de uso, ABAP Doc, pretty printer, ATC, ABAP Unit, refactorización (renombrar, extraer método).
- Llamar módulos de función RFC —
callFunctionViaJsonRpcejecuta un módulo de función habilitado para RFC y valida la solicitud contra su firma real, leída del sistema. - Llamadas RFC por lotes en una sola LUW —
callFunctionsViaJsonRpcenvía varios módulos de función en una sola solicitud, que es lo que permite que un BAPI de actualización y suBAPI_TRANSACTION_COMMITcompartan una LUW. - Acceso a datos —
tableContentsy SELECTsrunQueryad-hoc. - Ver el sistema en ejecución —
listLoggedOnUsersresponde "quién está conectado" desdeTH_USER_LIST, los datos detrás deSM04;readProfileParameterslee valores RZ11 en un solo viaje de ida y vuelta; ycheckLogonConfigurationindica qué autenticación acepta realmente el sistema. - Habilidades de agente incluidas — 54 habilidades en
skills/, para ABAP (Clean ABAP, RAP, CDS, ATC, abapGit…) e ingeniería general (TDD, revisión de código, diagnóstico de errores), servidas como recursos y a través dereadSkill. - Autodocumentado — las guías siguientes las sirve el propio servidor, como recursos MCP (
abap-adt://guides/…) y a través de la herramientareadServerGuide, de modo que un agente puede consultar un flujo de trabajo o un argumento a mitad de tarea sin salir de la sesión.
Requisitos previos
- Un sistema SAP ABAP accesible a través de ADT.
/sap/bc/adtdebe estar activo enSICF. Para las herramientas RFC,/sap/gw/jsonrpctambién debe estar activo (SAP_GWFND), y tu usuario necesitaS_RFCpara los grupos de funciones que llames. - Una forma de iniciar sesión sin contraseña, una de:
- Un inicio de sesión Kerberos funcional — el sistema SAP debe aceptar SPNEGO y debes tener un ticket válido (
klist). Este es el predeterminado y necesita Windows tal como se distribuye: el bootstrap invoca aC:\Windows\System32\curl.exe --negotiate, que necesita el backend Schannel/SSPI de curl. En otras plataformas apuntaSSO_CURL_PATHa un curl compilado con soporte GSS-API.- Un certificado de cliente X.509 — para un usuario de servicio o técnico que no tiene identidad Kerberos. No necesita ni curl ni Windows. SAP debe estar configurado para ello: el puerto ICM debe solicitar un certificado (
VCLIENTenicm/server_port_<n>, que anulaicm/HTTPS/verify_client), la CA emisora debe ser de confianza enSTRUST, y un mapeoCERTRULEal usuario. Configuración completa — incluido cómo comprobar todo eso desde este servidor — endocs/Authentication.md. - Un cliente OAuth 2.0 — para un entorno ABAP de SAP BTP, donde no hay dominio Kerberos ni ICM que configurar, o para un sistema on-premise que publica ADT a través de
SOAUTH2. Una clave de servicio BTP ya es una de estas. Ver §11.
- Un certificado de cliente X.509 — para un usuario de servicio o técnico que no tiene identidad Kerberos. No necesita ni curl ni Windows. SAP debe estar configurado para ello: el puerto ICM debe solicitar un certificado (
- Un inicio de sesión Kerberos funcional — el sistema SAP debe aceptar SPNEGO y debes tener un ticket válido (
- Node.js (LTS) y npm — verifica con
node -vynpm -v.
Instalación
git clone --recurse-submodules https://github.com/Ciltress/sap-abap-mcp.git
cd sap-abap-mcp
npm install
npm run build
--recurse-submodulesimporta: las habilidades generales de ingeniería viven en un submódulo, y sin él ese directorio está vacío y el servidor ofrece 35 habilidades menos. ¿Ya clonado? Ejecutagit submodule update --init --recursive.
El paquete
npx mcp-abap-abap-adt-apien npm es el servidor upstream y no incluye el bootstrap SSO ni las herramientas RFC. Compila este repositorio desde el código fuente en su lugar.
Configurar
Copia .env.example a .env y completa tu sistema:
SAP_URL=https://your-sap-server.example.com:44301
SAP_USER=YOUR_SAP_USER
SAP_CLIENT=100
SAP_LANGUAGE=EN
SAP_URL y SAP_USER son obligatorios; SAP_CLIENT y SAP_LANGUAGE son opcionales pero recomendados. Tres de los cuatro modos de inicio de sesión no necesitan ningún SAP_PASSWORD en absoluto.
Nunca hagas commit de .env; ya está en .gitignore.
| Variable opcional | Efecto |
|---|---|
SAP_SYSTEM_ID | El id del sistema, como en sy-sysid (p. ej. DEV). Se anuncia en el momento de la conexión para que un cliente pueda elegir entre varios servidores por nombre. Ver Más de un sistema. |
NODE_TLS_REJECT_UNAUTHORIZED=0 | Aceptar un certificado de una CA interna/desconocida. Solo desarrollo. |
SSO_CURL_PATH | Ruta a un binario de curl con soporte SPNEGO, si no es el del sistema Windows. |
SAP_JSONRPC_PATH | Anular la ruta ICF JSON-RPC cuando el nodo se publica bajo un alias. |
ABAP_MCP_PROFILE | Qué herramientas lista este servidor — y por tanto cuáles responderá. Ver más abajo. |
ABAP_MCP_MAX_RESPONSE_BYTES | Tope para una sola respuesta, en bytes. 0 lo elimina. |
ABAP_MCP_GATE | off omite la comprobación de capacidades al inicio que retiene herramientas que esta versión no puede servir. |
ABAP_MCP_RFC_FALLBACK | Iniciar incluso cuando SAP deniega a este usuario el nodo ADT, conservando las herramientas RFC. Ver docs/Authentication.md. |
SAP_FALLBACK_BOOTSTRAP_PATH | A qué nodo ICF inicia sesión ese respaldo. Solo necesita emitir una cookie de sesión y un token CSRF. |
Dimensionar el servidor para su cliente
Las tres variables ABAP_MCP_* existen por una razón: un cliente que no puede obtener esquemas de herramientas bajo demanda paga por la lista completa de herramientas en cada turno. Claude Code difiere los esquemas y debería quedarse en el valor predeterminado; un modelo 8B con una ventana de 128k gasta una sexta parte de su contexto antes de que empiece la conversación, y de ahí viene "el mismo prompt funciona la mitad de las veces".
ABAP_MCP_PROFILE — sin definir significa all, de modo que una configuración existente no cambia.
| perfil | tools/list | coste por turno | para |
|---|---|---|---|
core | 9 | ~2.737 tokens | leer un sistema y completar una edición |
analyst | 18 | ~3.982 tokens | solo lectura: diccionario, datos de tabla, llamadas RFC |
rfc | 10 | ~2.900 tokens | un usuario con derechos RFC pero sin S_DEVELOP, donde las herramientas ADT no pueden funcionar |
dev | 49 | ~8.034 tokens | el ciclo de edición más pruebas, ATC, transportes, refactorización |
all | 129 | ~17.759 tokens | el predeterminado; adecuado para clientes que obtienen esquemas bajo demanda |
Los recuentos incluyen healthcheck, que está fuera de todos los perfiles porque es la herramienta que responde "¿qué perfil estoy ejecutando?".
Un perfil no es un filtro de conveniencia. Una herramienta fuera del perfil activo no se lista ni se enruta, por lo que no se puede llamar — que es lo que convierte a analyst en una garantía de que nada edita código fuente en lugar de un menú más pequeño. Las llamadas fuera de perfil reciben un error que lo dice, en lugar de "herramienta desconocida", así que no tiene sentido reintentar. Un nombre de perfil no reconocido detiene el servidor al inicio en lugar de recurrir a all — servir silenciosamente 129 herramientas a algo que pidió 9 es exactamente el fallo que los perfiles existen para prevenir.
core es pequeño porque una herramienta, editAbapSource, es el ciclo de escritura: bloquear, escribir, activar, desbloquear, liberando el bloqueo incluso cuando un paso falla. Los cuatro pasos separados permanecen en dev y all.
ABAP_MCP_MAX_RESPONSE_BYTES — la lista de herramientas es un coste fijo que un perfil puede reducir; una respuesta no tiene límite. En core toda la lista de herramientas es ~11KB mientras que un adtDiscovery es ~42KB. Sin definir sigue el perfil (core 24.000 bytes, analyst 32.000, dev 48.000, all sin tope); 0 lo elimina.
Una respuesta que supera el presupuesto se retiene y se sustituye por JSON válido — status:"truncated", el bytes original, el budget, un preview de 2.000 bytes y un nextStep — nunca por un fragmento cortado, que no se analizaría y solo invitaría al reintento idéntico.
ABAP_MCP_GATE — antes de listar nada, el servidor pregunta al sistema qué soporta y retiene las herramientas cuyas colecciones ADT están ausentes. En DEV son las 10 herramientas de abapGit y las 3 herramientas de enlace de servicios, que de otro modo responderían HTTP 400. Cuesta un viaje de ida y vuelta de descubrimiento por proceso, solo puede acortar la lista, y cualquier fallo deja todas las herramientas listadas. ABAP_MCP_GATE=off lo omite.
healthcheck informa de los tres: el perfil activo, responseBudgetBytes y cualquier cosa retenida.
Un certificado en lugar de Kerberos
Para un usuario de servicio o técnico, añade un certificado — eso solo cambia el modo:
SAP_USER=CLAUDEAGENT # the user CERTRULE maps the certificate to
SAP_CERT_FILE=C:\Users\svc_agent\SNC\sec\claudeagent.p12
SAP_CERT_PASSPHRASE=<PKCS#12 password / PSE PIN>
| Variable opcional | Efecto |
|---|---|
SAP_AUTH_MODE | kerberos, certificate, oauth o password. Solo se necesita para forzar un modo mientras otro está configurado. |
SAP_CERT_KEY_FILE | La clave privada, cuando no está en SAP_CERT_FILE. |
SAP_CA_FILE | Paquete de CA para verificar el certificado propio de SAP, en lugar de deshabilitar la verificación TLS. |
Esto es TLS mutuo, no SNC — ADT es HTTPS. Un certificado que ya funciona para RFC/SNC se puede reutilizar y su mapeo
CERTRULEse transfiere, pero la ACLSNC0no juega ningún papel y el ICM necesitaicm/HTTPS/verify_client.docs/Authentication.mdcubre las diferencias, la trampa desapgenpse export_p12/ OpenSSL 3, y cómo leer un certificado rechazado.
Un cliente OAuth 2.0, para BTP y para SOAUTH2
Para un entorno ABAP de SAP BTP, o un sistema local que publica ADT detrás de un servidor de autorización. Configurar el id de cliente cambia el modo:
SAP_OAUTH_TOKEN_URL=https://your-tenant.authentication.eu10.hana.ondemand.com/oauth/token
SAP_OAUTH_CLIENT_ID=sb-abap-agent!t1234 # 'clientid' in a BTP service key
SAP_OAUTH_CLIENT_SECRET=<'clientsecret'>
En local, el endpoint está en el propio host de SAP — https://<host>:<port>/sap/bc/sec/oauth2/token — y el cliente es el registrado en SOAUTH2.
| Variable opcional | Efecto |
|---|---|
SAP_OAUTH_GRANT | client_credentials (predeterminado), refresh_token, password o static. |
SAP_OAUTH_SCOPE | Ámbitos a solicitar. Sin configurar, pide los valores predeterminados del cliente, lo que suele ser correcto. |
SAP_OAUTH_REFRESH_TOKEN | Para la concesión refresh_token; la selecciona por sí mismo. |
SAP_OAUTH_TOKEN | Un token emitido en otro lugar, usado tal cual. Nada puede renovarlo. |
SAP_OAUTH_CLIENT_AUTH | basic (predeterminado) o post, cuando un servidor rechaza un secreto que es correcto. |
El token inicia sesión una vez. Después, la cookie de sesión de SAP lleva cada solicitud, como en los otros modos — así que un token que expira en cinco minutos no es un problema. Ten en cuenta que un cliente OAuth 2.0 en AS ABAP es un usuario en
SU01: unSAP_OAUTH_CLIENT_SECRETincorrecto cuenta contralogin/fails_to_user_lockcomo una contraseña, por lo que una solicitud de token rechazada nunca se reintenta. El flujo de código de autorización no está implementado — necesita un navegador, que un servidor iniciado sobre stdio no tiene forma de abrir; complétalo una vez a mano y pasa el token de actualización.docs/Authentication.md§11 tiene el detalle, incluyendo qué fallos se bloquean y por qué.
Una contraseña, cuando no hay nada más
Para un sistema sin Kerberos ni certificados — un sandbox, una prueba, cualquier cosa fuera del dominio:
SAP_USER=CLAUDEAGENT
SAP_PASSWORD=<the password>
El último recurso, y no intercambiable con los otros dos. Un ticket faltante o un certificado no mapeado simplemente se rechaza; una contraseña incorrecta cuenta contra
login/fails_to_user_locky bloquea a ese usuario para todos los consumidores, no solo para este servidor. La implementación se niega a reintentar una contraseña rechazada por esa razón — un inicio de sesión fallido, bloqueado, sin importar cuántas herramientas se llamen. Prefiere un certificado para cualquier cosa desatendida.docs/Authentication.md§10 tiene el detalle.
Apunta el cliente al punto de entrada compilado con rutas absolutas:
{
"mcpServers": {
"sap-abap-dev-100": {
"command": "node",
"args": ["C:/path/to/sap-abap-mcp/dist/index.js"],
"env": {
"SAP_URL": "https://your-sap-server.example.com:44301",
"SAP_USER": "YOUR_SAP_USER",
"SAP_SYSTEM_ID": "DEV",
"SAP_CLIENT": "100",
"SAP_LANGUAGE": "EN"
}
}
}
}
El bloque env del cliente gana sobre .env. Ejecuta npm run start para lanzar el servidor manualmente, o npm run dev para manejarlo a través del MCP Inspector.
Para un cliente que lleva el esquema de cada herramienta en cada turno, añade un perfil a ese mismo bloque:
"env": { "…": "…", "ABAP_MCP_PROFILE": "core" }
En Docker
El servidor habla MCP sobre stdio, así que no hay puerto que publicar — el cliente inicia el contenedor y se comunica con él a través de stdin/stdout.
docker build -t abap-adt-mcp .
{
"mcpServers": {
"sap-abap-dev-100": {
"command": "docker",
"args": ["run", "-i", "--rm", "--env-file", "C:/path/to/.env", "abap-adt-mcp"]
}
}
}
Los cuatro modos de inicio de sesión funcionan aquí, pero una credencial es algo que el contenedor debe recibir, y --env-file no es dotenv — Docker no elimina comillas, no lee export, y no elimina # comment finales, así que un valor que dotenv habría limpiado llega tal cual. Las rutas de Windows en .env deben reemplazarse por las montadas. Kerberos es el modo que más necesita del contenedor y OAuth el que menos: un token se obtiene a través de la red, así que no hay que montar nada.
Modo certificado — monta el material de clave de solo lectura, y la CA que firma el certificado de SAP con él:
docker run -i --rm --env-file .env \
-v /host/certs:/certs:ro \
-e SAP_CERT_FILE=/certs/agent.p12 \
-e SAP_CA_FILE=/certs/corporate-root.pem \
abap-adt-mcp
Modo Kerberos — la imagen incluye un curl compilado contra GSS-API y kinit, así que lo que queda es un dominio y una credencial:
docker run -i --rm --env-file .env \
-v /etc/krb5.conf:/etc/krb5.conf:ro \
-v /host/agent.keytab:/krb5/agent.keytab:ro \
-e SAP_KRB_KEYTAB=/krb5/agent.keytab \
-e SAP_KRB_PRINCIPAL=SVC_AGENT@CORP.EXAMPLE.COM \
abap-adt-mcp
Modo OAuth 2.0 — nada que montar; la credencial se obtiene:
docker run -i --rm --env-file .env \
-e SAP_OAUTH_TOKEN_URL=https://your-tenant.authentication.eu10.hana.ondemand.com/oauth/token \
-e SAP_OAUTH_CLIENT_ID='sb-abap-agent!t1234' \
-e SAP_OAUTH_CLIENT_SECRET=<clientsecret> \
abap-adt-mcp
Modo contraseña — ¡Último recurso!
docker run -i --rm --env-file .env \
-e SAP_USER=YourUser \
-e SAP_PASSWORD=YourPassword \
abap-adt-mcp
Tres cosas que saber antes de recurrir a él:
- Un keytab, no tu propio ticket. Un contenedor no puede tomar prestada la credencial de la sesión como lo hace un inicio de sesión interactivo. En un host Linux puedes montar la caché de tickets que ya tienes (
-v /tmp/krb5cc_1000:/krb5/ccache:ro -e KRB5CCNAME=FILE:/krb5/ccache), pero expira con la del host. Desde un host Windows tampoco funciona: el TGT vive en la caché de LSA y no se puede escribir en un archivo — usa el modo certificado, que no necesita nada de esto. El keytab es la única credencial que funciona desatendida, y la única que sobrevive a la vida del ticket. - Verifica el certificado de SAP, o sabe que no lo estás haciendo. La imagen confía solo en el paquete de CA público, así que una CA interna que el host confía es desconocida aquí y el handshake falla con
UNABLE_TO_GET_ISSUER_CERT_LOCALLY. Monta la CA raíz y apuntaSAP_CA_FILEa ella. Llevar un.envde escritorio al por mayor oculta esto en su lugar:NODE_TLS_REJECT_UNAUTHORIZED=0es un ajuste de desarrollo y no tiene cabida en una imagen desplegada. - Compila desde un clon
--recurse-submodules.skills/Developmentes un submódulo; sin él, la imagen incluye 35 habilidades menos.
La imagen es Debian en lugar de Alpine por una razón: el curl de Alpine está compilado sin GSS-API, y ese curl no falla — simplemente nunca envía un token, y SAP responde el mismo 401 que produce un ticket caducado. Lo que falta se nombra al inicio, en stderr, antes de intentar una sesión. Para preguntar al contenedor con qué credencial terminó, dale un comando en lugar del servidor:
docker run --rm --env-file .env -v /host/agent.keytab:/krb5/agent.keytab:ro \
-e SAP_KRB_KEYTAB=/krb5/agent.keytab abap-adt-mcp klist
docs/, skills/ y AGENTS.md se copian en la imagen a propósito — el servidor los lee en tiempo de ejecución para servir los recursos readServerGuide, readSkill y abap-adt://. docs/Authentication.md §7 tiene la configuración completa del contenedor, modo por modo.
Más de un sistema
Un servidor está vinculado a un sistema y un cliente durante toda su vida — ninguno se puede cambiar en tiempo de ejecución. Así que registra una entrada por sistema/cliente y dale a cada uno su SAP_SYSTEM_ID:
"sap-abap-dev-100": { "env": { "SAP_SYSTEM_ID": "DEV", "SAP_CLIENT": "100", "…": "…" } },
"sap-abap-dev-200": { "env": { "SAP_SYSTEM_ID": "DEV", "SAP_CLIENT": "200", "…": "…" } },
"sap-abap-q01-100": { "env": { "SAP_SYSTEM_ID": "Q01", "SAP_CLIENT": "100", "…": "…" } }
Cada servidor se anuncia entonces en el instructions de MCP que devuelve al conectarse:
Este servidor está vinculado al sistema SAP DEV, cliente 100 (https://…:44301). No puede cambiar de sistema o cliente en tiempo de ejecución — ambos están fijados por el entorno con el que se inició. Si una solicitud nombra un sistema o cliente diferente, usa el servidor MCP configurado para ese; si no hay ninguno registrado, dilo en lugar de actuar aquí.
Eso es lo que permite a un agente enrutar "por favor revisa esto en DEV cliente 200" al servidor correcto sin llamar a nada. healthcheck reporta la misma identidad para un servidor que necesita ser preguntado directamente.
La declaración se comprueba. SAP nombra el sistema y el cliente en la cookie de sesión que establece al iniciar sesión (SAP_SESSIONID_DEV_100), así que el servidor sabe a qué está realmente conectado. Si eso no coincide con SAP_SYSTEM_ID — una entrada copiada y pegada que apunta al host equivocado, por ejemplo — healthcheck lleva un WARNING y se registra ruidosamente al inicio. Vale la pena vigilarlo, porque cada herramienta sigue funcionando perfectamente; solo que en el sistema equivocado.
Recorrido rápido
Lee cualquier objeto por nombre — no se necesita descubrimiento de URL:
{"tool":"readAbapObject","args":{"objectName":"ZCL_MY_CLASS"}}
{"tool":"describeAbapTable","args":{"tableName":"T000"}}
Examina una convención de nombres completa — los patrones se normalizan por ti, así que zpp_lab se convierte en ZPP_LAB*:
{"tool":"searchPackages","args":{"patterns":["ZPP_*","Z_PP*"]}}
// -> each package with its objects grouped by type, sub-packages, and a \`truncated\` flag
Llama a un módulo de funciones — la firma se lee primero y la solicitud se valida contra ella:
{"tool":"readAbapFunctionModule","args":{"functionModuleName":"STFC_CONNECTION"}}
{"tool":"callFunctionViaJsonRpc","args":{"functionModuleName":"STFC_CONNECTION",
"inputParameters":{"REQUTEXT":"hello"}}}
Un BAPI y su commit deben viajar en un lote, o el commit cae en su propia LUW y los cambios del BAPI se pierden:
{"tool":"callFunctionsViaJsonRpc","args":{"calls":[
{"functionModuleName":"BAPI_USER_LOCK","inputParameters":{"USERNAME":"DEVUSER"}},
{"functionModuleName":"BAPI_TRANSACTION_COMMIT","inputParameters":{"WAIT":"X"}}
]}}
El ciclo completo de escritura (bloquear → modificar → comprobar → activar → desbloquear), el depurador, ATC y todos los demás flujos de trabajo están en docs/MCP-Tools.md §4.
Trabajando con objetos ABAP
Tres herramientas cubren la mayor parte de lo que necesitas, y cada una toma un nombre en lugar de una URL de ADT:
| Quieres | Herramienta |
|---|---|
| El código fuente de una clase, programa, include, grupo de funciones o módulo | readAbapObject |
| Cómo se ve una tabla, estructura o vista | describeAbapTable |
| Todo lo que hay detrás de una convención de nombres | searchPackages |
{"tool":"readAbapObject", "args":{"objectName":"ZCL_MY_CLASS"}}
{"tool":"describeAbapTable","args":{"tableName":"T000"}}
{"tool":"searchPackages", "args":{"patterns":["ZPP_*","Z_PP*"]}}
readAbapObject devuelve los metadatos y el código fuente en una sola llamada. Cuando un nombre pertenece a varios objetos — ZPP_EXT_LABEL_DATA es tanto un grupo de funciones como un módulo de funciones — elige el más específico y te lo dice, mediante ambiguous:true y alternatives; pasa objectType para forzar la elección. Los objetos sin código fuente vuelven con hasSource:false y un puntero a la herramienta correcta.
describeAbapTable da nombres de campos, tipos DDIC, longitudes, indicadores de clave, elementos de datos, dominios y tablas de verificación — la tabla de verificación es el objetivo de la clave externa, que es la forma más rápida de ver cómo se unen dos tablas. objectStructure no devuelve campos para una tabla, y tableContents devuelve filas en lugar de una definición, así que ninguno responde "¿cómo se ve esta tabla?".
Reglas que vale la pena poner en el prompt del sistema de tu cliente
- Prefiere las herramientas por nombre. Solo recurre a
searchObject→objectStructure→getObjectSourcecuando necesites los resultados intermedios. Nunca construyas manualmente una ruta/sap/bc/adt/.... - Selecciona eficientemente. Las tablas de SAP son grandes. Siempre restringe los
SELECTcon una cláusulaWHERE, y usaSELECT SINGLE(todos los campos clave conocidos) oUP TO n ROWSen caso contrario.
SELECT vgbel FROM vbrp WHERE vbeln = @lv_vbeln INTO @DATA(lv_vgbel) UP TO 1 ROWS.
EXIT.
ENDSELECT.
SAP está desacoplado de tu sistema de archivos: leer el código fuente lo devuelve solo como resultado de herramienta, y escribir un archivo local no cambia nada en SAP. Las copias locales son útiles para comparar, nada más.
Los README anteriores listaban
GetTable,GetStructureyGetTypeInfo. Esos pertenecen al proyecto separadomcp-abap-adt, no a este servidor.
Desarrollo
npm run build # tsc -> dist/
npm test # jest: parser, tool catalogue, JSON-RPC handler (no SAP system needed)
npx tsc --noEmit # type check only
Las pruebas viven en src/__tests__ y se ejecutan completamente sin conexión — la suite JSON-RPC ejercita el manejador de extremo a extremo contra un nodo falso de SAP Gateway.
Contra un sistema real (necesita un ticket Kerberos), la comprobación de extremo a extremo es:
npm run build
node scripts/live-jsonrpc-check.mjs # add NODE_TLS_REJECT_UNAUTHORIZED=0 for an internal CA
Conduce el servidor compilado sobre MCP stdio exactamente como lo haría un cliente, y solo llama a módulos de funciones de solo lectura.
Añadir una herramienta es un cambio de un archivo — ver docs/MCP-Tools.md §10.
Solución de problemas
| Síntoma | Causa / solución |
|---|---|
HTTP 401 en cada llamada | Modo Kerberos: sin ticket válido, o el sistema no acepta SPNEGO — comprueba klist y tu conexión VPN/dominio. Modo certificado: ver docs/Authentication.md §6. |
curl nicht gefunden | El arranque SSO no pudo encontrar curl — establece SSO_CURL_PATH. |
SAP rejected the client certificate | El mapeo CERTRULE, icm/HTTPS/verify_client, o la confianza de CA en STRUST. El error nombra el sujeto que se presentó — compáralo con CERTRULE. |
unable to get local issuer certificate | CA interna. Establece NODE_TLS_REJECT_UNAUTHORIZED=0 (solo desarrollo). |
Las herramientas RFC devuelven reachable:false | Ejecuta checkJsonRpcEndpoint. Separa un nodo SICF /sap/gw/jsonrpc inactivo de un problema de CSRF o autorización. |
-32601 de un módulo de funciones | No existe, no está habilitado para RFC, o S_RFC deniega su grupo de funciones. |
| El cliente no muestra herramientas | Verifica la ruta absoluta a dist/index.js y que npm run build se haya ejecutado. |
Más en docs/MCP-Tools.md §8.
Contribuciones
- Haz un fork del repositorio
git checkout -b feature/your-feature-name- Haz tu cambio, mantén
npm testynpx tsc --noEmiten verde git commit -m "Add some feature"ygit push origin feature/your-feature-name- Abre un pull request