@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 CHANGED
@@ -1,221 +1,177 @@
1
1
  # ThinkSeq MCP Server
2
2
 
3
- <img src="docs/logo.png" alt="ThinkSeq MCP Server Logo" width="175" />
3
+ <img src="assets/logo.svg" alt="ThinkSeq MCP Server Logo" width="225" />
4
4
 
5
- An MCP server for structured, sequential thinking with revision support.
6
-
7
- [![npm version](https://img.shields.io/npm/v/@j0hanz/thinkseq-mcp.svg)](https://www.npmjs.com/package/@j0hanz/thinkseq-mcp)
8
-
9
- ## One-click install
5
+ [![npm version](https://img.shields.io/npm/v/@j0hanz/thinkseq-mcp.svg)](https://www.npmjs.com/package/@j0hanz/thinkseq-mcp)[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)[![Powered by MCP](https://img.shields.io/badge/MCP-SDK-blue)](https://github.com/modelcontextprotocol/typescript-sdk)
10
6
 
11
7
  [![Install with NPX in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](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) [![Install with NPX in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](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
  [![Install in Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/install-mcp?name=thinkseq&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBqMGhhbnovdGhpbmtzZXEtbWNwQGxhdGVzdCJdfQ==)
14
10
 
15
- ## Overview
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
- ```bash
22
- npx -y @j0hanz/thinkseq-mcp@latest
23
- ```
13
+ ## Overview
24
14
 
25
- ## CLI options
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
- ```bash
28
- thinkseq --max-thoughts 500 --max-memory-mb 100
29
- ```
17
+ ## Key Features
30
18
 
31
- Available flags:
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
- - `--max-thoughts <number>`: Max thoughts to keep in memory.
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
- Defaults and limits:
28
+ - **Runtime**: Node.js >=22.0.0
29
+ - **Language**: TypeScript 5.9+
30
+ - **MCP SDK**: `@modelcontextprotocol/sdk`
31
+ - **Validation**: `zod`
40
32
 
41
- - `maxThoughts` default: 500 (cap 10000).
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
- ## MCP client configuration
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
- Add this to your MCP client settings:
50
+ ## Requirements
49
51
 
50
- ```json
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
- <details>
62
- <summary><b>VS Code</b></summary>
54
+ ## Quickstart
63
55
 
64
- Add to your `mcp.json` (command palette: "MCP: Open Settings"):
56
+ To run the server using `npx`:
65
57
 
66
- ```json
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>Claude Desktop</b></summary>
63
+ <summary><b>Quick Test with MCP Inspector</b></summary>
81
64
 
82
- Add to your `claude_desktop_config.json`:
65
+ You can inspect the tools using the MCP Inspector:
83
66
 
84
- ```json
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
- <details>
98
- <summary><b>Cursor</b></summary>
73
+ ## Installation
99
74
 
100
- 1. Go to **Cursor Settings** > **General** > **MCP**.
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
- </details>
77
+ This server is designed to be run directly via `npx` in your MCP client configuration.
108
78
 
109
- <details>
110
- <summary><b>Windsurf</b></summary>
79
+ ```bash
80
+ npx -y @j0hanz/thinkseq-mcp@latest
81
+ ```
111
82
 
112
- Add to your `~/.codeium/windsurf/mcp_config.json`:
83
+ ### From Source
113
84
 
114
- ```json
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
- </details>
87
+ ```bash
88
+ git clone https://github.com/j0hanz/thinkseq-mcp-server.git
89
+ cd thinkseq-mcp-server
90
+ ```
126
91
 
127
- ## Tool: `thinkseq`
92
+ 2. Install dependencies:
128
93
 
129
- Record a concise thinking step. Be brief: capture only the essential insight, calculation, or decision-like a minimal draft, not a verbose explanation.
94
+ ```bash
95
+ npm install
96
+ ```
130
97
 
131
- ### Input
98
+ 3. Build the project:
132
99
 
133
- | Field | Type | Required | Description |
134
- | :--------------- | :----- | :------: | :----------------------------------------------------------------- |
135
- | `thought` | string | yes | Current thinking step (1-8000 chars). |
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
- ### Output
104
+ 4. Run the server:
141
105
 
142
- The tool returns `structuredContent` with an `ok` flag. On success, `result` is populated; on error, `error` is populated.
106
+ ```bash
107
+ node dist/index.js
108
+ ```
143
109
 
144
- Envelope fields:
110
+ ## Configuration
145
111
 
146
- | Field | Type | Description |
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
- Result fields:
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
- | Field | Type | Description |
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
- Context fields:
124
+ ### Tools
167
125
 
168
- | Field | Type | Description |
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
- Notes:
128
+ Record a concise thinking step. Be brief: capture only the essential insight, calculation, or decision.
174
129
 
175
- - `recentThoughts` previews are truncated to 100 characters.
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
- Error fields:
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
- | Code | Description |
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
- ### Example
141
+ A JSON object containing the current state of the thinking process, including:
188
142
 
189
- **Basic usage:**
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": "3 steps: parse -> validate -> transform"
153
+ "thought": "I need to calculate the fibonacci sequence up to 10.",
154
+ "totalThoughts": 5
196
155
  }
197
156
  ```
198
157
 
199
- Output (success):
158
+ **Example Output:**
200
159
 
201
160
  ```json
202
161
  {
203
162
  "ok": true,
204
163
  "result": {
205
164
  "thoughtNumber": 1,
206
- "totalThoughts": 3,
207
- "progress": 0.3333333333333333,
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": "3 steps: parse -> validate -> transform"
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
- **Revising a thought:**
182
+ ### Resources
183
+
184
+ _No resources are currently exposed by this server._
185
+
186
+ ### Prompts
227
187
 
228
- If you realize an earlier step was wrong, use `revisesThought` to correct it:
188
+ _No prompts are currently exposed by this server._
229
189
 
230
- Input:
190
+ ## Client Configuration Examples
191
+
192
+ <details>
193
+ <summary><b>VS Code (mcp.json)</b></summary>
231
194
 
232
195
  ```json
233
196
  {
234
- "thought": "Better approach: validate first, then parse",
235
- "revisesThought": 1
197
+ "mcpServers": {
198
+ "thinkseq": {
199
+ "command": "npx",
200
+ "args": ["-y", "@j0hanz/thinkseq-mcp@latest"]
201
+ }
202
+ }
236
203
  }
237
204
  ```
238
205
 
239
- Output:
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
- "ok": true,
244
- "result": {
245
- "thoughtNumber": 2,
246
- "totalThoughts": 3,
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
- ## Behavior and validation
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
- - `thinkseq:tool` for `tool.start` and `tool.end` (includes duration, errors, and request context).
285
- - `thinkseq:lifecycle` for `lifecycle.started` and `lifecycle.shutdown`.
226
+ <details>
227
+ <summary><b>Cursor</b></summary>
286
228
 
287
- ## Configuration
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
- No environment variables or CLI flags are required for basic operation. The server runs over stdio, enforces MCP initialization order, and validates protocol versions. Invalid JSON-RPC message shapes and parse errors are surfaced as JSON-RPC errors on stdio.
235
+ </details>
290
236
 
291
- ## Development
237
+ ## Security
292
238
 
293
- ### Prerequisites
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
- - Node.js >= 20.0.0
243
+ ## Development Workflow
296
244
 
297
- ### Scripts
245
+ 1. **Install dependencies**:
298
246
 
299
- | Command | Description |
300
- | :----------------------- | :------------------------------- |
301
- | `npm run build` | Compile TypeScript to `dist/`. |
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
- Benchmark environment variables:
251
+ 2. **Run in development mode**:
317
252
 
318
- - `THINKSEQ_BENCH_SAMPLES` (default: 1)
319
- - `THINKSEQ_BENCH_NEW_ITERATIONS` (default: 10000)
320
- - `THINKSEQ_BENCH_REV_ITERATIONS` (default: 1000)
321
- - `THINKSEQ_BENCH_WARMUP` (default: 1000)
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
- ### Project structure
258
+ 3. **Run tests**:
325
259
 
326
- ```text
327
- src/
328
- app.ts # Application setup and MCP wiring
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
- ## Troubleshooting
264
+ 4. **Lint and Format**:
345
265
 
346
- - CI workflow references `npm run maintainability` and `npm run duplication`, but these scripts are not defined in `package.json`.
266
+ ```bash
267
+ npm run lint
268
+ npm run format
269
+ ```
347
270
 
348
- ## Contributing
271
+ ## Contributing & License
349
272
 
350
- Contributions are welcome. Please open a pull request with a clear description and include relevant tests.
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 server = resolved.createServer(name, version);
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,3 @@
1
+ export declare const APP_ENV: {
2
+ readonly INCLUDE_TEXT_CONTENT: boolean;
3
+ };
@@ -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: readInstructionsText(),
39
+ text: INSTRUCTIONS_TEXT,
41
40
  mimeType: 'text/markdown',
42
41
  },
43
42
  ],
44
43
  }));
45
44
  }
46
- const SERVER_INSTRUCTIONS = loadServerInstructions();
45
+ const INSTRUCTIONS_TEXT = readInstructionsText();
46
+ const SERVER_INSTRUCTIONS = loadServerInstructions(INSTRUCTIONS_TEXT);
47
47
  const DEFAULT_PACKAGE_READ_TIMEOUT_MS = 2000;
48
- function buildServerConfig() {
48
+ function buildServerCapabilities(overrides = {}) {
49
49
  return {
50
- instructions: SERVER_INSTRUCTIONS,
51
- capabilities: {
52
- logging: {},
53
- tools: { listChanged: false },
54
- resources: { subscribe: false, listChanged: false },
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 server = new McpServer({ name, version }, buildServerConfig());
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',