feat(worker): bulk ingest endpoint (0.0.9-alpha.0)#35
Merged
Conversation
`POST /annotations/bulk` at the canonical worker. Accepts an array of
CreateInput items and one-creates-per-item against the adapter.
Returns a summary with the successful annotations alongside any per-
item errors, so a partial failure does not abort the entire batch.
## API contract
```
POST /annotations/bulk
Authorization: Bearer <member-token>
content-type: application/json
{
"items": [
{ "anchor": { "mode": "route", "path": "/" }, "body": "note 1" },
{ "anchor": { "mode": "route", "path": "/" }, "body": "note 2" }
]
}
```
Response:
```
200 OK
{
"created": [ <Annotation>, <Annotation> ],
"errors": [ { "index": 1, "error": "invalid_item" } ]
}
```
## Constraints
- Member-token only. Reporter (share-link) tokens get 403
(`bulk_member_only`). Bulk insert is an admin / migration operation.
- Volume capped at MAX_BULK_ITEMS = 200 per request. Larger imports
should chunk. Cap protects Worker CPU budget per invocation.
- Sequential per-item creates so adapter audit-log ordering stays
deterministic. Per-row error isolation: one bad item does not taint
the rest of the batch.
## Use cases this unblocks
- Brain-dump import: bulk-insert a batch of notes from a transcript,
spreadsheet, or call-prep doc into the inbox in one request. The
pattern Pivotal used with notes 49-72 via raw SQL becomes an API
every consumer can use.
- Migration: move notes from another system (BugHerd export, Linear
export, etc.) into TEB without per-row POST round-trips.
- Seeding: initialize a fresh tenant (Phase 2 LS A6 pilot client) with
a starter set of notes from the LSD welcome packet.
## Tests
`apps/worker/src/handlers.test.ts` adds 7 new tests:
- Member token creates multiple annotations in one call
- Rejects share-link tokens with 403 `bulk_member_only`
- 400 when body lacks `items` array
- 400 when `items` array is empty (`empty_items`)
- 413 when items exceed `MAX_BULK_ITEMS` cap
(`too_many_items_max_200`)
- Partial-failure: one bad item recorded in `errors`, rest persist
- Inserted batch is queryable via the regular list endpoint
afterward
Full repo: 195 tests across widget + adapter-cloudflare + adapter-http
+ worker, all green. Typecheck + lint clean. Em-dash gate clean.
## Version bumps
Bumps 0.0.7-alpha.0 -> 0.0.9-alpha.0 (skipping 0.0.8 on this branch
because it landed in parallel via PR #34; when #34 merges to main,
the package.json conflict resolves to 0.0.9-alpha.0).
- `@travisbreaks/travisEATSbugs` 0.0.7-alpha.0 -> 0.0.9-alpha.0
- `@travisbreaks/travisEATSbugs-cloudflare` 0.0.7-alpha.0 -> 0.0.9-alpha.0
- `@travisbreaks/travisEATSbugs-http` 0.0.7-alpha.0 -> 0.0.9-alpha.0
Phase 1 of the strategic plan
(second of the OSS uplift releases).
Co-Authored-By: Tadao <tadao@travisfixes.com>
# Conflicts: # packages/adapter-cloudflare/package.json # packages/adapter-http/package.json # packages/widget/package.json
travisbreaks
added a commit
that referenced
this pull request
May 20, 2026
New `apps/mcp-server/` workspace. Ships a working MCP server that exposes feedback annotations as tools so AI agents (Claude Code, Claude Desktop, others) can list, inspect, resolve, and reopen notes against the canonical eats.travisfixes.com worker. BugHerd announced "BugHerd MCP coming soon" in their 2025 wrap-up. TEB ships a working MCP server first as a public credibility marker per the Phase 1 strategic plan. ## Tools shipped (0.0.10) | Tool | Description | |---|---| | `list_annotations` | List with optional path + state filters | | `get_annotation` | Fetch by id | | `resolve_annotation` | Resolve with resolvedPR + optional resolutionNote | | `reopen_annotation` | Clear resolution, flip state to open | Deferred for 0.0.11+: - `bulk_create_annotations` (calls POST /annotations/bulk from 0.0.9) - `triage_annotation` (calls POST /triage; member-only) - `link_pr_to_annotation` (ergonomic resolve + PR link shorthand) ## Configuration Two env vars: - `TEB_API_TOKEN` (required): member token from worker MEMBER_TOKENS - `TEB_API_URL` (optional): defaults to https://eats.travisfixes.com ## Transport stdio. Wires into Claude Code via `claude mcp add teb npx @travisbreaks/travisEATSbugs-mcp`. Claude Desktop config example in the package README. ## Architecture - `src/client.ts`: loads env config, builds the canonical HttpAdapter - `src/tools.ts`: tool defs (JSON Schema) + handlers that delegate to the ApiAdapter contract - `src/index.ts`: MCP server entry point with stdio transport - `src/tools.test.ts`: smoke tests against MemoryAdapter, 12 tests JSON Schema instead of zod to keep the bundle tight; the MCP SDK validates against inputSchema before calling each handler. ## Tests - +12 mcp-server tests (tool defs sanity + 4 handler smoke tests each) - Full repo: 200 tests across widget + adapter-cloudflare + adapter-http + worker + mcp-server, all green - Typecheck + lint clean across 6 workspaces - Em-dash gate clean ## Dependencies added - `@modelcontextprotocol/sdk` ^1.0.4 (the official MCP SDK) - `@travisbreaks/travisEATSbugs-http` workspace dep (used as the canonical client) - `@travisbreaks/travisEATSbugs` workspace dep (types) Note: pnpm reports a zod peer-dep warning (SDK wants 3.25+ or 4.x; repo has 3.22 transitively). Tests pass and tool-call validation works; revisit when bumping zod becomes ergonomic. ## Use cases this unblocks - An agent (e.g. Claude Code running in the Pivotal repo) can call `list_annotations({ state: 'open' })` to surface unresolved notes while you crank, and `resolve_annotation({ id, resolvedPR: 200 })` to close them inline as you ship fixes - Hosts can offer their own per-team agents (e.g. LSD assigning client-feedback tickets) that read TEB via MCP instead of building a custom integration - The MCP MCP-inspector tool can be used to verify any TEB worker deployment by smoke-testing the tools against it ## Versions Stays at 0.0.7-base in package.json (this PR was branched off main which had 0.0.8; when this lands the mcp-server is on 0.0.10 standalone). Widget + adapter packages unchanged on this branch; 0.0.9 (bulk ingest) lives on its own PR #35. Phase 1 of the strategic plan (third of the OSS uplift releases). Co-authored-by: Tadao <tadao@travisfixes.com>
travisbreaks
added a commit
that referenced
this pull request
May 20, 2026
Update the per-project thread state to reflect the full 2026-05-20 strategic sprint: - Phase 0 COMPLETE: PRs #24 (hygiene) + #25 (tenancy ratified) + #26 (per-project memory dir) merged. Branch protection enabled. CI secret configured. CODE MEMORY.md routing updated. Injection log incident 122 appended. - Phase 1 COMPLETE: PRs #34 (0.0.8 bug-button + hint-ribbon config) + #33 (region-screenshot doc + Pivotal reframe) + #35 (0.0.9 bulk ingest worker endpoint) + #36 (0.0.10 TEB MCP server) merged. - Test growth: 175 -> 207 (+32 new across 4 PRs). - Widget canonical: 0.0.10-alpha.0 on main. - Hallucination audits + Dependabot triage results captured for future reference. - Phase 2 entry point (LS A6 multi-tenant scaffolding) documented for next-session pickup. - 6 dependabot PRs still open at EOD: 4 GH Actions safe to merge next session, 2 npm groups recommended HOLD per triage. Co-authored-by: Tadao <tadao@travisfixes.com>
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
POST /annotations/bulkat the canonical worker. Bulk-insert an array ofCreateInputitems, one-create-per-item against the adapter, with per-item error isolation so a partial failure does not abort the batch.API contract
Body:
{ "items": [ { "anchor": { "mode": "route", "path": "/" }, "body": "note 1" }, { "anchor": { "mode": "route", "path": "/" }, "body": "note 2" } ] }Response:
{ "created": [ {...}, {...} ], "errors": [ { "index": 1, "error": "invalid_item" } ] }Constraints
bulk_member_only.MAX_BULK_ITEMS = 200per request (413 over).Use cases unblocked
Tests
apps/worker/src/handlers.test.tsadds 7 new tests:Full repo: 195 tests green. Typecheck + lint clean. Em-dash gate clean.
Versions
Skips 0.0.8 on this branch because it landed in parallel via PR #34; when #34 merges to main, the package.json conflict resolves to keep
0.0.9-alpha.0.@travisbreaks/travisEATSbugs0.0.7-alpha.0 -> 0.0.9-alpha.0@travisbreaks/travisEATSbugs-cloudflare0.0.7-alpha.0 -> 0.0.9-alpha.0@travisbreaks/travisEATSbugs-http0.0.7-alpha.0 -> 0.0.9-alpha.0Test plan
Phase 1 of the strategic plan (second of the OSS uplift releases).
Co-Authored-By: Tadao tadao@travisfixes.com