@skillstate/mcp 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.
- package/bin/mcp.js +5 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-adapter.d.ts +49 -0
- package/dist/mcp-adapter.d.ts.map +1 -0
- package/dist/mcp-adapter.js +80 -0
- package/dist/mcp-adapter.js.map +1 -0
- package/dist/mcp-server.d.ts +132 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +485 -0
- package/dist/mcp-server.js.map +1 -0
- package/package.json +27 -0
package/bin/mcp.js
ADDED
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { StatePathRef } from '@skillstate/core';
|
|
2
|
+
/** Options for {@link McpAdapter.generateMcpConfig}. */
|
|
3
|
+
export interface McpConfigOptions {
|
|
4
|
+
/** Path to the procedural-spec JSON. Defaults to `./skill-spec.json`. */
|
|
5
|
+
specPath?: string;
|
|
6
|
+
/** Command that starts the server. Defaults to `node`. */
|
|
7
|
+
command?: string;
|
|
8
|
+
/** Absolute launcher module path. Defaults to the package bin entry. */
|
|
9
|
+
launcherPath?: string;
|
|
10
|
+
/** Extra environment variables to merge into the server env. */
|
|
11
|
+
env?: Record<string, string>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* MCP platform adapter (@non-paper; see module doc).
|
|
15
|
+
*/
|
|
16
|
+
export declare class McpAdapter {
|
|
17
|
+
readonly name = "mcp";
|
|
18
|
+
/**
|
|
19
|
+
* Generate a `.mcp.json`-compatible config document registering the
|
|
20
|
+
* `skillstate` server. The config is a plain JSON object:
|
|
21
|
+
*
|
|
22
|
+
* ```json
|
|
23
|
+
* {
|
|
24
|
+
* "mcpServers": {
|
|
25
|
+
* "skillstate": {
|
|
26
|
+
* "command": "node",
|
|
27
|
+
* "args": ["/path/to/bin/mcp.js"],
|
|
28
|
+
* "env": { "SKILLSTATE_STATE_PATH": "...", "SKILLSTATE_SPEC_PATH": "..." }
|
|
29
|
+
* }
|
|
30
|
+
* }
|
|
31
|
+
* }
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* `statePath` accepts a raw path (legacy) or a `{ root, name }` ref
|
|
35
|
+
* confined via `resolveStatePath`. Deterministic and secret-free.
|
|
36
|
+
*/
|
|
37
|
+
generateMcpConfig(statePath: string | StatePathRef, options?: McpConfigOptions): string;
|
|
38
|
+
/**
|
|
39
|
+
* @non-paper additive helper: generate the config and persist it via
|
|
40
|
+
* `atomicWriteFile` (tmp + fsync + rename). Both the destination and the
|
|
41
|
+
* embedded state path accept raw strings (legacy behavior) or
|
|
42
|
+
* `{ root, name }` refs confined by `resolveStatePath`. Returns the
|
|
43
|
+
* absolute destination path.
|
|
44
|
+
*/
|
|
45
|
+
saveMcpConfig(target: string | StatePathRef, statePath: string | StatePathRef, options?: McpConfigOptions): Promise<string>;
|
|
46
|
+
/** Resolve a `string | StatePathRef` via `resolveStatePath`. */
|
|
47
|
+
private resolve;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=mcp-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-adapter.d.ts","sourceRoot":"","sources":["../src/mcp-adapter.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAarD,wDAAwD;AACxD,MAAM,WAAW,gBAAgB;IAC/B,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gEAAgE;IAChE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAED;;GAEG;AACH,qBAAa,UAAU;IACrB,QAAQ,CAAC,IAAI,SAAS;IAEtB;;;;;;;;;;;;;;;;;;OAkBG;IACH,iBAAiB,CACf,SAAS,EAAE,MAAM,GAAG,YAAY,EAChC,OAAO,CAAC,EAAE,gBAAgB,GACzB,MAAM,CAuBR;IAED;;;;;;OAMG;IACG,aAAa,CACjB,MAAM,EAAE,MAAM,GAAG,YAAY,EAC7B,SAAS,EAAE,MAAM,GAAG,YAAY,EAChC,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,MAAM,CAAC,CAMjB;IAMD,gEAAgE;IAChE,OAAO,CAAC,OAAO;CAKhB"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { fileURLToPath } from 'node:url';
|
|
2
|
+
import { atomicWriteFile, resolveStatePath, } from '@skillstate/core';
|
|
3
|
+
/**
|
|
4
|
+
* Default launcher: the umbrella package's MCP stdio entry (`bin/mcp.js`).
|
|
5
|
+
* When installed, `@skillstate/mcp` lives at the same depth as the
|
|
6
|
+
* package's own `dist/` (or `src/`), so `../../../bin/mcp.js` from the
|
|
7
|
+
* compiled module resolves to the root `bin/mcp.js`. Overridable via
|
|
8
|
+
* {@link McpConfigOptions.launcherPath}.
|
|
9
|
+
*/
|
|
10
|
+
const LAUNCHER_PATH = fileURLToPath(new URL('../../../bin/mcp.js', import.meta.url));
|
|
11
|
+
/**
|
|
12
|
+
* MCP platform adapter (@non-paper; see module doc).
|
|
13
|
+
*/
|
|
14
|
+
export class McpAdapter {
|
|
15
|
+
name = 'mcp';
|
|
16
|
+
/**
|
|
17
|
+
* Generate a `.mcp.json`-compatible config document registering the
|
|
18
|
+
* `skillstate` server. The config is a plain JSON object:
|
|
19
|
+
*
|
|
20
|
+
* ```json
|
|
21
|
+
* {
|
|
22
|
+
* "mcpServers": {
|
|
23
|
+
* "skillstate": {
|
|
24
|
+
* "command": "node",
|
|
25
|
+
* "args": ["/path/to/bin/mcp.js"],
|
|
26
|
+
* "env": { "SKILLSTATE_STATE_PATH": "...", "SKILLSTATE_SPEC_PATH": "..." }
|
|
27
|
+
* }
|
|
28
|
+
* }
|
|
29
|
+
* }
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* `statePath` accepts a raw path (legacy) or a `{ root, name }` ref
|
|
33
|
+
* confined via `resolveStatePath`. Deterministic and secret-free.
|
|
34
|
+
*/
|
|
35
|
+
generateMcpConfig(statePath, options) {
|
|
36
|
+
const resolved = this.resolve(statePath);
|
|
37
|
+
const specPath = options?.specPath ?? './skill-spec.json';
|
|
38
|
+
const command = options?.command ?? 'node';
|
|
39
|
+
const launcherPath = options?.launcherPath ?? LAUNCHER_PATH;
|
|
40
|
+
const env = {
|
|
41
|
+
SKILLSTATE_STATE_PATH: resolved,
|
|
42
|
+
SKILLSTATE_SPEC_PATH: specPath,
|
|
43
|
+
...(options?.env ?? {}),
|
|
44
|
+
};
|
|
45
|
+
const doc = {
|
|
46
|
+
mcpServers: {
|
|
47
|
+
skillstate: {
|
|
48
|
+
command,
|
|
49
|
+
args: [launcherPath],
|
|
50
|
+
env,
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
return JSON.stringify(doc, null, 2) + '\n';
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* @non-paper additive helper: generate the config and persist it via
|
|
58
|
+
* `atomicWriteFile` (tmp + fsync + rename). Both the destination and the
|
|
59
|
+
* embedded state path accept raw strings (legacy behavior) or
|
|
60
|
+
* `{ root, name }` refs confined by `resolveStatePath`. Returns the
|
|
61
|
+
* absolute destination path.
|
|
62
|
+
*/
|
|
63
|
+
async saveMcpConfig(target, statePath, options) {
|
|
64
|
+
const dest = this.resolve(target);
|
|
65
|
+
const resolved = this.resolve(statePath);
|
|
66
|
+
const config = this.generateMcpConfig(resolved, options);
|
|
67
|
+
await atomicWriteFile(dest, config);
|
|
68
|
+
return dest;
|
|
69
|
+
}
|
|
70
|
+
/* ------------------------------------------------------------------ */
|
|
71
|
+
/* Internal helpers */
|
|
72
|
+
/* ------------------------------------------------------------------ */
|
|
73
|
+
/** Resolve a `string | StatePathRef` via `resolveStatePath`. */
|
|
74
|
+
resolve(target) {
|
|
75
|
+
return typeof target === 'string'
|
|
76
|
+
? target
|
|
77
|
+
: resolveStatePath(target.root, target.name);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=mcp-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-adapter.js","sourceRoot":"","sources":["../src/mcp-adapter.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EACL,eAAe,EACf,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAG1B;;;;;;GAMG;AACH,MAAM,aAAa,GAAG,aAAa,CACjC,IAAI,GAAG,CAAC,qBAAqB,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAChD,CAAC;AAcF;;GAEG;AACH,MAAM,OAAO,UAAU;IACZ,IAAI,GAAG,KAAK,CAAC;IAEtB;;;;;;;;;;;;;;;;;;OAkBG;IACH,iBAAiB,CACf,SAAgC,EAChC,OAA0B;QAE1B,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACzC,MAAM,QAAQ,GAAG,OAAO,EAAE,QAAQ,IAAI,mBAAmB,CAAC;QAC1D,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,IAAI,MAAM,CAAC;QAC3C,MAAM,YAAY,GAAG,OAAO,EAAE,YAAY,IAAI,aAAa,CAAC;QAE5D,MAAM,GAAG,GAA2B;YAClC,qBAAqB,EAAE,QAAQ;YAC/B,oBAAoB,EAAE,QAAQ;YAC9B,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC;SACxB,CAAC;QAEF,MAAM,GAAG,GAAG;YACV,UAAU,EAAE;gBACV,UAAU,EAAE;oBACV,OAAO;oBACP,IAAI,EAAE,CAAC,YAAY,CAAC;oBACpB,GAAG;iBACJ;aACF;SACF,CAAC;QAEF,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;IAC7C,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,aAAa,CACjB,MAA6B,EAC7B,SAAgC,EAChC,OAA0B;QAE1B,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACzC,MAAM,MAAM,GAAG,IAAI,CAAC,iBAAiB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACzD,MAAM,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACpC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,wEAAwE;IACxE,yEAAyE;IACzE,wEAAwE;IAExE,gEAAgE;IACxD,OAAO,CAAC,MAA6B;QAC3C,OAAO,OAAO,MAAM,KAAK,QAAQ;YAC/B,CAAC,CAAC,MAAM;YACR,CAAC,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IACjD,CAAC;CACF"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import type { Readable, Writable } from 'node:stream';
|
|
2
|
+
import type { ProceduralSpec } from '@skillstate/core';
|
|
3
|
+
import type { TokenTracker } from '@skillstate/core';
|
|
4
|
+
/** MCP stdio framing modes the server can speak. */
|
|
5
|
+
export type FrameMode = 'jsonl' | 'content-length';
|
|
6
|
+
/** A JSON-RPC request object (id may be a number, string, or null). */
|
|
7
|
+
export interface JsonRpcRequest {
|
|
8
|
+
jsonrpc?: string;
|
|
9
|
+
id?: number | string | null;
|
|
10
|
+
method?: unknown;
|
|
11
|
+
params?: unknown;
|
|
12
|
+
}
|
|
13
|
+
/** The MCP tool-result payload returned on `tools/call`. */
|
|
14
|
+
export interface McpToolResult {
|
|
15
|
+
content: Array<{
|
|
16
|
+
type: 'text';
|
|
17
|
+
text: string;
|
|
18
|
+
}>;
|
|
19
|
+
isError?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/** Options for {@link McpServer}. */
|
|
22
|
+
export interface McpServerOptions {
|
|
23
|
+
/** Procedural spec: drives `spec.get`, schema validation, and reset defaults. */
|
|
24
|
+
spec: ProceduralSpec;
|
|
25
|
+
/** State file root directory (confined by `resolveStatePath`). */
|
|
26
|
+
root: string;
|
|
27
|
+
/** State file name (confined by `resolveStatePath`). */
|
|
28
|
+
name: string;
|
|
29
|
+
/** Optional token tracker for the `state.metrics` tool. */
|
|
30
|
+
tracker?: TokenTracker;
|
|
31
|
+
}
|
|
32
|
+
/** Options for {@link launch} (mirrors `McpServerOptions` + env fallbacks). */
|
|
33
|
+
export interface LaunchArgs {
|
|
34
|
+
spec?: ProceduralSpec;
|
|
35
|
+
specPath?: string;
|
|
36
|
+
statePath?: string;
|
|
37
|
+
root?: string;
|
|
38
|
+
name?: string;
|
|
39
|
+
tracker?: TokenTracker;
|
|
40
|
+
input?: Readable;
|
|
41
|
+
output?: Writable;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The `skillstate` MCP server: a JSON-RPC 2.0 over stdio server exposing
|
|
45
|
+
* the skillstate runtime as MCP tools.
|
|
46
|
+
*/
|
|
47
|
+
export declare class McpServer {
|
|
48
|
+
private readonly options;
|
|
49
|
+
/** Protocol version advertised by the server on `initialize`. */
|
|
50
|
+
readonly protocolVersion = "2024-11-05";
|
|
51
|
+
/** Advertised server capabilities (a minimal subset). */
|
|
52
|
+
readonly capabilities: {
|
|
53
|
+
tools: {
|
|
54
|
+
listChanged: boolean;
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
/** Advertised server identity. */
|
|
58
|
+
readonly serverInfo: {
|
|
59
|
+
name: string;
|
|
60
|
+
version: string;
|
|
61
|
+
};
|
|
62
|
+
private buffer;
|
|
63
|
+
private running;
|
|
64
|
+
private frameMode;
|
|
65
|
+
constructor(options: McpServerOptions);
|
|
66
|
+
/**
|
|
67
|
+
* Process a single (already-framed) JSON-RPC message line and return the
|
|
68
|
+
* response string, or `null` when the message needs no reply (a
|
|
69
|
+
* notification). This is the stateless unit entry point used by the
|
|
70
|
+
* stdio transport; `feed` drives it for framed/streamed input.
|
|
71
|
+
*/
|
|
72
|
+
handleLine(line: string): string | null;
|
|
73
|
+
/**
|
|
74
|
+
* Feed a raw chunk of stdin and return every response produced by the
|
|
75
|
+
* complete messages it contains. Handles BOTH newline-delimited JSON-RPC
|
|
76
|
+
* and `Content-Length`-framed messages; partial frames are buffered until
|
|
77
|
+
* the rest arrives. Responses are framed like the message that triggered
|
|
78
|
+
* them.
|
|
79
|
+
*/
|
|
80
|
+
feed(chunk: string): string[];
|
|
81
|
+
/**
|
|
82
|
+
* Attach the server to a stdin/stdout pair (defaults to `process`).
|
|
83
|
+
* Resolves once the server is reading; `stop()` detaches it. The server
|
|
84
|
+
* conserves its own buffered state, so real transports may hand over
|
|
85
|
+
* chunks that split mid-frame.
|
|
86
|
+
*/
|
|
87
|
+
start(input?: Readable, output?: Writable): Promise<McpServer>;
|
|
88
|
+
/** Mark the server stopped (idempotent). */
|
|
89
|
+
stop(): void;
|
|
90
|
+
/** Whether the server is currently reading from its input stream. */
|
|
91
|
+
get isRunning(): boolean;
|
|
92
|
+
/** Parse raw text into a message and dispatch; `-32700` on parse error. */
|
|
93
|
+
private processRaw;
|
|
94
|
+
private processMessage;
|
|
95
|
+
private handleRequest;
|
|
96
|
+
private handleToolCall;
|
|
97
|
+
private callTool;
|
|
98
|
+
private stateGet;
|
|
99
|
+
private statePatch;
|
|
100
|
+
private stateMerge;
|
|
101
|
+
private stateReset;
|
|
102
|
+
private specGet;
|
|
103
|
+
private stateMetrics;
|
|
104
|
+
/** Resolve the target state file path (args override the defaults). */
|
|
105
|
+
private resolveStore;
|
|
106
|
+
/** Read + normalize the state, falling back to schema defaults. */
|
|
107
|
+
private loadState;
|
|
108
|
+
/** Crash-safe synchronous write: temp sibling + fsync + rename. */
|
|
109
|
+
private writeState;
|
|
110
|
+
private toolsList;
|
|
111
|
+
private resourcesList;
|
|
112
|
+
/**
|
|
113
|
+
* Parse a `Content-Length`-framed message from the front of the buffer
|
|
114
|
+
* (the caller has already asserted the buffer begins with a valid
|
|
115
|
+
* `Content-Length:` header). Returns the body + consumed length, or
|
|
116
|
+
* `'incomplete'` if the payload has not all arrived.
|
|
117
|
+
*/
|
|
118
|
+
private takeContentLengthFrame;
|
|
119
|
+
/** Encode a response in the given framing mode. */
|
|
120
|
+
private encodeResponse;
|
|
121
|
+
private successResponse;
|
|
122
|
+
private errorResponse;
|
|
123
|
+
private textResult;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Launch an MCP server from an argument/env config (reads
|
|
127
|
+
* `SKILLSTATE_SPEC_PATH` and `SKILLSTATE_STATE_PATH` when not passed
|
|
128
|
+
* explicitly). Defaults to the canonical InterCode CTF spec and
|
|
129
|
+
* `.skillstate.json`.
|
|
130
|
+
*/
|
|
131
|
+
export declare function launch(args?: LaunchArgs): Promise<McpServer>;
|
|
132
|
+
//# sourceMappingURL=mcp-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @non-paper MCP server — no MCP exists in arXiv 2608.26263v3.
|
|
3
|
+
*
|
|
4
|
+
* A zero-dependency Model Context Protocol server over stdio (JSON-RPC
|
|
5
|
+
* 2.0) that exposes the skillstate runtime as MCP tools. It reuses the
|
|
6
|
+
* paper-exact core directly:
|
|
7
|
+
*
|
|
8
|
+
* - `mergeState` (⊕ null-deletion merge, §3.2) and `createInitialState`;
|
|
9
|
+
* - `validatePatchDeep` (stricter defense-in-depth validation, @non-paper);
|
|
10
|
+
* - `resolveStatePath` (confines `{ root, name }` — traversal throws);
|
|
11
|
+
* - `migrate` (normalizes bare/v0/v1 persisted state);
|
|
12
|
+
* - `redactSecrets` (fail-closed scrubber so secrets never leave the
|
|
13
|
+
* process via a tool result).
|
|
14
|
+
*
|
|
15
|
+
* TRANSPORT: accepts both official MCP stdio newline-delimited JSON-RPC
|
|
16
|
+
* AND `Content-Length`-framed messages (LSP-style). Responses echo the
|
|
17
|
+
* framing of the message that triggered them. State persistence uses a
|
|
18
|
+
* synchronous temp-sibling + fsync + rename so a mid-write crash can never
|
|
19
|
+
* produce a truncated state file.
|
|
20
|
+
*/
|
|
21
|
+
import * as fs from 'node:fs';
|
|
22
|
+
import * as path from 'node:path';
|
|
23
|
+
import { resolveStatePath } from '@skillstate/core';
|
|
24
|
+
import { mergeState, createInitialState } from '@skillstate/core';
|
|
25
|
+
import { validatePatchDeep } from '@skillstate/core';
|
|
26
|
+
import { migrate } from '@skillstate/core';
|
|
27
|
+
import { redactSecrets } from '@skillstate/core';
|
|
28
|
+
import { INTERCODE_CTF_SPEC } from '@skillstate/core/schemas';
|
|
29
|
+
/**
|
|
30
|
+
* The `skillstate` MCP server: a JSON-RPC 2.0 over stdio server exposing
|
|
31
|
+
* the skillstate runtime as MCP tools.
|
|
32
|
+
*/
|
|
33
|
+
export class McpServer {
|
|
34
|
+
options;
|
|
35
|
+
/** Protocol version advertised by the server on `initialize`. */
|
|
36
|
+
protocolVersion = '2024-11-05';
|
|
37
|
+
/** Advertised server capabilities (a minimal subset). */
|
|
38
|
+
capabilities = { tools: { listChanged: false } };
|
|
39
|
+
/** Advertised server identity. */
|
|
40
|
+
serverInfo = { name: 'skillstate', version: '1.0.0' };
|
|
41
|
+
buffer = '';
|
|
42
|
+
running = false;
|
|
43
|
+
frameMode = 'jsonl';
|
|
44
|
+
constructor(options) {
|
|
45
|
+
this.options = options;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Process a single (already-framed) JSON-RPC message line and return the
|
|
49
|
+
* response string, or `null` when the message needs no reply (a
|
|
50
|
+
* notification). This is the stateless unit entry point used by the
|
|
51
|
+
* stdio transport; `feed` drives it for framed/streamed input.
|
|
52
|
+
*/
|
|
53
|
+
handleLine(line) {
|
|
54
|
+
const text = line.trim();
|
|
55
|
+
if (text.length === 0) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
return this.processRaw(text);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Feed a raw chunk of stdin and return every response produced by the
|
|
62
|
+
* complete messages it contains. Handles BOTH newline-delimited JSON-RPC
|
|
63
|
+
* and `Content-Length`-framed messages; partial frames are buffered until
|
|
64
|
+
* the rest arrives. Responses are framed like the message that triggered
|
|
65
|
+
* them.
|
|
66
|
+
*/
|
|
67
|
+
feed(chunk) {
|
|
68
|
+
this.buffer += chunk;
|
|
69
|
+
const responses = [];
|
|
70
|
+
while (this.buffer.length > 0) {
|
|
71
|
+
this.buffer = this.buffer.replace(/^(\r?\n)+/, '');
|
|
72
|
+
if (this.buffer.length === 0) {
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
if (/^Content-Length:\s*\d+/i.test(this.buffer)) {
|
|
76
|
+
const framed = this.takeContentLengthFrame();
|
|
77
|
+
if (framed === 'incomplete') {
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
this.frameMode = 'content-length';
|
|
81
|
+
const response = this.processRaw(framed.body);
|
|
82
|
+
if (response !== null) {
|
|
83
|
+
responses.push(this.encodeResponse(response, this.frameMode));
|
|
84
|
+
}
|
|
85
|
+
this.buffer = this.buffer.slice(framed.consumed);
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
const newline = this.buffer.indexOf('\n');
|
|
89
|
+
if (newline === -1) {
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
const line = this.buffer.slice(0, newline).trim();
|
|
93
|
+
this.buffer = this.buffer.slice(newline + 1);
|
|
94
|
+
if (line.length === 0) {
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
this.frameMode = 'jsonl';
|
|
98
|
+
const response = this.processRaw(line);
|
|
99
|
+
if (response !== null) {
|
|
100
|
+
responses.push(this.encodeResponse(response, this.frameMode));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return responses;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Attach the server to a stdin/stdout pair (defaults to `process`).
|
|
107
|
+
* Resolves once the server is reading; `stop()` detaches it. The server
|
|
108
|
+
* conserves its own buffered state, so real transports may hand over
|
|
109
|
+
* chunks that split mid-frame.
|
|
110
|
+
*/
|
|
111
|
+
async start(input, output) {
|
|
112
|
+
const source = input ?? process.stdin;
|
|
113
|
+
const sink = output ?? process.stdout;
|
|
114
|
+
this.running = true;
|
|
115
|
+
source.on('data', (chunk) => {
|
|
116
|
+
const text = typeof chunk === 'string' ? chunk : chunk.toString();
|
|
117
|
+
for (const response of this.feed(text)) {
|
|
118
|
+
sink.write(response);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
return this;
|
|
122
|
+
}
|
|
123
|
+
/** Mark the server stopped (idempotent). */
|
|
124
|
+
stop() {
|
|
125
|
+
this.running = false;
|
|
126
|
+
}
|
|
127
|
+
/** Whether the server is currently reading from its input stream. */
|
|
128
|
+
get isRunning() {
|
|
129
|
+
return this.running;
|
|
130
|
+
}
|
|
131
|
+
/* ------------------------------------------------------------------ */
|
|
132
|
+
/* JSON-RPC dispatch */
|
|
133
|
+
/* ------------------------------------------------------------------ */
|
|
134
|
+
/** Parse raw text into a message and dispatch; `-32700` on parse error. */
|
|
135
|
+
processRaw(text) {
|
|
136
|
+
let message;
|
|
137
|
+
try {
|
|
138
|
+
message = JSON.parse(text);
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
return this.errorResponse(null, -32700, 'Parse error');
|
|
142
|
+
}
|
|
143
|
+
return this.processMessage(message);
|
|
144
|
+
}
|
|
145
|
+
processMessage(message) {
|
|
146
|
+
if (typeof message !== 'object' || message === null || Array.isArray(message)) {
|
|
147
|
+
return this.errorResponse(null, -32600, 'Invalid Request');
|
|
148
|
+
}
|
|
149
|
+
const msg = message;
|
|
150
|
+
const id = 'id' in msg ? msg.id ?? null : null;
|
|
151
|
+
const method = msg.method;
|
|
152
|
+
const hasId = 'id' in msg;
|
|
153
|
+
if (typeof method === 'string' && method.startsWith('notifications/')) {
|
|
154
|
+
if (hasId) {
|
|
155
|
+
return this.errorResponse(id, -32600, 'Invalid Request: notifications must not include an id');
|
|
156
|
+
}
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
if (typeof method !== 'string' || method.length === 0) {
|
|
160
|
+
return this.errorResponse(id, -32600, 'Invalid Request');
|
|
161
|
+
}
|
|
162
|
+
if (!hasId) {
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
return this.handleRequest(id, method, msg.params);
|
|
166
|
+
}
|
|
167
|
+
handleRequest(id, method, params) {
|
|
168
|
+
switch (method) {
|
|
169
|
+
case 'initialize':
|
|
170
|
+
return this.successResponse(id, {
|
|
171
|
+
protocolVersion: this.protocolVersion,
|
|
172
|
+
capabilities: this.capabilities,
|
|
173
|
+
serverInfo: this.serverInfo,
|
|
174
|
+
});
|
|
175
|
+
case 'ping':
|
|
176
|
+
return this.successResponse(id, {});
|
|
177
|
+
case 'tools/list':
|
|
178
|
+
return this.successResponse(id, { tools: this.toolsList() });
|
|
179
|
+
case 'tools/call':
|
|
180
|
+
return this.handleToolCall(id, params);
|
|
181
|
+
case 'resources/list':
|
|
182
|
+
return this.successResponse(id, { resources: this.resourcesList() });
|
|
183
|
+
default:
|
|
184
|
+
return this.errorResponse(id, -32601, `Method not found: ${method}`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
handleToolCall(id, params) {
|
|
188
|
+
if (!isPlainObject(params)) {
|
|
189
|
+
return this.errorResponse(id, -32602, 'Invalid params: expected an object');
|
|
190
|
+
}
|
|
191
|
+
const name = params.name;
|
|
192
|
+
if (typeof name !== 'string' || name.length === 0) {
|
|
193
|
+
return this.errorResponse(id, -32602, 'Invalid params: name required');
|
|
194
|
+
}
|
|
195
|
+
const args = params.arguments;
|
|
196
|
+
const argsObj = isPlainObject(args) ? args : {};
|
|
197
|
+
try {
|
|
198
|
+
const result = this.callTool(name, argsObj);
|
|
199
|
+
return this.successResponse(id, result);
|
|
200
|
+
}
|
|
201
|
+
catch (err) {
|
|
202
|
+
const message = String(err);
|
|
203
|
+
return this.successResponse(id, {
|
|
204
|
+
content: [{ type: 'text', text: message }],
|
|
205
|
+
isError: true,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
/* ------------------------------------------------------------------ */
|
|
210
|
+
/* Tool implementations */
|
|
211
|
+
/* ------------------------------------------------------------------ */
|
|
212
|
+
callTool(name, args) {
|
|
213
|
+
switch (name) {
|
|
214
|
+
case 'state.get':
|
|
215
|
+
return this.stateGet(args);
|
|
216
|
+
case 'state.patch':
|
|
217
|
+
return this.statePatch(args);
|
|
218
|
+
case 'state.merge':
|
|
219
|
+
return this.stateMerge(args);
|
|
220
|
+
case 'state.reset':
|
|
221
|
+
return this.stateReset(args);
|
|
222
|
+
case 'spec.get':
|
|
223
|
+
return this.specGet();
|
|
224
|
+
case 'state.metrics':
|
|
225
|
+
return this.stateMetrics();
|
|
226
|
+
default:
|
|
227
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
stateGet(args) {
|
|
231
|
+
const filePath = this.resolveStore(args);
|
|
232
|
+
const state = this.loadState(filePath);
|
|
233
|
+
return this.textResult(redactSecrets(JSON.stringify(state)));
|
|
234
|
+
}
|
|
235
|
+
statePatch(args) {
|
|
236
|
+
const patch = args.patch;
|
|
237
|
+
if (!isPlainObject(patch)) {
|
|
238
|
+
throw new Error('patch must be an object');
|
|
239
|
+
}
|
|
240
|
+
const filePath = this.resolveStore(args);
|
|
241
|
+
const merged = mergeState(this.loadState(filePath), patch);
|
|
242
|
+
this.writeState(filePath, merged);
|
|
243
|
+
return this.textResult(redactSecrets(JSON.stringify(merged)));
|
|
244
|
+
}
|
|
245
|
+
stateMerge(args) {
|
|
246
|
+
const patch = args.patch;
|
|
247
|
+
if (!isPlainObject(patch)) {
|
|
248
|
+
throw new Error('patch must be an object');
|
|
249
|
+
}
|
|
250
|
+
const validation = validatePatchDeep(this.options.spec.schema, patch);
|
|
251
|
+
if (!validation.valid) {
|
|
252
|
+
throw new Error(validation.error);
|
|
253
|
+
}
|
|
254
|
+
const filePath = this.resolveStore(args);
|
|
255
|
+
const merged = mergeState(this.loadState(filePath), patch);
|
|
256
|
+
this.writeState(filePath, merged);
|
|
257
|
+
return this.textResult(redactSecrets(JSON.stringify(merged)));
|
|
258
|
+
}
|
|
259
|
+
stateReset(args) {
|
|
260
|
+
const filePath = this.resolveStore(args);
|
|
261
|
+
const initial = createInitialState(this.options.spec.schema);
|
|
262
|
+
this.writeState(filePath, initial);
|
|
263
|
+
return this.textResult(redactSecrets(JSON.stringify(initial)));
|
|
264
|
+
}
|
|
265
|
+
specGet() {
|
|
266
|
+
const spec = this.options.spec;
|
|
267
|
+
return this.textResult(redactSecrets(JSON.stringify({
|
|
268
|
+
id: spec.id,
|
|
269
|
+
name: spec.name,
|
|
270
|
+
version: spec.version,
|
|
271
|
+
instructions: spec.instructions,
|
|
272
|
+
schema: spec.schema,
|
|
273
|
+
})));
|
|
274
|
+
}
|
|
275
|
+
stateMetrics() {
|
|
276
|
+
const tracker = this.options.tracker;
|
|
277
|
+
if (!tracker) {
|
|
278
|
+
throw new Error('No token tracker configured');
|
|
279
|
+
}
|
|
280
|
+
const metrics = {
|
|
281
|
+
...tracker.getMetrics(),
|
|
282
|
+
...tracker.getBookkeeping(),
|
|
283
|
+
};
|
|
284
|
+
return this.textResult(redactSecrets(JSON.stringify(metrics)));
|
|
285
|
+
}
|
|
286
|
+
/* ------------------------------------------------------------------ */
|
|
287
|
+
/* State helpers */
|
|
288
|
+
/* ------------------------------------------------------------------ */
|
|
289
|
+
/** Resolve the target state file path (args override the defaults). */
|
|
290
|
+
resolveStore(args) {
|
|
291
|
+
const root = typeof args.root === 'string' ? args.root : this.options.root;
|
|
292
|
+
const name = typeof args.name === 'string' ? args.name : this.options.name;
|
|
293
|
+
return resolveStatePath(root, name);
|
|
294
|
+
}
|
|
295
|
+
/** Read + normalize the state, falling back to schema defaults. */
|
|
296
|
+
loadState(filePath) {
|
|
297
|
+
try {
|
|
298
|
+
const raw = fs.readFileSync(filePath, 'utf-8');
|
|
299
|
+
return migrate(JSON.parse(raw)).state;
|
|
300
|
+
}
|
|
301
|
+
catch {
|
|
302
|
+
return createInitialState(this.options.spec.schema);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
/** Crash-safe synchronous write: temp sibling + fsync + rename. */
|
|
306
|
+
writeState(filePath, state) {
|
|
307
|
+
const dir = path.dirname(filePath);
|
|
308
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
309
|
+
const tmp = `${filePath}.tmp.${process.pid}.${Math.random().toString(36).slice(2)}`;
|
|
310
|
+
const fd = fs.openSync(tmp, 'w');
|
|
311
|
+
try {
|
|
312
|
+
fs.writeSync(fd, JSON.stringify(state, null, 2));
|
|
313
|
+
fs.fsyncSync(fd);
|
|
314
|
+
}
|
|
315
|
+
finally {
|
|
316
|
+
fs.closeSync(fd);
|
|
317
|
+
}
|
|
318
|
+
fs.renameSync(tmp, filePath);
|
|
319
|
+
}
|
|
320
|
+
/* ------------------------------------------------------------------ */
|
|
321
|
+
/* Tool / resource schemas */
|
|
322
|
+
/* ------------------------------------------------------------------ */
|
|
323
|
+
toolsList() {
|
|
324
|
+
const stringProp = (desc) => ({
|
|
325
|
+
type: 'string',
|
|
326
|
+
description: desc,
|
|
327
|
+
});
|
|
328
|
+
return [
|
|
329
|
+
{
|
|
330
|
+
name: 'state.get',
|
|
331
|
+
description: 'Read the current skill state (secrets redacted).',
|
|
332
|
+
inputSchema: {
|
|
333
|
+
type: 'object',
|
|
334
|
+
properties: { name: stringProp('Optional alternate state file name.') },
|
|
335
|
+
},
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
name: 'state.patch',
|
|
339
|
+
description: 'Apply a sparse patch (null deletes a key) to the state and persist it.',
|
|
340
|
+
inputSchema: {
|
|
341
|
+
type: 'object',
|
|
342
|
+
properties: {
|
|
343
|
+
patch: { type: 'object' },
|
|
344
|
+
root: stringProp('Optional state root directory.'),
|
|
345
|
+
name: stringProp('Optional state file name.'),
|
|
346
|
+
},
|
|
347
|
+
required: ['patch'],
|
|
348
|
+
},
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
name: 'state.merge',
|
|
352
|
+
description: 'Schema-validated patch: validate then apply the ⊕ merge and persist.',
|
|
353
|
+
inputSchema: {
|
|
354
|
+
type: 'object',
|
|
355
|
+
properties: {
|
|
356
|
+
patch: { type: 'object' },
|
|
357
|
+
root: stringProp('Optional state root directory.'),
|
|
358
|
+
name: stringProp('Optional state file name.'),
|
|
359
|
+
},
|
|
360
|
+
required: ['patch'],
|
|
361
|
+
},
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
name: 'state.reset',
|
|
365
|
+
description: 'Reset the state to the schema defaults.',
|
|
366
|
+
inputSchema: {
|
|
367
|
+
type: 'object',
|
|
368
|
+
properties: { name: stringProp('Optional alternate state file name.') },
|
|
369
|
+
},
|
|
370
|
+
},
|
|
371
|
+
{
|
|
372
|
+
name: 'spec.get',
|
|
373
|
+
description: 'Return the procedural spec (id, name, version, schema).',
|
|
374
|
+
inputSchema: { type: 'object' },
|
|
375
|
+
},
|
|
376
|
+
{
|
|
377
|
+
name: 'state.metrics',
|
|
378
|
+
description: 'Return the paper §4.3 metrics readout from the token tracker.',
|
|
379
|
+
inputSchema: { type: 'object' },
|
|
380
|
+
},
|
|
381
|
+
];
|
|
382
|
+
}
|
|
383
|
+
resourcesList() {
|
|
384
|
+
return [
|
|
385
|
+
{
|
|
386
|
+
uri: 'skillstate://state',
|
|
387
|
+
name: 'Skill State',
|
|
388
|
+
mimeType: 'application/json',
|
|
389
|
+
},
|
|
390
|
+
];
|
|
391
|
+
}
|
|
392
|
+
/* ------------------------------------------------------------------ */
|
|
393
|
+
/* Frame codec */
|
|
394
|
+
/* ------------------------------------------------------------------ */
|
|
395
|
+
/**
|
|
396
|
+
* Parse a `Content-Length`-framed message from the front of the buffer
|
|
397
|
+
* (the caller has already asserted the buffer begins with a valid
|
|
398
|
+
* `Content-Length:` header). Returns the body + consumed length, or
|
|
399
|
+
* `'incomplete'` if the payload has not all arrived.
|
|
400
|
+
*/
|
|
401
|
+
takeContentLengthFrame() {
|
|
402
|
+
const match = this.buffer.match(/^Content-Length:\s*(\d+)/i);
|
|
403
|
+
const crlf = this.buffer.indexOf('\r\n\r\n');
|
|
404
|
+
let headerEnd;
|
|
405
|
+
if (crlf !== -1) {
|
|
406
|
+
headerEnd = crlf + 4;
|
|
407
|
+
}
|
|
408
|
+
else {
|
|
409
|
+
const lf = this.buffer.indexOf('\n\n');
|
|
410
|
+
if (lf === -1) {
|
|
411
|
+
return 'incomplete';
|
|
412
|
+
}
|
|
413
|
+
headerEnd = lf + 2;
|
|
414
|
+
}
|
|
415
|
+
const length = Number(match[1]);
|
|
416
|
+
if (this.buffer.length - headerEnd < length) {
|
|
417
|
+
return 'incomplete';
|
|
418
|
+
}
|
|
419
|
+
return {
|
|
420
|
+
body: this.buffer.slice(headerEnd, headerEnd + length),
|
|
421
|
+
consumed: headerEnd + length,
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
/** Encode a response in the given framing mode. */
|
|
425
|
+
encodeResponse(text, mode) {
|
|
426
|
+
if (mode === 'content-length') {
|
|
427
|
+
return `Content-Length: ${Buffer.byteLength(text, 'utf-8')}\r\n\r\n${text}`;
|
|
428
|
+
}
|
|
429
|
+
return `${text}\n`;
|
|
430
|
+
}
|
|
431
|
+
/* ------------------------------------------------------------------ */
|
|
432
|
+
/* JSON-RPC response builders */
|
|
433
|
+
/* ------------------------------------------------------------------ */
|
|
434
|
+
successResponse(id, result) {
|
|
435
|
+
return JSON.stringify({ jsonrpc: '2.0', id, result });
|
|
436
|
+
}
|
|
437
|
+
errorResponse(id, code, message) {
|
|
438
|
+
return JSON.stringify({
|
|
439
|
+
jsonrpc: '2.0',
|
|
440
|
+
id,
|
|
441
|
+
error: { code, message },
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
textResult(text) {
|
|
445
|
+
return { content: [{ type: 'text', text }] };
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
function isPlainObject(value) {
|
|
449
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* Resolve the procedural spec for a launch: explicit `args.spec` wins, then
|
|
453
|
+
* a `SKILLSTATE_SPEC_PATH`/`args.specPath` JSON file, else the canonical
|
|
454
|
+
* InterCode CTF spec. Pure w.r.t. the returned value.
|
|
455
|
+
*/
|
|
456
|
+
function resolveSpec(args, env) {
|
|
457
|
+
if (args?.spec) {
|
|
458
|
+
return args.spec;
|
|
459
|
+
}
|
|
460
|
+
const specPath = args?.specPath ?? env['SKILLSTATE_SPEC_PATH'];
|
|
461
|
+
if (typeof specPath === 'string' && specPath.length > 0) {
|
|
462
|
+
return JSON.parse(fs.readFileSync(specPath, 'utf-8'));
|
|
463
|
+
}
|
|
464
|
+
return INTERCODE_CTF_SPEC;
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* Launch an MCP server from an argument/env config (reads
|
|
468
|
+
* `SKILLSTATE_SPEC_PATH` and `SKILLSTATE_STATE_PATH` when not passed
|
|
469
|
+
* explicitly). Defaults to the canonical InterCode CTF spec and
|
|
470
|
+
* `.skillstate.json`.
|
|
471
|
+
*/
|
|
472
|
+
export async function launch(args) {
|
|
473
|
+
const spec = resolveSpec(args, process.env);
|
|
474
|
+
const statePath = args?.statePath ?? process.env['SKILLSTATE_STATE_PATH'];
|
|
475
|
+
const root = args?.root ?? (statePath ? path.dirname(statePath) : '.');
|
|
476
|
+
const name = args?.name ?? (statePath ? path.basename(statePath) : '.skillstate.json');
|
|
477
|
+
const server = new McpServer({
|
|
478
|
+
spec,
|
|
479
|
+
root,
|
|
480
|
+
name,
|
|
481
|
+
tracker: args?.tracker,
|
|
482
|
+
});
|
|
483
|
+
return server.start(args?.input, args?.output);
|
|
484
|
+
}
|
|
485
|
+
//# sourceMappingURL=mcp-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@skillstate/mcp",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Zero-dependency MCP server + adapter for the skillstate runtime.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"skillstate-mcp": "bin/mcp.js"
|
|
10
|
+
},
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"default": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"./package.json": "./package.json"
|
|
17
|
+
},
|
|
18
|
+
"files": ["dist", "bin"],
|
|
19
|
+
"sideEffects": false,
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">=20"
|
|
22
|
+
},
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@skillstate/core": "^2.0.0"
|
|
26
|
+
}
|
|
27
|
+
}
|