@vanmoose/mcp-server 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/README.md ADDED
@@ -0,0 +1,189 @@
1
+ # @vanmoose/mcp-server
2
+
3
+ 73 developer utility APIs as MCP tools — one key, one server.
4
+
5
+ [![npm version](https://badge.fury.io/js/@vanmoose%2Fmcp-server.svg)](https://www.npmjs.com/package/@vanmoose/mcp-server)
6
+
7
+ ## What This Does
8
+
9
+ This MCP server exposes **192 tools from 73 VanMoose APIs** to any MCP-compatible AI agent (Claude, GPT, Cursor, Windsurf, etc.).
10
+
11
+ One API key. One server. Screenshot capture, email validation, NLP, WHOIS, tech stack detection, PDF generation, and 66 more — all callable as native tools.
12
+
13
+ ## Quick Start
14
+
15
+ ### 1. Get Your API Key
16
+
17
+ Sign up free at [vanmoose.cc](https://vanmoose.cc/sign-up) — a key is auto-issued on signup.
18
+
19
+ ### 2. Configure Claude Desktop
20
+
21
+ **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
22
+ **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
23
+
24
+ ```json
25
+ {
26
+ "mcpServers": {
27
+ "vanmoose": {
28
+ "command": "npx",
29
+ "args": ["-y", "@vanmoose/mcp-server"],
30
+ "env": {
31
+ "VANMOOSE_API_KEY": "vm_live_your_key_here"
32
+ }
33
+ }
34
+ }
35
+ }
36
+ ```
37
+
38
+ Restart Claude Desktop. You'll see 192 tools available.
39
+
40
+ ### 3. Configure Cursor / Windsurf
41
+
42
+ Add to `.cursor/mcp.json` or `.windsurf/mcp.json`:
43
+
44
+ ```json
45
+ {
46
+ "mcpServers": {
47
+ "vanmoose": {
48
+ "command": "npx",
49
+ "args": ["-y", "@vanmoose/mcp-server"],
50
+ "env": {
51
+ "VANMOOSE_API_KEY": "vm_live_your_key_here"
52
+ }
53
+ }
54
+ }
55
+ }
56
+ ```
57
+
58
+ ### 4. Configure Claude Code
59
+
60
+ Add to `.claude/settings.json`:
61
+
62
+ ```json
63
+ {
64
+ "mcpServers": {
65
+ "vanmoose": {
66
+ "command": "npx",
67
+ "args": ["-y", "@vanmoose/mcp-server"],
68
+ "env": {
69
+ "VANMOOSE_API_KEY": "vm_live_your_key_here"
70
+ }
71
+ }
72
+ }
73
+ }
74
+ ```
75
+
76
+ ## Available Tools (190 total)
77
+
78
+ ### Image Generation
79
+ | Tool | Description |
80
+ |------|-------------|
81
+ | `vanmoose_screenshot` | Capture full-page screenshots via headless Chrome |
82
+ | `vanmoose_qrcode` | Generate QR codes with custom colors and sizes |
83
+ | `vanmoose_barcode` | Generate barcodes (Code128, EAN-13, etc.) |
84
+ | `vanmoose_socialcard` | Generate Open Graph and Twitter Card images |
85
+ | `vanmoose_placeholder` | Generate SVG placeholder images |
86
+ | `vanmoose_avatar` | Generate SVG avatars (initials, identicons, pixel art) |
87
+ | `vanmoose_gradient` | Generate CSS and SVG gradients |
88
+ | `vanmoose_patterngen` | Generate SVG patterns |
89
+ | `vanmoose_favicon` | Extract favicons from any website |
90
+ | `vanmoose_imagecompress` | Compress images with quality control |
91
+ | `vanmoose_imageresize` | Resize and crop images |
92
+
93
+ ### Web Scraping & Intelligence
94
+ | Tool | Description |
95
+ |------|-------------|
96
+ | `vanmoose_techstack_detect` | Detect frameworks, CMS, technologies on websites |
97
+ | `vanmoose_metadata_extract` | Extract Open Graph, Twitter Cards, meta tags |
98
+ | `vanmoose_readable_extract` | Extract clean article content from URLs |
99
+ | `vanmoose_unfurl_preview` | Link preview data for rich embeds |
100
+ | `vanmoose_pricewatch` | Extract prices from web pages |
101
+ | `vanmoose_rssfeed_parse` | Parse RSS/Atom feeds |
102
+ | `vanmoose_sitemap_parse` | Parse XML sitemaps |
103
+ | `vanmoose_linkcheck_check` | Check if URLs are alive, dead, or redirecting |
104
+ | `vanmoose_changecheck` | Detect website content changes |
105
+
106
+ ### Validation
107
+ | Tool | Description |
108
+ |------|-------------|
109
+ | `vanmoose_emailverify_verify` | Validate emails (syntax, MX, disposable) |
110
+ | `vanmoose_emailverify_bulk` | Bulk email verification |
111
+ | `vanmoose_phonevalidate` | Validate international phone numbers |
112
+ | `vanmoose_vatvalidate` | Validate EU VAT numbers |
113
+ | `vanmoose_whois_lookup` | Domain WHOIS lookup |
114
+ | `vanmoose_checkcheck` | Domain availability check |
115
+ | `vanmoose_breachcheck` | Check emails/passwords in known breaches |
116
+ | `vanmoose_vpndetect` | Detect VPN, proxy, Tor IPs |
117
+
118
+ ### Text & NLP
119
+ | Tool | Description |
120
+ |------|-------------|
121
+ | `vanmoose_nlptools` | Language detection, sentiment, keywords |
122
+ | `vanmoose_markdown` | Convert Markdown ↔ HTML |
123
+ | `vanmoose_profanity` | Detect and filter profanity |
124
+ | `vanmoose_languagedetect` | Detect text language |
125
+ | `vanmoose_readability` | Analyze text readability |
126
+
127
+ ### Developer Utils
128
+ | Tool | Description |
129
+ |------|-------------|
130
+ | `vanmoose_jwt` | Create, decode, verify JWTs |
131
+ | `vanmoose_hashtools` | Generate/verify hashes (MD5, SHA256) |
132
+ | `vanmoose_uuidgen` | Generate UUIDs, ULIDs, NanoIDs |
133
+ | `vanmoose_regextester` | Test regular expressions |
134
+ | `vanmoose_cronparser` | Parse cron expressions |
135
+ | `vanmoose_dataconv` | Convert JSON ↔ CSV ↔ XML ↔ YAML |
136
+
137
+ *Plus 130+ more tools across network, converter, and data categories.*
138
+
139
+ ## For Agent Builders
140
+
141
+ ```typescript
142
+ // An LLM orchestrator discovers tools via list_tools
143
+ const tools = await mcpClient.listTools();
144
+ // → Returns 190 tool definitions with inputSchemas
145
+
146
+ // Call any tool
147
+ const result = await mcpClient.callTool('vanmoose_emailverify_verify', {
148
+ email: 'test@example.com'
149
+ });
150
+ ```
151
+
152
+ All tools return structured JSON. Error responses include machine-readable codes:
153
+ - `VANMOOSE_AUTH_ERROR` — Invalid/missing API key
154
+ - `VANMOOSE_QUOTA_EXCEEDED` — Monthly limit hit (upgrade URL included)
155
+ - `VANMOOSE_VALIDATION_ERROR` — Bad input parameters
156
+ - `VANMOOSE_RATE_LIMITED` — Too many requests (Retry-After included)
157
+
158
+ ## Environment Variables
159
+
160
+ | Variable | Required | Description |
161
+ |----------|----------|-------------|
162
+ | `VANMOOSE_API_KEY` | Yes | Your `vm_live_` API key |
163
+
164
+ ## Development
165
+
166
+ ```bash
167
+ # Install dependencies
168
+ pnpm install
169
+
170
+ # Generate tool definitions from OpenAPI specs
171
+ pnpm run generate
172
+
173
+ # Build
174
+ pnpm run build
175
+
176
+ # Run locally (stdio transport)
177
+ VANMOOSE_API_KEY=vm_live_xxx node dist/index.js
178
+ ```
179
+
180
+ ## Links
181
+
182
+ - [Van Moose API Platform](https://vanmoose.cc)
183
+ - [Get API Key](https://vanmoose.cc/dashboard)
184
+ - [All 73 APIs](https://vanmoose.cc/apis)
185
+ - [JavaScript SDK](https://www.npmjs.com/package/@vanmoose/sdk)
186
+
187
+ ## License
188
+
189
+ MIT — [Van Moose BV](https://vanmoose.com), Amsterdam
package/dist/auth.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @vanmoose/mcp-server — API key validation + env handling
3
+ */
4
+ export declare function getApiKey(): string;
5
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,wBAAgB,SAAS,IAAI,MAAM,CAiBlC"}
package/dist/auth.js ADDED
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @vanmoose/mcp-server — API key validation + env handling
3
+ */
4
+ const API_KEY_PREFIX = 'vm_live_';
5
+ export function getApiKey() {
6
+ const key = process.env.VANMOOSE_API_KEY;
7
+ if (!key) {
8
+ console.error('Error: VANMOOSE_API_KEY environment variable is required.\n' +
9
+ 'Get your free API key at https://vanmoose.cc/dashboard');
10
+ process.exit(1);
11
+ }
12
+ if (!key.startsWith(API_KEY_PREFIX)) {
13
+ console.error(`Error: Invalid API key format. Keys must start with "${API_KEY_PREFIX}".\n` +
14
+ 'Get a valid key at https://vanmoose.cc/dashboard');
15
+ process.exit(1);
16
+ }
17
+ return key;
18
+ }
19
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,cAAc,GAAG,UAAU,CAAC;AAElC,MAAM,UAAU,SAAS;IACvB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IACzC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,CAAC,KAAK,CACX,6DAA6D;YAC7D,wDAAwD,CACzD,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QACpC,OAAO,CAAC,KAAK,CACX,wDAAwD,cAAc,MAAM;YAC5E,kDAAkD,CACnD,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @vanmoose/mcp-server — VanMoose API HTTP client
3
+ *
4
+ * Lightweight fetch-based client. No external dependencies.
5
+ */
6
+ export declare class VanMooseClient {
7
+ private apiKey;
8
+ constructor(apiKey: string);
9
+ request(domain: string, path: string, method: 'GET' | 'POST', params: Record<string, unknown>): Promise<unknown>;
10
+ private mapError;
11
+ }
12
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,EAAE,MAAM;IAIpB,OAAO,CACX,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,KAAK,GAAG,MAAM,EACtB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC,OAAO,CAAC;IA0EnB,OAAO,CAAC,QAAQ;CAkCjB"}
package/dist/client.js ADDED
@@ -0,0 +1,115 @@
1
+ /**
2
+ * @vanmoose/mcp-server — VanMoose API HTTP client
3
+ *
4
+ * Lightweight fetch-based client. No external dependencies.
5
+ */
6
+ import { ERROR_CODES } from './types.js';
7
+ const TIMEOUT_MS = 30_000;
8
+ export class VanMooseClient {
9
+ apiKey;
10
+ constructor(apiKey) {
11
+ this.apiKey = apiKey;
12
+ }
13
+ async request(domain, path, method, params) {
14
+ const url = new URL(`https://${domain}${path}`);
15
+ const headers = {
16
+ 'X-VanMoose-Key': this.apiKey,
17
+ 'User-Agent': '@vanmoose/mcp-server/1.0.0',
18
+ };
19
+ let body;
20
+ if (method === 'GET') {
21
+ for (const [key, value] of Object.entries(params)) {
22
+ if (value !== undefined && value !== null) {
23
+ if (Array.isArray(value)) {
24
+ url.searchParams.set(key, value.join(','));
25
+ }
26
+ else {
27
+ url.searchParams.set(key, String(value));
28
+ }
29
+ }
30
+ }
31
+ }
32
+ else {
33
+ headers['Content-Type'] = 'application/json';
34
+ body = JSON.stringify(params);
35
+ }
36
+ const controller = new AbortController();
37
+ const timeout = setTimeout(() => controller.abort(), TIMEOUT_MS);
38
+ try {
39
+ const response = await fetch(url.toString(), {
40
+ method,
41
+ headers,
42
+ body,
43
+ signal: controller.signal,
44
+ });
45
+ const retryAfter = response.headers.get('Retry-After');
46
+ const rateLimitRemaining = response.headers.get('X-RateLimit-Remaining');
47
+ if (!response.ok) {
48
+ const errorBody = await response.text().catch(() => 'Unknown error');
49
+ throw this.mapError(response.status, errorBody, retryAfter);
50
+ }
51
+ const contentType = response.headers.get('Content-Type') || '';
52
+ if (contentType.includes('application/json')) {
53
+ const data = await response.json();
54
+ return {
55
+ data,
56
+ _meta: {
57
+ rateLimitRemaining: rateLimitRemaining ? parseInt(rateLimitRemaining) : undefined,
58
+ },
59
+ };
60
+ }
61
+ // Binary or text response (screenshots, PDFs, etc.)
62
+ const text = await response.text();
63
+ return { data: text };
64
+ }
65
+ catch (error) {
66
+ if (error instanceof Error && error.name === 'AbortError') {
67
+ const e = {
68
+ code: ERROR_CODES.TIMEOUT,
69
+ message: `Request timed out after ${TIMEOUT_MS / 1000}s`,
70
+ status: 408,
71
+ };
72
+ throw e;
73
+ }
74
+ throw error;
75
+ }
76
+ finally {
77
+ clearTimeout(timeout);
78
+ }
79
+ }
80
+ mapError(status, body, retryAfter) {
81
+ switch (status) {
82
+ case 401:
83
+ return {
84
+ code: ERROR_CODES.AUTH_ERROR,
85
+ message: 'Invalid or missing API key. Get one at https://vanmoose.cc/dashboard',
86
+ status,
87
+ };
88
+ case 402:
89
+ return {
90
+ code: ERROR_CODES.QUOTA_EXCEEDED,
91
+ message: `Monthly quota exceeded. Upgrade at https://vanmoose.cc/dashboard/billing — ${body}`,
92
+ status,
93
+ };
94
+ case 422:
95
+ return {
96
+ code: ERROR_CODES.VALIDATION_ERROR,
97
+ message: `Validation error: ${body}`,
98
+ status,
99
+ };
100
+ case 429:
101
+ return {
102
+ code: ERROR_CODES.RATE_LIMITED,
103
+ message: `Rate limited.${retryAfter ? ` Retry after ${retryAfter}s.` : ''} ${body}`,
104
+ status,
105
+ };
106
+ default:
107
+ return {
108
+ code: ERROR_CODES.API_ERROR,
109
+ message: `API error (${status}): ${body}`,
110
+ status,
111
+ };
112
+ }
113
+ }
114
+ }
115
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @vanmoose/mcp-server — 72 developer utility APIs as MCP tools
4
+ *
5
+ * One key. One server. 72 tools for any AI agent.
6
+ * https://vanmoose.cc
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;GAKG"}
package/dist/index.js ADDED
@@ -0,0 +1,176 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @vanmoose/mcp-server — 72 developer utility APIs as MCP tools
4
+ *
5
+ * One key. One server. 72 tools for any AI agent.
6
+ * https://vanmoose.cc
7
+ */
8
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
9
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
10
+ import { z } from "zod";
11
+ import { getApiKey } from "./auth.js";
12
+ import { VanMooseClient } from "./client.js";
13
+ import { getKeyScope } from "./scope.js";
14
+ import { tools } from "./tools/index.js";
15
+ // ============================================================================
16
+ // INITIALIZATION
17
+ // ============================================================================
18
+ const apiKey = getApiKey();
19
+ const client = new VanMooseClient(apiKey);
20
+ const server = new McpServer({
21
+ name: "@vanmoose/mcp-server",
22
+ version: "1.0.0",
23
+ });
24
+ // ============================================================================
25
+ // HELPER: Build zod schema from tool parameter definitions
26
+ // ============================================================================
27
+ function buildZodSchema(params) {
28
+ const shape = {};
29
+ for (const p of params) {
30
+ let schema;
31
+ switch (p.type) {
32
+ case 'number':
33
+ case 'integer':
34
+ schema = z.number().describe(p.description);
35
+ break;
36
+ case 'boolean':
37
+ schema = z.boolean().describe(p.description);
38
+ break;
39
+ case 'array':
40
+ schema = z.array(z.string()).describe(p.description);
41
+ break;
42
+ case 'object':
43
+ schema = z.record(z.unknown()).describe(p.description);
44
+ break;
45
+ default:
46
+ schema = z.string().describe(p.description);
47
+ }
48
+ if (!p.required) {
49
+ schema = schema.optional();
50
+ }
51
+ shape[p.name] = schema;
52
+ }
53
+ return z.object(shape);
54
+ }
55
+ // ============================================================================
56
+ // REGISTER ALL TOOLS
57
+ // ============================================================================
58
+ function registerTool(tool) {
59
+ const allParams = [...tool.parameters, ...tool.bodyParameters];
60
+ const inputSchema = buildZodSchema(allParams);
61
+ server.registerTool(tool.name, {
62
+ title: tool.title,
63
+ description: tool.description,
64
+ inputSchema,
65
+ annotations: {
66
+ readOnlyHint: true,
67
+ destructiveHint: false,
68
+ idempotentHint: true,
69
+ openWorldHint: true,
70
+ },
71
+ }, async (params) => {
72
+ try {
73
+ // Split params into query vs body based on tool definition
74
+ const queryParamNames = new Set(tool.parameters.map(p => p.name));
75
+ const queryParams = {};
76
+ const bodyParams = {};
77
+ for (const [key, value] of Object.entries(params)) {
78
+ if (value === undefined)
79
+ continue;
80
+ if (queryParamNames.has(key)) {
81
+ queryParams[key] = value;
82
+ }
83
+ else {
84
+ bodyParams[key] = value;
85
+ }
86
+ }
87
+ const requestParams = tool.method === 'GET' ? queryParams : bodyParams;
88
+ const result = await client.request(tool.domain, tool.path, tool.method, requestParams);
89
+ return {
90
+ content: [{
91
+ type: "text",
92
+ text: JSON.stringify(result, null, 2),
93
+ }],
94
+ };
95
+ }
96
+ catch (error) {
97
+ const vmError = error;
98
+ if (vmError.code) {
99
+ return {
100
+ isError: true,
101
+ content: [{
102
+ type: "text",
103
+ text: JSON.stringify({
104
+ error: vmError.code,
105
+ message: vmError.message,
106
+ status: vmError.status,
107
+ }),
108
+ }],
109
+ };
110
+ }
111
+ return {
112
+ isError: true,
113
+ content: [{
114
+ type: "text",
115
+ text: `Error calling ${tool.name}: ${error instanceof Error ? error.message : String(error)}`,
116
+ }],
117
+ };
118
+ }
119
+ });
120
+ }
121
+ // ============================================================================
122
+ // SCOPE-AWARE TOOL REGISTRATION
123
+ // ============================================================================
124
+ async function registerTools() {
125
+ // Fetch scope to determine which tools to register
126
+ const scope = await getKeyScope(apiKey);
127
+ let filteredTools = tools;
128
+ if (scope && scope.scopeType !== 'full') {
129
+ const allowedSet = new Set(scope.allowedSlugs);
130
+ filteredTools = tools.filter(t => allowedSet.has(t.apiId));
131
+ if (scope.scopeType === 'category') {
132
+ console.error(`[Scope] Key scoped to category "${scope.scopeValue}" — ${filteredTools.length}/${tools.length} tools`);
133
+ }
134
+ else if (scope.scopeType === 'api') {
135
+ console.error(`[Scope] Key scoped to API "${scope.scopeValue}" — ${filteredTools.length}/${tools.length} tools`);
136
+ }
137
+ }
138
+ for (const tool of filteredTools) {
139
+ registerTool(tool);
140
+ }
141
+ // Register catalog resource with filtered tools
142
+ server.registerResource("API Catalog", "vanmoose://catalog", {
143
+ description: `Catalog of ${filteredTools.length} VanMoose APIs available with this key`,
144
+ mimeType: "application/json",
145
+ }, async () => {
146
+ const catalog = filteredTools.map(t => ({
147
+ name: t.name,
148
+ title: t.title,
149
+ description: t.description,
150
+ apiId: t.apiId,
151
+ domain: t.domain,
152
+ }));
153
+ return {
154
+ contents: [{
155
+ uri: "vanmoose://catalog",
156
+ mimeType: "application/json",
157
+ text: JSON.stringify(catalog, null, 2),
158
+ }],
159
+ };
160
+ });
161
+ return filteredTools.length;
162
+ }
163
+ // ============================================================================
164
+ // TRANSPORT
165
+ // ============================================================================
166
+ async function main() {
167
+ const toolCount = await registerTools();
168
+ const transport = new StdioServerTransport();
169
+ await server.connect(transport);
170
+ console.error(`@vanmoose/mcp-server running — ${toolCount} tools registered`);
171
+ }
172
+ main().catch((error) => {
173
+ console.error("Fatal error:", error);
174
+ process.exit(1);
175
+ });
176
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @vanmoose/mcp-server — Scope filtering
3
+ * Fetches allowed API slugs from vanmoose.cc based on the key's scope.
4
+ */
5
+ export interface KeyScope {
6
+ scopeType: string;
7
+ scopeValue: string | null;
8
+ allowedSlugs: string[];
9
+ }
10
+ /**
11
+ * Get the scope info for the current API key.
12
+ * Returns all slugs for full-access keys.
13
+ * On error, returns null (caller should register all tools as fallback).
14
+ */
15
+ export declare function getKeyScope(apiKey: string): Promise<KeyScope | null>;
16
+ //# sourceMappingURL=scope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../src/scope.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,WAAW,QAAQ;IACvB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,YAAY,EAAE,MAAM,EAAE,CAAA;CACvB;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAkB1E"}
package/dist/scope.js ADDED
@@ -0,0 +1,29 @@
1
+ /**
2
+ * @vanmoose/mcp-server — Scope filtering
3
+ * Fetches allowed API slugs from vanmoose.cc based on the key's scope.
4
+ */
5
+ const BASE_URL = process.env.VANMOOSE_BASE_URL || 'https://vanmoose.cc';
6
+ /**
7
+ * Get the scope info for the current API key.
8
+ * Returns all slugs for full-access keys.
9
+ * On error, returns null (caller should register all tools as fallback).
10
+ */
11
+ export async function getKeyScope(apiKey) {
12
+ try {
13
+ const res = await fetch(`${BASE_URL}/api/key-scope`, {
14
+ method: 'POST',
15
+ headers: { 'Content-Type': 'application/json' },
16
+ body: JSON.stringify({ apiKey }),
17
+ });
18
+ if (!res.ok) {
19
+ console.error(`[Scope] Failed to fetch key scope: ${res.status}`);
20
+ return null;
21
+ }
22
+ return (await res.json());
23
+ }
24
+ catch (error) {
25
+ console.error('[Scope] Error fetching key scope:', error);
26
+ return null;
27
+ }
28
+ }
29
+ //# sourceMappingURL=scope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scope.js","sourceRoot":"","sources":["../src/scope.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,qBAAqB,CAAA;AAQvE;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAAc;IAC9C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,QAAQ,gBAAgB,EAAE;YACnD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;SACjC,CAAC,CAAA;QAEF,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,OAAO,CAAC,KAAK,CAAC,sCAAsC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAA;YACjE,OAAO,IAAI,CAAA;QACb,CAAC;QAED,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAa,CAAA;IACvC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,KAAK,CAAC,CAAA;QACzD,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Auto-generated tool definitions for @vanmoose/mcp-server
3
+ * Generated: 2026-03-17T19:05:16.421Z
4
+ * Total: 192 tools from 73 APIs
5
+ *
6
+ * DO NOT EDIT — run `npm run generate` to regenerate.
7
+ */
8
+ import type { ToolDefinition } from '../types.js';
9
+ export declare const tools: ToolDefinition[];
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,eAAO,MAAM,KAAK,EAAE,cAAc,EAo2HjC,CAAC"}