# FutureInfra service guide for AI agents ## Users here usually know nothing about infrastructure Most FutureInfra users are "vibe coders": they know what they want to build or automate, but not what a server, container, database or CDN is, and they cannot pick a size. - Do not ask the user to choose products or sizes. Listen to the goal, pick ONE option yourself, and confirm it in plain Korean as: what you will use — one-line reason — expected monthly cost. Build after they agree. - Start with the smallest, cheapest option; it can be resized later. - Avoid jargon. If you must use a term, explain it in brackets (e.g. 데이터베이스(정보를 저장하는 곳)). - When done, report: the URL, the expected monthly cost, and what to do next — in plain words. How to choose: - One website / web app → an **app** (apps.*): 5,500 KRW/month, HTTPS address included, no server to manage. Needs to store sign-ups, bookings, etc. → add the database sidecar: 7,700 KRW/month total. - Something that must run on a schedule or all the time (automation, bot, crawler), needs custom software, or 3+ apps → a **server** (cloud.*): - Nano (1 vCPU · RAM 1GB · disk 30GB) — 9,000 KRW/month - Small (2 vCPU · RAM 2GB · disk 40GB) — 14,000 KRW/month - Medium (4 vCPU · RAM 4GB · disk 100GB) — 32,000 KRW/month - Large (4 vCPU · RAM 8GB · disk 160GB) — 66,000 KRW/month - AI chat / images / video / speech → API only (llm, gen, ai), pay per use, no server. - A free *.futureinfra.app address is issued automatically. Domain purchases need human approval. - The UTM firewall add-on (150,000 KRW/month) is only for explicit corporate security requirements. Common goals (Korean prompt a user can paste into Claude Code): - 홈페이지·랜딩 페이지 → 앱 1개 · 월 5,500원 `퓨처인프라로 [가게 소개 홈페이지]를 만들어서 인터넷에 올려 줘. 필요한 건 알아서 골라 만들고, 다 되면 접속 주소와 한 달 예상 요금을 쉬운 말로 알려 줘.` - 예약·신청·회원가입 받는 사이트 → 앱 1개 + 데이터베이스 · 월 7,700원 `퓨처인프라로 [미용실 예약을 받는 사이트]를 만들어 줘. 예약 정보는 데이터베이스에 저장하고, 관리자가 예약 목록을 볼 수 있게 해 줘. 다 되면 주소·관리자 로그인 방법·한 달 예상 요금을 알려 줘.` - 챗봇·AI 기능 붙이기 → 앱 1개 + AI(쓴 만큼) · 월 5,500원부터 `퓨처인프라로 [우리 가게 자주 묻는 질문에 답하는 챗봇]을 만들어 줘. AI 모델은 퓨처인프라 AI 라우터를 쓰고, 답할 내용은 세컨브레인에 저장해 둬. 다 되면 주소와 한 달 예상 요금(AI 사용료 포함)을 알려 줘.` - 매일 자동으로 모아서 알려 주기 → 작은 서버(Nano) · 월 9,000원 `퓨처인프라로 [매일 아침 8시에 업계 뉴스를 모아 요약해서 내 메일로 보내는 자동화]를 만들어 줘. 가장 싼 사양으로 시작하고, 다 되면 언제 돌아가는지·결과를 어디서 보는지·한 달 예상 요금을 알려 줘.` - 가격·리뷰 모니터링 → 작은 서버(Nano) 또는 스크래핑 · 월 9,000원부터 `퓨처인프라로 [경쟁사 상품 5개의 가격을 매일 확인해서 바뀌면 알려 주는 모니터링]을 만들어 줘. 공개된 정보만 모으고, 결과는 엑셀로 받을 수 있게 해 줘. 다 되면 한 달 예상 요금을 알려 줘.` - AI 이미지·영상·음성 만들기 → 쓴 만큼(장·초·글자 단위) `퓨처인프라 AI 로 [우리 상품 소개 이미지 3장과 30초 한국어 내레이션]을 만들어 줘. 만들기 전에 예상 비용부터 알려 줘.` ## Connecting — follow this so the user never gets stuck The user is not technical. They should only ever (a) click a login/approve button in a browser, or (b) paste ONE line you give them into a terminal. Tell them exactly what to click or type, one step at a time, in plain Korean. 0. Already connected? If you have FutureInfra tools, call `account.me` and say the organisation name in one line. If that is the organisation the user means, skip the rest. If they want a DIFFERENT organisation, run A anyway — they pick the organisation on the 허용 page — and register it under altMcpName so both connections stay. Speak Korean to the user at every step, including while you wait. No account yet? Nothing to ask first — the page in A lets the user sign in OR sign up, then press 허용. If you can open a browser, do it for them — every page below is a plain URL. Use your browser tool, or run (ALWAYS quote the URL — it contains `&`, which a shell otherwise cuts off): Windows — prefer PowerShell `Start-Process ""` (cmd: `start "" ""`, Git Bash: `cmd //c start "" ""`), macOS `open ""`, Linux `xdg-open ""`. Then the user only logs in and presses 허용/승인. Never type the user's password, 2FA code or card number, and never press approve/pay for them — those stay with the person. A. One-click connect (preferred — works inside any app that can run a command or open a URL) 1. POST https://futureinfra.ai/v1/public/connect/start with JSON {"client":"Claude Code"} — no secret involved. HTTP 201 returns: deviceCode (keep it to yourself), userCode (e.g. ABCD-EFGH), verificationUrl, expiresIn (600 s), interval (3 s), tellUser (a ready Korean sentence for the user) and next. 2. Open verificationUrl in the user's browser yourself (see above); if you cannot, show the link. Then show tellUser, e.g. "브라우저에서 퓨처인프라에 로그인하고(계정이 없으면 가입), 코드 가 맞는지 확인한 뒤 [허용]을 눌러 주세요". 3. POST https://futureinfra.ai/v1/public/connect/poll {"deviceCode":"..."} every `interval` seconds. Responses: - pending — keep waiting. It also has `viewed` (true once the user reached the 허용 page) and `expiresIn` (seconds left). If `viewed` is still false after ~60 s, nobody has reached the 허용 page yet (browser did not open, or stuck at login). Open the same verificationUrl once more with another method (e.g. PowerShell Start-Process), show the link, and ask what they see if you can talk to them. Keep polling the SAME deviceCode — only expiry needs a new one. - slow_down (HTTP 200) — you polled too fast; wait `interval` + 2 seconds. - denied (HTTP 200) — the user pressed 거절. Ask if it was a mistake; if they want to retry, go back to step 1. - expired (HTTP 410, with a Korean message) — 10 minutes passed. Do NOT reuse the deviceCode; go back to step 1. 4. approved (HTTP 200, status "approved") — sent ONCE. Fields: apiKey, org.name, scopes, mcpUrl, mcpName, altMcpName, claudeCommand, next. The key gets the console's default permissions (servers, apps, domains, AI, git, storage, billing read …; never approvals or member management) and no spending cap unless the user chose one; it may carry an expiry the user picked. - Tell the user the organisation name from org.name in one line (no need to call /v1/me). - Run `claude mcp list` first. If a server named futureinfra already exists, do NOT remove it (it may be another organisation) — replace the name in claudeCommand with altMcpName (futureinfra-). If that name exists too, add -2, -3 … - Run claudeCommand. Registering stores the key in the MCP client's own settings on this computer — that is the ONE place a key is meant to live, and the command will appear in your local tool log. Do not put it anywhere else (repo, notes, memory, chat) and never repeat the key or the command in your messages to the user. If running it is blocked, ask the user to allow that one permission prompt; if that is impossible, use B instead. - Ask the user to open a new session (or restart the app) so the FutureInfra tools load. The connection is saved. account.me only works in that new session — in the current one, org.name from this response is your confirmation. - Lost the response before registering? The key cannot be fetched again. Tell the user to revoke "AI 연결 · " in https://futureinfra.ai/console/?screen=api-keys and run A again. B. Claude Code — browser login without a key 1. Run it yourself: `claude mcp add --transport http --scope user futureinfra https://futureinfra.ai/v1/mcp` It contains no secret, so auto mode does not block it. If the name futureinfra already exists, do not touch it — use `futureinfra-2` (then -3, -4 … if taken) as the name instead. A gives you altMcpName for this. 2. The login must be done by the user: - Claude Code (terminal or the Claude desktop app's Code tab): tell them — "채팅 입력창에 /mcp 입력 → 목록에서 futureinfra 선택 → 로그인(Authenticate) → 열린 브라우저에서 퓨처인프라 로그인 → 허용 → 끝나면 '다 했어'라고 말해 주세요". In the desktop app the same login is also under the app's Connectors menu (futureinfra → 로그인). Do not claim `/mcp` is unavailable — it works in the app. - Only if neither works (some IDE extensions): "터미널(윈도우: PowerShell, 맥: 터미널)에서 claude 입력 → /mcp → futureinfra → 로그인 → 끝나면 /exit". The login is stored on this computer for the user, so a new session can use it. If it still says "Needs authentication", use A or C. - After they say it is done, check again (call a FutureInfra tool or `claude mcp list`). 401 means the login is not finished yet — repeat the steps, do not guess. 3. Confirm with `account.me` and say the organisation name in one line. C. API key — any MCP client 1. Open https://futureinfra.ai/console/?screen=api-keys for them (or send the link) → "+ 키 발급" → choose a preset → 발급. 2. The console shows a ready-made Claude Code command. The USER pastes it into their own terminal and presses Enter. Never ask the user to paste the key into chat. If they already did: you may run `claude mcp add ... --header "Authorization: Bearer "` (it only writes the local MCP settings), suggest revoking that key later, and never send the key to any URL yourself (curl, fetch) — auto-mode safety checks block that as secret exfiltration. 3. Ask them to open a new session, then confirm with `account.me`. When Claude Code blocks one of your commands (auto mode, permission prompt): - Do not retry, rephrase, or work around it. Show the exact command in a code block and say "이 한 줄을 터미널에 붙여 넣고 엔터를 눌러 주세요", or, if a permission prompt is on screen, ask them to press 허용 (allow) for that one command. - Exception: never show a command that contains a key. For those, ask for the permission prompt, or switch to B (no key). - Never suggest turning off safety checks or switching to a bypass/"권한 무시" mode. When FutureInfra says no: - 401 → not logged in or wrong key → connect again with A. - 403 `insufficient_scope` → the key lacks that permission. Tell them: 콘솔 › API 키 → 그 키 → 권한에 추가, or connect again with B (browser login carries the user's own role). - 403 `human_session_required` / 202 `pending_approval` → show the `userAction.consoleUrl` / `action_required.url` link as-is and say "이 링크를 열어 '승인'을 눌러 주세요". The server runs the action after approval — do not call it again. - Not enough balance → https://futureinfra.ai/console/?screen=billing → "충전". Purchases and payments are always done by the user in the browser. - Only the organisation's owner/admin can issue keys, approve, and pay. If the user is a plain member, tell them to ask their admin. ## MCP tools (247) Generated from the server's registry. If a tool is listed here it exists; if it is not, it does not. Tools marked *(human approval required)* return a pending approval rather than executing, and no scope can approve it. ### llm - `llm.chat` — Send an OpenAI-compatible chat completion request. - `ai.voices` — AI 보이스 목록 — 음성 합성(TTS)에 쓸 수 있는 한국어 목소리(모델·voice id·이름·성별·나이대·톤·용도·미리듣기 주소·1,000자당 원). 조건(q·gender·language·mood·use·emotion·free·maxFirstSoundMs·sort)으로 골라 준다. ### cloud - `cloud.list_instances` — List this tenant's cloud instances and their current state. `status` is the desired state; `powerState` (running|stopped|paused|unknown) + `powerReason` is the - `cloud.catalog` — 가상서버를 만들 때 고를 수 있는 것들 — blueprint(OS 이미지) 와 plan(사양) 목록. **cloud.create_instance 전에 반드시 여기서 id 를 얻어라.** - `cloud.get_instance` — 가상서버 한 대의 상세 — 상태·사양·내부 IP·공인 IP·도메인. 실제 전원은 powerState·powerReason·powerCheckedAt 으로 본다(status 는 원하는 상태). powerReason=suspended_insufficient_credits 면 잔액 부족으로 - `cloud.power` — 가상서버 전원 조작 — start | stop | reboot. stop 은 서비스가 즉시 끊긴다. - `cloud.list_hostnames` — 이 가상서버에 붙은 호스트네임(공개 주소) 목록. - `cloud.list_snapshots` — 가상서버의 스냅샷 목록. - `cloud.create_snapshot` — 스냅샷을 찍는다. **되돌리기 어려운 작업(패키지 교체·설정 덮어쓰기) 전에 먼저 해라.** - `cloud.rollback_snapshot` *(human approval required)* — 스냅샷 시점으로 되돌린다. ★현재 디스크 상태를 버린다 — 사람 승인이 필요하다. - `cloud.delete_snapshot` — 스냅샷을 지운다. 디스크 상태는 그대로고 되돌릴 지점만 없어진다. - `cloud.list_backups` — 가상서버의 백업 목록(스냅샷과 다르다 — 백업은 별도 저장소에 있다). - `cloud.create_backup` — 지금 백업을 뜬다(자동 백업은 새벽 2시). **위험한 작업 전에 스냅샷 대신 이걸 쓰면** 디스크가 통째로 망가져도 살아남는다 — 백업은 다른 장비에 있다. 몇 분 걸리고, 끝나면 cloud.list_backups 에 나타난다. - `cloud.restore_backup` *(human approval required)* — 백업으로 복원한다. ★현재 상태를 덮어쓴다 — 사람 승인이 필요하다. volid 는 cloud.list_backups 에서 얻는다. - `cloud.publish` — 가상서버의 포트를 호스트네임으로 공개한다(우리 프록시 경유, TLS 포함). 공인 IP 없이도 인터넷에서 닿는다. - `cloud.unpublish` — 공개를 내린다. 가상서버는 그대로 돌고 바깥에서만 안 닿는다. - `cloud.list_images` — 저장해 둔 내 이미지 목록. cloud.create_instance 의 blueprint 로 쓸 수 있다. - `cloud.save_as_image` — 지금 가상서버를 이미지로 굳힌다. 같은 구성을 반복해 세울 때 쓴다. - `cloud.save_as_sale_image` — 판매용(앱마켓) 이미지를 만든다. 원본 서버는 그대로 두고, 복제본에서 비밀 검사 → 청소(판매자 SSH 키·개인키·셸 기록·로그·machine-id·호스트 키·cloud-init) 뒤 이미지로 굳힌다. 1~3분 걸리며 진행은 cloud.list_images 의 status(creati - `cloud.delete_image` — 저장한 이미지를 지운다. 그 이미지로 이미 만든 가상서버는 영향 없다. - `cloud.firewall_presets` — 방화벽 프리셋 목록(웹·SSH 같은 흔한 조합). cloud.open_port 로 직접 여는 것보다 실수가 적다. - `cloud.create_instance` — Create a cloud instance. Provisioning continues asynchronously. This platform has NO region/zone selection — do not ask the customer to pick one. There is NO ro - `cloud.exec` — Run a shell command inside one of your instances and get stdout/stderr/exit code. Use this to install packages, start services, and inspect state. Long jobs sho - `cloud.write_file` — Write a text file inside one of your instances, creating parent directories. Use this to deploy source code, configs, and unit files. - `cloud.read_file` — Read a text file from one of your instances. Useful for checking logs and configs. - `cloud.list_firewall_rules` — List inbound firewall rules for an instance. Only instances with a public IP have rules. - `cloud.open_port` — Open an inbound port on an instance that has a public IP. Prefer restricting `source` to a specific address for admin ports like SSH — leaving it at 0.0.0.0/0 e - `cloud.close_port` — Remove an inbound firewall rule by its policy id (from cloud.list_firewall_rules). - `cloud.access_log` — 이 서버에 대한 **관리 접근 기록**(콘솔·API·exec) — 언제·누가·어느 IP 에서·무엇을. 기본 최근 7일. 키가 유출됐거나 이상 접근이 의심될 때 여기부터 본다(네트워크 연결 로그는 아님). - `cloud.list_blocked_ips` — 이 서버로 못 오게 막아 둔 출발지 IP 목록. 이미 열린 포트여도 이 IP 들은 거부된다. - `cloud.block_ip` — 특정 출발지 IP/대역을 이 서버로 못 오게 막는다(방화벽 deny, 열린 포트보다 우선). 악성 스캐너·공격 IP 차단용. 예: '1.2.3.4' 또는 '1.2.3.0/24'. - `cloud.unblock_ip` — 차단을 푼다. ip 는 cloud.list_blocked_ips 의 source 를 그대로 준다. - `cloud.change_plan` — Change an instance's plan (CPU/memory/disk). The instance must be stopped. Disk can only grow — moving to a plan with a smaller disk is rejected. - `cloud.delete_instance` *(human approval required)* — Delete an instance. This destructive action requires human approval. - `cloud.list_public_ips` — List public IPs held by this tenant and the pool's remaining capacity. - `cloud.attach_public_ip` — Lease a public IP from the pool and attach it to an instance in one step (IPAM lease → interface config → firewall address object). Use this to make a service r - `cloud.detach_public_ip` *(human approval required)* — Release the instance's public IP back to the pool. The service becomes unreachable from the internet immediately and the same address may not be available again - `cloud.set_ssh_key` — Register an SSH public key on an instance so it can be reached through the SSH gateway. Without a key nobody can log in — a running instance with no key is unre - `cloud.set_auto_snapshot` — 가상서버의 자동 스냅샷을 켜고 끈다. 정해진 시각(한국 기준)에 매일 찍고, 보관 개수를 넘으면 오래된 것부터 지운다. 사람이 손으로 만든 스냅샷은 정리 대상이 아니다. 기본은 꺼짐 — 스냅샷은 디스크를 쓰고 그건 요금이다. - `cloud.run_auto_snapshot` — 자동 스냅샷을 지금 한 번 찍는다. 예약이 제대로 도는지 다음 날까지 기다리지 않고 확인할 때 쓴다. - `security.get` — 이 조직의 보호 설정 — 운영 표시 사용 여부, 해제·삭제 시 메일 확인 여부, 삭제 유예 일수. 무엇을 건드리면 안 되는지 먼저 알기 위해 읽는다. 바꾸는 것은 사람만 할 수 있다. - `cloud.rename` — 가상서버의 표시 이름을 바꾼다(목록·상세·청구서). 서버는 멈추지 않고 주소(서브도메인)·vmid 는 그대로다. 주소를 바꾸려면 서브도메인 변경 도구를 쓴다. - `cloud.set_note` — 가상서버에 사람이 읽는 설명을 단다(목록·상세에 보인다). 빈 문자열이면 지운다. - `cloud.set_firewall_note` — 방화벽 규칙에 설명을 단다. 규칙 자체는 건드리지 않으므로 접속이 끊기지 않는다. rule 값은 cloud.firewall 이 돌려주는 규칙 이름이다. - `cloud.get_default_ssh_key` — 조직 기본 SSH 공개키 — 새 서버를 만들 때 sshKey 를 안 주면 자동으로 심기는 키. 지문·타입·키 없는 서버 수를 준다. 서버가 접속 안 될 때 여기부터 봐라. - `cloud.set_default_ssh_key` — 조직 기본 SSH 공개키 등록·교체. **앞으로 만드는 서버에만** 적용된다 — 이미 있는 서버의 키는 cloud.set_ssh_key 로 서버마다 바꿔야 한다. 공개키만 보내라(비밀키 절대 금지). - `cloud.add_default_ssh_key` — 기본 SSH 공개키에 키(들)를 **더한다**(교체가 아니다). 여러 사람·도구의 키를 하나씩 쌓을 때. 중복은 걸러진다. 기본은 앞으로 만드는 서버에만 적용된다 — 지금 있는 서버로 이 키로 들어가야 하면 applyToExisting:true(서버마다 있던 키는 그대로 두고 더한다). - `cloud.remove_default_ssh_key` — 기본 SSH 공개키에서 **지문 하나**를 뺀다. 퇴사자·안 쓰는 임시 키 정리에. 지문은 cloud.get_default_ssh_key 의 keys[].fingerprint(SHA256:...) 를 그대로 준다. - `cloud.metrics` — 가상서버 사용량 그래프 데이터 — CPU·메모리·디스크·네트워크 시계열과 제공량(limits). 느리다는 신고를 받으면 추측하지 말고 여기부터. - `cloud.set_subdomain` — 가상서버의 기본 주소(