@jaypie/mcp 0.8.162 → 0.8.164

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/assets.js CHANGED
@@ -55,11 +55,11 @@ function getMcpAssetPaths() {
55
55
  */
56
56
  function getMcpBuildInfo() {
57
57
  return {
58
- commit: "09240f3e"
58
+ commit: "9c56f9fc"
59
59
  ,
60
- version: "0.8.162"
60
+ version: "0.8.164"
61
61
  ,
62
- versionString: "@jaypie/mcp@0.8.162#09240f3e"
62
+ versionString: "@jaypie/mcp@0.8.164#9c56f9fc"
63
63
  ,
64
64
  };
65
65
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jaypie/mcp",
3
- "version": "0.8.162",
3
+ "version": "0.8.164",
4
4
  "description": "Jaypie MCP",
5
5
  "repository": {
6
6
  "type": "git",
@@ -0,0 +1,11 @@
1
+ ---
2
+ version: 1.2.103
3
+ date: 2026-09-19
4
+ summary: Pulls @jaypie/llm 1.3.44
5
+ ---
6
+
7
+ ## Changes
8
+
9
+ - **`@jaypie/llm` 1.3.44**: `Llm.ocr` extracts documents to per-page markdown
10
+ over Mistral OCR or the new `llamacloud` provider (LlamaParse), behind one
11
+ request and response shape with fallback across engines.
@@ -0,0 +1,120 @@
1
+ ---
2
+ version: 1.3.44
3
+ date: 2026-09-19
4
+ summary: "Llm.ocr extracts documents to per-page markdown over Mistral OCR or LlamaParse behind one shape"
5
+ ---
6
+
7
+ ## Changes
8
+
9
+ ### New Features
10
+
11
+ - `Llm.ocr(document, options?)` is a fifth entry point: a document in,
12
+ per-page markdown out. Static and instance forms mirror `question`,
13
+ including `model` array sugar, `fallback`, `retry`, and `signal`. The
14
+ document (an `https://` URL, a `data:` URI, an S3 key, a local path, or the
15
+ `{ file }` / `{ image }` objects `operate()` accepts) is resolved once before
16
+ the fallback chain runs.
17
+ - New provider `llamacloud` serves LlamaParse over the LlamaCloud Parse API
18
+ v2 with `LLAMA_CLOUD_API_KEY` and match words `llamacloud`, `llamaindex`,
19
+ and `llamaparse`. A parse is a job: submitted by `source_url` or multipart
20
+ upload, polled from one second backing off to five, then fetched. It
21
+ implements `ocr` only; `send` throws `NotImplementedError`. The client is
22
+ `fetch` against four routes; no SDK dependency is taken.
23
+ - The LlamaParse **tier is the model id**: `MODEL.LLAMAPARSE.FAST`,
24
+ `COST_EFFECTIVE`, `AGENTIC` (the provider default), and `AGENTIC_PLUS`.
25
+ A chain such as `[MODEL.MISTRAL.OCR, MODEL.LLAMAPARSE.COST_EFFECTIVE]`
26
+ therefore reads as a plain model list and routes through
27
+ `determineModelProvider`.
28
+ - The API version is pinned per tier in `PROVIDER.LLAMACLOUD.VERSION`; each
29
+ tier accepts its own dated versions and rejects the others (verified live
30
+ 2026-09-19). `providerOptions.version` overrides it per call, and the
31
+ response `model` is `<tier id>@<version>`.
32
+ - Common shape: `markdown`, 1-indexed `pages[]` with `header`, `footer`,
33
+ `images`, `success`/`error`, and the vendor page at `raw`; `images[]`;
34
+ `usage` with `pages`, LlamaParse `credits`, and `cost`; `responses[]`; and
35
+ the `provider`/`model`/`fallbackAttempts`/`fallbackUsed` fields `operate`
36
+ carries. Options: `pages` (`[1, 3]` or `"1,3,5-10"`), `tables`
37
+ (`"markdown"` or `"html"`), `images` (download extracted images as `data:`
38
+ URIs), `timeout` (asynchronous job ceiling, default ten minutes), and
39
+ `providerOptions` spread last onto the vendor request.
40
+ - `PAGE_COST` prices document-extraction engines in USD per 1,000 pages,
41
+ keyed by literal id: `mistral-ocr-4-1` at $4 and the four LlamaParse tiers
42
+ at $1.25, $3.75, $12.50, and $56.25 (credits at
43
+ `PROVIDER.LLAMACLOUD.CREDIT_COST`, $1.25 per 1,000). A LlamaParse job's
44
+ recorded credits win over the per-page estimate.
45
+ - `DEFAULT.OCR` names the engine `Llm.ocr` uses when neither a provider nor a
46
+ model is given: Mistral OCR, one synchronous call and the cheapest markdown
47
+ tier on offer.
48
+ - **OCR emulation on chat models**, as `question` emulates: a provider with
49
+ `operate` but no `ocr` transcribes through `src/ocr/OcrEmulator.ts`, so a
50
+ chain such as `[MODEL.MISTRAL.OCR, MODEL.HAIKU]` falls from a native engine
51
+ to any model that accepts files. Each page rides alone in one structured
52
+ `operate()` call (a PDF is trimmed to one page per request, so the model
53
+ never counts or numbers pages), under a fixed `{ confidence, markdown,
54
+ notes }` schema and a verbatim-transcription prompt with `[UNCLEAR: …]` and
55
+ `[ELEMENT: …]` markers. A page scored under 0.4 is transcribed once more
56
+ and the higher score wins. `concurrency` (default 5) bounds pages in
57
+ flight; the first failure aborts the rest and rethrows so the next engine
58
+ starts clean, and unreadable content throws `InternalError` to the same
59
+ end. The response carries `emulated: true`, `pages[].confidence`,
60
+ `usage.tokens`, and `usage.cost` priced from `COST` through the new
61
+ `tokenCost` helper. `user` forwards to the calls. A provider with neither
62
+ (`typesafe`) fails its attempt and the chain moves on.
63
+ - `LlmOcrResponse.emulated` is present on every response (`false` from a
64
+ native engine), matching `LlmQuestionResponse`.
65
+
66
+ ### Changed
67
+
68
+ - `MistralProvider.ocr()` takes the common `(document, options)` signature
69
+ and returns the common shape. The provider-specific `{ markdown, model,
70
+ pages, raw }` return shipped in 1.3.43 and is gone: `raw` is
71
+ `responses[0]`, and the 0-indexed `pages[].index` is the 1-indexed
72
+ `pages[].page` with the vendor page at `pages[].raw`. `MistralOcrPage` and
73
+ `MistralOcrResponse` are no longer exported. `OcrRequest` widens to the full
74
+ Mistral `OCRRequest` field set.
75
+ - Client failures on Mistral OCR classify through the chat adapter into the
76
+ typed `LlmError` family, and both engines share one retry loop
77
+ (`src/ocr/runOcrAttempts.ts`), so `retry` and `signal` mean the same thing
78
+ on each. A LlamaParse job that reports `FAILED` throws
79
+ `LlmUnrecoverableError` with the API's message, `CANCELLED` throws
80
+ `LlmAbortError`, and a job that outlives `timeout` throws
81
+ `LlmTransientError` so a chain can try the next engine.
82
+ - `loadFileData` and `getExtensionForMimeType` are exported from the upload
83
+ helpers for reuse; `LlmProvider` gains an optional `ocr`.
84
+ - `extractPdfPages` throws `BadRequestError` on an out-of-range page where it
85
+ threw a vanilla `Error`.
86
+
87
+ ### Internal
88
+
89
+ - `MODEL.LLAMAPARSE.*` join `MODEL.MISTRAL.OCR` in `MATRIX_EXCLUDE`: a
90
+ document-extraction engine implements neither `operate()` nor `send()`, so
91
+ every capability cell would fail by construction. They are exercised by
92
+ `tsx test/ocr.ts` (`npm run test:llm:ocr`) and the provider hot specs.
93
+ - Both CI workflows pass `LLAMA_CLOUD_API_KEY` from the
94
+ `CICD_LLAMA_CLOUD_API_KEY` org secret; the LlamaCloud hot spec skips until
95
+ the secret exists.
96
+
97
+ ## Testing
98
+
99
+ - Live, 2026-09-19 (`npm run test:llm:ocr`): `page.pdf` and `page.png`
100
+ through Mistral OCR and all four LlamaParse tiers, every run reading the
101
+ fixture text, plus a chain falling from an unknown tier to Mistral. 11 of 11
102
+ passed. Mistral answered in about one second at $0.004 per page; LlamaParse
103
+ completed in 3 to 5 polls (6 to 15 seconds) at 1, 3, 10, and 45 credits per
104
+ page by tier.
105
+ - Live, 2026-09-19, with emulation: the same fixtures through Haiku and
106
+ Luna, plus a chain falling from an unknown tier into Haiku. 15 of 15
107
+ passed. Haiku transcribed a page in 1.5 to 2.5 seconds for $0.0015 to
108
+ $0.0026 (1,200 to 2,200 tokens) at 0.95 confidence; Luna in 1 to 3 seconds
109
+ for $0.0002 to $0.0003 at 0.98 to 0.99. Both marked the fixture's rule as
110
+ `---` or `[ELEMENT: decorative horizontal line]`; Luna read the PDF's
111
+ heading last, where every other engine read it first.
112
+ - New unit coverage for page-selection parsing, document resolution (URL,
113
+ data URI, S3, disk, inline data, PDF trimming), the shared retry loop, the
114
+ LlamaCloud client's routes and status-to-error mapping, the provider's
115
+ submit/poll/fetch cycle (including fast-tier text, failed pages, image
116
+ download, per-tier version, timeout, and abort), the reworked Mistral OCR
117
+ mapping, `Llm.ocr` routing and fallback (native to emulated and back),
118
+ the emulator (page splitting, selection, image and URL input, low-confidence
119
+ re-transcription, concurrency cap, first-failure abort, caller abort, and
120
+ fetch classification), `tokenCost`, and provider routing for every new id.
@@ -0,0 +1,14 @@
1
+ ---
2
+ version: 1.3.45
3
+ date: 2026-09-19
4
+ summary: Settle a response the provider cut short as incomplete with the provider's reason
5
+ ---
6
+
7
+ ## Changes
8
+
9
+ - `operate()` settles `status: "incomplete"` with `error.reason: "incomplete"` (502) when the provider stops the model before it finishes; the partial text stays in `content` and `error.detail` names the provider's reason
10
+ - Every adapter reports it: OpenAI, xAI, and Meta from `status: "incomplete"` plus `incomplete_details.reason` (`max_output_tokens`, `content_filter`); Anthropic from `stop_reason` `max_tokens` or `refusal`; Google from `finishReason` `MAX_TOKENS` or a safety finish; Bedrock from `max_tokens` or a guardrail stop; Fireworks, Mistral, and OpenRouter from `finish_reason` `length` or `content_filter`
11
+ - Previously the loop completed with the truncated text, and a structured request surfaced as prose that failed the format contract ("OCR emulation did not return JSON")
12
+ - `stream()` emits an error chunk from the same stop event on every provider and settles the exchange incomplete; usage from that event still tallies
13
+ - `Llm.ocr` emulation wraps a settled error body in `LlmUnrecoverableError` so a fallback chain logs the provider's reason and moves to the next engine
14
+ - New `LlmResponseErrorReason.Incomplete` and `ParsedResponse.incompleteReason` for adapters
@@ -0,0 +1,17 @@
1
+ ---
2
+ version: 0.8.163
3
+ date: 2026-09-19
4
+ summary: Document Llm.ocr and the LlamaCloud provider in the llm skill
5
+ ---
6
+
7
+ ## Changes
8
+
9
+ ### Documentation
10
+
11
+ - `skills/llm.md` gains an "OCR" section: the document forms `Llm.ocr`
12
+ accepts, the page and usage shape, `pages`/`tables`/`images`/`timeout`/
13
+ `providerOptions`, per-tier LlamaParse versions, and fallback across
14
+ engines.
15
+ - The providers table carries a `llamacloud` row, the model constants name
16
+ `MODEL.LLAMAPARSE.*` and `PAGE_COST`, and the environment block carries
17
+ `LLAMA_CLOUD_API_KEY`.
@@ -0,0 +1,10 @@
1
+ ---
2
+ version: 0.8.164
3
+ date: 2026-09-19
4
+ summary: Document the incomplete loop stop in the llm skill
5
+ ---
6
+
7
+ ## Changes
8
+
9
+ - The llm skill's loop stops table gains `incomplete` (502): the provider cut the model off before it finished; `content` holds the partial text and `error.detail` names the provider's reason
10
+ - Add release notes for `@jaypie/llm` 1.3.45
@@ -0,0 +1,11 @@
1
+ ---
2
+ version: 1.2.76
3
+ date: 2026-09-19
4
+ summary: Mock Llm.ocr and the LlamaCloud provider
5
+ ---
6
+
7
+ ## Changes
8
+
9
+ - `Llm.ocr` (static, instance, and on the inner provider) resolves a mock OCR
10
+ response with one page of `_MOCK_OCR_MARKDOWN`.
11
+ - New mocks: `LlamaCloudProvider` and `LlamaCloudClient`.
package/skills/llm.md CHANGED
@@ -42,6 +42,7 @@ the alias rather than the id it currently resolves to. Read the id off
42
42
  | Meta | "muse" (plus the exact name `meta` and a `meta:` prefix) | `MODEL.MUSE_SPARK` |
43
43
  | Bedrock | "amazon.nova", "anthropic.claude", "meta.llama", "deepseek.", "google.gemma", "moonshotai.", "openai.gpt-oss", … | `MODEL.NOVA_PRO` |
44
44
  | TypeSafe | "jev", "typesafe" | `MODEL.JEV` |
45
+ | LlamaCloud | "llamacloud", "llamaindex", "llamaparse" | `MODEL.LLAMAPARSE.AGENTIC` |
45
46
 
46
47
  The provider name for Gemini models is `"google"` — `"gemini"` is accepted as a deprecated alias.
47
48
 
@@ -51,10 +52,12 @@ Mistral's family names mostly do not contain the substring "mistral" (`ministral
51
52
 
52
53
  TypeSafe serves System One models (Jev), which answer typed questions and generate no text. The provider implements `question()` only: `operate()`, `send()`, and `stream()` throw. See [Questions](#questions-jev-shape).
53
54
 
55
+ LlamaCloud serves LlamaParse, which extracts documents and generates no text. The provider implements `ocr()` only. The parse tier is the model id (`MODEL.LLAMAPARSE.FAST`, `COST_EFFECTIVE`, `AGENTIC`, `AGENTIC_PLUS`). See [OCR](#ocr).
56
+
54
57
  ### Model Constants
55
58
 
56
59
  - **`PROVIDER.<name>.DEFAULT`** — the single default model per provider (above), used when no `model` is given.
57
- - **`LLM.MODEL.*`** — the named model catalog (e.g. `MODEL.SONNET`, `MODEL.ASTRA`, `MODEL.SOL`, `MODEL.GEMINI_FLASH`, `MODEL.GROK`, `MODEL.MUSE_SPARK`, `MODEL.MUSE_SPARK_CONTRIBUTOR`, `MODEL.NOVA_PRO`, `MODEL.NOVA_LITE`), plus three nested subtrees: `MODEL.FIREWORKS.*` for Fireworks serverless models (`DEEPSEEK`, `GLM`, `GPT_OSS`, `INKLING`, `KIMI`, `MINIMAX`, `NEMOTRON`, `QWEN`), `MODEL.MISTRAL.*` (`LARGE`, `OCR`, `SMALL`), and `MODEL.OPENROUTER.*` for provider-prefixed routes (`GLM`, `LUNA`, `SONNET`). Pick specific models from here. `MODEL.MISTRAL.OCR` serves `POST /v1/ocr` rather than chat completions: it is priced per page, carries no `COST` entry, and is reached through `MistralProvider.ocr()`. Amazon's Nova models are first-class ids served over Bedrock; Bedrock's third-party routes are not catalogued — pass the literal id (e.g. `us.anthropic.claude-sonnet-4-6`) and `determineModelProvider` resolves it to `bedrock`.
60
+ - **`LLM.MODEL.*`** — the named model catalog (e.g. `MODEL.SONNET`, `MODEL.ASTRA`, `MODEL.SOL`, `MODEL.GEMINI_FLASH`, `MODEL.GROK`, `MODEL.MUSE_SPARK`, `MODEL.MUSE_SPARK_CONTRIBUTOR`, `MODEL.NOVA_PRO`, `MODEL.NOVA_LITE`), plus three nested subtrees: `MODEL.FIREWORKS.*` for Fireworks serverless models (`DEEPSEEK`, `GLM`, `GPT_OSS`, `INKLING`, `KIMI`, `MINIMAX`, `NEMOTRON`, `QWEN`), `MODEL.MISTRAL.*` (`LARGE`, `OCR`, `SMALL`), `MODEL.LLAMAPARSE.*` for LlamaParse tiers (`FAST`, `COST_EFFECTIVE`, `AGENTIC`, `AGENTIC_PLUS`), and `MODEL.OPENROUTER.*` for provider-prefixed routes (`GLM`, `LUNA`, `SONNET`). Pick specific models from here. `MODEL.MISTRAL.OCR` and `MODEL.LLAMAPARSE.*` are document-extraction engines reached through `Llm.ocr`, not chat completions: they are priced per page in `LLM.PAGE_COST` (USD per 1,000 pages, keyed by literal id) and carry no `COST` entry. Amazon's Nova models are first-class ids served over Bedrock; Bedrock's third-party routes are not catalogued — pass the literal id (e.g. `us.anthropic.claude-sonnet-4-6`) and `determineModelProvider` resolves it to `bedrock`.
58
61
  - `MODEL.MUSE_SPARK` and `MODEL.MUSE_SPARK_CONTRIBUTOR` are the same Meta model at two tiers. The contributor tier is roughly a tenth of the price because prompts and completions may train Meta models; it is limited to 100 RPM and does not accept `reasoning.effort: "max"`. It is an explicit opt-in: `PROVIDER.META.DEFAULT` is `MODEL.MUSE_SPARK`.
59
62
  - The catalog is the **single source of truth for CI coverage**: `packages/llm/test/models.ts` derives the live capability matrix from `MODEL.*` plus each `PROVIDER.*.DEFAULT`, and the workflow shards it by provider. Adding a model to `MODEL.*` puts it under test; no id list exists anywhere else.
60
63
  - **Deprecated:** the size-tier map `PROVIDER.<name>.MODEL.{DEFAULT,LARGE,SMALL,TINY}`, the `DEFAULT.MODEL` bundle, and `ALL` are `@deprecated` and retired in 2.0 — use `PROVIDER.*.DEFAULT` for defaults and `MODEL.*` for named models.
@@ -485,6 +488,70 @@ an attempt with somewhere left to go skips the rate-limit wait. A provider
485
488
  that can neither `question` nor `operate` counts as a failed attempt and the
486
489
  chain moves on.
487
490
 
491
+ ## OCR
492
+
493
+ `Llm.ocr(document, options?)` turns a document into per-page markdown. Two
494
+ engines answer natively behind one request and response shape: Mistral OCR
495
+ (`MODEL.MISTRAL.OCR`, one synchronous call, the default when no provider or
496
+ model is named) and LlamaParse over LlamaCloud (`MODEL.LLAMAPARSE.*`, a job
497
+ that is submitted, polled, and fetched; `LLAMA_CLOUD_API_KEY`). Every other
498
+ provider answers through emulation, as `Llm.question` does: one structured
499
+ `operate()` call per page. A `model` array is therefore a fallback chain
500
+ across native engines and chat models alike.
501
+
502
+ ```typescript
503
+ import { Llm, LLM } from "@jaypie/llm";
504
+
505
+ const { emulated, markdown, pages, usage } = await Llm.ocr(
506
+ "./scans/invoice.pdf",
507
+ {
508
+ model: [
509
+ LLM.MODEL.MISTRAL.OCR,
510
+ LLM.MODEL.LLAMAPARSE.COST_EFFECTIVE,
511
+ LLM.MODEL.HAIKU, // emulated: any provider that accepts files
512
+ ],
513
+ pages: "1,3-5", // 1-indexed; [1, 3, 4, 5] also works
514
+ tables: "markdown", // or "html"
515
+ },
516
+ );
517
+
518
+ pages[0].page; // 1
519
+ pages[0].markdown;
520
+ pages[0].confidence; // emulated only: the model's self-reported 0..1
521
+ emulated; // true when a chat model transcribed the pages
522
+ usage.pages; // pages billed
523
+ usage.cost; // USD from LLM.PAGE_COST (LlamaParse: from recorded credits; emulated: from COST tokens)
524
+ usage.tokens; // emulated only: every operate() call's usage
525
+ ```
526
+
527
+ Emulation sends each page alone (a PDF is trimmed to one page per call, so
528
+ the model never numbers pages), asks for verbatim Markdown with
529
+ `[UNCLEAR: best guess]` and `[ELEMENT: description]` markers, transcribes a
530
+ page scored under 0.4 once more and keeps the higher score, and runs
531
+ `concurrency` pages at a time (default 5); the first failure stops the rest
532
+ so the next engine starts clean. Unreadable content fails the attempt so the
533
+ chain moves on. A provider with native `ocr` (Mistral) always answers
534
+ natively; a provider with neither `ocr` nor `operate` (`typesafe`) fails its
535
+ attempt and the chain moves on.
536
+
537
+ `document` is an `https://` URL (fetched by the vendor), a `data:` URI, an S3
538
+ key (when `CDK_ENV_BUCKET` is set), a local path, or the `{ file, bucket?,
539
+ data?, pages? }` / `{ image, ... }` objects `operate()` accepts. Set
540
+ `images: true` to download extracted images as `data:` URIs onto
541
+ `images[]` and `pages[].images`. `providerOptions` spreads last onto the
542
+ vendor request: Mistral `OCRRequest` fields (`document_annotation_format`,
543
+ `include_blocks`, ...) or LlamaParse `ParseRequestConfiguration` fields
544
+ (`version`, `agentic_options.custom_prompt`, `processing_options`,
545
+ `output_options`, `disable_cache`, ...). `timeout` (default ten minutes)
546
+ bounds a LlamaParse job; expiry throws `LlmTransientError` so a chain can try
547
+ the next engine. `retry` and `signal` behave as on `operate()`.
548
+
549
+ LlamaParse's API version is pinned per tier in `PROVIDER.LLAMACLOUD.VERSION`
550
+ (each tier accepts its own dated versions); the response `model` reads
551
+ `llamaparse-agentic@2026-09-13` so usage records name the configuration. The
552
+ fast tier returns text only, copied into `markdown`. Failed pages arrive with
553
+ `success: false` and `error` rather than failing the call.
554
+
488
555
  ## Conversation History
489
556
 
490
557
  Continue conversations across calls:
@@ -734,6 +801,7 @@ OPENROUTER_API_KEY # Required for OpenRouter
734
801
  XAI_API_KEY # Required for xAI (Grok)
735
802
  META_API_KEY # Required for Meta (Muse Spark); MODEL_API_KEY is read as a fallback
736
803
  TYPESAFE_API_KEY # Required for TypeSafe (Jev); emulated questions use the answering provider's key
804
+ LLAMA_CLOUD_API_KEY # Required for LlamaParse (Llm.ocr); Mistral OCR uses MISTRAL_API_KEY
737
805
  ```
738
806
 
739
807
  Keys are resolved via `getEnvSecret()` which supports AWS Secrets Manager.
@@ -850,6 +918,7 @@ exactly like a provider rate limit.
850
918
  |----------|--------|---------|
851
919
  | `max_turns` | 429 | The model asked for another tool call after `turns` ran out. Nothing failed; the run did not converge. |
852
920
  | `tool_errors` | 502 | Tool execution failed six times in a row and the loop stopped. |
921
+ | `incomplete` | 502 | The provider cut the model off before it finished (an output token ceiling, a content filter). `content` holds the partial text; `error.detail` names the provider's reason. |
853
922
 
854
923
  ```typescript
855
924
  import { LlmResponseErrorReason } from "@jaypie/llm";