@keeeeeeeks/cryptoloom-mcp-server 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/dist/index.d.ts +2 -0
- package/dist/index.js +90 -0
- package/dist/index.js.map +1 -0
- package/package.json +43 -0
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
const BASE_URL = process.env.CRYPTOLOOM_API_URL ?? "https://web-mu-silk.vercel.app";
|
|
6
|
+
async function api(path, options = {}) {
|
|
7
|
+
const url = `${BASE_URL}${path}`;
|
|
8
|
+
return fetch(url, {
|
|
9
|
+
...options,
|
|
10
|
+
headers: {
|
|
11
|
+
"Content-Type": "application/json",
|
|
12
|
+
...options.headers,
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
const server = new McpServer({
|
|
17
|
+
name: "cryptoloom",
|
|
18
|
+
version: "0.1.0",
|
|
19
|
+
});
|
|
20
|
+
server.tool("cryptoloom_list_works", "List all playable interactive fiction works on Cryptoloom with their IDs, formats, and prices", {}, async () => {
|
|
21
|
+
const res = await api("/api/works");
|
|
22
|
+
const data = await res.json();
|
|
23
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
24
|
+
});
|
|
25
|
+
server.tool("cryptoloom_get_work", "Get details for a specific work including description, format, pricing, and remix info", { workId: z.string().describe("Work ID (e.g., 'minutes', 'the-intake', 'dead-air')") }, async ({ workId }) => {
|
|
26
|
+
const res = await api(`/api/works/${workId}`);
|
|
27
|
+
if (!res.ok)
|
|
28
|
+
return { content: [{ type: "text", text: `Error: ${res.status} — work not found` }] };
|
|
29
|
+
const data = await res.json();
|
|
30
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
31
|
+
});
|
|
32
|
+
server.tool("cryptoloom_start_game", "Start a new game session for a work. Returns the opening text and either choices (Ink) or a sessionId (Glulx parser)", { workId: z.string().describe("Work ID to play") }, async ({ workId }) => {
|
|
33
|
+
const res = await api(`/api/works/${workId}/play`, { method: "POST" });
|
|
34
|
+
if (!res.ok) {
|
|
35
|
+
const err = await res.json();
|
|
36
|
+
return { content: [{ type: "text", text: `Error: ${err.error}` }] };
|
|
37
|
+
}
|
|
38
|
+
const data = await res.json();
|
|
39
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
40
|
+
});
|
|
41
|
+
server.tool("cryptoloom_make_choice", "Make a choice in an Ink (choice-based) game. Provide the state from the previous response and the choice index.", {
|
|
42
|
+
workId: z.string().describe("Work ID"),
|
|
43
|
+
state: z.string().describe("Serialized game state from the previous response"),
|
|
44
|
+
choiceIndex: z.number().int().min(0).describe("Index of the choice to make (0-based)"),
|
|
45
|
+
}, async ({ workId, state, choiceIndex }) => {
|
|
46
|
+
const res = await api(`/api/works/${workId}/play/choice`, {
|
|
47
|
+
method: "POST",
|
|
48
|
+
body: JSON.stringify({ state, choiceIndex }),
|
|
49
|
+
});
|
|
50
|
+
if (!res.ok) {
|
|
51
|
+
const err = await res.json();
|
|
52
|
+
return { content: [{ type: "text", text: `Error: ${err.error}` }] };
|
|
53
|
+
}
|
|
54
|
+
const data = await res.json();
|
|
55
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
56
|
+
});
|
|
57
|
+
server.tool("cryptoloom_send_command", "Send a text command to a Glulx (parser-based) game. Provide the sessionId from the start response.", {
|
|
58
|
+
workId: z.string().describe("Work ID"),
|
|
59
|
+
sessionId: z.string().describe("Session ID from the start_game response"),
|
|
60
|
+
command: z.string().max(256).describe("Parser command (e.g., 'look', 'go north', 'take key')"),
|
|
61
|
+
}, async ({ workId, sessionId, command }) => {
|
|
62
|
+
const res = await api(`/api/works/${workId}/play/command`, {
|
|
63
|
+
method: "POST",
|
|
64
|
+
body: JSON.stringify({ sessionId, command }),
|
|
65
|
+
});
|
|
66
|
+
if (!res.ok) {
|
|
67
|
+
const err = await res.json();
|
|
68
|
+
return { content: [{ type: "text", text: `Error: ${err.error}` }] };
|
|
69
|
+
}
|
|
70
|
+
const data = await res.json();
|
|
71
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
72
|
+
});
|
|
73
|
+
server.tool("cryptoloom_get_remix_contract", "Get the remix contract for a work — required variables, forbidden spoilers, and split configuration", { workId: z.string().describe("Work ID") }, async ({ workId }) => {
|
|
74
|
+
const res = await api(`/api/works/${workId}/remix`, { method: "POST" });
|
|
75
|
+
if (!res.ok) {
|
|
76
|
+
const err = await res.json();
|
|
77
|
+
return { content: [{ type: "text", text: `Error: ${err.error}` }] };
|
|
78
|
+
}
|
|
79
|
+
const data = await res.json();
|
|
80
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
81
|
+
});
|
|
82
|
+
async function main() {
|
|
83
|
+
const transport = new StdioServerTransport();
|
|
84
|
+
await server.connect(transport);
|
|
85
|
+
}
|
|
86
|
+
main().catch((err) => {
|
|
87
|
+
console.error("MCP server failed:", err);
|
|
88
|
+
process.exit(1);
|
|
89
|
+
});
|
|
90
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@keeeeeeeks/cryptoloom-mcp-server",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server for Cryptoloom interactive fiction platform — enables AI agents to discover, play, and verify text-based games",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"cryptoloom-mcp": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"keywords": [
|
|
14
|
+
"mcp",
|
|
15
|
+
"interactive-fiction",
|
|
16
|
+
"cryptoloom",
|
|
17
|
+
"agent",
|
|
18
|
+
"text-game",
|
|
19
|
+
"glulx",
|
|
20
|
+
"ink"
|
|
21
|
+
],
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "https://github.com/Resoworks/cryptoloom.git",
|
|
25
|
+
"directory": "mcp-server"
|
|
26
|
+
},
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public"
|
|
30
|
+
},
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "tsc",
|
|
33
|
+
"start": "node dist/index.js",
|
|
34
|
+
"prepublishOnly": "npm run build"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@modelcontextprotocol/sdk": "^1.12.1"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/node": "^25.5.0",
|
|
41
|
+
"typescript": "^5"
|
|
42
|
+
}
|
|
43
|
+
}
|