COBOLSTACK.COM
//BLOG    DD DSN=POSTS(MCPONTHE),DISP=SHR

2026-09-25 · CobolStack

MCP on the Mainframe Already Runs: Answering the Architecture and Security Questions from Something We Built

Can MCP have a place in the mainframe world? Yes, and it already runs. The post's six areas and its failed-batch-job flow, mapped to real MCP tools on SteelFrame, our mainframe-compatible environment. Then the questions that actually matter: direct exposure or an integration layer, and how you govern an agent's identity, scopes, audit trail and writes.

Vidyut Saha, whose two earlier pieces on the 2030 mainframe talent model we answered in August and earlier this month, has moved on to a question that is more technical and, we think, more urgent: can the Model Context Protocol have a place in the mainframe world? His answer is a cautious yes. He sketches an AI assistant that works with z/OS, COBOL, JCL/JES, CICS, DB2 and VSAM. He walks through a failed batch job (find the job, read the JES output, identify the ABEND, trace the COBOL, check DB2, explain). He insists that RACF, authorization, auditing and governance stay at the centre. Then he asks three questions: whether the mainframe could become an active participant in an agent ecosystem, whether you would expose COBOL, CICS, DB2 and JES directly or put an integration layer in between, and where the biggest opportunity and the biggest risk lie.[1]

Infographic titled 'Can MCP have a place in the Mainframe world?': an AI agent connects through an MCP bridge to z/OS (system and operational information), COBOL (code understanding and dependency analysis), JCL/JES (job submission, monitoring and output analysis), CICS (controlled transaction invocation), DB2 (governed data and metadata access) and VSAM (file and dataset analysis), with three discussion questions on opportunity, direct-versus-API-layer integration, and security concerns

Infographic from Vidyut Saha's LinkedIn post. Reproduced here to credit and respond to it, not as our work.

We can answer from experience, because we built one. SteelFrame, our mainframe-compatible environment, has an MCP server in daily use. SteelFrame is an independent clean-room implementation, not IBM z/OS, and is not affiliated with or endorsed by IBM. It runs COBOL, JCL through a JES2-class spool, CICS-compatible transactions, VSAM and a DB2-compatible SQL engine to the published semantics. This post takes the six areas and the batch-failure flow, shows each one as real tool calls against a running system, and then answers the architecture and security questions the way we had to answer them in code.

First, the landscape: this is no longer hypothetical

MCP itself is small. It is an open protocol in which a server exposes tools (named functions with a JSON Schema for their inputs), and an AI application's client discovers them with tools/list and invokes them with tools/call, all over JSON-RPC 2.0.[2] That simplicity is why mainframe vendors have moved quickly:

So the answer to "can MCP have a place?" is already yes. What is still open is what the architecture should look like, and what makes it safe.

The six areas, as tools that exist today

These are the tools SteelFrame's MCP server exposes, taken from the live catalog the server publishes (99 tools on the persistent lane on the day we checked). The first column uses the post's own words. The last column is the question a security reviewer would ask about each area.

Saha's areaSteelFrame MCP toolsScope requiredGovernance control
z/OS: system & operational info system_info, whoami, list_replies (see outstanding WTORs), reply_wtor system.read · jobs.read / jobs.write read-only by default. system_info reports the engine's own security posture, so an agent can tell whether enforcement is on. Admin, operator and security verbs are left out of the MCP catalog whatever the token
COBOL: understanding & dependencies search_source, find_program, explain_program, analysis_impact / graph / metrics, check_source datasets.read facts come from a deterministic analysis model: copybook closure, the JCL steps that run a program, its CSD slice, the scheduler jobs. explain_program assembles those facts into a provider-agnostic request for the tenant's own configured LLM provider, so source only goes where the tenant has decided it may
JCL / JES: submit, monitor, output list_jobs, get_job, read_spool, wait_job; submit_job, run_batch; hold, release, cancel, purge jobs.read · jobs.write looking and acting need different scopes. read_spool returns only the last 500 lines unless asked for more, so a runaway SYSOUT cannot flood the model's context. Cancel and purge carry MCP's destructive hint
CICS: controlled invocation cics_csd; cics_open_session / cics_send / cics_run_script; cics_link with a COMMAREA; cics_define cics.read · cics.exec · cics.admin reading definitions, driving transactions and defining resources are three separate scopes. cics_define is refused on the live estate and works only inside an isolated workspace
DB2: governed data & metadata sql (SPUFI-style: SQLCODE, message text and rows per statement) db2.exec SQL execution is its own scope, separate from dataset and job access, and is granted only to agents that need SQL. Every SQL batch is recorded in the audit trail as the calling userid
VSAM: file & dataset analysis vsam_info, dataset_info, read_records, decode_records (records through the copybook, beside the raw EBCDIC and packed bytes); write_records, define_cluster datasets.read · datasets.write decoding is read-only. The bulk-seeding tool, load_dataset, carries the destructive hint and refuses system high-level qualifiers. Writes can be confined to a copy-on-write workspace

Every row has a read tier and a separate write or execute tier, which is the most important design decision in the server. And there is no "run any TSO command" or "issue any console command" tool. That is deliberate, for reasons covered below.

The failed batch job, as real tool calls

Saha's flow is find the job → analyse JES output → identify the ABEND → trace the COBOL → check DB2 → explain. We ran it, read-only, against the hosted SteelFrame estate on 25 September 2026. The job is a deliberately broken 13-line test program left over from an earlier MCP test session, not a production failure, and we say so because the results below are quoted, not illustrated. Outputs are trimmed but otherwise verbatim.

// 1 · find the job: newest-first list, filtered on the abend field
list_jobs      {owner:""}
  → … JOB07444 IBMUSERR  maxcc:"S0C7"  abend:"S0C7"  steps:[GO / S0C7TST] …

// 2 · analyse the JES output: status + spool file list, then the one that matters
get_job        {jobid:"JOB07444"}
  → steps:[{name:"GO", pgm:"S0C7TST", rc:"S0C7"}]
    files: JESJCLIN · JESMSGLG · JESJCL · JESYSMSG · D0060.GO.SYSOUT (0 bytes)
read_spool     {jobid:"JOB07444", name:"JESYSMSG"}
  → CEE3207S The system detected a data exception (System Completion Code=0C7).
             From compile unit S0C7TST at entry point S0C7TST at statement 11 …
    IEF450I IBMUSERR GO - ABEND=S0C7 REASON=00000000
    (the same log names the field, WS-BAD, PACKED-DECIMAL, bytes X'404040')

// 3 · identify the ABEND: S0C7 = data exception; X'404040' is three EBCDIC spaces
//     sitting where a packed-decimal number should be

// 4 · trace the COBOL
find_program   {name:"S0C7TST"}
  → source: IBMUSER.SOURCE(S0C7TST) · loadModules: IBMUSER.LOADLIB(S0C7TST)
    summary: {loc:13, calls:[], files:[], sql:0} · jclRunning:[] · csd: none
read_member    {dsn:"IBMUSER.SOURCE", member:"S0C7TST"}
  →  05 WS-BAD PIC S9(5) COMP-3.
     05 WS-CHR REDEFINES WS-BAD PIC X(3).
     …
     MOVE X'404040' TO WS-CHR.
     COMPUTE WS-RES = WS-BAD + 1.          ← statement 11

// 5 · check DB2: skipped on evidence. find_program says sql:0. (The door is `sql`;
//     a read-only catalog SELECT we ran on the same box returned SQLCODE 0.)

// 6 · explain
explain_program {program:"S0C7TST"}
  → context pack: {loc:13, paragraphs:["(MAIN) (lines 10-13, 4 stmts)"], callers:[],
    jobs:[], datasets:[], sql:[], complexity:1} + source, assembled as a
    provider-agnostic request for the tenant's configured LLM

The diagnosis needed no language model at all. The spool named the statement and the bytes. The source showed a REDEFINES that let an alphanumeric MOVE put spaces into a COMP-3 field. The analysis model said there was no SQL, so the DB2 step was correctly skipped instead of being done out of ritual. The agent's job here is sequencing and reading, and the tools give it facts to sequence. The explanation step reasons over those same facts, grounded in the analysis model, rather than replacing them.

Least privilege is two strings Every call in that trace needs only jobs.read and datasets.read. A token minted with those two scopes can run the whole diagnosis, and if its prompt is hijacked it still cannot submit, purge, write or define anything. Least privilege is not a policy slide. It is two strings in a token request.

Direct exposure, or an integration layer?

Saha's sharpest question is whether you would expose COBOL, CICS, DB2 and JES "directly through MCP", or put APIs and an integration layer between MCP and the mainframe. Our answer, reached by building it, is neither in its naive form. MCP should be a governed projection of the platform's own API. It should be neither a raw pipe into the subsystems nor a new, separately governed integration tier.

Concretely, SteelFrame has one REST route registry, and the MCP catalog is generated from it. Every route that opts in becomes exactly one tool, whose name, description, input schema, scope and read or destructive annotation all come from the route definition. Nothing is hand-written per tool, so the catalog cannot drift from the dispatcher. Both MCP doors (a local stdio bridge and a remote POST /mcp endpoint) authenticate through the same function as the REST API and dispatch every tool call through the same call path, so scope checks, audit and metrics are identical by construction.[9] IBM's z/OS Connect design follows a similar instinct: the tools are the API operations you already deploy and govern, and "no new access paths" is the point.[3][4]

Three rules came out of that design, and we would apply them on any estate, ours or IBM's:

  1. Curate verbs, not systems. read_spool is a verb. "Run any TSO command" is a system. A verb has a schema, a scope and an audit shape. A general command channel has none of them, and you are left hoping the model stays well-behaved. Zowe does expose TSO and console, and it wraps them in capability tiers and pattern checks.[6] We chose not to expose them at all.
  2. If a capability has no governed API yet, build that API first. MCP should not be the first governed interface a subsystem ever has. When the only route to a CICS transaction is a screen, the answer is a proper interface (for us, cics_link with a COMMAREA, or a scripted session that returns fields by BMS name). It is not an agent scraping a 3270 stream.
  3. Return facts, not verdicts. Tool results are structured data: step RCs, spool text, decoded rows beside their raw bytes, screens as named fields. The server never decides whether two systems are equivalent and never converts code. The judging happens in your harness, where it can be reviewed.

Security: the concerns, and how each one is governed

The MCP specification is blunt about where responsibility sits. Servers MUST validate inputs, implement access controls, rate-limit and sanitize outputs. There SHOULD "always be a human in the loop with the ability to deny tool invocations". And tool annotations are to be treated as untrusted unless they come from a trusted server.[2][10] Here is how those obligations land on a mainframe-shaped system.

ConcernWhat we do in SteelFrameWhat we'd insist on in production
Identity every call carries a bearer token: a scoped API token or a logon session. Scope lists fail closed (no list means no scopes). Self-service tokens are clamped to the minter's own scopes. RACF-style revocation applies to both modes one identity per agent, never a shared or SPECIAL userid. The MCP spec also forbids passing through tokens not issued to the MCP server itself[11]
Over-broad scopes separate read, write and execute scopes per area. A triage agent needs jobs.read + datasets.read. SQL execution (db2.exec), CICS execution and scheduler control are each separate grants grant each agent only the scopes its job needs. On real DB2, a look-only agent's authorization ID should carry SELECT-only grants
RACF-style resource checks RACF-style dataset and resource checks run under the agent's own userid. With enforcement switched on, a violation is denied and written to the audit trail as an ICH408I entry enforcement on, with the agent's userid profiled like any batch ID. Zowe's server enforces through SAF/RACF on the host, which is the right place[6]
Audit every mutating call (POST, PUT or DELETE), denials included, is written to the audit trail with user, token kind (mcp), operation, path and status. Every call is counted in per-operation metrics. Passwords never reach the log the audit trail fed into the same SIEM as your SMF records, reviewed like any other privileged-access log
Human in the loop every tool carries MCP annotations: 41 read-only, 19 destructive, 39 non-destructive writes in today's catalog. MCP clients use these to decide what to confirm treat the annotations as hints for the confirmation prompt. The enforcement belongs in the server's scopes. Confirm every write, and double-confirm destructive ones
Isolation & change control create_workspace clones the estate copy-on-write, and every tool can run inside it while the live estate stays untouched. A private lane runs RAM-only with zero retention. cics_define and scheduler reset are workspace-only agents change copies, and promotion to production goes through the change control you already have. MCP is not a change-management system
Prompt injection tool results are returned as data, and the blast radius is set by the token, not by the model's good behaviour assume spool, source comments and record contents are attacker-reachable text. OWASP calls this indirect prompt injection, and its mitigations are least privilege and human approval for high-risk actions[12]
Data residency / PII the private lane's parent-side audit keeps sizes, return codes and workspace IDs, never content. explain_program calls only the tenant's configured LLM provider, or nobody mask production data before it reaches any environment an agent can read. The model provider is a data processor, and your DPA should say so

If we had to name the biggest risk, it is not a new MCP-specific attack. It is an old mainframe mistake repeated at machine speed: giving a non-human worker a powerful human identity. An agent logged on as a SPECIAL user can do whatever that user can, faster, driven by whatever text it read last. The MCP specification warns against wildcard scopes for the same reason.[11] The control is one the mainframe community already knows: a dedicated userid, profiled narrowly and audited, the way RACF has handled batch IDs for decades.

Active participant, or modernization target?

Saha's larger question is whether governed MCP access could make the mainframe "an active participant in an AI-agent ecosystem, rather than simply being a system that AI helps modernize." We think it already is one, in three roles that do not compete with each other:

What makes the mainframe a participant is not the protocol. It is the discipline that already governs a production LPAR: narrow identities, separate read and write privileges, an audit trail, and no change without evidence and a human signature. MCP makes it cheap for agents to ask questions. Governance decides which answers they may act on.

Try it

The SteelFrame MCP documentation is public. It covers both doors (stdio bridge and remote POST /mcp), both authentication modes, the scope sets, the persistent and zero-retention lanes, a worked compile → run → spool example, and a live tool reference rendered from the same catalog your MCP client will receive: steelframe.cobolstack.com/mcp-docs.html ↗.

The same design runs on the midrange side. SteelFrame X is our IBM i-compatible (AS/400-style) environment, also an independent clean-room implementation that is not affiliated with or endorsed by IBM. It has its own MCP server over CL, RPG IV and RPG III, COBOL, DDS physical, logical, display and printer files, DB2 for i SQL, job queues, spooled files and 5250 display sessions driven one AID key at a time. Every call runs as a real user profile in a real job, under that profile's own object and special authorities, so nothing an MCP caller does can exceed what the profile could do at a 5250: steelframex.cobolstack.com/mcp-docs.html ↗.

Our MCP page puts the mainframe server and its IBM i companion side by side and describes the evaluation, agent-loop and governance engagements we run around them. Access is issued per organisation, with scopes, after a conversation, so ask for evaluation access and bring the batch failure you would most like an agent to have diagnosed.

On LinkedIn

This post responds to Vidyut Saha's LinkedIn post asking whether MCP can have a place in the mainframe world and how its architecture and security should work. It is a practitioner's opinion and question, which is how we have cited it: for its framing and its questions, never for a figure. Our responses to his earlier pieces are here and here.

Sources

  1. Vidyut Saha: "Can MCP have a place in the Mainframe world?", LinkedIn post, September 2026. Opinion and questions; cited for framing only.
  2. Model Context Protocol specification (2025-06-18): Server features, Tools: tools/list and tools/call over JSON-RPC 2.0; "there SHOULD always be a human in the loop with the ability to deny tool invocations"; servers MUST validate inputs, implement access controls, rate limit and sanitize outputs; clients MUST treat annotations as untrusted unless from trusted servers.
  3. IBM Documentation: IBM z/OS Connect 3.0, "What is MCP": each deployed API operation is exposed as an MCP tool.
  4. IBM Think: Pratibha Ryali, "AI for business workflows on IBM Z: Governed decisions with z/OS Connect": MCP to "discover and invoke only approved operations"; "without introducing new access paths".
  5. IBM Documentation: IBM z/OS Connect 3.0, "Configuring MCP for z/OS Connect": security not yet available for the zosconnect:mcp-1.0 feature; not recommended for production until it is (as read in September 2026).
  6. zowe/zowe-mcp on GitHub: data sets, jobs, TSO/console and USS tools; read-strict default capability tier; untrusted-data marking; SAF/RACF enforcement.
  7. Open Mainframe Project: Joe Winchester, "Hello, Mainframe: Using Zowe in an AI World with MCP Agents", 1 July 2026.
  8. BMC Software press release: governed AI agents for enterprise workflows and mainframe operations (AMI Assistant MCP client, Control-M MCP server), 14 July 2026.
  9. SteelFrame: MCP servers & reference oracle (documentation): route-registry projection, two doors, scopes, lanes, workspaces; live tool catalog from GET /api/mcp/tools.
  10. Model Context Protocol specification (2025-06-18): Security and Trust & Safety: user consent and control; tools as arbitrary code execution; annotations untrusted unless from a trusted server.
  11. Model Context Protocol: Security Best Practices: token passthrough forbidden ("MCP servers MUST NOT accept any tokens that were not explicitly issued for the MCP server"); scope minimization; confused deputy; session hijacking.
  12. OWASP GenAI Security Project: LLM01 Prompt Injection: indirect injection via external content; least privilege; human approval for high-risk actions.

Vendor capabilities are reported as their own documentation states them, as read in September 2026. None implies endorsement of CobolStack. SteelFrame facts (tool names, scopes, annotation counts, audit behaviour) come from the live MCP catalog, the public documentation and the server source. The batch-failure trace was run read-only against the hosted estate on 25 September 2026 and is quoted, trimmed, from its actual output. IBM, z/OS, CICS, Db2, IBM i, AS/400, RPG, RACF and other marks are trademarks of their respective owners. CobolStack is not affiliated with, endorsed by, or sponsored by IBM. SteelFrame and SteelFrame X are independent clean-room mainframe- and IBM i-compatible implementations that conform to the published specifications but are not identical to them; your licensed system remains the sole conformance authority.