HivePaaS
An open-source, self-hosted PaaS on Docker Swarm. Deploy apps, databases and functions from one VPS to a whole cluster, with SSL, backups and autoscaling built in.
Enterprise MCP server for IBM z/OS — jobs, datasets, USS, CICS, Db2, and operational diagnostics via Zowe SDK.
Developer toolsTypeScript · JavaScriptGitHub @NotHarshhaaOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
An enterprise-grade Model Context Protocol (MCP) server for IBM z/OS environments. Bridges MCP-compatible AI agents with mainframe resources jobs, datasets, USS, and operational diagnostics using IBM Zowe SDK as the connectivity layer.
Taken from the repository README
Loading the full README.
Read the full README ↗An enterprise-grade Model Context Protocol (MCP) server for IBM z/OS environments. Bridges MCP-compatible AI agents with mainframe resources — jobs, datasets, USS, and operational diagnostics — using the Zowe SDK (Open Mainframe Project) as the connectivity layer.
mainframe-mcp-server exposes z/OS capabilities as Model Context Protocol tools. An AI agent can list jobs, read datasets, inspect USS paths, submit JCL, and run operational diagnostics — without you writing Zowe CLI commands by hand.
Connectivity is handled by the Zowe SDK (Open Mainframe Project) over z/OSMF REST. This project adds the MCP tool layer, input validation, safety limits, and AI-friendly response formatting on top.
| mainframe-mcp-server | Zowe CLI + scripts | Host IDE tooling (IDz, Z Open Editor) | Other z/OS MCP bridges | |
|---|---|---|---|---|
| Interface | MCP tools for AI agents | Terminal commands, shell scripts | Eclipse/VS Code GUIs | MCP tools for AI agents |
| Output | Structured sections & tables tuned for LLM reasoning | Raw terminal text you must parse yourself | IDE views | Varies by project |
| Guardrails | Read-only by default, tool allow/block lists, dataset & USS boundaries, audit logging, JCL size cap | None built in — you script them | Client-side only | Varies by project |
| Failure knowledge | Curated abend-code reference, failing-step heuristics, risk scoring | Manual message lookup | Interactive debugging | Rare |
| Install | npx — no server-side footprint beyond z/OSMF access | Node + Zowe CLI + your scripts | Full IDE estate | Often heavier runtimes |
| Coverage | Jobs, datasets, USS, CICS, Db2, SMF/RMF, RACF audit (30+ tools) | Full Zowe command set | Edit, debug, compile | Varies |
Honest positioning: the z/OS MCP ecosystem is early. IBM and community authors publish their own MCP bridges — evaluate them against your requirements. This project's differentiators are zero-dependency npm install, guardrails enforced at the server layer, and output shaped for LLM consumption rather than human eyes. It is not a replacement for Zowe CLI or IBM Z Open Editor — it is an MCP bridge over the same z/OSMF APIs.
The server is a pure client — nothing is installed on z/OS. It requires REST services that are enabled in standard z/OSMF estates.
| z/OSMF REST service | Used by | Notes |
|---|---|---|
Jobs REST (/zosmf/restjobs/jobs) | list_jobs, get_job_status, get_job_output, get_job_jcl, submit_jcl, all operations & intelligence tools | List, query, spool content, JES submit |
Files REST — datasets (/zosmf/restfiles/ds) | list_datasets, search_dataset, read_dataset, search_members, get_dataset_info | Catalog list, members, content read |
Files REST — USS (/zosmf/restfiles/fs) | list_uss_directory, read_uss_file, search_uss_files, RACF audit source | Directory list, file read |
z/OSMF info (/info) | verify_zosmf_connection | Optional; version read-out only |
RMF REST (/rmf/mvs/GPO/) | get_smf_metrics | Optional; disabled with RMF_METRICS_ENABLED=false |
Baseline: z/OS 2.4 LTS or later with APAR-current z/OSMF — the target the Zowe SDK (v8) is built against. Core job/dataset/USS tools are expected to work on z/OSMF levels from z/OS 2.3 onward; if you run an older or unusual level, open an issue with your results so the matrix can be updated.
list_cics_regions, get_cics_region_status, list_cics_transactions)CMCI_CONTEXT (CICSplex name or region APPLID); optionally CMCI_HOST, CMCI_PORT (default 1490), CMCI_BASE_PATH (default /CICSSystemManagement).XCSDATA/CICSPLEX resource classes as configured at your site).list_db2_subsystems, search_db2_catalog)DB2_HOST:DB2_PORT (default 50400, base path /dbrest) — direct DDF-served REST or fronted by your API mediation layer.DB2_LOCATION (the subsystem location name). Tools run read-only catalog SQL against SYSIBM.SYSTABLES with literal-escaped, size-capped input.query_racf_audit)RACF_AUDIT_USS_PATH) or a sequential dataset (RACF_AUDIT_DATASET), e.g. ADUINFOS/IRRADU00 output written to file. The server parses the text; it does not run IRRADU00 for you.Use a dedicated z/OS user with least-privilege RACF profiles (job list/read authority, submit authority only if SECURITY_READ_ONLY=false).
Type legend: READ — reads z/OS state, never modifies anything · WRITE — submits work to JES · OFFLINE — no mainframe I/O at all.
| Tool | Type | Description |
|---|---|---|
list_jobs | READ | List jobs by owner, prefix, or status |
get_job_status | READ | Status and return code for a job |
get_job_output | READ | Spool inventory or DD content |
submit_jcl | WRITE | Submit inline JCL — governed by pre-flight scan, change ticket, change window, and optional human approval |
approve_write | WRITE | Execute a pending JCL submission after human review (requires SECURITY_WRITE_APPROVAL=true) |
analyze_job_failure | READ | Abend code, failing step, and suggested fix |
get_job_jcl | READ | Retrieve submitted JCL from job spool |
| Tool | Type | Description |
|---|---|---|
list_datasets | READ | List datasets matching an HLQ pattern |
read_dataset | READ | Read a sequential dataset or PDS member |
search_dataset | READ | Search datasets by pattern |
search_members | READ | Search or list PDS members |
get_dataset_info | READ | Catalog attributes without reading content |
| Tool | Type | Description |
|---|---|---|
list_uss_directory | READ | List a USS directory |
read_uss_file | READ | Read a USS file |
search_uss_files | READ | Search files under a USS path |
| Tool | Type | Description |
|---|---|---|
find_failed_jobs | READ | Failed jobs in a time window |
summarize_abends | READ | Abend code breakdown across recent jobs |
system_health_summary | READ | Active, queued, and failed job snapshot |
investigate_incident | READ | Full incident bundle for a job |
lookup_abend_code | OFFLINE | Abend reference lookup (S0C7, S806, S222, S0C4, …) |
verify_zosmf_connection | READ | Test z/OSMF connectivity and auth |
compare_jobs | READ | Side-by-side comparison of two jobs |
get_user_jobs_summary | READ | Job counts by status for an owner |
Requires optional CMCI configuration — see z/OS prerequisites.
| Tool | Type | Description |
|---|---|---|
list_cics_regions | READ | List CICS regions via CMCI REST |
get_cics_region_status | READ | Status and attributes of a CICS region |
list_cics_transactions | READ | Transaction definitions in a region |
get_cics_region_stats | READ | Region statistics/attributes from the CMCI CICSRegion resource |
cics_newcopy | WRITE | NEWCOPY a program via CMCI action (CICS TS 5.6+) |
cics_disable_transaction | WRITE | Disable/enable a local transaction via CMCI SET action |
Requires optional Db2 REST configuration — see z/OS prerequisites.
| Tool | Type | Description |
|---|---|---|
list_db2_subsystems | READ | List Db2 locations via Db2 REST |
search_db2_catalog | READ | Read-only catalog search (tables, views, aliases) |
Operator commands run through an extended MCS console (ZOSMF_CONSOLE_NAME);
command tools are gated writes subject to read-only mode, policy roles,
change tickets, and change windows.
| Tool | Type | Description |
|---|---|---|
issue_console_command | WRITE | MVS commands (D A,L, D GRS,RES=…) with follow-up message collection |
get_console_messages | READ | Operations-log tail (SYSLOG-style console feed) |
hold_job / release_job | WRITE | JES2 $HJ / $OJ job hold and release |
cancel_job | WRITE | Cancel a job via the z/OSMF jobs API |
get_wlm_status | WRITE | D WLM display (service policy / resources) |
ims_command | WRITE | IMS commands via the system console (/DIS ACTIVE, /DIS TRAN …) |
get_hsm_activity | READ | DFSMShsm recall/migration activity from the operations log |
analyze_logrec | WRITE | Submit an EREP report against LOGREC and summarize error records |
| Tool | Type | Description |
|---|---|---|
scheduler_job_status | READ | Control-M / CA 7 / IBM WLS job status via their REST APIs (SCHEDULER_ADAPTERS) |
job_dependencies | READ | JCL dataset-flow analysis — inputs, outputs, updates, PROCs (predecessor/successor material) |
Requires MQ_REST_HOST (mqweb server) and optional MQ_REST_PORT/_USER/_PASSWORD.
| Tool | Type | Description |
|---|---|---|
mq_queue_status | READ | Queue curdepth vs maxdepth with high-water warnings |
mq_channel_status | READ | Channel status (RUNNING/RETRYING/STOPPED) and connection counts |
| Tool | Type | Description |
|---|---|---|
get_volume_space | READ | DASD volume space via z/OSMF SMI, with low-space alerts (STORAGE_FREE_THRESHOLD) |
get_job_capacity | READ | Per-step and total CPU from JESMSGLG (IEF374I/IEF376I) + MSU estimate (CAPACITY_MSU_RATING) |
estimate_mlc_cost | OFFLINE | MLC cost attribution from CPU/MSU (MLC_MSU_MONTHLY_PRICE) |
| Tool | Type | Description |
|---|---|---|
summarize_dump | READ | CEEDUMP / SYSMDUMP / SYSUDUMP digest — completion codes, failing module, LE conditions |
| Tool | Type | Description |
|---|---|---|
get_smf_metrics | READ | SMF/RMF performance metrics snapshot |
query_racf_audit | READ | Query RACF audit records from a log source |
security_posture_summary | OFFLINE | Report active security controls and recommendations |
Built in — see How the intelligence tools work.
| Tool | Type | Description |
|---|---|---|
analyze_root_cause | READ | Deep root-cause analysis with correlation and action items |
predict_batch_failures | READ | Predictive risk scoring for recurring batch failures |
| Tool | Type | Description |
|---|---|---|
list_environments | OFFLINE | Named z/OS environments (DEV/TEST/UAT/PROD, LPARs) with per-environment read-only and role policy |
whoami | OFFLINE | Acting identity, resolved role, permission summary, active environment, data-protection status |
Optional — file tickets from investigation bundles. Configure one provider with the INCIDENT_* variables (see Incident management & runbooks); the tool registers only when a provider is set.
| Tool | Type | Description |
|---|---|---|
create_incident_ticket | WRITE | Rebuild the investigate_incident bundle for a job and file it as a ServiceNow incident, Jira issue, or PagerDuty incident |
Optional — retrieval over your own runbooks and playbooks. Point DOCS_SOURCES at local .md/.txt files; the tool registers only when sources are set.
| Tool | Type | Description |
|---|---|---|
search_internal_docs | OFFLINE | Retrieve the most relevant excerpts from internal documentation, with file and heading attribution |
See docs/tools-reference.md for full input/output details.
Beyond tools, the server exposes the full MCP surface so clients can offer reusable playbooks and address mainframe data directly:
Prompts — guided, multi-step playbooks your client surfaces like slash commands:
| Prompt | Purpose |
|---|---|
triage_failed_job | Triage one failed job (or every failure in a window) end-to-end: investigate, check runbooks and internal docs, optionally file a ticket |
morning_batch_health_check | Overnight health check for the morning standup: system health, failures, abend trends, prediction, capacity and storage |
investigate_abend | Deep-dive one abend code: reference entry, internal docs, recent occurrences, remediation plan |
Resources — addressable read-only URIs (gated, masked, and audited exactly like the equivalent tools):
| URI | Returns |
|---|---|
mainframe://jobs/{jobId}/spool | Spool file (DD) inventory for a job |
mainframe://jobs/{jobId}/spool/{ddName} | Content of one spool DD |
mainframe://datasets/{dsn} | Member listing of a PDS/PDSE |
mainframe://datasets/{dsn}/members/{member} | Content of one member |
mainframe://reference/abend-codes | The built-in abend reference catalog |
Tool annotations — every tool advertises readOnlyHint, destructiveHint,
idempotentHint, and a human-readable title, derived from the same
write-tool registry the server enforces. Clients that confirm based on hints
(reactive confirmations, plan approval, etc.) agree with the server's own
gates: reads are readOnlyHint: true; submit_jcl, cancel_job,
issue_console_command, and the other destructive operations are flagged
destructiveHint: true.
Everything a security team asks for on day one is built into the release pipeline (see docs/deployment.md — Supply-chain assurance):
| Artifact | Where | Assurance |
|---|---|---|
| npm package | @notharshhaa/mainframe-mcp-server | Published with SLSA provenance (GitHub Actions OIDC) — npm audit signatures |
| Official image | ghcr.io/notharshhaa/mainframe-mcp-server (version / minor / SHA tags) | Non-root, signed with Sigstore keyless cosign, BuildKit provenance mode=max + SBOM attestations |
| SBOMs | GitHub release assets | SPDX and CycloneDX for both the package and the image |
| Checksums | sha256sums.txt on the release | Signed with cosign (sha256sums.txt.sig) |
| Helm chart | helm/mainframe-mcp-server/ | Non-root + read-only rootfs + dropped caps by default; policy file and SIEM sinks wired via values |
Verify the image before you run it:
cosign verify ghcr.io/notharshhaa/mainframe-mcp-server:3.0.0 \
--certificate-identity-regexp 'https://github.com/NotHarshhaa/mainframe-mcp-server/\.github/workflows/release\.yml@refs/tags/v' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
The docker-compose file and the Helm chart ship hardened defaults
(read_only, cap_drop: ALL, no-new-privileges, seccomp RuntimeDefault,
non-root uid 1000).
Security is enforced at the MCP server layer, in addition to RACF/z/OSMF permissions on the mainframe itself. Every control below is enabled through environment variables:
| Control | Env variable | Purpose |
|---|---|---|
| Read-only mode | SECURITY_READ_ONLY | Default true: submit_jcl, approve_write, and write operations are blocked unless you explicitly opt in |
| Tool allowlist | SECURITY_ALLOWED_TOOLS | Only permit specific tools (least privilege) |
| Tool blocklist | SECURITY_BLOCKED_TOOLS | Explicitly deny dangerous tools |
| Dataset boundaries | SECURITY_ALLOWED_DATASET_PATTERNS | Restrict dataset access by HLQ pattern |
| USS boundaries | SECURITY_ALLOWED_USS_PATHS | Restrict USS paths by prefix |
| Audit logging | SECURITY_AUDIT_LOGGING=true | Log every tool call (credentials redacted) |
| JCL size limit | SECURITY_MAX_JCL_BYTES | Cap inline JCL submit size |
| TLS verification | ZOSMF_REJECT_UNAUTHORIZED=true | Enforce certificate validation (default true) |
Four scale-up capabilities build on these controls — see docs/enterprise.md for the full guide and config/policy.example.yaml for a worked policy:
ZOSMF_ENVIRONMENTS; every tool takes
an environment argument; each environment carries its own credentials and
policy, e.g. readOnly: true on PROD.SECURITY_POLICY_FILE) maps
roles to tool allow/deny lists, dataset/USS globs, change-ticket rules, and
users to roles per environment; ${env:VAR} keeps credentials out of the
file; unknown users fail closed.npm run verify:audit.By default the server authenticates to z/OSMF with one configured credential. Enterprise deployments usually need RACF to see who asked, not "the MCP service account". Four mechanisms are built in:
PassTicket identity propagation — the strongest fit for shared deployments:
ZOSMF_USER_ID=PAYUSR # the end user RACF should see
ZOSMF_PASSTICKET_APP=ZOSMF # PTKTDATA application (RDEFINE PTKTDATA ZOSMF ...)
The server authenticates with the service credential, calls the z/OSMF
Generate PassTicket API for PAYUSR, and issues every z/OSMF call under a
PassTicket-authenticated session as that user. PassTickets are cached for
8 minutes and regenerated transparently; CICS/Db2 REST calls keep the service
identity. Requires the service account to be permitted to generate
PassTickets for the target user.
mTLS client certificates:
ZOSMF_CERT=/pki/client.pem
ZOSMF_CERT_KEY=/pki/client.key
Certificate authentication takes precedence over token/basic. Combine with a RACF IDID mapping (certificate → user) for certificate-based identity.
JWT / APIML tokens (SSO):
ZOSMF_TOKEN=$JWT
ZOSMF_TOKEN_TYPE=APIML # or JWT — both travel as Authorization: Bearer
ZOSMF_BASE_PATH=/api/v1 # APIML gateway prefix
ZOSMF_TOKEN_TYPE=LTPA2 (default) keeps classic z/OSMF session-token
behavior. Full OIDC/SSO flows run in your IdP/gateway — inject the issued JWT
via ZOSMF_TOKEN_FILE so a vault or credential-helper agent can refresh it
without touching the config file.
Zowe team config import — reuse existing Zowe connection settings:
ZOWE_TEAM_CONFIG=/root/.zowe/zowe.config.json
ZOSMF_PROFILE=lpar1.zosmf # default: defaults.zosmf
Any z/OSMF setting (host, port, base path, credentials, rejectUnauthorized)
not set via environment variables is filled from the profile. Values marked
@secure are honored when stored in the config file itself; secrets held by
an OS-keychain credential manager are not readable by this process and are
skipped. Environment variables always win.
submit_jcl is the only way an agent can mutate anything on z/OS — so it runs
through a governance pipeline before JES ever sees the job. Every layer is
independent; enable what your change process requires.
| Gate | Env variable | Default |
|---|---|---|
| Pre-flight JCL scan | SECURITY_JCL_SCAN | on |
| Strict scan mode (WARN blocks) | SECURITY_JCL_SCAN_STRICT | off |
| Blocked utilities | SECURITY_BLOCKED_PROGRAMS | ADRDSSU, ICKDSF, IEHINITT |
| Restricted job classes | SECURITY_BLOCKED_JOB_CLASSES | none |
| Change-ticket requirement | SECURITY_CHANGE_TICKET_PATTERN | off |
| Change window | SECURITY_WRITE_WINDOW / SECURITY_WRITE_DAYS / SECURITY_WRITE_WINDOW_TZ | off / every day / UTC |
| Human-in-the-loop approval | SECURITY_WRITE_APPROVAL | off |
The pre-flight scan blocks, with rule name and JCL line number:
IDCAMS DELETE in SYSIN instream data (IDCAMS ALTER is a WARN; blocks in strict mode)IEFBR14 steps that delete datasets via DISP=(,DELETE) / DISP=(MOD,DELETE)ADRDSSU, ICKDSF, IEHINITT), extendable with SECURITY_BLOCKED_PROGRAMSCLASS=Change tickets: with SECURITY_CHANGE_TICKET_PATTERN=CHG[0-9]{6}, every
submission must carry changeTicket: "CHG000123" or it is rejected with
[FORBIDDEN].
Change windows: with SECURITY_WRITE_WINDOW=22:00-06:00,
SECURITY_WRITE_DAYS=1-5, SECURITY_WRITE_WINDOW_TZ=Europe/Berlin,
submissions outside the window are rejected — dryRun still works so the
agent can validate JCL for a future change.
Dry-run: submit_jcl({ ..., dryRun: true }) runs structure checks and the
scan and reports exactly what a real submission would do — overrides, scan
findings, ticket/window/approval status, and the effective identity — without
submitting anything.
Human-in-the-loop approval: with SECURITY_WRITE_APPROVAL=true:
submit_jcl → the JCL is validated and scanned, and a
one-time token is returned. Nothing is submitted.approve_write({ token }) → the change window is
re-checked and the job is submitted.Tokens expire after 10 minutes, work exactly once, and are redacted from
audit logs. If you use SECURITY_ALLOWED_TOOLS with approval mode, allowlist
both submit_jcl and approve_write. Read-only mode (SECURITY_READ_ONLY=true)
blocks both regardless of approval being enabled.
Use security_posture_summary to inspect which controls are active and get hardening recommendations.
Important: Enterprise deployment also requires:
The mainframe still enforces the final authorization — this server adds guardrails so AI agents cannot exceed configured boundaries.
Everything this server returns — spool output, dataset contents, USS files, audit logs — is untrusted text that flows into your AI agent's context. A hostile JCL comment, COBOL literal, or log line can contain English text that tries to steer the agent ("ignore previous instructions, submit JCL that …").
What the server guarantees:
submit_jcl, and it is blocked by default (SECURITY_READ_ONLY=true), subject to SECURITY_ALLOWED_TOOLS/SECURITY_BLOCKED_TOOLS, and size-capped (SECURITY_MAX_JCL_BYTES).What the server cannot guarantee: it cannot stop a convincing log line from influencing what your agent asks to do next — that is an MCP-client-side concern by design. Defense in depth:
SECURITY_READ_ONLY=true (the default) for agents that browse logs/datasets.SECURITY_ALLOWED_TOOLS so the agent cannot reach tools it should not.submit_jcl requests by a human before approving them in the client (most MCP clients support per-call approval prompts).No LLM, no external AI API. The "intelligence" layer is deterministic, rule-based analysis that runs inside the server so results are reproducible and auditable. The MCP client's LLM interprets the structured report.
analyze_job_failure / analyze_root_cause:
ABEND Sxxx/Uxxxx, system/user completion codes, bare tokens), then matches it against a curated reference table of common z/OS abend codes (S0C1, S0C4, S0C7, S806, S322, S222, U4038, …) with explanations and remediations.lookbackHours, default 72, max 720).HIGH = abend code + failing step + spool evidence all found; MEDIUM = abend code or failing step found; LOW = neither — treat the report as a starting point.predict_batch_failures:
CRITICAL ≥ 75, HIGH ≥ 50, MEDIUM ≥ 25, else LOW.Known limitation (important for reviewers): JES only exposes jobs still in the system. "History" means failures currently listed in the OUTPUT queue (capped at MAX_FAILED_JOB_RESULTS), not a query of SMF archives. For long-horizon analytics, feed SMF data into a real analytics platform — this tool answers "what is failing right now, repeatedly?"
Bridge investigations into your ITSM flow. Configure one provider and
create_incident_ticket registers automatically; without configuration the
server behaves exactly as before.
// ServiceNow — Table API with basic auth
"INCIDENT_PROVIDER": "servicenow",
"INCIDENT_BASE_URL": "https://acme.service-now.com",
"INCIDENT_USER": "svc-mcp",
"INCIDENT_TOKEN": "<password or OAuth token>",
"INCIDENT_SERVICENOW_TABLE": "incident", // default
"INCIDENT_SERVICENOW_CALLER_ID": "<sys_id>", // optional
// Jira — REST API v3, basic auth with account email + API token
"INCIDENT_PROVIDER": "jira",
"INCIDENT_BASE_URL": "https://acme.atlassian.net",
"INCIDENT_USER": "[email protected]",
"INCIDENT_TOKEN": "<API token>",
"INCIDENT_JIRA_PROJECT": "OPS",
"INCIDENT_JIRA_ISSUE_TYPE": "Bug", // default
// PagerDuty — Events API v2 (routing-key auth, dedup per job)
"INCIDENT_PROVIDER": "pagerduty",
"INCIDENT_PAGERDUTY_ROUTING_KEY": "<routing key>"
Shared settings: INCIDENT_SEVERITY (default error), INCIDENT_LABELS
(comma-separated; applied to ServiceNow comments and Jira labels), and
INCIDENT_RUNBOOKS — a JSON map linking abend codes to your own runbooks:
"INCIDENT_RUNBOOKS": "{\"S0C7\": \"https://wiki.acme.com/runbooks/s0c7\", \"S2*\": \"https://wiki.acme.com/runbooks/jes-timeouts\", \"U*\": \"https://wiki.acme.com/runbooks/user-abends\"}"
Exact codes win over patterns; matches attach to lookup_abend_code output,
investigate_incident bundles, and every created ticket. Creating a ticket is
a governed write: blocked by SECURITY_READ_ONLY, subject to policy RBAC,
and audited like every other tool call. The ticket embeds the full incident
bundle — failure analysis, abend reference, runbook link, internal-doc
excerpts, spool inventory, and diagnostic excerpts.
Point DOCS_SOURCES at comma-separated local .md/.txt files or
directories (walked recursively; node_modules and dot-directories are
skipped):
"DOCS_SOURCES": "/opt/mcp-docs/runbooks,/opt/mcp-docs/playbooks",
"DOCS_MAX_RESULTS": "3", // excerpts per search / bundle
"DOCS_MAX_EXCERPT_CHARS": "1200",
"DOCS_REFRESH_SECONDS": "300" // re-index TTL (0 = index once at startup)
Retrieval is local TF-IDF — zero dependencies, no external embedding API,
and document contents never leave the host. Excerpts (with file and heading
attribution) attach automatically to incident bundles and abend lookups next
to the built-in reference, and search_internal_docs queries them directly.
Requirements: Node.js 18+, a reachable z/OSMF endpoint, and valid z/OS credentials (see z/OS prerequisites).
npx -y @notharshhaa/mainframe-mcp-server
When you add this server in your IDE (Cursor, VS Code, Claude Desktop, etc.), the
installer prompts for connection settings (driven by server.json). Those values
are stored in your MCP config file — not in a .env file.
Example MCP config — token auth, the recommended setup. Source the token from your vault or the IDE's secret storage rather than hardcoding it (see also config/mcp-client.example.json):
{
"mcpServers": {
"mainframe": {
"command": "npx",
"args": ["-y", "@notharshhaa/mainframe-mcp-server"],
"env": {
"ZOSMF_HOST": "your-zosmf-host.internal",
"ZOSMF_PORT": "443",
"ZOSMF_TOKEN": "your-zosmf-token",
"ZOSMF_TOKEN_TYPE": "LTPA2"
}
}
}
}
Basic auth (ZOSMF_USER + ZOSMF_PASSWORD) is also supported — if you use it, inject the values from a vault or secret manager instead of pasting them into the config file.
git clone https://github.com/NotHarshhaa/mainframe-mcp-server.git
cd mainframe-mcp-server
npm install
npm run build
Point your IDE at dist/index.js and set env in MCP config (copy from
config/mcp-client.example.json), or export variables in your shell before npm start.
| Variable | Required | Description |
|---|---|---|
ZOSMF_HOST | yes | z/OSMF hostname |
ZOSMF_TOKEN | yes* | Token auth — recommended over basic credentials |
ZOSMF_TOKEN_TYPE | no | Token type (default LTPA2) |
ZOSMF_USER / ZOSMF_PASSWORD | yes* | Basic auth — alternative to token auth |
ZOSMF_PORT | no | HTTPS port (default 443) |
ZOSMF_REJECT_UNAUTHORIZED | no | TLS verification (default true) |
* Provide either a token or user/password.
Full configuration reference: docs/configuration.md
Any MCP client that launches stdio servers works. Known-good setups:
| Client | Config location |
|---|---|
| Claude Desktop | claude_desktop_config.json → mcpServers |
| Cursor | ~/.cursor/mcp.json (or project .cursor/mcp.json) |
| VS Code (Copilot / MCP) | user or workspace MCP settings |
| Claude Code / other CLIs | standard mcpServers block |
Two MCP transports are supported, selected with MCP_TRANSPORT:
| Transport | How to enable | Use when |
|---|---|---|
| stdio (default) | Omit MCP_TRANSPORT | IDE / desktop MCP clients (Cursor, VS Code, Claude Desktop). Logs go to stderr only. |
| HTTP+SSE | MCP_TRANSPORT=sse | Containerized or shared deployments. Endpoints: GET /sse (open stream), POST /messages?sessionId=…, GET /health. Place it behind an auth proxy if exposed beyond localhost. |
Streamable HTTP is not supported yet. The MCP spec has moved from HTTP+SSE to Streamable HTTP, and this server still implements the legacy HTTP+SSE transport. Clients that only speak Streamable HTTP should launch the server over stdio (or front it with a transport shim). See docs/deployment.md.
Output is truncated, never paginated — every cap emits an explicit [truncated N of M lines] notice plus guidance to narrow filters.
| Limit | Env variable | Default | Applies to |
|---|---|---|---|
| Spool DD lines | MAX_JOB_OUTPUT_LINES | 5000 | One spool DD (get_job_output, JCL) |
| File lines | MAX_DATASET_READ_LINES | 2000 | One dataset / PDS member / USS file read |
| Diagnostic DDs | MAX_JES_SPOOL_FILES | 20 | Spool files fetched per failure analysis |
| Audit lines | MAX_AUDIT_LINES | 500 | RACF audit text parsed per query |
| Job list results | MAX_JOB_LIST_RESULTS | 500 | list_jobs before agent-side filters |
| Failed-job results | MAX_FAILED_JOB_RESULTS | 100 | find_failed_jobs, intelligence correlation |
| JCL payload | SECURITY_MAX_JCL_BYTES | 65536 | submit_jcl input size |
Timeouts & concurrency:
submit_jcl wait=true polls JES every 2 s for up to timeout seconds (default 30, max 300).[CONNECTION_ERROR] results the agent can retry.All tool errors come back as [ERROR_CODE]: message — codes are stable and listed in docs/tools-reference.md.
[CONNECTION_ERROR] — z/OSMF authentication failed (401/403)
Credentials rejected by z/OSMF. Check: user/password or token validity; ZOSMF_TOKEN_TYPE matches how the token was issued (LTPA2 vs JWT); the account is not revoked. An expired TSO password also surfaces here — log on via TSO once to reset it, then retry.
[CONNECTION_ERROR] — certificate / TLS errors
Self-signed or private-CA z/OSMF certificate. Preferred fix: trust the CA chain, e.g. NODE_EXTRA_CA_CERTS=/path/to/ca.pem. For throwaway dev only: ZOSMF_REJECT_UNAUTHORIZED=false (logs a warning; never in production).
[CONNECTION_ERROR] — unable to reach z/OSMF (ENOTFOUND / ECONNREFUSED / ETIMEDOUT)
Host/port wrong, VPN not connected, or you are behind an API mediation layer — set ZOSMF_BASE_PATH to your gateway prefix.
[CONFIG_ERROR] — CICS/Db2/RACF tools refuse to run
Those tools need optional setup: CMCI_CONTEXT, DB2_LOCATION, or RACF_AUDIT_USS_PATH/RACF_AUDIT_DATASET. See z/OS prerequisites. The error message names the exact variable.
[NOT_FOUND] — job/dataset not found
Job ids are JES-qualified (JOB01234, STC00012, TSU00123) and jobs vanish when purged from the OUTPUT queue. For datasets, check the HLQ and that the name is cataloged (migrated/HSM datasets may still resolve but show MIGRATED).
[FORBIDDEN] — tool blocked or write rejected
Read-only mode (the default) blocks submit_jcl and approve_write; an allowlist/blocklist rule matched; the pre-flight scan found a destructive construct; the change ticket was missing or malformed; or the submission is outside the change window. The error message names the specific gate — each one is an operator decision (env variables), not something the agent can turn off.
The client doesn't show any tools
Check stderr for the startup log (mainframe-mcp-server connected over stdio). Invalid config aborts with a variable-by-variable message. Set LOG_LEVEL=debug for per-call tracing. Requires Node 18+.
HTTP+SSE returns 400 Unknown or missing sessionId
The SSE session was restarted; reconnect GET /sse and use the fresh sessionId.
Why did a job fail?
User: Why did PAYJOB01 fail?
Agent: analyze_job_failure({ jobId: "JOB01234" })
Job: PAYJOB01 (JOB01234)
Status: ABEND S806
Step: STEP030 - LOADPGM
Reason: Program load failure — module PAYRPTX not found
Fix: Verify PAYRPTX is compiled and linked into the correct load library.
Failed jobs in the last 24 hours
User: Show me all failed jobs from the last 24 hours
Agent: find_failed_jobs({ hours: 24 })
Read a dataset member
User: Show me SYS1.PROCLIB(IKJEFT01)
Agent: read_dataset({ dsn: "SYS1.PROCLIB", member: "IKJEFT01" })
What does abend S0C7 mean?
User: What is abend S0C7?
Agent: lookup_abend_code({ code: "S0C7" })
Predict which batch jobs might fail next
User: Which batch jobs are at risk of failing?
Agent: predict_batch_failures({ hours: 168 })
MIT — see LICENSE
Not affiliated with IBM or the Open Mainframe Project. IBM, z/OS, CICS, Db2 and RACF are trademarks of IBM.