cics-bridge-mcp 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cics_bridge_mcp-0.1.0/.github/dependabot.yml +8 -0
- cics_bridge_mcp-0.1.0/.github/workflows/ci.yml +12 -0
- cics_bridge_mcp-0.1.0/.github/workflows/codeql.yml +14 -0
- cics_bridge_mcp-0.1.0/.github/workflows/scorecard.yml +20 -0
- cics_bridge_mcp-0.1.0/.gitignore +5 -0
- cics_bridge_mcp-0.1.0/LICENSE +5 -0
- cics_bridge_mcp-0.1.0/PKG-INFO +24 -0
- cics_bridge_mcp-0.1.0/README.md +12 -0
- cics_bridge_mcp-0.1.0/SECURITY.md +10 -0
- cics_bridge_mcp-0.1.0/llms.txt +8 -0
- cics_bridge_mcp-0.1.0/pyproject.toml +16 -0
- cics_bridge_mcp-0.1.0/server.json +17 -0
- cics_bridge_mcp-0.1.0/server.py +99 -0
- cics_bridge_mcp-0.1.0/tests/__init__.py +0 -0
- cics_bridge_mcp-0.1.0/tests/test_server.py +9 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
name: CodeQL
|
|
2
|
+
on:
|
|
3
|
+
push: { branches: [main] }
|
|
4
|
+
pull_request: { branches: [main] }
|
|
5
|
+
schedule: [{ cron: "30 1 * * 0" }]
|
|
6
|
+
jobs:
|
|
7
|
+
analyze:
|
|
8
|
+
runs-on: ubuntu-latest
|
|
9
|
+
permissions: { security-events: write, actions: read, contents: read }
|
|
10
|
+
steps:
|
|
11
|
+
- uses: actions/checkout@v4
|
|
12
|
+
- uses: github/codeql-action/init@v3
|
|
13
|
+
with: { languages: python }
|
|
14
|
+
- uses: github/codeql-action/analyze@v3
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
name: Scorecard
|
|
2
|
+
on:
|
|
3
|
+
branch_protection_rule:
|
|
4
|
+
schedule: [{ cron: "20 7 * * 1" }]
|
|
5
|
+
push: { branches: [main] }
|
|
6
|
+
permissions: read-all
|
|
7
|
+
jobs:
|
|
8
|
+
analysis:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
permissions: { security-events: write, id-token: write, contents: read }
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v4
|
|
13
|
+
with: { persist-credentials: false }
|
|
14
|
+
- uses: ossf/scorecard-action@v2.4.0
|
|
15
|
+
with:
|
|
16
|
+
results_file: results.sarif
|
|
17
|
+
results_format: sarif
|
|
18
|
+
publish_results: false
|
|
19
|
+
- uses: github/codeql-action/upload-sarif@v3
|
|
20
|
+
with: { sarif_file: results.sarif }
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 CSOAI-ORG
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction... THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cics-bridge-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Bridge IBM CICS mainframe transactions to ONE OS — parse, map, govern (SOX / PCI-DSS / DORA). CSOAI Layer-0 legacy-bridge family.
|
|
5
|
+
Author: CSOAI-ORG
|
|
6
|
+
License: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
|
+
Requires-Dist: mcp>=1.28.0
|
|
10
|
+
Requires-Dist: pydantic>=2.0.0
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
|
|
13
|
+
# cics-bridge-mcp
|
|
14
|
+
|
|
15
|
+
mcp-name: io.github.CSOAI-ORG/cics-bridge-mcp
|
|
16
|
+
|
|
17
|
+
Part of the **CSOAI Layer-0 legacy-bridge family**. Bridge IBM CICS mainframe transactions to ONE OS — parse, map, govern (SOX / PCI-DSS / DORA).
|
|
18
|
+
|
|
19
|
+
**Tools:** parse_cics · identify_transactions · map_to_modern · govern_cics
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pip install -e .
|
|
23
|
+
python server.py
|
|
24
|
+
```
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# cics-bridge-mcp
|
|
2
|
+
|
|
3
|
+
mcp-name: io.github.CSOAI-ORG/cics-bridge-mcp
|
|
4
|
+
|
|
5
|
+
Part of the **CSOAI Layer-0 legacy-bridge family**. Bridge IBM CICS mainframe transactions to ONE OS — parse, map, govern (SOX / PCI-DSS / DORA).
|
|
6
|
+
|
|
7
|
+
**Tools:** parse_cics · identify_transactions · map_to_modern · govern_cics
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install -e .
|
|
11
|
+
python server.py
|
|
12
|
+
```
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Reporting a vulnerability
|
|
4
|
+
Email security@csoai.org (or open a private security advisory). We aim to acknowledge within 72 hours.
|
|
5
|
+
|
|
6
|
+
## Scope
|
|
7
|
+
This MCP parses untrusted legacy/protocol input. It performs read-only parsing + governance classification; it does not execute, write to, or control source systems. SCADA/MQTT/CICS control actions are flagged for human authorisation, never executed.
|
|
8
|
+
|
|
9
|
+
## Supported versions
|
|
10
|
+
The latest released version on the default branch.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "cics-bridge-mcp"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Bridge IBM CICS mainframe transactions to ONE OS — parse, map, govern (SOX / PCI-DSS / DORA). CSOAI Layer-0 legacy-bridge family."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.10"
|
|
7
|
+
license = {text = "MIT"}
|
|
8
|
+
authors = [{name = "CSOAI-ORG"}]
|
|
9
|
+
dependencies = ["mcp>=1.28.0", "pydantic>=2.0.0"]
|
|
10
|
+
[project.scripts]
|
|
11
|
+
cics-bridge-mcp = "server:main"
|
|
12
|
+
[build-system]
|
|
13
|
+
requires = ["hatchling"]
|
|
14
|
+
build-backend = "hatchling.build"
|
|
15
|
+
[tool.hatch.build.targets.wheel]
|
|
16
|
+
only-include = ["server.py"]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-07-09/server.schema.json",
|
|
3
|
+
"name": "io.github.CSOAI-ORG/cics-bridge-mcp",
|
|
4
|
+
"description": "Bridge IBM CICS mainframe transactions to ONE OS \u2014 parse, map, govern (SOX / PCI-DSS / DORA).",
|
|
5
|
+
"version": "0.1.0",
|
|
6
|
+
"packages": [
|
|
7
|
+
{
|
|
8
|
+
"identifier": "cics-bridge-mcp",
|
|
9
|
+
"version": "0.1.0",
|
|
10
|
+
"transport": {
|
|
11
|
+
"type": "stdio"
|
|
12
|
+
},
|
|
13
|
+
"registryType": "pypi",
|
|
14
|
+
"runtimeHint": "python"
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
CICS (mainframe transaction) Bridge MCP — CSOAI Layer-0 legacy-bridge family.
|
|
4
|
+
Parse CICS programs/transactions, map to modern services, govern. Sibling of cobol-bridge-mcp.
|
|
5
|
+
Tools: parse_cics · identify_transactions · map_to_modern · govern_cics
|
|
6
|
+
"""
|
|
7
|
+
from mcp.server.fastmcp import FastMCP
|
|
8
|
+
from pydantic import BaseModel, Field
|
|
9
|
+
from typing import List, Dict, Any
|
|
10
|
+
import re
|
|
11
|
+
|
|
12
|
+
mcp = FastMCP("CICS Bridge", instructions="Bridge IBM CICS mainframe transactions to ONE OS — parse, map, govern.")
|
|
13
|
+
|
|
14
|
+
# ── SIGIL: every governed action → one signed hash-chained hop (SIGIL_LOG unifies all layers) ──
|
|
15
|
+
import hashlib as _hl, time as _t, json as _j, os as _os
|
|
16
|
+
_SIGIL_LOG = _os.environ.get("SIGIL_LOG", _os.path.join(_os.path.dirname(_os.path.abspath(__file__)), "bridge_sigil.log"))
|
|
17
|
+
def _sigil(op, body):
|
|
18
|
+
try:
|
|
19
|
+
prev = ""
|
|
20
|
+
if _os.path.exists(_SIGIL_LOG):
|
|
21
|
+
with open(_SIGIL_LOG) as f:
|
|
22
|
+
ls = f.readlines()
|
|
23
|
+
if ls: prev = _j.loads(ls[-1]).get("digest", "")
|
|
24
|
+
ts = int(_t.time()); dg = _hl.sha256(f"{op}|{ts}|{prev[:8]}|{body}".encode()).hexdigest()[:16]
|
|
25
|
+
_os.makedirs(_os.path.dirname(_SIGIL_LOG), exist_ok=True)
|
|
26
|
+
with open(_SIGIL_LOG, "a") as f: f.write(_j.dumps({"ts": ts, "op": op, "body": body, "prev_digest": prev, "digest": dg}) + "\n")
|
|
27
|
+
return dg
|
|
28
|
+
except Exception: return ""
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class CICSParsed(BaseModel):
|
|
32
|
+
exec_commands: List[str] = Field(default_factory=list)
|
|
33
|
+
transactions: List[str] = Field(default_factory=list)
|
|
34
|
+
programs_called: List[str] = Field(default_factory=list)
|
|
35
|
+
uses_commarea: bool = False
|
|
36
|
+
line_count: int = 0
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class Governance(BaseModel):
|
|
40
|
+
risk_flags: List[str] = Field(default_factory=list)
|
|
41
|
+
frameworks: List[str] = Field(default_factory=list)
|
|
42
|
+
attestable: bool = True
|
|
43
|
+
note: str = ""
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@mcp.tool()
|
|
47
|
+
def parse_cics(source_code: str) -> CICSParsed:
|
|
48
|
+
"""Parse a CICS program: EXEC CICS commands, transaction IDs, LINK/XCTL targets, COMMAREA use."""
|
|
49
|
+
s = source_code
|
|
50
|
+
cmds = re.findall(r"EXEC\s+CICS\s+([A-Z]+)", s, re.I)
|
|
51
|
+
txns = re.findall(r"\bTRANSID\s*\(\s*['\"]?(\w+)", s, re.I) + re.findall(r"\bSTART\s+TRANSID\s*\(\s*['\"]?(\w+)", s, re.I)
|
|
52
|
+
progs = re.findall(r"(?:LINK|XCTL)\s+PROGRAM\s*\(\s*['\"]?(\w+)", s, re.I)
|
|
53
|
+
return CICSParsed(
|
|
54
|
+
exec_commands=sorted(set(c.upper() for c in cmds))[:30],
|
|
55
|
+
transactions=sorted(set(txns))[:30],
|
|
56
|
+
programs_called=sorted(set(progs))[:30],
|
|
57
|
+
uses_commarea=bool(re.search(r"COMMAREA", s, re.I)),
|
|
58
|
+
line_count=len(s.splitlines()),
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@mcp.tool()
|
|
63
|
+
def identify_transactions(source_code: str) -> Dict[str, Any]:
|
|
64
|
+
"""List the CICS transactions + programs this code drives (migration scope)."""
|
|
65
|
+
p = parse_cics(source_code)
|
|
66
|
+
return {"transactions": p.transactions, "programs": p.programs_called,
|
|
67
|
+
"commands": p.exec_commands, "note": "Each EXEC CICS verb maps to a modern transaction-context call."}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@mcp.tool()
|
|
71
|
+
def map_to_modern(source_code: str) -> Dict[str, Any]:
|
|
72
|
+
"""Map CICS program shape to a modern transactional service skeleton."""
|
|
73
|
+
p = parse_cics(source_code)
|
|
74
|
+
return {"source": "IBM CICS", "target": "modern transactional service",
|
|
75
|
+
"endpoints": p.transactions or ["main"], "calls": p.programs_called,
|
|
76
|
+
"state": "COMMAREA -> request/session context" if p.uses_commarea else "stateless"}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
@mcp.tool()
|
|
80
|
+
def govern_cics(source_code: str) -> Governance:
|
|
81
|
+
"""Governance: transaction integrity + access surface (attestable for CSOAI)."""
|
|
82
|
+
_sigil("G", "cics|govern_cics")
|
|
83
|
+
p = parse_cics(source_code)
|
|
84
|
+
flags = []
|
|
85
|
+
if any(c in p.exec_commands for c in ("SEND", "RECEIVE")) and "RETURN" not in p.exec_commands:
|
|
86
|
+
flags.append("Terminal I/O without explicit RETURN — review transaction boundaries")
|
|
87
|
+
if not p.uses_commarea and p.programs_called:
|
|
88
|
+
flags.append("Inter-program calls without COMMAREA — verify state handling on migration")
|
|
89
|
+
return Governance(risk_flags=flags,
|
|
90
|
+
frameworks=["IBM CICS TS", "SOX (ITGC)", "PCI-DSS (if cardholder)", "DORA"],
|
|
91
|
+
note="CSOAI governs the bridge: transaction lineage attestable on the ledger.")
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def main():
|
|
95
|
+
mcp.run()
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
if __name__ == "__main__":
|
|
99
|
+
main()
|
|
File without changes
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import sys,os
|
|
2
|
+
sys.path.insert(0,os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
3
|
+
import server
|
|
4
|
+
|
|
5
|
+
SRC="EXEC CICS SEND MAP('M1') END-EXEC. EXEC CICS LINK PROGRAM('PROG2') COMMAREA(WS) END-EXEC. EXEC CICS RETURN TRANSID('TR01') END-EXEC."
|
|
6
|
+
def test_parse():
|
|
7
|
+
p=server.parse_cics(SRC); assert "SEND" in p.exec_commands; assert p.uses_commarea; assert "PROG2" in p.programs_called
|
|
8
|
+
def test_govern():
|
|
9
|
+
assert any("SOX" in f for f in server.govern_cics(SRC).frameworks)
|