Anna's Archive and OpenAlex
Find books, papers and dissertations with Anna's Archive and OpenAlex, then download or read them.
제작자가 쓴 설명(영어 원문)
Calendars for AI agents: free/busy, next free slot, and bookings PostgreSQL never double-books.
이 세 가지는 절대 하나의 점수로 합치지 않아요. 의견, 측정, 인기는 서로 다른 것이니까요.
이 서버는 아직 쉬운 말로 된 요약을 쓰지 못했어요. 아래는 레지스트리에서 읽어 온 사실이에요.
쓰고 있는 AI 앱을 고른 다음 설정을 복사하세요.
DATABASE_URL, SLOTLOCK_AUTH_TOKEN, SLOTLOCK_CONFIRMATION_SECRET, SLOTLOCK_METRICS_TOKEN, PORT, SLOTLOCK_MIGRATE_DATABASE_URL, SLOTLOCK_CONFIRM_WRITES, SLOTLOCK_AVAILABILITY, SLOTLOCK_REST_API, SLOTLOCK_RETENTION_DAYS, SLOTLOCK_SHARED_LIMITS, SLOTLOCK_WEBHOOKS, SLOTLOCK_TENANT비밀로 표시된 값은 내 계정의 열쇠예요. 절대 다른 사람과 공유하거나 채팅에 붙여 넣지 마세요.
필요한 것
어떤 앱을 쓰세요?
위에서 앱을 고르세요. 기억해 두었다가 다음부터는 버튼에 “…에 설치”라고 표시해요.
Claude Desktop → Settings → Developer → Edit Config를 열고 claude_desktop_config.json에 이 내용을 붙여 넣으세요
{
"mcpServers": {
"slotlock": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"DATABASE_URL",
"-e",
"SLOTLOCK_AUTH_TOKEN",
"-e",
"SLOTLOCK_CONFIRMATION_SECRET",
"-e",
"SLOTLOCK_METRICS_TOKEN",
"-e",
"PORT",
"-e",
"SLOTLOCK_MIGRATE_DATABASE_URL",
"-e",
"SLOTLOCK_CONFIRM_WRITES",
"-e",
"SLOTLOCK_AVAILABILITY",
"-e",
"SLOTLOCK_REST_API",
"-e",
"SLOTLOCK_RETENTION_DAYS",
"-e",
"SLOTLOCK_SHARED_LIMITS",
"-e",
"SLOTLOCK_WEBHOOKS",
"-e",
"SLOTLOCK_TENANT",
"ghcr.io/pilotaai/slotlock:0.6.0",
"serve",
"--migrate"
],
"env": {
"DATABASE_URL": "your-value",
"SLOTLOCK_AUTH_TOKEN": "your-value",
"SLOTLOCK_CONFIRMATION_SECRET": "your-value",
"SLOTLOCK_METRICS_TOKEN": "your-value",
"PORT": "your-value",
"SLOTLOCK_MIGRATE_DATABASE_URL": "your-value",
"SLOTLOCK_CONFIRM_WRITES": "your-value",
"SLOTLOCK_AVAILABILITY": "your-value",
"SLOTLOCK_REST_API": "your-value",
"SLOTLOCK_RETENTION_DAYS": "your-value",
"SLOTLOCK_SHARED_LIMITS": "your-value",
"SLOTLOCK_WEBHOOKS": "your-value",
"SLOTLOCK_TENANT": "your-value"
}
}
}
}터미널에서 이 명령어를 실행하세요
claude mcp add slotlock --env DATABASE_URL=your-value --env SLOTLOCK_AUTH_TOKEN=your-value --env SLOTLOCK_CONFIRMATION_SECRET=your-value --env SLOTLOCK_METRICS_TOKEN=your-value --env PORT=your-value --env SLOTLOCK_MIGRATE_DATABASE_URL=your-value --env SLOTLOCK_CONFIRM_WRITES=your-value --env SLOTLOCK_AVAILABILITY=your-value --env SLOTLOCK_REST_API=your-value --env SLOTLOCK_RETENTION_DAYS=your-value --env SLOTLOCK_SHARED_LIMITS=your-value --env SLOTLOCK_WEBHOOKS=your-value --env SLOTLOCK_TENANT=your-value -- docker run -i --rm -e DATABASE_URL -e SLOTLOCK_AUTH_TOKEN -e SLOTLOCK_CONFIRMATION_SECRET -e SLOTLOCK_METRICS_TOKEN -e PORT -e SLOTLOCK_MIGRATE_DATABASE_URL -e SLOTLOCK_CONFIRM_WRITES -e SLOTLOCK_AVAILABILITY -e SLOTLOCK_REST_API -e SLOTLOCK_RETENTION_DAYS -e SLOTLOCK_SHARED_LIMITS -e SLOTLOCK_WEBHOOKS -e SLOTLOCK_TENANT ghcr.io/pilotaai/slotlock:0.6.0 serve --migrate실행하기 전에 빈 값을 채워 주세요.
프로젝트의 .cursor/mcp.json 또는 ~/.cursor/mcp.json에 붙여 넣으세요
{
"mcpServers": {
"slotlock": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"DATABASE_URL",
"-e",
"SLOTLOCK_AUTH_TOKEN",
"-e",
"SLOTLOCK_CONFIRMATION_SECRET",
"-e",
"SLOTLOCK_METRICS_TOKEN",
"-e",
"PORT",
"-e",
"SLOTLOCK_MIGRATE_DATABASE_URL",
"-e",
"SLOTLOCK_CONFIRM_WRITES",
"-e",
"SLOTLOCK_AVAILABILITY",
"-e",
"SLOTLOCK_REST_API",
"-e",
"SLOTLOCK_RETENTION_DAYS",
"-e",
"SLOTLOCK_SHARED_LIMITS",
"-e",
"SLOTLOCK_WEBHOOKS",
"-e",
"SLOTLOCK_TENANT",
"ghcr.io/pilotaai/slotlock:0.6.0",
"serve",
"--migrate"
],
"env": {
"DATABASE_URL": "your-value",
"SLOTLOCK_AUTH_TOKEN": "your-value",
"SLOTLOCK_CONFIRMATION_SECRET": "your-value",
"SLOTLOCK_METRICS_TOKEN": "your-value",
"PORT": "your-value",
"SLOTLOCK_MIGRATE_DATABASE_URL": "your-value",
"SLOTLOCK_CONFIRM_WRITES": "your-value",
"SLOTLOCK_AVAILABILITY": "your-value",
"SLOTLOCK_REST_API": "your-value",
"SLOTLOCK_RETENTION_DAYS": "your-value",
"SLOTLOCK_SHARED_LIMITS": "your-value",
"SLOTLOCK_WEBHOOKS": "your-value",
"SLOTLOCK_TENANT": "your-value"
}
}
}
}브라우저가 앱을 열지 물어본 다음, 앱이 설정을 보여 주고 확인을 요청해요. 키 값은 비워 두니 직접 입력하세요.
프로젝트의 .vscode/mcp.json에 붙여 넣으세요
{
"servers": {
"slotlock": {
"type": "stdio",
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"DATABASE_URL",
"-e",
"SLOTLOCK_AUTH_TOKEN",
"-e",
"SLOTLOCK_CONFIRMATION_SECRET",
"-e",
"SLOTLOCK_METRICS_TOKEN",
"-e",
"PORT",
"-e",
"SLOTLOCK_MIGRATE_DATABASE_URL",
"-e",
"SLOTLOCK_CONFIRM_WRITES",
"-e",
"SLOTLOCK_AVAILABILITY",
"-e",
"SLOTLOCK_REST_API",
"-e",
"SLOTLOCK_RETENTION_DAYS",
"-e",
"SLOTLOCK_SHARED_LIMITS",
"-e",
"SLOTLOCK_WEBHOOKS",
"-e",
"SLOTLOCK_TENANT",
"ghcr.io/pilotaai/slotlock:0.6.0",
"serve",
"--migrate"
],
"env": {
"DATABASE_URL": "your-value",
"SLOTLOCK_AUTH_TOKEN": "your-value",
"SLOTLOCK_CONFIRMATION_SECRET": "your-value",
"SLOTLOCK_METRICS_TOKEN": "your-value",
"PORT": "your-value",
"SLOTLOCK_MIGRATE_DATABASE_URL": "your-value",
"SLOTLOCK_CONFIRM_WRITES": "your-value",
"SLOTLOCK_AVAILABILITY": "your-value",
"SLOTLOCK_REST_API": "your-value",
"SLOTLOCK_RETENTION_DAYS": "your-value",
"SLOTLOCK_SHARED_LIMITS": "your-value",
"SLOTLOCK_WEBHOOKS": "your-value",
"SLOTLOCK_TENANT": "your-value"
}
}
}
}브라우저가 앱을 열지 물어본 다음, 앱이 설정을 보여 주고 확인을 요청해요. 키 값은 비워 두니 직접 입력하세요.
이 서버는 내 컴퓨터에서 실행되는데, ChatGPT는 인터넷에 있는 서버에만 연결할 수 있어요. 다른 앱을 고르세요.
선택한 앱은 이 기기의 쿠키에만 저장돼요. 계정은 필요 없어요.
PORT envSLOTLOCK_CONFIRM_WRITES envSLOTLOCK_AVAILABILITY envSLOTLOCK_REST_API envSLOTLOCK_RETENTION_DAYS envSLOTLOCK_SHARED_LIMITS envSLOTLOCK_WEBHOOKS envSLOTLOCK_TENANT env이 설정은 제작자의 레지스트리 정보로 만들었어요. README와 다르면 README를 따르세요.
내 컴퓨터에서 실행돼요. 설치하면 AI 앱에 도구 목록이 나타나요.
누구나 볼 수 있는 정보를 점검했고, 코드는 읽지 않았어요. 해당하지 않는 항목은 개수에서 뺐어요. · 2026년 11월 7일 점검
레지스트리 이름이 GitHub 계정 PILOTAAI 기준으로 확인되었고, 이 계정이 저장소를 소유하고 있어요
아직 GitHub에서 이 저장소를 읽어 오지 않았어요
아직 GitHub에서 이 저장소를 읽어 오지 않았어요
내 컴퓨터에서 실행되는 서버라 인터넷 엔드포인트가 없어요
내 컴퓨터에서 실행되며, 대신 로컬 설정을 사용해요
내 컴퓨터에서 실행돼요. 도구 목록은 인터넷 엔드포인트가 있는 서버에서만 읽을 수 있어요
레지스트리에서 이 카테고리의 활성 서버 전체와 비교했어요. 스타는 게시자가 저장소를 소유한 경우에만 세요.
해당하는 기본 점검 1개 중 1개를 통과했어요. 코드는 읽지 않았어요. 키나 토큰을 넣기 전에 서버가 어떤 권한을 요구하는지 확인하고, 꼭 필요한 권한만 있는 키를 쓰세요.
입력해야 할 값: DATABASE_URL, SLOTLOCK_AUTH_TOKEN, SLOTLOCK_CONFIRMATION_SECRET, SLOTLOCK_METRICS_TOKEN, SLOTLOCK_MIGRATE_DATABASE_URL
내 컴퓨터에서 실행돼요. AI 앱이 필요할 때 실행하고, 데이터는 제작자의 서버를 거치지 않아요(서버 자체가 온라인 서비스를 호출하는 경우는 제외).
GitHub 저장소는 마지막으로 – 변경됐고, 최신 버전(0.6.0)은 9일 전 레지스트리에 올라왔어요.
Claude Desktop, Claude Code, Cursor, VS Code처럼 MCP를 지원하는 앱에서 쓸 수 있어요. 내 컴퓨터에 Docker도 있어야 해요.
같은 카테고리에는: Anna's Archive and OpenAlex, Neural Cosmology, slopped.site
같은 카테고리에서 다른 제작자가 만든 서버예요. 스타 순으로 정렬했어요.
카드 보는 법:★ GitHub 스타i세 기둥: 리뷰 · 점검 · 사용 정도i업데이트 = 최신 버전을 레지스트리에 공개한 날i
Find books, papers and dissertations with Anna's Archive and OpenAlex, then download or read them.
Answers, essays, experiments and books on consciousness and cosmology: search, read, buy.
Read-only tools over slopped.site: AI-made art, lore, games, sites, the curriculum.
제작자의 저장소에서 쓰인 그대로 가져왔어요. PopNx MCP가 검토하거나 보증한 내용이 아니에요. HTML, 이미지, 스크립트는 제거했어요. 링크를 누르면 이 사이트를 벗어나요.
Slotlock is a calendar for AI agents. It books vehicles, rooms, machines, people or anything else reservable, answers "when is this free?" from weekly availability rules, and lets PostgreSQL reject double bookings, however many writers race. Agents call it over MCP or A2A; your code calls it as a TypeScript library.
[start, end), so back-to-back bookings never collide.npm install slotlock postgres
Node.js 22.12+, PostgreSQL 16 or newer with btree_gist (created for you if missing; CI runs 16, 17 and 18), and postgres ^3.4.5 as a peer dependency. TypeScript declarations are included.
From a clone of this repository:
scripts/quickstart-env.sh > .env # .env.example, its four secrets set to openssl rand -hex 32
docker compose up --build --detach docker compose exec slotlock slotlock resource add vehicle-42 --timezone Europe/London
| URL | What |
|---|---|
http://localhost:8080/mcp | MCP, with Authorization: Bearer |
http://localhost:8080/a2a | A2A 1.0, same token; card at /.well-known/agent-card.json |
http://localhost:8080/v1/… | REST: the tools, and the application API for admin keys; described at /openapi.json |
http://localhost:8080/healthz | Readiness, including the database |
http://localhost:8080/metrics | Prometheus metrics, with Authorization: Bearer ; off without it |
slotlock_calls_total, with their duration in slotlock_call_duration_seconds), confirmations, subscriptions, refusals, maintenance and webhook deliveries. No label names a tenant, key or client. createSlotlockMetrics builds them for a server of your own, from its hooks.migrate service applies the schema as the owner.SLOTLOCK_AVAILABILITY sets the default bookable hours. A resource can have its own (slotlock hours set, or the dashboard); with neither, no slot is offered. SLOTLOCK_CONFIRM_WRITES=all (as .env.example sets it; the server's default is none) makes every write wait for a person.SLOTLOCK_PUBLIC_URL.429 rate_limited with Retry-After and the RateLimit fields. The application API counts an admin key's calls in its tenant's own app_read and app_write budgets, apart from the agents'; another key's are its own. A recurring create and every event update (a new title re-expands a recurring event's series too) takes its write token, then waits for a slot: one at a time per tenant (tenant_series_writes) and per server (series_writes); each server process counts its own. A freed slot rests for as long as the server was busy while the write before held it (at most a second), so with one slot, writes that each hold it under a second keep the server busy at most about half the time. It then goes to the waiting tenant with the fewest writes in flight and, among those, the one whose writes have kept the server busy least lately (halving every ten seconds), then to the first to ask. So a tenant sending one write at a time waits for the write running, its rest, and the other tenants with one write in flight whose writes kept the server less busy: many such tenants, new ones included, can each go ahead of it once. Tenants keeping more writes waiting never go ahead of it. Four more of a tenant's writes may wait and the rest get 429. When the server's 64 places are all taken, a write from a tenant with fewer writes in flight than the tenant with the most takes the place of that tenant's last write, which gets 503 server_busy; otherwise it gets 503 at once. An expansion runs on the server's main thread, so any request may also wait for the one running. A write that has waited two seconds gets 429 while its tenant's own write is still running, otherwise 503 server_busy. An application API maintenance run waits the same way for slots of its own: one per tenant, maintenance_runs per server. The health check is not counted. One tenant's requests hold at most tenant_transactions (2) of the server's 10 database connections at once and the rest wait their turn, so a tenant's writes waiting on its own locks leave the others to other tenants and key lookups; a server with one tenant can set tenant_transactions=10. A request whose transaction waits more than 5 seconds for a lock gets 503 server_busy. With more than one server, SLOTLOCK_SHARED_LIMITS=on shares the tenant budgets (tenant_*, app_*) through the database, so N servers allow a tenant its rate once, not N times; each server checks its own buckets first, and goes on with them alone if the database cannot be reached. SLOTLOCK_LIMITS changes the limits; behind a proxy, set SLOTLOCK_TRUSTED_PROXY_HEADER to the field it puts the client's address in (CF-Connecting-IP behind Cloudflare) before the server takes traffic, or every client shares the proxy's budget: the server logs a client_address_field_ignored warning when such a field arrives without the setting. Behind two proxies, such as Cloudflare and then kamal-proxy, name the first one's field: the server reads the last address of a list field such as X-Forwarded-For, which the second proxy writes as Cloudflare's. A client can send that field itself, so let nothing reach the server except through the proxy.tenantLimits count them, besides 10,000 resources. A write past one answers 409 hold_limit_reached, reservation_limit_reached, event_limit_reached or coverage_limit_reached; SLOTLOCK_LIMITS changes them (tenant_holds, tenant_reservations, tenant_events, tenant_coverage).slotlock hours set '[{"rrule":"FREQ=WEEKLY;BYDAY=SA","startMinutes":600,"durationMinutes":240}]' --resource vehicle-42
slotlock hours clear --all # back to SLOTLOCK_AVAILABILITY
A rule is rrule, startMinutes and durationMinutes here and in SLOTLOCK_AVAILABILITY. The REST application API spells every field in snake_case, so there it is rrule, start_minutes and duration_minutes. slotlock --help lists every setting.
A resource can also say what a booking on it must satisfy:
slotlock rules set '{"minNoticeMinutes":120,"slotStepMinutes":30,"turnaroundMinutes":30,"enforceHours":true}' --resource vehicle-42
slotlock rules clear --resource vehicle-42
| Rule | A booking made now |
|---|---|
minNoticeMinutes | starts at least this far ahead |
maxAdvanceDays | starts at most this far ahead |
slotStepMinutes | starts on a step from local midnight in the resource's time zone |
stepOffsetMinutes | starts this far past each step (0 to the step less one): with a 30-minute step, 15 starts bookings on :15 and :45 |
bufferBeforeMinutes | keeps this long free before it: its leading buffer, which the database enforces |
turnaroundMinutes | keeps this long free after it: its trailing buffer, which the database enforces |
enforceHours | lies inside the resource's bookable hours |
checkInMinutes | is claimed (checkInReservation) this long after its start, or maintenance releases it |
requireCertain | lies in time every calendar sync recording coverage for the resource has read within a day |
booking_rule_violated with rule in the store, booking_rule_min_notice, _max_advance, _slot_step, _outside_hours or _uncertain to an agent). Under requireCertain, a search (the store's and the tools') needs those syncs' coverage too, read within a day, of the slot and its turnaround, so it offers no slot they leave unproven.slotlock_find_next_available, slotlock_find_available_slots, findNextAvailableFor) offer only slots the rules allow, so an offered slot is one the write accepts.PUT /v1/resources/{resource_id}/booking-rules, in snake_case; the store with setResourceBookingRules.PUT /v1/booking-rules) and for every member of a pool (PUT /v1/pools/{pool}/booking-rules), read back with GET /v1/booking-rules; the store's setBookingRuleDefaults and getBookingRuleDefaults. A resource's rules as they apply (effective_booking_rules, effectiveBookingRules) are the tenant's defaults, overlaid by its pool's, overlaid by its own: a rule set at a narrower level wins. checkInMinutes is a resource's own only. The dashboard's resource page shows which rules a resource inherits, and from where.pool_rules_limit_reached, 409, for one more). Merged rules are read leniently: a pool's stepOffsetMinutes under a resource's shorter step applies modulo that step, and a field that is invalid on its own is ignored (and logged), never read as refusing every booking.With Node.js 22.12+ and PostgreSQL 16 or newer, run each command as npx slotlock after npm install slotlock postgres, or from a clone, built once, as node dist/cli.js (a clone does not put slotlock on your PATH). Use two roles, as Compose does, so two URLs: serve connects as DATABASE_URL, a role that owns nothing and cannot bypass row-level security, and migrate connects as SLOTLOCK_MIGRATE_DATABASE_URL, the schema owner, and grants that role what it needs. serve refuses to start as a superuser or a BYPASSRLS role, which row-level security does not confine, and warns (serving_as_schema_owner) when its role owns the schema.
npm ci && npm run build
export SLOTLOCK_MIGRATE_DATABASE_URL='postgresql:// : @localhost:5432/slotlock' export DATABASE_URL='postgresql://slotlock_app: @localhost:5432/slotlock' export SLOTLOCK_AUTH_TOKEN="$(openssl rand -hex 32)" export SLOTLOCK_CONFIRMATION_SECRET="$(openssl rand -hex 32)" node dist/cli.js migrate node dist/cli.js resource add vehicle-42 --timezone Europe/London node dist/cli.js serve
The slotlock … commands in this README run the same way as node dist/cli.js … (with Compose, docker compose exec slotlock slotlock …).
앞부분만 보여 드려요. 나머지는 저장소에서 읽어 보세요