@j0hanz/thinkseq-mcp 2.0.0 → 2.1.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/README.md +160 -237
- package/dist/app.js +18 -2
- package/dist/appConfig/env.d.ts +3 -0
- package/dist/appConfig/env.js +9 -0
- package/dist/appConfig/runDependencies.d.ts +4 -4
- package/dist/appConfig/runDependencies.js +21 -14
- package/dist/assets/logo.svg +4029 -0
- package/dist/engine/revision.js +14 -26
- package/dist/engine/thoughtQueries.js +20 -13
- package/dist/engine/thoughtStore.js +107 -102
- package/dist/engine.js +85 -61
- package/dist/index.js +1 -0
- package/dist/instructions.md +11 -16
- package/dist/lib/types.d.ts +2 -0
- package/dist/tools/thinkseq.d.ts +1 -1
- package/dist/tools/thinkseq.js +13 -11
- package/package.json +19 -14
- package/dist/tsconfig.tsbuildinfo +0 -1
package/README.md
CHANGED
|
@@ -1,221 +1,177 @@
|
|
|
1
1
|
# ThinkSeq MCP Server
|
|
2
2
|
|
|
3
|
-
<img src="
|
|
3
|
+
<img src="assets/logo.svg" alt="ThinkSeq MCP Server Logo" width="225" />
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
[](https://www.npmjs.com/package/@j0hanz/thinkseq-mcp)
|
|
8
|
-
|
|
9
|
-
## One-click install
|
|
5
|
+
[](https://www.npmjs.com/package/@j0hanz/thinkseq-mcp)[](https://opensource.org/licenses/MIT)[](https://github.com/modelcontextprotocol/typescript-sdk)
|
|
10
6
|
|
|
11
7
|
[](https://insiders.vscode.dev/redirect/mcp/install?name=thinkseq&inputs=%5B%5D&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40j0hanz%2Fthinkseq-mcp%40latest%22%5D%7D) [](https://insiders.vscode.dev/redirect/mcp/install?name=thinkseq&inputs=%5B%5D&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40j0hanz%2Fthinkseq-mcp%40latest%22%5D%7D&quality=insiders)
|
|
12
8
|
|
|
13
9
|
[](https://cursor.com/install-mcp?name=thinkseq&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBqMGhhbnovdGhpbmtzZXEtbWNwQGxhdGVzdCJdfQ==)
|
|
14
10
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
ThinkSeq exposes a single MCP tool, `thinkseq`, for structured, sequential thinking. The server runs over stdio and stores an in-memory thought history so it can return progress, active-path context, and revision metadata on each call.
|
|
18
|
-
|
|
19
|
-
## Quick start
|
|
11
|
+
An MCP server for structured, sequential thinking with revision support.
|
|
20
12
|
|
|
21
|
-
|
|
22
|
-
npx -y @j0hanz/thinkseq-mcp@latest
|
|
23
|
-
```
|
|
13
|
+
## Overview
|
|
24
14
|
|
|
25
|
-
|
|
15
|
+
ThinkSeq exposes a single MCP tool, `thinkseq`, that enables Language Models to "think" in a structured, step-by-step manner. It maintains an in-memory history of thoughts, calculates progress, and critically allows for **destructive revision**—where a model can realize a mistake, "rewind" to a previous step, and branch off with a correction. This capability mirrors human reasoning patterns and improves problem-solving accuracy for complex tasks.
|
|
26
16
|
|
|
27
|
-
|
|
28
|
-
thinkseq --max-thoughts 500 --max-memory-mb 100
|
|
29
|
-
```
|
|
17
|
+
## Key Features
|
|
30
18
|
|
|
31
|
-
|
|
19
|
+
- **Sequential Thinking**: Records thoughts as discrete steps with auto-incrementing numbers.
|
|
20
|
+
- **Progress Tracking**: Automatically calculates progress (0.0 to 1.0) based on estimated total thoughts.
|
|
21
|
+
- **Revision Support**: Allows models to revise specific past thoughts, superseding the old path and starting a new reasoning branch.
|
|
22
|
+
- **Context Awareness**: Returns recent thoughts and revision context with every tool call to keep the model grounded.
|
|
23
|
+
- **Session Isolation**: Supports multiple concurrent thinking sessions via `sessionId`.
|
|
24
|
+
- **Memory Management**: Configurable limits for max thoughts and memory usage to prevent resource exhaustion.
|
|
32
25
|
|
|
33
|
-
|
|
34
|
-
- `--max-memory-mb <number>`: Max memory (MB) for stored thoughts.
|
|
35
|
-
- `--shutdown-timeout-ms <number>`: Graceful shutdown timeout.
|
|
36
|
-
- `--package-read-timeout-ms <number>`: Package.json read timeout.
|
|
37
|
-
- `-h, --help`: Show help.
|
|
26
|
+
## Tech Stack
|
|
38
27
|
|
|
39
|
-
|
|
28
|
+
- **Runtime**: Node.js >=22.0.0
|
|
29
|
+
- **Language**: TypeScript 5.9+
|
|
30
|
+
- **MCP SDK**: `@modelcontextprotocol/sdk`
|
|
31
|
+
- **Validation**: `zod`
|
|
40
32
|
|
|
41
|
-
|
|
42
|
-
- `maxMemoryBytes` default: 100 MB (derived from `--max-memory-mb`).
|
|
43
|
-
- `packageReadTimeoutMs` default: 2000 ms.
|
|
44
|
-
- `shutdownTimeoutMs` default: 5000 ms.
|
|
33
|
+
## Repository Structure
|
|
45
34
|
|
|
46
|
-
|
|
35
|
+
```text
|
|
36
|
+
c:\thinkseq-mcp
|
|
37
|
+
├── dist/ # Compiled JavaScript
|
|
38
|
+
├── src/
|
|
39
|
+
│ ├── app.ts # Application entry and MCP wiring
|
|
40
|
+
│ ├── engine.ts # Core thinking engine logic
|
|
41
|
+
│ ├── engineConfig.ts # Configuration defaults
|
|
42
|
+
│ ├── index.ts # CLI entrypoint
|
|
43
|
+
│ ├── lib/ # Utilities (CLI, logging, types)
|
|
44
|
+
│ ├── schemas/ # Zod schemas for inputs/outputs
|
|
45
|
+
│ └── tools/ # MCP tool definitions
|
|
46
|
+
├── package.json
|
|
47
|
+
└── tsconfig.json
|
|
48
|
+
```
|
|
47
49
|
|
|
48
|
-
|
|
50
|
+
## Requirements
|
|
49
51
|
|
|
50
|
-
|
|
51
|
-
{
|
|
52
|
-
"mcpServers": {
|
|
53
|
-
"thinkseq": {
|
|
54
|
-
"command": "npx",
|
|
55
|
-
"args": ["-y", "@j0hanz/thinkseq-mcp@latest"]
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
```
|
|
52
|
+
- **Node.js**: Version 22.0.0 or higher.
|
|
60
53
|
|
|
61
|
-
|
|
62
|
-
<summary><b>VS Code</b></summary>
|
|
54
|
+
## Quickstart
|
|
63
55
|
|
|
64
|
-
|
|
56
|
+
To run the server using `npx`:
|
|
65
57
|
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
"mcpServers": {
|
|
69
|
-
"thinkseq": {
|
|
70
|
-
"command": "npx",
|
|
71
|
-
"args": ["-y", "@j0hanz/thinkseq-mcp@latest"]
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
58
|
+
```bash
|
|
59
|
+
npx -y @j0hanz/thinkseq-mcp@latest
|
|
75
60
|
```
|
|
76
61
|
|
|
77
|
-
</details>
|
|
78
|
-
|
|
79
62
|
<details>
|
|
80
|
-
<summary><b>
|
|
63
|
+
<summary><b>Quick Test with MCP Inspector</b></summary>
|
|
81
64
|
|
|
82
|
-
|
|
65
|
+
You can inspect the tools using the MCP Inspector:
|
|
83
66
|
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
"mcpServers": {
|
|
87
|
-
"thinkseq": {
|
|
88
|
-
"command": "npx",
|
|
89
|
-
"args": ["-y", "@j0hanz/thinkseq-mcp@latest"]
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
67
|
+
```bash
|
|
68
|
+
npx @modelcontextprotocol/inspector npx -y @j0hanz/thinkseq-mcp@latest
|
|
93
69
|
```
|
|
94
70
|
|
|
95
71
|
</details>
|
|
96
72
|
|
|
97
|
-
|
|
98
|
-
<summary><b>Cursor</b></summary>
|
|
73
|
+
## Installation
|
|
99
74
|
|
|
100
|
-
|
|
101
|
-
2. Click **Add New MCP Server**.
|
|
102
|
-
3. Fill in the details:
|
|
103
|
-
- **Name:** `thinkseq`
|
|
104
|
-
- **Type:** `command`
|
|
105
|
-
- **Command:** `npx -y @j0hanz/thinkseq-mcp@latest`
|
|
75
|
+
### Using NPX (Recommended)
|
|
106
76
|
|
|
107
|
-
|
|
77
|
+
This server is designed to be run directly via `npx` in your MCP client configuration.
|
|
108
78
|
|
|
109
|
-
|
|
110
|
-
|
|
79
|
+
```bash
|
|
80
|
+
npx -y @j0hanz/thinkseq-mcp@latest
|
|
81
|
+
```
|
|
111
82
|
|
|
112
|
-
|
|
83
|
+
### From Source
|
|
113
84
|
|
|
114
|
-
|
|
115
|
-
{
|
|
116
|
-
"mcpServers": {
|
|
117
|
-
"thinkseq": {
|
|
118
|
-
"command": "npx",
|
|
119
|
-
"args": ["-y", "@j0hanz/thinkseq-mcp@latest"]
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
```
|
|
85
|
+
1. Clone the repository:
|
|
124
86
|
|
|
125
|
-
|
|
87
|
+
```bash
|
|
88
|
+
git clone https://github.com/j0hanz/thinkseq-mcp-server.git
|
|
89
|
+
cd thinkseq-mcp-server
|
|
90
|
+
```
|
|
126
91
|
|
|
127
|
-
|
|
92
|
+
2. Install dependencies:
|
|
128
93
|
|
|
129
|
-
|
|
94
|
+
```bash
|
|
95
|
+
npm install
|
|
96
|
+
```
|
|
130
97
|
|
|
131
|
-
|
|
98
|
+
3. Build the project:
|
|
132
99
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
| `sessionId` | string | no | Optional session identifier to isolate thought histories. |
|
|
137
|
-
| `totalThoughts` | number | no | Estimated total thoughts (1-25, default: 3). |
|
|
138
|
-
| `revisesThought` | number | no | Revise a previous thought by number. Original preserved for audit. |
|
|
100
|
+
```bash
|
|
101
|
+
npm run build
|
|
102
|
+
```
|
|
139
103
|
|
|
140
|
-
|
|
104
|
+
4. Run the server:
|
|
141
105
|
|
|
142
|
-
|
|
106
|
+
```bash
|
|
107
|
+
node dist/index.js
|
|
108
|
+
```
|
|
143
109
|
|
|
144
|
-
|
|
110
|
+
## Configuration
|
|
145
111
|
|
|
146
|
-
|
|
147
|
-
| :------- | :------ | :----------------------------------- |
|
|
148
|
-
| `ok` | boolean | `true` on success, `false` on error. |
|
|
149
|
-
| `result` | object | Present when `ok` is true. |
|
|
150
|
-
| `error` | object | Present when `ok` is false. |
|
|
112
|
+
The server is configured via CLI arguments.
|
|
151
113
|
|
|
152
|
-
|
|
114
|
+
| Argument | Description | Default |
|
|
115
|
+
| :----------------------------------- | :-------------------------------------------- | :------ |
|
|
116
|
+
| `--max-thoughts <number>` | Max thoughts to keep in memory before pruning | 500 |
|
|
117
|
+
| `--max-memory-mb <number>` | Max memory (MB) for stored thoughts | 100 |
|
|
118
|
+
| `--shutdown-timeout-ms <number>` | Graceful shutdown timeout in ms | 5000 |
|
|
119
|
+
| `--package-read-timeout-ms <number>` | Package.json read timeout in ms | 2000 |
|
|
120
|
+
| `-h, --help` | Show help message | - |
|
|
153
121
|
|
|
154
|
-
|
|
155
|
-
| :--------------------- | :------- | :--------------------------------------------------- |
|
|
156
|
-
| `thoughtNumber` | number | Auto-incremented thought number. |
|
|
157
|
-
| `totalThoughts` | number | Effective total thoughts (at least `thoughtNumber`). |
|
|
158
|
-
| `progress` | number | `thoughtNumber / totalThoughts` (0 to 1). |
|
|
159
|
-
| `isComplete` | boolean | `true` when `thoughtNumber >= totalThoughts`. |
|
|
160
|
-
| `thoughtHistoryLength` | number | Stored thought count after pruning. |
|
|
161
|
-
| `hasRevisions` | boolean | `true` if any thought has been revised. |
|
|
162
|
-
| `activePathLength` | number | Count of non-superseded thoughts. |
|
|
163
|
-
| `revisableThoughts` | number[] | Thought numbers available for revision. |
|
|
164
|
-
| `context` | object | Recent context summary (see below). |
|
|
122
|
+
## MCP Surface
|
|
165
123
|
|
|
166
|
-
|
|
124
|
+
### Tools
|
|
167
125
|
|
|
168
|
-
|
|
169
|
-
| :--------------- | :----- | :---------------------------------------------------------------------- |
|
|
170
|
-
| `recentThoughts` | array | Up to the last 5 active thoughts with `stepIndex`, `number`, `preview`. |
|
|
171
|
-
| `revisionInfo` | object | Present when revising: `revises` (number) and `supersedes` (number[]). |
|
|
126
|
+
#### `thinkseq`
|
|
172
127
|
|
|
173
|
-
|
|
128
|
+
Record a concise thinking step. Be brief: capture only the essential insight, calculation, or decision.
|
|
174
129
|
|
|
175
|
-
|
|
176
|
-
- Revisions are a destructive rewind: they supersede the target thought and any later active thoughts in the active chain.
|
|
177
|
-
- `recentThoughts[].stepIndex` is a contiguous 1-based index in the current active chain (useful when thought numbers become non-contiguous after revisions).
|
|
130
|
+
**Parameters:**
|
|
178
131
|
|
|
179
|
-
|
|
132
|
+
| Name | Type | Required | Description |
|
|
133
|
+
| :--------------- | :------ | :------: | :-------------------------------------------------------------------------------------------------------------------- |
|
|
134
|
+
| `thought` | string | Yes | Your current thinking step (1-8000 chars). |
|
|
135
|
+
| `sessionId` | string | No | Optional session identifier (max 200 chars) to isolate thought histories. |
|
|
136
|
+
| `totalThoughts` | integer | No | Estimated total thoughts (1-25, default: 3). |
|
|
137
|
+
| `revisesThought` | integer | No | Revise a previous thought by number. The original is preserved for audit, but the active chain rewinds to this point. |
|
|
180
138
|
|
|
181
|
-
|
|
182
|
-
| :----------------------------- | :---------------------------------------------- |
|
|
183
|
-
| `E_REVISION_TARGET_NOT_FOUND` | The requested thought number does not exist. |
|
|
184
|
-
| `E_REVISION_TARGET_SUPERSEDED` | The requested thought was already superseded. |
|
|
185
|
-
| `E_THINK` | Unexpected tool failure while processing input. |
|
|
139
|
+
**Returns:**
|
|
186
140
|
|
|
187
|
-
|
|
141
|
+
A JSON object containing the current state of the thinking process, including:
|
|
188
142
|
|
|
189
|
-
|
|
143
|
+
- `thoughtNumber`: The current step number.
|
|
144
|
+
- `progress`: A value between 0 and 1 indicating completion.
|
|
145
|
+
- `isComplete`: Boolean indicating if the thought process is finished.
|
|
146
|
+
- `revisableThoughts`: Array of thought numbers that can be revised.
|
|
147
|
+
- `context`: Recent thoughts and revision information.
|
|
190
148
|
|
|
191
|
-
Input
|
|
149
|
+
**Example Input:**
|
|
192
150
|
|
|
193
151
|
```json
|
|
194
152
|
{
|
|
195
|
-
"thought": "
|
|
153
|
+
"thought": "I need to calculate the fibonacci sequence up to 10.",
|
|
154
|
+
"totalThoughts": 5
|
|
196
155
|
}
|
|
197
156
|
```
|
|
198
157
|
|
|
199
|
-
Output
|
|
158
|
+
**Example Output:**
|
|
200
159
|
|
|
201
160
|
```json
|
|
202
161
|
{
|
|
203
162
|
"ok": true,
|
|
204
163
|
"result": {
|
|
205
164
|
"thoughtNumber": 1,
|
|
206
|
-
"totalThoughts":
|
|
207
|
-
"progress": 0.
|
|
165
|
+
"totalThoughts": 5,
|
|
166
|
+
"progress": 0.2,
|
|
208
167
|
"isComplete": false,
|
|
209
|
-
"thoughtHistoryLength": 1,
|
|
210
|
-
"hasRevisions": false,
|
|
211
|
-
"activePathLength": 1,
|
|
212
168
|
"revisableThoughts": [1],
|
|
213
169
|
"context": {
|
|
214
170
|
"recentThoughts": [
|
|
215
171
|
{
|
|
216
172
|
"stepIndex": 1,
|
|
217
173
|
"number": 1,
|
|
218
|
-
"preview": "
|
|
174
|
+
"preview": "I need to calculate the fibonacci sequence up to 10."
|
|
219
175
|
}
|
|
220
176
|
]
|
|
221
177
|
}
|
|
@@ -223,128 +179,95 @@ Output (success):
|
|
|
223
179
|
}
|
|
224
180
|
```
|
|
225
181
|
|
|
226
|
-
|
|
182
|
+
### Resources
|
|
183
|
+
|
|
184
|
+
_No resources are currently exposed by this server._
|
|
185
|
+
|
|
186
|
+
### Prompts
|
|
227
187
|
|
|
228
|
-
|
|
188
|
+
_No prompts are currently exposed by this server._
|
|
229
189
|
|
|
230
|
-
|
|
190
|
+
## Client Configuration Examples
|
|
191
|
+
|
|
192
|
+
<details>
|
|
193
|
+
<summary><b>VS Code (mcp.json)</b></summary>
|
|
231
194
|
|
|
232
195
|
```json
|
|
233
196
|
{
|
|
234
|
-
"
|
|
235
|
-
|
|
197
|
+
"mcpServers": {
|
|
198
|
+
"thinkseq": {
|
|
199
|
+
"command": "npx",
|
|
200
|
+
"args": ["-y", "@j0hanz/thinkseq-mcp@latest"]
|
|
201
|
+
}
|
|
202
|
+
}
|
|
236
203
|
}
|
|
237
204
|
```
|
|
238
205
|
|
|
239
|
-
|
|
206
|
+
</details>
|
|
207
|
+
|
|
208
|
+
<details>
|
|
209
|
+
<summary><b>Claude Desktop</b></summary>
|
|
210
|
+
|
|
211
|
+
Add this to your `claude_desktop_config.json`:
|
|
240
212
|
|
|
241
213
|
```json
|
|
242
214
|
{
|
|
243
|
-
"
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
"progress": 0.6666666666666666,
|
|
248
|
-
"isComplete": false,
|
|
249
|
-
"thoughtHistoryLength": 2,
|
|
250
|
-
"hasRevisions": true,
|
|
251
|
-
"activePathLength": 1,
|
|
252
|
-
"revisableThoughts": [2],
|
|
253
|
-
"context": {
|
|
254
|
-
"recentThoughts": [
|
|
255
|
-
{
|
|
256
|
-
"stepIndex": 1,
|
|
257
|
-
"number": 2,
|
|
258
|
-
"preview": "Better approach: validate first, then parse"
|
|
259
|
-
}
|
|
260
|
-
],
|
|
261
|
-
"revisionInfo": {
|
|
262
|
-
"revises": 1,
|
|
263
|
-
"supersedes": [1]
|
|
264
|
-
}
|
|
215
|
+
"mcpServers": {
|
|
216
|
+
"thinkseq": {
|
|
217
|
+
"command": "npx",
|
|
218
|
+
"args": ["-y", "@j0hanz/thinkseq-mcp@latest"]
|
|
265
219
|
}
|
|
266
220
|
}
|
|
267
221
|
}
|
|
268
222
|
```
|
|
269
223
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
- Inputs are validated with Zod and unknown keys are rejected.
|
|
273
|
-
- `thoughtNumber` is auto-incremented (1, 2, 3...).
|
|
274
|
-
- `totalThoughts` defaults to 3, must be in 1-25, and is adjusted up to at least `thoughtNumber`.
|
|
275
|
-
- The engine stores thoughts in memory and prunes when limits are exceeded:
|
|
276
|
-
- `maxThoughts` default: 500 (cap 10000). When exceeded, prunes the oldest 10% (minimum excess).
|
|
277
|
-
- `maxMemoryBytes` default: 100 MB. When exceeded and history is large, prunes roughly 20% of history.
|
|
278
|
-
- `estimatedThoughtOverheadBytes` default: 200.
|
|
279
|
-
|
|
280
|
-
## Diagnostics
|
|
281
|
-
|
|
282
|
-
This server publishes events via `node:diagnostics_channel`:
|
|
224
|
+
</details>
|
|
283
225
|
|
|
284
|
-
|
|
285
|
-
|
|
226
|
+
<details>
|
|
227
|
+
<summary><b>Cursor</b></summary>
|
|
286
228
|
|
|
287
|
-
|
|
229
|
+
1. Navigate to **Settings** > **General** > **MCP**.
|
|
230
|
+
2. Click **Add New MCP Server**.
|
|
231
|
+
3. Name: `thinkseq`
|
|
232
|
+
4. Type: `command`
|
|
233
|
+
5. Command: `npx -y @j0hanz/thinkseq-mcp@latest`
|
|
288
234
|
|
|
289
|
-
|
|
235
|
+
</details>
|
|
290
236
|
|
|
291
|
-
##
|
|
237
|
+
## Security
|
|
292
238
|
|
|
293
|
-
|
|
239
|
+
- **Stdio Transport**: This server runs over stdio. It creates a console bridge to intercept `console.log` calls and redirect them to standard error (stderr) to prevent interfering with the JSON-RPC protocol.
|
|
240
|
+
- **Memory Limits**: The server enforces maximum thought counts and memory usage limits (configurable via CLI) to prevent memory exhaustion attacks.
|
|
241
|
+
- **Input Validation**: All inputs are strictly validated using Zod schemas.
|
|
294
242
|
|
|
295
|
-
|
|
243
|
+
## Development Workflow
|
|
296
244
|
|
|
297
|
-
|
|
245
|
+
1. **Install dependencies**:
|
|
298
246
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
| `npm run dev` | Run the server in watch mode. |
|
|
303
|
-
| `npm start` | Run `dist/index.js`. |
|
|
304
|
-
| `npm run test` | Run the test suite. |
|
|
305
|
-
| `npm run test:ci` | Build, then run the test suite. |
|
|
306
|
-
| `npm run test:coverage` | Run tests with coverage output. |
|
|
307
|
-
| `npm run lint` | Lint with ESLint. |
|
|
308
|
-
| `npm run format` | Format with Prettier. |
|
|
309
|
-
| `npm run format:check` | Check formatting with Prettier. |
|
|
310
|
-
| `npm run type-check` | Type-check without emitting. |
|
|
311
|
-
| `npm run inspector` | Launch the MCP inspector. |
|
|
312
|
-
| `npm run clean` | Remove `dist/`. |
|
|
313
|
-
| `npm run prepublishOnly` | Lint, type-check, and build. |
|
|
314
|
-
| `npm run benchmark` | Run `benchmark/engine.bench.ts`. |
|
|
247
|
+
```bash
|
|
248
|
+
npm install
|
|
249
|
+
```
|
|
315
250
|
|
|
316
|
-
|
|
251
|
+
2. **Run in development mode**:
|
|
317
252
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
- `THINKSEQ_BENCH_PIN` (optional CPU affinity mask)
|
|
253
|
+
```bash
|
|
254
|
+
npm run dev # Runs tsc in watch mode
|
|
255
|
+
npm run dev:run # Runs the built app in watch mode
|
|
256
|
+
```
|
|
323
257
|
|
|
324
|
-
|
|
258
|
+
3. **Run tests**:
|
|
325
259
|
|
|
326
|
-
```
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
appConfig.ts # Dependency wiring and shutdown handling
|
|
330
|
-
engine.ts # Core thinking engine
|
|
331
|
-
engineConfig.ts # Defaults and limits
|
|
332
|
-
engine/ # Revision and query helpers
|
|
333
|
-
lib/ # CLI, diagnostics, errors, protocol, stdio utilities
|
|
334
|
-
schemas/ # Zod input/output schemas
|
|
335
|
-
tools/ # MCP tool definitions (thinkseq)
|
|
336
|
-
tests/ # Node.js tests
|
|
337
|
-
benchmark/ # Benchmark targets
|
|
338
|
-
docs/ # Assets (logo)
|
|
339
|
-
dist/ # Build output
|
|
340
|
-
scripts/ # Quality gates and metrics helpers
|
|
341
|
-
metrics/ # Generated metrics outputs
|
|
342
|
-
```
|
|
260
|
+
```bash
|
|
261
|
+
npm test
|
|
262
|
+
```
|
|
343
263
|
|
|
344
|
-
|
|
264
|
+
4. **Lint and Format**:
|
|
345
265
|
|
|
346
|
-
|
|
266
|
+
```bash
|
|
267
|
+
npm run lint
|
|
268
|
+
npm run format
|
|
269
|
+
```
|
|
347
270
|
|
|
348
|
-
## Contributing
|
|
271
|
+
## Contributing & License
|
|
349
272
|
|
|
350
|
-
|
|
273
|
+
This project is licensed under the MIT License.
|
package/dist/app.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import process from 'node:process';
|
|
1
3
|
import { resolvePackageIdentity, resolveRunDependencies, } from './appConfig/runDependencies.js';
|
|
2
4
|
import { buildShutdownDependencies } from './appConfig/shutdown.js';
|
|
3
5
|
import { installConsoleBridge, installMcpLogging } from './lib/mcpLogging.js';
|
|
@@ -8,6 +10,19 @@ const createHandlerFor = (logError, exit) => (label) => (value) => {
|
|
|
8
10
|
logError(`thinkseq: ${label}: ${error.message}`);
|
|
9
11
|
exit(1);
|
|
10
12
|
};
|
|
13
|
+
function getLocalIconData() {
|
|
14
|
+
try {
|
|
15
|
+
const iconPath = new URL('../assets/logo.svg', import.meta.url);
|
|
16
|
+
const buffer = readFileSync(iconPath);
|
|
17
|
+
if (buffer.length > 2 * 1024 * 1024) {
|
|
18
|
+
console.warn('Warning: logo.svg is larger than 2MB');
|
|
19
|
+
}
|
|
20
|
+
return `data:image/svg+xml;base64,${buffer.toString('base64')}`;
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
11
26
|
export function installProcessErrorHandlers(deps = {}) {
|
|
12
27
|
const proc = deps.processLike ?? process;
|
|
13
28
|
const logError = deps.logError ?? console.error;
|
|
@@ -20,7 +35,8 @@ export async function run(deps = {}) {
|
|
|
20
35
|
const resolved = resolveRunDependencies(deps);
|
|
21
36
|
const pkg = await resolved.readPackageJson(AbortSignal.timeout(resolved.packageReadTimeoutMs));
|
|
22
37
|
const { name, version } = resolvePackageIdentity(pkg);
|
|
23
|
-
const
|
|
38
|
+
const localIcon = getLocalIconData();
|
|
39
|
+
const server = resolved.createServer(name, version, localIcon);
|
|
24
40
|
installMcpLogging(server);
|
|
25
41
|
const { flush: flushConsole, restore: restoreConsole } = installConsoleBridge(server);
|
|
26
42
|
process.on('exit', restoreConsole);
|
|
@@ -29,7 +45,7 @@ export async function run(deps = {}) {
|
|
|
29
45
|
ts: resolved.now(),
|
|
30
46
|
});
|
|
31
47
|
const engine = resolved.engineFactory();
|
|
32
|
-
resolved.registerTool(server, engine);
|
|
48
|
+
resolved.registerTool(server, engine, localIcon);
|
|
33
49
|
const transport = await resolved.connectServer(server);
|
|
34
50
|
flushConsole();
|
|
35
51
|
resolved.installShutdownHandlers(buildShutdownDependencies(resolved, { server, engine, transport }));
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import process from 'node:process';
|
|
2
|
+
const FALSY_ENV_VALUES = new Set(['0', 'false', 'no', 'off']);
|
|
3
|
+
function resolveIncludeTextContent() {
|
|
4
|
+
const raw = process.env.THINKSEQ_INCLUDE_TEXT_CONTENT;
|
|
5
|
+
return raw === undefined || !FALSY_ENV_VALUES.has(raw.trim().toLowerCase());
|
|
6
|
+
}
|
|
7
|
+
export const APP_ENV = {
|
|
8
|
+
INCLUDE_TEXT_CONTENT: resolveIncludeTextContent(),
|
|
9
|
+
};
|
|
@@ -8,9 +8,9 @@ export interface RunDependencies {
|
|
|
8
8
|
shutdownTimeoutMs?: number;
|
|
9
9
|
readPackageJson?: (signal?: AbortSignal) => Promise<PackageInfo>;
|
|
10
10
|
publishLifecycleEvent?: (event: LifecycleEvent) => void;
|
|
11
|
-
createServer?: (name: string, version: string) => ServerLike;
|
|
11
|
+
createServer?: (name: string, version: string, icon?: string) => ServerLike;
|
|
12
12
|
connectServer?: (server: ServerLike, createTransport?: () => TransportLike) => Promise<TransportLike>;
|
|
13
|
-
registerTool?: (server: ServerLike, engine: EngineLike) => void;
|
|
13
|
+
registerTool?: (server: ServerLike, engine: EngineLike, icon?: string) => void;
|
|
14
14
|
engineFactory?: () => EngineLike;
|
|
15
15
|
installShutdownHandlers?: (deps: ShutdownDependencies) => void;
|
|
16
16
|
now?: () => number;
|
|
@@ -21,9 +21,9 @@ export interface ResolvedRunDependencies {
|
|
|
21
21
|
shutdownTimeoutMs?: number;
|
|
22
22
|
readPackageJson: (signal?: AbortSignal) => Promise<PackageInfo>;
|
|
23
23
|
publishLifecycleEvent: (event: LifecycleEvent) => void;
|
|
24
|
-
createServer: (name: string, version: string) => ServerLike;
|
|
24
|
+
createServer: (name: string, version: string, icon?: string) => ServerLike;
|
|
25
25
|
connectServer: (server: ServerLike, createTransport?: () => TransportLike) => Promise<TransportLike>;
|
|
26
|
-
registerTool: (server: ServerLike, engine: EngineLike) => void;
|
|
26
|
+
registerTool: (server: ServerLike, engine: EngineLike, icon?: string) => void;
|
|
27
27
|
engineFactory: () => EngineLike;
|
|
28
28
|
installShutdownHandlers: (deps: ShutdownDependencies) => void;
|
|
29
29
|
now: () => number;
|
|
@@ -17,8 +17,7 @@ function readInstructionsText() {
|
|
|
17
17
|
return INSTRUCTIONS_FALLBACK;
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
|
-
function loadServerInstructions() {
|
|
21
|
-
const raw = readInstructionsText();
|
|
20
|
+
function loadServerInstructions(raw) {
|
|
22
21
|
const trimmed = raw.trim();
|
|
23
22
|
return trimmed.length > 0 ? trimmed : INSTRUCTIONS_FALLBACK;
|
|
24
23
|
}
|
|
@@ -37,27 +36,35 @@ function registerInstructionsResource(server) {
|
|
|
37
36
|
contents: [
|
|
38
37
|
{
|
|
39
38
|
uri: uri.href,
|
|
40
|
-
text:
|
|
39
|
+
text: INSTRUCTIONS_TEXT,
|
|
41
40
|
mimeType: 'text/markdown',
|
|
42
41
|
},
|
|
43
42
|
],
|
|
44
43
|
}));
|
|
45
44
|
}
|
|
46
|
-
const
|
|
45
|
+
const INSTRUCTIONS_TEXT = readInstructionsText();
|
|
46
|
+
const SERVER_INSTRUCTIONS = loadServerInstructions(INSTRUCTIONS_TEXT);
|
|
47
47
|
const DEFAULT_PACKAGE_READ_TIMEOUT_MS = 2000;
|
|
48
|
-
function
|
|
48
|
+
function buildServerCapabilities(overrides = {}) {
|
|
49
49
|
return {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
prompts: { listChanged: false },
|
|
56
|
-
},
|
|
50
|
+
logging: {},
|
|
51
|
+
tools: { listChanged: false },
|
|
52
|
+
resources: { subscribe: false, listChanged: false },
|
|
53
|
+
prompts: { listChanged: false },
|
|
54
|
+
...overrides,
|
|
57
55
|
};
|
|
58
56
|
}
|
|
59
|
-
const defaultCreateServer = (name, version) => {
|
|
60
|
-
const
|
|
57
|
+
const defaultCreateServer = (name, version, icon) => {
|
|
58
|
+
const capabilities = buildServerCapabilities();
|
|
59
|
+
const server = new McpServer({ name, version }, {
|
|
60
|
+
instructions: SERVER_INSTRUCTIONS,
|
|
61
|
+
capabilities,
|
|
62
|
+
...(icon
|
|
63
|
+
? {
|
|
64
|
+
icons: [{ src: icon, mimeType: 'image/svg+xml', sizes: ['any'] }],
|
|
65
|
+
}
|
|
66
|
+
: {}),
|
|
67
|
+
});
|
|
61
68
|
registerInstructionsResource(server);
|
|
62
69
|
server.registerPrompt('get-help', {
|
|
63
70
|
description: 'Get usage instructions for this server',
|