Integration test bed for the mcp2 ABAP MCP Server SDK: ABAP test servers
(src/), abapGit table-content provisioning (data/), and a Jest suite (test/) that
exercises a live ABAP system over HTTP.
The native target is the MCP 2026-07-28 draft synchronous request/response
profile. ABAP ICF cannot provide SSE or streaming responses, so sessions,
subscriptions/listen, server-pushed notifications, and other streaming-only
features are explicitly unsupported and tested as such. Ordinary requests use
single application/json responses.
Legacy 2025-03-26, 2025-06-18, and 2025-11-25 requests are supported
statelessly using the latest legacy (2025-11-25) data shapes. Without a
session, requests following initialize cannot recover an older negotiated
revision reliably because the older revisions did not require a per-request
version header.
src/— minimal, full-capability, schema, and authorization test servers. The schema server covers complex, wide, deep, and DDIC-derived schema integration cases; the authorization server is registered twice to exercise both allow and deny paths.data/— abapGit table-content files that provision thezmcp2_serversandzmcp2_originsrows the suite expects (areaTEST, serversMINIMAL,FULL,SCHEMAS,ALLOWED, andDENIED).test/— Jest suite.cd test && npm test. Endpoint defaults tohttp://172.26.128.1:8000/zmcp2(override withMCP2_BASE_URL).
The data/*.conf.json + *.tabu.json pairs are abapGit table content (TABU) files.
abapGit only deserializes them when all of the following hold — otherwise it silently
skips them or raises Table … not supported for updating data, and the rows never appear:
- The target table must pass abapGit's data supporter. By default only
customer-defined customizing tables qualify: transparent table, delivery class C,
data class APPL2, active, not SAP-owned
(
zcl_abapgit_data_supporter->get_supported_objects). The mcp2 config tables (zmcp2_servers,zmcp2_origins,zmcp2_config) are set up exactly like that — note APPL0 would not work, which is why data pulls silently did nothing before the tables were switched to APPL2. Alternatively a system-wide abapGit user exit (zif_abapgit_exit~change_supported_data_objects) can whitelist tables. - The data objects must be confirmed in the pull dialog. TABU entries show up as decisions alongside overwrite prompts; unconfirmed entries are skipped.
- Customizing request. In a transportable package, pulling customizing-table rows
prompts for a customizing request. In a
$-package this doesn't apply. - Client. Rows are written to the client you are logged into during the pull, and
the suite's servers run in client
001— pull in001.
If data deserialization still doesn't cooperate, enter the rows by hand (SE16/SM30). Values are case-insensitive where noted:
| Table | Row |
|---|---|
zmcp2_servers |
TEST / MINIMAL / ZCL_MCP2_TEST_MINIMAL |
zmcp2_servers |
TEST / FULL / ZCL_MCP2_TEST_FULL |
zmcp2_servers |
TEST / SCHEMAS / ZCL_MCP2_TEST_SCHEMAS |
zmcp2_servers |
TEST / ALLOWED / ZCL_MCP2_TEST_AUTH |
zmcp2_servers |
TEST / DENIED / ZCL_MCP2_TEST_AUTH |
zmcp2_origins |
TEST / FULL / ALLOW1 / https://allowed.example (origin matching is case-insensitive, uppercase is fine) |
In the SAP client running the suite, zmcp2_config must have no cors_mode = ignore row —
the CORS tests assume the default check mode (an empty table is fine).
MIT. See LICENSE.
cd test
npm test # full suite against the live system
npx tsc --noEmit # typecheck only
The suite is the authoritative test count; it covers both protocol eras (legacy
initialize clients and modern _meta clients), raw-HTTP edge cases, header
mirroring, CORS, tasks, and MRTR input round-trips.
Run ZMCP2_SCHEMA_BENCH from SE38, or profile it directly with SAT. Parameters control
schema width, nesting depth, iterations, and whether DDIC generation is included. The report
prints separate build, serialization, validation, and DDIC timings plus the serialized schema
size. Defaults are intentionally moderate; use SAT variants for repeatable comparisons.
test/schema/ vendors the official generated JSON schemas for every supported
legacy revision and the modern draft. test/schema/pin.json records the exact
upstream commit and SHA-256 hashes, so normal tests remain network-independent.
Run npm run schema:refresh -- <git-ref> from test/ to update the snapshot
and pin manifest, then review the resulting schema diff before committing it.
The modern Tasks extension is pinned independently from the core specification
using the generated schema from modelcontextprotocol/ext-tasks. The pin
manifest records both upstream commits and every vendored schema hash.
The test:schema suite validates representative JSON-RPC envelopes and
method-specific results using draft-07 for older revisions and 2020-12 thereafter.
Legacy method results intentionally use the 2025-11-25 schema profile for all
supported legacy headers because the stateless server cannot retain the version
negotiated by an earlier initialize request.
The test project pins the v2 TypeScript SDK packages to the exact published
2.0.0-beta.4 release; the v1 alias remains for legacy compatibility coverage.
The modern and legacy suites use the SDK for ordinary tools, resources, prompts,
completion, discovery, and elicitation flows. Raw HTTP remains intentional for
transport headers, HTTP status codes, malformed JSON-RPC nodes, media types,
exact result metadata, and legacy/modern wire-shape checks.
Modern Tasks also remain raw: beta.3's 2026 wire registry does not expose
tasks/get, tasks/update, or tasks/cancel, and its exported task schemas are
the deprecated 2025 vocabulary rather than SEP-2663's flat task results. This
prevents the beta SDK from masking Tasks interoperability defects until it adds
the extension surface (confirmed still unimplemented as of 2.0.0-beta.4; see
modelcontextprotocol/typescript-sdk#2189).
Modern serverInfo is checked in both places the server writes it. The 2026-07-28 draft
moved serverInfo out of the top-level DiscoverResult and into every modern result's _meta
under io.modelcontextprotocol/serverInfo (schema change merged 2026-07-16, three days after
2.0.0-beta.4 shipped) — but every currently published SDK release, including 2.0.0-beta.4,
bundles a DiscoverResultSchema that still requires the old top-level field, and fails
client.connect()'s version-negotiation probe outright if it's missing (not just a stale
getServerVersion() — the whole modern SDK connection breaks). The server therefore writes
serverInfo top-level (discover only, for every current SDK) and in _meta (every modern
result, spec-current). modern/discover.test.ts keeps asserting the top-level field via the SDK;
the ... (via _meta) tests in raw/http.test.ts cover the new location until a released SDK
reads it for the modern era, at which point the top-level write can be dropped.