@ttoss/http-server-mcp 0.34.0 → 0.34.1
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/README.md +2 -2
- package/dist/index.cjs +55 -16
- package/dist/index.d.cts +6 -0
- package/dist/index.d.mts +6 -0
- package/dist/index.mjs +55 -16
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -484,14 +484,14 @@ registerTools({ server: fullServer, tools });
|
|
|
484
484
|
registerTools({ server: deferredServer, tools, defer: true });
|
|
485
485
|
```
|
|
486
486
|
|
|
487
|
-
A schema enters the model's context only for the tools it is about to use. `call` enforces the tool's schema as a direct call would, and its errors help the model recover: an unknown name answers suggestions, and invalid arguments, a tool's own error result, or a thrown error carry the input schema, so a `call` made without `describe` corrects itself in one retry.
|
|
487
|
+
A schema enters the model's context only for the tools it is about to use. `call` enforces the tool's schema as a direct call would, and its errors help the model recover: an unknown name answers suggestions (near-miss names, then tools the name's words match; a lone prefix in a description is not enough), and invalid arguments, a tool's own error result, or a thrown error carry the input schema, so a `call` made without `describe` corrects itself in one retry.
|
|
488
488
|
|
|
489
489
|
Pass options instead of `true` to tune it:
|
|
490
490
|
|
|
491
491
|
- `except` — tools kept standalone, not deferred; they stay reachable through `search` too. Defaults to those linked to an [MCP Apps](#mcp-apps-interactive-uis) view, since a host finds a view through the tool's own `tools/list` entry.
|
|
492
492
|
- `visible` — runs on every `search`, `describe` and `call`; a tool it rejects is absent from all three. Standalone tools stay listed.
|
|
493
493
|
- `search` — replaces the default ranking, `rankTools`, e.g. with embeddings.
|
|
494
|
-
- `searchLimit` (default `10`) and `names` (default `search` / `describe` / `call`).
|
|
494
|
+
- `searchLimit` (default `10`), `searchMaxLimit` — the largest `limit` accepted (default `50`, or `searchLimit` when higher) — and `names` (default `search` / `describe` / `call`).
|
|
495
495
|
|
|
496
496
|
A gate (below) sees each call with the tool's own name and arguments, so authorization stays per tool when deferred.
|
|
497
497
|
|
package/dist/index.cjs
CHANGED
|
@@ -507,6 +507,7 @@ var defineTool = ({
|
|
|
507
507
|
//#region src/toolSearch.ts
|
|
508
508
|
var SUMMARY_MAX_LENGTH = 160;
|
|
509
509
|
var SUGGESTION_COUNT = 3;
|
|
510
|
+
var MIN_RELATED_SCORE = 1;
|
|
510
511
|
/** Plural and singular forms rank alike: `agents` finds `get-agent`. */
|
|
511
512
|
var stem = term => {
|
|
512
513
|
if (term.length > 4 && term.endsWith("ies")) return `${term.slice(0, -3)}y`;
|
|
@@ -573,23 +574,29 @@ var scoreOf = ({
|
|
|
573
574
|
}
|
|
574
575
|
return score;
|
|
575
576
|
};
|
|
577
|
+
var withTag = ({
|
|
578
|
+
tag,
|
|
579
|
+
tools
|
|
580
|
+
}) => {
|
|
581
|
+
return tag === void 0 ? tools : tools.filter(tool => {
|
|
582
|
+
return tool.tags?.includes(tag) ?? false;
|
|
583
|
+
});
|
|
584
|
+
};
|
|
576
585
|
/**
|
|
577
|
-
* The
|
|
578
|
-
*
|
|
579
|
-
* tools' order. No index — a few hundred tools need none.
|
|
586
|
+
* The tools `query` matches, best first, ties in the tools' order; `undefined`
|
|
587
|
+
* when the query has no words.
|
|
580
588
|
*/
|
|
581
|
-
var
|
|
589
|
+
var scoreTools = ({
|
|
582
590
|
query,
|
|
583
591
|
tag,
|
|
584
|
-
limit,
|
|
585
592
|
tools
|
|
586
593
|
}) => {
|
|
587
|
-
const candidates = tag === void 0 ? tools : tools.filter(tool => {
|
|
588
|
-
return tool.tags?.includes(tag) ?? false;
|
|
589
|
-
});
|
|
590
594
|
const terms = [...new Set(termsOf(query))];
|
|
591
|
-
if (terms.length === 0) return
|
|
592
|
-
return
|
|
595
|
+
if (terms.length === 0) return void 0;
|
|
596
|
+
return withTag({
|
|
597
|
+
tag,
|
|
598
|
+
tools
|
|
599
|
+
}).map((tool, index) => {
|
|
593
600
|
return {
|
|
594
601
|
tool,
|
|
595
602
|
index,
|
|
@@ -604,7 +611,29 @@ var rankTools = ({
|
|
|
604
611
|
return score > 0;
|
|
605
612
|
}).sort((a, b) => {
|
|
606
613
|
return b.score - a.score || a.index - b.index;
|
|
607
|
-
})
|
|
614
|
+
});
|
|
615
|
+
};
|
|
616
|
+
/**
|
|
617
|
+
* The deferred tools' default search: scores each tool by the query's terms,
|
|
618
|
+
* weighted name > summary > tags > description, and breaks ties by the
|
|
619
|
+
* tools' order. No index — a few hundred tools need none.
|
|
620
|
+
*/
|
|
621
|
+
var rankTools = ({
|
|
622
|
+
query,
|
|
623
|
+
tag,
|
|
624
|
+
limit,
|
|
625
|
+
tools
|
|
626
|
+
}) => {
|
|
627
|
+
const scored = scoreTools({
|
|
628
|
+
query,
|
|
629
|
+
tag,
|
|
630
|
+
tools
|
|
631
|
+
});
|
|
632
|
+
if (!scored) return withTag({
|
|
633
|
+
tag,
|
|
634
|
+
tools
|
|
635
|
+
}).slice(0, limit);
|
|
636
|
+
return scored.slice(0, limit).map(({
|
|
608
637
|
tool
|
|
609
638
|
}) => {
|
|
610
639
|
return tool;
|
|
@@ -651,11 +680,16 @@ var suggestionsFor = ({
|
|
|
651
680
|
}).map(candidate => {
|
|
652
681
|
return candidate.name;
|
|
653
682
|
});
|
|
654
|
-
const related =
|
|
683
|
+
const related = (scoreTools({
|
|
655
684
|
query: name,
|
|
656
|
-
limit: SUGGESTION_COUNT,
|
|
657
685
|
tools
|
|
658
|
-
}).
|
|
686
|
+
}) ?? []).filter(({
|
|
687
|
+
score
|
|
688
|
+
}) => {
|
|
689
|
+
return score >= MIN_RELATED_SCORE;
|
|
690
|
+
}).slice(0, SUGGESTION_COUNT).map(({
|
|
691
|
+
tool
|
|
692
|
+
}) => {
|
|
659
693
|
return tool.name;
|
|
660
694
|
});
|
|
661
695
|
return [...new Set([...nearMisses, ...related])].slice(0, SUGGESTION_COUNT);
|
|
@@ -664,6 +698,7 @@ var suggestionsFor = ({
|
|
|
664
698
|
//#endregion
|
|
665
699
|
//#region src/deferTools.ts
|
|
666
700
|
var DEFAULT_SEARCH_LIMIT = 10;
|
|
701
|
+
var DEFAULT_SEARCH_MAX_LIMIT = 50;
|
|
667
702
|
var jsonResult = ({
|
|
668
703
|
data,
|
|
669
704
|
isError = false
|
|
@@ -708,6 +743,7 @@ var deferredToolsOf = ({
|
|
|
708
743
|
tool
|
|
709
744
|
}) : true;
|
|
710
745
|
};
|
|
746
|
+
const searchLimit = options.searchLimit ?? DEFAULT_SEARCH_LIMIT;
|
|
711
747
|
return {
|
|
712
748
|
names: {
|
|
713
749
|
search: "search",
|
|
@@ -716,7 +752,8 @@ var deferredToolsOf = ({
|
|
|
716
752
|
...options.names
|
|
717
753
|
},
|
|
718
754
|
tools,
|
|
719
|
-
searchLimit
|
|
755
|
+
searchLimit,
|
|
756
|
+
searchMaxLimit: options.searchMaxLimit ?? Math.max(DEFAULT_SEARCH_MAX_LIMIT, searchLimit),
|
|
720
757
|
searchTools: options.search ?? rankTools,
|
|
721
758
|
visibleTools: () => {
|
|
722
759
|
return tools.filter(isVisible);
|
|
@@ -731,6 +768,7 @@ var searchToolOf = ({
|
|
|
731
768
|
names,
|
|
732
769
|
tools,
|
|
733
770
|
searchLimit,
|
|
771
|
+
searchMaxLimit,
|
|
734
772
|
searchTools,
|
|
735
773
|
visibleTools
|
|
736
774
|
}) => {
|
|
@@ -745,7 +783,7 @@ var searchToolOf = ({
|
|
|
745
783
|
properties: {
|
|
746
784
|
query: {
|
|
747
785
|
type: "string",
|
|
748
|
-
description: "Words describing the action, e.g. \"create agent\". Empty lists
|
|
786
|
+
description: "Words describing the action, e.g. \"create agent\". Empty lists the tools in order."
|
|
749
787
|
},
|
|
750
788
|
tag: {
|
|
751
789
|
type: "string",
|
|
@@ -757,6 +795,7 @@ var searchToolOf = ({
|
|
|
757
795
|
limit: {
|
|
758
796
|
type: "integer",
|
|
759
797
|
minimum: 1,
|
|
798
|
+
maximum: searchMaxLimit,
|
|
760
799
|
description: `Maximum number of results. Defaults to ${searchLimit}.`
|
|
761
800
|
}
|
|
762
801
|
},
|
package/dist/index.d.cts
CHANGED
|
@@ -865,6 +865,12 @@ interface DeferToolsOptions {
|
|
|
865
865
|
* @default 10
|
|
866
866
|
*/
|
|
867
867
|
searchLimit?: number;
|
|
868
|
+
/**
|
|
869
|
+
* The largest `limit` `search` accepts. With no ceiling, an empty query
|
|
870
|
+
* lists every tool, more than a client's context holds.
|
|
871
|
+
* @default 50, or `searchLimit` when that is higher
|
|
872
|
+
*/
|
|
873
|
+
searchMaxLimit?: number;
|
|
868
874
|
/**
|
|
869
875
|
* Runs on every `search`, `describe` and `call`. A tool it rejects is
|
|
870
876
|
* absent from all three; `call` answers it as an unknown name. Tools
|
package/dist/index.d.mts
CHANGED
|
@@ -866,6 +866,12 @@ interface DeferToolsOptions {
|
|
|
866
866
|
* @default 10
|
|
867
867
|
*/
|
|
868
868
|
searchLimit?: number;
|
|
869
|
+
/**
|
|
870
|
+
* The largest `limit` `search` accepts. With no ceiling, an empty query
|
|
871
|
+
* lists every tool, more than a client's context holds.
|
|
872
|
+
* @default 50, or `searchLimit` when that is higher
|
|
873
|
+
*/
|
|
874
|
+
searchMaxLimit?: number;
|
|
869
875
|
/**
|
|
870
876
|
* Runs on every `search`, `describe` and `call`. A tool it rejects is
|
|
871
877
|
* absent from all three; `call` answers it as an unknown name. Tools
|
package/dist/index.mjs
CHANGED
|
@@ -504,6 +504,7 @@ var defineTool = ({
|
|
|
504
504
|
//#region src/toolSearch.ts
|
|
505
505
|
var SUMMARY_MAX_LENGTH = 160;
|
|
506
506
|
var SUGGESTION_COUNT = 3;
|
|
507
|
+
var MIN_RELATED_SCORE = 1;
|
|
507
508
|
/** Plural and singular forms rank alike: `agents` finds `get-agent`. */
|
|
508
509
|
var stem = term => {
|
|
509
510
|
if (term.length > 4 && term.endsWith("ies")) return `${term.slice(0, -3)}y`;
|
|
@@ -570,23 +571,29 @@ var scoreOf = ({
|
|
|
570
571
|
}
|
|
571
572
|
return score;
|
|
572
573
|
};
|
|
574
|
+
var withTag = ({
|
|
575
|
+
tag,
|
|
576
|
+
tools
|
|
577
|
+
}) => {
|
|
578
|
+
return tag === void 0 ? tools : tools.filter(tool => {
|
|
579
|
+
return tool.tags?.includes(tag) ?? false;
|
|
580
|
+
});
|
|
581
|
+
};
|
|
573
582
|
/**
|
|
574
|
-
* The
|
|
575
|
-
*
|
|
576
|
-
* tools' order. No index — a few hundred tools need none.
|
|
583
|
+
* The tools `query` matches, best first, ties in the tools' order; `undefined`
|
|
584
|
+
* when the query has no words.
|
|
577
585
|
*/
|
|
578
|
-
var
|
|
586
|
+
var scoreTools = ({
|
|
579
587
|
query,
|
|
580
588
|
tag,
|
|
581
|
-
limit,
|
|
582
589
|
tools
|
|
583
590
|
}) => {
|
|
584
|
-
const candidates = tag === void 0 ? tools : tools.filter(tool => {
|
|
585
|
-
return tool.tags?.includes(tag) ?? false;
|
|
586
|
-
});
|
|
587
591
|
const terms = [...new Set(termsOf(query))];
|
|
588
|
-
if (terms.length === 0) return
|
|
589
|
-
return
|
|
592
|
+
if (terms.length === 0) return void 0;
|
|
593
|
+
return withTag({
|
|
594
|
+
tag,
|
|
595
|
+
tools
|
|
596
|
+
}).map((tool, index) => {
|
|
590
597
|
return {
|
|
591
598
|
tool,
|
|
592
599
|
index,
|
|
@@ -601,7 +608,29 @@ var rankTools = ({
|
|
|
601
608
|
return score > 0;
|
|
602
609
|
}).sort((a, b) => {
|
|
603
610
|
return b.score - a.score || a.index - b.index;
|
|
604
|
-
})
|
|
611
|
+
});
|
|
612
|
+
};
|
|
613
|
+
/**
|
|
614
|
+
* The deferred tools' default search: scores each tool by the query's terms,
|
|
615
|
+
* weighted name > summary > tags > description, and breaks ties by the
|
|
616
|
+
* tools' order. No index — a few hundred tools need none.
|
|
617
|
+
*/
|
|
618
|
+
var rankTools = ({
|
|
619
|
+
query,
|
|
620
|
+
tag,
|
|
621
|
+
limit,
|
|
622
|
+
tools
|
|
623
|
+
}) => {
|
|
624
|
+
const scored = scoreTools({
|
|
625
|
+
query,
|
|
626
|
+
tag,
|
|
627
|
+
tools
|
|
628
|
+
});
|
|
629
|
+
if (!scored) return withTag({
|
|
630
|
+
tag,
|
|
631
|
+
tools
|
|
632
|
+
}).slice(0, limit);
|
|
633
|
+
return scored.slice(0, limit).map(({
|
|
605
634
|
tool
|
|
606
635
|
}) => {
|
|
607
636
|
return tool;
|
|
@@ -648,11 +677,16 @@ var suggestionsFor = ({
|
|
|
648
677
|
}).map(candidate => {
|
|
649
678
|
return candidate.name;
|
|
650
679
|
});
|
|
651
|
-
const related =
|
|
680
|
+
const related = (scoreTools({
|
|
652
681
|
query: name,
|
|
653
|
-
limit: SUGGESTION_COUNT,
|
|
654
682
|
tools
|
|
655
|
-
}).
|
|
683
|
+
}) ?? []).filter(({
|
|
684
|
+
score
|
|
685
|
+
}) => {
|
|
686
|
+
return score >= MIN_RELATED_SCORE;
|
|
687
|
+
}).slice(0, SUGGESTION_COUNT).map(({
|
|
688
|
+
tool
|
|
689
|
+
}) => {
|
|
656
690
|
return tool.name;
|
|
657
691
|
});
|
|
658
692
|
return [...new Set([...nearMisses, ...related])].slice(0, SUGGESTION_COUNT);
|
|
@@ -661,6 +695,7 @@ var suggestionsFor = ({
|
|
|
661
695
|
//#endregion
|
|
662
696
|
//#region src/deferTools.ts
|
|
663
697
|
var DEFAULT_SEARCH_LIMIT = 10;
|
|
698
|
+
var DEFAULT_SEARCH_MAX_LIMIT = 50;
|
|
664
699
|
var jsonResult = ({
|
|
665
700
|
data,
|
|
666
701
|
isError = false
|
|
@@ -705,6 +740,7 @@ var deferredToolsOf = ({
|
|
|
705
740
|
tool
|
|
706
741
|
}) : true;
|
|
707
742
|
};
|
|
743
|
+
const searchLimit = options.searchLimit ?? DEFAULT_SEARCH_LIMIT;
|
|
708
744
|
return {
|
|
709
745
|
names: {
|
|
710
746
|
search: "search",
|
|
@@ -713,7 +749,8 @@ var deferredToolsOf = ({
|
|
|
713
749
|
...options.names
|
|
714
750
|
},
|
|
715
751
|
tools,
|
|
716
|
-
searchLimit
|
|
752
|
+
searchLimit,
|
|
753
|
+
searchMaxLimit: options.searchMaxLimit ?? Math.max(DEFAULT_SEARCH_MAX_LIMIT, searchLimit),
|
|
717
754
|
searchTools: options.search ?? rankTools,
|
|
718
755
|
visibleTools: () => {
|
|
719
756
|
return tools.filter(isVisible);
|
|
@@ -728,6 +765,7 @@ var searchToolOf = ({
|
|
|
728
765
|
names,
|
|
729
766
|
tools,
|
|
730
767
|
searchLimit,
|
|
768
|
+
searchMaxLimit,
|
|
731
769
|
searchTools,
|
|
732
770
|
visibleTools
|
|
733
771
|
}) => {
|
|
@@ -742,7 +780,7 @@ var searchToolOf = ({
|
|
|
742
780
|
properties: {
|
|
743
781
|
query: {
|
|
744
782
|
type: "string",
|
|
745
|
-
description: "Words describing the action, e.g. \"create agent\". Empty lists
|
|
783
|
+
description: "Words describing the action, e.g. \"create agent\". Empty lists the tools in order."
|
|
746
784
|
},
|
|
747
785
|
tag: {
|
|
748
786
|
type: "string",
|
|
@@ -754,6 +792,7 @@ var searchToolOf = ({
|
|
|
754
792
|
limit: {
|
|
755
793
|
type: "integer",
|
|
756
794
|
minimum: 1,
|
|
795
|
+
maximum: searchMaxLimit,
|
|
757
796
|
description: `Maximum number of results. Defaults to ${searchLimit}.`
|
|
758
797
|
}
|
|
759
798
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ttoss/http-server-mcp",
|
|
3
|
-
"version": "0.34.
|
|
3
|
+
"version": "0.34.1",
|
|
4
4
|
"description": "Model Context Protocol (MCP) server integration for @ttoss/http-server",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
"zod": "^4.4.3",
|
|
40
40
|
"@ttoss/auth-core": "^0.16.1",
|
|
41
41
|
"@ttoss/http-server": "^0.11.1",
|
|
42
|
-
"@ttoss/
|
|
43
|
-
"@ttoss/
|
|
42
|
+
"@ttoss/i18n-core": "^0.7.0",
|
|
43
|
+
"@ttoss/http-server-auth": "^0.8.1"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@modelcontextprotocol/client": "^2.0.0",
|