yorck-mcp 0.1.3 → 0.1.5
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/package.json +11 -2
- package/src/cli.ts +15 -1
- package/src/index.ts +14 -1
- package/src/landing.ts +5 -3
- package/src/skill-content.ts +97 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yorck-mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -38,5 +38,14 @@
|
|
|
38
38
|
"bin",
|
|
39
39
|
"src",
|
|
40
40
|
"README.md"
|
|
41
|
-
]
|
|
41
|
+
],
|
|
42
|
+
"repository": {
|
|
43
|
+
"type": "git",
|
|
44
|
+
"url": "git+https://github.com/Mahir-Isikli/yorck-mcp.git"
|
|
45
|
+
},
|
|
46
|
+
"homepage": "https://yorck-mcp.isiklimahir.workers.dev",
|
|
47
|
+
"bugs": {
|
|
48
|
+
"url": "https://github.com/Mahir-Isikli/yorck-mcp/issues"
|
|
49
|
+
},
|
|
50
|
+
"license": "MIT"
|
|
42
51
|
}
|
package/src/cli.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { findSeatByRowAndId, getSeatPlan, renderSeatPlanHtml, renderSeatPlanSvg
|
|
|
9
9
|
import { cancelOrder, commitOrder, reserveUnlimited } from "./yorck/booking.ts";
|
|
10
10
|
import { showtimeToIcs } from "./lib/ics.ts";
|
|
11
11
|
import { whoAmI } from "./yorck/auth.ts";
|
|
12
|
-
import { YORCK_MOVIE_AGENT_SKILL } from "./skill-content.ts";
|
|
12
|
+
import { CLAUDE_CODE_BOOTSTRAP_PROMPT, YORCK_MOVIE_AGENT_SKILL } from "./skill-content.ts";
|
|
13
13
|
|
|
14
14
|
const PUBLIC_MCP_URL = "https://yorck-mcp.isiklimahir.workers.dev/public/mcp";
|
|
15
15
|
|
|
@@ -450,6 +450,16 @@ async function commandSkill(args: ParsedArgs) {
|
|
|
450
450
|
}
|
|
451
451
|
}
|
|
452
452
|
|
|
453
|
+
async function commandClaudeCodePrompt(args: ParsedArgs) {
|
|
454
|
+
const out = str(args, "out");
|
|
455
|
+
if (out) {
|
|
456
|
+
await writeFile(out, CLAUDE_CODE_BOOTSTRAP_PROMPT, "utf8");
|
|
457
|
+
console.log(`Wrote ${out}`);
|
|
458
|
+
} else {
|
|
459
|
+
process.stdout.write(CLAUDE_CODE_BOOTSTRAP_PROMPT);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
453
463
|
async function commandInstallSkill(args: ParsedArgs) {
|
|
454
464
|
const target = (str(args, "target") || "claude").toLowerCase();
|
|
455
465
|
const home = process.env.HOME || process.cwd();
|
|
@@ -525,6 +535,7 @@ Usage:
|
|
|
525
535
|
yorck mcp-stdio
|
|
526
536
|
yorck mcp-config [--private]
|
|
527
537
|
yorck skill [--out SKILL.md]
|
|
538
|
+
yorck claude-code-prompt [--out prompt.md]
|
|
528
539
|
yorck install-skill [--target claude|pi|both]
|
|
529
540
|
|
|
530
541
|
Public commands need no account. Booking commands need Yorck credentials and an Unlimited card number.
|
|
@@ -573,6 +584,9 @@ async function main() {
|
|
|
573
584
|
return commandMcpConfig(args);
|
|
574
585
|
case "skill":
|
|
575
586
|
return commandSkill(args);
|
|
587
|
+
case "claude-code-prompt":
|
|
588
|
+
case "bootstrap-prompt":
|
|
589
|
+
return commandClaudeCodePrompt(args);
|
|
576
590
|
case "install-skill":
|
|
577
591
|
return commandInstallSkill(args);
|
|
578
592
|
case "mcp-stdio":
|
package/src/index.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { reserveUnlimited, cancelOrder, getOrder } from "./yorck/booking.ts";
|
|
|
7
7
|
import { whoAmI } from "./yorck/auth.ts";
|
|
8
8
|
import { showtimeToIcs } from "./lib/ics.ts";
|
|
9
9
|
import { PublicYorckMcp, YorckMcp } from "./mcp.ts";
|
|
10
|
-
import { installScript, YORCK_MOVIE_AGENT_SKILL } from "./skill-content.ts";
|
|
10
|
+
import { CLAUDE_CODE_BOOTSTRAP_PROMPT, installScript, skillZip, YORCK_MOVIE_AGENT_SKILL } from "./skill-content.ts";
|
|
11
11
|
import { landingPage } from "./landing.ts";
|
|
12
12
|
|
|
13
13
|
export { PublicYorckMcp, YorckMcp };
|
|
@@ -42,6 +42,19 @@ app.get("/skill/SKILL.md", (c) => c.text(YORCK_MOVIE_AGENT_SKILL, 200, { "Conten
|
|
|
42
42
|
|
|
43
43
|
app.get("/install.sh", (c) => c.text(installScript("https://yorck-mcp.isiklimahir.workers.dev"), 200, { "Content-Type": "text/x-shellscript; charset=utf-8" }));
|
|
44
44
|
|
|
45
|
+
app.get("/claude-code-prompt.md", (c) => c.text(CLAUDE_CODE_BOOTSTRAP_PROMPT, 200, { "Content-Type": "text/markdown; charset=utf-8" }));
|
|
46
|
+
|
|
47
|
+
app.get("/skill.zip", () => {
|
|
48
|
+
const zip = skillZip();
|
|
49
|
+
const body = zip.buffer.slice(zip.byteOffset, zip.byteOffset + zip.byteLength) as ArrayBuffer;
|
|
50
|
+
return new Response(body, {
|
|
51
|
+
headers: {
|
|
52
|
+
"Content-Type": "application/zip",
|
|
53
|
+
"Content-Disposition": "attachment; filename=yorck-movie-agent-skill.zip",
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
45
58
|
// REST endpoints (also handy for quick curl tests)
|
|
46
59
|
app.get("/v1/films", async (c) => {
|
|
47
60
|
const q = c.req.query();
|
package/src/landing.ts
CHANGED
|
@@ -14,7 +14,7 @@ export function landingPage(): string {
|
|
|
14
14
|
</head>
|
|
15
15
|
<body>
|
|
16
16
|
<main>
|
|
17
|
-
<nav class="nav"><div class="brand">yorck-mcp</div><div class="links"><a class="pill" href="/public/mcp">public MCP</a><a class="pill" href="/skill/SKILL.md">SKILL.md</a><a class="pill" href="/
|
|
17
|
+
<nav class="nav"><div class="brand">yorck-mcp</div><div class="links"><a class="pill" href="/public/mcp">public MCP</a><a class="pill" href="/claude-code-prompt.md">Claude Code prompt</a><a class="pill" href="/skill/SKILL.md">SKILL.md</a><a class="pill" href="/skill.zip">skill.zip</a><a class="pill" href="https://github.com/Mahir-Isikli/yorck-mcp">GitHub</a><a class="pill" href="https://www.npmjs.com/package/yorck-mcp">npm</a></div></nav>
|
|
18
18
|
<section class="hero">
|
|
19
19
|
<div>
|
|
20
20
|
<div class="eyebrow">Berlin cinema for agents</div>
|
|
@@ -41,6 +41,7 @@ export function landingPage(): string {
|
|
|
41
41
|
<div class="install-grid">
|
|
42
42
|
<div class="tabs">
|
|
43
43
|
<button class="tab active" data-tab="claude-web">Claude Web connector</button>
|
|
44
|
+
<button class="tab" data-tab="claude-code-prompt">Claude Code prompt</button>
|
|
44
45
|
<button class="tab" data-tab="claude-code-public">Claude Code public</button>
|
|
45
46
|
<button class="tab" data-tab="claude-code-private">Claude Code private</button>
|
|
46
47
|
<button class="tab" data-tab="skill">Claude skill</button>
|
|
@@ -48,14 +49,15 @@ export function landingPage(): string {
|
|
|
48
49
|
<button class="tab" data-tab="html">Inline HTML fallback</button>
|
|
49
50
|
</div>
|
|
50
51
|
<div>
|
|
51
|
-
<div class="panel active" id="claude-web"><h3>Claude Web / custom connector</h3><p>Customize → Connectors → Add custom connector, then paste:</p><pre class="screen"><button class="copy">copy</button>https://yorck-mcp.isiklimahir.workers.dev/public/mcp</pre></div>
|
|
52
|
+
<div class="panel active" id="claude-web"><h3>Claude Web / custom connector</h3><p>Customize → Connectors → Add custom connector, then paste:</p><pre class="screen"><button class="copy">copy</button>https://yorck-mcp.isiklimahir.workers.dev/public/mcp</pre><p>Then upload the skill ZIP from <a href="/skill.zip">/skill.zip</a> under Customize → Skills.</p></div>
|
|
53
|
+
<div class="panel" id="claude-code-prompt"><h3>Claude Code bootstrap prompt</h3><p>Paste this into Claude Code and let it install the repo, npm package, skill, and MCP config for you.</p><pre class="screen"><button class="copy">copy</button>curl -fsSL https://yorck-mcp.isiklimahir.workers.dev/claude-code-prompt.md</pre><p>Or open <a href="/claude-code-prompt.md">the prompt</a> and copy it.</p></div>
|
|
52
54
|
<div class="panel" id="claude-code-public"><h3>Claude Code, public tools</h3><pre class="screen"><button class="copy">copy</button>claude mcp add --transport http yorck https://yorck-mcp.isiklimahir.workers.dev/public/mcp</pre></div>
|
|
53
55
|
<div class="panel" id="claude-code-private"><h3>Claude Code, local bookable MCP</h3><pre class="screen"><button class="copy">copy</button>claude mcp add --transport stdio \\
|
|
54
56
|
--env YORCK_EMAIL=you@example.com \\
|
|
55
57
|
--env YORCK_PASSWORD=your-password \\
|
|
56
58
|
--env YORCK_UNLIMITED_CARD=your-card-number \\
|
|
57
59
|
yorck -- npx -y yorck-mcp mcp-stdio</pre></div>
|
|
58
|
-
<div class="panel" id="skill"><h3>Install the skill file</h3><pre class="screen"><button class="copy">copy</button>curl -fsSL https://yorck-mcp.isiklimahir.workers.dev/install.sh | bash</pre><p>Or from npm:</p><pre class="screen"><button class="copy">copy</button>npx -y yorck-mcp install-skill --target claude</pre></div>
|
|
60
|
+
<div class="panel" id="skill"><h3>Install the skill file</h3><p>Claude Web skills can upload the ZIP. Claude Code can install the filesystem skill.</p><pre class="screen"><button class="copy">copy</button>https://yorck-mcp.isiklimahir.workers.dev/skill.zip</pre><pre class="screen"><button class="copy">copy</button>curl -fsSL https://yorck-mcp.isiklimahir.workers.dev/install.sh | bash</pre><p>Or from npm:</p><pre class="screen"><button class="copy">copy</button>npx -y yorck-mcp install-skill --target claude</pre></div>
|
|
59
61
|
<div class="panel" id="cli"><h3>Use it directly</h3><pre class="screen"><button class="copy">copy</button>npx -y yorck-mcp whats-on --when tonight --after 18:00
|
|
60
62
|
npx -y yorck-mcp plan --q "devil wears prada" --when tonight
|
|
61
63
|
npx -y yorck-mcp seat-map 1007-30456 --out seat-map.svg</pre></div>
|
package/src/skill-content.ts
CHANGED
|
@@ -118,6 +118,103 @@ Private/local mode can book with credentials. It currently supports Yorck Unlimi
|
|
|
118
118
|
- "book the best option if my Unlimited card makes it free"
|
|
119
119
|
`;
|
|
120
120
|
|
|
121
|
+
function crc32(bytes: Uint8Array): number {
|
|
122
|
+
let crc = 0xffffffff;
|
|
123
|
+
for (const byte of bytes) {
|
|
124
|
+
crc ^= byte;
|
|
125
|
+
for (let i = 0; i < 8; i++) crc = (crc >>> 1) ^ (0xedb88320 & -(crc & 1));
|
|
126
|
+
}
|
|
127
|
+
return (crc ^ 0xffffffff) >>> 0;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function u16(n: number) { return [n & 255, (n >>> 8) & 255]; }
|
|
131
|
+
function u32(n: number) { return [n & 255, (n >>> 8) & 255, (n >>> 16) & 255, (n >>> 24) & 255]; }
|
|
132
|
+
|
|
133
|
+
export function skillZip(): Uint8Array {
|
|
134
|
+
const encoder = new TextEncoder();
|
|
135
|
+
const filename = encoder.encode("yorck-movie-agent/SKILL.md");
|
|
136
|
+
const content = encoder.encode(YORCK_MOVIE_AGENT_SKILL);
|
|
137
|
+
const crc = crc32(content);
|
|
138
|
+
const localHeader = new Uint8Array([
|
|
139
|
+
...u32(0x04034b50), ...u16(20), ...u16(0), ...u16(0), ...u16(0), ...u16(0),
|
|
140
|
+
...u32(crc), ...u32(content.length), ...u32(content.length), ...u16(filename.length), ...u16(0),
|
|
141
|
+
]);
|
|
142
|
+
const centralOffset = localHeader.length + filename.length + content.length;
|
|
143
|
+
const centralHeader = new Uint8Array([
|
|
144
|
+
...u32(0x02014b50), ...u16(20), ...u16(20), ...u16(0), ...u16(0), ...u16(0), ...u16(0),
|
|
145
|
+
...u32(crc), ...u32(content.length), ...u32(content.length), ...u16(filename.length), ...u16(0), ...u16(0), ...u16(0), ...u16(0), ...u32(0), ...u32(0),
|
|
146
|
+
]);
|
|
147
|
+
const centralSize = centralHeader.length + filename.length;
|
|
148
|
+
const end = new Uint8Array([
|
|
149
|
+
...u32(0x06054b50), ...u16(0), ...u16(0), ...u16(1), ...u16(1), ...u32(centralSize), ...u32(centralOffset), ...u16(0),
|
|
150
|
+
]);
|
|
151
|
+
const out = new Uint8Array(localHeader.length + filename.length + content.length + centralHeader.length + filename.length + end.length);
|
|
152
|
+
let o = 0;
|
|
153
|
+
for (const part of [localHeader, filename, content, centralHeader, filename, end]) { out.set(part, o); o += part.length; }
|
|
154
|
+
return out;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export const CLAUDE_CODE_BOOTSTRAP_PROMPT = `# Install the Yorck Movie Agent in Claude Code
|
|
158
|
+
|
|
159
|
+
You are helping me install the Yorck Movie Agent from the public repo and npm package.
|
|
160
|
+
|
|
161
|
+
Public repo:
|
|
162
|
+
|
|
163
|
+
https://github.com/Mahir-Isikli/yorck-mcp
|
|
164
|
+
|
|
165
|
+
Install page:
|
|
166
|
+
|
|
167
|
+
https://yorck-mcp.isiklimahir.workers.dev
|
|
168
|
+
|
|
169
|
+
NPM package:
|
|
170
|
+
|
|
171
|
+
\`\`\`bash
|
|
172
|
+
npx -y yorck-mcp@latest
|
|
173
|
+
\`\`\`
|
|
174
|
+
|
|
175
|
+
Please do the following:
|
|
176
|
+
|
|
177
|
+
1. Read the public repo README or install page so you understand the package.
|
|
178
|
+
2. Install the Claude Code skill locally:
|
|
179
|
+
|
|
180
|
+
\`\`\`bash
|
|
181
|
+
npx -y yorck-mcp@latest install-skill --target claude
|
|
182
|
+
\`\`\`
|
|
183
|
+
|
|
184
|
+
3. Add the public read-only MCP server to Claude Code:
|
|
185
|
+
|
|
186
|
+
\`\`\`bash
|
|
187
|
+
claude mcp add --transport http yorck https://yorck-mcp.isiklimahir.workers.dev/public/mcp
|
|
188
|
+
\`\`\`
|
|
189
|
+
|
|
190
|
+
4. Smoke-test the CLI:
|
|
191
|
+
|
|
192
|
+
\`\`\`bash
|
|
193
|
+
npx -y yorck-mcp@latest whats-on --when tonight --after 18:00 --limit 3
|
|
194
|
+
\`\`\`
|
|
195
|
+
|
|
196
|
+
5. If I ask for a seat map and SVG/image output does not render in this environment, use the HTML fallback:
|
|
197
|
+
|
|
198
|
+
\`\`\`bash
|
|
199
|
+
npx -y yorck-mcp@latest seat-map-html <session-id> --out seat-map.html
|
|
200
|
+
open seat-map.html
|
|
201
|
+
\`\`\`
|
|
202
|
+
|
|
203
|
+
6. If I want private automated booking, do not collect secrets into chat. Instead explain that I should configure the local MCP with environment variables:
|
|
204
|
+
|
|
205
|
+
\`\`\`bash
|
|
206
|
+
claude mcp add --transport stdio \\
|
|
207
|
+
--env YORCK_EMAIL=you@example.com \\
|
|
208
|
+
--env YORCK_PASSWORD=your-password \\
|
|
209
|
+
--env YORCK_UNLIMITED_CARD=your-card-number \\
|
|
210
|
+
yorck-private -- npx -y yorck-mcp@latest mcp-stdio
|
|
211
|
+
\`\`\`
|
|
212
|
+
|
|
213
|
+
7. Never claim a ticket was booked or a calendar event was created unless a tool actually succeeded. Booking must require explicit confirmation.
|
|
214
|
+
|
|
215
|
+
After installing, tell me exactly what you changed and how to test it with one prompt like: "find original-language Yorck movies tonight after 7 and show me the best seat map".
|
|
216
|
+
`;
|
|
217
|
+
|
|
121
218
|
export function installScript(baseUrl = "https://yorck-mcp.isiklimahir.workers.dev") {
|
|
122
219
|
return `#!/usr/bin/env bash
|
|
123
220
|
set -euo pipefail
|