AGENTS.md
+41 −19
https://raw.githubusercontent.com/cyanheads/smithsonian-mcp-server/HEAD/AGENTS.md
− **Version:** 0.3.9− **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.15`− **MCP SDK:** `@modelcontextprotocol/server` ^2.3.1− rows: z.number().int().min(1).max(100).default(20).describe('Page size (max 100).'),− This server declares `sessionMode: 'stateless'` and no `teardown` — `initSmithsonianService` allocates nothing beyond the framework-owned `StorageService` handle it is given, so there is nothing to release.− server-config.ts # SMITHSONIAN_API_KEY, SMITHSONIAN_BASE_URL, SMITHSONIAN_TERMS_CACHE_TTL_SECONDS− smithsonian-service.ts # Smithsonian API client (init/accessor pattern)− types.ts # Domain types (ObjectSummary, FullObject, ImageItem)− tools/definitions/− smithsonian-search-objects.tool.ts # smithsonian_search_objects− smithsonian-list-terms.tool.ts # smithsonian_list_terms− smithsonian-get-object.tool.ts # smithsonian_get_object− smithsonian-get-media.tool.ts # smithsonian_get_media− smithsonian-browse-category.tool.ts # smithsonian_browse_category− smithsonian-find-related.tool.ts # smithsonian_find_related− Skills are modular instructions in `framework-skills/` at the project root. Read them directly when a task matches — e.g., `framework-skills/add-tool/SKILL.md` when adding a tool. `bun run list-skills` prints the full registry. The directory is deliberately not `skills/`: Claude Code and Codex auto-load a plugin's root `skills/`, so a server that ships `.claude-plugin/` or `.codex-plugin/` would hand these development skills to every agent that installs it. Keep `skills/` free for skills meant f− **Agent skill directory:** Copy skills into the directory your agent discovers (Claude Code: `.claude/skills/`, others: equivalent). Skills then load as context without referencing `framework-skills/` paths. After framework updates, run the `maintenance` skill — Phase B re-syncs the agent directory.− | `bun run lint:packaging` | Packaging surface checks — `server.json`/`manifest.json` env-var parity (run by devcheck) |− `npm run bundle` produces a `.mcpb` extension bundle for one-click install in Claude Desktop. The pack step is followed by `scripts/clean-mcpb.ts`, which prunes dev dependencies (`mcpb clean`) and strips two classes of `node_modules/**` content that root-anchored `.mcpbignore` patterns cannot reach: dependency-shipped agent docs (`framework-skills/`, `skills/`, `.claude/`, `.agents/`, `SKILL.md`) and platform-specific native bindings, which would otherwise lock the bundle to the platform it was + **Version:** 0.4.0+ **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.18`+ **MCP SDK:** `@modelcontextprotocol/server` ^2.4.0+ rows: z.number().int().min(1).max(1000).default(20).describe('Page size (max 1000).'),+ This server declares `sessionMode: 'stateless'` and a `teardown` that stops the Open Access mirror's refresh child process and closes its store (`setup()` opens the mirror only when `SMITHSONIAN_MIRROR_PATH` is set; without one `teardown` is a no-op). `initSmithsonianService` also builds the per-instance response cache, an in-process `Map` that holds no handle needing release.+ server-config.ts # SMITHSONIAN_API_KEY, _BASE_URL, _TERMS/_SEARCH/_CONTENT_CACHE_TTL_SECONDS, _CLAMP_LIMITS, _MIRROR_PATH, _MIRROR_REFRESH_CRON+ smithsonian-service.ts # Smithsonian API client (init/accessor pattern); reads through the cache and the mirror+ response-cache.ts # Per-instance LRU response cache (64 MiB, UTF-8 bytes), shared concurrent loads+ oa-mirror.ts # Open Access mirror store: schema, codec, facet index, reads (never VACUUM)+ oa-ingest.ts # Open Access bucket ingest for the mirror+ types.ts # Domain types (ObjectSummary, FullObject, ImageItem, NonImageMedia)+ mirror/+ cli.ts # mirror init | refresh | status (bun run mirror:*, runs from dist/)+ server-mirror.ts # Opens the mirror at startup; schedules the HTTP refresh child process+ tools/+ page-size.ts # Page-size caps, clamp, and notice (SMITHSONIAN_CLAMP_LIMITS)+ provenance.ts # sources / mirror_snapshot enrichment, mirror-order notice+ definitions/+ smithsonian-search-objects.tool.ts # smithsonian_search_objects+ smithsonian-list-terms.tool.ts # smithsonian_list_terms+ smithsonian-get-object.tool.ts # smithsonian_get_object+ smithsonian-get-media.tool.ts # smithsonian_get_media+ smithsonian-browse-category.tool.ts # smithsonian_browse_category+ smithsonian-find-related.tool.ts # smithsonian_find_related+ skills/+ smithsonian-guide/SKILL.md # Published agent skill, served as skill://smithsonian-guide/SKILL.md+ Two skill trees live at the project root, written for different readers:+ | Tree | For | Written by |+ |:-----|:----|:-----------|+ | `framework-skills/` | The agent developing this server — framework skills (`metadata.audience: external`) plus any development-time skills of the server's own | `init` and the `maintenance` sync (framework skills); you (your own) |+ | `skills/` | The agents that install the server and call its tools — tool chains, identifier sources, gates | You, deliberately, with the `add-skill` skill. Absent by default; usually none is needed |+ Development skills are modular instructions. Read them directly when a task matches — e.g., `framework-skills/add-tool/SKILL.md` when adding a tool. `bun run list-skills` prints the full registry. Their directory is deliberately not `skills/`: Claude Code and Codex auto-load a plugin's root `skills/`, so a server that ships `.claude-plugin/` or `.codex-plugin/` would hand them to every agent that installs it.+ This server publishes `skills/smithsonian-guide/`, and `createApp({ skills: 'skills' })` in `src/index.ts` serves it. A published skill in root `skills/` reaches plugin installs and the `.mcpb` bundle as-is, ships in the npm package and the Docker image, and reaches MCP clients when the server opts in with `createApp({ skills: 'skills' })`. `lint:packaging` validates the tree.+ **Agent skill directory:** Copy `framework-skills/` into the directory your agent discovers (Claude Code: `.claude/skills/`, others: equivalent). Skills then load as context without referencing `framework-skills/` paths. After framework updates, run the `maintenance` skill — Phase B re-syncs the agent directory.+ | `add-skill` | Author a skill the server publishes in root `skills/` for the agents that use it — when one earns its place, structure, validation, delivery |+ | `bun run lint:packaging` | Packaging surface checks — `server.json`/`manifest.json` env-var parity, `.mcpbignore` coverage, plugin manifests, the published `skills/` tree (run by devcheck) |+ | `bun run mirror:init` / `mirror:refresh` / `mirror:status` | Build, refresh, or inspect the optional Open Access mirror at `SMITHSONIAN_MIRROR_PATH` (runs `dist/mirror/cli.js`, so build first) |+ `npm run bundle` produces a `.mcpb` extension bundle for one-click install in Claude Desktop. `mcpb pack` reads `.mcpbignore`, not `.gitignore`, so every root path the bundle must not ship — source, tests, docs, caches, logs, agent docs, plugin manifests, gitignored local files — needs a root-anchored line there (`/docs/`, never `docs/`, which also strips `node_modules/*/docs/`); `lint:packaging` names each missing or unanchored line. Root `skills/` ships on purpose. The pack step is followed by+ - [ ] `plugin.json` + `mcp.json` (Agent Plugins 1.0.0 — read by Codex, Cursor, GitHub Copilot, VS Code, Kiro) populated — `plugin.json` `name` = the unscoped repo name (lowercase `a-z`, `0-9`, `-`, `.` only); `version`, `description`, `author`, `homepage`, `repository`, `license`, `keywords` from `package.json`; no other top-level field, `extensions` included. `mcp.json` holds one `"type": "stdio"` entry keyed by the unscoped name, `npx -y <full package name>`, and the same fixed `env` as `.code+ - [ ] Any new root dev path has a root-anchored line in `.mcpbignore`; `bun run bundle` and `lint:packaging` pass