@skillstate/mcp 2.0.1 → 2.0.3
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 +149 -0
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# @skillstate/mcp
|
|
4
|
+
|
|
5
|
+
**Zero-dependency Model Context Protocol server + adapter for the @skillstate/core runtime.**
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/@skillstate/mcp)
|
|
8
|
+
[](https://www.npmjs.com/package/@skillstate/mcp)
|
|
9
|
+
[](https://github.com/vitkuz573/skillstate)
|
|
10
|
+
[](https://github.com/vitkuz573/skillstate/blob/main/LICENSE)
|
|
11
|
+
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
`@skillstate/mcp` exposes the skillstate runtime ([`@skillstate/core`](../core))
|
|
17
|
+
as a **Model Context Protocol** server over stdio (JSON-RPC 2.0). It reuses the
|
|
18
|
+
paper-exact core directly — `mergeState`, `createInitialState`,
|
|
19
|
+
`validatePatchDeep`, `migrate`, `redactSecrets` — so any MCP client can read,
|
|
20
|
+
patch, merge, and reset the execution state as tools.
|
|
21
|
+
|
|
22
|
+
> **@non-paper** — the server is additive; no MCP exists in arXiv 2608.26263v3.
|
|
23
|
+
> Unlike the prompting adapters, MCP is runtime **access**, not prompting, so
|
|
24
|
+
> the O(1) question does not apply.
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm i @skillstate/core @skillstate/mcp
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Requires Node.js >= 20. TypeScript types are bundled. Ships a `skillstate-mcp`
|
|
33
|
+
bin that launches the server directly.
|
|
34
|
+
|
|
35
|
+
## Quick start
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { McpAdapter, McpServer, launch } from '@skillstate/mcp';
|
|
39
|
+
import { INTERCODE_CTF_SPEC } from '@skillstate/core/schemas';
|
|
40
|
+
|
|
41
|
+
const adapter = new McpAdapter();
|
|
42
|
+
|
|
43
|
+
// .mcp.json config registering the skillstate stdio server:
|
|
44
|
+
const config = adapter.generateMcpConfig('/path/to/.skillstate.json');
|
|
45
|
+
// -> { "mcpServers": { "skillstate": { "command", "args", "env" } } }
|
|
46
|
+
|
|
47
|
+
// Or run an in-process server and drive it line-by-line:
|
|
48
|
+
const server = new McpServer({
|
|
49
|
+
spec: INTERCODE_CTF_SPEC,
|
|
50
|
+
root: '.',
|
|
51
|
+
name: '.skillstate.json',
|
|
52
|
+
});
|
|
53
|
+
const response = server.handleLine(
|
|
54
|
+
JSON.stringify({
|
|
55
|
+
jsonrpc: '2.0', id: 1, method: 'tools/call',
|
|
56
|
+
params: { name: 'state.get', arguments: {} },
|
|
57
|
+
}),
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
// Or launch a stdio server from env / args (SKILLSTATE_SPEC_PATH, SKILLSTATE_STATE_PATH):
|
|
61
|
+
await launch({ statePath: './.skillstate.json', spec: INTERCODE_CTF_SPEC });
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Command-line:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
skillstate-mcp # reads SKILLSTATE_SPEC_PATH / SKILLSTATE_STATE_PATH
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Register in opencode.jsonc
|
|
71
|
+
|
|
72
|
+
For an OpenCode host, add the stdio server to the `mcp` block of
|
|
73
|
+
`~/.config/opencode/opencode.jsonc` (or the project `opencode.jsonc`). The
|
|
74
|
+
`environment` block feeds `SKILLSTATE_STATE_PATH`, which `launch()` reads:
|
|
75
|
+
|
|
76
|
+
```jsonc
|
|
77
|
+
{
|
|
78
|
+
"mcp": {
|
|
79
|
+
"skillstate": {
|
|
80
|
+
"type": "local",
|
|
81
|
+
"command": ["node", "/abs/path/to/skillstate/packages/mcp/bin/mcp.js"],
|
|
82
|
+
"enabled": true,
|
|
83
|
+
"environment": {
|
|
84
|
+
"SKILLSTATE_STATE_PATH": "/abs/path/to/.skillstate.json"
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
If you installed from npm instead of a checkout, replace the command with
|
|
92
|
+
`["npx", "-y", "skillstate-mcp"]` (the packaged bin). Create the state file
|
|
93
|
+
first (see the `@skillstate/opencode` README for a sample). Verify with:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
opencode debug config # mcp.skillstate appears in the resolved config
|
|
97
|
+
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"t","version":"0"}}}
|
|
98
|
+
{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' \
|
|
99
|
+
| SKILLSTATE_STATE_PATH=/abs/path/to/.skillstate.json node packages/mcp/bin/mcp.js
|
|
100
|
+
# -> serverInfo {"name":"skillstate","version":"1.0.0"} + 6 tools
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## API / Exports
|
|
104
|
+
|
|
105
|
+
Root path `@skillstate/mcp` exports `McpAdapter`, `McpServer`, and `launch`
|
|
106
|
+
(plus the types `McpServerOptions`, `LaunchArgs`, `FrameMode`, `JsonRpcRequest`,
|
|
107
|
+
`McpToolResult`, and `McpConfigOptions`).
|
|
108
|
+
|
|
109
|
+
- `new McpAdapter()` — `name = 'mcp'`.
|
|
110
|
+
- `generateMcpConfig(statePath, options?): string` — a deterministic,
|
|
111
|
+
secret-free `.mcp.json` document (`McpConfigOptions.specPath`, `.command`,
|
|
112
|
+
`.launcherPath`, `.env`).
|
|
113
|
+
- `saveMcpConfig(target, statePath, options?): Promise<string>` — atomic write.
|
|
114
|
+
- `new McpServer(options: McpServerOptions)` — `{ spec, root, name, tracker? }`.
|
|
115
|
+
- `handleLine(line): string | null` — process one already-framed JSON-RPC
|
|
116
|
+
message.
|
|
117
|
+
- `feed(chunk): string[]` — consume streamed stdin, handling both
|
|
118
|
+
newline-delimited JSON-RPC and `Content-Length`-framed messages.
|
|
119
|
+
- `start(input?, output?): Promise<McpServer>` / `stop()` / `get isRunning()`.
|
|
120
|
+
- `launch(args?): Promise<McpServer>` — resolves spec/state from args or
|
|
121
|
+
env and starts a stdio server.
|
|
122
|
+
|
|
123
|
+
**Tools:** `state.get`, `state.patch`, `state.merge` (schema-validated),
|
|
124
|
+
`state.reset`, `spec.get`, `state.metrics`. **Resource:** `skillstate://state`.
|
|
125
|
+
State is redacted on every read, and the server conserves its own buffering so
|
|
126
|
+
transports may split frames mid-message.
|
|
127
|
+
|
|
128
|
+
## Notes
|
|
129
|
+
|
|
130
|
+
- **Zero dependencies.** `@skillstate/mcp` declares only
|
|
131
|
+
[`@skillstate/core`](../core); it uses Node's `fs`/`path`/`stream` for the
|
|
132
|
+
stdio transport and crash-safe state writes (temp sibling + fsync + rename).
|
|
133
|
+
- Both newline-delimited JSON-RPC and `Content-Length`-framed (LSP-style)
|
|
134
|
+
messages are accepted; responses echo the framing that triggered them.
|
|
135
|
+
- `state.merge` runs `validatePatchDeep` (defense-in-depth) before the ⊕ merge;
|
|
136
|
+
`state.patch` applies the raw ⊕ merge. `redactSecrets` fails closed so
|
|
137
|
+
secrets never leave the process through a tool result.
|
|
138
|
+
|
|
139
|
+
## Related
|
|
140
|
+
|
|
141
|
+
- Paper: [arXiv:2608.26263](https://arxiv.org/abs/2608.26263).
|
|
142
|
+
- Core runtime: [`@skillstate/core`](../core).
|
|
143
|
+
- [`state.md`](../../state.md) — design notes.
|
|
144
|
+
- Prompting adapters: `@skillstate/claude`, `@skillstate/opencode`,
|
|
145
|
+
`@skillstate/codex`.
|
|
146
|
+
|
|
147
|
+
## License
|
|
148
|
+
|
|
149
|
+
[MIT](LICENSE) © 2026 Vitaly Kuzyaev
|