mcp-recipes 1.3.0 → 2.0.0

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.
@@ -24,10 +24,10 @@ interface Config {
24
24
  logLevel: LogLevel;
25
25
  }
26
26
  interface Logger {
27
- debug(message: string): void;
28
- info(message: string): void;
29
- warn(message: string): void;
30
- error(message: string): void;
27
+ debug: (message: string) => void;
28
+ info: (message: string) => void;
29
+ warn: (message: string) => void;
30
+ error: (message: string) => void;
31
31
  }
32
32
 
33
33
  /** The shapes the source layer produces. Nothing here knows about MCP. */
@@ -249,12 +249,10 @@ interface SourceAdapter extends SourceProfile {
249
249
  * no source claims is refused, instead of being sent somewhere that would
250
250
  * answer it with a confident absence.
251
251
  */
252
- claims(raw: string): Claim | null;
253
- search(query: string, limit: number): Promise<ReadRows>;
254
- getRecipe(reference: string): Promise<ReadRecipe>;
252
+ claims: (raw: string) => Claim | null;
253
+ search: (query: string, limit: number) => Promise<ReadRows>;
254
+ getRecipe: (reference: string) => Promise<ReadRecipe>;
255
255
  }
256
- /** Build the identifier this server hands out for a row from a source. */
257
- declare function namespacedId(source: SourceId, reference: string): string;
258
256
 
259
257
  /**
260
258
  * Identifiers that name the source they came from.
@@ -272,21 +270,6 @@ interface ResolvedId {
272
270
  /** Set when the shape was read rather than stated, so the answer can say so. */
273
271
  inferred: string | null;
274
272
  }
275
- /**
276
- * Work out which source an identifier belongs to.
277
- *
278
- * A prefixed identifier is routed on what it says. A raw one is offered to each
279
- * source in turn, and a source claims only the shapes it mints: digits for one,
280
- * a namespaced page key for another. Exactly one claim routes the read and the
281
- * answer says which reading it used.
282
- *
283
- * More than one claim is refused rather than resolved, because picking a winner
284
- * would send the read somewhere a caller did not intend and answer with a
285
- * confident recipe for the wrong dish. No claim at all is refused too: a bare
286
- * dish name is a search, not an identifier, and guessing a page name from it
287
- * returns whatever that guess happens to hit.
288
- */
289
- declare function resolveId(rawId: string, sources: readonly SourceAdapter[]): ResolvedId;
290
273
 
291
274
  /**
292
275
  * The Cookbook on the English Wikibooks, as a source.
@@ -329,13 +312,13 @@ interface CookbookRecipe {
329
312
  }
330
313
  /** The part of the Cookbook's client this server uses. */
331
314
  interface CookbookReader {
332
- search(query: string, limit: number): Promise<{
315
+ search: (query: string, limit: number) => Promise<{
333
316
  data: {
334
317
  results: CookbookSummary[];
335
318
  };
336
319
  cached: boolean;
337
320
  }>;
338
- getRecipe(reference: string): Promise<{
321
+ getRecipe: (reference: string) => Promise<{
339
322
  data: CookbookRecipe;
340
323
  cached: boolean;
341
324
  }>;
@@ -382,14 +365,14 @@ interface MarmitonRecipe {
382
365
  }
383
366
  /** The part of Marmiton's client this server uses. */
384
367
  interface MarmitonReader {
385
- search(query: string): Promise<{
368
+ search: (query: string) => Promise<{
386
369
  data: MarmitonSummary[];
387
370
  cached: boolean;
388
371
  }>;
389
- getRecipe(ref: {
372
+ getRecipe: (ref: {
390
373
  id?: string;
391
374
  url?: string;
392
- }): Promise<{
375
+ }) => Promise<{
393
376
  data: MarmitonRecipe;
394
377
  cached: boolean;
395
378
  }>;
@@ -412,109 +395,6 @@ interface Readers {
412
395
  marmiton?: MarmitonReader;
413
396
  cookbook?: CookbookReader;
414
397
  }
415
- /** The sources a caller can name, in the order an answer takes them. */
416
- declare const SOURCE_IDS: readonly SourceId[];
417
-
418
- /**
419
- * Several wordings from one question.
420
- *
421
- * A person asks for a recipe in a sentence, and a recipe index reads none of
422
- * it. One of the indexes behind this server requires every word given to appear
423
- * on the same page, so a sentence returns nothing where the corpus holds several
424
- * of the dish. The other ranks pages on the words it was handed, so the words
425
- * framing the question pull up whatever happens to share them and push the dish
426
- * down the list or out of it. Both come back to a reader looking like a
427
- * statement about a corpus when they are statements about a wording. Deriving
428
- * the shorter wordings and asking for the union is what keeps the two apart.
429
- *
430
- * Every wording is built from the words the question carried, with no
431
- * dictionary, no corpus statistics and no translation. That has two
432
- * consequences worth stating. A derived wording is one a reader can retype by
433
- * hand, so an answer built from several of them stays checkable. And the
434
- * derivations that would need a lexicon are not made: a question asked in one
435
- * language is never turned into the other, because a source that publishes in
436
- * the other language and holds nothing under the words written is an honest
437
- * absence, while a guessed translation is a word nobody wrote.
438
- *
439
- * The order runs from the wording closest to what was asked to the widest.
440
- *
441
- * A question also states what the recipe must not hold, and that part is read
442
- * by the role its words play rather than by the turn of phrase they are written
443
- * in: a negation, a sentence about how a food affects the person, or the name
444
- * of a diet. All three put a food out of the dish, so all three are set aside
445
- * from the derived wordings and named back to the caller. Reading them off a
446
- * list of phrasings is what lets a declared allergen become a word to search
447
- * for, and there is no phrasing whose absence from such a list is safe.
448
- */
449
- /** One wording, and how it was arrived at. */
450
- interface Wording {
451
- query: string;
452
- /** How this wording was derived from the question, in words. */
453
- derivation: string;
454
- }
455
- /**
456
- * The most searches one source receives for one question.
457
- *
458
- * A ceiling per source rather than a budget shared between them, because the
459
- * sources are asked in parallel and each is paced on its own, so the worst case
460
- * is three of one source's intervals rather than six. Three is also the whole
461
- * ladder: the question as asked, the dish words, and the word naming the dish.
462
- */
463
- declare const MAX_WORDINGS_PER_SOURCE = 3;
464
- /** How a question put a condition, which decides how it is reported back. */
465
- type ConditionKind =
466
- /** The question wrote the recipe must not hold this. */
467
- "excluded"
468
- /** The question said the person reacts to this food. */
469
- | "allergy"
470
- /** The question named a diet, which is a class defined by what it leaves out. */
471
- | "diet";
472
- /** One thing a question asks the recipe not to hold. */
473
- interface Condition {
474
- /**
475
- * The words the question used for the food, or null where the question states
476
- * a condition and the sentence does not say plainly which food it covers.
477
- *
478
- * A word named here is a word the recipe must not hold and a word no wording
479
- * looks for, so naming the wrong one both hides a dish and leaves the food
480
- * being avoided in the search. Where the reading is not certain, the caller is
481
- * told a condition was stated and that its food was not read, which is a
482
- * smaller claim than either.
483
- */
484
- named: string | null;
485
- kind: ConditionKind;
486
- }
487
- /** What a question asks the dish to avoid, and how many it has to serve. */
488
- interface Conditions {
489
- /** What the dish must not hold, in the words the question used. */
490
- conditions: Condition[];
491
- /** How many the dish has to serve, when the question said. */
492
- servings: number | null;
493
- }
494
- /**
495
- * Read what the question asks the recipe to avoid or to serve.
496
- *
497
- * These are the parts of a question no recipe index answers. A page is not
498
- * named for what it leaves out, and the number of people at a table is not
499
- * printed in a title at all, so both are read here and handled as what they
500
- * are rather than as words to look for.
501
- */
502
- declare function readConditions(question: string): Conditions;
503
- declare function deriveWordings(question: string): Wording[];
504
- /**
505
- * Whether a row's title carries a word naming the dish that was asked for.
506
- *
507
- * This decides whether a wording answered, and nothing else: no row is dropped
508
- * and no row is moved for failing it. A source that ranks on the words it was
509
- * handed answers a sentence with a page of recipes that share its framing
510
- * words, and counting those as an answer would stop the search on the page that
511
- * proves it has not found the dish.
512
- *
513
- * Diacritics and punctuation fold away, so "crêpes" reads the same as "crepes"
514
- * and a namespace in front of a page name settles nothing. A question that
515
- * names no dish has nothing to check against, and every row passes.
516
- */
517
- declare function namesDish(title: string, question: string): boolean;
518
398
 
519
399
  /**
520
400
  * The one place that talks to the sources.
@@ -622,4 +502,4 @@ declare class RecipesClient {
622
502
  }>;
623
503
  }
624
504
 
625
- export { type Conditions, type CookbookReader, MAX_LIMIT_PER_SOURCE, MAX_WORDINGS_PER_SOURCE, type MarmitonReader, type MergedSearch, type ReadRecipe, type ReadRows, type Readers, type RecipeDetail, type RecipeRow, RecipesClient, type RecipesClientOptions, SOURCE_IDS, type SearchOptions, type SourceAdapter, type SourceId, type SourceProfile, type SourceReport, type Wording, type WordingAttempt, deriveWordings, interleave, namesDish, namespacedId, readConditions, resolveId };
505
+ export { type CookbookReader, MAX_LIMIT_PER_SOURCE, type MarmitonReader, type MergedSearch, type ReadRecipe, type ReadRows, type Readers, type RecipeDetail, type RecipeRow, RecipesClient, type RecipesClientOptions, type SearchOptions, type SourceAdapter, type SourceId, type SourceProfile, type SourceReport, type WordingAttempt, interleave };