@shrkcrft/mcp-server 0.1.0-alpha.2 → 0.1.0-alpha.21
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/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/server/columnar-format.d.ts +34 -0
- package/dist/server/columnar-format.d.ts.map +1 -0
- package/dist/server/columnar-format.js +95 -0
- package/dist/server/create-mcp-server.d.ts +3 -0
- package/dist/server/create-mcp-server.d.ts.map +1 -1
- package/dist/server/create-mcp-server.js +24 -9
- package/dist/server/fit-array-to-budget.d.ts +24 -0
- package/dist/server/fit-array-to-budget.d.ts.map +1 -0
- package/dist/server/fit-array-to-budget.js +60 -0
- package/dist/server/serialize-tool-data.d.ts +15 -0
- package/dist/server/serialize-tool-data.d.ts.map +1 -0
- package/dist/server/serialize-tool-data.js +22 -0
- package/dist/server/tool-definition.d.ts +15 -0
- package/dist/server/tool-definition.d.ts.map +1 -1
- package/dist/server/tool-input-validators.d.ts.map +1 -1
- package/dist/server/tool-input-validators.js +43 -0
- package/dist/tools/agent-brief.tool.d.ts.map +1 -1
- package/dist/tools/agent-brief.tool.js +20 -0
- package/dist/tools/align-cache.tool.d.ts +11 -0
- package/dist/tools/align-cache.tool.d.ts.map +1 -0
- package/dist/tools/align-cache.tool.js +76 -0
- package/dist/tools/all-tools.d.ts.map +1 -1
- package/dist/tools/all-tools.js +72 -7
- package/dist/tools/architecture-map.tool.d.ts.map +1 -1
- package/dist/tools/architecture-map.tool.js +4 -2
- package/dist/tools/code-find-usages.tool.d.ts +16 -0
- package/dist/tools/code-find-usages.tool.d.ts.map +1 -0
- package/dist/tools/code-find-usages.tool.js +180 -0
- package/dist/tools/command-catalog.tool.d.ts.map +1 -1
- package/dist/tools/command-catalog.tool.js +11 -7
- package/dist/tools/compress-context.tool.d.ts +8 -0
- package/dist/tools/compress-context.tool.d.ts.map +1 -0
- package/dist/tools/compress-context.tool.js +81 -0
- package/dist/tools/dashboard-summary.tool.d.ts.map +1 -1
- package/dist/tools/dashboard-summary.tool.js +2 -4
- package/dist/tools/delegate-task.tool.d.ts +3 -0
- package/dist/tools/delegate-task.tool.d.ts.map +1 -0
- package/dist/tools/delegate-task.tool.js +94 -0
- package/dist/tools/deps-audit.tool.d.ts +10 -0
- package/dist/tools/deps-audit.tool.d.ts.map +1 -0
- package/dist/tools/deps-audit.tool.js +251 -0
- package/dist/tools/diff-check.tool.d.ts +15 -0
- package/dist/tools/diff-check.tool.d.ts.map +1 -0
- package/dist/tools/diff-check.tool.js +157 -0
- package/dist/tools/file-advice.tool.d.ts +22 -0
- package/dist/tools/file-advice.tool.d.ts.map +1 -0
- package/dist/tools/file-advice.tool.js +88 -0
- package/dist/tools/get-api-surface-diff.tool.d.ts +3 -0
- package/dist/tools/get-api-surface-diff.tool.d.ts.map +1 -0
- package/dist/tools/get-api-surface-diff.tool.js +60 -0
- package/dist/tools/get-arch-violations.tool.d.ts +3 -0
- package/dist/tools/get-arch-violations.tool.d.ts.map +1 -0
- package/dist/tools/get-arch-violations.tool.js +30 -0
- package/dist/tools/get-code-intelligence-state.tool.d.ts +11 -0
- package/dist/tools/get-code-intelligence-state.tool.d.ts.map +1 -0
- package/dist/tools/get-code-intelligence-state.tool.js +60 -0
- package/dist/tools/get-context-pack.tool.d.ts +3 -0
- package/dist/tools/get-context-pack.tool.d.ts.map +1 -0
- package/dist/tools/get-context-pack.tool.js +40 -0
- package/dist/tools/get-framework-entities.tool.d.ts +3 -0
- package/dist/tools/get-framework-entities.tool.d.ts.map +1 -0
- package/dist/tools/get-framework-entities.tool.js +68 -0
- package/dist/tools/get-graph-callers.tool.d.ts +3 -0
- package/dist/tools/get-graph-callers.tool.d.ts.map +1 -0
- package/dist/tools/get-graph-callers.tool.js +94 -0
- package/dist/tools/get-graph-context.tool.d.ts +3 -0
- package/dist/tools/get-graph-context.tool.d.ts.map +1 -0
- package/dist/tools/get-graph-context.tool.js +125 -0
- package/dist/tools/get-graph-cycles.tool.d.ts +10 -0
- package/dist/tools/get-graph-cycles.tool.d.ts.map +1 -0
- package/dist/tools/get-graph-cycles.tool.js +58 -0
- package/dist/tools/get-graph-deps.tool.d.ts +12 -0
- package/dist/tools/get-graph-deps.tool.d.ts.map +1 -0
- package/dist/tools/get-graph-deps.tool.js +80 -0
- package/dist/tools/get-graph-hubs.tool.d.ts +3 -0
- package/dist/tools/get-graph-hubs.tool.d.ts.map +1 -0
- package/dist/tools/get-graph-hubs.tool.js +61 -0
- package/dist/tools/get-graph-impact-analysis.tool.d.ts +3 -0
- package/dist/tools/get-graph-impact-analysis.tool.d.ts.map +1 -0
- package/dist/tools/get-graph-impact-analysis.tool.js +44 -0
- package/dist/tools/get-graph-impact.tool.d.ts +3 -0
- package/dist/tools/get-graph-impact.tool.d.ts.map +1 -0
- package/dist/tools/get-graph-impact.tool.js +150 -0
- package/dist/tools/get-graph-path.tool.d.ts +3 -0
- package/dist/tools/get-graph-path.tool.d.ts.map +1 -0
- package/dist/tools/get-graph-path.tool.js +144 -0
- package/dist/tools/get-graph-search.tool.d.ts +3 -0
- package/dist/tools/get-graph-search.tool.d.ts.map +1 -0
- package/dist/tools/get-graph-search.tool.js +95 -0
- package/dist/tools/get-graph-status.tool.d.ts +11 -0
- package/dist/tools/get-graph-status.tool.d.ts.map +1 -0
- package/dist/tools/get-graph-status.tool.js +55 -0
- package/dist/tools/get-graph-unresolved.tool.d.ts +11 -0
- package/dist/tools/get-graph-unresolved.tool.d.ts.map +1 -0
- package/dist/tools/get-graph-unresolved.tool.js +85 -0
- package/dist/tools/get-impact-baseline.tool.d.ts +9 -0
- package/dist/tools/get-impact-baseline.tool.d.ts.map +1 -0
- package/dist/tools/get-impact-baseline.tool.js +65 -0
- package/dist/tools/get-intent-benchmark-run.tool.d.ts +12 -0
- package/dist/tools/get-intent-benchmark-run.tool.d.ts.map +1 -0
- package/dist/tools/get-intent-benchmark-run.tool.js +55 -0
- package/dist/tools/get-knowledge-graph.tool.d.ts +7 -0
- package/dist/tools/get-knowledge-graph.tool.d.ts.map +1 -1
- package/dist/tools/get-knowledge-graph.tool.js +62 -3
- package/dist/tools/get-migrations.tool.d.ts +3 -0
- package/dist/tools/get-migrations.tool.d.ts.map +1 -0
- package/dist/tools/get-migrations.tool.js +70 -0
- package/dist/tools/get-pattern-registry.tool.d.ts +8 -0
- package/dist/tools/get-pattern-registry.tool.d.ts.map +1 -0
- package/dist/tools/get-pattern-registry.tool.js +40 -0
- package/dist/tools/get-quality-gate.tool.d.ts +3 -0
- package/dist/tools/get-quality-gate.tool.d.ts.map +1 -0
- package/dist/tools/get-quality-gate.tool.js +27 -0
- package/dist/tools/get-relevant-context.tool.d.ts.map +1 -1
- package/dist/tools/get-relevant-context.tool.js +30 -6
- package/dist/tools/get-rules-for-file.tool.d.ts +3 -0
- package/dist/tools/get-rules-for-file.tool.d.ts.map +1 -0
- package/dist/tools/get-rules-for-file.tool.js +54 -0
- package/dist/tools/get-structural-rewrite-plan.tool.d.ts +3 -0
- package/dist/tools/get-structural-rewrite-plan.tool.d.ts.map +1 -0
- package/dist/tools/get-structural-rewrite-plan.tool.js +46 -0
- package/dist/tools/get-structural-search.tool.d.ts +3 -0
- package/dist/tools/get-structural-search.tool.d.ts.map +1 -0
- package/dist/tools/get-structural-search.tool.js +35 -0
- package/dist/tools/get-task-packet.tool.d.ts.map +1 -1
- package/dist/tools/get-task-packet.tool.js +26 -22
- package/dist/tools/graph-staleness.d.ts +34 -0
- package/dist/tools/graph-staleness.d.ts.map +1 -0
- package/dist/tools/graph-staleness.js +36 -0
- package/dist/tools/list-boundary-rules.tool.d.ts.map +1 -1
- package/dist/tools/list-boundary-rules.tool.js +20 -16
- package/dist/tools/list-knowledge.tool.d.ts.map +1 -1
- package/dist/tools/list-knowledge.tool.js +14 -13
- package/dist/tools/list-packs.tool.d.ts.map +1 -1
- package/dist/tools/list-packs.tool.js +19 -15
- package/dist/tools/list-path-conventions.tool.d.ts.map +1 -1
- package/dist/tools/list-path-conventions.tool.js +19 -15
- package/dist/tools/list-pipelines.tool.d.ts.map +1 -1
- package/dist/tools/list-pipelines.tool.js +18 -14
- package/dist/tools/list-presets.tool.d.ts.map +1 -1
- package/dist/tools/list-presets.tool.js +25 -21
- package/dist/tools/list-rules.tool.d.ts.map +1 -1
- package/dist/tools/list-rules.tool.js +18 -14
- package/dist/tools/list-templates.tool.d.ts.map +1 -1
- package/dist/tools/list-templates.tool.js +18 -14
- package/dist/tools/plan-quality-review.tool.d.ts +21 -0
- package/dist/tools/plan-quality-review.tool.d.ts.map +1 -0
- package/dist/tools/plan-quality-review.tool.js +294 -0
- package/dist/tools/primary-tools.d.ts +24 -0
- package/dist/tools/primary-tools.d.ts.map +1 -0
- package/dist/tools/primary-tools.js +86 -0
- package/dist/tools/r19-extras.tool.js +1 -1
- package/dist/tools/r32-profiles.tool.d.ts +0 -3
- package/dist/tools/r32-profiles.tool.d.ts.map +1 -1
- package/dist/tools/r32-profiles.tool.js +3 -54
- package/dist/tools/retrieve-original.tool.d.ts +9 -0
- package/dist/tools/retrieve-original.tool.d.ts.map +1 -0
- package/dist/tools/retrieve-original.tool.js +47 -0
- package/dist/tools/runtime-reports.tool.d.ts.map +1 -1
- package/dist/tools/runtime-reports.tool.js +1 -3
- package/dist/tools/safety-audit.tool.d.ts.map +1 -1
- package/dist/tools/safety-audit.tool.js +1 -4
- package/dist/tools/search-knowledge.tool.d.ts.map +1 -1
- package/dist/tools/search-knowledge.tool.js +17 -13
- package/dist/tools/search.tool.d.ts.map +1 -1
- package/dist/tools/search.tool.js +11 -8
- package/dist/tools/smart-context-bundle.tool.d.ts +17 -0
- package/dist/tools/smart-context-bundle.tool.d.ts.map +1 -0
- package/dist/tools/smart-context-bundle.tool.js +110 -0
- package/dist/tools/smart-context-feed.tool.d.ts +17 -0
- package/dist/tools/smart-context-feed.tool.d.ts.map +1 -0
- package/dist/tools/smart-context-feed.tool.js +138 -0
- package/dist/tools/start-here.tool.js +2 -2
- package/package.json +28 -16
- package/dist/tools/r22-extras.tool.d.ts +0 -4
- package/dist/tools/r22-extras.tool.d.ts.map +0 -1
- package/dist/tools/r22-extras.tool.js +0 -42
- package/dist/tools/r26-ingest.tool.d.ts +0 -10
- package/dist/tools/r26-ingest.tool.d.ts.map +0 -1
- package/dist/tools/r26-ingest.tool.js +0 -174
- package/dist/tools/r28-plugin-lifecycle.tool.d.ts +0 -4
- package/dist/tools/r28-plugin-lifecycle.tool.d.ts.map +0 -1
- package/dist/tools/r28-plugin-lifecycle.tool.js +0 -94
- package/dist/tools/r34-search-unified.tool.d.ts +0 -3
- package/dist/tools/r34-search-unified.tool.d.ts.map +0 -1
- package/dist/tools/r34-search-unified.tool.js +0 -38
package/dist/index.d.ts
CHANGED
|
@@ -5,4 +5,8 @@ export { ALL_TOOLS } from './tools/index.js';
|
|
|
5
5
|
export type { IToolDefinition, IToolResponse, IToolContext, IMcpGateDecision, McpGateResolver, } from './server/tool-definition.js';
|
|
6
6
|
export { MCP_PROTOCOL_VERSION, MCP_SERVER_NAME, MCP_SERVER_VERSION, } from './server/mcp-server-config.js';
|
|
7
7
|
export { buildResourceList, readResource, parseResourceUri, knowledgeUri, templateUri, docUri, OVERVIEW_URI, AGENT_INSTRUCTIONS_URI, URI_SCHEME, } from './resources/index.js';
|
|
8
|
+
export { getRelevantContextTool } from './tools/get-relevant-context.tool.js';
|
|
9
|
+
export { getTaskPacketTool } from './tools/get-task-packet.tool.js';
|
|
10
|
+
export { prepareAgentTaskTool } from './tools/r33-agent-task-prep.tool.js';
|
|
11
|
+
export { COMMAND_CATALOG_EXPORT } from './tools/command-catalog.tool.js';
|
|
8
12
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,sBAAsB,EACtB,iBAAiB,EACjB,KAAK,qBAAqB,EAC1B,KAAK,6BAA6B,GACnC,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,KAAK,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACpF,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAK7C,YAAY,EACV,eAAe,EACf,aAAa,EACb,YAAY,EACZ,gBAAgB,EAChB,eAAe,GAChB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,oBAAoB,EACpB,eAAe,EACf,kBAAkB,GACnB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,MAAM,EACN,YAAY,EACZ,sBAAsB,EACtB,UAAU,GACX,MAAM,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,sBAAsB,EACtB,iBAAiB,EACjB,KAAK,qBAAqB,EAC1B,KAAK,6BAA6B,GACnC,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,KAAK,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACpF,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAK7C,YAAY,EACV,eAAe,EACf,aAAa,EACb,YAAY,EACZ,gBAAgB,EAChB,eAAe,GAChB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,oBAAoB,EACpB,eAAe,EACf,kBAAkB,GACnB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,MAAM,EACN,YAAY,EACZ,sBAAsB,EACtB,UAAU,GACX,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -4,3 +4,7 @@ export { startSharkcraftWatcher } from "./server/sharkcraft-watcher.js";
|
|
|
4
4
|
export { ALL_TOOLS } from "./tools/index.js";
|
|
5
5
|
export { MCP_PROTOCOL_VERSION, MCP_SERVER_NAME, MCP_SERVER_VERSION, } from "./server/mcp-server-config.js";
|
|
6
6
|
export { buildResourceList, readResource, parseResourceUri, knowledgeUri, templateUri, docUri, OVERVIEW_URI, AGENT_INSTRUCTIONS_URI, URI_SCHEME, } from "./resources/index.js";
|
|
7
|
+
export { getRelevantContextTool } from "./tools/get-relevant-context.tool.js";
|
|
8
|
+
export { getTaskPacketTool } from "./tools/get-task-packet.tool.js";
|
|
9
|
+
export { prepareAgentTaskTool } from "./tools/r33-agent-task-prep.tool.js";
|
|
10
|
+
export { COMMAND_CATALOG_EXPORT } from "./tools/command-catalog.tool.js";
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One-line explainer shipped alongside a columnar payload so an agent can decode
|
|
3
|
+
* it. Kept terse on purpose: this string is paid once per columnar response, so
|
|
4
|
+
* a shorter legend is a real per-response token saving — and a smaller fixed
|
|
5
|
+
* cost means the net-loss guard keeps `table` form on more (smaller) payloads.
|
|
6
|
+
*/
|
|
7
|
+
export declare const COLUMNAR_LEGEND = "_table: rows[i] are values in cols order; absent=[row,col] keys to skip when rebuilding objects. If _table.dict[col] exists, that column\u2019s cells are integer indices into dict[col].";
|
|
8
|
+
/** Shared `format` input fragment for list tools that support columnar output. */
|
|
9
|
+
export declare const FORMAT_INPUT_PROPERTY: {
|
|
10
|
+
format: {
|
|
11
|
+
type: "string";
|
|
12
|
+
enum: readonly ["json", "table"];
|
|
13
|
+
description: string;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
/** Whether a tool should emit columnar for this request. */
|
|
17
|
+
export declare function wantsTable(input: Record<string, unknown>): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Shape a list tool's homogeneous rows for output. `format:"table"` returns a
|
|
20
|
+
* columnar envelope (`{ format, legend, items }`) — still valid JSON but with
|
|
21
|
+
* the schema hoisted out of every row. Any other value returns the bare array
|
|
22
|
+
* unchanged (back-compat). If the rows don't qualify for compaction, the bare
|
|
23
|
+
* array is returned so callers always get valid data.
|
|
24
|
+
*/
|
|
25
|
+
export declare function formatRows(rows: ReadonlyArray<Record<string, unknown>>, input: Record<string, unknown>): unknown;
|
|
26
|
+
/**
|
|
27
|
+
* Columnar-compact the top-level array fields of a result OBJECT (e.g. a graph
|
|
28
|
+
* query's `{ directDependents: [...], transitiveDependents: [...] }`) when the
|
|
29
|
+
* caller asked for `format:"table"`. Each compactable array becomes a columnar
|
|
30
|
+
* envelope; scalars, small arrays, and heterogeneous arrays are left as-is.
|
|
31
|
+
* Returns the original object unchanged when nothing compacted (back-compat).
|
|
32
|
+
*/
|
|
33
|
+
export declare function formatObjectArrays(data: unknown, input: Record<string, unknown>): unknown;
|
|
34
|
+
//# sourceMappingURL=columnar-format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"columnar-format.d.ts","sourceRoot":"","sources":["../../src/server/columnar-format.ts"],"names":[],"mappings":"AAOA;;;;;GAKG;AACH,eAAO,MAAM,eAAe,8LAC4J,CAAC;AAEzL,kFAAkF;AAClF,eAAO,MAAM,qBAAqB;;;;;;CAOjC,CAAC;AAiBF,4DAA4D;AAC5D,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAIlE;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAC5C,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,OAAO,CAQT;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CA0BzF"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { compactArrayToColumnar, estimateTokens, EContentType } from '@shrkcrft/compress';
|
|
2
|
+
/** Token cost of a value as minified JSON — the shape the wire serializes. */
|
|
3
|
+
function jsonTokens(value) {
|
|
4
|
+
return estimateTokens(JSON.stringify(value) ?? 'null', EContentType.Json);
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* One-line explainer shipped alongside a columnar payload so an agent can decode
|
|
8
|
+
* it. Kept terse on purpose: this string is paid once per columnar response, so
|
|
9
|
+
* a shorter legend is a real per-response token saving — and a smaller fixed
|
|
10
|
+
* cost means the net-loss guard keeps `table` form on more (smaller) payloads.
|
|
11
|
+
*/
|
|
12
|
+
export const COLUMNAR_LEGEND = '_table: rows[i] are values in cols order; absent=[row,col] keys to skip when rebuilding objects. If _table.dict[col] exists, that column’s cells are integer indices into dict[col].';
|
|
13
|
+
/** Shared `format` input fragment for list tools that support columnar output. */
|
|
14
|
+
export const FORMAT_INPUT_PROPERTY = {
|
|
15
|
+
format: {
|
|
16
|
+
type: 'string',
|
|
17
|
+
enum: ['json', 'table'],
|
|
18
|
+
description: 'json: explicit object array. table: token-efficient columnar encoding (still valid JSON, schema hoisted, keys deduped) — recommended for large lists. Default is table; set SHRK_MCP_TABLE=0 on the server (or pass format:"json") for the explicit array.',
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
/** Deployment toggle: whether columnar `table` is the default wire shape.
|
|
22
|
+
* Default ON — every columnar-capable tool emits `table` so agents get the
|
|
23
|
+
* token savings without asking. Set `SHRK_MCP_TABLE=0` (or `false`/`no`/`off`)
|
|
24
|
+
* to opt out fleet-wide and restore the explicit-array shape for clients that
|
|
25
|
+
* need it. `format:"json"` always forces the explicit array per call,
|
|
26
|
+
* `format:"table"` always forces columnar — both override this default.
|
|
27
|
+
*
|
|
28
|
+
* Compaction itself is conservative: `compactArrayToColumnar` returns null for
|
|
29
|
+
* small / heterogeneous arrays, so default-on only reshapes payloads where the
|
|
30
|
+
* columnar form is an actual win; everything else stays a bare array. */
|
|
31
|
+
function tableIsDefault() {
|
|
32
|
+
const v = (process.env.SHRK_MCP_TABLE ?? '').toLowerCase();
|
|
33
|
+
return v !== '0' && v !== 'false' && v !== 'no' && v !== 'off';
|
|
34
|
+
}
|
|
35
|
+
/** Whether a tool should emit columnar for this request. */
|
|
36
|
+
export function wantsTable(input) {
|
|
37
|
+
if (input.format === 'table')
|
|
38
|
+
return true;
|
|
39
|
+
if (input.format === 'json')
|
|
40
|
+
return false;
|
|
41
|
+
return tableIsDefault();
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Shape a list tool's homogeneous rows for output. `format:"table"` returns a
|
|
45
|
+
* columnar envelope (`{ format, legend, items }`) — still valid JSON but with
|
|
46
|
+
* the schema hoisted out of every row. Any other value returns the bare array
|
|
47
|
+
* unchanged (back-compat). If the rows don't qualify for compaction, the bare
|
|
48
|
+
* array is returned so callers always get valid data.
|
|
49
|
+
*/
|
|
50
|
+
export function formatRows(rows, input) {
|
|
51
|
+
if (!wantsTable(input))
|
|
52
|
+
return rows;
|
|
53
|
+
const columnar = compactArrayToColumnar(rows);
|
|
54
|
+
if (!columnar)
|
|
55
|
+
return rows;
|
|
56
|
+
const candidate = { format: 'table', legend: COLUMNAR_LEGEND, items: columnar };
|
|
57
|
+
// Net-loss guard: the legend + envelope can exceed the bare array on a small
|
|
58
|
+
// list. Ship whichever is smaller so `format:"table"` never inflates a payload.
|
|
59
|
+
return jsonTokens(candidate) < jsonTokens(rows) ? candidate : rows;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Columnar-compact the top-level array fields of a result OBJECT (e.g. a graph
|
|
63
|
+
* query's `{ directDependents: [...], transitiveDependents: [...] }`) when the
|
|
64
|
+
* caller asked for `format:"table"`. Each compactable array becomes a columnar
|
|
65
|
+
* envelope; scalars, small arrays, and heterogeneous arrays are left as-is.
|
|
66
|
+
* Returns the original object unchanged when nothing compacted (back-compat).
|
|
67
|
+
*/
|
|
68
|
+
export function formatObjectArrays(data, input) {
|
|
69
|
+
if (!wantsTable(input) || data === null || typeof data !== 'object' || Array.isArray(data)) {
|
|
70
|
+
return data;
|
|
71
|
+
}
|
|
72
|
+
const src = data;
|
|
73
|
+
const out = {};
|
|
74
|
+
let compacted = false;
|
|
75
|
+
for (const [key, value] of Object.entries(src)) {
|
|
76
|
+
if (Array.isArray(value)) {
|
|
77
|
+
const table = compactArrayToColumnar(value);
|
|
78
|
+
// Per-array net-loss guard: only hoist an array whose columnar form is
|
|
79
|
+
// actually smaller — a tiny array loses to its own hoisted schema header.
|
|
80
|
+
if (table && jsonTokens(table) < jsonTokens(value)) {
|
|
81
|
+
out[key] = table;
|
|
82
|
+
compacted = true;
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
out[key] = value;
|
|
87
|
+
}
|
|
88
|
+
if (!compacted)
|
|
89
|
+
return data;
|
|
90
|
+
const candidate = { _format: 'table', _legend: COLUMNAR_LEGEND, ...out };
|
|
91
|
+
// Overall net-loss guard: the shared legend must not push the whole payload
|
|
92
|
+
// above the bare object — table mode never inflates (the "never a negative
|
|
93
|
+
// saving" promise the dashboard makes).
|
|
94
|
+
return jsonTokens(candidate) < jsonTokens(data) ? candidate : data;
|
|
95
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
2
|
import { type ISharkcraftInspection } from '@shrkcrft/inspector';
|
|
3
|
+
import { type ICcrStore } from '@shrkcrft/compress';
|
|
3
4
|
import { type IMcpServerConfig } from './mcp-server-config.js';
|
|
4
5
|
import type { IToolDefinition, McpGateResolver } from './tool-definition.js';
|
|
5
6
|
export interface StartMcpServerOptions {
|
|
@@ -40,6 +41,8 @@ interface ServerState {
|
|
|
40
41
|
toolsByName: Map<string, IToolDefinition>;
|
|
41
42
|
/** Optional tier-gate resolver. */
|
|
42
43
|
gateResolver?: McpGateResolver;
|
|
44
|
+
/** In-memory CCR store shared across this server's tool calls. */
|
|
45
|
+
ccrStore: ICcrStore;
|
|
43
46
|
}
|
|
44
47
|
/**
|
|
45
48
|
* Resolve which directory the MCP server should treat as the target project.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-mcp-server.d.ts","sourceRoot":"","sources":["../../src/server/create-mcp-server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAQnE,OAAO,EAAqB,KAAK,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACpF,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EACV,eAAe,EAEf,eAAe,EAChB,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"create-mcp-server.d.ts","sourceRoot":"","sources":["../../src/server/create-mcp-server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAQnE,OAAO,EAAqB,KAAK,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACpF,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEtE,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EACV,eAAe,EAEf,eAAe,EAChB,MAAM,sBAAsB,CAAC;AAM9B,MAAM,WAAW,qBAAqB;IACpC,0DAA0D;IAC1D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,qEAAqE;IACrE,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC7B,yCAAyC;IACzC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yCAAyC;IACzC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,YAAY,CAAC,EAAE,eAAe,CAAC;CAChC;AAED,MAAM,WAAW,6BAA8B,SAAQ,gBAAgB;IACrE,0DAA0D;IAC1D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sDAAsD;IACtD,YAAY,CAAC,EAAE,eAAe,CAAC;CAChC;AAED,UAAU,WAAW;IACnB,MAAM,EAAE,gBAAgB,CAAC;IACzB,UAAU,EAAE,qBAAqB,GAAG,IAAI,CAAC;IACzC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC1C,mCAAmC;IACnC,YAAY,CAAC,EAAE,eAAe,CAAC;IAC/B,kEAAkE;IAClE,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,iBAAiB,EAAE,MAAM,GAAG,SAAS,EACrC,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,GACpD,MAAM,CAIR;AAqBD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,6BAA6B,GAAG;IAC7E,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,WAAW,CAAC;CACpB,CAiIA;AAED,wBAAsB,cAAc,CAAC,OAAO,GAAE,qBAA0B,GAAG,OAAO,CAAC,IAAI,CAAC,CAmEvF"}
|
|
@@ -3,8 +3,11 @@ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
|
3
3
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
4
|
import { CallToolRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, ReadResourceRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
5
5
|
import { inspectSharkcraft } from '@shrkcrft/inspector';
|
|
6
|
+
import { InMemoryCcrStore } from '@shrkcrft/compress';
|
|
7
|
+
import { serializeToolData } from "./serialize-tool-data.js";
|
|
6
8
|
import { MCP_SERVER_NAME, MCP_SERVER_VERSION, } from "./mcp-server-config.js";
|
|
7
9
|
import { ALL_TOOLS } from "../tools/index.js";
|
|
10
|
+
import { PRIMARY_MCP_TOOLS, shouldAdvertiseFullToolset } from "../tools/primary-tools.js";
|
|
8
11
|
import { validateToolInput } from "./tool-input-validators.js";
|
|
9
12
|
import { buildResourceList, readResource } from "../resources/index.js";
|
|
10
13
|
/**
|
|
@@ -26,7 +29,7 @@ function toolResponseToCallResult(response) {
|
|
|
26
29
|
if (response.text)
|
|
27
30
|
content.push({ type: 'text', text: response.text });
|
|
28
31
|
if (response.data !== undefined) {
|
|
29
|
-
content.push({ type: 'text', text:
|
|
32
|
+
content.push({ type: 'text', text: serializeToolData(response.data) });
|
|
30
33
|
}
|
|
31
34
|
if (content.length === 0)
|
|
32
35
|
content.push({ type: 'text', text: '(empty)' });
|
|
@@ -44,6 +47,7 @@ export function createSharkcraftServer(config) {
|
|
|
44
47
|
config: effectiveConfig,
|
|
45
48
|
inspection: null,
|
|
46
49
|
toolsByName: new Map(ALL_TOOLS.map((t) => [t.name, t])),
|
|
50
|
+
ccrStore: new InMemoryCcrStore(),
|
|
47
51
|
...(config.gateResolver ? { gateResolver: config.gateResolver } : {}),
|
|
48
52
|
};
|
|
49
53
|
const server = new Server({ name: effectiveConfig.name, version: effectiveConfig.version }, {
|
|
@@ -52,13 +56,24 @@ export function createSharkcraftServer(config) {
|
|
|
52
56
|
resources: { listChanged: true },
|
|
53
57
|
},
|
|
54
58
|
});
|
|
55
|
-
server.setRequestHandler(ListToolsRequestSchema, async () =>
|
|
56
|
-
tools
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
60
|
+
// Default `tools/list` advertises only the ~30 primary tools to
|
|
61
|
+
// keep the agent's tool-selection surface focused. The other ~200
|
|
62
|
+
// tools stay CALLABLE via `tools/call` for agents that already
|
|
63
|
+
// know the name (e.g. via `shrk export claude-skill` referencing
|
|
64
|
+
// them). Set SHRK_MCP_FULL_TOOLS=1 to advertise everything.
|
|
65
|
+
const advertiseFull = shouldAdvertiseFullToolset();
|
|
66
|
+
const advertised = advertiseFull
|
|
67
|
+
? ALL_TOOLS
|
|
68
|
+
: ALL_TOOLS.filter((t) => PRIMARY_MCP_TOOLS.has(t.name));
|
|
69
|
+
return {
|
|
70
|
+
tools: advertised.map((t) => ({
|
|
71
|
+
name: t.name,
|
|
72
|
+
description: t.description,
|
|
73
|
+
inputSchema: t.inputSchema,
|
|
74
|
+
})),
|
|
75
|
+
};
|
|
76
|
+
});
|
|
62
77
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
63
78
|
const name = request.params.name;
|
|
64
79
|
const args = (request.params.arguments ?? {});
|
|
@@ -112,7 +127,7 @@ export function createSharkcraftServer(config) {
|
|
|
112
127
|
}
|
|
113
128
|
try {
|
|
114
129
|
const inspection = await loadInspection(state);
|
|
115
|
-
const response = await tool.handler(validation.data, { inspection, cwd: state.config.cwd });
|
|
130
|
+
const response = await tool.handler(validation.data, { inspection, cwd: state.config.cwd, allTools: ALL_TOOLS, ccrStore: state.ccrStore });
|
|
116
131
|
return toolResponseToCallResult(response);
|
|
117
132
|
}
|
|
118
133
|
catch (e) {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type ICcrStore } from '@shrkcrft/compress';
|
|
2
|
+
export interface IFittedArray {
|
|
3
|
+
/** The array shaped for output: lossless columnar, or a lossy sample. */
|
|
4
|
+
value: unknown;
|
|
5
|
+
/** Set when a lossy sample was taken — the CCR key for the cached original. */
|
|
6
|
+
ccrKey?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Fit a homogeneous object array to an optional token budget (P5.2).
|
|
10
|
+
*
|
|
11
|
+
* - No budget (or under budget): the lossless columnar form.
|
|
12
|
+
* - Over budget: the SmartCrusher row-sample (representative rows kept, the
|
|
13
|
+
* rest dropped) with the FULL original cached in `store` — the agent can
|
|
14
|
+
* `retrieve_original` with the returned `ccrKey`.
|
|
15
|
+
*
|
|
16
|
+
* `compressJson({ maxTokens })` owns the lossless-vs-lossy DECISION, but its
|
|
17
|
+
* sampler keep-count is not derived from the budget, so a single sample can
|
|
18
|
+
* still exceed `maxTokens`. We therefore binary-search the row cap so the
|
|
19
|
+
* emitted payload actually fits the budget (down to a 1-row floor — a single
|
|
20
|
+
* row's columnar envelope may still exceed a very small budget, which is the
|
|
21
|
+
* best achievable while keeping any data).
|
|
22
|
+
*/
|
|
23
|
+
export declare function fitArrayToBudget(array: readonly unknown[], maxTokens: number | undefined, store?: ICcrStore): IFittedArray;
|
|
24
|
+
//# sourceMappingURL=fit-array-to-budget.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fit-array-to-budget.d.ts","sourceRoot":"","sources":["../../src/server/fit-array-to-budget.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,oBAAoB,CAAC;AAE5B,MAAM,WAAW,YAAY;IAC3B,yEAAyE;IACzE,KAAK,EAAE,OAAO,CAAC;IACf,+EAA+E;IAC/E,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,SAAS,OAAO,EAAE,EACzB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,KAAK,CAAC,EAAE,SAAS,GAChB,YAAY,CA2Cd"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { compactArrayToColumnar, compressJson, estimateTokens, EContentType, } from '@shrkcrft/compress';
|
|
2
|
+
/**
|
|
3
|
+
* Fit a homogeneous object array to an optional token budget (P5.2).
|
|
4
|
+
*
|
|
5
|
+
* - No budget (or under budget): the lossless columnar form.
|
|
6
|
+
* - Over budget: the SmartCrusher row-sample (representative rows kept, the
|
|
7
|
+
* rest dropped) with the FULL original cached in `store` — the agent can
|
|
8
|
+
* `retrieve_original` with the returned `ccrKey`.
|
|
9
|
+
*
|
|
10
|
+
* `compressJson({ maxTokens })` owns the lossless-vs-lossy DECISION, but its
|
|
11
|
+
* sampler keep-count is not derived from the budget, so a single sample can
|
|
12
|
+
* still exceed `maxTokens`. We therefore binary-search the row cap so the
|
|
13
|
+
* emitted payload actually fits the budget (down to a 1-row floor — a single
|
|
14
|
+
* row's columnar envelope may still exceed a very small budget, which is the
|
|
15
|
+
* best achievable while keeping any data).
|
|
16
|
+
*/
|
|
17
|
+
export function fitArrayToBudget(array, maxTokens, store) {
|
|
18
|
+
const columnar = compactArrayToColumnar(array) ?? array;
|
|
19
|
+
if (!maxTokens || maxTokens <= 0)
|
|
20
|
+
return { value: columnar };
|
|
21
|
+
const json = JSON.stringify(array);
|
|
22
|
+
const run = (maxItems) => {
|
|
23
|
+
const r = compressJson(json, {
|
|
24
|
+
maxTokens,
|
|
25
|
+
...(maxItems !== undefined ? { maxItems } : {}),
|
|
26
|
+
...(store ? { store } : {}),
|
|
27
|
+
});
|
|
28
|
+
// A CCR key is set only on the lossy sample path; under budget the result
|
|
29
|
+
// is the lossless form, so the caller falls back to the columnar value.
|
|
30
|
+
if (!r.ccrKey)
|
|
31
|
+
return null;
|
|
32
|
+
const firstLine = r.compressed.split('\n')[0] ?? 'null';
|
|
33
|
+
return { value: JSON.parse(firstLine), ccrKey: r.ccrKey };
|
|
34
|
+
};
|
|
35
|
+
const fits = (fitted) => estimateTokens(JSON.stringify(fitted.value), EContentType.JsonArray) <= maxTokens;
|
|
36
|
+
// Default sample (no cap). Null → under budget, emit the lossless form.
|
|
37
|
+
const initial = run();
|
|
38
|
+
if (!initial)
|
|
39
|
+
return { value: columnar };
|
|
40
|
+
if (fits(initial))
|
|
41
|
+
return initial;
|
|
42
|
+
// Largest row cap whose sampled payload still fits the budget.
|
|
43
|
+
let lo = 1;
|
|
44
|
+
let hi = array.length;
|
|
45
|
+
let best = null;
|
|
46
|
+
while (lo <= hi) {
|
|
47
|
+
const mid = Math.floor((lo + hi) / 2);
|
|
48
|
+
const candidate = run(mid);
|
|
49
|
+
if (candidate && fits(candidate)) {
|
|
50
|
+
best = candidate;
|
|
51
|
+
lo = mid + 1;
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
hi = mid - 1;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// Even one row over budget → keep the smallest sample (best effort, still
|
|
58
|
+
// recoverable via ccrKey) rather than the much larger default sample.
|
|
59
|
+
return best ?? run(1) ?? initial;
|
|
60
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serialize a tool's structured `data` into the text the MCP wire carries.
|
|
3
|
+
*
|
|
4
|
+
* The default is **minified** JSON: still valid JSON (identical shape, so
|
|
5
|
+
* JSON-parsing clients are unaffected), but without the pretty-print
|
|
6
|
+
* indentation that every `JSON.stringify(data, null, 2)` paid for. Across
|
|
7
|
+
* ~200 tools that indentation is pure token overhead an agent reads and pays
|
|
8
|
+
* for. Set `SHRK_MCP_PRETTY=1` to restore indented output for debugging.
|
|
9
|
+
*
|
|
10
|
+
* This transform is lossless and structure-preserving by design. Lossy /
|
|
11
|
+
* shape-changing compaction (columnar tables, CCR offload) is opt-in per
|
|
12
|
+
* tool, never applied blindly here.
|
|
13
|
+
*/
|
|
14
|
+
export declare function serializeToolData(data: unknown): string;
|
|
15
|
+
//# sourceMappingURL=serialize-tool-data.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serialize-tool-data.d.ts","sourceRoot":"","sources":["../../src/server/serialize-tool-data.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAGvD"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serialize a tool's structured `data` into the text the MCP wire carries.
|
|
3
|
+
*
|
|
4
|
+
* The default is **minified** JSON: still valid JSON (identical shape, so
|
|
5
|
+
* JSON-parsing clients are unaffected), but without the pretty-print
|
|
6
|
+
* indentation that every `JSON.stringify(data, null, 2)` paid for. Across
|
|
7
|
+
* ~200 tools that indentation is pure token overhead an agent reads and pays
|
|
8
|
+
* for. Set `SHRK_MCP_PRETTY=1` to restore indented output for debugging.
|
|
9
|
+
*
|
|
10
|
+
* This transform is lossless and structure-preserving by design. Lossy /
|
|
11
|
+
* shape-changing compaction (columnar tables, CCR offload) is opt-in per
|
|
12
|
+
* tool, never applied blindly here.
|
|
13
|
+
*/
|
|
14
|
+
export function serializeToolData(data) {
|
|
15
|
+
if (wantsPretty())
|
|
16
|
+
return JSON.stringify(data, null, 2) ?? 'null';
|
|
17
|
+
return JSON.stringify(data) ?? 'null';
|
|
18
|
+
}
|
|
19
|
+
function wantsPretty() {
|
|
20
|
+
const v = process.env.SHRK_MCP_PRETTY;
|
|
21
|
+
return v === '1' || v === 'true' || v === 'yes';
|
|
22
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ISharkcraftInspection } from '@shrkcrft/inspector';
|
|
2
|
+
import type { ICcrStore } from '@shrkcrft/compress';
|
|
2
3
|
export interface IToolJsonSchema {
|
|
3
4
|
type: 'object';
|
|
4
5
|
properties?: Record<string, unknown>;
|
|
@@ -8,6 +9,20 @@ export interface IToolJsonSchema {
|
|
|
8
9
|
export interface IToolContext {
|
|
9
10
|
inspection: ISharkcraftInspection;
|
|
10
11
|
cwd: string;
|
|
12
|
+
/**
|
|
13
|
+
* The full list of tools registered in the server. Tools that need
|
|
14
|
+
* to self-reflect (e.g. `get_safety_audit`) use this instead of
|
|
15
|
+
* importing `ALL_TOOLS` from the tool-registry to avoid import cycles.
|
|
16
|
+
*/
|
|
17
|
+
allTools?: readonly IToolDefinition[];
|
|
18
|
+
/**
|
|
19
|
+
* Per-server in-memory Compress-Cache-Retrieve store. The
|
|
20
|
+
* `compress_context` tool caches originals here and `retrieve_original`
|
|
21
|
+
* reads them back. In-memory only — the MCP server never writes to disk,
|
|
22
|
+
* honouring the read-only contract. Absent in unit tests that construct a
|
|
23
|
+
* bare context.
|
|
24
|
+
*/
|
|
25
|
+
ccrStore?: ICcrStore;
|
|
11
26
|
}
|
|
12
27
|
export interface IToolDefinition {
|
|
13
28
|
name: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-definition.d.ts","sourceRoot":"","sources":["../../src/server/tool-definition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"tool-definition.d.ts","sourceRoot":"","sources":["../../src/server/tool-definition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEpD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,QAAQ,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,qBAAqB,CAAC;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,QAAQ,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IACtC;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,eAAe,CAAC;IAC7B,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,YAAY,KAAK,OAAO,CAAC,aAAa,CAAC,GAAG,aAAa,CAAC;IAC3G;;;;;;;;;OASG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,eAAe,GAAG,CAAC,IAAI,EAAE,eAAe,KAAK,gBAAgB,GAAG,IAAI,CAAC;AAEjF,MAAM,WAAW,UAAU;IACzB,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAC;IACb,8BAA8B;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,2BAA2B;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,uDAAuD;IACvD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2EAA2E;IAC3E,KAAK,CAAC,EAAE,UAAU,CAAC;CACpB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-input-validators.d.ts","sourceRoot":"","sources":["../../src/server/tool-input-validators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"tool-input-validators.d.ts","sourceRoot":"","sources":["../../src/server/tool-input-validators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAmIxB,eAAO,MAAM,kBAAkB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,CAAC,CAsBpE,CAAC;AAEH,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC7C;AAED,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,OAAO,GACb;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,sBAAsB,CAAA;CAAE,CAkB9E"}
|
|
@@ -38,6 +38,7 @@ const getRelevantContextSchema = z
|
|
|
38
38
|
includeRules: z.boolean().optional(),
|
|
39
39
|
includePaths: z.boolean().optional(),
|
|
40
40
|
includeDocs: z.boolean().optional(),
|
|
41
|
+
compact: z.boolean().optional(),
|
|
41
42
|
})
|
|
42
43
|
.strict();
|
|
43
44
|
const getRelevantRulesSchema = z
|
|
@@ -75,6 +76,42 @@ const getPipelineContextSchema = z
|
|
|
75
76
|
scope: z.array(z.string()).optional(),
|
|
76
77
|
})
|
|
77
78
|
.strict();
|
|
79
|
+
const compressContextSchema = z
|
|
80
|
+
.object({
|
|
81
|
+
content: z.string().min(1, 'content is required'),
|
|
82
|
+
contentType: z.string().optional(),
|
|
83
|
+
query: z.string().optional(),
|
|
84
|
+
maxItems: z.number().int().min(1).optional(),
|
|
85
|
+
// Arms the lossy SmartCrusher row-sampler for oversized homogeneous arrays.
|
|
86
|
+
// Must mirror the tool's inputSchema, or the strict validator rejects the
|
|
87
|
+
// call on the real MCP wire before the handler ever runs.
|
|
88
|
+
maxTokens: z.number().int().min(1).optional(),
|
|
89
|
+
})
|
|
90
|
+
.strict();
|
|
91
|
+
const retrieveOriginalSchema = z.object({ key: z.string().min(1, 'key is required') }).strict();
|
|
92
|
+
const alignCacheSchema = z
|
|
93
|
+
.object({ content: z.string().min(1, 'content is required'), map: z.unknown().optional() })
|
|
94
|
+
.strict();
|
|
95
|
+
const restoreCacheSchema = z
|
|
96
|
+
.object({ content: z.string(), map: z.unknown() })
|
|
97
|
+
.strict();
|
|
98
|
+
const getKnowledgeGraphSchema = z
|
|
99
|
+
.object({
|
|
100
|
+
format: z.enum(['json', 'table']).optional(),
|
|
101
|
+
// Mirrors the tool's inputSchema (P5.2). Must stay in lockstep, or the
|
|
102
|
+
// schema-parity guard (schema-parity.test.ts) turns red.
|
|
103
|
+
maxTokens: z.number().int().min(1).optional(),
|
|
104
|
+
})
|
|
105
|
+
.strict();
|
|
106
|
+
// deps_audit advertises package/format/maxTokens; validate them on the wire so
|
|
107
|
+
// the new lossy `maxTokens` budget can't be armed with a bad value (P5.2/P1.3).
|
|
108
|
+
const depsAuditSchema = z
|
|
109
|
+
.object({
|
|
110
|
+
package: z.string().optional(),
|
|
111
|
+
format: z.enum(['json', 'table']).optional(),
|
|
112
|
+
maxTokens: z.number().int().min(1).optional(),
|
|
113
|
+
})
|
|
114
|
+
.strict();
|
|
78
115
|
export const TOOL_INPUT_SCHEMAS = Object.freeze({
|
|
79
116
|
create_generation_plan: createGenerationPlanSchema,
|
|
80
117
|
render_template_preview: renderTemplatePreviewSchema,
|
|
@@ -91,6 +128,12 @@ export const TOOL_INPUT_SCHEMAS = Object.freeze({
|
|
|
91
128
|
get_pipeline_context: getPipelineContextSchema,
|
|
92
129
|
get_pack: getPackSchema,
|
|
93
130
|
create_pipeline_plan: createPipelinePlanSchema,
|
|
131
|
+
compress_context: compressContextSchema,
|
|
132
|
+
retrieve_original: retrieveOriginalSchema,
|
|
133
|
+
align_cache: alignCacheSchema,
|
|
134
|
+
restore_cache: restoreCacheSchema,
|
|
135
|
+
get_knowledge_graph: getKnowledgeGraphSchema,
|
|
136
|
+
deps_audit: depsAuditSchema,
|
|
94
137
|
});
|
|
95
138
|
export function validateToolInput(toolName, input) {
|
|
96
139
|
const schema = TOOL_INPUT_SCHEMAS[toolName];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-brief.tool.d.ts","sourceRoot":"","sources":["../../src/tools/agent-brief.tool.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"agent-brief.tool.d.ts","sourceRoot":"","sources":["../../src/tools/agent-brief.tool.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAIpE,eAAO,MAAM,oBAAoB,EAAE,eA+DlC,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { buildAgentBrief, BriefMode } from '@shrkcrft/inspector';
|
|
2
|
+
import { compressMarkdown } from '@shrkcrft/compress';
|
|
2
3
|
const VALID_MODES = new Set(Object.values(BriefMode));
|
|
3
4
|
export const createAgentBriefTool = {
|
|
4
5
|
name: 'create_agent_brief',
|
|
@@ -14,6 +15,10 @@ export const createAgentBriefTool = {
|
|
|
14
15
|
maxTokens: { type: 'number' },
|
|
15
16
|
chunked: { type: 'boolean' },
|
|
16
17
|
sectionBudgets: { type: 'object' },
|
|
18
|
+
compact: {
|
|
19
|
+
type: 'boolean',
|
|
20
|
+
description: 'Run the brief markdown through the deterministic markdown compressor (headers/leads/structure kept, prose thinned). Reversible — the original is cached and a `<<ccr:KEY>>` marker emitted (retrieve_original to recover).',
|
|
21
|
+
},
|
|
17
22
|
},
|
|
18
23
|
additionalProperties: false,
|
|
19
24
|
},
|
|
@@ -39,6 +44,21 @@ export const createAgentBriefTool = {
|
|
|
39
44
|
...(chunked ? { chunked: true } : {}),
|
|
40
45
|
...(sectionBudgets ? { sectionBudgets } : {}),
|
|
41
46
|
});
|
|
47
|
+
if (input['compact'] === true) {
|
|
48
|
+
const c = compressMarkdown(brief.markdown, ctx.ccrStore ? { store: ctx.ccrStore } : {});
|
|
49
|
+
return {
|
|
50
|
+
data: {
|
|
51
|
+
...brief,
|
|
52
|
+
markdown: c.compressed,
|
|
53
|
+
compaction: {
|
|
54
|
+
strategy: c.strategy,
|
|
55
|
+
tokensBefore: c.savings.before,
|
|
56
|
+
tokensAfter: c.savings.after,
|
|
57
|
+
ccrKey: c.ccrKey ?? null,
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
}
|
|
42
62
|
return { data: brief };
|
|
43
63
|
},
|
|
44
64
|
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { IToolDefinition } from '../server/tool-definition.js';
|
|
2
|
+
/**
|
|
3
|
+
* Active cache-aligner: replace volatile tokens with stable placeholders so a
|
|
4
|
+
* provider KV-cache prefix stays steady across turns. Returns the map in the
|
|
5
|
+
* payload (never writes disk) so the host carries it forward — honouring
|
|
6
|
+
* MCP-never-writes. Reversible via `restore_cache`.
|
|
7
|
+
*/
|
|
8
|
+
export declare const alignCacheTool: IToolDefinition;
|
|
9
|
+
/** The restore half of {@link alignCacheTool}. Read-only. */
|
|
10
|
+
export declare const restoreCacheTool: IToolDefinition;
|
|
11
|
+
//# sourceMappingURL=align-cache.tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"align-cache.tool.d.ts","sourceRoot":"","sources":["../../src/tools/align-cache.tool.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AASpE;;;;;GAKG;AACH,eAAO,MAAM,cAAc,EAAE,eAkC5B,CAAC;AAEF,6DAA6D;AAC7D,eAAO,MAAM,gBAAgB,EAAE,eA0B9B,CAAC"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { alignVolatileTokens, restoreVolatileTokens } from '@shrkcrft/compress';
|
|
2
|
+
function asAlignmentMap(value) {
|
|
3
|
+
if (typeof value !== 'object' || value === null)
|
|
4
|
+
return undefined;
|
|
5
|
+
const m = value;
|
|
6
|
+
if (m.version !== 1 || !Array.isArray(m.bindings))
|
|
7
|
+
return undefined;
|
|
8
|
+
return value;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Active cache-aligner: replace volatile tokens with stable placeholders so a
|
|
12
|
+
* provider KV-cache prefix stays steady across turns. Returns the map in the
|
|
13
|
+
* payload (never writes disk) so the host carries it forward — honouring
|
|
14
|
+
* MCP-never-writes. Reversible via `restore_cache`.
|
|
15
|
+
*/
|
|
16
|
+
export const alignCacheTool = {
|
|
17
|
+
name: 'align_cache',
|
|
18
|
+
description: 'Replace volatile tokens (UUIDs, JWTs, ISO timestamps, hashes, epochs) in a blob with stable `«vk:…»` placeholders so a provider KV-cache prefix stays stable across turns — same information, fewer cache-busting tokens. Returns the aligned text plus a map; pass the map back in next turn (and to `restore_cache`) so placeholders stay stable. Deterministic, reversible, no model. Read-only.',
|
|
19
|
+
inputSchema: {
|
|
20
|
+
type: 'object',
|
|
21
|
+
properties: {
|
|
22
|
+
content: { type: 'string', description: 'The text to align.' },
|
|
23
|
+
map: { type: 'object', description: 'A prior alignment map to carry forward (optional).' },
|
|
24
|
+
},
|
|
25
|
+
required: ['content'],
|
|
26
|
+
additionalProperties: false,
|
|
27
|
+
},
|
|
28
|
+
handler(input) {
|
|
29
|
+
const content = typeof input.content === 'string' ? input.content : '';
|
|
30
|
+
if (content.length === 0) {
|
|
31
|
+
return {
|
|
32
|
+
isError: true,
|
|
33
|
+
text: 'align_cache requires a non-empty "content" string.',
|
|
34
|
+
error: { code: 'invalid-input', message: 'content is required' },
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
const prior = asAlignmentMap(input.map);
|
|
38
|
+
const result = alignVolatileTokens(content, prior);
|
|
39
|
+
return {
|
|
40
|
+
data: {
|
|
41
|
+
aligned: result.aligned,
|
|
42
|
+
map: result.map,
|
|
43
|
+
replaced: result.replaced,
|
|
44
|
+
restoreWith: 'restore_cache { "content": "<aligned>", "map": <map> }',
|
|
45
|
+
},
|
|
46
|
+
text: result.aligned,
|
|
47
|
+
};
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
/** The restore half of {@link alignCacheTool}. Read-only. */
|
|
51
|
+
export const restoreCacheTool = {
|
|
52
|
+
name: 'restore_cache',
|
|
53
|
+
description: 'Reverse `align_cache`: restore the original volatile tokens in an aligned blob using its map. Lossless. Read-only.',
|
|
54
|
+
inputSchema: {
|
|
55
|
+
type: 'object',
|
|
56
|
+
properties: {
|
|
57
|
+
content: { type: 'string', description: 'Aligned text containing `«vk:…»` placeholders.' },
|
|
58
|
+
map: { type: 'object', description: 'The alignment map returned by `align_cache`.' },
|
|
59
|
+
},
|
|
60
|
+
required: ['content', 'map'],
|
|
61
|
+
additionalProperties: false,
|
|
62
|
+
},
|
|
63
|
+
handler(input) {
|
|
64
|
+
const content = typeof input.content === 'string' ? input.content : '';
|
|
65
|
+
const map = asAlignmentMap(input.map);
|
|
66
|
+
if (!map) {
|
|
67
|
+
return {
|
|
68
|
+
isError: true,
|
|
69
|
+
text: 'restore_cache requires the `map` returned by align_cache.',
|
|
70
|
+
error: { code: 'invalid-input', message: 'a valid alignment map is required' },
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
const restored = restoreVolatileTokens(content, map);
|
|
74
|
+
return { data: { restored }, text: restored };
|
|
75
|
+
},
|
|
76
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"all-tools.d.ts","sourceRoot":"","sources":["../../src/tools/all-tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"all-tools.d.ts","sourceRoot":"","sources":["../../src/tools/all-tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAkVpE,eAAO,MAAM,SAAS,EAAE,SAAS,eAAe,EA4R9C,CAAC"}
|