mcp-mainframe
README.md
# mcp-mainframe
A minimal **Model Context Protocol (MCP) server** that lets an AI assistant
(Claude, or any other MCP-compatible client) browse mainframe datasets, read
COBOL/JCL source, and submit/monitor batch jobs — the way this conversation's
Dice/Indeed connectors let Claude search job postings.
This is the proof-of-concept for the question: *"Mainframe code sits on some
machine — how would an AI tool actually get access to it?"* The answer is:
something has to expose it over an API first. On z/OS, that something is
**z/OSMF** (z/OS Management Facility), IBM's REST API layer over datasets,
jobs, and USS files. This project wraps that API as MCP tools.
## Why this exists
Mainframe shops don't let arbitrary tools touch production z/OS directly.
Real access always goes through a mediated layer — here, that's z/OSMF, with
its own auth and audit trail. This project makes that mediation visible and
concrete rather than hand-waving "AI can just read the mainframe."
## Architecture
```
┌─────────────────┐ MCP protocol ┌──────────────┐ z/OSMF REST API ┌──────────┐
│ Claude / any │ (stdio, JSON-RPC) │ server.py │ (HTTPS, Basic Auth) │ z/OS │
│ MCP-compatible │ ──────────────────────▶ │ (MCP tools) │ ────────────────────────▶ │ mainframe│
│ AI client │ │ │ │ │
└─────────────────┘ └──────┬───────┘ └──────────┘
│
▼
┌─────────────────┐
│ zosmf_client.py │
│ (mock or live) │
└─────────────────┘
```
- **`server.py`** — declares the MCP tools (`list_datasets`, `read_member`,
`submit_jcl`, etc.) and their input/output shapes. This is the only file an
MCP client ever talks to.
- **`zosmf_client.py`** — the only file that knows about z/OSMF's actual REST
endpoints. Has two modes:
- **MOCK_MODE (default)** — returns canned COBOL/JCL data so you can demo
the whole pipeline with zero mainframe access. This is what's checked in
and what runs out of the box.
- **LIVE MODE** — makes real HTTPS calls to a real z/OSMF instance. Flip on
by setting `ZOSMF_MOCK_MODE=false` plus real credentials (see below).
## Tools exposed
| Tool | What it does |
|---|---|
| `list_datasets(pattern)` | List datasets matching an HLQ pattern, e.g. `NAVEEN.*` |
| `list_members(dataset)` | List members inside a PDS |
| `read_member(dataset, member)` | Read a member's full source (COBOL, JCL, copybook, whatever) |
| `submit_jcl(jcl_text)` | Submit a JCL job to JES, returns jobname/jobid |
| `get_job_status(jobname, jobid)` | Poll a submitted job's status (INPUT/ACTIVE/OUTPUT) and return code |
| `get_job_output(jobname, jobid)` | Pull the spool/SYSOUT text once the job finishes |
## Setup
```bash
python3 -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txt
```
## Running it
**Quick manual smoke test** (calls the client logic directly, no MCP protocol involved):
```bash
python3 -c "
from zosmf_client import ZosmfClient
c = ZosmfClient()
print(c.list_datasets('NAVEEN.*'))
print(c.read_member('NAVEEN.COBOL.SOURCE', 'PARTUPD'))
"
```
**Full MCP server, with the official MCP Inspector** (browser UI to call each
tool by hand — best for a live demo):
```bash
mcp dev server.py
```
**Point Claude Desktop or Claude Code at it** by adding to that client's MCP
config (e.g. `claude_desktop_config.json`):
```json
{
"mcpServers": {
"mainframe": {
"command": "/absolute/path/to/venv/bin/python",
"args": ["/absolute/path/to/server.py"]
}
}
}
```
Once connected, you can literally ask Claude things like *"list the COBOL
members in NAVEEN.COBOL.SOURCE and explain what PARTUPD does"* and it will
call these tools to answer — using the mock data out of the box.
## Going live against a real z/OS system
Set these environment variables and flip mock mode off:
```bash
export ZOSMF_MOCK_MODE=false
export ZOSMF_BASE_URL=https://your-mainframe-host:443
export ZOSMF_USER=your_tso_userid
export ZOSMF_PASSWORD=your_password
export ZOSMF_VERIFY_TLS=true # set false only for self-signed dev certs
```
No code changes needed — `zosmf_client.py` will start making real HTTPS calls
to `/zosmf/restfiles/...` and `/zosmf/restjobs/...` instead of returning mock
data. Note: `PARTUPD`, `DLRBATCH`, `NAVEEN.COBOL.SOURCE`, etc. are fictional —
swap in real dataset names once pointed at an actual z/OSMF-enabled LPAR.
## Known limitations
- **z/OSMF must already be configured on the target LPAR.** Hercules/TK4- (a
classic 3270/TSO setup) does not ship z/OSMF enabled by default — this
targets a modern z/OS system with z/OSMF turned on, which most current
mainframe shops run, but it's not "any mainframe out of the box."
- **No write/update tools are implemented** (e.g. no `update_member`) —
intentionally, since letting an AI agent directly overwrite production
COBOL source is exactly the kind of unreviewed change most shops' change
management (ChangeMan, Endevor) would never allow. Read + submit-job only,
by design.
- **Auth is Basic Auth for simplicity.** A production version would use
z/OSMF's token-based auth or client certificates, and would run behind
the same access controls (RACF, ACF2, Top Secret) already governing the
mainframe.
- **This is a proof-of-concept, not a vetted enterprise tool** — it's meant
to demonstrate the architecture (MCP ⇄ z/OSMF ⇄ z/OS), not to be pointed at
a real production LPAR without a security review.
## Talking points this supports
- "AI tools can't reach mainframe code directly — something has to expose it
over an API first. On z/OS that's z/OSMF; I built an MCP server on top of
it so any MCP-compatible AI client can browse datasets and submit jobs.
- "I designed it read-mostly on purpose — job submission but no direct
dataset writes — because that mirrors how real shops gate mainframe changes
through formal change management, not ad hoc edits."
- "It runs in mock mode against realistic COBOL/JCL so it's demoable without
needing a live z/OS system, but the live-mode code path against real
z/OSMF REST endpoints is implemented and ready to point at a real LPAR."
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues