@bigapi/mcp 0.1.0 → 0.3.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 +1 -1
- package/package.json +2 -2
- package/src/index.js +36 -6
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ Gives Claude Desktop, Cursor, Cline, Windsurf and any MCP-capable agent the file
|
|
|
14
14
|
| `get_access` | Free API key, instantly, no signup – 100 free operations |
|
|
15
15
|
| `get_balance` · `get_usage` · `set_monthly_cap` · `get_pricing` | Account |
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
**$0.01 (one US cent) per operation. 100 free. Balance never expires. Failed calls are free.** Servers in Germany, files deleted after delivery.
|
|
18
18
|
|
|
19
19
|
## Install
|
|
20
20
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bigapi/mcp",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "MCP server for bigapi.dev
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "MCP server for bigapi.dev \u2013 the output layer for AI agents: render HTML/Markdown to PDF, merge/split/compress PDFs, convert images. One cent per operation.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"start": "node src/index.js",
|
package/src/index.js
CHANGED
|
@@ -5,10 +5,10 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
|
|
|
5
5
|
import { z } from 'zod';
|
|
6
6
|
import { apiJson, opJson, opFiles, getKey, saveKey, configPath, BigapiError, BASE_URL } from './client.js';
|
|
7
7
|
|
|
8
|
-
const server = new McpServer({ name: 'bigapi', version: '0.
|
|
8
|
+
const server = new McpServer({ name: 'bigapi', version: '0.3.0' }, {
|
|
9
9
|
instructions: `bigapi.dev – the output layer for AI agents. Deterministic file operations an LLM cannot do itself:
|
|
10
10
|
render HTML/Markdown/URLs to PDF or PNG, merge/split/rotate/compress PDFs, turn PDF pages into images, resize/convert/watermark images.
|
|
11
|
-
Pricing:
|
|
11
|
+
Pricing: $0.01 (one US cent) per operation, 100 free operations per new key (no signup), balance never expires, failed calls are free.
|
|
12
12
|
If no API key is configured, call get_access first – it is free and instant. Files are given and returned as local paths.`,
|
|
13
13
|
});
|
|
14
14
|
|
|
@@ -20,8 +20,8 @@ function fail(e) {
|
|
|
20
20
|
if (e instanceof BigapiError) {
|
|
21
21
|
const b = e.body || {};
|
|
22
22
|
let hint = '';
|
|
23
|
-
if (b.error === 'balance_empty') hint = `\
|
|
24
|
-
if (b.error === 'cap_reached') hint = `\
|
|
23
|
+
if (b.error === 'balance_empty') hint = `\nBalance empty. Add credit (from $5, never expires): ${b.upgrade_url}`;
|
|
24
|
+
if (b.error === 'cap_reached') hint = `\nMonthly cap of this key reached (${b.monthly_cap_cents} US cents). Raise it with set_monthly_cap.`;
|
|
25
25
|
if (b.error === 'rate_limited') hint = `\nZu viele Anfragen. In ${b.retry_after ?? 1} s erneut versuchen.`;
|
|
26
26
|
if (b.error === 'no_api_key' || e.status === 401) hint = `\nKein gültiger Key. Tool get_access aufrufen (kostenlos).`;
|
|
27
27
|
return { isError: true, content: [{ type: 'text', text: `bigapi error ${e.status}: ${b.error}${hint}\n${JSON.stringify(b)}` }] };
|
|
@@ -32,7 +32,7 @@ const run = (fn) => async (args) => { try { return await fn(args); } catch (e) {
|
|
|
32
32
|
|
|
33
33
|
// ---- Zugang -----------------------------------------------------------------
|
|
34
34
|
server.tool('get_access',
|
|
35
|
-
'Get a free bigapi API key instantly – no signup, no credit card. 100 free operations for 7 days, then
|
|
35
|
+
'Get a free bigapi API key instantly – no signup, no credit card. 100 free operations for 7 days, then $0.01 per operation. The key is stored locally and used by all other tools. Call this once if no key is configured.',
|
|
36
36
|
{ name: z.string().optional().describe('Optional label for the key, e.g. "claude-desktop"') },
|
|
37
37
|
run(async ({ name }) => {
|
|
38
38
|
const existing = await getKey();
|
|
@@ -51,7 +51,7 @@ server.tool('get_balance',
|
|
|
51
51
|
server.tool('get_usage', 'Operations and cost this month, grouped by operation.', {}, run(async () => ok(await apiJson('GET', '/v1/usage'))));
|
|
52
52
|
|
|
53
53
|
server.tool('set_monthly_cap',
|
|
54
|
-
'Raise or lower the monthly spending cap (in cents) of the configured key. Default is 1000 (10
|
|
54
|
+
'Raise or lower the monthly spending cap (in US cents) of the configured key. Default is 1000 ($10). Protects against runaway loops.',
|
|
55
55
|
{ monthly_cap_cents: z.number().int().min(0).max(1_000_000) },
|
|
56
56
|
run(async ({ monthly_cap_cents }) => {
|
|
57
57
|
const bal = await apiJson('GET', '/v1/balance');
|
|
@@ -111,6 +111,36 @@ server.tool('pdf_to_images', 'Render PDF pages as JPEG (default) or PNG images
|
|
|
111
111
|
format: z.enum(['jpeg', 'png']).default('jpeg'), quality: z.number().int().min(30).max(100).default(85), output_path: z.string().optional(), idempotency_key: z.string().optional() },
|
|
112
112
|
run(async (a) => ok(await opFiles('/v1/pdf/pages', [['file', a.file]], { dpi: String(a.dpi), first: a.first_page && String(a.first_page), last: a.last_page && String(a.last_page), format: a.format, quality: String(a.quality) }, a.output_path, a.idempotency_key), 'Pages rendered.')));
|
|
113
113
|
|
|
114
|
+
// ---- Welle 1a: Screenshot · OCR · PDF/A -----------------------------------------
|
|
115
|
+
server.tool('screenshot',
|
|
116
|
+
'Screenshot of a public URL with device presets (desktop, laptop, tablet, mobile). Full page by default. Returns the local output path. 1 cent.',
|
|
117
|
+
{ url: z.string().url(), device: z.enum(['desktop', 'laptop', 'tablet', 'mobile']).default('desktop'),
|
|
118
|
+
full_page: z.boolean().default(true), format: z.enum(['png', 'jpeg']).default('png'),
|
|
119
|
+
quality: z.number().int().min(30).max(100).default(85).describe('JPEG only'),
|
|
120
|
+
delay_ms: z.number().int().min(0).max(10000).optional().describe('Extra wait after load'),
|
|
121
|
+
output_path: z.string().optional(), idempotency_key: z.string().optional() },
|
|
122
|
+
run(async (a) => ok(await opJson('/v1/screenshot',
|
|
123
|
+
{ url: a.url, device: a.device, fullPage: a.full_page, format: a.format, quality: a.quality, delayMs: a.delay_ms },
|
|
124
|
+
a.output_path, a.idempotency_key), 'Screenshot taken.')));
|
|
125
|
+
|
|
126
|
+
server.tool('ocr',
|
|
127
|
+
'OCR a scanned PDF or image (local path) into a searchable PDF (default), plain text, or JSON per page. Languages e.g. "deu", "eng", "deu+eng". 1 cent PER PAGE.',
|
|
128
|
+
{ file: z.string(), lang: z.string().default('deu+eng'),
|
|
129
|
+
output: z.enum(['pdf', 'text', 'json']).default('pdf'),
|
|
130
|
+
dpi: z.number().int().min(100).max(600).default(300),
|
|
131
|
+
output_path: z.string().optional(), idempotency_key: z.string().optional() },
|
|
132
|
+
run(async (a) => ok(await opFiles('/v1/ocr', [['file', a.file]], { lang: a.lang, output: a.output, dpi: String(a.dpi) }, a.output_path, a.idempotency_key), 'OCR done.')));
|
|
133
|
+
|
|
134
|
+
server.tool('pdf_to_pdfa',
|
|
135
|
+
'Convert a PDF (local path) to archival PDF/A-2b with embedded fonts – for long-term storage and compliance. 5 cents.',
|
|
136
|
+
{ file: z.string(), output_path: z.string().optional(), idempotency_key: z.string().optional() },
|
|
137
|
+
run(async (a) => ok(await opFiles('/v1/pdf/pdfa', [['file', a.file]], {}, a.output_path, a.idempotency_key), 'Converted to PDF/A.')));
|
|
138
|
+
|
|
139
|
+
server.tool('office_to_pdf',
|
|
140
|
+
'Convert an Office document (local path: DOCX, DOC, XLSX, XLS, PPTX, PPT, ODT, ODS, ODP, RTF, CSV, TXT) to PDF via LibreOffice. 1 cent PER PAGE.',
|
|
141
|
+
{ file: z.string(), output_path: z.string().optional(), idempotency_key: z.string().optional() },
|
|
142
|
+
run(async (a) => ok(await opFiles('/v1/office/pdf', [['file', a.file]], {}, a.output_path, a.idempotency_key), 'Converted to PDF.')));
|
|
143
|
+
|
|
114
144
|
// ---- Images --------------------------------------------------------------------
|
|
115
145
|
server.tool('image_process', 'Resize, crop, rotate, convert (jpeg/png/webp/avif/tiff), compress, strip EXIF and/or watermark an image in one call. 1 cent.',
|
|
116
146
|
{ file: z.string(),
|