irlevents-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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 IRLEvents
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,172 @@
1
+ # irlevents-mcp
2
+
3
+ Model Context Protocol server for [IRLEvents](https://irlevents.io) — the
4
+ token-gated event platform for the on-chain world.
5
+
6
+ Plugs IRLEvents into **Claude Desktop**, **Claude Code**, **Cursor**, **Cline**,
7
+ and any other MCP-compatible client. Once configured, the model can list events,
8
+ check whether you qualify for a token gate, RSVP, sync your on-chain assets,
9
+ and more — all on your behalf, using a long-lived `api_*` key you control.
10
+
11
+ ## Tools exposed
12
+
13
+ | Tool | What it does |
14
+ |---|---|
15
+ | `list_events` | List public events with filters (category, city, chainId, date range) |
16
+ | `trending_events` | Most RSVPed events in the last 14 days |
17
+ | `get_event` | Single event by short id (title, dates, location, gates) |
18
+ | `top_creators` | Leaderboard of top creators |
19
+ | `platform_stats` | Cached platform-wide counts |
20
+ | `get_my_profile` | Read your own profile, wallets, cached assets |
21
+ | `sync_my_assets` | Force-refresh NFT/token holdings across chains (slow, don't poll) |
22
+ | `check_eligibility` | Will I pass this event's token gate? |
23
+ | `rsvp_status` | My RSVP state for this event |
24
+ | `rsvp_event` | RSVP on my behalf (locks the qualifying token) |
25
+ | `cancel_rsvp` | Cancel my RSVP, free the locked token |
26
+ | `my_eligible_events` | Every public event a wallet currently qualifies for |
27
+
28
+ Sensitive actions (key management, billing, 2FA, OAuth unlink, account delete)
29
+ are **not** exposed — those still require a browser session at irlevents.io.
30
+
31
+ ## Setup
32
+
33
+ ### 1. Mint an API key
34
+
35
+ Sign in at https://irlevents.io, open **Profile → API Keys**, click **Create
36
+ key**, and copy the `api_<64 hex>` value. It's only shown once.
37
+
38
+ ### 2. Add to your MCP client config
39
+
40
+ #### Claude Desktop (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS, `%APPDATA%\Claude\claude_desktop_config.json` on Windows)
41
+
42
+ ```json
43
+ {
44
+ "mcpServers": {
45
+ "irlevents": {
46
+ "command": "npx",
47
+ "args": ["-y", "irlevents-mcp"],
48
+ "env": {
49
+ "IRLEVENTS_API_KEY": "api_your_key_here"
50
+ }
51
+ }
52
+ }
53
+ }
54
+ ```
55
+
56
+ Restart Claude Desktop. The IRLEvents tools will appear in the tools panel.
57
+
58
+ #### Claude Code (project-scoped, `.mcp.json` at the repo root)
59
+
60
+ ```json
61
+ {
62
+ "mcpServers": {
63
+ "irlevents": {
64
+ "command": "npx",
65
+ "args": ["-y", "irlevents-mcp"],
66
+ "env": { "IRLEVENTS_API_KEY": "api_your_key_here" }
67
+ }
68
+ }
69
+ }
70
+ ```
71
+
72
+ Or via CLI: `claude mcp add irlevents npx -y irlevents-mcp -e IRLEVENTS_API_KEY=api_...`
73
+
74
+ #### Cursor (`~/.cursor/mcp.json`)
75
+
76
+ ```json
77
+ {
78
+ "mcpServers": {
79
+ "irlevents": {
80
+ "command": "npx",
81
+ "args": ["-y", "irlevents-mcp"],
82
+ "env": { "IRLEVENTS_API_KEY": "api_your_key_here" }
83
+ }
84
+ }
85
+ }
86
+ ```
87
+
88
+ #### Cline (VS Code MCP settings)
89
+
90
+ Same config shape — add under `cline.mcpServers`.
91
+
92
+ ### 3. Try it
93
+
94
+ Ask the model:
95
+
96
+ - *"What events are trending on IRLEvents right now?"*
97
+ - *"List events in Las Vegas this month."*
98
+ - *"Check if I'm eligible for event 7s5TZhMQqrCs."*
99
+ - *"RSVP me to that event if I qualify."*
100
+
101
+ ## Configuration
102
+
103
+ | Env var | Default | Purpose |
104
+ |---|---|---|
105
+ | `IRLEVENTS_API_KEY` | *(required)* | Your `api_*` key |
106
+ | `IRLEVENTS_API_BASE` | `https://irlevents.io` | Override for staging or self-hosted |
107
+
108
+ ## Local development
109
+
110
+ ```bash
111
+ git clone <this repo>
112
+ cd irlevents-mcp
113
+ npm install
114
+ npm run build
115
+ IRLEVENTS_API_KEY=api_... node dist/index.js
116
+ ```
117
+
118
+ To smoke-test the wire format without a live MCP client:
119
+
120
+ ```bash
121
+ printf '%s\n%s\n%s\n' \
122
+ '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"test","version":"0.0.1"}}}' \
123
+ '{"jsonrpc":"2.0","method":"notifications/initialized"}' \
124
+ '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' \
125
+ | IRLEVENTS_API_KEY=api_... node dist/index.js
126
+ ```
127
+
128
+ ## Etiquette
129
+
130
+ - **Don't poll `sync_my_assets`.** It hits external NFT providers (Alchemy,
131
+ Helius, Hiro). Once per session is plenty.
132
+ - **Always `check_eligibility` before `rsvp_event`.** The API rejects ineligible
133
+ users with 403 — you'll waste a tool call otherwise.
134
+ - **Respect rate limits.** Each api key gets 1000 req/hr by default. The IRLEvents
135
+ API returns `X-RateLimit-Remaining` headers; this MCP server surfaces 429
136
+ errors back to the model so it can back off.
137
+
138
+ ## See also
139
+
140
+ - [IRLEvents agent guide](https://irlevents.io/api/guides/agent-guide)
141
+ - [Full agent docs (one-shot LLM ingest)](https://irlevents.io/llms-full.txt)
142
+ - [OpenAPI spec](https://irlevents.io/api/openapi.json)
143
+ - [Webhook integration guide](https://irlevents.io/api/guides/webhook-guide) — push instead of pull
144
+
145
+ ## Releasing (maintainers)
146
+
147
+ CI auto-publishes to npm when a `v*.*.*` tag is pushed. Steps:
148
+
149
+ ```bash
150
+ # 1. Bump version in package.json (e.g. 0.1.0 → 0.1.1)
151
+ # 2. Commit
152
+ git commit -am "Release v0.1.1"
153
+
154
+ # 3. Tag and push
155
+ git tag v0.1.1
156
+ git push && git push --tags
157
+ ```
158
+
159
+ The GitHub Actions workflow (`.github/workflows/publish.yml`) will:
160
+
161
+ 1. Verify the tag matches `package.json` version
162
+ 2. Build with `tsc`
163
+ 3. Smoke-test the MCP handshake (asserts all 12 tools register)
164
+ 4. Publish to npm with provenance attestation
165
+
166
+ Required GitHub repo secret: **`NPM_TOKEN`** — an npm "Automation" or
167
+ "Publish" token. Generate at <https://www.npmjs.com/settings/_/tokens>,
168
+ then add at *Settings → Secrets and variables → Actions*.
169
+
170
+ ## License
171
+
172
+ MIT
package/dist/client.js ADDED
@@ -0,0 +1,68 @@
1
+ // Thin fetch wrapper around the IRLEvents API.
2
+ // Used by every tool handler in src/index.ts. Centralizes auth, base URL,
3
+ // and error shape normalization so individual tools stay one-liners.
4
+ const DEFAULT_BASE = "https://irlevents.io";
5
+ export class IRLApiError extends Error {
6
+ status;
7
+ code;
8
+ body;
9
+ constructor(status, code, message, body) {
10
+ super(message);
11
+ this.status = status;
12
+ this.code = code;
13
+ this.body = body;
14
+ this.name = "IRLApiError";
15
+ }
16
+ }
17
+ export function createClient(opts) {
18
+ const base = (opts.base ?? DEFAULT_BASE).replace(/\/+$/, "");
19
+ if (!opts.apiKey) {
20
+ throw new Error("IRLEVENTS_API_KEY is required");
21
+ }
22
+ if (!opts.apiKey.startsWith("api_")) {
23
+ throw new Error('IRLEVENTS_API_KEY must start with "api_"');
24
+ }
25
+ async function request(path, init = {}) {
26
+ const url = new URL(base + (path.startsWith("/") ? path : "/" + path));
27
+ const { query, ...rest } = init;
28
+ if (query) {
29
+ for (const [k, v] of Object.entries(query)) {
30
+ if (v !== undefined && v !== null && v !== "")
31
+ url.searchParams.set(k, String(v));
32
+ }
33
+ }
34
+ const headers = new Headers(rest.headers);
35
+ headers.set("Authorization", `Bearer ${opts.apiKey}`);
36
+ headers.set("Accept", "application/json");
37
+ if (rest.body && !headers.has("Content-Type")) {
38
+ headers.set("Content-Type", "application/json");
39
+ }
40
+ headers.set("User-Agent", "irlevents-mcp/0.1.0");
41
+ const res = await fetch(url, { ...rest, headers });
42
+ const text = await res.text();
43
+ let parsed = text;
44
+ if (text && (res.headers.get("content-type") || "").includes("json")) {
45
+ try {
46
+ parsed = JSON.parse(text);
47
+ }
48
+ catch {
49
+ // leave as text
50
+ }
51
+ }
52
+ if (!res.ok) {
53
+ const body = parsed;
54
+ const code = typeof body === "object" && body !== null
55
+ ? body.code ?? body.error ?? null
56
+ : null;
57
+ const msg = (typeof body === "object" && body !== null
58
+ ? body.message
59
+ : undefined) ??
60
+ (typeof body === "string" ? body : null) ??
61
+ `HTTP ${res.status}`;
62
+ throw new IRLApiError(res.status, code, msg, parsed);
63
+ }
64
+ return parsed;
65
+ }
66
+ return { base, request };
67
+ }
68
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,204 @@
1
+ #!/usr/bin/env node
2
+ // IRLEvents MCP Server
3
+ //
4
+ // Exposes the IRLEvents agent-callable API as Model Context Protocol tools so
5
+ // Claude Desktop, Claude Code, Cursor, Cline, and other MCP-compatible clients
6
+ // can read and act on a user's behalf with their api_* key.
7
+ //
8
+ // Configure in claude_desktop_config.json:
9
+ // {
10
+ // "mcpServers": {
11
+ // "irlevents": {
12
+ // "command": "npx",
13
+ // "args": ["-y", "irlevents-mcp"],
14
+ // "env": { "IRLEVENTS_API_KEY": "api_..." }
15
+ // }
16
+ // }
17
+ // }
18
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
19
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
20
+ import { z } from "zod";
21
+ import { createClient, IRLApiError } from "./client.js";
22
+ const apiKey = process.env.IRLEVENTS_API_KEY;
23
+ if (!apiKey) {
24
+ console.error("irlevents-mcp: IRLEVENTS_API_KEY env var is required.\n" +
25
+ "Mint a key at https://irlevents.io/profile (API Keys tab) and pass it as:\n" +
26
+ ' { "env": { "IRLEVENTS_API_KEY": "api_..." } }\n' +
27
+ "in your MCP client config.");
28
+ process.exit(1);
29
+ }
30
+ const client = createClient({
31
+ apiKey,
32
+ base: process.env.IRLEVENTS_API_BASE,
33
+ });
34
+ const server = new McpServer({ name: "irlevents-mcp", version: "0.1.0" }, {
35
+ capabilities: { tools: {} },
36
+ instructions: "Tools for the IRLEvents token-gated event platform. Use list_events / " +
37
+ "trending_events / get_event to discover; check_eligibility before any " +
38
+ "rsvp_event call (the API will reject ineligible users). Use sync_my_assets " +
39
+ "sparingly — it hits external NFT providers and is slow.",
40
+ });
41
+ // ----- Helpers ----------------------------------------------------------
42
+ function ok(data) {
43
+ return {
44
+ content: [
45
+ {
46
+ type: "text",
47
+ text: typeof data === "string" ? data : JSON.stringify(data, null, 2),
48
+ },
49
+ ],
50
+ };
51
+ }
52
+ function err(e) {
53
+ if (e instanceof IRLApiError) {
54
+ return {
55
+ isError: true,
56
+ content: [
57
+ {
58
+ type: "text",
59
+ text: `IRLEvents API error ${e.status}${e.code ? ` (${e.code})` : ""}: ${e.message}`,
60
+ },
61
+ ],
62
+ };
63
+ }
64
+ const msg = e instanceof Error ? e.message : String(e);
65
+ return {
66
+ isError: true,
67
+ content: [{ type: "text", text: `Error: ${msg}` }],
68
+ };
69
+ }
70
+ async function handle(fn) {
71
+ try {
72
+ return ok(await fn());
73
+ }
74
+ catch (e) {
75
+ return err(e);
76
+ }
77
+ }
78
+ // ----- Discovery tools (no user-context needed) -------------------------
79
+ server.registerTool("list_events", {
80
+ title: "List events",
81
+ description: "List public IRLEvents events. Filter by category, city, chain, or date range. " +
82
+ "Returns a paginated list of event summaries.",
83
+ inputSchema: {
84
+ category: z.string().optional().describe("e.g. 'conference', 'meetup', 'workshop'"),
85
+ city: z.string().optional().describe("City name, e.g. 'Las Vegas'"),
86
+ chainId: z.number().int().optional().describe("EVM chain id, e.g. 1, 137, 8453"),
87
+ from: z.string().optional().describe("ISO 8601 date — events starting on/after this"),
88
+ to: z.string().optional().describe("ISO 8601 date — events starting on/before this"),
89
+ limit: z.number().int().min(1).max(100).optional().default(20),
90
+ offset: z.number().int().min(0).optional().default(0),
91
+ },
92
+ annotations: { readOnlyHint: true, openWorldHint: true },
93
+ }, async (args) => handle(() => client.request("/api/events", { query: args })));
94
+ server.registerTool("trending_events", {
95
+ title: "Trending events",
96
+ description: "Most RSVPed events in the last 14 days. Fast, public, cached. Good first call " +
97
+ "to surface what's happening right now.",
98
+ inputSchema: {},
99
+ annotations: { readOnlyHint: true, openWorldHint: true },
100
+ }, async () => handle(() => client.request("/api/events/trending")));
101
+ server.registerTool("get_event", {
102
+ title: "Get event details",
103
+ description: "Fetch a single event by its short id (e.g. '7s5TZhMQqrCs'). Returns title, " +
104
+ "description, dates, location, capacity, host, and the full gates config.",
105
+ inputSchema: {
106
+ eventId: z.string().describe("Public event short id"),
107
+ },
108
+ annotations: { readOnlyHint: true, openWorldHint: true },
109
+ }, async ({ eventId }) => handle(() => client.request(`/api/events/${encodeURIComponent(eventId)}`)));
110
+ server.registerTool("top_creators", {
111
+ title: "Top creators leaderboard",
112
+ description: "Top creators on IRLEvents ranked by RSVPs and events hosted.",
113
+ inputSchema: {},
114
+ annotations: { readOnlyHint: true, openWorldHint: true },
115
+ }, async () => handle(() => client.request("/api/creators/leaderboard")));
116
+ server.registerTool("platform_stats", {
117
+ title: "Platform stats",
118
+ description: "Cached platform-wide counts: events, RSVPs, creators, chains active.",
119
+ inputSchema: {},
120
+ annotations: { readOnlyHint: true, openWorldHint: true },
121
+ }, async () => handle(() => client.request("/api/stats/public")));
122
+ // ----- User-context tools (act on the api key owner) --------------------
123
+ server.registerTool("get_my_profile", {
124
+ title: "Get my profile",
125
+ description: "Read the api-key owner's IRLEvents profile: display name, bio, wallets across " +
126
+ "every connected chain, and the cached on-chain assets snapshot. " +
127
+ "If `assetsUpdatedAt` is stale, call sync_my_assets.",
128
+ inputSchema: {},
129
+ annotations: { readOnlyHint: true, openWorldHint: false },
130
+ }, async () => handle(() => client.request("/api/profile")));
131
+ server.registerTool("sync_my_assets", {
132
+ title: "Sync my on-chain assets",
133
+ description: "Force-refresh the user's NFT/token holdings across every connected chain. " +
134
+ "SLOW (5–30s) and resource-heavy — hits Alchemy / Helius / Hiro. " +
135
+ "Don't poll. Once per session is fine; rely on cached `Profile.assets` otherwise.",
136
+ inputSchema: {},
137
+ annotations: { readOnlyHint: false, openWorldHint: false, idempotentHint: true },
138
+ }, async () => handle(() => client.request("/api/profile/assets/sync", { method: "POST" })));
139
+ server.registerTool("check_eligibility", {
140
+ title: "Check event eligibility",
141
+ description: "Check whether the api-key owner satisfies any gate group on the given event. " +
142
+ "Always call this before rsvp_event — the API will reject ineligible users with 403. " +
143
+ "Returns { eligible, reason, matchedGroupId }.",
144
+ inputSchema: {
145
+ eventId: z.string().describe("Public event short id"),
146
+ },
147
+ annotations: { readOnlyHint: true, openWorldHint: false },
148
+ }, async ({ eventId }) => handle(() => client.request(`/api/events/${encodeURIComponent(eventId)}/eligibility`)));
149
+ server.registerTool("rsvp_status", {
150
+ title: "Get my RSVP status for an event",
151
+ description: "Returns whether the user has RSVPed to this event, plus check-in status and " +
152
+ "which gate group they qualified through.",
153
+ inputSchema: {
154
+ eventId: z.string().describe("Public event short id"),
155
+ },
156
+ annotations: { readOnlyHint: true, openWorldHint: false },
157
+ }, async ({ eventId }) => handle(() => client.request(`/api/events/${encodeURIComponent(eventId)}/rsvp/status`)));
158
+ server.registerTool("rsvp_event", {
159
+ title: "RSVP to an event",
160
+ description: "Create an RSVP for the api-key owner. Re-checks eligibility, locks the qualifying " +
161
+ "token in Redis (5-min TTL), and returns a check-in token. Failure modes: " +
162
+ "NOT_ELIGIBLE (403), TOKEN_LOCKED (409, qualifying NFT used elsewhere), " +
163
+ "ALREADY_RSVPED (409), EVENT_FULL (410), EVENT_PAST (410). " +
164
+ "Always call check_eligibility first.",
165
+ inputSchema: {
166
+ eventId: z.string().describe("Public event short id"),
167
+ },
168
+ annotations: { readOnlyHint: false, openWorldHint: false, destructiveHint: false },
169
+ }, async ({ eventId }) => handle(() => client.request(`/api/events/${encodeURIComponent(eventId)}/rsvp`, {
170
+ method: "POST",
171
+ body: JSON.stringify({}),
172
+ })));
173
+ server.registerTool("cancel_rsvp", {
174
+ title: "Cancel an RSVP",
175
+ description: "Cancel the api-key owner's RSVP for this event. Frees the locked token so it " +
176
+ "can be reused for another event in the same window.",
177
+ inputSchema: {
178
+ eventId: z.string().describe("Public event short id"),
179
+ },
180
+ annotations: { readOnlyHint: false, openWorldHint: false, destructiveHint: true },
181
+ }, async ({ eventId }) => handle(() => client.request(`/api/events/${encodeURIComponent(eventId)}/rsvp`, {
182
+ method: "DELETE",
183
+ })));
184
+ server.registerTool("my_eligible_events", {
185
+ title: "My eligible events",
186
+ description: "List every public event the given wallet currently qualifies for, based on its " +
187
+ "cached on-chain assets. Pass the user's primary wallet address (lowercased EVM, " +
188
+ "or chain-native for non-EVM).",
189
+ inputSchema: {
190
+ wallet: z.string().describe("Wallet address (EVM lowercased, or Solana/BTC native)"),
191
+ },
192
+ annotations: { readOnlyHint: true, openWorldHint: false },
193
+ }, async ({ wallet }) => handle(() => client.request(`/api/users/${encodeURIComponent(wallet)}/events/eligible`)));
194
+ // ----- Boot -------------------------------------------------------------
195
+ async function main() {
196
+ const transport = new StdioServerTransport();
197
+ await server.connect(transport);
198
+ console.error(`irlevents-mcp v0.1.0 ready (base: ${client.base}). Awaiting MCP requests on stdio.`);
199
+ }
200
+ main().catch((e) => {
201
+ console.error("irlevents-mcp fatal:", e);
202
+ process.exit(1);
203
+ });
204
+ //# 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,52 @@
1
+ {
2
+ "name": "irlevents-mcp",
3
+ "version": "0.1.0",
4
+ "description": "Model Context Protocol server for IRLEvents — token-gated event platform tools for Claude Desktop, Claude Code, Cursor, Cline, and other MCP-compatible clients.",
5
+ "type": "module",
6
+ "bin": {
7
+ "irlevents-mcp": "dist/index.js"
8
+ },
9
+ "main": "./dist/index.js",
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "start": "node dist/index.js",
13
+ "dev": "tsc --watch",
14
+ "prepublishOnly": "npm run build"
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "README.md"
19
+ ],
20
+ "keywords": [
21
+ "mcp",
22
+ "model-context-protocol",
23
+ "claude",
24
+ "irlevents",
25
+ "events",
26
+ "web3",
27
+ "nft",
28
+ "token-gating"
29
+ ],
30
+ "engines": {
31
+ "node": ">=18"
32
+ },
33
+ "license": "MIT",
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "git+https://github.com/Web3EK/irlevents-mcp.git"
37
+ },
38
+ "homepage": "https://github.com/Web3EK/irlevents-mcp#readme",
39
+ "bugs": {
40
+ "url": "https://github.com/Web3EK/irlevents-mcp/issues"
41
+ },
42
+ "author": "IRLEvents (https://irlevents.io)",
43
+ "dependencies": {
44
+ "@cfworker/json-schema": "^4.1.1",
45
+ "@modelcontextprotocol/sdk": "^1.29.0",
46
+ "zod": "^3.25.0"
47
+ },
48
+ "devDependencies": {
49
+ "@types/node": "^22.0.0",
50
+ "typescript": "^5.6.0"
51
+ }
52
+ }