데이터베이스를 읽을 수 있는 에이전트는, 평소라면 SQL 편집기를 열어야 답하던 질문에 답합니다. “왜 화요일에 가입이 떨어졌지?” “pending 상태로 한 시간 넘게 멈춘 주문이 뭐지?” “events 테이블에 실제로 뭐가 들었지?” 조회 능력이 있으면 모델이 몇 초 만에 답하고, 없으면 추측합니다. 유용한 부분은 SQL이 아닙니다 — Claude Code와 Cursor는 둘 다 SQL을 잘 씁니다 — 자격 증명을 넘기지 않고 읽기를 실행할 길을 에이전트에게 주는 것입니다. 그 인계가 마찰의 전부이고, 이 글이 두 도구 모두에 대해 짚어 가는 지점입니다.
데이터베이스 연결 문자열을 에이전트에 붙여 넣는 것이 왜 되돌릴 수 없는 수인지(영어)는 따로 써 뒀습니다 — 자격 증명은 소지자 접근이라 읽기만이 아니라 쓰기와 삭제도 할 수 있고, 모델의 컨텍스트를 한 번 지나가면 공유를 되돌릴 수 없습니다. 안전 모델은 그 글을 보시고, 여기서는 그걸 정해진 사실로 두고 배선 작업을 끝냅니다. 짧게 말하면: 클라이언트가 자격 증명을 쥐고, 에이전트는 범위가 한정된, 기본 읽기 전용의 요청을 얻습니다.
준비물
- Termalin — 데스크톱 앱, Free 요금제면 충분합니다. 내장 MCP 서버를 갖춘 SSH·데이터베이스 클라이언트이고, 그 로컬 서버가 에이전트와 대화할 대상입니다.
- Termalin의 Data 클라이언트에 저장된 데이터베이스 연결 하나 이상 — Postgres, MySQL, SQLite, SQL Server, ClickHouse, MongoDB, Redis 등. 첫 실행에는 위험이 낮은 것을 고르세요: 분석 레플리카, 스테이징 데이터베이스, 사본 같은 것요.
- 앱과 같은 머신의 Claude Code 또는 Cursor. 데이터베이스 도구는 돌고 있는 데스크톱 앱을 구동하므로, 에이전트와 앱은 한 상자를 공유합니다.
세워 둘 기대 하나: Claude Code와 Cursor에서 데이터베이스 접근은 로컬 stdio MCP 서버를 거치므로, 에이전트가 잠금 해제된 데스크톱 앱과 같은 머신에 있어야 합니다. (호스팅 경로도 있습니다 — 호스팅 MCP 서버, 즉 claude.ai·ChatGPT·Claude Code·Cursor용 로그인이 붙은 termal.in/mcp나 API 키가 붙은 termal.in/api/v1/mcp는, 데스크톱 앱 없이도 등록된 서버의 데이터베이스를 서버 자신의 로컬 데이터베이스 신뢰를 써서 비밀번호 없이 조회할 수 있습니다. 데스크톱 앱 Data 클라이언트에 저장된 연결에는 로컬 서버가 맞습니다.)
1단계 — 에이전트 데이터 액세스 켜기
이건 기본적으로, 그리고 의도적으로 꺼져 있습니다. 설정 → 에이전트를 열고 “Let agents query your databases.”(에이전트가 내 데이터베이스를 조회하도록 허용)를 켜세요. 부제가 그 자세를 명확히 적어 둡니다: 기본적으로 꺼져 있고, 연결이 전체 액세스를 허용하지 않는 한 읽기 전용으로 유지됩니다. 켜기 전까지 모든 데이터베이스 도구는 database access for agents is off — enable it in Settings → Agent(에이전트의 데이터베이스 액세스가 꺼져 있습니다 — 설정 → 에이전트에서 켜세요)를 돌려주고, 그걸로 끝입니다.
더 나아가기 전에 몸에 새겨 둘 기본값 둘:
- 돌고 있는 앱 위에, 두 번째 옵트인입니다. 서버에 대한 에이전트 액세스를 켠다고 데이터베이스 액세스가 켜지지 않습니다 — 이건 자기만의 스위치입니다. 내가 결정하기 전에는 아무것도 노출되지 않습니다.
- 모든 연결이 에이전트에게는 읽기 전용입니다. 마스터 스위치가 켜져 있어도 각 쿼리는 실행 전에 검사됩니다. 쓰기는 그 특정 연결의 에이전트 정책을 전체 액세스로 올린 경우에만 통과합니다 — 전역이 아니라 연결별 선택입니다. 지금은 읽기 전용으로 두세요.
자격 증명 자체는 결코 움직이지 않습니다. 연결의 호스트·포트·비밀번호는 앱의 보관함에 남고, 에이전트는 그저 돌고 있는 앱에게 쿼리를 실행해 행을 돌려 달라고 요청할 뿐입니다. 에이전트가 — 또는 프롬프트 인젝션이 — 읽을 연결 문자열이 설정 파일에 없습니다.
2단계 — 로컬 MCP 서버 등록하기
Claude Code — 명령 하나:
claude mcp add termalin -- <path>/termalin-mcp
<path>를 termalin-mcp 바이너리가 있는 위치로 바꾸세요(앱이 위치를 짚어 줄 수 있습니다). Claude Code를 재시작하면 도구를 집어 올립니다.
Cursor — Cursor는 JSON 파일에서 MCP 서버를 읽습니다: 그 프로젝트에만 적용하려면 프로젝트 루트의 .cursor/mcp.json, 어디서나 서버를 쓰려면 ~/.cursor/mcp.json입니다. 로컬 stdio 서버인 경우 항목은 명령과 그 인자입니다:
{
"mcpServers": {
"termalin": {
"command": "<path>/termalin-mcp",
"args": []
}
}
}
전역 파일이 합리적인 선택입니다 — 데이터베이스 접근은 저장소마다의 관심사가 아니니까요. Cursor를 재시작하거나(또는 설정에서 MCP 목록을 새로고침하고) 서버가 running으로 표시되는지 확인하세요. 이건 Cursor SSH 안내와 Claude Code 안내(영어)가 쓰는 것과 같은 등록입니다 — 서버는 하나이고, 이제 SSH 도구와 나란히 데이터베이스 도구도 싣습니다.
3단계 — 도구들, 그리고 진짜 첫 작업
서버가 등록되고 스위치가 켜지면, 에이전트에 데이터베이스 도구 네 개가 보입니다:
data_list # your saved connections: id, name, engine, and whether the agent may write
data_tables # tables / collections / measurements for a connection, with row counts
data_schema # one table's columns: name, type, nullable, primary key
data_query # run a query in the connection's own language; default cap 200 rows
손으로 데이터베이스를 탐색하는 방식을 그대로 비춥니다: 연결된 것을 나열하고, 테이블을 보고, 테이블을 설명하고, 쿼리를 실행합니다. data_query는 연결이 말하는 언어라면 뭐든 말합니다 — 관계형 엔진과 ClickHouse에는 SQL, Neo4j에는 Cypher, Redis 명령, MongoDB에는 collection {filter} — 그리고 호출마다 올릴 수 있는 상한(maxRows)까지 행을 돌려줍니다. 기본값은 200이라, 에이전트가 실수로 백만 행을 자기 컨텍스트로 끌어오지 못합니다.
이제 데모 쿼리가 아니라 실제로 물을 법한 질문을 주세요:
대시보드를 보니 화요일에 가입이 떨어졌어. analytics 데이터베이스를 써서 무슨 일이 있었는지 알아내 줘.
에이전트가 도구를 순서대로 다루는 걸 지켜보세요:
data_list—analytics연결을 찾고, 엔진이 Postgres임을 보고, 에이전트에게 읽기 전용임을 알아챕니다.data_tables— 테이블을 나열하고,signups와signup_events를 발견하고, 어디를 조회할 가치가 있는지 알려고 행 수를 읽습니다.signups에 대한data_schema— 컬럼(created_at,source,status, …)을 익히고, 이제 날짜별·소스별로 쪼개는 법을 압니다.data_query—SELECT date_trunc('day', created_at) AS day, source, count(*) FROM signups WHERE created_at >= now() - interval '10 days' GROUP BY 1, 2 ORDER BY 1같은 걸 실행하고 행을 되읽습니다.
행이 이야기를 들려줍니다 — 어쩌면 한 source가 화요일에 0으로 떨어졌거나(끊긴 추천 링크), 어쩌면 총계는 유지됐는데 status = 'failed'가 치솟았을 수도(사업자 장애) 있습니다. 어느 쪽이든 에이전트는 추측이 아니라 실제 스키마에서 쿼리를 빚었고, 요청할 능력 이상의 것은 결코 쥐지 않았습니다. 결과가 200행 상한에서 잘리면, 그렇다고 말하고 더 밀어붙이는 대신 쿼리를 좁힙니다.
경계가 어디에 있나
짧게 짚습니다. 안전 글(영어)이 전부 다루니까요 — 하지만 의지하고 있는 기본값은:
- 기본 읽기 전용. SQL 계열 엔진에서는 읽기 동사만 통과합니다 —
SELECT,SHOW,DESCRIBE,EXPLAIN,WITH,PRAGMA. Redis에서는 읽기 명령만, MongoDB에서는$out/$merge가 붙은 애그리게이션이 차단되고, Neo4j에서는CREATE/MERGE/DELETE/SET/DROP이 차단됩니다. 혼란스럽거나 탈취된 모델은DROP이 아니라 읽기를 얻습니다. - 전역이 아니라 연결별. 분석 레플리카는 프로덕션 기본 DB와는 별개의 결정입니다. 하나를 전체 쓰기 액세스로 올려도 다른 쪽은 건드리지 않습니다.
- 토글 하나로 끄기, 그리고 앱이 자격 증명을 쥡니다 — 애초에 공유된 게 없으니, 꺼도 남는 사본도, 교체할 비밀번호도 없습니다.
민감한 것에는 둘 다 하세요: Data 연결을 읽기 레플리카나 최소 권한 데이터베이스 역할로 가리키게 하고 에이전트를 읽기 전용으로 두세요. 클라이언트 쪽 관문이 실수를 잡고, 데이터베이스 권한이 천장을 정합니다.
도구별 메모
- Cursor는 기본적으로 도구 호출 전에 묻습니다. 첫 세션들에서는 켜 두세요 — 모든
data_query를 실행 전에 보고, 에이전트가 제안하는 SQL을 읽을 수 있습니다. 자동 승인은 한 번에 하나씩 넓힐 편의입니다:data_list와data_schema는 먼저 통과시켜도 안전하고,data_query는 가장 오래 수동으로 둘 것입니다. - Claude Code는 각 도구 호출을 인자와 함께 인라인으로 드러내므로, 실행 전에 쿼리 텍스트가 트랜스크립트에 있습니다. 요약을 믿는 게 아니라 에이전트의 SQL을 읽는 것이고 — 모든 호출이 에이전트에게 귀속되니, 새벽 2시에 “그것이 읽은 것”과 “내가 읽은 것”을 구분할 수 있습니다.
Termalin이 들어맞는 자리
대부분의 “에이전트를 데이터베이스에 연결하기” 가이드는 설정 파일에 연결 문자열을 붙여 넣는 데서 끝나는데, 이는 에이전트에게 내 앱이 가진 것과 똑같은 쓰기·삭제 권한을 조용히 줍니다. Termalin의 Data 클라이언트는 그것을 뒤집습니다. 앱이 커스터디언이고, 에이전트는 돌고 있는 창을 통해 구동되는 범위 한정 도구 네 개를 얻으며, 그 능력 전체는 내가 달리 정하기 전까지 읽기 전용이고 스위치 하나로 꺼집니다. 이는 에이전트를 위한 SSH 액세스(영어)와 MCP 서버가 실제로 무엇인지(영어)에 적용하는 것과 같은 커스터디 발상입니다 — 데이터베이스는 그저 잘못된 쓰기가 행 단위로 측정되는 버전일 뿐이죠. 연결 하나로 시작해, 읽기 전용으로 두고, 무언가를 넓히기 전에 진짜 질문을 하나 던져 보세요.
Termalin은 내장 MCP 서버와 연결별 에이전트 정책을 갖춘 무료 크로스 플랫폼 SSH·데이터베이스 클라이언트입니다 — 다운로드하거나, 자격 증명을 안전하게 다루는 방식을 읽어 보세요.