@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.
@@ -0,0 +1,110 @@
1
+ import { asToolResult, callMicrolink } from '../microlink-client.js'
2
+
3
+ function getHeaderValueCaseInsensitive (headers, headerName) {
4
+ if (!headers || typeof headers !== 'object') {
5
+ return undefined
6
+ }
7
+
8
+ const lookup = headerName.toLowerCase()
9
+
10
+ for (const [key, value] of Object.entries(headers)) {
11
+ if (key.toLowerCase() === lookup) {
12
+ if (Array.isArray(value)) {
13
+ return value[0]
14
+ }
15
+
16
+ return value
17
+ }
18
+ }
19
+
20
+ return undefined
21
+ }
22
+
23
+ function getApiKeyFromRequestHeaders (headers) {
24
+ const authorization = getHeaderValueCaseInsensitive(headers, 'authorization')
25
+
26
+ if (typeof authorization === 'string') {
27
+ const match = /^Bearer\s+(.+)$/i.exec(authorization.trim())
28
+ const bearerToken = match?.[1]?.trim()
29
+
30
+ if (bearerToken) {
31
+ return bearerToken
32
+ }
33
+ }
34
+
35
+ const xApiKey = getHeaderValueCaseInsensitive(headers, 'x-api-key')
36
+ if (typeof xApiKey === 'string') {
37
+ const token = xApiKey.trim()
38
+ if (token) {
39
+ return token
40
+ }
41
+ }
42
+
43
+ return undefined
44
+ }
45
+
46
+ export function register (server, name, description, inputSchema, forcedFlags) {
47
+ server.registerTool(
48
+ name,
49
+ {
50
+ description,
51
+ inputSchema
52
+ },
53
+ async (args, extra) => {
54
+ const parsedArgs = inputSchema.safeParse(args)
55
+ if (!parsedArgs.success) {
56
+ return {
57
+ isError: true,
58
+ content: [
59
+ {
60
+ type: 'text',
61
+ text: JSON.stringify(
62
+ {
63
+ message: 'Input validation failed.',
64
+ issues: parsedArgs.error.issues
65
+ },
66
+ null,
67
+ 2
68
+ )
69
+ }
70
+ ]
71
+ }
72
+ }
73
+
74
+ try {
75
+ const headerApiKey = getApiKeyFromRequestHeaders(extra?.requestInfo?.headers)
76
+ const params =
77
+ parsedArgs.data.apiKey || !headerApiKey
78
+ ? parsedArgs.data
79
+ : {
80
+ ...parsedArgs.data,
81
+ apiKey: headerApiKey
82
+ }
83
+
84
+ const result = await callMicrolink({
85
+ params,
86
+ forcedFlags
87
+ })
88
+
89
+ return asToolResult(result)
90
+ } catch (error) {
91
+ return {
92
+ isError: true,
93
+ content: [
94
+ {
95
+ type: 'text',
96
+ text: JSON.stringify(
97
+ {
98
+ message: 'Microlink request failed before receiving an API response.',
99
+ error: error instanceof Error ? error.message : String(error)
100
+ },
101
+ null,
102
+ 2
103
+ )
104
+ }
105
+ ]
106
+ }
107
+ }
108
+ }
109
+ )
110
+ }
@@ -0,0 +1,23 @@
1
+ import { screenshotInputSchema } from '../schemas.js'
2
+ import { register } from './register.js'
3
+
4
+ export function screenshot (server) {
5
+ register(
6
+ server,
7
+ 'microlink_screenshot',
8
+ [
9
+ 'Capture a screenshot of any public URL via Microlink and return a permanent CDN asset URL.',
10
+ 'The screenshot URL is in `data.screenshot.url`.',
11
+ 'Pass `screenshot: true` for defaults or `screenshot: { ... }` for options; `screenshot: {}` is treated as `true`.',
12
+ 'Use `screenshot.fullPage` to capture the entire scrollable page.',
13
+ 'Use `screenshot.element` (CSS selector) to capture a specific DOM element.',
14
+ 'Use `screenshot.type` to choose output format: "jpeg" (default "png").',
15
+ 'Use `screenshot.omitBackground` to remove the white background (useful with transparent PNGs).',
16
+ 'Use `screenshot.overlay` to add a browser chrome overlay with `browser` ("light"|"dark") and `background` (CSS color or gradient).',
17
+ 'Use `screenshot.codeScheme` to set the syntax-highlighting theme for code pages (e.g. "dracula", "atom-dark").',
18
+ 'Combine with `device`, `viewport`, `click`, `scroll`, `styles`, `scripts`, `modules`, `waitForSelector`, `waitForTimeout`, `waitUntil`, `colorScheme`, and `mediaType` for full browser control.'
19
+ ].join(' '),
20
+ screenshotInputSchema,
21
+ { screenshot: true, meta: false }
22
+ )
23
+ }
@@ -0,0 +1,16 @@
1
+ import { textInputSchema } from '../schemas.js'
2
+ import { register } from './register.js'
3
+
4
+ export function text (server) {
5
+ register(
6
+ server,
7
+ 'microlink_text',
8
+ [
9
+ 'Extract plain text from any public URL via Microlink.',
10
+ 'Returns JSON output with plain text content under `data.text`.',
11
+ 'Useful for getting raw text content from web pages.'
12
+ ].join(' '),
13
+ textInputSchema,
14
+ { data: { text: { attr: 'text' } }, meta: false }
15
+ )
16
+ }
@@ -0,0 +1,17 @@
1
+ import { videoInputSchema } from '../schemas.js'
2
+ import { register } from './register.js'
3
+
4
+ export function video (server) {
5
+ register(
6
+ server,
7
+ 'microlink_video',
8
+ [
9
+ 'Detect and extract playable video sources from any URL via Microlink.',
10
+ 'Works with YouTube, Vimeo, Twitter/X, TikTok, Instagram, Dailymotion, and hundreds of other platforms.',
11
+ 'The video URL is in `data.video.url`. Also returns `type`, `duration`, `size`, `width`, `height`, `duration_pretty`, and `size_pretty`.',
12
+ 'Combine with `proxy` for sites that require it, or with `meta` to suppress metadata extraction.'
13
+ ].join(' '),
14
+ videoInputSchema,
15
+ { video: true, meta: false }
16
+ )
17
+ }