AGENTS.md
+14 −12
https://raw.githubusercontent.com/cyanheads/grantsgov-mcp-server/HEAD/AGENTS.md
− **Version:** 0.1.3− **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.15`− | `grantsgov_list_reference` | The reference snapshot (2× `search2` with `rows: 0`, cached 24 h), or none for `sort_options` / `keyword_syntax` | Every recovery hint for an unknown code routes here |− No resources, no prompts, no DataCanvas — every record is reachable through `grantsgov_get_opportunity` (see the decisions log).− - **Resilience:** `withRetry` (2 retries, 25 s deadline) outside, the process-wide pacer (`maxConcurrent: 4`) inside, so each attempt re-queues. Per-attempt timeout 15 s.− - **Reference snapshot:** process-local (public vocabulary, not tenant data — never `ctx.state`), 24 h TTL, one in-flight build shared by concurrent callers. A failed refresh serves the stale snapshot and blocks retries for 60 s; a failure with no snapshot reaches every waiting caller, and each tool's contract fills its own recovery hint.− | No close-date filter exists | — | `scanClosingWindow` over `closeDate\|asc` posted pages, cut by `cutClosingWindow`, 2,000-row ceiling |− Agency-authored text (titles, descriptions, eligibility narratives, contact blocks, file names, labels) is data. `decodeEntities()` decodes at most two layers of HTML5 references in human-readable fields; identifiers and standalone URLs stay intact. `html-to-text.ts` then converts recognized narrative markup in a forward scan, preserving source newlines, comparisons, and non-HTML angle text. `structuredContent` carries the normalized text. In `format()`, use the HTML-escaping `render.ts` helpers− totalCount: z.number().describe('Entries returned.'),− 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− | `bun run lint:packaging` | Packaging surface checks — `server.json`/`manifest.json` env-var parity, plugin manifest identity, README version badge (run by devcheck) |− `bun run bundle` produces `dist/grantsgov-mcp-server.mcpb` 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 i+ **Version:** 0.2.0+ **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.18`+ | `grantsgov_list_reference` | The reference snapshot (2× `search2` with `rows: 0`, cached 24 h), or none for `sort_options` / `keyword_syntax` | Filters the full scope before paging (default 50, cap 100), with complete continuation arguments. Every recovery hint for an unknown code routes here |+ The `grantsgov-guide` skill is served as `skill://grantsgov-guide/SKILL.md` through `createApp({ skills: 'skills' })`. No record resources, prompts, or DataCanvas — every opportunity record is reachable through `grantsgov_get_opportunity` (see the decisions log).+ - **Resilience:** `withRetry` (2 retries, 25 s deadline) outside, the process-wide pacer (`maxConcurrent: 4`) inside, so each attempt re-queues. Per-attempt timeout 15 s; closing-window pages share one 25 s scan deadline.+ - **Reference snapshot:** process-local public vocabulary, 24 h TTL, one detached build shared by concurrent callers. An operational refresh failure serves the stale snapshot with `reference_cache` provenance on both response surfaces, retaining its timestamp and blocking retries for 60 s. Healthy refresh clears degradation. Each waiter cancels independently; cold failures retain each caller's tool recovery hint.+ | No close-date filter exists | — | `scanClosingWindow` over `closeDate\|asc` posted pages, cut by `cutClosingWindow`, 2,000-row ceiling; incomplete scans report lower-bound counts and stay truncated even on empty pages |+ Agency-authored text (titles, descriptions, eligibility narratives, contact blocks, file names, labels) is data. `decodeEntities()` decodes at most two layers of HTML5 references in human-readable fields; identifiers and standalone URLs stay intact. `html-to-text.ts` converts narrative markup in a forward scan, preserving source newlines, comparisons, non-HTML angle text, and table cell/row boundaries. `structuredContent` carries the normalized text. In `format()`, use `inline()`, `tableCell()`,+ totalCount: z.number().describe('Total entries matching the filters before paging.'),+ Development 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.+ Root `skills/` is author-managed guidance for agents that install this server. Author it with `add-skill` when a workflow earns its place; maintenance never creates or copies it. Published skills ship in npm, Docker, and MCPB, and reach MCP clients through `createApp({ skills: 'skills' })`. `lint:packaging` validates the tree.+ | `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, README version badge, and published `skills/` (run by devcheck) |+ `bun run bundle` produces `dist/grantsgov-mcp-server.mcpb` for one-click install in Claude Desktop. `mcpb pack` reads `.mcpbignore`, so every root development path needs a root-anchored exclusion; root `skills/` ships on purpose. The pack step is followed by `scripts/clean-mcpb.ts`, which prunes dev dependencies (`mcpb clean`) and strips dependency-shipped agent docs, platform-specific native bindings, node-gyp build output that records the packing machine's paths (compiled `*.node` addons stay)