{
  "markdown": "# pocketnook MCP server\n\nDeploy a repository to a private URL without leaving the agent that wrote it.\n\n```\n> deploy this somewhere private\n\n  owner/studio-board is deployed: https://pocketnook.dev/s/nook-…/\n  It is private — only you can open it until you share it. (static, 42 files)\n```\n\nThe deploy step belongs inside the tool where the software is being written,\nwhich is both the distribution and the product.\n\n## Install\n\n**1. Get a token.** Sign in at [pocketnook.dev](https://pocketnook.dev), open\n**Agent access** on the home page, and create one. It is shown once.\n\n**2. Add the server.**\n\n```sh\nclaude mcp add pocketnook \\\n  --env POCKETNOOK_TOKEN=pnka_… \\\n  -- npx -y @pocketnook/mcp\n```\n\nOr, from a checkout of this repository, point at the entry directly:\n\n```sh\nclaude mcp add pocketnook \\\n  --env POCKETNOOK_TOKEN=pnka_… \\\n  -- node /absolute/path/to/apps/mcp/bin/pocketnook-mcp.mjs\n```\n\nThe server has no dependencies and runs on Node 22.18 or newer — the floor\n`package.json` declares, so an older Node warns rather than silently half-works.\nAny MCP client works; the commands above are Claude Code's.\n\n**3. Optionally add the skill**, which teaches the agent the things the tool\ndescriptions cannot say on their own — that a deploy builds what is pushed\nrather than what is on disk, and that sharing does not notify anyone:\n\n```sh\ncp -r skills/pocketnook ~/.claude/skills/\n```\n\n### Or install both at once, as a Claude Code plugin\n\nThis repository is also a Claude Code plugin: the skill above and the MCP\nserver, wired together, with the token read from your environment.\n\n```sh\nclaude plugin marketplace add shotintoeternity/pocketnook-mcp\nclaude plugin install pocketnook@pocketnook-mcp\n```\n\nThen check it: `claude plugin details pocketnook@pocketnook-mcp` should report\none skill and one MCP server.\n\nThat check is worth running, because the obvious one does not cover it.\n`claude plugin validate` reads `plugin.json` and the skills, and **does not\nread `.mcp.json` at all** — it reports `✔ Validation passed` on a plugin whose\n`.mcp.json` is not even parseable JSON. `details` is what counts the\ncomponents, and it reports `MCP servers (0)` for exactly that plugin.\n\nThe marketplace manifest and the plugin manifest are both here, in one\nrepository, because a plugin-only repository is not installable: `plugin\nmarketplace add` fails with *Marketplace file not found*, and `plugin install`\nanswers *not found in any configured marketplace*. `.claude-plugin/marketplace.json`\nlists this repository's root as its one plugin.\n\n## Configuration\n\n| Variable | Meaning |\n|---|---|\n| `POCKETNOOK_TOKEN` | An agent token. Required. |\n| `POCKETNOOK_URL` | Base URL, if not `https://pocketnook.dev`. |\n\n## Tools\n\n| Tool | What it does |\n|---|---|\n| `deploy` | Deploy a GitHub repository — the tip of its default branch — and return its private URL. |\n| `deploy_directory` | Deploy a directory from this machine as it is on disk. No repository needed. |\n| `list_nooks` | Everything this account has deployed, with URLs and status. |\n| `nook_logs` | Build output — the first thing to read when a deploy went wrong. |\n| `stop_nook` | Take a nook offline, keeping its URL, grants, and secrets. |\n\n### The two deploys, and why they are two tools\n\n`deploy` builds what GitHub has. `deploy_directory` uploads what is on the disk,\nincluding uncommitted work, and needs no repository at all. It exists because\nthe person an agent is writing for may never make a push.\n\nThey are not merged into one tool with a heuristic, because the heuristic has\ntwo silent failure modes: guess towards the repository and an afternoon of work\nis quietly not deployed; guess towards the directory and half-finished local\nedits go live. Neither announces itself, which is what makes the guess\nunaffordable: a wrong answer that stays quiet is worse than a question.\n\n### What is deliberately absent\n\nThere is no `delete` tool. Deleting a nook destroys its grants and secrets and\ncannot be undone, so it stays a decision made on a page that can say so; `stop`\nis the recoverable version of the same intent. There is nothing for managing\ntokens either — the gateway refuses a token on `/api/tokens` entirely, so an\nagent cannot extend its own credential or revoke the one being used to stop it.\n\n**`share_nook` and `set_nook_secret` were removed on 2026-08-01.** They shipped\nhere on 2026-07-27 and then a design decision made both routes session-only —\n*a token deploys, a session administers.* They did not\nbecome ill-advised, they became impossible: `sessionOnly` in the gateway answers\nany bearer token with 401. A tool that can never succeed is worse than no tool,\nbecause an agent reads the refusal as transient and retries it. Setting a\nsecret, sharing a nook and deleting one all happen in the browser now, and the\nserver's MCP `instructions` say so, so a model sends its person there rather\nthan inventing a workaround such as committing the secret into the project.\n\n## What the token can and cannot do\n\nAn agent token acts as the account that minted it, on that account's own nooks.\nThree limits are enforced by pocketnook's gateway, and tested there — they are\nproperties of the server, not of this client, so a modified copy of this code\ncannot widen them:\n\n- **It cannot mint or revoke a token.** Only a browser session can, so a leaked\n  token cannot renew itself, and revoking always has somewhere to happen from.\n- **It carries no email or GitHub username claim.** Access to someone else's\n  nook is granted to a username or a verified email domain, and a token holds\n  neither — so it can act as an owner but can never become a viewer.\n- **It cannot open a nook.** `/s/:id/` reads the session cookie and nothing\n  else. A token is one more way to deploy and no new way to read.\n\nTokens are stored as a SHA-256 hash, expire after 90 days, and can be revoked\nfrom the same panel that created them.\n\n## Known limits\n\n- **Builds are synchronous.** A deploy holds the request until the build\n  finishes, and this client waits up to 15 minutes. Clients apply their own tool\n  timeout on top of that; if a build outlasts it, the build still completes —\n  check `list_nooks` or pocketnook.dev/home rather than deploying again.\n- **A disconnecting client cancels a build.** Same root cause: there is no\n  queue, so the build lives in the request.\n- **Root-relative assets.** A nook is served under `/s/:id/`, so an app that\n  requests `/logo.png` escapes its own prefix. Apps that use relative paths (for\n  example Vite's `base: './'`) are unaffected.\n- **`deploy_directory` needs `tar` on the PATH**, and refuses a directory that\n  contains your home directory — packing `~` would upload SSH keys and cloud\n  credentials along with the project. Uploads are capped at 32 MB by the\n  gateway; `node_modules`, `.git` and build caches are left out.\n- **A build log is somebody else's output.** Control characters are stripped\n  before it reaches the agent, and it arrives inside `--- begin build output ---`\n  markers that say whose text it is. That is a mitigation, not a fix: an\n  instruction written into a build log is ordinary text and no escaping removes\n  it. The markers give the model the context to discount it.\n\n## Development\n\n```sh\nnpm test          # node --test, no dependencies\n```\n\nTo drive the protocol by hand:\n\n```sh\nprintf '%s\\n' '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/list\"}' | node bin/pocketnook-mcp.mjs\n```\n",
  "bytes": 7425,
  "sha": "00589386e94d34cb035f4ae0d84a20c182aee4d3e2d13136a413658c7a15df62",
  "repo_slug": "shotintoeternity/pocketnook-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_shotintoeternity_pocketnook_cc54c236/readme"
}