Skip to main content
Glama
temporary111111

agent-mcp-gateway

Agent Gateway

ChatGPT Web(GPT-5.6 Sol)이 Streamable HTTP를 통한 Model Context Protocol(MCP) 로 로컬 머신에 결정적으로 액세스할 수 있게 해주는 프로덕션 지향 로컬 에이전트 게이트웨이입니다.

직접 모드가 기본 아키텍처입니다. 게이트웨이는 운영자가 승인한 디렉터리 안에서 실행되는 정밀하고 결정적인 MCP 도구(파일시스템, 검색, 프로세스, git)를 노출합니다. GPT-5.6 Sol이 유일한 추론 에이전트입니다. GPT-5.6 Sol이 계획 및 결정 루프를 소유하고 게이트웨이가 그 도구 호출을 실행합니다. 게이트웨이는 두 번째 LLM을 절대 호출하지 않습니다. 게이트웨이는 OpenCode 서버나 모델/프로바이더 구성 없이 작동합니다.

선택적 OpenCode 에이전트 모드(기본 비활성화)는 추가로 전체 작업을 로컬 OpenCode 에이전트에 위임하여 더 길고 자율적인 작업을 수행합니다.

ChatGPT Web (GPT-5.6 Sol)  <-- the reasoning agent
        │
        │  MCP over HTTPS (Streamable HTTP)
        ▼
Cloudflare Quick Tunnel
        │
        ▼
Agent Gateway  http://127.0.0.1:8000/mcp
        │
        ├── Direct mode (default): deterministic tools
        │       workspace_open / file_* / code_search / process_run / git_*
        │       (filesystem, search, process, git — no OpenCode, no LLM)
        │
        └── OpenCode agent mode (optional, ENABLE_OPENCODE_AGENT=true)
                agent_start_task / agent_status / agent_messages / agent_diff
                → OpenCode  http://127.0.0.1:4096  (localhost only)
        │
        ▼
Local system / repositories / tools

이 프로젝트는 이전 chatgpt-local-repo-mcp 프로토타입을 깨끗하고 테스트된 확장 가능한 기반으로 대체합니다. 해당 프로토타입의 복사본이 아닙니다.


게이트웨이가 필요한 이유

  • ChatGPT는 로컬호스트에 도달할 수 없습니다. 터널링된 MCP 엔드포인트가 검증된 브리지입니다.

  • 직접 결정적 도구가 두 번째 에이전트보다 낫습니다. 대부분의 파일, 검색, 프로세스, git 작업에서 게이트웨이의 프리미티브는 정확하고 빠르며 추가 모델이 필요 없습니다. GPT-5.6 Sol은 추론을 담당하고 게이트웨이는 머신을 담당합니다.

  • 확장할 수 있습니다. OpenCode(또는 향후 Codex/Claude Code 어댑터)는 자율 작업 위임을 위해 동일한 안정적인 MCP 인터페이스 뒤에서 활성화할 수 있습니다.

Related MCP server: chatgpt-local-coding-agent

신뢰 경계

경계

신뢰

ChatGPT ⇄ Cloudflare 터널

공개; HTTPS

Cloudflare 터널 ⇄ 게이트웨이

로컬 터널; MCP 전송 보안 + 선택적 베어러 토큰

게이트웨이 ⇄ OpenCode(활성화 시)

로컬호스트 전용(127.0.0.1:4096), 선택적 Basic Auth

게이트웨이 ⇄ 파일시스템

AGENT_ALLOWED_ROOTS에 명시적으로 나열된 디렉터리만

게이트웨이의 /mcp 엔드포인트가 유일한 공개 표면입니다. 외부 호출자는 다음을 할 수 없습니다:

  • 구성된 허용 루트 외부의 디렉터리에 액세스,

  • 제한 없는 셸 명령 실행(명령은 AGENT_ENABLE_COMMANDS를 통해 옵트인되며 시간 제한이 있음),

  • 운영자가 해당 모드를 활성화하지 않는 한 OpenCode에 작업 위임,

  • 자체 권한 요청을 자동 승인(구현된 적 없음),

  • AGENT_GATEWAY_TOKEN이 설정된 경우 베어러 토큰 없이 게이트웨이에 도달.

아키텍처

tools/  (MCP tools)            thin, callable by GPT-5.6 Sol
   │
   ├── tools/direct.py         deterministic primitives (default mode)
   │       workspace_open → workspace_tree / file_read / file_stat /
   │       file_find / code_search / file_write / file_replace /
   │       file_apply_patch / process_run / git_status / git_diff /
   │       git_log / git_show
   │
   ├── workspaces/             WorkspaceManager: opaque ws_ IDs bound to
   │                           allowed roots; every path re-validated
   │
   └── services/delegation.py  OpenCode mode: session lifecycle + registry
           │
           ▼
       executors/base.py       Executor interface (health, sessions, prompts,
           │                   status, messages, diffs, abort, permissions)
           ▼
       executors/opencode/     OpenCodeExecutor → OpenCodeClient → HTTP API

모든 모듈은 아래 계층에 의존하며 MCP 도구는 httpx를 직접 다루지 않습니다.

MCP 도구 — 직접 모드(기본, OpenCode 없음, 모델 없음)

직접 도구는 게이트웨이가 실행될 때마다 사용할 수 있습니다. workspace_open을 통해 열린 작업 공간 안에서만 작동합니다(디렉터리가 AGENT_ALLOWED_ROOTS 안에 있어야 함).

도구

읽기 전용

용도

workspace_open

아니요

디렉터리를 검증하고 불투명한 ws_... ID에 바인딩

workspace_tree

예

디렉터리 트리 목록(깊이/항목 상한)

file_read

예

파일 읽기(크기 상한 및 오프셋/제한 포함)

file_stat

예

파일 또는 디렉터리의 메타데이터

file_find

예

디렉터리 아래에서 이름/글로브로 파일 찾기

code_search

예

대소문자 구분 없는 콘텐츠 검색(라인 히트 포함)

file_write

아니요

파일 생성/교체

file_replace

아니요

정확한 이전 문자열 → 새 문자열 교체(전체 또는 N번째 발생)

file_apply_patch

아니요

컨텍스트 검증이 포함된 통합 diff 패치

process_run

아니요

작업 공간 안에서 명령 실행(opt-in, 제한적)

git_status

예

작업 트리 상태

git_diff

예

작업 트리 diff

git_log

예

커밋 기록

git_show

예

특정 리비전의 커밋/파일 콘텐츠

모든 직접 도구: 검증된 경로(절대 경로 없음, .. 없음, 심링크 이스케이프 없음), 읽기 크기 상한, 목록 항목 상한, 바인딩된 작업 공간 내의 엄격한 상대 경로 인자.

직접 모드 루프 (ChatGPT가 사용하는 방식)

workspace_open("C:\...\project")
   → ws_abc123
file_read(ws_abc123, "src/main.py")          → current content
file_apply_patch(ws_abc123, "src/main.py", <<<diff>>>)   → patch applied
process_run(ws_abc123, executable="pytest", args=["-q"], timeout_seconds=60) → verification
git_diff(ws_abc123)                           → review the change set

MCP 도구 — OpenCode 에이전트 모드(선택적)

ENABLE_OPENCODE_AGENT=true로만 활성화됩니다. 일반적인 위임 수명주기와 OpenCode 진단을 추가합니다:

도구

읽기 전용

백엔드 작업

gateway_health

예

게이트웨이 + 각 실행기의 상태 확인

agent_executors

예

구성된 실행기와 기능 목록

agent_start_task

아니요

세션 생성 + 비동기 prompt_async

agent_continue

아니요

기존 세션에 대한 비동기 후속 프롬프트

agent_status

예

세션 상태(바쁨 / 유휴 / 재시도) + 보류 중인 권한

agent_session

예

세션 메타데이터 + 변경 요약

agent_messages

예

텍스트 및 도구 호출 부분이 포함된 메시지 기록

agent_diff

예

에이전트가 생성한 파일별 diff

agent_abort

아니요

바쁜 세션 중단

agent_pending_permissions

예

결정을 기다리는 권한 요청 목록

agent_reply_permission

아니요

once / always / reject로 응답

opencode_health

예

상세 백엔드 상태/버전/url

opencode_agents

예

OpenCode 에이전트 목록

opencode_providers

예

모델 프로바이더 목록(비밀 제외)

위임 수명주기

agent_start_task(executor, task, directory)
      │
      ▼  returns session ID immediately (async dispatch)
agent_status(session_id)
      │
      ├── busy / retry   → wait and poll again
      │
      └── idle + completed
            ├── agent_messages(session_id)   → read what the agent did
            ├── agent_diff(session_id)        → review file changes
            ├── agent_continue(session_id, followup)  → keep going
            └── agent_abort(session_id)       → stop runaway work

장기 실행 에이전트 작업은 OpenCode의 비동기 프롬프트 API(POST /session/{id}/prompt_async)를 사용합니다. 게이트웨이는 즉시 응답하며 에이전트가 작업하는 동안 MCP 요청을 열어두지 않습니다. 완료는 세션이 유휴 상태 이고 마지막 어시스턴트 턴이 finish="stop"으로 끝난 경우에만 보고됩니다.

기존 세션에 대한 모든 작업은 세션의 실제 디렉터리가 여전히 AGENT_ALLOWED_ROOTS 안에 있는지 다시 확인합니다(실패 시 닫힘).

권한 워크플로우

게이트웨이는 절대 자동 승인하지 않습니다. 에이전트가 승인이 필요하면 권한 요청을 발생시키고, 감독자는 agent_status / agent_pending_permissions를 통해 이를 확인하며, 사람이 agent_reply_permission을 통해 결정합니다. 허용된 응답: once, always, reject.

보안 모델

  • 전송 인증: AGENT_GATEWAY_TOKEN이 설정되면 /mcp에 대한 모든 요청은 Authorization: Bearer <token>을 포함해야 합니다(상수 시간 비교). 유효한 토큰이 없는 요청은 401을 받습니다. MCP_HOST가 루프백이 아닌 주소(예: 0.0.0.0, LAN IP)인 경우 우발적인 공개 노출을 방지하기 위해 토큰도 필요합니다.

  • 디렉터리 보안: AGENT_ALLOWED_ROOTS는 세미콜론으로 구분된 절대 경로 목록입니다. 설정되지 않으면 모든 디렉터리가 거부됩니다(실패 시 닫힘). 각 후보는 정규화되고, 존재해야 하며(작업 루트 기준), 파일시스템 루트가 아니어야 하고, 허용된 루트 안에 있어야 합니다. 트래버설, 심링크 이스케이프, 형제 접두어 스푸핑(sample vs sample-evil)은 거부됩니다. 비교는 Windows에서 대소문자를 구분하지 않습니다.

  • 기본적으로 제한 없는 셸 없음: process_run은 AGENT_ENABLE_COMMANDS=true가 필요하며 타임아웃(기본 300초)을 적용합니다.

  • 제한된 I/O: 읽기 크기, 트리 항목, 검색 결과, 프로세스 출력이 제한됩니다. 거대한 페이로드는 무제한 스트리밍 대신 잘립니다.

  • OpenCode 모드는 opt-in입니다(ENABLE_OPENCODE_AGENT=true). 없으면 agent_* 도구가 등록되지 않고 백엔드에 연결되지 않습니다.

  • OpenCode 모드에서 권한은 절대 자동 승인되지 않습니다.

  • 네트워크: OpenCode는 로컬호스트 전용으로 유지됩니다. /mcp만 터널링됩니다. PUBLIC_MCP_HOST는 DNS 리바인딩 보호를 유지하면서 터널 호스트를 허용 목록에 추가합니다.

  • 비밀: 비밀번호와 Authorization 헤더는 절대 로그에 기록되지 않습니다. 구성 요약은 비밀번호를 마스킹합니다. 프로바이더 모델 목록은 키를 제외합니다.

설치

요구 사항: Python 3.11+(3.14에서 테스트됨), git. OpenCode CLI는 선택적 OpenCode 모드에만 필요합니다.

cd C:\Users\dev\Desktop\chatgpt-like\chatgpt-agent-gateway
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -e ".[dev]"

구성

.env.example을 .env로 복사하고 편집하거나 환경 변수를 직접 설정하세요:

$env:MCP_PORT = "8000"
$env:PUBLIC_MCP_HOST = "your-tunnel.trycloudflare.com"   # optional
$env:AGENT_ALLOWED_ROOTS = "C:\Users\dev\Desktop\sample-repo;C:\Users\dev\Desktop\projects"
$env:AGENT_GATEWAY_TOKEN = "generate-a-long-random-token"   # recommended
$env:AGENT_ENABLE_COMMANDS = "true"   # allow process_run
$env:LOG_LEVEL = "INFO"

변수

기본값

의미

MCP_HOST

127.0.0.1

게이트웨이 바인드 주소(로컬호스트 유지)

MCP_PORT

8000

게이트웨이 포트

PUBLIC_MCP_HOST

(없음)

MCP 전송 보안에 추가된 공개 호스트 이름(예: Cloudflare 터널)

AGENT_ALLOWED_ROOTS

(비어 있음)

세미콜론으로 구분된 허용 디렉터리; 비어 있으면 실패 시 닫힘

AGENT_GATEWAY_TOKEN

(비어 있음)

/mcp용 베어러 토큰; 비어 있으면 토큰 불필요(로컬호스트 전용)

AGENT_INSECURE_NO_TOKEN_OPT_OUT

false

PUBLIC_MCP_HOST가 설정된 경우 토큰 없이 실행하는 데 필요(위험)

AGENT_ENABLE_COMMANDS

false

process_run 활성화

AGENT_PROCESS_TIMEOUT_MAX

300

process_run이 걸릴 수 있는 최대 초

AGENT_MAX_READ_BYTES

200_000

file_read 출력 상한

AGENT_MAX_TREE_ENTRIES

1000

workspace_tree 항목 상한

AGENT_MAX_SEARCH_RESULTS

200

code_search 결과 상한

AGENT_MAX_PROCESS_OUTPUT_BYTES

100_000

process_run 출력 상한

ENABLE_OPENCODE_AGENT

false

선택적 OpenCode 에이전트 모드 활성화

OPENCODE_URL

http://127.0.0.1:4096

로컬 OpenCode 헤드리스 서버

OPENCODE_USERNAME / OPENCODE_PASSWORD

(비어 있음)

OpenCode용 선택적 Basic Auth

LOG_LEVEL

INFO

로깅 상세 수준

게이트웨이 실행

agent-gateway
# or
python -m agent_gateway.server

로컬 MCP 엔드포인트: http://127.0.0.1:8000/mcp

Cloudflare를 통한 노출

게이트웨이의 전송 보안은 DNS 리바인딩 보호를 활성화된 상태로 유지하며, PUBLIC_MCP_HOST에 설정한 호스트 이름과 localhost를 허용합니다. http://127.0.0.1:8000를 가리키는 Quick Tunnel을 시작하세요:

cloudflared tunnel --url http://127.0.0.1:8000

출력된 https://<id>.trycloudflare.com을 가져와 PUBLIC_MCP_HOST로 설정한 후 게이트웨이를 다시 시작하세요. AGENT_GATEWAY_TOKEN을 설정하세요 — 게이트웨이는 AGENT_INSECURE_NO_TOKEN_OPT_OUT=true를 명시적으로 설정하지 않는 한 토큰 없는 /mcp를 공개적으로 노출하지 않습니다. 터널이 작동하도록 보안 검사를 비활성화하지 않습니다. 대신 공개 호스트가 명시적으로 허용 목록에 추가됩니다.

OpenCode 실행(선택적 에이전트 모드)

opencode serve --port 4096 --hostname 127.0.0.1

확인: Invoke-RestMethod http://127.0.0.1:4096/global/health

테스트

pytest                     # default suite: direct mode only (150 passed, 9 skipped)
pytest tests/unit          # unit tests — no services needed
$env:ENABLE_OPENCODE_AGENT = "true"
pytest                     # full suite incl. OpenCode mode (158 passed, 1 skipped)

e2e 스위트는 임시 포트에서 실제 게이트웨이 프로세스를 시작하고, ChatGPT가 사용하는 정확한 프로토콜로 MCP-over-HTTP를 통해 이를 구동합니다. 두 가지 형태가 있습니다:

  • tests/e2e/test_direct_e2e.py — OpenCode도 모델도 없는 direct 모드): 토큰 없이 401, 도구 목록, workspace → read → patch → write → process → git diff, 그리고 권한 없는 디렉토리 거부. 기본 스위트에서 실행됩니다.

  • tests/e2e/test_opencode_e2e.py — OpenCode 모드(ENABLE_OPENCODE_AGENT=true 및 라이브 서버에서만 활성화): 읽기 전용 위임 작업(저장소가 바이트 단위로 수정되지 않았음을 검증)과 오류 사례만 포함한 전체 MCP 프로토콜 흐름이 포함됩니다.

리포지토리 구조

src/agent_gateway/
├── config.py            typed configuration (env-driven, validated)
├── errors.py            gateway error taxonomy
├── logging.py           redacted logging
├── security/
│   ├── paths.py         allowed-roots enforcement
│   └── auth.py          bearer-token middleware (constant-time compare)
├── workspaces/          WorkspaceManager: ws_ IDs, per-workspace validation
├── direct/              deterministic primitives (filesystem, search,
│   │                    process, git) shared by the direct tools
├── executors/
│   ├── base.py          Executor interface
│   └── opencode/        OpenCode client, models, errors, executor
├── services/delegation.py  OpenCode orchestration + session registry
├── tools/               MCP tool registration (direct, gateway, delegation,
│   │                    permissions, opencode)
└── server.py            MCP server assembly + entry point

향후 실행기 아키텍처

executors/base.py를 구현하고, executors/__init__.py에서 등록하고, tools/에 백엔드별 진단 도구를 추가하여 새 백엔드를 추가하세요. 일반 agent_* 도구와 위임 서비스는 변경이 필요하지 않습니다. 가짜 Codex/Claude 어댑터는 제공되지 않습니다.

제한 사항

  • OpenCode 세션 레지스트리는 인메모리입니다; 게이트웨이를 다시 시작하면 세션이 어떤 디렉토리에서 왔는지 잊어버립니다(OpenCode 자체는 세션을 ID로 유지합니다).

  • 직접 모드 workspace(ws_...)도 게이트웨이 재시작 시 만료됩니다; workspace_open으로 다시여세요.

  • file_apply_patch는 정확한 컨텍스트 일치를 요구하며, 퍼지 적용이 없습니다.

  • OpenCode API는 v1 OpenAPI 경로의 상위 집합으로 사용됩니다; 향후 백엔드 버전은 자체 /doc를 기준으로 다시 검증해야 합니다.

  • always 권한 회신은 프로토콜 수준에서 지원됩니다; 운영자는 모든 실행을 검증할 수 있도록 전역적으로 비활성화할 수 있습니다.

Related MCP Connectors

Related MCP Servers