프로토타입 · 미리 보기: 공식 레지스트리의 모든 서버를 담고 있으며 30분마다 동기화해요. 리뷰와 계정 기능은 다음 단계에서 열려요.
PopNx MCPAI를 쓰는 사람을 위한 MCP 서버 · 쉬운 말로 설명해요

otgate — OT policy gateway

제작자: alikup-ai버전 0.1.1i★ –i내 컴퓨터에서 실행
레지스트리 이름io.github.alikup-ai/otgate-opcua

설치

개요

제작자가 쓴 설명(영어 원문)

Gates an LLM agent's writes to an OPC UA server on ranges, rate of change and live interlocks.

PopNx MCP의 세 기둥

이 세 가지는 절대 하나의 점수로 합치지 않아요. 의견, 측정, 인기는 서로 다른 것이니까요.

할 수 있는 일

이 서버는 아직 쉬운 말로 된 요약을 쓰지 못했어요. 아래는 레지스트리에서 읽어 온 사실이에요.

  • 연결 방식: 내 컴퓨터에서 실행
  • 전송 방식: stdio
  • 카테고리: 검색 및 AI 기억

설치

쓰고 있는 AI 앱을 고른 다음 설정을 복사하세요.

설치하기 전에

  • 기본 점검: 1개 중 1개 통과
  • 내 컴퓨터에서 내 사용자 계정의 권한(파일, 네트워크, 앱)으로 실행돼요.
  • 직접 입력할 값: OTGATE_BACKEND, OTGATE_POLICY, OTGATE_AUDIT, OTGATE_SHADOW, OTGATE_RATE_HISTORY, OTGATE_OPCUA_ENDPOINT

필요한 것

  • PyPIPython의 uv 설치(uvx 명령어용)

어떤 앱을 쓰세요?

위에서 앱을 고르세요. 기억해 두었다가 다음부터는 버튼에 “…에 설치”라고 표시해요.

Claude Desktop → Settings → Developer → Edit Config를 열고 claude_desktop_config.json에 이 내용을 붙여 넣으세요

{
  "mcpServers": {
    "otgate-opcua": {
      "command": "uvx",
      "args": [
        "otgate"
      ],
      "env": {
        "OTGATE_BACKEND": "your-value",
        "OTGATE_POLICY": "your-value",
        "OTGATE_AUDIT": "your-value",
        "OTGATE_SHADOW": "your-value",
        "OTGATE_RATE_HISTORY": "your-value",
        "OTGATE_OPCUA_ENDPOINT": "your-value"
      }
    }
  }
}

터미널에서 이 명령어를 실행하세요

claude mcp add otgate-opcua --env OTGATE_BACKEND=your-value --env OTGATE_POLICY=your-value --env OTGATE_AUDIT=your-value --env OTGATE_SHADOW=your-value --env OTGATE_RATE_HISTORY=your-value --env OTGATE_OPCUA_ENDPOINT=your-value -- uvx otgate

실행하기 전에 빈 값을 채워 주세요.

Cursor에서 열기

또는 설정을 직접 복사하기

프로젝트의 .cursor/mcp.json 또는 ~/.cursor/mcp.json에 붙여 넣으세요

{
  "mcpServers": {
    "otgate-opcua": {
      "command": "uvx",
      "args": [
        "otgate"
      ],
      "env": {
        "OTGATE_BACKEND": "your-value",
        "OTGATE_POLICY": "your-value",
        "OTGATE_AUDIT": "your-value",
        "OTGATE_SHADOW": "your-value",
        "OTGATE_RATE_HISTORY": "your-value",
        "OTGATE_OPCUA_ENDPOINT": "your-value"
      }
    }
  }
}

브라우저가 앱을 열지 물어본 다음, 앱이 설정을 보여 주고 확인을 요청해요. 키 값은 비워 두니 직접 입력하세요.

VS Code에서 열기

또는 설정을 직접 복사하기

프로젝트의 .vscode/mcp.json에 붙여 넣으세요

{
  "servers": {
    "otgate-opcua": {
      "type": "stdio",
      "command": "uvx",
      "args": [
        "otgate"
      ],
      "env": {
        "OTGATE_BACKEND": "your-value",
        "OTGATE_POLICY": "your-value",
        "OTGATE_AUDIT": "your-value",
        "OTGATE_SHADOW": "your-value",
        "OTGATE_RATE_HISTORY": "your-value",
        "OTGATE_OPCUA_ENDPOINT": "your-value"
      }
    }
  }
}

브라우저가 앱을 열지 물어본 다음, 앱이 설정을 보여 주고 확인을 요청해요. 키 값은 비워 두니 직접 입력하세요.

이 서버는 내 컴퓨터에서 실행되는데, ChatGPT는 인터넷에 있는 서버에만 연결할 수 있어요. 다른 앱을 고르세요.

선택한 앱은 이 기기의 쿠키에만 저장돼요. 계정은 필요 없어요.

직접 입력할 값

  • OTGATE_BACKEND env
    Backend to gate: 'fake' for the bundled in-memory reactor simulator, 'asyncua' for a real OPC UA server. Start with 'fake' — it needs no plant and no extra dependency.
  • OTGATE_POLICY env
    Path to the policy YAML. Any tag not listed in it is denied by default.
  • OTGATE_AUDIT env
    Path to the append-only JSONL audit log. Every call, allowed or not, produces exactly one line.
  • OTGATE_SHADOW env
    Set to 1 to run in shadow mode: allowed writes are recorded as 'WOULD execute' and never reach the backend. Use this to watch an agent for a while before letting it touch anything.
  • OTGATE_RATE_HISTORY env
    Path to a JSONL file that keeps the rate-of-change time base across restarts. Without it a restart loses the time base, and rate limits fall back to a one-interval allowance.
  • OTGATE_OPCUA_ENDPOINT env
    OPC UA endpoint, e.g. opc.tcp://localhost:4840. Required when OTGATE_BACKEND=asyncua.

이 설정은 제작자의 레지스트리 정보로 만들었어요. README와 다르면 README를 따르세요.

할 수 있는 일

내 컴퓨터에서 실행돼요. 설치하면 AI 앱에 도구 목록이 나타나요.

기본 점검i

누구나 볼 수 있는 정보를 점검했고, 코드는 읽지 않았어요. 해당하지 않는 항목은 개수에서 뺐어요. · 2026년 11월 8일 점검

  • ✓ 통과

    제작자와 저장소 일치

    레지스트리 이름이 GitHub 계정 alikup-ai 기준으로 확인되었고, 이 계정이 저장소를 소유하고 있어요

  • … 아직 점검 안 함

    계속 관리되고 있음

    아직 GitHub에서 이 저장소를 읽어 오지 않았어요

  • … 아직 점검 안 함

    라이선스 있음

    아직 GitHub에서 이 저장소를 읽어 오지 않았어요

  • – 해당 없음

    엔드포인트 응답

    내 컴퓨터에서 실행되는 서버라 인터넷 엔드포인트가 없어요

  • – 해당 없음

    OAuth로 로그인

    내 컴퓨터에서 실행되며, 대신 로컬 설정을 사용해요

  • … 아직 점검 안 함

    도구 설명에 숨겨진 지시 없음

    내 컴퓨터에서 실행돼요. 도구 목록은 인터넷 엔드포인트가 있는 서버에서만 읽을 수 있어요

검색 및 AI 기억 카테고리의 다른 서버와 비교i

  • 이 카테고리의 다른 서버 5666개 중 0%보다 스타가 많아요
  • 이 카테고리의 다른 서버 5666개 중 100%보다 최근에 레지스트리에 공개됐어요
  • 기본 점검 결과가 이 카테고리의 다른 서버 5666개 중 100%와 같거나 더 좋아요

레지스트리에서 이 카테고리의 활성 서버 전체와 비교했어요. 스타는 게시자가 저장소를 소유한 경우에만 세요.

자주 묻는 질문

otgate — OT policy gateway, 안전한가요?

해당하는 기본 점검 1개 중 1개를 통과했어요. 코드는 읽지 않았어요. 키나 토큰을 넣기 전에 서버가 어떤 권한을 요구하는지 확인하고, 꼭 필요한 권한만 있는 키를 쓰세요.

어떤 키나 코드가 필요한가요?

레지스트리에 필수 키가 나와 있지 않아요. 다만 처음 쓸 때 로그인을 요구하는 서버도 있어요.

내 컴퓨터에서 실행되나요, 클라우드에서 실행되나요?

내 컴퓨터에서 실행돼요. AI 앱이 필요할 때 실행하고, 데이터는 제작자의 서버를 거치지 않아요(서버 자체가 온라인 서비스를 호출하는 경우는 제외).

아직 관리되고 있나요?

GitHub 저장소는 마지막으로 – 변경됐고, 최신 버전(0.1.1)은 오늘 레지스트리에 올라왔어요.

어떤 앱에서 쓸 수 있나요?

Claude Desktop, Claude Code, Cursor, VS Code처럼 MCP를 지원하는 앱에서 쓸 수 있어요. 내 컴퓨터에 Python (uv)도 있어야 해요.

대신 쓸 수 있는 건 뭐가 있나요?

같은 카테고리에는: Context7, Codebase Memory, Exa

대안

같은 카테고리에서 다른 제작자가 만든 서버예요. 스타 순으로 정렬했어요.

카드 보는 법:★ GitHub 스타i세 기둥: 리뷰 · 점검 · 사용 정도i업데이트 = 최신 버전을 레지스트리에 공개한 날i

Context7

제작자: upstash

Up-to-date docs for AI agents

컴퓨터 또는 클라우드★ 64,224MIT어제 업데이트
설치

Codebase Memory

제작자: DeusData

Codebase knowledge graph for AI agents — 162 languages, sub-ms queries, 99% fewer tokens.

내 컴퓨터에서 실행★ 48,148MIT21일 전 업데이트
설치

Exa

제작자: exa-labs

Connect AI agents to Exa for web search, content fetching, and multi-step research.

클라우드에서 실행★ 5,213MIT2개월 전 업데이트
설치

제작자의 README

README 열기

제작자의 저장소에서 쓰인 그대로 가져왔어요. PopNx MCP가 검토하거나 보증한 내용이 아니에요. HTML, 이미지, 스크립트는 제거했어요. 링크를 누르면 이 사이트를 벗어나요.

otgate

An OT-aware authorization gateway that sits between an LLM agent and an industrial OPC UA server, applying a process-aware access policy — value ranges, rate limits, interlocks — to every call the agent makes.

Русская версия →

[MCP client / agent] ---MCP---> [otgate] ---OPC UA---> [OPC UA server]

| [policy engine + audit + shadow mode]

The same decisions as terminal output ( python examples/demo.py )

otgate is itself an MCP server. The agent connects to it as if it were an ordinary OPC UA MCP; internally otgate holds a client to the real OPC UA server. Every call is transparent to the agent, and otgate intercepts each one to apply policy and record an audit line.

Why

  • Existing OPC UA MCP servers write to tags with no authorization layer — the agent has full, unbounded access.
  • Existing LLM guardrails (LlamaFirewall, NeMo Guardrails) work on text/prompts and do not understand process semantics — they know nothing about ranges, rates of change, or interlocks.
  • otgate closes exactly that gap: OT semantics + admission policy + audit.

It is not "you may write to this tag" but "you may write *within range X, no faster than Y over interval Z, and only while the emergency tag W is not active*".

Where this fits: OWASP ASI02

In the OWASP Top 10 for Agentic Applications, the risk otgate targets is ASI02 — Tool Misuse & Exploitation: an agent that stays inside its granted privileges but uses a legitimate tool unsafely — parameter pollution, excessive execution, or a call that is only dangerous given the current system state.

Identity and access layers (ASI03) answer *may this agent call this tool*. They do not look at what it writes, how fast, or under which conditions. otgate is the layer that does:

ASI02 sub-mechanismotgate
Parameter pollutionvalue_range — the argument itself is checked
Excessive execution / scalemax_rate over rate_interval, durable across restarts
Unsafe given system stateinterlocks — reads live guard tags before allowing
Unsafe composition (salami attack)cumulative_range — bounds total drift over a window, so slicing a forbidden move into legal steps does not work
Recursion / call stormsmax_calls over calls_interval
Unverifiable safety conditionfails closed — denies rather than guesses

Per-step limits judge one write; cumulative limits judge a *series*. Without the latter an agent walks around max_rate with many small legal steps:

step 1: 50.0 -> 52.5  (drift  +2.5)  ALLOW

step 2: 52.5 -> 55.0 (drift +5) ALLOW step 3: 55.0 -> 57.5 (drift +7.5) ALLOW step 4: 57.5 -> 60.0 (drift +10) ALLOW step 5: 60.0 -> 62.5 (drift +12.5) DENY cumulative drift too large: 62.5 is +12.5 from 50, allowed [-10, 10]

A full mapping against all ten OWASP agentic risks — including what otgate explicitly does not cover (tool-chain manipulation, goal hijacking, memory poisoning, rogue-agent detection) — is in [docs/threat-model.md](docs/threat-model.md).

Install

pip install -e .           # core: FakeBackend, engine, MCP server

pip install -e ".[dev]" # + pytest for the test suite pip install -e ".[opcua]" # + asyncua for a real OPC UA backend

Python 3.11+.

Policy example

A policy is a YAML list of per-tag rules. Any tag not listed is denied by default.

# examples/reactor_policy.yaml
  • tag: "ns=2;s=Reactor.TIC101.PV" # temperature, read-only access: read
  • tag: "ns=2;s=Reactor.TIC101.SP" # temperature setpoint access: write_with_approval # writes need human approval (ASK) value_range: [40, 80] # only within 40..80 degC cumulative_range: [-10, 10] # ... and no more than 10 degC total drift cumulative_interval: 3600 # from where it stood an hour ago max_rate: 5 # no faster than 5 degC ... rate_interval: 60 # ... per 60 seconds interlocks:
  • tag: "ns=2;s=Reactor.ESD" # blocked while emergency shutdown ... condition: "== true" # ... is active action: deny

Access levels: read, write, write_with_approval, deny.

Write check order (first failing check wins): tag-in-policy → access → value range → interlocks → rate of change → approval → allow.

Demo

python examples/demo.py
otgate demo — agent interacting with a reactor via the policy gateway

read temperature (PV) ALLOW read allowed -> 55.0 write setpoint = 60 degC (in range) ASK write requires human approval write setpoint = 200 degC (out of range) DENY value 200.0 is outside allowed range [40.0, 80.0] write setpoint = 60 degC while ESD active DENY interlock active: ns=2;s=Reactor.ESD == True (current ns=2;s=Reactor.ESD = True) write setpoint = 78 degC one second later DENY rate of change too high: |78.0 - 50.0| = 28 in 1s exceeds 5 per 60s

audit log


{"timestamp": "...", "action": "read", "node_id": "ns=2;s=Reactor.TIC101.PV", "value": null, "decision": "ALLOW", "reason": "read allowed", "shadow": false, "executed": true} {"timestamp": "...", "action": "write", "node_id": "ns=2;s=Reactor.TIC101.SP", "value": 60.0, "decision": "ASK", "reason": "write requires human approval", "shadow": false, "executed": false} {"timestamp": "...", "action": "write", "node_id": "ns=2;s=Reactor.TIC101.SP", "value": 200.0, "decision": "DENY", "reason": "value 200.0 is outside allowed range [40.0, 80.0]", "shadow": false, "executed": false} {"timestamp": "...", "action": "write", "node_id": "ns=2;s=Reactor.TIC101.SP", "value": 60.0, "decision": "DENY", "reason": "interlock active: ns=2;s=Reactor.ESD == True (current ns=2;s=Reactor.ESD = True)", "shadow": false, "executed": false} {"timestamp": "...", "action": "write", "node_id": "ns=2;s=Reactor.TIC101.SP", "value": 78.0, "decision": "DENY", "reason": "rate of change too high: |78.0 - 50.0| = 28 in 1s exceeds 5 per 60s", "shadow": false, "executed": false}

Run as an MCP server

Published to the official MCP Registry as `io.github.alikup-ai/otgate-opcua`, and to PyPI as `otgate`.

The registry name carries opcua because its search matches on the server name only and does not index

descriptions, so a bare otgate is findable only by someone who already knows the word.

otgate exposes: read_tag, write_tag, browse, get_audit_log, and the operator approval tools list_pending, approve, deny.

otgate                      # console script (stdio transport)

python -m otgate.server # equivalent

Configuration is via environment variables (so the backend switches without code changes):

VariableDefaultMeaning
OTGATE_BACKENDfakefake or asyncua
OTGATE_POLICYexamples/reactor_policy.yamlpolicy YAML path
OTGATE_AUDITaudit.jsonlaudit log path
OTGATE_SHADOW*(off)*1/true to enable shadow mode
OTGATE_RATE_HISTORY*(in-memory)*path to a JSONL file to make rate-of-change history survive restarts
OTGATE_OPCUA_ENDPOINT—required when backend is asyncua
OTGATE_AGENT_TOKEN—bearer token for the single-agent HTTP channel
OTGATE_AGENTS—path to agents.yaml for multi-agent mode (overrides single-agent)
OTGATE_OPERATOR_TOKEN—bearer token for the operator HTTP channel (must differ from every agent token)
OTGATE_HOST / OTGATE_AGENT_PORT / OTGATE_OPERATOR_PORT127.0.0.1 / 8770 / 8771HTTP bind host and ports

Example MCP client config (FakeBackend):

{

"mcpServers": { "otgate": { "command": "otgate", "env": { "OTGATE_BACKEND": "fake" } } } }

Related work: the layer underneath

otgate governs what the process allows right now — ranges, rate against the live value, interlocks, drift, approval. It does not try to be the access layer underneath that, and there is a good one: IndustriAgents/OPCUA-MCP answers *may this caller touch this node at all* — read-only by default, control profiles, allowlisted targets, pinned certificates, audited control calls.

The two questions are genuinely different. A write of 40 °C to an allowlisted target satisfies every access rule and is still wrong if the tag reads 22 °C and the ramp violates a thermal limit. Access control without process limits permits that write; process limits without access control have nothing to stand on.

A visible difference in the audit trail shows the split: their acceptance criteria require records to carry profile, tool, decision and target IDs without values, which is right for an access log. otgate records the value, because "200.0 refused, outside [40, 80]" is not a sentence you can write without it.

Connecting a real OPC UA server

No code changes — install the extra and point the config at your server:

pip install -e ".[opcua]"

export OTGATE_BACKEND=asyncua export OTGATE_OPCUA_ENDPOINT=opc.tcp://localhost:4840 otgate

The backend lives behind an abstract interface (otgate/backends/base.py) with two implementations — FakeBackend (in-memory simulator, no dependencies) and AsyncuaBackend (real OPC UA). asyncua is imported lazily, so the fake backend, the tests and the demo run without it.

Shadow mode

With OTGATE_SHADOW=1, a write that the engine allows is not executed on the backend — instead the audit records a "WOULD execute" line with executed: false. This lets you run an agent and see what it *would* do to the process without any real effect.

Human approval workflow

A write_with_approval tag returns ASK. Rather than silently drop the write, otgate parks it as a pending request with a TTL and hands the agent an approval id. A human then resolves it through the operator tools:

  • list_pending — show parked write requests.
  • approve — approve and execute, *after re-checking policy* against the current process state. If an interlock tripped or the value drifted out of range while the request waited, the approval is recorded but the write is blocked — an approval is intent, never a blind execute.
  • deny — reject; the write never runs.

Requests

앞부분만 보여 드려요. 나머지는 저장소에서 읽어 보세요

PopNx에게 묻기