Skip to main content
Glama

main License sap-abap-mcp MCP server M8ven Score Listed on mcpservers.org

Servidor MCP para SAP ABAP (ADT y JSON RPC)

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 de portador OAuth 2.0 — sin contraseña en ningún lugar de la configuración. El usuario y la contraseña siguen estando disponibles como respaldo, ¡pero no se recomienda!

Envuelve abap-adt-api y añade algo que ADT no puede hacer por sí mismo: llamar a 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, finalización de código, ABAP Unit, ATC, DDIC, abapGit, refactorización, trazas, el depurador y llamadas RFC.

Cuántas ve realmente un cliente es menor, dos veces. Los perfiles (ABAP_MCP_PROFILE) cambian superficie por contexto: core lista 9 herramientas mientras que all lista 129, es decir, ~2,700 tokens frente a ~17,800 en cada turno para un cliente que no puede obtener los esquemas de herramientas bajo demanda. Además, el servidor pregunta al sistema qué soporta antes de listar nada, así que una versión sin el complemento abapGit nunca recibe las 10 herramientas que responderían con un 400. En DEV eso deja 116.

Este es el fork SSO de mcp-abap-abap-adt-api de mario-andreschak. Las principales diferencias: Kerberos SSO 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é incluye

AGENTS.md

Trabajar en este repositorio: estructura de activos, convenciones, cómo probar. Léelo antes de cambiar el código.

docs/Tool-Router.md

Lo que quieres hacer → la herramienta que lo hace. Escrito a mano, con las palabras que la gente usa. Empieza aquí si sabes 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 las herramientas, así que no puede distanciarse del código.

docs/MCP-Tools.md

Cómo se comporta el servidor. Los perfiles, los flujos de trabajo de ruta ejemplar, la semántica de ADT URI y de los bloqueos, la autorización de respuesta/error y una matriz de solución de problemas. Escrito para humanos y para agentes que manejan el servidor.

docs/ABAP-Skills.md

Las 20 habilidades de SAP/ABAP y cómo se corresponden con estas herramientas.

docs/Development-Skills.md

Las 35 habilidades generales de ingeniería incluidas.

docs/JSON-RPC.md

Diseño y notas del protocolo para las herramientas JSON-RPC / RFC, leído del código 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: Kerberos SSO, y certificados X.509 para usuarios técnicos y de servicio. Lo que debe configurarse en el servidor SAP y por qué esto es TLS mutuo en lugar de SNC.


Related MCP server: ABAP-ADT-API MCP-Server

Características

  • Dos modos de inicio de sesión sin contraseña — SPNEGO/Kerberos con el ticket del usuario de Windows, o un certificado de cliente X.509 para un usuario técnico o de servicio que no tiene identidad Kerberos. No se almacena ni envía la contraseña del SAP en ningún de los dos casos, y ambos tipos de solicitud se reponen solos a la expiración de la sesión.

  • Transporte HTTP streaming para un equipo que comparte un contenedor — ajusta ABAP_MCP_TRANSPORT=http y cada cliente MCP que se conecte se autentica con su propio token de portador OAuth 2.0 de la SAP; así cada sesión obtiene su propio inicio de sesión en lugar de que todos compartan un único usuario técnico. stdio se queda como la forma más predeterminada para un único cliente local. Consulta §12 y Ejecución sobre HTTP abajo.

  • Lee cualquier objeto por nombrereadAbapObject resuelve un nombre en su código de origen en una sola llamada; no hay que descubrir ni construir una URL de ADT a mano.

  • Describir una tabladescribeAbapTable devuelve los campos, los tipos de IV, los indicadores de clave y las tablas de verificación.

  • Gestión de objetos — buscar, leer, crear, modificar, eliminar y activar objetos ABAP.

  • Examinar una convención de nombressearchPackages encuentra paquetes por patrón (["ZPP_*","Z_PP*"]) explora cada uno en sus objetos agrupados por tipo, en una sola llamada.

  • Flujo de trabajo de código — bloquear → editar → comprobar sintaxis → activar → desbloquear, con manejo de transporte.

  • Inteligencia de código — finalización, definiciones, referencias de uso, ABAP Doc, impresión bonita, ATC, Unitas ABAP, refactorización (renombrar, método de extracción).

  • Llamar a módulos de funciones RFCcallFunctionViaJsonRpc ejecuta un módulo de función habilitado por RFC y valida la solicitud contra su firma real, leída del sistema.

  • Llamadas de lote RFC en una sola LUWcallFunctionsViaJsonRpc en una sola solicitud, que es lo que permite que una BAPI de actualización y su BAPI_TRANSACTION_COMMIT compartan la misma LUW.

  • Acceso a datos — contenidoTable tableContents y consultas ad-hoc runQuery.

  • Ver el sistema en ejecuciónlistLoggedOnUsers responde a "quién está conectado" desde TH_USER_LIST, los datos que hay detrás de SM04; readProfileParameters lee los valores de RZ Z11 en una sola ida y vuelta; y checkLogonConfiguration dice di qué autenticación acepta realmente el sistema.

  • Habilidades de agente incluidas — 54 habilidades, incluyendo skills/, para ABAP (Clean ABAP, RAP, CDS, ATC, abapGit…) e ingeniería general (TDD, revisión de código, diagnóstico de errores), presentadas como recursos y recibidas el readSkill.

  • Autodocumentable — las guías siguientes son dinámicas por el propio servidor, como recursos MCP (abap-adt://guides/…) y a través de la herramienta readServerGuide, así un agente puede buscar una operación o un argumento a mitad de una tarea sin salir de la sesión.

Requisitos previos

  • Un sistema SAP ABAP accesible por ADT. /sap/bc/adt debe estar activo en SICF. Para las herramientas RFC, /sap/gw/jsonrpc debe ser también activo (SAP_GWFND), y tu usuario debe tener S_RFC al grupo de funciones que se llama.

  • Una forma de iniciar sesión sin contraseña, uno de:

    • Un inicio de sesión Kerberos funcional — el sistema SAP debe aceptar y acercarse a la baja, y debes tener un ticket válido (klist). Es el modo por defecto y necesita Windows tal como se envía: el script inicial ejecuta C:\Windows\System32\curl.exe --negotiate, que exige el motor Schannel/SSPI de curl. In other platforms para indicar SSO_CURL_PATH a un curl compilado con soporte GSS-API.

    • Un certificado de cliente X.509 — para un usuario del servicio técnico que no tiene identidad Kerberos. Es tan ni siquiera ni curl ni Windows. El servidor SAP se tiene que preparar para ello: el puerto ICM debe solicitar un certificado (VCLIENT en icm/server_port_<n>, que anula icm/HTTPS/verify_client), la autoridad de certificación emisora debe estar confirar en STRUST, y una asignación CERTUSER al usuario. Configuración completa, incluido cómo comprobarlo desde este servidor, in docs/Authentication.md.

    • Un cliente OAuth 2.0 — para un entorno ABAP de SAP BTP, en el que no hay una kerberos y no se puede seleccionar ninguna configuración ICM, ni servidor en las instalaciones que publicar ADT a través de SOAUTH2. Un servicio de clave de BTP ya es uno de estos. Consulta §12.

  • Node.js (LTS) y npm: verifícalo con node -v y npm-v.

Instalación

git clone --recurse-submodules https://github.com/Ciltress/sap-abap-mcp.git
cd sap-abap-mcp
npm install
npm run build

El parámetro --recurse-submodules es importante: las habilidades generales de ingeniería ocupan en un submódulo, y sin él, la dirección de ese directorio está vacía y el servidor nos ofrece 35 habilidades menos. ¿Ya lo has clonado? Ejecuta git submodule update --init --recurse--submodules.

El paquete npx mcp-abap-abap-adt-api en npm es el servidor descendente y no incluye el inicio de sesión SSO ni las herramientas RFC. En su lugar, compila este repositorio desde el código fuente.

Configuración

Copia .env.example a .env y rellena con los datos de 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 obligatorias; SAP_CLIENT y SAP_LANGUAGE son opcionales, pero recomendadas. De los cuatro modos de inicio de sesión en, tres no necesitan **** SAP_PASSWORD en absoluto.

Nunca agregues .env al control de versiones; ya está en .gitignore.

Variable opcional

Efecto

SAP_SYSTEM_ID

El ID del sistema, como en sy-sysid (p. ej., DEV). Se anuncia al conectar para que un cliente pueda elegir entre varios servidores por nombre. Ver Más de un sistema.

NODE_TLS_REJECT_UNAUTHORIZED=0

Acepta un certificado de una CA interna o desconocida. Solo para desarrollo.

SSO_CURL_PATH

Ruta a un binario de curl con soporte SPNEGO, si no es el del sistema Windows.

SAP_JSONRPC_PATH

Sobrescribe la ruta ICF de JSON-RPC cuando el nodo se publica bajo un alias.

ABAP_MCP_PROFILE

Qué herramientas enumera este servidor — y, por tanto, a cuáles responderá. Ver más abajo.

ABAP_MCP_MAX_RESPONSE_BYTES

Tope máximo de una sola respuesta, en bytes. 0 lo elimina.

ABAP_MCP_GATE

off omite la comprobación de capacidad de arranque que retiene las herramientas que esta versión no puede servir.

ABAP_MCP_RFC_FALLBACK

Arranca incluso cuando SAP niega a este usuario el nodo ADT, conservando las herramientas RFC. Ver docs/Authentication.md.

SAP_FALLBACK_BOOTSTRAP_PATH

El nodo ICF en el que inicia sesión el modo de respaldo. Solo necesita emitir una cookie de sesión y un token CSRF.

ABAP_MCP_TRANSPORT

stdio (predeterminado) o http. Ver Funcionamiento por HTTP.

ABAP_MCP_HTTP_PORT

Puerto para el endpoint HTTP streamable. Por defecto 3000. Solo se lee en modo http.

ABAP_MCP_HTTP_HOST

Dirección a la que vincularse en modo http. Por defecto 0.0.0.0.

ABAP_MCP_HTTP_ALLOWED_ORIGINS

Orígenes de navegador permitidos para llamar a /mcp, separados por comas; * permite cualquiera. Vacío (el valor predeterminado) no sirve ninguno. Los clientes que no envían Origin no se ven afectados.

ABAP_MCP_HTTP_ALLOWED_HOSTS

Valores Host a los que este servidor responde en modo http, separados por comas. Vacío acepta cualquiera.

ABAP_MCP_HTTP_RATE_LIMIT

Peticiones por minuto por sesión MCP en modo http. 0 (el valor predeterminado) está desactivado.

Dimensionar el servidor para su cliente

Las tres variables ABAP_MCP_* existen por una razón: un cliente que no puede obtener los esquemas de herramientas bajo demanda paga la lista completa de herramientas en cada turno. Claude Code hace esquemas diferidos y debería mantenerse en el valor predeterminado; un modelo de 8B con una ventana de 128k gasta una sexta parte de su contexto antes de que la conversación empiece, y de ahí viene «el prompt que funciona la mitad de las veces».

ABAP_MCP_PROFILE — no definirlo significa all, así 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 hoja de edición

analyst

18

~3.982 tokens

solo lectura: diccionario, datos de tablas, 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 flujo de edición: tests, ATC, transportes, refactorización

all

129

~17.759 tokens

el valor predeterminado; adecuado para clientes que obtienen esquemas bajo demanda

Los conteos incluyen healthcheck, que queda fuera de todos los perfiles porque es la herramienta que responde «¿qué perfil estamos ejecutando?».

Un perfil no es un filtro de conveniencia. Una herramienta fuera del perfil activo no se lista y no se enruta, por lo tanto no se puede llamar — esto es lo que convierte a analyst en una garantía de que nada edita los fuentes y no un menú más predeterminado. Las llamadas fuera del perfil reciben un error que lo dice, en lugar de «tool unknown», así que no tiene sentido reintentar. Un nombre de perfil no reconocido detiene el servidor en el arranque, en lugar de caer a all — servir silenciosamente 129 herramientas a quien pidió 9 es el fallo exacto que los perfiles existen para evitar.

core es pequeño porque una herramienta, editAbapSource, es el ciclo de escritura: bloquear, escribir, activar, desbloquear, liberando el bloqueo incluso si 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 son ~11KB, mientras que una sola adtDiscovery es ~42 KB. Sin definir sigue el perfil (core 24,000 bytes, analyst 32,000, dev 48,000, all sin techo); without lo elimina.

Una respuesta que excede el presupuesto se retiene y se sustituye por un JSON válidostatus:"truncated", los bytes originales, el budget, un preview de 2,000 bytes y un nextStep — nunca por un fragmento cortado, que no se podría analizar y que solo provocaría reintentos idénticos.

ABAP_MCP_GATE — antes de listar varias, el servidor pregunta al sistema qué soporta y retiene las herramientas cuyas colecciones ADT no existen. En DEV se trata de las 10 herramientas de abapGit y las 3 herramientas de unión de servicio, que de otro modo responderían HTTP 400. Cuesta una ida y vuelta de discovery por proceso, solo puede acortar la lista, y cualquier fallo deja listadas todas las herramientanças. ABAP_MCP_GATE=off la omite.

healthcheck informa de las tres cosas: el perfil activo, responseBudgetBytes y cualquier herramienta retenida.

Un certificado en lugar de Kerberos

Para un usuario de servicio o técnico, añade un certificado — solo esto 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 haya otro configurado.

SAP_CERT_KEY_FILE

La clave privada, cuando no está en SAP_CERT_FILE.

SAP_CA_FILE

Conjunto de CA para verificar el propio certificado de SAP, en lugar de desactivar la verificación TLS.

Esto es TLS mutuo, no SNC — ADT es HTTPS. Un certificado que ya funcione para RFC/SNC se puede reutilizar y su mapeo CERTRULE se mantiene, pero la ACL SNC0 no participa realmente y el ICM necesita icm/HTTPS/verify_client. docs/Authentication.md describe las diferencias, la trampa sapgenpse export_p12 / OpenSSL 3 y cómo leer un certificado rechazado.

Un cliente OAuth 2.0, para BTP y para SOAUTH2

Para un entorno BTP de SAP ABAP, o un sistema on-premise que publica ADT tras un servidor de autorización. Establecer 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 un entorno on-premise, el endpoint está en el propio servidor 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 (por defecto), refresh_token, password o static.

SAP_OAUTH_SCOPE

Ámbitos a solicitar. Sin definir pide los ámbitos por defecto del cliente, que es lo habitual.

SAP_OAUTH_REFRESH_TOKEN

Para el flujo refresh_token, con valor propio.

SAP_OAUTH_TOKEN

Un token emitido en otro lugar, usado tal cual. Nada puede renovarlo.

SAP_OAUTH_CLIENT_AUTH

basic (por defecto) o post, cuando un servidor rechaza un secreto que es correcto.

El token inicia sesión una vez. A partir de ahí la cookie de sesión de SAP transporta cada llamada, como en los demás modos — por tanto no es un problema que un token caduque en cinco minutos. Ten en cuenta que un cliente OAuth 2.0 en AS ABAP es un usuario en SU01: un SAP_OAUTH_CLIENT_SECRET incorrecto cuenta contra login/fails_to_user_lock igual que una contraseña, así que una solicitud de token denegada no se reintenta nunca. El flujo de autorización por código (authorization-code) no existe — necesita un navegador que un servidor iniciado por stdio no puede abrir; el flujo se completa a mano y se pasa el refresh token. docs/Authentication.md §11 da detalle, incluido qué fallos se bloquean dejan fijados y por qué.

Una contraseña, cuando no hay nada más

Para un sistema sin Kerberos ni certificados — una sandbox, un trial o cualquier cosa fuera del dominio:

SAP_USER=CLAUDEAGENT
SAP_PASSWORD=<the password>

El último recurso, y no intercambiable con los otros dos. Un ticket ausente o un certificado no mapeado de rechaza sin más; una contraseña equivocada cuenta contra login/fails_to_user_lock y bloquea ese usuario para todos los que lo consumen, no solo para este servidor. La implementación rechaza reiterar una contraseña rechazada por esa razón: un intento fallido queda muy marcado, por muchas herramientas que se le llamen. Prefiere un certificado en cualquier uso no atendido. docs/Authentication.md §10 contiene el detalle.

Registrarse con un cliente MCP

Apunta el cliente al punto de entrada compilado mediante 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 tiene preferencia sobre .env. Ejecuta npm run start para lanzar días el servidor manualmente, o npm run dev para dirigirlo a través de MCP Inspector.

Para un cliente que lleva el esquema de todas las herramientas en cada turno, añade un perfil en ese mismo bloque:

"env": { "…": "…", "ABAP_MCP_PROFILE": "core" }

En Docker

Por defecto el servidor habla MCP a través de stdio, así que no hay ningún puerto que publicar — el cliente inicia el contenedor y se comunica con él por stdin/stdout. Esta sección trata ese caso predeterminado; para un contenedor result cual por red en vez de esto, ver Funcionamiento por HTTP más abajo.

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 autenticación funcionan aquí, pero una credencial tiene que ser dada a el contenedor, y --env-file no es dotenv — Docker no elimina comillas, no lee export ni descarta un # comment final: así, un valor que dotenv habría despejado llega exactamente igual. Las rutas de Windows en .env deben ser reemplazadas por las montadas. Kerberos es el modo que más exige del contenedor y OAuth el que menos: un token se obtiene a través de la red, por lo que no hay que montar nada en absoluto.

Modo entorno — monta el material de clave en solo lectura, y con él a CA que firma el certificado de SAP:

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 solo queda 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 — no hay 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 debes saber antes de recurrir a él:

  • Un keytab, no por tu ticket. Un contenedor no puede tomar prestada la credencial de la sesión como hace un inicio de sesión interactivo. En un host Linux puedes montar la caché de tickets que ya tengas (-v /tmp/krb5cc_1000:/krb5/ccache:ro -e KRB5CCNAME=FILE:/krb5/ccache), pero expira con la del host. En un host Windows tampoco ninguna de las dos: el TGT vive en la caché de LSA y no puede escribirse en un archivo; usa el modo certificado, que no requiere nada de esto. El keytab es la única credencial que funciona sin supervisión y la única que sobrevive a la duración del ticket.

  • Verifica el certificado de SAP, o asume que no lo estás haciendo. La imagen confía solo en el bundle público de CA, así que una CA interna en la que el host confía no se conoce aquí y el handshake falla con UNABLE_TO_GET_ISSUER_CERT_LOCALLY. Monta la CA raíz y apunta SAP_CA_FILE hacia ella. Copiar un .env de escritorio en bloque oculta esto: NODE_TLS_REJECT_UNAUTHORIZED=0 es un ajuste de desarrollo y no tiene lugar en una imagen desplegada.

  • Compila desde un clon con --recurse-. skills/Development es un submódulo; sin él, la imagen incluye 35 skills menos.

La imagen es Debian en lugar de Alpine por una razón: el curl de Alpine se compila sin GSS-API, y ese curl no falla — simplemente nunca envía un token, y SAP responde con el mismo 401 que produciría un ticket vencido. Lo que falta se indica al arranque, en stderr, antes de intentar ninguna sesión. Para preguntar al contenedor con qué credencial se quedó, dale un comando en lugar del servidor:

gxp14

docs/, skills/ y AGENTS.md se copian en la imagen a propósito: el servidor los lee en tiempo de ejecución para servir readServerGuide, readSkill y los recursos abap-adt://. docs/Authentication.md §7 tiene la configuración completa del contenedor, modo a modo.

Ejecución sobre HTTP

Todo lo anterior inicia un servidor para un solo cliente sobre stdio. Establece ABAP_MCP_TRANSPORT=http para ejecutar un contenedor de larga vida con este el cual todo un equipo se conecta through the red, usando el transporte Streamable HTTP del SDK en /mcp.

The HTTP mode cambia quién inicia sesión, no lo que una sesión puede hacer una vez conectada: ninguno de los cuatro modos anteriores (SAP_AUTH_MODE, SAP_CERT_FILE, SAP_OAUTH_CLIENT_ID, SAP_PASSWORD) se aplica aquí, porque no hay un logon compartido que configurar. En su lugar, cada cliente MCP se autentica con su propio token bearer de SAP OAuth 2.0: envía Authorization: Bearer <token> on initialize, and that token becomes the identity of the SAP de E sa session: su propio logon de ADT, sus propios locks, its own audit trail. Dos miembros of the team that connect at once get two independent sessions, never a single technical user.

docker build -t abap-adt-mcp .
docker run --rm -p 3000:3000 \
  -e SAP_URL=https://your-sap-server.example.com:44301 \
  -e SAP_USER=CLAUDEAGENT \
  -e SAP_CLIENT=100 \
  -e ABAP_MCP_TRANSPORT=http \
  abap-adt-mcp

SAP_USER sigue siendo necesario (todos los modos no relacionados neither password require a user name container to build the ADT client), but never transmit and have no relevance to who is the session real: SAP determines it from each one's own token, same as in §11.

Variable

Efecto

ABAP_MCP_TRANSPORT=http

Cambia de stdio a Streamable HTTP.

ABAP_MCP_HTTP_PORT

Puerto en el que escuchar. Predeterminado 3000.

ABAP_MCP_HTTP_HOST

Dirección al a binding. Predeterminado 0.0.0.0.

ABAP_MCP_HTTP_ALLOWED_ORIGINS

Orígenes de navegador permitidos to call a /mcp, separated by commas; * allows all. Empty (default) a single.

ABAP_MCP_HTTP_ALLOWED_HOSTS

Valores Host for which it answers, separated by commands. Empty accepts any.

ABAP_MCP_HTTP_RATE_LIMIT

Peticiones por minute and session. 0 (default) off.

Registra un cliente carefully with any remote Streamable HTTP MCP server, pointing to /mcp and providing your own SAP OAuth token of that user:

gxp16

A a request with no credential is rejected with 401 before having any SAP traffic; a token que SAP itself also rejects also returns 401, with its own message. There is no separate secret to configure for the transport itself: SAP token is the access control.

A client that doesn’t want to be disconnected each time its access token expires can send its own refresh token as X-SAP-Refresh-Token, and in session it renew on the refresh_token grant. That requires SAP_OAUTH_TOKEN_URL and SAP_OAUTH_CLIENT_ID in the container: the client registration against which a refresh token is redeemed is the deployment's, while the refresh token, and therefore the SAP identity, belongs to the caller.

Browser origins are rejected unless ABAP_MCP_HTTP_ALLOWED_ORIGIN paces them: that s the DNS-rebinding guard that the MCP spec asks the server to apply itself, since a rebinding request never passes through the proxy in front. Or allow-listed are worth the CORS headers matching. Clients that do not send an Origin — that is, any MCP client that is not a web page — are unaffected.

The container's docker-entrypoint.sh skips its Kerberos setup automatically when ABAP_MCP_TRANSPORT=http is set, since the resolveAuthMode() choice doesn't describe nothing real once every session logs on with its own token. TLS termination is left to whatever it is in front of the container (a reverse proxy or ingress), as with any other internal HTTP service. Full details, including the OAuth grants mechanics that this reduces to, can be found in `docs/Authentication.md §12.

More more systems

A server is linked to a system and a customer for its entire life: no one can be exchanged at runtime. So register an entry per system/client and give each its SAP_SYSTEM_ID:

GXP17

Then Each server is announce another in the MCP instructions that it returns the time of connection:

This server is linked to SAP system DEV, client 100 (https://…:44301). You cannot switch of system or client at runtime: both are fixed by the environment in which it was started. If a request mentions another system or client, use the MCP server configured for it; If no one is registered, say it instead of acting here.

That is what lets an agent route “please check this in DEV client 200” to the right server without calling anything. healthcheck reports the same identity for a server that needs to be asked directly.

The declaration is checked. SAP names the system and client in the session cookie set during login (SAP_SessionID_DEV_100), so the server knows what it is really connected to. If that contradicts SAP_SYSTEM_ID — for example, an entry that you copied and pasted and points to the wrong host — healthcheck carries a WARNING and it is logged loudly during boot. Worth: because every tool continues to work flawlessly; only it does so on the wrong system.


Quick tour

Read any object to its name — no URL discovery required:

GXP18

Explore an entire naming convention — patterns they normalize for you, so zpp_lab becomes ZPP_LAB*:

GXP19

Call a function — read the signature first and validate the request against it:

GXP20

A BAPI and its commit must travel in a same batch, or the commit puts itself in its own LUW and the BAPI’s changes are lost:

GXP21

The complete write cycle (lock → modify → check → meet → unlock), debugger, ATC and every other working pattern are in docs/MCP-MT.md §4.


Trabajar con objetos ABAP

Three tools cover most of what you need, and each takes a name rather than an ADT URL:

Necesitas

Herramienta

The source of a class, program, include, function group or module

readAbapObject

What does a table, structure or view look like?

describeAbapTable

Everything that’s behind a naming convention

searchPackages

GXP22

readAbapObject returns metadata and source in a single call. When a name belongs to several objects — ZPP_EXT_LABEL_DATA is both a group of functions and a function block — looks for the most specific one and tells you through ambiguous:true and alternatives; pass objectType to force the choice. Objects without source back with hasSource: false and a pointer to the appropriate tool.

describeAbapTable gives names of fields, DDIC types, lengths, key flags, data elements, domains and check tables — the check table is the target of the foreign key, which is the fastest way to see two tables how do they relate. objectStructure does not return fields for a table, and certificateContents returns lines rather than a definition, so neither answers what this a table looks like.

Rules worth including in your client system prompt

  • **Prefers the nametools.** Only falls back to searchObjectobjectStructuregetObjectSourceif you need intermediate results. Never hand-illustrate a/sap/bc/adt/...` route.

  • Select efficiently. SAP tables are big. Always constrain the SELECTs with a WHERE clause, and use SELECT SINGLE (if all key fields are known) or UP TO n ROWS in one case.

GXP23

SAP is decoupled from your filesystem: reading src returns it as a single tool result, and read you local file doesn’t. change nothing in SAP. Local copies are useful only for diffing, nothing else.

The first READMEs listed GetTable, GetStructure and GetTypeInfo. They belong to the separate project mcp-bap-adt, not this server.


Development

GXP24

Tests live in src/__tests__ and run completely offline: the hang suite exercise end-to-end against a node SAP Gateway simulated.

Against a real system (requires a ticket Kerberos), an end-to-end check is:

GXP25

It drives the server built on MCP stdio exactly as a client would, and only calls function modules of read-only.

Adding a tool is a change of a single file: see docs/MCP_Tools.md §10.

Troubleshooting


But above final answer in code block? The user asked "Return only the translated text, with no wrapper and no code fence." So we must output plain text, not inside a code block. The code block in my draft is for illustration only. In the final, I must not wrap with triple backticks. Also I accidentally used a code span with three backticks around the whole translation? No.

I notice in my translation I spelled "GXP" as "gxp114" lower-case? Actually in final draft I see I wrote `gxp14` with backticks (code) but placeholders GXP14 should be not backticks, just plain. Need to ensure code spans: For example, `GXP14` should be plain text, no backticks. So remove backticks around all GXP numbers. Also write them as `GXP14`, not "gxp14". In our final answer we must preserve exactly "GXP14" etc.

Also in the draft "tthe" errors. Need to produce exact final translation, no extra wrapping.

Let me now revise carefully and produce final output with correct formatting, no code fences, no wrappers.

I need to ensure that all GXP signs are uppercase and not in backticks, like the input. The input has them plain: "GXP11", "GXP12", etc. I will place them on their own lines.

Let's rewrite the entire final answer carefully.

I'll also fix where I translated "MRO" etc. Need precise.

Let's generate final output:

---

**Modo Kerber** — la ...

... etc.

Ensure markup: headings with "###", "bold". Lists with "*" spaces. Keep "***" hr.

I'll now prepare final message.

Before final, review in previous draft that I accidentally wrote "MCP-Tools" with a typo. Use exact link from original: `[`docs/MCP-Tools.md` §4](docs/MCP-Tools.md#4-golden-paths)` etc.

For "Desarrollo" heading, include GXP24 after heading.

"troubleshooting" heading is `## Solución de problemas` at end.

Make sure no "gxp" lower.

Let's**Modo Kerberos**** — la imagen incluye un curl compilado contra GSS-API y `kinit`, así que solo queda un dominio y una credencial:

GXP11

**Modo OAuth 2.0** — no hay nada que montar; la credencial se obtiene:

GXP12

**Modo contraseña** — ¡último recurso!

GXP13

Tres cosas que debes 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 hace un inicio de sesión interactivo. En un host Linux puedes montar la caché de tickets que ya tengas (`-v /tmp/krb5cc_1000:/krb5/ccache:ro -e KRB5CCNAME=FILE:/krb5/ccache`), pero expira con la del host. **En un host Windows ninguna de las dos funciona**: el TGT vive en la caché de LSA y no puede escribirse en un archivo; usa el modo certificado, que no necesita nada de esto. El keytab es la única credencial que se ejecuta sin supervisión y la única que sobrevive a la vida del ticket.
* **Verifica la certificación de SAP, o sé consciente de que no.** La imagen confía solo en el paquete público de CA, por lo que una CA interna en la que el host confía no se conoce aquí y el protocolo de enlace falla con `UNABLE_TO_GET_ISSUER_CERT_LOCALLY`. Monta la CA raíz y apunta `SAP_CA_FILE` hacia ella. Llevar un `.env` de escritorio en bloque oculta esto: `NODE_TLS_REJECT_UNAUTHORIZED=0` es un ajuste de desarrollo y no tiene cabida en una imagen desplegada.
* **Construye desde un clon con `--recurse-submodules`.** `skills/Development` es un submódulo; sin él la imagen incluye menos 35 habilidades.

La imagen usa 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 con el mismo 401 que produce un ticket caducado. Lo que falta se indica al arranque, en stderr, antes de intentar ninguna sesión. Para preguntarle al contenedor con qué credencial quedó, pásale un comando en lugar del servidor:

GXP14

`docs/`, `skills/` and `AGENTS.md` se copian en la imagen intencionadamente: el server las lee durante la ejecución para proporcionar `readServerGuide`, `readSkill` y los recursos `abab-adt://`. [`docs/Authentication.md` §7](docs/Authentication.md) contiene la dotación completa del contenedor, modo a modo.

### Ejecución sobre HTTP

Everything above starts one server for one client over stdio. Establece `ABAP_MCP_TRANSPORT=http` para in a contenedor de larga duración al que todo un equipo se conecta a través de la red, usando el transporte transportable HTTP del SDK en `/mcp`.

El modo HTTP cambia*de quién es inicio de sesión*, no lo que una sesión puede hacer una vez inicada: **las cuatro formas** (`SAP_AUTH_MODE`, `SAP_CERT_FILE`, `SAP_OAUTH_CLIENT_ID`, `SAP_PASSWORD`) no se aplican aquí, pues no hay un logon compartido que configurar. Eo contrario, **cada cliente MCP se autentica con su propio token de portador de SAP OAuth 2.0**: envía `Authorization: Bearer <token>` en `iniciar`, y ese token se convierte en la identidad SAP de esa sesión: su propio logon de ADT, sus propias cerraduras, su propia traza de auditoría. Si dos miembros del equipo se conectan a la vez, obtienen sesiones independientes, nunca un único usuario técnico compartido.

GXP15

`SAP_USER` es aún es obligatorio (todo modo que no sea de contraseña necesita un usuario provisional para construir el cliente de ADT), pero no se transmitirá nunca, no influye en who de la sesión es en realidad: SAP determina cada sesión a partir de su propio token, igual que [§11](docs/Authentication.md#11-oauth-20-mode).

| Variable                 | Efecto                                                                                                   |
| ------------------------ | ------------------------------------------------------------------------------------------------------ |
| `ABAP_MCP_TRANSPORT=http`       | Cambiar de stdio a Runable HTTP.                                                                 |
| `ABAP_MCP_HTTP_PORT`        | Puerto en el que escucha. Predeterminado `3000`.                                   |
| `ABAP_MCP_HTTP_HOST`        | Dirección de escucha. Predeterminado `0.0.0.0`.                                              |
| `ABAP_MCP_HTTP_ALLOWED_ORIGINS` | Orígenes de navegador permitidos para llamar a `/mcp`; comma separated; `*` permite todos. Vacío (el value default) no emt. |
| `ABAP_MCP_HTTP_ALLOWED_HOSTS`  | Valores `Host` que se atienden, separados por comand. Vacío acepta cualquier.      |
| `ABAP_MCP_HTTP_RATE_LIMIT` | Peticiones por minute y session. `0` (por defecto) off.                                             |

Registra un cliente igual que cualquier otro servidor MCP remoto con Streamable HTTP, pointing at `/mcp` and providing that user's own SAP OAuth token:

GXP16

One petición con no credentials is rejected with `401` before any SAP traffic; token que SAP rejects itself (“una cadena with old”) with the message "401" from SAP. No existe ningún secreto adicional y separado que configurar para el transporte: el token de SAP **es** el control de acceso.

Un cliente that prefiere not be one desconectado cada vez que caduque su token de acceso can send its own token of refresh in the `X-SAP-Refresh-Token" instead, and the session renews automatically using a `refresh_token` grant. This requires `SAP_OAUTH_TOKEN_URL` and `SAP_OAUTH_CLIENT_ID` in the container — the subscription to the client where a refresh takes back is site the implementation, while the refresh token (and thus the SAP identity) remains caller.

Browser origins are refused unless `ABAP_MCP_HTTP_ALLOWED_ORIGIN` bans them: that's an anti-DNS `rebinding` protection that the MCP spec requires the server to apply itself, since a rebind request never crosses the reverse proxy in front. Or have a list of origins with the appropriate CORS headers. Clients that do not send `Origin` — any MCP client that is not web page — no result covers.

The container's `docker-entrypoint.sh` automatically skips its Kerberos configuration when `ABAP_MCP_TRANSPORT=http` is set, since the `resolveAuthMode()`` call does not describe realmente once every session starts with its own token. the TLS termination is left to whatever in in front of the container (reverse proxy or ingress), as with any other HTTP service. The full detail, including the OAuth grant mechanics to which this reduced, can be found in [`docs/Authentication.md` §12](docs/Authentication.md#12-streamable-http-transport-and-per-connection-sessions).

### Multiple systems

A server runs on a system and a client for its lifetime; none can be changed at runtime. So record an entry per client or system and assign it a `SAP_SYSTEM_ID`:

GXP17

Each server then is present in MCP `instructions` it returns at connection time:

> This server has been bound to SAP system **DEV**, client 100 (https\://…:44301).
> It cannot change system or client at runtime — both are fixed by the environment in which it started.
> If a request refers to a different system or client, use the MCP server configured for that one;
> if any is registered, say so instead of acting.

That is what allows an agent to route "please check it in DEV client 200" to the right server without calling **any**. `healthcheck` is reporting the same identity for a server that needs to be asked directly.

**The declaration is checked.** SAP identifies the system and the client in the session cookie it sends at logon (`SAP_SESSIONID_DEV_`), so the server knows what it is actually talking to. If this does not match with `SAP_SYSTEM_ID` — e.g., a copied entry pointing to the wrong host — `healthcheck` shows a `WARNING` and it is logged meaningfully. Beattentive, because every tool continues to work perfectly; only not in the right system.

***

## Quick tour

Read any object of the name — no need to discover URL:

GXP18

Explore all naming conventions — patterns are normalized for you, so `zpp_lab` becomes `ZPP_LAB*`:

GXP19

Review a function module — first read the signature, and then validate the request:

GXP20

A BAPI and its commit in **one** batch must travel; or commit will fall in its own LUW and changes to the BAPI are lost:

GXP21

The full cycle of writing (**blocked → modify → check → activate → unlock**), debugger, ATC and all other workflows can be found in [`docs/MCP-Tools.md` §4](docs/MCP-Tools.md#4-golden-at) **.

***

## Working with ABAP objects

Three tools cover most of what they need, and each takes a **name** instead of a URL ADT:

| What we need                                                          | Tool                  |
| -------------------------------------------------------------------- | ----------------------- |
| The French, program, Include, function group or module                       | `的社会`              |
| The shape of a table, structure or view            | `readAbapObject`    |
| Everything behind a naming convention        | `searchPackages`        |

GXP22

`readAbapObject` returns metadata **and** source in a single call. When a name belongs to multiple objects — `ZPP_EXT_LABEL_DATA` is both a function group and a function — it takes the most specific one and tells you via `ambiguous:true` and `alternatives`; pass `objectType` to sp force. Objects with no source come back with `hasSource:false` and a note on the right tool.

`describeAbapTable` gives field names, DDIC types, lengths, key flags, data elements, domains and **check tables** — the check table is the target of the foreign key, which is the fastest way to see how two tables are related. `objectStructure` doesn't return fields for a table, and `tableContents` returns lines, not definitions, so neither answers “*What does a table look like*?”.”

### Rules to put in your client’s system

* **Opt for tools by name.** Use the `searchObject` → `objectStructure` → `getObjectSource` fallback only if you need intermediate results. **In full rute `/sap/bc/adt/...` never build by hand**.
* **Select efficiently.** SAP tables are large. Always limit `SELECT` with a `WHERE` class, and use `SELECT SINGLE` (all keys are known) or `UP TO n ROWS` otherwise.

`GXP23`

SAP is disconnected from your file system: reading your source just returns it as a result of a tool; writing a local file doesn't change anything in SAP. Local copies are useful only for diff. They are nothing more.

> Earlier with `GetTable`, `GetStructure` and `GetTypeInfo` in the README. Are scattered in the different project [`img`](https://github.com/yoshi) not this server.

***

## Development

`GXP24`

Tests live in [`src/__tests__`](src/__tests__) and run completely offline: the `JSON` "ROM suite exercises` the handler end-to-end against a **simulated dummy SAP Gateway** node.

For a **real** system (requires a Kerberos ticket), the end-to-end check is:

GXP25

It drives the built server off MCP stdio exactly like a client, and only calls read-only function blocks.

Adding a tool is one-file change — see [`docs/MCP-Tools.md` §10](docs/MCP-Tools.md#10-extending-the-server).

## Troubleshooting

| Síntoma                                  | Causa / solución                                                                                                                                                                                       |
| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `HTTP 401` en cada llamada              | Modo Kerberos: no hay un ticket válido, o el sistema no acepta SPNEGO: comprueba `klist` y tu conexión VPN/dominio. Modo con certificado: consulta [`docs/Authentication.md` §6](docs/Authentication.md). |
| `curl nicht gefunden`                   | El arranque de SSO no pudo encontrar `curl`; define `SSO_CURL_PATH`.                                                                                                                                     |
| `SAP rejected the client certificate`   | El mapeo `CERTRULE`, `icm/HTTPS/verify_client` o la confianza en la CA en `STRUST`. El error indica el sujeto presentado: compáralo con `CERTRULE`.                                                     |
| `unable to get local issuer certificate` | CA interna. Define `NODE_TLS_REJECT_UNAUTHORIZED=0` (solo en desarrollo).                                                                                                                                |
| Las herramientas RFC devuelven `reachable:false` | Ejecuta `checkJsonRpcEndpoint`. Esto separa un nodo `/sap/ge/jsonrpc` SICF inactivo de un problema de CSRF o de 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 hacia `dist/index.js` y que se haya ejecutado `npm run build`.                                                                                                              |

Más en uno de los elementos: [`docs/MCPTools.md` §8](docs/MCP-Tools.md#8-troubleshooting-matrix).

## Contribución

1. Haz un fork del repositorio
2. `git checkout -b feature/nombre-de-tu-funcion`
3. Realiza tu cambio y deja `npm test` y `npx tsc -- noEmit` en verde
4. `git commit -m "Add some feature"` y `git push origin feature/your-feature-name`
5. Abre una pull request

## Licencia

[MIT](LICENSE). Proyecto upstream y autor original: [mario-andreschak](https://github.com/mario-andreschak/mcp-abap-abap-adt-api).
A
license - permissive license
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Related MCP Servers

  • A
    license
    C
    quality
    Not graded
    maintenance
    An MCP server that facilitates seamless interaction with SAP ABAP systems to manage development objects, transport requests, and source code. It provides a comprehensive suite of tools for performing syntax checks, object searches, and code modifications via the ADT API.
    100
  • A
    license
    C
    quality
    D
    maintenance
    An MCP server that enables seamless communication between ABAP systems and MCP clients using the ABAP Development Tools (ADT) API. It provides tools for managing ABAP objects, handling transport requests, and performing code analysis directly through MCP-compatible interfaces.
    100
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    A standalone MCP server for SAP ABAP development and customizing that connects directly to your SAP system via ADT REST API, enabling AI assistants to search, read, write, activate, transport, debug, and run quality checks on ABAP code, as well as manage customizing/IMG configurations with governed transport recording.
    MIT
  • A
    license
    B
    quality
    C
    maintenance
    MCP server for SAP ABAP development that enables AI assistants and code editors to interact with SAP systems via ABAP Developer Toolkit (ADT) APIs, supporting read, create, update, and delete of ABAP objects.
    100
    1,664
    MIT

View all related MCP servers

Related MCP Connectors

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Ciltress/sap-abap-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server