@vampsieee/techterrain-mcp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +95 -0
- package/dist/index.js +336 -0
- package/package.json +52 -0
- package/server.json +76 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-2026 Romulus (https://techterrain.io)
|
|
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,95 @@
|
|
|
1
|
+
# @vampsieee/techterrain-mcp
|
|
2
|
+
|
|
3
|
+
An [MCP server](https://modelcontextprotocol.io) that lets AI agents explore **3.4 million years of technology history** through [TechTerrain](https://techterrain.io) — a 3D voxel timeline of 1,200+ curated milestones.
|
|
4
|
+
|
|
5
|
+
Capture screenshots, generate GIFs, search any topic, and analyze cross-domain patterns — all from Claude, OpenClaw, or any MCP-compatible client.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx -y @vampsieee/techterrain-mcp
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
No API key required. The server connects to the public TechTerrain API at techterrain.io.
|
|
14
|
+
|
|
15
|
+
## Claude Desktop
|
|
16
|
+
|
|
17
|
+
Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
|
|
18
|
+
|
|
19
|
+
```json
|
|
20
|
+
{
|
|
21
|
+
"mcpServers": {
|
|
22
|
+
"techterrain": {
|
|
23
|
+
"command": "npx",
|
|
24
|
+
"args": ["-y", "@vampsieee/techterrain-mcp"]
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Restart Claude Desktop. You'll see the hammer icon with 7 tools.
|
|
31
|
+
|
|
32
|
+
## Try It
|
|
33
|
+
|
|
34
|
+
> "Explore quantum computing on TechTerrain and take a screenshot"
|
|
35
|
+
|
|
36
|
+
> "Show me how AI and biotech have co-evolved, then generate a GIF orbiting the scene"
|
|
37
|
+
|
|
38
|
+
> "What causal relationships exist between technology categories?"
|
|
39
|
+
|
|
40
|
+
## Tools
|
|
41
|
+
|
|
42
|
+
| Tool | Description | Cost |
|
|
43
|
+
|------|-------------|------|
|
|
44
|
+
| `capture_screenshot` | Headless screenshot via Cloudflare Browser Rendering → CDN URL | Free (35/hr) |
|
|
45
|
+
| `capture_gif` | Animated GIF generation (orbit or timelapse) → async job | Free (35/hr) |
|
|
46
|
+
| `get_gif_status` | Poll async GIF job progress and get result URL | Free |
|
|
47
|
+
| `explore_topic` | Search any topic → mapped milestones with years, categories, impact | LLM cost |
|
|
48
|
+
| `generate_insights` | LLM pattern analysis of a scene descriptor | LLM cost |
|
|
49
|
+
| `list_captures` | Browse the Agent Showcase gallery | Free |
|
|
50
|
+
| `get_insights` | Pre-computed Granger causality findings | Free |
|
|
51
|
+
|
|
52
|
+
## Resources
|
|
53
|
+
|
|
54
|
+
| Resource | URI | Description |
|
|
55
|
+
|----------|-----|-------------|
|
|
56
|
+
| Agent API Docs | `techterrain://docs` | Full API reference with code examples |
|
|
57
|
+
| LLM Documentation | `techterrain://llms.txt` | Concise API reference for LLMs |
|
|
58
|
+
| Dataset | `techterrain://dataset` | Raw milestone dataset (1,200+ entries) |
|
|
59
|
+
|
|
60
|
+
## Example Workflow
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
User: "Show me how AI and biotech have co-evolved"
|
|
64
|
+
|
|
65
|
+
Agent:
|
|
66
|
+
1. explore_topic("AI biotech co-evolution")
|
|
67
|
+
→ Gets 15 milestones mapped across both categories
|
|
68
|
+
2. capture_screenshot({
|
|
69
|
+
injectJs: "window.__techterrain.navigate({goto: 2010, categories: ['AI', 'Health']})",
|
|
70
|
+
caption: "AI-Biotech convergence 2010s"
|
|
71
|
+
})
|
|
72
|
+
→ Gets CDN URL of the rendered view
|
|
73
|
+
3. get_insights({ limit: 5 })
|
|
74
|
+
→ Gets pre-computed causal findings about AI↔Health correlations
|
|
75
|
+
4. Returns: image, milestones, and statistical insights to user
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Environment Variables
|
|
79
|
+
|
|
80
|
+
| Variable | Default | Description |
|
|
81
|
+
|----------|---------|-------------|
|
|
82
|
+
| `TECHTERRAIN_URL` | `https://techterrain.io` | Base URL of the TechTerrain instance |
|
|
83
|
+
|
|
84
|
+
## Development
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
cd mcp
|
|
88
|
+
pnpm install
|
|
89
|
+
npm run dev # Run with tsx (hot reload)
|
|
90
|
+
npm run build # Build distributable
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## License
|
|
94
|
+
|
|
95
|
+
MIT
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// techterrain-mcp-server.ts
|
|
4
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
5
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
var BASE_URL = process.env.TECHTERRAIN_URL || "https://techterrain.io";
|
|
8
|
+
var TRPC_URL = `${BASE_URL}/api/trpc`;
|
|
9
|
+
async function trpcMutate(procedure, input) {
|
|
10
|
+
const res = await fetch(`${TRPC_URL}/${procedure}?batch=1`, {
|
|
11
|
+
method: "POST",
|
|
12
|
+
headers: { "Content-Type": "application/json" },
|
|
13
|
+
body: JSON.stringify({ "0": { json: input } })
|
|
14
|
+
});
|
|
15
|
+
if (!res.ok) {
|
|
16
|
+
const text = await res.text();
|
|
17
|
+
throw new Error(`tRPC ${procedure} failed (${res.status}): ${text}`);
|
|
18
|
+
}
|
|
19
|
+
const batch = await res.json();
|
|
20
|
+
if (batch[0]?.error) {
|
|
21
|
+
throw new Error(`tRPC ${procedure} error: ${JSON.stringify(batch[0].error)}`);
|
|
22
|
+
}
|
|
23
|
+
return batch[0]?.result?.data?.json;
|
|
24
|
+
}
|
|
25
|
+
async function trpcQuery(procedure, input) {
|
|
26
|
+
const inputParam = input ? `&input=${encodeURIComponent(JSON.stringify({ "0": { json: input } }))}` : `&input=${encodeURIComponent(JSON.stringify({ "0": { json: void 0 } }))}`;
|
|
27
|
+
const res = await fetch(`${TRPC_URL}/${procedure}?batch=1${inputParam}`, {
|
|
28
|
+
method: "GET",
|
|
29
|
+
headers: { "Content-Type": "application/json" }
|
|
30
|
+
});
|
|
31
|
+
if (!res.ok) {
|
|
32
|
+
const text = await res.text();
|
|
33
|
+
throw new Error(`tRPC ${procedure} failed (${res.status}): ${text}`);
|
|
34
|
+
}
|
|
35
|
+
const batch = await res.json();
|
|
36
|
+
if (batch[0]?.error) {
|
|
37
|
+
throw new Error(`tRPC ${procedure} error: ${JSON.stringify(batch[0].error)}`);
|
|
38
|
+
}
|
|
39
|
+
return batch[0]?.result?.data?.json;
|
|
40
|
+
}
|
|
41
|
+
async function fetchText(path) {
|
|
42
|
+
const res = await fetch(`${BASE_URL}${path}`);
|
|
43
|
+
if (!res.ok) throw new Error(`Failed to fetch ${path}: ${res.status}`);
|
|
44
|
+
return res.text();
|
|
45
|
+
}
|
|
46
|
+
var server = new McpServer({
|
|
47
|
+
name: "techterrain",
|
|
48
|
+
version: "1.0.0"
|
|
49
|
+
});
|
|
50
|
+
server.resource(
|
|
51
|
+
"docs",
|
|
52
|
+
"techterrain://docs",
|
|
53
|
+
{
|
|
54
|
+
description: "TechTerrain Agent API documentation \u2014 full reference with code examples for all endpoints",
|
|
55
|
+
mimeType: "text/html"
|
|
56
|
+
},
|
|
57
|
+
async () => ({
|
|
58
|
+
contents: [{
|
|
59
|
+
uri: "techterrain://docs",
|
|
60
|
+
text: await fetchText("/agent-docs.html"),
|
|
61
|
+
mimeType: "text/html"
|
|
62
|
+
}]
|
|
63
|
+
})
|
|
64
|
+
);
|
|
65
|
+
server.resource(
|
|
66
|
+
"llms-txt",
|
|
67
|
+
"techterrain://llms.txt",
|
|
68
|
+
{
|
|
69
|
+
description: "LLM-optimized documentation for TechTerrain \u2014 concise API reference, recommended workflows, and data coverage",
|
|
70
|
+
mimeType: "text/plain"
|
|
71
|
+
},
|
|
72
|
+
async () => ({
|
|
73
|
+
contents: [{
|
|
74
|
+
uri: "techterrain://llms.txt",
|
|
75
|
+
text: await fetchText("/llms.txt"),
|
|
76
|
+
mimeType: "text/plain"
|
|
77
|
+
}]
|
|
78
|
+
})
|
|
79
|
+
);
|
|
80
|
+
server.resource(
|
|
81
|
+
"dataset",
|
|
82
|
+
"techterrain://dataset",
|
|
83
|
+
{
|
|
84
|
+
description: "Raw TechTerrain milestone dataset \u2014 1,200+ curated technology milestones across 7 categories spanning 3.4 million years",
|
|
85
|
+
mimeType: "application/json"
|
|
86
|
+
},
|
|
87
|
+
async () => ({
|
|
88
|
+
contents: [{
|
|
89
|
+
uri: "techterrain://dataset",
|
|
90
|
+
text: await fetchText("/tech_data.json"),
|
|
91
|
+
mimeType: "application/json"
|
|
92
|
+
}]
|
|
93
|
+
})
|
|
94
|
+
);
|
|
95
|
+
server.tool(
|
|
96
|
+
"capture_screenshot",
|
|
97
|
+
`Render a headless screenshot of TechTerrain via Cloudflare Browser Rendering.
|
|
98
|
+
Returns a public CDN URL of the captured image. No client-side browser needed.
|
|
99
|
+
Use injectJs to position the camera, navigate to a year, or trigger UI actions before capture.
|
|
100
|
+
Rate limit: 35 renders/hour.`,
|
|
101
|
+
{
|
|
102
|
+
path: z.string().default("/").describe('URL path, e.g. "/" or "/explore/1900-2020/Computing,AI"'),
|
|
103
|
+
width: z.number().min(320).max(3840).default(1280).describe("Viewport width in pixels"),
|
|
104
|
+
height: z.number().min(240).max(2160).default(720).describe("Viewport height in pixels"),
|
|
105
|
+
format: z.enum(["png", "jpeg"]).default("png").describe("Image format"),
|
|
106
|
+
injectJs: z.string().optional().describe('JavaScript to inject after scene ready. Example: "window.__techterrain.navigate({goto: 1969})"'),
|
|
107
|
+
waitForOverlays: z.boolean().default(false).describe("Wait for search overlay data to finish loading before capture (set true when injectJs triggers a search)"),
|
|
108
|
+
caption: z.string().optional().describe("Caption for the showcase gallery"),
|
|
109
|
+
authorName: z.string().optional().describe("Author name for attribution")
|
|
110
|
+
},
|
|
111
|
+
async (args) => {
|
|
112
|
+
try {
|
|
113
|
+
const result = await trpcMutate("agent.renderUrl", args);
|
|
114
|
+
return {
|
|
115
|
+
content: [{
|
|
116
|
+
type: "text",
|
|
117
|
+
text: JSON.stringify({
|
|
118
|
+
success: true,
|
|
119
|
+
imageUrl: result.url,
|
|
120
|
+
browserMsUsed: result.browserMsUsed,
|
|
121
|
+
message: "Screenshot captured and uploaded to CDN."
|
|
122
|
+
}, null, 2)
|
|
123
|
+
}]
|
|
124
|
+
};
|
|
125
|
+
} catch (err) {
|
|
126
|
+
return {
|
|
127
|
+
content: [{ type: "text", text: `Error: ${err.message}` }],
|
|
128
|
+
isError: true
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
);
|
|
133
|
+
server.tool(
|
|
134
|
+
"capture_gif",
|
|
135
|
+
`Generate an animated GIF of TechTerrain via server-side Cloudflare Browser Rendering.
|
|
136
|
+
Returns a jobId immediately \u2014 poll with get_gif_status to check completion.
|
|
137
|
+
Two modes: "orbit" rotates the camera around the scene, "timeLapse" scrubs through years.
|
|
138
|
+
Rate limit: 35 renders/hour (each frame counts as one render).`,
|
|
139
|
+
{
|
|
140
|
+
path: z.string().default("/").describe("URL path to render"),
|
|
141
|
+
mode: z.enum(["orbit", "timeLapse"]).default("orbit").describe("orbit = camera rotation, timeLapse = year scrubbing"),
|
|
142
|
+
frameCount: z.number().min(2).max(24).default(12).describe("Number of frames in the GIF"),
|
|
143
|
+
totalRotationDeg: z.number().min(10).max(360).default(360).describe("Total camera rotation in degrees (orbit mode only)"),
|
|
144
|
+
startYear: z.number().optional().describe("Start year for timeLapse mode (supports negative/BCE values like -3400000)"),
|
|
145
|
+
endYear: z.number().optional().describe("End year for timeLapse mode"),
|
|
146
|
+
width: z.number().min(320).max(1920).default(800).describe("Frame width in pixels"),
|
|
147
|
+
height: z.number().min(240).max(1080).default(600).describe("Frame height in pixels"),
|
|
148
|
+
frameDelay: z.number().min(50).max(2e3).default(200).describe("Delay between frames in ms"),
|
|
149
|
+
injectJs: z.string().optional().describe("JavaScript to inject before capture begins"),
|
|
150
|
+
caption: z.string().optional().describe("Caption for the showcase gallery"),
|
|
151
|
+
authorName: z.string().optional().describe("Author name for attribution")
|
|
152
|
+
},
|
|
153
|
+
async (args) => {
|
|
154
|
+
try {
|
|
155
|
+
const result = await trpcMutate("agent.renderGif", args);
|
|
156
|
+
return {
|
|
157
|
+
content: [{
|
|
158
|
+
type: "text",
|
|
159
|
+
text: JSON.stringify({
|
|
160
|
+
success: true,
|
|
161
|
+
jobId: result.jobId,
|
|
162
|
+
status: result.status,
|
|
163
|
+
message: "GIF generation started. Poll with get_gif_status tool using this jobId."
|
|
164
|
+
}, null, 2)
|
|
165
|
+
}]
|
|
166
|
+
};
|
|
167
|
+
} catch (err) {
|
|
168
|
+
return {
|
|
169
|
+
content: [{ type: "text", text: `Error: ${err.message}` }],
|
|
170
|
+
isError: true
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
);
|
|
175
|
+
server.tool(
|
|
176
|
+
"get_gif_status",
|
|
177
|
+
`Poll the status of an async GIF generation job.
|
|
178
|
+
Returns progress percentage, frames captured, and the final CDN URL when complete.`,
|
|
179
|
+
{
|
|
180
|
+
jobId: z.string().describe("The jobId returned by capture_gif")
|
|
181
|
+
},
|
|
182
|
+
async (args) => {
|
|
183
|
+
try {
|
|
184
|
+
const result = await trpcQuery("agent.renderGifStatus", args);
|
|
185
|
+
return {
|
|
186
|
+
content: [{
|
|
187
|
+
type: "text",
|
|
188
|
+
text: JSON.stringify({
|
|
189
|
+
jobId: result.jobId,
|
|
190
|
+
status: result.status,
|
|
191
|
+
progress: `${result.progress}%`,
|
|
192
|
+
framesCaptured: result.framesCaptured,
|
|
193
|
+
framesTotalRequested: result.framesTotalRequested,
|
|
194
|
+
...result.resultUrl ? { gifUrl: result.resultUrl } : {},
|
|
195
|
+
...result.browserMsUsed ? { browserMsUsed: result.browserMsUsed } : {},
|
|
196
|
+
...result.errorMessage ? { error: result.errorMessage } : {}
|
|
197
|
+
}, null, 2)
|
|
198
|
+
}]
|
|
199
|
+
};
|
|
200
|
+
} catch (err) {
|
|
201
|
+
return {
|
|
202
|
+
content: [{ type: "text", text: `Error: ${err.message}` }],
|
|
203
|
+
isError: true
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
);
|
|
208
|
+
server.tool(
|
|
209
|
+
"explore_topic",
|
|
210
|
+
`Search any topic and get it mapped onto TechTerrain's timeline.
|
|
211
|
+
Uses LLM synthesis to find relevant technology milestones for any subject \u2014
|
|
212
|
+
people, companies, concepts, events, or scientific fields.
|
|
213
|
+
Returns structured milestone data with years, categories, impact scores, and source URLs.`,
|
|
214
|
+
{
|
|
215
|
+
query: z.string().describe('Topic to explore, e.g. "quantum computing", "Nikola Tesla", "CRISPR gene editing"')
|
|
216
|
+
},
|
|
217
|
+
async (args) => {
|
|
218
|
+
try {
|
|
219
|
+
const result = await trpcMutate("search.explore", { query: args.query });
|
|
220
|
+
return {
|
|
221
|
+
content: [{
|
|
222
|
+
type: "text",
|
|
223
|
+
text: JSON.stringify({
|
|
224
|
+
query: result.query,
|
|
225
|
+
summary: result.summary,
|
|
226
|
+
milestoneCount: result.milestones.length,
|
|
227
|
+
milestones: result.milestones
|
|
228
|
+
}, null, 2)
|
|
229
|
+
}]
|
|
230
|
+
};
|
|
231
|
+
} catch (err) {
|
|
232
|
+
return {
|
|
233
|
+
content: [{ type: "text", text: `Error: ${err.message}` }],
|
|
234
|
+
isError: true
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
);
|
|
239
|
+
server.tool(
|
|
240
|
+
"generate_insights",
|
|
241
|
+
`Generate LLM-powered pattern analysis from a TechTerrain scene descriptor.
|
|
242
|
+
Pass the output of getSceneDescriptor() to get cross-domain correlations,
|
|
243
|
+
geographic clustering patterns, and acceleration/deceleration insights.
|
|
244
|
+
Each insight includes confidence rating and suggested camera view.`,
|
|
245
|
+
{
|
|
246
|
+
sceneDescriptor: z.any().describe("Scene descriptor JSON from window.__techterrain.getSceneDescriptor()"),
|
|
247
|
+
focusArea: z.string().optional().describe('Optional focus, e.g. "cross-category correlations" or "geographic clustering"')
|
|
248
|
+
},
|
|
249
|
+
async (args) => {
|
|
250
|
+
try {
|
|
251
|
+
const result = await trpcMutate("agent.generateInsights", args);
|
|
252
|
+
return {
|
|
253
|
+
content: [{
|
|
254
|
+
type: "text",
|
|
255
|
+
text: JSON.stringify(result, null, 2)
|
|
256
|
+
}]
|
|
257
|
+
};
|
|
258
|
+
} catch (err) {
|
|
259
|
+
return {
|
|
260
|
+
content: [{ type: "text", text: `Error: ${err.message}` }],
|
|
261
|
+
isError: true
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
);
|
|
266
|
+
server.tool(
|
|
267
|
+
"list_captures",
|
|
268
|
+
`Browse the TechTerrain Agent Showcase gallery.
|
|
269
|
+
Returns recent agent-generated screenshots and GIFs with metadata, captions, and CDN URLs.`,
|
|
270
|
+
{
|
|
271
|
+
type: z.enum(["screenshot", "gif", "render", "all"]).default("all").describe("Filter by capture type"),
|
|
272
|
+
featuredOnly: z.boolean().default(false).describe("Only return featured captures"),
|
|
273
|
+
limit: z.number().min(1).max(50).default(20).describe("Number of captures to return")
|
|
274
|
+
},
|
|
275
|
+
async (args) => {
|
|
276
|
+
try {
|
|
277
|
+
const result = await trpcQuery("agent.listCaptures", args);
|
|
278
|
+
return {
|
|
279
|
+
content: [{
|
|
280
|
+
type: "text",
|
|
281
|
+
text: JSON.stringify({
|
|
282
|
+
total: result.total,
|
|
283
|
+
captures: result.captures.map((c) => ({
|
|
284
|
+
id: c.id,
|
|
285
|
+
imageUrl: c.url,
|
|
286
|
+
type: c.captureType,
|
|
287
|
+
author: c.authorName,
|
|
288
|
+
caption: c.caption,
|
|
289
|
+
featured: c.featured
|
|
290
|
+
}))
|
|
291
|
+
}, null, 2)
|
|
292
|
+
}]
|
|
293
|
+
};
|
|
294
|
+
} catch (err) {
|
|
295
|
+
return {
|
|
296
|
+
content: [{ type: "text", text: `Error: ${err.message}` }],
|
|
297
|
+
isError: true
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
);
|
|
302
|
+
server.tool(
|
|
303
|
+
"get_insights",
|
|
304
|
+
`Get pre-computed Granger causality findings from TechTerrain's Insights Engine.
|
|
305
|
+
Returns statistically significant causal relationships between technology categories
|
|
306
|
+
and economic indicators, with human-readable narrations.
|
|
307
|
+
Free \u2014 no LLM cost (findings are pre-computed via batch analysis).`,
|
|
308
|
+
{
|
|
309
|
+
limit: z.number().min(1).max(50).default(10).describe("Number of findings to return")
|
|
310
|
+
},
|
|
311
|
+
async (args) => {
|
|
312
|
+
try {
|
|
313
|
+
const result = await trpcQuery("insights.getLatest", { limit: args.limit });
|
|
314
|
+
return {
|
|
315
|
+
content: [{
|
|
316
|
+
type: "text",
|
|
317
|
+
text: JSON.stringify(result, null, 2)
|
|
318
|
+
}]
|
|
319
|
+
};
|
|
320
|
+
} catch (err) {
|
|
321
|
+
return {
|
|
322
|
+
content: [{ type: "text", text: `Error: ${err.message}` }],
|
|
323
|
+
isError: true
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
);
|
|
328
|
+
async function main() {
|
|
329
|
+
const transport = new StdioServerTransport();
|
|
330
|
+
await server.connect(transport);
|
|
331
|
+
console.error("TechTerrain MCP server running on stdio");
|
|
332
|
+
}
|
|
333
|
+
main().catch((err) => {
|
|
334
|
+
console.error("Fatal error:", err);
|
|
335
|
+
process.exit(1);
|
|
336
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vampsieee/techterrain-mcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "MCP server for TechTerrain — explore 3.4 million years of technology history through AI agents",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"techterrain-mcp": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md",
|
|
13
|
+
"LICENSE",
|
|
14
|
+
"server.json"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "esbuild techterrain-mcp-server.ts --bundle --platform=node --format=esm --target=node18 --outfile=dist/index.js --banner:js='#!/usr/bin/env node' --packages=external",
|
|
18
|
+
"start": "node dist/index.js",
|
|
19
|
+
"dev": "npx tsx techterrain-mcp-server.ts",
|
|
20
|
+
"prepublishOnly": "npm run build"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"mcp",
|
|
24
|
+
"model-context-protocol",
|
|
25
|
+
"techterrain",
|
|
26
|
+
"data-visualization",
|
|
27
|
+
"technology-history",
|
|
28
|
+
"ai-agent",
|
|
29
|
+
"claude",
|
|
30
|
+
"timeline"
|
|
31
|
+
],
|
|
32
|
+
"author": "Romulus (https://techterrain.io)",
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "https://github.com/vampsieee/tech-terrain-voxel.git",
|
|
37
|
+
"directory": "mcp"
|
|
38
|
+
},
|
|
39
|
+
"homepage": "https://techterrain.io",
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">=18.0.0"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
45
|
+
"zod": "^4.1.12"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"esbuild": "^0.25.0",
|
|
49
|
+
"tsx": "^4.0.0",
|
|
50
|
+
"typescript": "^5.9.0"
|
|
51
|
+
}
|
|
52
|
+
}
|
package/server.json
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://registry.modelcontextprotocol.io/schemas/server.json",
|
|
3
|
+
"name": "techterrain",
|
|
4
|
+
"display_name": "TechTerrain",
|
|
5
|
+
"description": "Explore 3.4 million years of technology history through AI agents. Capture screenshots, generate GIFs, search topics, and analyze patterns across 1,200+ curated milestones in a 3D voxel timeline.",
|
|
6
|
+
"homepage": "https://techterrain.io",
|
|
7
|
+
"repository": "https://github.com/vampsieee/tech-terrain-voxel",
|
|
8
|
+
"icon": "https://techterrain.io/favicon.ico",
|
|
9
|
+
"category": "data-visualization",
|
|
10
|
+
"tags": [
|
|
11
|
+
"data-visualization",
|
|
12
|
+
"technology-history",
|
|
13
|
+
"timeline",
|
|
14
|
+
"3d",
|
|
15
|
+
"voxel",
|
|
16
|
+
"screenshot",
|
|
17
|
+
"gif",
|
|
18
|
+
"research",
|
|
19
|
+
"education"
|
|
20
|
+
],
|
|
21
|
+
"installations": {
|
|
22
|
+
"npm": {
|
|
23
|
+
"type": "npm",
|
|
24
|
+
"package_name": "@vampsieee/techterrain-mcp",
|
|
25
|
+
"command": "npx",
|
|
26
|
+
"args": ["-y", "@vampsieee/techterrain-mcp"]
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"tools": [
|
|
30
|
+
{
|
|
31
|
+
"name": "capture_screenshot",
|
|
32
|
+
"description": "Render a headless screenshot of TechTerrain via Cloudflare Browser Rendering. Returns a public CDN URL."
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"name": "capture_gif",
|
|
36
|
+
"description": "Generate an animated GIF (orbit or timelapse). Returns a jobId for async polling."
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"name": "get_gif_status",
|
|
40
|
+
"description": "Poll the status of an async GIF generation job."
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"name": "explore_topic",
|
|
44
|
+
"description": "Search any topic and get it mapped onto TechTerrain's timeline with structured milestone data."
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"name": "generate_insights",
|
|
48
|
+
"description": "LLM-powered pattern analysis of a TechTerrain scene descriptor."
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"name": "list_captures",
|
|
52
|
+
"description": "Browse the Agent Showcase gallery of agent-generated screenshots and GIFs."
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"name": "get_insights",
|
|
56
|
+
"description": "Get pre-computed Granger causality findings between technology categories and economic indicators."
|
|
57
|
+
}
|
|
58
|
+
],
|
|
59
|
+
"resources": [
|
|
60
|
+
{
|
|
61
|
+
"name": "docs",
|
|
62
|
+
"uri": "techterrain://docs",
|
|
63
|
+
"description": "Full Agent API documentation with code examples"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"name": "llms-txt",
|
|
67
|
+
"uri": "techterrain://llms.txt",
|
|
68
|
+
"description": "LLM-optimized concise API reference"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"name": "dataset",
|
|
72
|
+
"uri": "techterrain://dataset",
|
|
73
|
+
"description": "Raw milestone dataset — 1,200+ curated technology milestones across 7 categories"
|
|
74
|
+
}
|
|
75
|
+
]
|
|
76
|
+
}
|