@microlink/mcp 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/LICENSE.md +21 -0
- package/README.md +435 -0
- package/bin/microlink-mcp.js +8 -0
- package/package.json +104 -0
- package/scripts/postinstall.js +49 -0
- package/src/index.js +65 -0
- package/src/microlink-client.js +239 -0
- package/src/schemas.js +271 -0
- package/src/tools/audio.js +17 -0
- package/src/tools/extract.js +20 -0
- package/src/tools/index.js +23 -0
- package/src/tools/insights.js +21 -0
- package/src/tools/markdown.js +16 -0
- package/src/tools/meta.js +17 -0
- package/src/tools/palette.js +17 -0
- package/src/tools/pdf.js +23 -0
- package/src/tools/register.js +110 -0
- package/src/tools/screenshot.js +23 -0
- package/src/tools/text.js +16 -0
- package/src/tools/video.js +17 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright © [Microlink](https://microlink.io)
|
|
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
|
|
13
|
+
> all 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,435 @@
|
|
|
1
|
+
# Microlink MCP
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
<img src="https://github.com/microlinkhq/cdn/raw/master/dist/logo/banner.png#gh-light-mode-only" alt="microlink logo">
|
|
5
|
+
<img src="https://github.com/microlinkhq/cdn/raw/master/dist/logo/banner-dark.png#gh-dark-mode-only" alt="microlink logo">
|
|
6
|
+
</div>
|
|
7
|
+
|
|
8
|
+
A [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server that exposes [Microlink API](https://microlink.io) capabilities to AI assistants. Runs over stdio transport, making it compatible with Claude Desktop, VS Code, Cursor, and any other MCP-capable client.
|
|
9
|
+
|
|
10
|
+
It turns natural-language requests into Microlink calls: take screenshots, generate PDFs, extract metadata or readable text, detect video/audio sources, run Lighthouse audits, and scrape custom fields with CSS selectors, all without leaving the assistant.
|
|
11
|
+
|
|
12
|
+
See the [MCP integration page](https://microlink.io/integration/mcp) for a guided walkthrough, or the [`@microlink/mcp`](https://www.npmjs.com/package/@microlink/mcp) npm package.
|
|
13
|
+
|
|
14
|
+
## Table of contents
|
|
15
|
+
|
|
16
|
+
- [Install](#install)
|
|
17
|
+
- [MCP client configuration](#mcp-client-configuration)
|
|
18
|
+
- [Usage](#usage)
|
|
19
|
+
- [Tools](#tools)
|
|
20
|
+
- [Authentication](#authentication)
|
|
21
|
+
- [Development](#development)
|
|
22
|
+
- [License](#license)
|
|
23
|
+
|
|
24
|
+
## Install
|
|
25
|
+
|
|
26
|
+
### Use the published package (recommended)
|
|
27
|
+
|
|
28
|
+
No local installation is required. Run directly with `npx`:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npx -y @microlink/mcp
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Optional: install globally
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm install -g @microlink/mcp
|
|
38
|
+
microlink-mcp
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
During installation, the package prints a console reminder about the free Microlink plan (`50 requests/day`) and where to get an API key for higher/unlimited usage at [microlink.io/#pricing](https://microlink.io/#pricing).
|
|
42
|
+
|
|
43
|
+
## MCP client configuration
|
|
44
|
+
|
|
45
|
+
### Claude Desktop
|
|
46
|
+
|
|
47
|
+
Edit `~/Library/Application\ Support/Claude/claude_desktop_config.json`:
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"mcpServers": {
|
|
52
|
+
"microlink": {
|
|
53
|
+
"command": "npx",
|
|
54
|
+
"args": ["-y", "@microlink/mcp"],
|
|
55
|
+
"env": {
|
|
56
|
+
"MICROLINK_API_KEY": "YOUR_MICROLINK_API_KEY"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### VS Code / Codex
|
|
64
|
+
|
|
65
|
+
Published package:
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{
|
|
69
|
+
"mcpServers": {
|
|
70
|
+
"microlink": {
|
|
71
|
+
"command": "npx",
|
|
72
|
+
"args": ["-y", "@microlink/mcp"],
|
|
73
|
+
"env": {
|
|
74
|
+
"MICROLINK_API_KEY": "YOUR_MICROLINK_API_KEY"
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Local repository:
|
|
82
|
+
|
|
83
|
+
```json
|
|
84
|
+
{
|
|
85
|
+
"mcpServers": {
|
|
86
|
+
"microlink": {
|
|
87
|
+
"command": "node",
|
|
88
|
+
"args": ["/absolute/path/to/mcp/src/index.js"],
|
|
89
|
+
"env": {
|
|
90
|
+
"MICROLINK_API_KEY": "YOUR_MICROLINK_API_KEY"
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Cursor
|
|
98
|
+
|
|
99
|
+
Add to your Cursor MCP settings (`.cursor/mcp.json`):
|
|
100
|
+
|
|
101
|
+
```json
|
|
102
|
+
{
|
|
103
|
+
"mcpServers": {
|
|
104
|
+
"microlink": {
|
|
105
|
+
"command": "npx",
|
|
106
|
+
"args": ["-y", "@microlink/mcp"],
|
|
107
|
+
"env": {
|
|
108
|
+
"MICROLINK_API_KEY": "YOUR_MICROLINK_API_KEY"
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Usage
|
|
116
|
+
|
|
117
|
+
Once the server is configured, talk to your assistant in plain language. It picks the right tool and parameters for you:
|
|
118
|
+
|
|
119
|
+
- *"Take a full-page screenshot of https://example.com in dark mode."* → `microlink_screenshot`
|
|
120
|
+
- *"Generate a Letter-size PDF of https://example.com."* → `microlink_pdf`
|
|
121
|
+
- *"Get the title, description, and image for https://example.com."* → `microlink_meta`
|
|
122
|
+
- *"Convert https://news.ycombinator.com to Markdown."* → `microlink_markdown`
|
|
123
|
+
- *"Find the playable video in this YouTube link."* → `microlink_video`
|
|
124
|
+
- *"Run a Lighthouse performance audit on https://example.com."* → `microlink_insights`
|
|
125
|
+
- *"Scrape every article title from this page using the `.title` selector."* → `microlink_extract` with `data`
|
|
126
|
+
|
|
127
|
+
Tools can also be invoked directly. Every tool takes a `url` and returns `structuredContent` (see [Response shape](#response-shape)):
|
|
128
|
+
|
|
129
|
+
```json
|
|
130
|
+
{
|
|
131
|
+
"name": "microlink_screenshot",
|
|
132
|
+
"arguments": {
|
|
133
|
+
"url": "https://example.com",
|
|
134
|
+
"screenshot": { "fullPage": true, "type": "png" },
|
|
135
|
+
"colorScheme": "dark"
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Tools
|
|
141
|
+
|
|
142
|
+
### Capabilities at a glance
|
|
143
|
+
|
|
144
|
+
- `microlink_extract`: metadata extraction + custom scraping rules (`data`) + multi-capability composition in one call.
|
|
145
|
+
- `microlink_screenshot`: screenshot generation with element/full-page modes and browser controls.
|
|
146
|
+
- `microlink_pdf`: PDF generation with page/layout controls.
|
|
147
|
+
- `microlink_video`: playable video source extraction.
|
|
148
|
+
- `microlink_audio`: playable audio source extraction.
|
|
149
|
+
- `microlink_insights`: Lighthouse + technology detection.
|
|
150
|
+
- `microlink_meta`: normalized metadata extraction with include/exclude config.
|
|
151
|
+
- `microlink_palette`: image palette and contrast color extraction.
|
|
152
|
+
- `microlink_markdown`: URL to Markdown conversion.
|
|
153
|
+
- `microlink_text`: URL to plain text conversion.
|
|
154
|
+
- Cross-cutting request capabilities: device/viewport emulation, click/scroll actions, JS/CSS injection, modules, wait conditions, cache controls (`ttl`, `staleTtl`, `force`), retries/timeouts, media mode, headers/proxy, and endpoint/auth routing.
|
|
155
|
+
|
|
156
|
+
### Response shape
|
|
157
|
+
|
|
158
|
+
- All tools (`microlink_extract`, `microlink_screenshot`, `microlink_pdf`, `microlink_video`, `microlink_audio`, `microlink_insights`, `microlink_meta`, `microlink_palette`, `microlink_markdown`, `microlink_text`) return `structuredContent` with:
|
|
159
|
+
- `endpoint`, `requestUrl`, `finalUrl`, `statusCode`, `responseHeaders`, `microlink`
|
|
160
|
+
- `microlink` preserves Microlink API JSend payload (`status`, `data`, and error fields like `code`, `id`, `message`, `more`, `report`).
|
|
161
|
+
- `responseHeaders` includes key cache/rate headers (such as `x-cache-status`, `cf-cache-status`, `cache-control`, `x-rate-limit-*`) when present.
|
|
162
|
+
- MCP `isError` is set when transport fails or when `microlink.status !== "success"`.
|
|
163
|
+
|
|
164
|
+
Parameters labeled `PRO` in the official Microlink docs require a paid plan.
|
|
165
|
+
For compatibility with some MCP clients:
|
|
166
|
+
- boolean parameters also accept the strings `"true"` and `"false"` and are normalized before validation.
|
|
167
|
+
- parameters that accept objects also accept JSON stringified objects (for example, `screenshot: "{\"overlay\":{\"browser\":\"dark\"}}"`).
|
|
168
|
+
|
|
169
|
+
### `microlink_extract`
|
|
170
|
+
|
|
171
|
+
Extract structured metadata from any public URL. Returns normalized fields (`title`, `description`, `author`, `publisher`, `date`, `image`, `logo`, `lang`, `url`) plus any custom fields defined via CSS selectors.
|
|
172
|
+
|
|
173
|
+
Supports combining multiple features in a single request: screenshot, PDF, video, audio, insights, and palette.
|
|
174
|
+
For `screenshot`, `pdf`, and `insights`, use `true` for defaults or an object for options. Empty objects (`{}`) are treated as `true`.
|
|
175
|
+
|
|
176
|
+
**Key parameters:**
|
|
177
|
+
|
|
178
|
+
| Parameter | Type | Description |
|
|
179
|
+
|-----------|------|-------------|
|
|
180
|
+
| `url` | `string` | The URL to extract data from *(required)* |
|
|
181
|
+
| `apiKey` | `string` | Microlink API key *(optional; see [Authentication](#authentication))* |
|
|
182
|
+
| `data` | `object` | Custom CSS-selector extraction rules |
|
|
183
|
+
| `meta` | `boolean \| object` | Include/exclude normalized metadata fields |
|
|
184
|
+
| `embed` | `string` | Microlink embed mode |
|
|
185
|
+
| `iframe` | `boolean \| object` | Include iframe payload options |
|
|
186
|
+
| `function` | `string` | Custom Microlink function hook |
|
|
187
|
+
| `ping` | `boolean \| object` | Enable ping checks |
|
|
188
|
+
| `screenshot` | `boolean \| object` | Capture a screenshot |
|
|
189
|
+
| `pdf` | `boolean \| object` | Generate a PDF |
|
|
190
|
+
| `video` | `boolean` | Extract video source |
|
|
191
|
+
| `audio` | `boolean` | Extract audio source |
|
|
192
|
+
| `insights` | `boolean \| object` | Run Lighthouse / tech detection |
|
|
193
|
+
| `palette` | `boolean` | Extract color palette |
|
|
194
|
+
| `adblock` | `boolean` | Enable ad blocking |
|
|
195
|
+
| `animations` | `boolean` | Enable/disable animations |
|
|
196
|
+
| `device` | `string` | Emulate a device (e.g. `"iPhone 12"`) |
|
|
197
|
+
| `colorScheme` | `"light" \| "dark" \| "no-preference"` | Preferred color scheme |
|
|
198
|
+
| `viewport` | `object` | Custom viewport dimensions |
|
|
199
|
+
| `click` | `string \| string[]` | CSS selector(s) to click before capture |
|
|
200
|
+
| `scroll` | `string` | CSS selector to scroll to |
|
|
201
|
+
| `javascript` | `boolean` | Toggle JavaScript execution |
|
|
202
|
+
| `modules` | `string \| string[]` | Browser module(s) to inject |
|
|
203
|
+
| `scripts` | `string \| string[]` | JavaScript to inject |
|
|
204
|
+
| `styles` | `string \| string[]` | CSS to inject |
|
|
205
|
+
| `mediaType` | `"screen" \| "print"` | CSS media mode |
|
|
206
|
+
| `prerender` | `"auto" \| boolean` | Prerender strategy |
|
|
207
|
+
| `proxy` | `string \| object` | Proxy configuration *(PRO)* |
|
|
208
|
+
| `retry` | `number` | Retry count |
|
|
209
|
+
| `ttl` | `string \| number` | Cache TTL |
|
|
210
|
+
| `staleTtl` | `string \| number \| boolean` | Stale cache TTL policy *(PRO)* |
|
|
211
|
+
| `force` | `boolean` | Bypass cache |
|
|
212
|
+
| `timeout` | `string \| number` | Request timeout |
|
|
213
|
+
| `headers` | `object` | Custom HTTP headers *(PRO)* |
|
|
214
|
+
| `filename` | `string` | Preferred output filename *(PRO)* |
|
|
215
|
+
| `filter` | `string` | Response filter |
|
|
216
|
+
| `waitForSelector` | `string` | Wait for element before capture |
|
|
217
|
+
| `waitForTimeout` | `string \| number` | Wait an additional timeout before capture |
|
|
218
|
+
| `waitUntil` | `string \| string[]` | Navigation event(s): `auto`, `load`, `domcontentloaded`, `networkidle0`, `networkidle2` |
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
### `microlink_screenshot`
|
|
223
|
+
|
|
224
|
+
Capture a screenshot of any public URL and receive a permanent CDN asset URL (`data.screenshot.url`).
|
|
225
|
+
Set `screenshot` to `true` for defaults, or pass `screenshot: { ... }` for options. `screenshot: {}` is treated as `true`.
|
|
226
|
+
|
|
227
|
+
**Key parameters:**
|
|
228
|
+
|
|
229
|
+
| Parameter | Type | Description |
|
|
230
|
+
|-----------|------|-------------|
|
|
231
|
+
| `url` | `string` | The URL to screenshot *(required)* |
|
|
232
|
+
| `screenshot` | `boolean \| object` | Enable screenshot with defaults (`true`) or provide screenshot options (`{...}`); `{}` behaves as `true` |
|
|
233
|
+
| `screenshot.fullPage` | `boolean` | Capture the full scrollable page |
|
|
234
|
+
| `screenshot.element` | `string` | CSS selector to capture a specific element |
|
|
235
|
+
| `screenshot.type` | `"jpeg" \| "png"` | Output format (default: `"png"`) |
|
|
236
|
+
| `screenshot.omitBackground` | `boolean` | Transparent background |
|
|
237
|
+
| `screenshot.overlay` | `object` | Browser chrome overlay (`browser`: `"light"\|"dark"`, `background`: CSS color) |
|
|
238
|
+
| `screenshot.codeScheme` | `string` | Syntax-highlight theme for code pages (e.g. `"dracula"`) |
|
|
239
|
+
| `colorScheme` | `"light" \| "dark" \| "no-preference"` | Preferred color scheme |
|
|
240
|
+
| `device` | `string` | Device emulation |
|
|
241
|
+
| `viewport` | `object` | Custom viewport |
|
|
242
|
+
| `click` | `string \| string[]` | Click before capture |
|
|
243
|
+
| `scroll` | `string` | Scroll to element |
|
|
244
|
+
| `scripts` | `string \| string[]` | JavaScript to inject before capture |
|
|
245
|
+
| `styles` | `string \| string[]` | CSS to inject before capture |
|
|
246
|
+
| `modules` | `string \| string[]` | Browser module(s) to inject |
|
|
247
|
+
| `proxy` | `string \| object` | Proxy configuration *(PRO)* |
|
|
248
|
+
| `headers` | `object` | Custom HTTP headers *(PRO)* |
|
|
249
|
+
| `force` | `boolean` | Bypass cache |
|
|
250
|
+
| `ttl` | `string \| number` | Cache TTL |
|
|
251
|
+
| `staleTtl` | `string \| number \| boolean` | Stale cache TTL policy *(PRO)* |
|
|
252
|
+
| `retry` | `number` | Retry count |
|
|
253
|
+
| `timeout` | `string \| number` | Request timeout |
|
|
254
|
+
| `prerender` | `"auto" \| boolean` | Prerender strategy |
|
|
255
|
+
| `adblock` | `boolean` | Enable ad blocking |
|
|
256
|
+
| `animations` | `boolean` | Enable/disable animations |
|
|
257
|
+
| `javascript` | `boolean` | Toggle JavaScript execution |
|
|
258
|
+
| `mediaType` | `"screen" \| "print"` | CSS media mode |
|
|
259
|
+
| `filename` | `string` | Preferred output filename *(PRO)* |
|
|
260
|
+
| `filter` | `string` | Response filter |
|
|
261
|
+
| `waitForSelector` | `string` | Wait for element |
|
|
262
|
+
| `waitForTimeout` | `string \| number` | Wait an additional timeout before capture |
|
|
263
|
+
| `waitUntil` | `string \| string[]` | Navigation event(s): `auto`, `load`, `domcontentloaded`, `networkidle0`, `networkidle2` |
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
### `microlink_pdf`
|
|
268
|
+
|
|
269
|
+
Generate a PDF of any public URL and receive a permanent CDN asset URL (`data.pdf.url`).
|
|
270
|
+
Set `pdf` to `true` for defaults, or pass `pdf: { ... }` for options. `pdf: {}` is treated as `true`.
|
|
271
|
+
|
|
272
|
+
**Key parameters:**
|
|
273
|
+
|
|
274
|
+
| Parameter | Type | Description |
|
|
275
|
+
|-----------|------|-------------|
|
|
276
|
+
| `url` | `string` | The URL to convert *(required)* |
|
|
277
|
+
| `pdf` | `boolean \| object` | Enable PDF with defaults (`true`) or provide PDF options (`{...}`); `{}` behaves as `true` |
|
|
278
|
+
| `pdf.format` | `string` | Paper size: `"A4"` (default), `"Letter"`, `"Legal"`, `"Tabloid"`, `"Ledger"`, `"A0"`–`"A6"` |
|
|
279
|
+
| `pdf.landscape` | `boolean` | Landscape orientation |
|
|
280
|
+
| `pdf.margin` | `string \| object` | Page margins (e.g. `"0.35cm"` or `{top, bottom, left, right}`) |
|
|
281
|
+
| `pdf.scale` | `number` | Page scale factor (0.1–2.0) |
|
|
282
|
+
| `pdf.pageRanges` | `string` | Page range (e.g. `"1-5"`) |
|
|
283
|
+
| `pdf.width` / `pdf.height` | `string` | Custom dimensions (overrides `format`) |
|
|
284
|
+
| `scripts` | `string \| string[]` | JavaScript to inject before rendering |
|
|
285
|
+
| `styles` | `string \| string[]` | CSS to inject before rendering |
|
|
286
|
+
| `modules` | `string \| string[]` | Browser module(s) to inject |
|
|
287
|
+
| `proxy` | `string \| object` | Proxy configuration *(PRO)* |
|
|
288
|
+
| `headers` | `object` | Custom HTTP headers *(PRO)* |
|
|
289
|
+
| `force` | `boolean` | Bypass cache |
|
|
290
|
+
| `ttl` | `string \| number` | Cache TTL |
|
|
291
|
+
| `staleTtl` | `string \| number \| boolean` | Stale cache TTL policy *(PRO)* |
|
|
292
|
+
| `retry` | `number` | Retry count |
|
|
293
|
+
| `timeout` | `string \| number` | Request timeout |
|
|
294
|
+
| `prerender` | `"auto" \| boolean` | Prerender strategy |
|
|
295
|
+
| `adblock` | `boolean` | Enable ad blocking |
|
|
296
|
+
| `animations` | `boolean` | Enable/disable animations |
|
|
297
|
+
| `javascript` | `boolean` | Toggle JavaScript execution |
|
|
298
|
+
| `device` | `string` | Device emulation |
|
|
299
|
+
| `viewport` | `object` | Custom viewport |
|
|
300
|
+
| `filename` | `string` | Preferred output filename *(PRO)* |
|
|
301
|
+
| `filter` | `string` | Response filter |
|
|
302
|
+
| `mediaType` | `"screen" \| "print"` | CSS media type |
|
|
303
|
+
| `waitForSelector` | `string` | Wait for element |
|
|
304
|
+
| `waitForTimeout` | `string \| number` | Wait an additional timeout before rendering |
|
|
305
|
+
| `waitUntil` | `string \| string[]` | Navigation event(s): `auto`, `load`, `domcontentloaded`, `networkidle0`, `networkidle2` |
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
### `microlink_video`
|
|
310
|
+
|
|
311
|
+
Detect and extract a playable video source from any URL. Returns the video URL in `data.video.url` along with `type`, `duration`, `size`, `width`, `height`, `duration_pretty`, and `size_pretty`.
|
|
312
|
+
|
|
313
|
+
Supports YouTube, Vimeo, Twitter/X, TikTok, Instagram, Dailymotion, and hundreds of other platforms.
|
|
314
|
+
|
|
315
|
+
**Key parameters:**
|
|
316
|
+
|
|
317
|
+
| Parameter | Type | Description |
|
|
318
|
+
|-----------|------|-------------|
|
|
319
|
+
| `url` | `string` | The URL containing a video *(required)* |
|
|
320
|
+
| `proxy` | `string \| object` | Proxy for restricted platforms *(PRO)* |
|
|
321
|
+
| `meta` | `boolean \| object` | Include/suppress page metadata |
|
|
322
|
+
|
|
323
|
+
---
|
|
324
|
+
|
|
325
|
+
### `microlink_audio`
|
|
326
|
+
|
|
327
|
+
Detect and extract a playable audio source from any URL. Returns the audio URL in `data.audio.url` along with `type`, `duration`, `size`, `duration_pretty`, and `size_pretty`.
|
|
328
|
+
|
|
329
|
+
Supports SoundCloud, Spotify, Mixcloud, and other audio platforms.
|
|
330
|
+
|
|
331
|
+
**Key parameters:**
|
|
332
|
+
|
|
333
|
+
| Parameter | Type | Description |
|
|
334
|
+
|-----------|------|-------------|
|
|
335
|
+
| `url` | `string` | The URL containing audio *(required)* |
|
|
336
|
+
| `proxy` | `string \| object` | Proxy for restricted platforms *(PRO)* |
|
|
337
|
+
| `meta` | `boolean \| object` | Include/suppress page metadata |
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
### `microlink_insights`
|
|
342
|
+
|
|
343
|
+
Get web performance and technology-stack insights for any URL.
|
|
344
|
+
Set `insights` to `true` for defaults, or pass `insights: { ... }` for options. `insights: {}` is treated as `true`.
|
|
345
|
+
|
|
346
|
+
**Key parameters:**
|
|
347
|
+
|
|
348
|
+
| Parameter | Type | Description |
|
|
349
|
+
|-----------|------|-------------|
|
|
350
|
+
| `url` | `string` | The URL to analyze *(required)* |
|
|
351
|
+
| `insights` | `boolean \| object` | Enable default insights (`true`) or provide insights options (`{...}`); `{}` behaves as `true` |
|
|
352
|
+
| `insights.lighthouse` | `boolean \| object` | Run a Lighthouse audit |
|
|
353
|
+
| `insights.lighthouse.output` | `"json" \| "html" \| "csv"` | Report format (default: `"json"`) |
|
|
354
|
+
| `insights.lighthouse.preset` | `string` | Audit preset: `"default"`, `"desktop"`, `"perf"`, `"experimental"`, `"full"`, `"lr-desktop"`, `"lr-mobile"` |
|
|
355
|
+
| `insights.lighthouse.onlyCategories` | `string \| string[]` | Lighthouse category IDs (e.g. `["performance", "accessibility"]`) |
|
|
356
|
+
| `insights.technologies` | `boolean` | Detect tech stack via Wappalyzer |
|
|
357
|
+
|
|
358
|
+
---
|
|
359
|
+
|
|
360
|
+
### `microlink_meta`
|
|
361
|
+
|
|
362
|
+
Extract normalized metadata from any public URL. Returns: `title`, `description`, `lang`, `author`, `publisher`, `date`, `url`, `image` (with dimensions and file info), and `logo` (publisher favicon).
|
|
363
|
+
|
|
364
|
+
**Key parameters:**
|
|
365
|
+
|
|
366
|
+
| Parameter | Type | Description |
|
|
367
|
+
|-----------|------|-------------|
|
|
368
|
+
| `url` | `string` | The URL to inspect *(required)* |
|
|
369
|
+
| `meta` | `boolean \| object` | `false` to skip all metadata; object to include/exclude specific fields (e.g. `{ logo: true, title: true }`) |
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
### `microlink_palette`
|
|
374
|
+
|
|
375
|
+
Extract a color palette from images detected on any public URL. For each image returns: `palette` (hex colors from most to least dominant), `background_color` (optimal WCAG-contrast background), `color` (best overlay color), and `alternative_color`.
|
|
376
|
+
|
|
377
|
+
Color data is nested under each image field (e.g. `data.image.palette`). Useful for generating design tokens, theming, or accessibility checks.
|
|
378
|
+
|
|
379
|
+
**Key parameters:**
|
|
380
|
+
|
|
381
|
+
| Parameter | Type | Description |
|
|
382
|
+
|-----------|------|-------------|
|
|
383
|
+
| `url` | `string` | The URL to analyze *(required)* |
|
|
384
|
+
| `meta` | `boolean \| object` | Control metadata fields returned |
|
|
385
|
+
| `palette` | `boolean` | Enable palette extraction (default: `true`) |
|
|
386
|
+
|
|
387
|
+
---
|
|
388
|
+
|
|
389
|
+
### `microlink_markdown`
|
|
390
|
+
|
|
391
|
+
Convert any public URL to Markdown. Returns JSON output with Markdown content in `microlink.data.markdown`, useful for extracting readable content from web pages, articles, and documentation.
|
|
392
|
+
|
|
393
|
+
**Key parameters:**
|
|
394
|
+
|
|
395
|
+
| Parameter | Type | Description |
|
|
396
|
+
|-----------|------|-------------|
|
|
397
|
+
| `url` | `string` | The URL to convert *(required)* |
|
|
398
|
+
| `apiKey` | `string` | Microlink API key *(optional)* |
|
|
399
|
+
|
|
400
|
+
---
|
|
401
|
+
|
|
402
|
+
### `microlink_text`
|
|
403
|
+
|
|
404
|
+
Extract plain text from any public URL. Returns JSON output with plain text content in `microlink.data.text`.
|
|
405
|
+
|
|
406
|
+
**Key parameters:**
|
|
407
|
+
|
|
408
|
+
| Parameter | Type | Description |
|
|
409
|
+
|-----------|------|-------------|
|
|
410
|
+
| `url` | `string` | The URL to extract text from *(required)* |
|
|
411
|
+
| `apiKey` | `string` | Microlink API key *(optional)* |
|
|
412
|
+
|
|
413
|
+
---
|
|
414
|
+
|
|
415
|
+
## Authentication
|
|
416
|
+
|
|
417
|
+
Every tool accepts an optional `apiKey` parameter. The key is resolved from these sources in order of priority:
|
|
418
|
+
|
|
419
|
+
1. `apiKey` field in the tool input parameters
|
|
420
|
+
2. `Authorization: Bearer <key>` header from the MCP request
|
|
421
|
+
3. `x-api-key` header from the MCP request
|
|
422
|
+
4. `MICROLINK_API_KEY` environment variable
|
|
423
|
+
|
|
424
|
+
The `MICROLINK_API_KEY` environment variable is the recommended approach for most integrations. Get your key at [microlink.io](https://microlink.io).
|
|
425
|
+
|
|
426
|
+
If an API key is present, requests are sent to `https://pro.microlink.io`; otherwise they go to `https://api.microlink.io` (free endpoint).
|
|
427
|
+
|
|
428
|
+
When the free endpoint returns `429`, this MCP adds a clear hint in the tool error message: free daily quota reached (`50 requests/day`) and upgrade/API key guidance at [microlink.io/#pricing](https://microlink.io/#pricing).
|
|
429
|
+
|
|
430
|
+
## License
|
|
431
|
+
|
|
432
|
+
**microlink** © [Microlink](https://microlink.io), released under the [MIT](https://github.com/microlinkhq/mcp/blob/master/LICENSE.md) License.<br>
|
|
433
|
+
Authored and maintained by [Kiko Beats](https://kikobeats.com) with help from [contributors](https://github.com/microlinkhq/mcp/contributors).
|
|
434
|
+
|
|
435
|
+
> [microlink.io](https://microlink.io) · GitHub [microlinkhq](https://github.com/microlinkhq) · X [@microlinkhq](https://x.com/microlinkhq)
|
package/package.json
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@microlink/mcp",
|
|
3
|
+
"description": "MCP server for Microlink API",
|
|
4
|
+
"homepage": "https://github.com/microlinkhq/mcp",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"main": "./src/index.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./src/index.js"
|
|
9
|
+
},
|
|
10
|
+
"bin": {
|
|
11
|
+
"microlink-mcp": "./bin/microlink-mcp.js"
|
|
12
|
+
},
|
|
13
|
+
"contributors": [
|
|
14
|
+
{
|
|
15
|
+
"name": "Joseba",
|
|
16
|
+
"email": "josebalega@gmail.com"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"name": "Kiko Beats",
|
|
20
|
+
"email": "josefrancisco.verdu@gmail.com"
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "git+https://github.com/microlinkhq/mcp.git"
|
|
26
|
+
},
|
|
27
|
+
"bugs": {
|
|
28
|
+
"url": "https://github.com/microlinkhq/mcp/issues"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"api",
|
|
32
|
+
"mcp",
|
|
33
|
+
"microlink",
|
|
34
|
+
"model-context-protocol",
|
|
35
|
+
"scraping",
|
|
36
|
+
"screenshot",
|
|
37
|
+
"server"
|
|
38
|
+
],
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@microlink/mql": "~0.16.1",
|
|
41
|
+
"@modelcontextprotocol/sdk": "1.29.0",
|
|
42
|
+
"zod": "~4.4.3"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@commitlint/cli": "latest",
|
|
46
|
+
"@commitlint/config-conventional": "latest",
|
|
47
|
+
"ava": "latest",
|
|
48
|
+
"c8": "latest",
|
|
49
|
+
"ci-publish": "latest",
|
|
50
|
+
"conventional-changelog-cli": "latest",
|
|
51
|
+
"finepack": "latest",
|
|
52
|
+
"git-authors-cli": "latest",
|
|
53
|
+
"github-generate-release": "latest",
|
|
54
|
+
"nano-staged": "latest",
|
|
55
|
+
"simple-git-hooks": "latest",
|
|
56
|
+
"standard": "latest",
|
|
57
|
+
"standard-version": "latest"
|
|
58
|
+
},
|
|
59
|
+
"engines": {
|
|
60
|
+
"node": ">=20"
|
|
61
|
+
},
|
|
62
|
+
"files": [
|
|
63
|
+
"bin",
|
|
64
|
+
"scripts",
|
|
65
|
+
"src"
|
|
66
|
+
],
|
|
67
|
+
"license": "MIT",
|
|
68
|
+
"commitlint": {
|
|
69
|
+
"extends": [
|
|
70
|
+
"@commitlint/config-conventional"
|
|
71
|
+
]
|
|
72
|
+
},
|
|
73
|
+
"nano-staged": {
|
|
74
|
+
"*.js": [
|
|
75
|
+
"npx @kikobeats/prettier-standard",
|
|
76
|
+
"standard --fix"
|
|
77
|
+
],
|
|
78
|
+
"package.json": [
|
|
79
|
+
"finepack"
|
|
80
|
+
]
|
|
81
|
+
},
|
|
82
|
+
"publishConfig": {
|
|
83
|
+
"access": "public"
|
|
84
|
+
},
|
|
85
|
+
"simple-git-hooks": {
|
|
86
|
+
"commit-msg": "npx commitlint --edit",
|
|
87
|
+
"pre-commit": "npx nano-staged"
|
|
88
|
+
},
|
|
89
|
+
"type": "module",
|
|
90
|
+
"scripts": {
|
|
91
|
+
"contributors": "(git-authors-cli && finepack && git add package.json && git commit -m 'build: contributors' --no-verify) || true",
|
|
92
|
+
"postinstall": "node scripts/postinstall.js",
|
|
93
|
+
"postrelease": "pnpm release:tags && pnpm release:github && (ci-publish || pnpm publish --access=public)",
|
|
94
|
+
"release": "pnpm release:version && pnpm release:changelog && pnpm release:commit && pnpm release:tag",
|
|
95
|
+
"release:changelog": "conventional-changelog -p conventionalcommits -i CHANGELOG.md -s",
|
|
96
|
+
"release:commit": "git add package.json CHANGELOG.md && git commit -m \"chore(release): $(node -p \"require('./package.json').version\")\"",
|
|
97
|
+
"release:github": "github-generate-release",
|
|
98
|
+
"release:tag": "git tag -a v$(node -p \"require('./package.json').version\") -m \"v$(node -p \"require('./package.json').version\")\"",
|
|
99
|
+
"release:tags": "git push origin HEAD:master --follow-tags",
|
|
100
|
+
"release:version": "standard-version --skip.changelog --skip.commit --skip.tag",
|
|
101
|
+
"start": "node src/index.js",
|
|
102
|
+
"test": "node --test test/*.test.js"
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
const WIDTH = 74
|
|
2
|
+
|
|
3
|
+
const ANSI_PATTERN = /\u001b\[[0-9;]*m/g
|
|
4
|
+
const hasColor = process.stdout.isTTY && process.env.NO_COLOR === undefined
|
|
5
|
+
|
|
6
|
+
const colors = hasColor
|
|
7
|
+
? {
|
|
8
|
+
reset: '\x1b[0m',
|
|
9
|
+
bold: '\x1b[1m',
|
|
10
|
+
cyan: '\x1b[36m',
|
|
11
|
+
yellow: '\x1b[33m',
|
|
12
|
+
green: '\x1b[32m',
|
|
13
|
+
gray: '\x1b[90m'
|
|
14
|
+
}
|
|
15
|
+
: {
|
|
16
|
+
reset: '',
|
|
17
|
+
bold: '',
|
|
18
|
+
cyan: '',
|
|
19
|
+
yellow: '',
|
|
20
|
+
green: '',
|
|
21
|
+
gray: ''
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function stripAnsi (text) {
|
|
25
|
+
return text.replace(ANSI_PATTERN, '')
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function borderLine () {
|
|
29
|
+
return `${colors.cyan}+${'-'.repeat(WIDTH - 2)}+${colors.reset}`
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function contentLine (text = '') {
|
|
33
|
+
const visibleLength = stripAnsi(text).length
|
|
34
|
+
const padded = text + ' '.repeat(Math.max(0, WIDTH - 4 - visibleLength))
|
|
35
|
+
return `${colors.cyan}|${colors.reset} ${padded} ${colors.cyan}|${colors.reset}`
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const lines = [
|
|
39
|
+
borderLine(),
|
|
40
|
+
contentLine(`${colors.bold}MICROLINK MCP${colors.reset}`),
|
|
41
|
+
contentLine(),
|
|
42
|
+
contentLine(`${colors.bold}Free plan:${colors.reset} 50 requests/day included.`),
|
|
43
|
+
contentLine(`${colors.yellow}Need more or unlimited usage?${colors.reset}`),
|
|
44
|
+
contentLine(`Get an API key at ${colors.green}https://microlink.io/#pricing${colors.reset}`),
|
|
45
|
+
contentLine(`${colors.gray}Tip:${colors.reset} set MICROLINK_API_KEY in your MCP server env.`),
|
|
46
|
+
borderLine()
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
console.log(`\n${lines.join('\n')}\n`)
|
package/src/index.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
|
|
2
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
|
|
3
|
+
import { createRequire } from 'node:module'
|
|
4
|
+
import { pathToFileURL } from 'node:url'
|
|
5
|
+
|
|
6
|
+
import { tools } from './tools/index.js'
|
|
7
|
+
|
|
8
|
+
const require = createRequire(import.meta.url)
|
|
9
|
+
const { version: pkgVersion } = require('../package.json')
|
|
10
|
+
|
|
11
|
+
export function createMicrolinkServer ({ name = 'microlink-mcp-server', version = pkgVersion } = {}) {
|
|
12
|
+
const server = new McpServer({
|
|
13
|
+
name,
|
|
14
|
+
version
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
tools(server)
|
|
18
|
+
|
|
19
|
+
return server
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export async function startStdioServer ({
|
|
23
|
+
server = createMicrolinkServer(),
|
|
24
|
+
transport = new StdioServerTransport()
|
|
25
|
+
} = {}) {
|
|
26
|
+
await server.connect(transport)
|
|
27
|
+
return { server, transport }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export async function shutdown ({ server, signal }) {
|
|
31
|
+
if (signal) {
|
|
32
|
+
console.error(`Received ${signal}. Shutting down...`)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
await server.close()
|
|
37
|
+
} catch {
|
|
38
|
+
// No-op on shutdown.
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
process.exit(0)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export async function main () {
|
|
45
|
+
const { server } = await startStdioServer()
|
|
46
|
+
|
|
47
|
+
;['SIGINT', 'SIGTERM'].forEach(signal => {
|
|
48
|
+
process.on(signal, () => {
|
|
49
|
+
shutdown({ server, signal })
|
|
50
|
+
})
|
|
51
|
+
})
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const isEntryPoint =
|
|
55
|
+
process.argv[1] !== undefined &&
|
|
56
|
+
import.meta.url === pathToFileURL(process.argv[1]).href
|
|
57
|
+
|
|
58
|
+
if (isEntryPoint) {
|
|
59
|
+
main().catch(error => {
|
|
60
|
+
console.error('Failed to start Microlink stdio MCP server:', error)
|
|
61
|
+
process.exit(1)
|
|
62
|
+
})
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export default createMicrolinkServer
|