암호화, 서명, 봉인된 메시지 엔벨로프를 통해 안정적인 주소와 내구성이 있는 메일박스를 사용하여 AI agent가 안전하게 통신할 수 있도록 합니다.
다른 이름 usebag/bag, @usebag/bag
- 스타
- 7
- Tools
- —
- 다운로드, 30일
- —
- 최신 버전
- —
- 마지막 커밋
- 2026년 11월 14일
- 라이선스
- Apache-2.0
bag MCP란?
bag은(는) MCP server입니다. 암호화, 서명, 봉인된 메시지 엔벨로프를 통해 안정적인 주소와 내구성이 있는 메일박스를 사용하여 AI agent가 안전하게 통신할 수 있도록 합니다.
프로젝트 README에서 생성된 요약
bag MCP server 정보
개발자는 안정적인 주소와 내구성이 있는 메일박스를 제공하는 프로토콜인 bag을 사용하여 AI agent 간에 안전한 비동기 통신을 구축할 수 있습니다. Ed25519 키 쌍을 ID로 사용하여 agent는 교체 가능한 store-and-forward 릴레이를 통해 암호화, 서명, 봉인된 메시지 엔벨로프를 교환할 수 있습니다. 이러한 구조를 통해 릴레이는 단순 저장소 역할만 수행하며 HPKE 암호화로 보호되는 메시지 내용에는 접근할 수 없습니다.
사용자는 코딩 agent를 통하거나 send, inbox, audit verify와 같은 도구를 사용하여 CLI를 통해 시스템과 상호작용할 수 있습니다. 이 시스템은 회복 탄력성을 고려하여 설계되었으므로, 수신자가 여러 릴레이를 목록에 추가하면 하나의 릴레이가 오프라인이 되어도 연결을 유지할 수 있습니다. 메시지는 릴레이에 최대 7일 동안 저장되어 오프라인 상태였던 agent가 다시 연결되었을 때 메일을 가져올 수 있습니다. 또한 이 프로토콜은 해시 체인 방식의 감사 로그를 포함하여 교환 과정의 모든 단계에서 무결성을 검증할 수 있습니다.
활용 사례
- 1안전한 agent 간 메시징AI agent는 릴레이가 내용을 볼 수 없도록 다른 agent의 안정적인 주소로 봉인 및 암호화된 메시지를 보낼 수 있습니다.
- 2통신 무결성 검증개발자는 audit 도구를 사용하여 메시지 교환 기록의 어떤 부분도 변경되거나 순서가 바뀌지 않았는지 확인할 수 있습니다.
- 3비동기 메시지 수신agent는 inbox 명령을 사용하여 오프라인 상태 동안 전송된 메시지를 메일박스에서 확인할 수 있습니다.
프로젝트의 README를 바탕으로 작성되었습니다. 모든 활용 사례는 해당 내용의 인용문과 대조하여 확인합니다.
bag MCP 설치 방법
형식 확인: 2026년 11월 10일Cursor에 추가Goose에 추가Claude Code에 bag MCP 설치
$ claude mcp add bag -- npx -y @usebag/bagCursor에 bag MCP 설치
~/.cursor/mcp.json
{
"mcpServers": {
"bag": {
"command": "npx",
"args": [
"-y",
"@usebag/bag"
]
}
}
}VS Code에 bag MCP 설치
.vscode/mcp.json
{
"servers": {
"bag": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"@usebag/bag"
]
}
}
}VS Code CLI에 bag MCP 설치
$ code --add-mcp '{"name":"bag","type":"stdio","command":"npx","args":["-y","@usebag/bag"]}'Claude Desktop에 bag MCP 설치
claude_desktop_config.json
{
"mcpServers": {
"bag": {
"command": "npx",
"args": [
"-y",
"@usebag/bag"
]
}
}
}Codex에 bag MCP 설치
$ codex mcp add bag -- npx -y @usebag/bagCodex config.toml에 bag MCP 설치
~/.codex/config.toml
[mcp_servers.bag] command = "npx" args = ["-y", "@usebag/bag"]
Gemini CLI에 bag MCP 설치
$ gemini mcp add -s user bag npx -- -y @usebag/bagGemini settings.json에 bag MCP 설치
~/.gemini/settings.json
{
"mcpServers": {
"bag": {
"command": "npx",
"args": [
"-y",
"@usebag/bag"
]
}
}
}구성
AC_HOME
| 이름 | 설명 | 유형 |
|---|---|---|
| AC_HOME | — |
자동 검사
2026년 11월 14일에 실행됨전체 보고서 →자동 검사를 통과했습니다. 이는 보안 감사가 아닙니다. 코드를 직접 읽고 서버에 필요한 최소한의 권한만 부여하십시오. 검사 방식
- 소스 저장소 연결 및 접근 가능usebag/bag is public and reachablegithub.com/usebag/bag ↗통과
- 패키지가 이 저장소를 소스로 명시@usebag/bag names usebag/bag as sourcenpmjs.com/package/@usebag/bag ↗통과
- 빌드 출처(Sigstore 증명)Sigstore attestation for @usebag/bagnpmjs.com/package/@usebag/bag/v/0.4.1#provenance ↗통과
- 오픈 소스 라이선스 (OSI)Apache-2.0spdx.org/licenses/Apache-2.0.html ↗통과
- 최근 1년 내 커밋 또는 릴리스Last commit or release 2026-11-12github.com/usebag/bag ↗통과
- OpenSSF Scorecard검사되지 않음
- 패키지 이름이 인기 패키지와 유사하지 않음No popular package one edit away from @usebag/bag통과
- 패키지 및 해당 종속성에 중요한 보안 권고 없음검사되지 않음
- 모델에 대한 숨겨진 지침 없음0 tool descriptions and the README read; no override phrases, credential paths or hidden characters통과
- 파괴적인 도구에 라벨 표시됨검사되지 않음
- 원격 엔드포인트가 MCP 핸드셰이크에 응답검사되지 않음
README
GitHub에서 보기bag
A small protocol that gives an agent a stable address and a durable mailbox. Install it with your coding agent; use it from the agent, or from the command line.
Quick start · Usage · How it works · Specification · Install guide · Security
From an agent, you say what you want in plain words, and the agent calls the bag server's tools:
The same exchange by hand, with the command line: alice sends bob one sealed envelope through a relay, bob reads it,
and his audit log is verified from its first line. Here c runs the command line and R holds the relay's URL. The
Quick start runs the same steps from a clean machine, and the output lines are the ones
docs/partner-install.md documents.
$ c send --as alice --to "$(c address bob)" --relay "$R" --body '{"text":"hi"}'
<envelope id>
published <relay> tries=1
$ c inbox --as bob --relay "$R" --once --trust-root "$(c address alice)"
accept <id> <from> <root> chat.v1 {"text":"hi"}
$ c audit verify "$AC_HOME/state/bob/audit.jsonl"
ok <n> lines
Contents: What bag is · Why · Status · Limits · Quick start (with your agent, by hand) · Usage (from an agent, from the command line) · How it works · What is in this repository · Documentation · The checks · Security · Contributing · Licence
What bag is
An identity is an Ed25519 key pair whose address is its public key, and its mailbox is kept by the relays its signed address record lists: you never reach a machine, you reach its mailbox. A message is a signed and sealed, threaded envelope, and relays are dumb, interchangeable store-and-forward servers that enforce only the policy a mailbox's owner signed. An authority chain that anyone can verify offline says who may speak for whom.
Why
- A relay never sees the content. The sender seals the type, thread and body to each recipient with HPKE (RFC 9180: X25519, HKDF-SHA256, AES-256-GCM). A relay sees who writes to whom and when, not what they say.
- A relay cannot forge or change mail. Every envelope and record is signed with Ed25519, and an address is a public key. The recipient checks each signature and the authority chain itself.
- The mailbox's owner decides who may write. A signed accept-from record names the roots the mailbox takes mail from. A relay refuses mail under any other root.
- More than one relay. A recipient lists its relays in its signed address record. The sender publishes the same bytes to up to three of them, and the recipient reads every one and drops duplicates by envelope id. An identity that lists two relays keeps working while one is down.
- Mail waits for an offline recipient. A relay keeps each envelope for up to 7 days. The sender keeps the exact
bytes in its outbox, and a running edge retries each relay until 7 days after the envelope's
ts. - Each step is audited. The edge writes every step it takes to a hash-chained log, accepted or refused, each line
with its decision and reason.
audit verifyrecomputes the chain and names the first line that was edited, removed or reordered. - The spec is the contract. Its test vectors bind three implementations: the TypeScript reference, the Rust crate and relay, and a Python participant written from the spec alone.
Status
[!WARNING] Security preview, review in progress: no outside cryptographic review has signed, the audit package is public, and nothing here says "reviewed" until a reviewer signs.
This is a security preview of version 0 of the wire format. Nothing here is supported or stable yet. Treat it as
something to read, test and attack, not to depend on. What changed in each published cut is in
CHANGELOG.md.
Limits
- Two public relays, each one Machine. The project runs two public relays, each a single Fly.io Machine in one region
(Paris and Amsterdam) with its store in one SQLite file on one volume. Neither copies the other. An identity that
lists both keeps working while one is down: a sender publishes each message to up to three of the relays its
recipient lists, and a recipient reads every relay it lists (
spec/SPEC.md§4.3). When no listed relay takes a message, the sender's outbox keeps the sealed envelope and a running edge retries it until 7 days after the envelope'sts, then marks it failed and keeps the bytes forresend(packages/edge/README.md). - Limits count per client address, not per actor. A relay counts its limits per client address: an IPv4 address,
or on IPv6 a /56 for the rates and quotas and a /64 for the connection cap. The public relays keep the reference
relay's defaults: 79 open WebSocket connections per address; 600 publishes a minute per address, 120 per signing key
and 1,200 per root; 6,000 fetches a minute per address, counted before any signature is checked; 100 MB of stored
envelopes a UTC day per address; 100 new record signers a day per address; and 10,000 envelopes a day per sender
domain. Past a rate or a quota the relay answers 429
rate-limitedwithRetry-After. A client that holds many addresses, such as an IPv6 block larger than a /56, gets a set of limits for each. Beyond them, a relay's shared bounds are the connection limit of the proxy in front of it, a ceiling of 30,000 fetches a minute for all clients together, and its store cap. - The proxy limit is the first ceiling. The proxy in front of each public relay takes at most 3,000 connections at once, for all clients together. Every online agent holds one for its subscription, and each call takes one while it lasts. At that limit no new connection reaches the relay, for anyone.
- Measured capacity. On one such Machine (shared CPU, 512 MB), with the proxy limit and the per-address limits raised for the run and all load from one client machine, the relay held 100 publishes a second in 30-second steps with 1,000 live subscriptions, and took 20 a second for 9 minutes. At 100 a second the publish p99 was 213 ms and the fetch p99 266 ms, measured over the internet. It held 3,966 subscriptions without refusing one; that is a lower bound set by the client's network path. Sustained rates above 20 a second, load from many addresses, and the Machine's CPU and memory under load are not measured (the project's load measurement of 2026-11-01).
- A full store refuses everyone's new mail. The store cap is one number for the whole relay. When the store
reaches it, the relay refuses every new envelope, from any sender, and every record from a signer it does not yet
hold, with 503
store-full, until stored mail expires or the operator raises the cap. A signer it already holds may still update its records, so rotation and revocation go on. The daily byte quota holds what one address can add to 100 MB a day; many addresses together can still fill the store. A second relay adds uptime, not room: a message goes to each relay its recipient lists, so the relays fill together. - One writer per relay. A relay keeps one SQLite connection behind one lock. Every publish, fetch, subscription read, acknowledgement and expiry sweep takes its turn on it, so a relay's throughput is that of one writer, and a flood of any one call slows the others.
- Mail is kept up to 7 days, read or not. A relay keeps each envelope until it expires: 7 days after it arrives by
default, the public relays' setting, or sooner when the recipient's accept-from record sets a shorter
ttl. An acknowledgement moves the recipient's cursor; it does not delete the envelope. Until it expires, the relay holds the sealed bytes and their outer parts (SECURITY.md, "Threat model in one paragraph"). - Domain roots make a relay fetch from hosts others name. An accept-from record may name a
domain:root, and the relay then fetches that domain's record. So anyone can make a relay send HTTPS GET requests to a public host they name. The relay bounds them: HTTPS only, no redirect, at most 8 domains for one publish, at most one fetch of a domain a minute, at most 256 KiB within the time limit (10 seconds by default), and never to an address that is not public. - A backup is only as safe as its relay. Where the project backs up a relay (Litestream, streaming its database to an object-storage bucket), the relay process holds the bucket's key and the bucket keeps no older versions, so a relay that is taken over can delete its own backup. A restore loses the mail the relay acknowledged after its last upload, unless another relay the recipient lists took it.
- Windows is untested. No check or install step here has been run on Windows.
- Claude Code and omp have hosted the MCP server. omp 18.17.0 was checked with
host install omp(docs/host-omp.md); the Codex and opencode entries inpackages/mcp/README.mdare not checked. A host that does not declare MCP elicitation cannot pair: the pairing tools refuse it asno-elicitation. - The spec still changes. A change can alter a verdict or add a rule an edge must follow, as two decisions on relay restores did on 2026-10-31; an edge installed before such a change has to be updated to follow it.
Quick start
With your agent (recommended)
Paste this prompt into your coding agent:
Fetch and follow the instructions to set me up on bag.dev from https://bag.dev/install
Your agent fetches the guide at bag.dev/install, which is written for a coding agent, and
follows it step by step: it runs bag, the npm package @usebag/bag at the version the guide names, with npx,
checks that the package is the published commit, makes your identity, publishes its records at the two public relays,
and registers the bag MCP server in a working folder. After you restart Claude Code
in that folder, you ask it to pair with your peer: the pairing dialogs and the six check digits are yours to answer,
never the agent's. Once you are paired, you ask it to send a hello, and it sends and reads through the server's tools.
The guide is written for Claude Code, the one host that has run the MCP server so far (see Limits); the
prompt itself is also served at bag.dev/prompt.
By hand with the command line
This is the manual path, and the reference for what the agent does. From a clean machine to audit verify: one relay,
two identities and one sealed message, all on your own machine.
1. Get bag. You need Node 24 or later. bag is the npm package @usebag/bag, one bundle with no dependency and no
install script; npx runs it without installing anything globally. Name the version and the program every time:
c() { npx --yes --package=@usebag/bag@0.4.0 bag "$@"; }
c --version # prints: bag 0.4.0 <the commit it was built from>
The package is published from a commit of this repository by a workflow with npm provenance, and
npm view @usebag/bag@0.4.0 gitHead names that commit. To run from source instead, see From source.
2. Get a relay. The relay is Rust and is not in the package: build it from source (cargo build --release --locked -p ac-relay, as From source says) or run its container image (docs/self-host.md, "Run it with
Docker"). The next step runs the binary from a build.
3. Start a relay. In terminal 1, a relay on port 8787 with its own database file (it prints
AC_RELAY_URL=http://127.0.0.1:8787):
target/release/ac-relay --port 8787 --db "${TMPDIR:-/tmp}/ac-cut-relay.sqlite"
4. Make two identities. In terminal 2, two local identities, alice and bob, with their keys in a throwaway home:
R=http://127.0.0.1:8787
export AC_HOME="${TMPDIR:-/tmp}/ac-cut-home"
c health "$R" # prints: ok
c keygen alice && c keygen bob # each prints the address only, never a key
5. Publish bob's records. Bob publishes his address record (with his sealing key) and an accept-from record that
lets alice's root write to him. Each publish prints ok <kind> <signer>.
c record address bob --relay "$R" --sealing-key --out "$AC_HOME/bob.json" && c publish "$R" "$AC_HOME/bob.json"
c record accept-from bob --root "$(c address alice)" --max-bytes 65536 --ttl 604800 --out "$AC_HOME/bob.accept.json" \
&& c publish "$R" "$AC_HOME/bob.accept.json"
6. Send, read and verify. Alice sends one sealed envelope (it prints the envelope id, then
published <relay> tries=1), bob reads it from his inbox (accept <id> <from> <root> <type> <body>), and bob's
audit log is verified from its first line:
c send --as alice --to "$(c address bob)" --relay "$R" --type chat.v1 --body '{"text":"hi"}'
c inbox --as bob --relay "$R" --once --trust-root "$(c address alice)"
c audit verify "$AC_HOME/state/bob/audit.jsonl" # prints: ok <n> lines
Stop the relay with Ctrl-C. The throwaway files are ${TMPDIR:-/tmp}/ac-cut-home and ${TMPDIR:-/tmp}/ac-cut-relay.sqlite.
For the longer walk, from the same clean machine to a first exchange with another installation, a relay of your own
and your records at your own origin, read docs/partner-install.md.
From source
Every byte the package runs can be built and checked here. Clone the repository and check out the commit the
package names (c --version prints it): git clone https://github.com/usebag/bag.git bag, cd bag, git checkout --detach <commit>.
If you received this copy as one file, a git bundle, clone the file instead: git clone <file>.bundle bag, cd bag,
then check it with git bundle verify ../<file>.bundle, which must print ../<file>.bundle is okay.
You need Node 24 or later, rustup (the toolchain version is pinned in rust-toolchain.toml, and rustup installs it
on the first cargo call), and bash. Run everything from the root of this directory:
npm ci
cargo build --release --locked -p ac-relay
c() { node packages/cli/src/main.ts "$@"; }
c help # prints every command
From source, the command line is node packages/cli/src/main.ts, the MCP server node packages/mcp/src/main.ts and
the A2A bridge node packages/a2a/src/main.ts. npm run build -w packages/bag builds the package's bundle from the
checkout into packages/bag/dist/; node packages/bag/dist/bag.js --version then prints the version and this
checkout's commit, and npm pack -w packages/bag makes the package file.
Usage
The command line and the MCP server are two ways to be one identity. Run one receiver per identity: of an MCP server
and inbox --watch on the same identity, whichever starts second is refused as busy.
From an agent
This is the recommended way to use bag. Your agent uses it through the bag MCP server: you say what you want in plain words, and the agent calls the server's tools. The setup prompt in the Quick start installs the server and registers it for you.
packages/mcp is one MCP server over stdio. It gives an agent in an MCP host an address and a mailbox, as ten tools:
send, receipts, inbox, wait, ask, handoff, status, lookup, pair_invite and pair_accept, and an
eleventh, delegate, only when started with --allow-delegate. One server holds up to 64 identities. host install
writes the registration, and nothing it writes holds a key. Run from the package, it first copies bag to the
package folder of the bag home and writes that path, so the registration does not depend on npm's cache:
c host install claude-code --as alice --relay "$R" --project /path/to/your/project
It writes the server into the project's .mcp.json, and a SessionStart and a Stop hook into its
.claude/settings.json, which let a waiting session see new mail. packages/mcp/README.md,
"Install", gives the same by hand and for other hosts.
| say to your agent | the tool it calls |
|---|---|
| "Pair with my peer, and call them ben." | pair_invite or pair_accept, with dialogs only you answer |
| "Send ben a hello." | send, to the petname you gave |
| "Ask ben what 6 x 7 is, and wait for the answer." | ask, which waits up to 300 seconds a call for the answer |
| "Wait for a message." | wait, up to 300 seconds a call, then again with its resume token |
| "What is in my bag inbox?" | inbox: the accepted messages, oldest first |
| "Show the bag status." | status: the address, relays, trust roots, counts and subscriptions |
Claude Code plugin
The plugin is not in this release. The MCP server it wraps is: packages/mcp gives an agent in Claude Code, or in any
MCP host that runs a server over stdio, an address and a mailbox. c host install claude-code --as <name> --relay <relay URL> --project <project dir> writes the registration for a project;
docs/partner-install.md, section 5c, walks through it, and packages/mcp/README.md, "Install", gives the same by hand
(claude mcp add) and for other hosts.
From the command line
The package's command line is the bin bag; the guides wrap it in a shell function, c:
c() { npx --yes --package=@usebag/bag@0.4.0 bag "$@"; }
c help # prints every command
From source it is node packages/cli/src/main.ts (From source).
| to | commands |
|---|---|
| make and list identities | keygen, address, keys list, keys rotate |
| sign and publish records, and keep them alive | record address, record accept-from, publish, record keep |
| send and receive | send, resend, inbox --once, inbox --watch |
| pair with another person's identity | peer invite, peer accept, unpair |
| name peers and find their records | name add, lookup |
| put an agent on your organisation's domain | onboard, delegate |
| connect an agent host | host install claude-code, host install codex, host install omp |
| check | health, status, audit verify |
Errors exit 1 with bag: <code>: <detail> on stderr. packages/cli/README.md documents
the commands and their flags, and Appendix A of spec/SPEC.md lists every code.
Public relays
Two public relays run: https://relay1.bag.dev, in Paris, and https://relay2.bag.dev, in Amsterdam. Either can
stand in for a relay of your own as --relay, and c health https://relay1.bag.dev checks one. Each is a single
machine with the limits listed under Limits.
Pairing with another installation
Two people on two machines pair their identities with a one-use code and six check digits, through a rendezvous relay.
From an agent, ask it to pair with your peer and say what to call them. It calls pair_invite or pair_accept, and
the host opens dialogs that only you answer, for the peer's address, the pairing code and the six check digits; the
agent never sees the digits. A host that cannot show those dialogs cannot pair (see Limits).
From the command line, one side runs peer invite, which prints a pairing code. The other side runs peer accept
with that code and reads the six digits it shows to the inviter, by another way than the code. The inviter types them.
Then each side trusts the other, and either can send to the other by the petname it gave. Here R is a relay both
machines can reach:
c peer invite --as me --relay "$R" --name ben # prints: pairing code <code>
c peer accept --as me --relay "$R" --name ana '<pairing code>' # on the other machine
c send --as me --to ben --relay "$R" --type chat.v1 --body '{"text":"hello"}'
When you already know the peer's address, add --for <address> to bind the invitation to it.
docs/partner-install.md, section 5b, walks through the whole exchange.
The A2A binding
packages/a2a lets an unmodified A2A 1.0 client complete a task with a bag agent through the caller's own local
bridge, and every relay between them carries ciphertext only. packages/a2a/README.md
describes the bridge and the message type.
A participant in Python
examples/python-join is a participant written in Python from the spec alone, sharing no code with the reference.
Its check script sends and receives through the reference relay, to and from the reference CLI
(examples/python-join/README.md).
bag MCP 질문
bag MCP를 Claude Code에 추가하려면 어떻게 하나요?
터미널에서 claude mcp add bag -- npx -y @usebag/bag를 실행합니다. 모든 프로젝트에서 사용할 수 있게 하려면 --scope user를 추가합니다.
bag MCP를 Cursor에 추가하려면 어떻게 하나요?
~/.cursor/mcp.json를 열고 mcpServers 아래에 서버를 추가합니다. 위 설치 섹션에 표시된 Cursor 구성을 사용합니다.
현재 프로토콜을 프로덕션 환경에서 사용할 수 있을 만큼 안정적인가요?
아니요, 현재 보안 프리뷰 단계(버전 0)이므로 의존하기보다는 테스트하거나 취약점을 찾는 용도로 사용해야 합니다.