zerodb-sequential-thinking-mcp 0.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/.env.example +7 -0
- package/LICENSE +21 -0
- package/README.md +245 -0
- package/index.js +47 -0
- package/package.json +111 -0
- package/src/credentials.js +40 -0
- package/src/plan-store.js +57 -0
- package/src/provision.js +112 -0
- package/src/reasoner.js +56 -0
- package/src/tools.js +63 -0
- package/src/zerodb.js +37 -0
package/.env.example
ADDED
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 AINative Studio
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
# ZeroDB Sequential Thinking MCP
|
|
2
|
+
|
|
3
|
+
Persistent chain-of-thought reasoning for AI agents — reasoning chains survive sessions, resume across agents, and conclusions save as plan artifacts.
|
|
4
|
+
|
|
5
|
+
**Agents self-provision a ZeroDB account on first run. No signup, no dashboard, no API key copy-paste.**
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## What Makes This Different
|
|
10
|
+
|
|
11
|
+
The upstream `@modelcontextprotocol/server-sequential-thinking` discards every reasoning chain when the session ends. This one doesn't.
|
|
12
|
+
|
|
13
|
+
| Feature | Upstream | This package |
|
|
14
|
+
|---------|----------|--------------|
|
|
15
|
+
| Sequential reasoning steps | ✅ | ✅ |
|
|
16
|
+
| Persists across sessions | ❌ | ✅ |
|
|
17
|
+
| Resume prior chain by ID | ❌ | ✅ |
|
|
18
|
+
| Save conclusion as plan artifact | ❌ | ✅ |
|
|
19
|
+
| Agent self-provisioning | ❌ | ✅ |
|
|
20
|
+
| Setup required | Manual | Zero |
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Agent Self-Provisioning
|
|
25
|
+
|
|
26
|
+
This is the key capability: **the agent provisions its own ZeroDB account**. No human needs to visit a dashboard, create an account, or copy an API key.
|
|
27
|
+
|
|
28
|
+
### How it works
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
Agent installs MCP → MCP boots → No credentials found →
|
|
32
|
+
POST /api/v1/instant-db (zero-auth, terms auto-accepted on behalf of user) →
|
|
33
|
+
ZeroDB account created (72h trial) →
|
|
34
|
+
API key + project ID written to ~/.zerodb/credentials.json →
|
|
35
|
+
Claim URL printed to stderr →
|
|
36
|
+
MCP ready — agent starts working immediately
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**The agent does all of this in ~2 seconds on first boot.** Subsequent boots are silent — credentials are read from disk.
|
|
40
|
+
|
|
41
|
+
### For agent swarms and multi-agent systems
|
|
42
|
+
|
|
43
|
+
Each agent instance reads from `~/.zerodb/credentials.json`. In a shared environment (e.g. OpenClaw agent swarm, CrewAI, AutoGen multi-agent), set `ZERODB_CONFIG_DIR` to a shared path so all agents use the same project:
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{
|
|
47
|
+
"mcpServers": {
|
|
48
|
+
"sequential-thinking": {
|
|
49
|
+
"command": "npx",
|
|
50
|
+
"args": ["-y", "zerodb-sequential-thinking-mcp"],
|
|
51
|
+
"env": {
|
|
52
|
+
"ZERODB_CONFIG_DIR": "/shared/zerodb"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Or provision once manually and share credentials via env vars:
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"env": {
|
|
64
|
+
"ZERODB_API_KEY": "zdb_live_...",
|
|
65
|
+
"ZERODB_PROJECT_ID": "your-project-id"
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Claiming the provisioned account
|
|
71
|
+
|
|
72
|
+
On first run you'll see this in stderr:
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
76
|
+
│ ZeroDB account provisioned (72h trial) │
|
|
77
|
+
│ │
|
|
78
|
+
│ Your reasoning chains are now persisted in ZeroDB. │
|
|
79
|
+
│ API key: tmp_xxxxxx... │
|
|
80
|
+
│ │
|
|
81
|
+
│ Claim your account to keep data permanently: │
|
|
82
|
+
│ → https://ainative.studio/claim?token=...&project=... │
|
|
83
|
+
│ │
|
|
84
|
+
│ Optional: set ZERODB_EMAIL=you@email.com in your MCP │
|
|
85
|
+
│ config to receive account details via email. │
|
|
86
|
+
│ │
|
|
87
|
+
│ This message won't appear again after you claim. │
|
|
88
|
+
└─────────────────────────────────────────────────────────────┘
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Visit the claim URL, sign up or log in — your project transfers to your permanent account with a `zdb_live_` API key. All reasoning history is preserved.
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Install
|
|
96
|
+
|
|
97
|
+
### Claude Code
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
npx zerodb-sequential-thinking-mcp
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Or add to `.mcp.json`:
|
|
104
|
+
|
|
105
|
+
```json
|
|
106
|
+
{
|
|
107
|
+
"mcpServers": {
|
|
108
|
+
"sequential-thinking": {
|
|
109
|
+
"command": "npx",
|
|
110
|
+
"args": ["-y", "zerodb-sequential-thinking-mcp"]
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Claude Desktop
|
|
117
|
+
|
|
118
|
+
Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
|
|
119
|
+
|
|
120
|
+
```json
|
|
121
|
+
{
|
|
122
|
+
"mcpServers": {
|
|
123
|
+
"sequential-thinking": {
|
|
124
|
+
"command": "npx",
|
|
125
|
+
"args": ["-y", "zerodb-sequential-thinking-mcp"],
|
|
126
|
+
"env": {
|
|
127
|
+
"ZERODB_EMAIL": "you@email.com"
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Cursor / Windsurf / Cline / Continue
|
|
135
|
+
|
|
136
|
+
Add to your IDE's MCP settings. Same config as above — `command: npx`, `args: ["-y", "zerodb-sequential-thinking-mcp"]`.
|
|
137
|
+
|
|
138
|
+
### OpenClaw / CrewAI / AutoGen / LangChain agent systems
|
|
139
|
+
|
|
140
|
+
For agent swarms, provision once then share credentials via `ZERODB_API_KEY` + `ZERODB_PROJECT_ID` env vars across all agent instances. All agents write to the same ZeroDB project — reasoning chains from any agent are resumable by any other agent.
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## Environment Variables
|
|
145
|
+
|
|
146
|
+
| Variable | Required | Description |
|
|
147
|
+
|----------|----------|-------------|
|
|
148
|
+
| `ZERODB_EMAIL` | No | Receive the claim link + account details via email after auto-provisioning |
|
|
149
|
+
| `ZERODB_API_KEY` | No | Skip auto-provisioning — use an existing ZeroDB key (e.g. after claiming) |
|
|
150
|
+
| `ZERODB_PROJECT_ID` | No | Required when `ZERODB_API_KEY` is set |
|
|
151
|
+
| `ZERODB_BASE_URL` | No | Override API base (default: `https://api.ainative.studio`) |
|
|
152
|
+
| `ZERODB_CONFIG_DIR` | No | Override credentials directory (default: `~/.zerodb`) |
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Tools
|
|
157
|
+
|
|
158
|
+
### `sequential_think`
|
|
159
|
+
|
|
160
|
+
Perform a sequential reasoning step. Chain multiple calls for complex, multi-step problems.
|
|
161
|
+
|
|
162
|
+
| Parameter | Type | Required | Description |
|
|
163
|
+
|-----------|------|----------|-------------|
|
|
164
|
+
| `thought` | string | Yes | The current reasoning step |
|
|
165
|
+
| `chain_id` | string | No | Chain ID — auto-generated on first call, pass on subsequent steps |
|
|
166
|
+
| `step_number` | number | No | Current step number |
|
|
167
|
+
| `total_steps` | number | No | Estimated total steps |
|
|
168
|
+
| `next_step` | string | No | What to reason about next |
|
|
169
|
+
| `is_final` | boolean | No | Is this the last step before concluding? |
|
|
170
|
+
| `persist_steps` | boolean | No | Store each step in ZeroDB working memory (default: `false`) |
|
|
171
|
+
|
|
172
|
+
### `sequential_conclude`
|
|
173
|
+
|
|
174
|
+
Finalize a reasoning chain and save the conclusion as a persistent ZeroDB plan artifact. Returns an `artifact_id` you can pass to `sequential_resume` in any future session or agent.
|
|
175
|
+
|
|
176
|
+
| Parameter | Type | Required | Description |
|
|
177
|
+
|-----------|------|----------|-------------|
|
|
178
|
+
| `conclusion` | string | Yes | The final answer or decision |
|
|
179
|
+
| `chain_id` | string | No | Chain ID from prior `sequential_think` calls |
|
|
180
|
+
| `title` | string | No | Artifact title (defaults to first 60 chars of conclusion) |
|
|
181
|
+
| `save_as` | string | No | `plan`, `prd`, or `task` (default: `plan`) |
|
|
182
|
+
|
|
183
|
+
### `sequential_resume`
|
|
184
|
+
|
|
185
|
+
Load a prior reasoning chain from ZeroDB and continue from where it left off — in any session, on any agent.
|
|
186
|
+
|
|
187
|
+
| Parameter | Type | Required | Description |
|
|
188
|
+
|-----------|------|----------|-------------|
|
|
189
|
+
| `artifact_id` | string | Yes | ID returned by a prior `sequential_conclude` call |
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## Example: Multi-Session, Multi-Agent Reasoning
|
|
194
|
+
|
|
195
|
+
**Agent A, Session 1 — Deep analysis:**
|
|
196
|
+
```
|
|
197
|
+
sequential_think: thought="Analyze architecture options for a payments service"
|
|
198
|
+
sequential_think: thought="Team is 4 engineers, 18-month runway, compliance required"
|
|
199
|
+
sequential_think: thought="Stripe + monolith wins on speed, microservices wins on scale"
|
|
200
|
+
sequential_conclude:
|
|
201
|
+
conclusion="Use Stripe + monolith now. Extract payments microservice at $1M ARR."
|
|
202
|
+
title="Payments Architecture Decision"
|
|
203
|
+
→ artifact_id: "f3a9-..."
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
**Agent B, Session 2 — Resume and extend (different agent, different session):**
|
|
207
|
+
```
|
|
208
|
+
sequential_resume: artifact_id="f3a9-..."
|
|
209
|
+
→ Prior conclusion loaded: "Use Stripe + monolith now..."
|
|
210
|
+
sequential_think: thought="We've hit $1M ARR. Revisiting the migration trigger."
|
|
211
|
+
sequential_conclude:
|
|
212
|
+
conclusion="Begin payments microservice extraction. Start with webhook handler."
|
|
213
|
+
title="Payments Architecture v2"
|
|
214
|
+
→ artifact_id: "b72c-..."
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
The `artifact_id` is the only thing that needs to pass between agents or sessions. Everything else is retrieved from ZeroDB.
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## How Credentials Work
|
|
222
|
+
|
|
223
|
+
```
|
|
224
|
+
First run:
|
|
225
|
+
~/.zerodb/credentials.json created automatically
|
|
226
|
+
{ api_key: "tmp_...", project_id: "...", claimed: false, expires_at: "..." }
|
|
227
|
+
|
|
228
|
+
After claiming:
|
|
229
|
+
{ api_key: "zdb_live_...", project_id: "...", claimed: true }
|
|
230
|
+
Silent boot from here on — no banner, no provisioning calls
|
|
231
|
+
|
|
232
|
+
Power user override (env vars take precedence over credentials file):
|
|
233
|
+
ZERODB_API_KEY + ZERODB_PROJECT_ID → skips all provisioning
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Powered by ZeroDB
|
|
239
|
+
|
|
240
|
+
[ZeroDB](https://ainative.studio) — the agent memory and storage platform built for agentic AI. Every reasoning chain, plan artifact, and working memory record is stored in ZeroDB's `memories` table with vector embeddings for semantic recall.
|
|
241
|
+
|
|
242
|
+
- **Plan artifacts API:** `POST/GET/PATCH /api/v1/public/memory/v2/plan`
|
|
243
|
+
- **Memory API:** `POST /api/v1/public/memory/v2/remember`
|
|
244
|
+
- **Instant provisioning:** `POST /api/v1/instant-db`
|
|
245
|
+
- **Docs:** [ainative.studio/docs](https://ainative.studio/docs)
|
package/index.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import 'dotenv/config';
|
|
3
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
4
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
5
|
+
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
6
|
+
import { provision } from './src/provision.js';
|
|
7
|
+
import { ZeroDBClient } from './src/zerodb.js';
|
|
8
|
+
import { TOOLS, executeTool } from './src/tools.js';
|
|
9
|
+
|
|
10
|
+
async function main() {
|
|
11
|
+
const credentials = await provision();
|
|
12
|
+
const client = new ZeroDBClient(credentials);
|
|
13
|
+
|
|
14
|
+
const server = new Server(
|
|
15
|
+
{ name: 'zerodb-sequential-thinking-mcp', version: '0.1.0' },
|
|
16
|
+
{ capabilities: { tools: {} } }
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
20
|
+
return { tools: TOOLS };
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
24
|
+
const { name, arguments: args } = request.params;
|
|
25
|
+
try {
|
|
26
|
+
const result = await executeTool(name, args || {}, client);
|
|
27
|
+
return {
|
|
28
|
+
content: [{ type: 'text', text: JSON.stringify(result) }]
|
|
29
|
+
};
|
|
30
|
+
} catch (err) {
|
|
31
|
+
return {
|
|
32
|
+
content: [{ type: 'text', text: JSON.stringify({ error: err.message }) }],
|
|
33
|
+
isError: true
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const transport = new StdioServerTransport();
|
|
39
|
+
await server.connect(transport);
|
|
40
|
+
|
|
41
|
+
process.stderr.write('ZeroDB Sequential Thinking MCP v0.1.0 — ready\n');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
main().catch((err) => {
|
|
45
|
+
process.stderr.write(`Fatal: ${err.message}\n`);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "zerodb-sequential-thinking-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Persistent sequential thinking MCP — chain-of-thought reasoning that survives sessions, resumes across agents, and saves conclusions as plan artifacts. Powered by ZeroDB. Zero-config: agents self-provision a ZeroDB account on first run, no signup required.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"zerodb-sequential-thinking-mcp": "./index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"start": "node index.js"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"mcp",
|
|
15
|
+
"mcp-server",
|
|
16
|
+
"mcp-server-hosting",
|
|
17
|
+
"model-context-protocol",
|
|
18
|
+
"model-context-protocol-server",
|
|
19
|
+
"sequential-thinking",
|
|
20
|
+
"sequential-reasoning",
|
|
21
|
+
"chain-of-thought",
|
|
22
|
+
"chain-of-thought-reasoning",
|
|
23
|
+
"reasoning",
|
|
24
|
+
"multi-step-reasoning",
|
|
25
|
+
"problem-solving",
|
|
26
|
+
"structured-thinking",
|
|
27
|
+
"deep-thinking",
|
|
28
|
+
"self-provisioning",
|
|
29
|
+
"agent-provisioning",
|
|
30
|
+
"zero-config",
|
|
31
|
+
"auto-provisioning",
|
|
32
|
+
"zero-signup",
|
|
33
|
+
"instant-setup",
|
|
34
|
+
"agent-onboarding",
|
|
35
|
+
"agent-memory",
|
|
36
|
+
"persistent-memory",
|
|
37
|
+
"cross-session",
|
|
38
|
+
"cross-session-memory",
|
|
39
|
+
"cross-session-reasoning",
|
|
40
|
+
"plan-artifacts",
|
|
41
|
+
"context-management",
|
|
42
|
+
"context-window",
|
|
43
|
+
"conversation-history",
|
|
44
|
+
"long-term-memory",
|
|
45
|
+
"zerodb",
|
|
46
|
+
"ainative",
|
|
47
|
+
"openclaw",
|
|
48
|
+
"openclaw-ai",
|
|
49
|
+
"agent-swarm",
|
|
50
|
+
"zerolocal",
|
|
51
|
+
"claude",
|
|
52
|
+
"claude-code",
|
|
53
|
+
"claude-desktop",
|
|
54
|
+
"claude-ai-agents",
|
|
55
|
+
"codex",
|
|
56
|
+
"openai-agents",
|
|
57
|
+
"openai-codex",
|
|
58
|
+
"windsurf",
|
|
59
|
+
"cursor",
|
|
60
|
+
"cline",
|
|
61
|
+
"continue",
|
|
62
|
+
"vscode",
|
|
63
|
+
"langchain",
|
|
64
|
+
"crewai",
|
|
65
|
+
"autogen",
|
|
66
|
+
"n8n-ai",
|
|
67
|
+
"multi-agent",
|
|
68
|
+
"multi-agent-architecture",
|
|
69
|
+
"agent-orchestration",
|
|
70
|
+
"llm",
|
|
71
|
+
"ai",
|
|
72
|
+
"agentic-ai",
|
|
73
|
+
"ai-agents",
|
|
74
|
+
"ai-tool-calling",
|
|
75
|
+
"rag",
|
|
76
|
+
"retrieval-augmented-generation",
|
|
77
|
+
"local-first-ai"
|
|
78
|
+
],
|
|
79
|
+
"author": {
|
|
80
|
+
"name": "AINative Studio",
|
|
81
|
+
"email": "toby@rely.ventures",
|
|
82
|
+
"url": "https://ainative.studio"
|
|
83
|
+
},
|
|
84
|
+
"license": "MIT",
|
|
85
|
+
"repository": {
|
|
86
|
+
"type": "git",
|
|
87
|
+
"url": "https://github.com/AINative-Studio/zerodb-sequential-thinking-mcp.git"
|
|
88
|
+
},
|
|
89
|
+
"bugs": {
|
|
90
|
+
"url": "https://github.com/AINative-Studio/zerodb-sequential-thinking-mcp/issues"
|
|
91
|
+
},
|
|
92
|
+
"homepage": "https://github.com/AINative-Studio/zerodb-sequential-thinking-mcp#readme",
|
|
93
|
+
"dependencies": {
|
|
94
|
+
"@modelcontextprotocol/sdk": "^0.5.0",
|
|
95
|
+
"dotenv": "^16.4.0"
|
|
96
|
+
},
|
|
97
|
+
"engines": {
|
|
98
|
+
"node": ">=18.0.0"
|
|
99
|
+
},
|
|
100
|
+
"files": [
|
|
101
|
+
"index.js",
|
|
102
|
+
"src/",
|
|
103
|
+
"README.md",
|
|
104
|
+
"LICENSE",
|
|
105
|
+
".env.example"
|
|
106
|
+
],
|
|
107
|
+
"publishConfig": {
|
|
108
|
+
"access": "public",
|
|
109
|
+
"registry": "https://registry.npmjs.org/"
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { homedir } from 'os';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { mkdirSync, readFileSync, writeFileSync, renameSync } from 'fs';
|
|
4
|
+
|
|
5
|
+
function credentialsDir() {
|
|
6
|
+
return process.env.ZERODB_CONFIG_DIR || join(homedir(), '.zerodb');
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function credentialsPath() {
|
|
10
|
+
return join(credentialsDir(), 'credentials.json');
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function readCredentials() {
|
|
14
|
+
try {
|
|
15
|
+
const raw = readFileSync(credentialsPath(), 'utf8');
|
|
16
|
+
return JSON.parse(raw);
|
|
17
|
+
} catch {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function writeCredentials(data) {
|
|
23
|
+
try {
|
|
24
|
+
const dir = credentialsDir();
|
|
25
|
+
mkdirSync(dir, { recursive: true });
|
|
26
|
+
const tmp = credentialsPath() + '.tmp';
|
|
27
|
+
writeFileSync(tmp, JSON.stringify(data, null, 2), 'utf8');
|
|
28
|
+
renameSync(tmp, credentialsPath());
|
|
29
|
+
} catch (e) {
|
|
30
|
+
process.stderr.write(`[zerodb] Warning: could not write credentials: ${e.message}\n`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function markClaimed(newApiKey) {
|
|
35
|
+
const creds = readCredentials();
|
|
36
|
+
if (!creds) return;
|
|
37
|
+
creds.claimed = true;
|
|
38
|
+
if (newApiKey) creds.api_key = newApiKey;
|
|
39
|
+
writeCredentials(creds);
|
|
40
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// Persists concluded reasoning chains as ZeroDB plan artifacts.
|
|
2
|
+
// Artifacts are keyed by artifact_id and can be resumed across sessions.
|
|
3
|
+
|
|
4
|
+
const PLAN_API = '/api/v1/public/memory/v2/plan';
|
|
5
|
+
|
|
6
|
+
export async function concludeChain(chainId, conclusion, title, type = 'plan', client) {
|
|
7
|
+
if (!client) {
|
|
8
|
+
return { artifact_id: null, conclusion, warning: 'No ZeroDB client — conclusion not persisted' };
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const artifactTitle = title || conclusion.slice(0, 60);
|
|
12
|
+
const content = chainId
|
|
13
|
+
? `## Conclusion\n${conclusion}\n\n## Chain ID\n${chainId}`
|
|
14
|
+
: `## Conclusion\n${conclusion}`;
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
const artifact = await client.request('POST', `${PLAN_API}/`, {
|
|
18
|
+
title: artifactTitle,
|
|
19
|
+
type,
|
|
20
|
+
content,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
return {
|
|
24
|
+
artifact_id: artifact.id,
|
|
25
|
+
title: artifact.title,
|
|
26
|
+
type: artifact.type,
|
|
27
|
+
status: artifact.status,
|
|
28
|
+
created_at: artifact.created_at,
|
|
29
|
+
resume_hint: `Use sequential_resume with artifact_id: "${artifact.id}" to continue this reasoning chain in a future session.`,
|
|
30
|
+
};
|
|
31
|
+
} catch (e) {
|
|
32
|
+
process.stderr.write(`[zerodb] Warning: failed to save plan artifact: ${e.message}\n`);
|
|
33
|
+
return { artifact_id: null, conclusion, error: e.message };
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export async function resumeChain(artifactId, client) {
|
|
38
|
+
if (!client) {
|
|
39
|
+
return { error: 'No ZeroDB client — cannot resume' };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
const artifact = await client.request('GET', `${PLAN_API}/${artifactId}`);
|
|
44
|
+
return {
|
|
45
|
+
artifact_id: artifact.id,
|
|
46
|
+
title: artifact.title,
|
|
47
|
+
type: artifact.type,
|
|
48
|
+
status: artifact.status,
|
|
49
|
+
prior_content: artifact.content,
|
|
50
|
+
updated_at: artifact.updated_at,
|
|
51
|
+
resume_instruction: 'Prior reasoning chain loaded. Continue from the conclusion above.',
|
|
52
|
+
};
|
|
53
|
+
} catch (e) {
|
|
54
|
+
process.stderr.write(`[zerodb] Warning: failed to load plan artifact: ${e.message}\n`);
|
|
55
|
+
return { artifact_id: artifactId, error: e.message };
|
|
56
|
+
}
|
|
57
|
+
}
|
package/src/provision.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
// Auto-provisions a ZeroDB account on first run.
|
|
2
|
+
// Full implementation: reads credentials, calls ZeroDB provisioning API,
|
|
3
|
+
// writes credentials to ~/.zerodb-sequential-thinking-mcp.json.
|
|
4
|
+
|
|
5
|
+
import { readCredentials, writeCredentials } from './credentials.js';
|
|
6
|
+
|
|
7
|
+
const API_BASE = 'https://api.ainative.studio';
|
|
8
|
+
|
|
9
|
+
export async function provision() {
|
|
10
|
+
// Power user override
|
|
11
|
+
if (process.env.ZERODB_API_KEY && process.env.ZERODB_PROJECT_ID) {
|
|
12
|
+
return {
|
|
13
|
+
api_key: process.env.ZERODB_API_KEY,
|
|
14
|
+
project_id: process.env.ZERODB_PROJECT_ID,
|
|
15
|
+
base_url: process.env.ZERODB_BASE_URL || API_BASE,
|
|
16
|
+
claimed: true,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const existing = readCredentials();
|
|
21
|
+
if (existing) {
|
|
22
|
+
const now = new Date();
|
|
23
|
+
const expires = existing.expires_at ? new Date(existing.expires_at) : null;
|
|
24
|
+
|
|
25
|
+
if (existing.claimed) return existing;
|
|
26
|
+
|
|
27
|
+
if (expires && expires <= now) {
|
|
28
|
+
process.stderr.write('[zerodb] Trial account expired — provisioning a new one...\n');
|
|
29
|
+
// fall through to re-provision
|
|
30
|
+
} else {
|
|
31
|
+
if (expires) {
|
|
32
|
+
const hoursLeft = Math.round((expires - now) / 3600000);
|
|
33
|
+
if (hoursLeft < 24) {
|
|
34
|
+
printExpiryWarning(existing.claim_url, hoursLeft);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return existing;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Provision new account
|
|
42
|
+
const creds = await createInstantDB();
|
|
43
|
+
writeCredentials(creds);
|
|
44
|
+
printFirstRunBanner(creds.claim_url, creds.api_key);
|
|
45
|
+
|
|
46
|
+
// Soft email capture
|
|
47
|
+
if (process.env.ZERODB_EMAIL) {
|
|
48
|
+
await sendClaimEmail(process.env.ZERODB_EMAIL, creds.claim_url, creds.project_id, creds.api_key).catch(() => {});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return creds;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async function createInstantDB() {
|
|
55
|
+
const res = await fetch(`${API_BASE}/api/v1/instant-db`, {
|
|
56
|
+
method: 'POST',
|
|
57
|
+
headers: { 'Content-Type': 'application/json' },
|
|
58
|
+
body: JSON.stringify({ agree_terms: true, on_behalf_of: 'mcp-sequential-thinking' }),
|
|
59
|
+
signal: AbortSignal.timeout(15000),
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
if (!res.ok) {
|
|
63
|
+
const text = await res.text().catch(() => '');
|
|
64
|
+
throw new Error(`ZeroDB provisioning failed (${res.status}): ${text}`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const data = await res.json();
|
|
68
|
+
return {
|
|
69
|
+
api_key: data.api_key,
|
|
70
|
+
project_id: data.project_id,
|
|
71
|
+
base_url: API_BASE,
|
|
72
|
+
expires_at: data.expires_at,
|
|
73
|
+
claim_url: data.claim_url,
|
|
74
|
+
claimed: false,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async function sendClaimEmail(email, claimUrl, projectId, apiKey) {
|
|
79
|
+
await fetch(`${API_BASE}/api/v1/instant-db/send-claim-email`, {
|
|
80
|
+
method: 'POST',
|
|
81
|
+
headers: { 'Content-Type': 'application/json', 'X-API-Key': apiKey },
|
|
82
|
+
body: JSON.stringify({ email, claim_url: claimUrl, project_id: projectId }),
|
|
83
|
+
signal: AbortSignal.timeout(10000),
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function printFirstRunBanner(claimUrl, apiKey) {
|
|
88
|
+
const key = apiKey ? apiKey.slice(0, 12) + '...' : '(see credentials file)';
|
|
89
|
+
process.stderr.write(`
|
|
90
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
91
|
+
│ ZeroDB account provisioned (72h trial) │
|
|
92
|
+
│ │
|
|
93
|
+
│ Your reasoning chains are now persisted in ZeroDB. │
|
|
94
|
+
│ API key: ${key.padEnd(49)}│
|
|
95
|
+
│ │
|
|
96
|
+
│ Claim your account to keep data permanently: │
|
|
97
|
+
│ → ${(claimUrl || '').slice(0, 55).padEnd(55)}│
|
|
98
|
+
│ │
|
|
99
|
+
│ Optional: set ZERODB_EMAIL=you@email.com in your MCP │
|
|
100
|
+
│ config to receive account details via email. │
|
|
101
|
+
│ │
|
|
102
|
+
│ This message won't appear again after you claim. │
|
|
103
|
+
└─────────────────────────────────────────────────────────────┘
|
|
104
|
+
`);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function printExpiryWarning(claimUrl, hoursLeft) {
|
|
108
|
+
process.stderr.write(`
|
|
109
|
+
[zerodb] ⚠️ Your ZeroDB trial expires in ${hoursLeft}h.
|
|
110
|
+
[zerodb] Claim now to keep your reasoning history: ${claimUrl}
|
|
111
|
+
`);
|
|
112
|
+
}
|
package/src/reasoner.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { randomUUID } from 'crypto';
|
|
2
|
+
|
|
3
|
+
// In-memory chain store for the current session
|
|
4
|
+
const chains = new Map();
|
|
5
|
+
|
|
6
|
+
export function getOrCreateChain(chainId) {
|
|
7
|
+
if (!chainId) chainId = randomUUID();
|
|
8
|
+
if (!chains.has(chainId)) {
|
|
9
|
+
chains.set(chainId, { chainId, steps: [], createdAt: new Date().toISOString() });
|
|
10
|
+
}
|
|
11
|
+
return chains.get(chainId);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export async function addStep(args, client) {
|
|
15
|
+
const { thought, chain_id, step_number, total_steps, next_step, is_final = false, persist_steps = false } = args;
|
|
16
|
+
const chain = getOrCreateChain(chain_id);
|
|
17
|
+
|
|
18
|
+
const step = {
|
|
19
|
+
step: step_number || chain.steps.length + 1,
|
|
20
|
+
thought,
|
|
21
|
+
next_step: next_step || null,
|
|
22
|
+
is_final,
|
|
23
|
+
timestamp: new Date().toISOString(),
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
chain.steps.push(step);
|
|
27
|
+
|
|
28
|
+
// Optional ZeroDB persistence
|
|
29
|
+
if (persist_steps && client) {
|
|
30
|
+
try {
|
|
31
|
+
await client.request('POST', '/api/v1/public/memory/v2/remember', {
|
|
32
|
+
content: `[Step ${step.step}] ${thought}`,
|
|
33
|
+
entity_id: chain.chainId,
|
|
34
|
+
memory_type: 'working',
|
|
35
|
+
importance: 0.6,
|
|
36
|
+
tags: ['sequential-thinking', `chain-${chain.chainId}`],
|
|
37
|
+
});
|
|
38
|
+
} catch (e) {
|
|
39
|
+
process.stderr.write(`[zerodb] Warning: failed to persist step: ${e.message}\n`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
chain_id: chain.chainId,
|
|
45
|
+
step: step.step,
|
|
46
|
+
total_steps: total_steps || '?',
|
|
47
|
+
thought,
|
|
48
|
+
next_step,
|
|
49
|
+
is_final,
|
|
50
|
+
steps_so_far: chain.steps.length,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function getChain(chainId) {
|
|
55
|
+
return chains.get(chainId) || null;
|
|
56
|
+
}
|
package/src/tools.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { addStep, getChain } from './reasoner.js';
|
|
2
|
+
import { concludeChain, resumeChain } from './plan-store.js';
|
|
3
|
+
|
|
4
|
+
export const TOOLS = [
|
|
5
|
+
{
|
|
6
|
+
name: 'sequential_think',
|
|
7
|
+
description: 'Perform a sequential reasoning step. Chain multiple calls for complex problems. Optionally persist steps to ZeroDB for cross-session continuity.',
|
|
8
|
+
inputSchema: {
|
|
9
|
+
type: 'object',
|
|
10
|
+
properties: {
|
|
11
|
+
thought: { type: 'string', description: 'The current reasoning step' },
|
|
12
|
+
chain_id: { type: 'string', description: 'Chain ID (auto-generated on first call)' },
|
|
13
|
+
step_number: { type: 'number', description: 'Current step number' },
|
|
14
|
+
total_steps: { type: 'number', description: 'Estimated total steps' },
|
|
15
|
+
next_step: { type: 'string', description: 'What to reason about next' },
|
|
16
|
+
is_final: { type: 'boolean', description: 'Is this the last step before concluding?', default: false },
|
|
17
|
+
persist_steps: { type: 'boolean', description: 'Persist each step to ZeroDB working memory', default: false }
|
|
18
|
+
},
|
|
19
|
+
required: ['thought']
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
name: 'sequential_conclude',
|
|
24
|
+
description: 'Finalize a reasoning chain and save the conclusion as a persistent ZeroDB plan artifact. Returns an artifact_id you can use to resume in future sessions.',
|
|
25
|
+
inputSchema: {
|
|
26
|
+
type: 'object',
|
|
27
|
+
properties: {
|
|
28
|
+
chain_id: { type: 'string', description: 'Chain ID from sequential_think calls' },
|
|
29
|
+
conclusion: { type: 'string', description: 'The final answer or decision' },
|
|
30
|
+
title: { type: 'string', description: 'Artifact title (defaults to first 60 chars of conclusion)' },
|
|
31
|
+
save_as: { type: 'string', enum: ['plan', 'prd', 'task'], default: 'plan', description: 'Artifact type' }
|
|
32
|
+
},
|
|
33
|
+
required: ['conclusion']
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: 'sequential_resume',
|
|
38
|
+
description: 'Resume a reasoning chain from a previous session using an artifact_id returned by sequential_conclude.',
|
|
39
|
+
inputSchema: {
|
|
40
|
+
type: 'object',
|
|
41
|
+
properties: {
|
|
42
|
+
artifact_id: { type: 'string', description: 'Artifact ID from a prior sequential_conclude call' }
|
|
43
|
+
},
|
|
44
|
+
required: ['artifact_id']
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
export async function executeTool(name, args, client) {
|
|
50
|
+
switch (name) {
|
|
51
|
+
case 'sequential_think':
|
|
52
|
+
return addStep(args, client);
|
|
53
|
+
|
|
54
|
+
case 'sequential_conclude':
|
|
55
|
+
return concludeChain(args.chain_id, args.conclusion, args.title, args.save_as || 'plan', client);
|
|
56
|
+
|
|
57
|
+
case 'sequential_resume':
|
|
58
|
+
return resumeChain(args.artifact_id, client);
|
|
59
|
+
|
|
60
|
+
default:
|
|
61
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
package/src/zerodb.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Thin HTTP client for the ZeroDB / AINative API.
|
|
2
|
+
|
|
3
|
+
export class ZeroDBClient {
|
|
4
|
+
constructor({ api_key, project_id, base_url = 'https://api.ainative.studio' }) {
|
|
5
|
+
this.apiKey = api_key;
|
|
6
|
+
this.projectId = project_id;
|
|
7
|
+
this.baseUrl = base_url;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async request(method, path, body) {
|
|
11
|
+
const url = `${this.baseUrl}${path}`;
|
|
12
|
+
const opts = {
|
|
13
|
+
method,
|
|
14
|
+
headers: {
|
|
15
|
+
'Content-Type': 'application/json',
|
|
16
|
+
'X-API-Key': this.apiKey,
|
|
17
|
+
},
|
|
18
|
+
signal: AbortSignal.timeout(10000),
|
|
19
|
+
};
|
|
20
|
+
if (body && method !== 'GET') opts.body = JSON.stringify(body);
|
|
21
|
+
|
|
22
|
+
const res = await fetch(url, opts);
|
|
23
|
+
|
|
24
|
+
if (res.status === 401) {
|
|
25
|
+
process.stderr.write('[zerodb] 401 Unauthorized — your API key may have expired. Re-run to re-provision or set ZERODB_API_KEY.\n');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (!res.ok) {
|
|
29
|
+
const text = await res.text().catch(() => '');
|
|
30
|
+
throw new Error(`ZeroDB API error ${res.status} ${method} ${path}: ${text}`);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const ct = res.headers.get('content-type') || '';
|
|
34
|
+
if (ct.includes('application/json')) return res.json();
|
|
35
|
+
return res.text();
|
|
36
|
+
}
|
|
37
|
+
}
|