@microlink/mcp 1.0.1 → 1.1.1

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,16 @@
1
+ import { imagesInputSchema } from '../schemas.js'
2
+ import { register, urlMethod } from './register.js'
3
+
4
+ export function images (server) {
5
+ register(
6
+ server,
7
+ 'microlink_images',
8
+ [
9
+ 'Collect every image (`<img src>`) from any public URL via Microlink.',
10
+ 'Returns an array of absolute, deduped image URLs. Pass `selectorAll` to scope the collection.',
11
+ 'Mirrors the `microlink.images(url)` library method.'
12
+ ].join(' '),
13
+ imagesInputSchema,
14
+ urlMethod('images')
15
+ )
16
+ }
@@ -1,23 +1,43 @@
1
1
  import { audio } from './audio.js'
2
+ import { audios } from './audios.js'
3
+ import { emails } from './emails.js'
4
+ import { embed } from './embed.js'
2
5
  import { extract } from './extract.js'
3
- import { insights } from './insights.js'
6
+ import { fn } from './function.js'
7
+ import { html } from './html.js'
8
+ import { images } from './images.js'
9
+ import { lighthouse } from './lighthouse.js'
10
+ import { links } from './links.js'
11
+ import { logo } from './logo.js'
4
12
  import { markdown } from './markdown.js'
5
- import { meta } from './meta.js'
6
- import { palette } from './palette.js'
13
+ import { metadata } from './metadata.js'
7
14
  import { pdf } from './pdf.js'
8
15
  import { screenshot } from './screenshot.js'
16
+ import { search } from './search.js'
17
+ import { technologies } from './technologies.js'
9
18
  import { text } from './text.js'
10
19
  import { video } from './video.js'
20
+ import { videos } from './videos.js'
11
21
 
12
22
  export function tools (server) {
13
- extract(server)
23
+ metadata(server)
24
+ logo(server)
25
+ markdown(server)
26
+ html(server)
27
+ text(server)
14
28
  screenshot(server)
15
29
  pdf(server)
30
+ embed(server)
16
31
  video(server)
17
32
  audio(server)
18
- insights(server)
19
- meta(server)
20
- palette(server)
21
- markdown(server)
22
- text(server)
33
+ links(server)
34
+ images(server)
35
+ videos(server)
36
+ audios(server)
37
+ emails(server)
38
+ technologies(server)
39
+ lighthouse(server)
40
+ search(server)
41
+ fn(server)
42
+ extract(server)
23
43
  }
@@ -0,0 +1,16 @@
1
+ import { lighthouseInputSchema } from '../schemas.js'
2
+ import { register, urlMethod } from './register.js'
3
+
4
+ export function lighthouse (server) {
5
+ register(
6
+ server,
7
+ 'microlink_lighthouse',
8
+ [
9
+ 'Run a Google Lighthouse audit (performance, accessibility, best-practices, SEO) for any public URL via Microlink.',
10
+ 'Returns the Lighthouse report.',
11
+ 'Mirrors the `microlink.lighthouse(url)` library method.'
12
+ ].join(' '),
13
+ lighthouseInputSchema,
14
+ urlMethod('lighthouse')
15
+ )
16
+ }
@@ -0,0 +1,16 @@
1
+ import { linksInputSchema } from '../schemas.js'
2
+ import { register, urlMethod } from './register.js'
3
+
4
+ export function links (server) {
5
+ register(
6
+ server,
7
+ 'microlink_links',
8
+ [
9
+ 'Collect every link (`<a href>`) from any public URL via Microlink.',
10
+ 'Returns an array of absolute, deduped URLs. Pass `selectorAll` to scope the collection.',
11
+ 'Mirrors the `microlink.links(url)` library method.'
12
+ ].join(' '),
13
+ linksInputSchema,
14
+ urlMethod('links')
15
+ )
16
+ }
@@ -0,0 +1,17 @@
1
+ import { logoInputSchema } from '../schemas.js'
2
+ import { register, urlMethod } from './register.js'
3
+
4
+ export function logo (server) {
5
+ register(
6
+ server,
7
+ 'microlink_logo',
8
+ [
9
+ 'Extract the brand logo of any public URL via Microlink.',
10
+ 'Returns the logo asset: `url`, `type`, `width`, `height`, `size`, and `size_pretty`.',
11
+ 'Pass `square: true` to prefer a square (icon-shaped) variant.',
12
+ 'Mirrors the `microlink.logo(url, { square })` library method.'
13
+ ].join(' '),
14
+ logoInputSchema,
15
+ urlMethod('logo')
16
+ )
17
+ }
@@ -1,5 +1,5 @@
1
1
  import { markdownInputSchema } from '../schemas.js'
2
- import { register } from './register.js'
2
+ import { register, urlMethod } from './register.js'
3
3
 
4
4
  export function markdown (server) {
5
5
  register(
@@ -7,10 +7,10 @@ export function markdown (server) {
7
7
  'microlink_markdown',
8
8
  [
9
9
  'Convert any public URL to Markdown via Microlink.',
10
- 'Returns JSON output with Markdown content under `data.markdown`.',
11
- 'Useful for extracting readable content from web pages, articles, and documentation.'
10
+ 'Returns the page content as a Markdown string. Pass `selector` to scope it to part of the page.',
11
+ 'Mirrors the `microlink.markdown(url)` library method.'
12
12
  ].join(' '),
13
13
  markdownInputSchema,
14
- { data: { markdown: { attr: 'markdown' } }, meta: false }
14
+ urlMethod('markdown')
15
15
  )
16
16
  }
@@ -0,0 +1,17 @@
1
+ import { metadataInputSchema } from '../schemas.js'
2
+ import { register, urlMethod } from './register.js'
3
+
4
+ export function metadata (server) {
5
+ register(
6
+ server,
7
+ 'microlink_metadata',
8
+ [
9
+ 'Extract normalized metadata from any public URL via Microlink.',
10
+ 'Returns the metadata object: `title`, `description`, `lang`, `author`, `publisher`, `date`, `url`, `image` (with dimensions and file info), and `logo`.',
11
+ 'Pass `meta: false` to skip extraction, or a config object to include/exclude fields (e.g. `{ logo: true, title: true }`).',
12
+ 'Mirrors the `microlink.metadata(url)` library method.'
13
+ ].join(' '),
14
+ metadataInputSchema,
15
+ urlMethod('metadata')
16
+ )
17
+ }
package/src/tools/pdf.js CHANGED
@@ -1,23 +1,18 @@
1
1
  import { pdfInputSchema } from '../schemas.js'
2
- import { register } from './register.js'
2
+ import { capabilityMethod, register } from './register.js'
3
3
 
4
4
  export function pdf (server) {
5
5
  register(
6
6
  server,
7
7
  'microlink_pdf',
8
8
  [
9
- 'Generate a PDF of any public URL via Microlink and return a permanent CDN asset URL.',
10
- 'The PDF URL is in `data.pdf.url`.',
9
+ 'Generate a PDF of any public URL via Microlink and return the asset object (`url`, `type`, `size`, ...) with a permanent CDN URL.',
11
10
  'Pass `pdf: true` for defaults or `pdf: { ... }` for options; `pdf: {}` is treated as `true`.',
12
- 'Use `pdf.format` to set paper size: "A4" (default), "Letter", "Legal", "Tabloid", "Ledger", "A0"–"A6".',
13
- 'Use `pdf.landscape` to switch to landscape orientation.',
14
- 'Use `pdf.margin` to set page margins as a string ("0.35cm") or object with top/bottom/left/right.',
15
- 'Use `pdf.scale` to scale the page (0.1–2.0).',
16
- 'Use `pdf.pageRanges` to select specific pages (e.g. "1-5").',
17
- 'Use `pdf.width` and `pdf.height` for custom dimensions (overrides format).',
18
- 'Combine with `styles`, `scripts`, `modules`, `mediaType`, `waitForSelector`, and `waitUntil` for full control.'
11
+ 'Use `pdf.format` ("A4" default, "Letter", "Legal", ...), `pdf.landscape`, `pdf.margin` (string or top/bottom/left/right object), `pdf.scale` (0.1-2.0), `pdf.pageRanges` ("1-5"), or `pdf.width`/`pdf.height`.',
12
+ 'Combine with `styles`, `scripts`, `modules`, `mediaType`, `waitForSelector`, and `waitUntil` for full control.',
13
+ 'Mirrors the `microlink.pdf(url, options)` library method.'
19
14
  ].join(' '),
20
15
  pdfInputSchema,
21
- { pdf: true, meta: false }
16
+ capabilityMethod('pdf', 'pdf')
22
17
  )
23
18
  }
@@ -1,4 +1,9 @@
1
- import { asToolResult, callMicrolink } from '../microlink-client.js'
1
+ import {
2
+ asErrorResult,
3
+ asToolResult,
4
+ client,
5
+ resolveApiKey
6
+ } from '../microlink-client.js'
2
7
 
3
8
  function getHeaderValueCaseInsensitive (headers, headerName) {
4
9
  if (!headers || typeof headers !== 'object') {
@@ -9,11 +14,7 @@ function getHeaderValueCaseInsensitive (headers, headerName) {
9
14
 
10
15
  for (const [key, value] of Object.entries(headers)) {
11
16
  if (key.toLowerCase() === lookup) {
12
- if (Array.isArray(value)) {
13
- return value[0]
14
- }
15
-
16
- return value
17
+ return Array.isArray(value) ? value[0] : value
17
18
  }
18
19
  }
19
20
 
@@ -26,33 +27,44 @@ function getApiKeyFromRequestHeaders (headers) {
26
27
  if (typeof authorization === 'string') {
27
28
  const match = /^Bearer\s+(.+)$/i.exec(authorization.trim())
28
29
  const bearerToken = match?.[1]?.trim()
29
-
30
- if (bearerToken) {
31
- return bearerToken
32
- }
30
+ if (bearerToken) return bearerToken
33
31
  }
34
32
 
35
33
  const xApiKey = getHeaderValueCaseInsensitive(headers, 'x-api-key')
36
34
  if (typeof xApiKey === 'string') {
37
35
  const token = xApiKey.trim()
38
- if (token) {
39
- return token
40
- }
36
+ if (token) return token
41
37
  }
42
38
 
43
39
  return undefined
44
40
  }
45
41
 
46
- export function register (server, name, description, inputSchema, forcedFlags) {
42
+ // Common shape: a tool that maps to `client.<method>(url, options)`.
43
+ export function urlMethod (method) {
44
+ return (client, { url, ...options }) => client[method](url, options)
45
+ }
46
+
47
+ // Capability tools nest their config under a key (e.g. `screenshot: { ... }`)
48
+ // to match the Microlink API surface; the library takes a flat options bag, so
49
+ // flatten the config back out before calling it.
50
+ export function capabilityMethod (method, key) {
51
+ return (client, { url, [key]: config, ...rest }) => {
52
+ const options =
53
+ config !== null && typeof config === 'object'
54
+ ? { ...config, ...rest }
55
+ : rest
56
+ return client[method](url, options)
57
+ }
58
+ }
59
+
60
+ export function register (server, name, description, inputSchema, invoke) {
47
61
  server.registerTool(
48
62
  name,
49
- {
50
- description,
51
- inputSchema
52
- },
63
+ { description, inputSchema },
53
64
  async (args, extra) => {
54
- const parsedArgs = inputSchema.safeParse(args)
55
- if (!parsedArgs.success) {
65
+ const parsed = inputSchema.safeParse(args)
66
+
67
+ if (!parsed.success) {
56
68
  return {
57
69
  isError: true,
58
70
  content: [
@@ -61,7 +73,7 @@ export function register (server, name, description, inputSchema, forcedFlags) {
61
73
  text: JSON.stringify(
62
74
  {
63
75
  message: 'Input validation failed.',
64
- issues: parsedArgs.error.issues
76
+ issues: parsed.error.issues
65
77
  },
66
78
  null,
67
79
  2
@@ -72,38 +84,16 @@ export function register (server, name, description, inputSchema, forcedFlags) {
72
84
  }
73
85
 
74
86
  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
- })
87
+ const headerApiKey = getApiKeyFromRequestHeaders(
88
+ extra?.requestInfo?.headers
89
+ )
90
+ const apiKey = resolveApiKey(parsed.data.apiKey, headerApiKey)
91
+ const params = apiKey ? { ...parsed.data, apiKey } : parsed.data
88
92
 
89
- return asToolResult(result)
93
+ const value = await invoke(client, params)
94
+ return asToolResult(value)
90
95
  } 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
- }
96
+ return asErrorResult(error)
107
97
  }
108
98
  }
109
99
  )
@@ -1,23 +1,20 @@
1
1
  import { screenshotInputSchema } from '../schemas.js'
2
- import { register } from './register.js'
2
+ import { capabilityMethod, register } from './register.js'
3
3
 
4
4
  export function screenshot (server) {
5
5
  register(
6
6
  server,
7
7
  'microlink_screenshot',
8
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`.',
9
+ 'Capture a screenshot of any public URL via Microlink and return the asset object (`url`, `type`, `width`, `height`, `size`, ...) with a permanent CDN URL.',
11
10
  '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.'
11
+ 'Use `screenshot.fullPage` to capture the whole scrollable page.',
12
+ 'Use `screenshot.animated` to capture an animated screenshot (GIF/MP4) instead of a still image.',
13
+ 'Use `screenshot.element` (CSS selector) to capture a specific element, `screenshot.type` for format ("jpeg", default "png"), `screenshot.omitBackground` for transparency, `screenshot.overlay` for browser chrome, `screenshot.palette` to also extract dominant colors, or `screenshot.codeScheme` to theme code pages.',
14
+ 'Combine with `device`, `viewport`, `click`, `scroll`, `styles`, `scripts`, `modules`, `waitForSelector`, `waitForTimeout`, `waitUntil`, `colorScheme`, and `mediaType`.',
15
+ 'Mirrors the `microlink.screenshot(url, options)` library method.'
19
16
  ].join(' '),
20
17
  screenshotInputSchema,
21
- { screenshot: true, meta: false }
18
+ capabilityMethod('screenshot', 'screenshot')
22
19
  )
23
20
  }
@@ -0,0 +1,17 @@
1
+ import { searchInputSchema } from '../schemas.js'
2
+ import { register } from './register.js'
3
+
4
+ export function search (server) {
5
+ register(
6
+ server,
7
+ 'microlink_search',
8
+ [
9
+ 'Search Google and get structured results via Microlink (requires an API key).',
10
+ 'Returns `results` (title, url, description) plus `knowledgeGraph`, `peopleAlsoAsk`, and `relatedSearches` when available.',
11
+ 'Use `type` for a vertical ("search" default, "news", "images", "videos", "places", "maps", "shopping", "scholar", "patents", "autocomplete"), and `limit` / `location` / `period` to refine.',
12
+ 'Google search operators (`site:`, `filetype:`, quotes, ...) work as-is. Mirrors the `microlink.search(query)` library method.'
13
+ ].join(' '),
14
+ searchInputSchema,
15
+ (client, { query, ...options }) => client.search(query, options)
16
+ )
17
+ }
@@ -0,0 +1,16 @@
1
+ import { technologiesInputSchema } from '../schemas.js'
2
+ import { register, urlMethod } from './register.js'
3
+
4
+ export function technologies (server) {
5
+ register(
6
+ server,
7
+ 'microlink_technologies',
8
+ [
9
+ 'Detect the technology stack behind any public URL via Microlink (Wappalyzer).',
10
+ 'Returns an array of detected technologies (frameworks, CDNs, analytics, e-commerce, etc.).',
11
+ 'Mirrors the `microlink.technologies(url)` library method.'
12
+ ].join(' '),
13
+ technologiesInputSchema,
14
+ urlMethod('technologies')
15
+ )
16
+ }
package/src/tools/text.js CHANGED
@@ -1,16 +1,16 @@
1
1
  import { textInputSchema } from '../schemas.js'
2
- import { register } from './register.js'
2
+ import { register, urlMethod } from './register.js'
3
3
 
4
4
  export function text (server) {
5
5
  register(
6
6
  server,
7
7
  'microlink_text',
8
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.'
9
+ 'Extract the plain text of any public URL via Microlink.',
10
+ 'Returns the readable page text as a string. Pass `selector` to scope it to part of the page.',
11
+ 'Mirrors the `microlink.text(url)` library method.'
12
12
  ].join(' '),
13
13
  textInputSchema,
14
- { data: { text: { attr: 'text' } }, meta: false }
14
+ urlMethod('text')
15
15
  )
16
16
  }
@@ -1,17 +1,17 @@
1
1
  import { videoInputSchema } from '../schemas.js'
2
- import { register } from './register.js'
2
+ import { register, urlMethod } from './register.js'
3
3
 
4
4
  export function video (server) {
5
5
  register(
6
6
  server,
7
7
  'microlink_video',
8
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.'
9
+ 'Detect the primary playable video of any public URL via Microlink.',
10
+ 'Works with YouTube, Vimeo, Twitter/X, TikTok, Instagram, and hundreds of other platforms.',
11
+ 'Returns the video asset: `url`, `type`, `duration`, `size`, `width`, `height`, `duration_pretty`, `size_pretty`.',
12
+ 'Mirrors the `microlink.video(url)` library method. For every video on the page, use `microlink_videos`.'
13
13
  ].join(' '),
14
14
  videoInputSchema,
15
- { video: true, meta: false }
15
+ urlMethod('video')
16
16
  )
17
17
  }
@@ -0,0 +1,16 @@
1
+ import { videosInputSchema } from '../schemas.js'
2
+ import { register, urlMethod } from './register.js'
3
+
4
+ export function videos (server) {
5
+ register(
6
+ server,
7
+ 'microlink_videos',
8
+ [
9
+ 'Collect every video source (`<video>`, `<source>`) from any public URL via Microlink.',
10
+ 'Returns an array of absolute, deduped video URLs.',
11
+ 'Mirrors the `microlink.videos(url)` library method. For the primary playable video, use `microlink_video`.'
12
+ ].join(' '),
13
+ videosInputSchema,
14
+ urlMethod('videos')
15
+ )
16
+ }
@@ -1,21 +0,0 @@
1
- import { insightsInputSchema } from '../schemas.js'
2
- import { register } from './register.js'
3
-
4
- export function insights (server) {
5
- register(
6
- server,
7
- 'microlink_insights',
8
- [
9
- 'Get web performance and technology-stack insights for any URL via Microlink.',
10
- 'Pass `insights: true` for defaults or `insights: { ... }` for options; `insights: {}` is treated as `true`.',
11
- 'Use `insights.lighthouse` (true or config object) for a Lighthouse performance audit.',
12
- ' - `insights.lighthouse.output`: report format — "json" (default), "html", or "csv".',
13
- ' - `insights.lighthouse.preset`: "default", "desktop", "perf", "experimental", "full", "lr-desktop", "lr-mobile".',
14
- ' - `insights.lighthouse.onlyCategories`: array of category IDs to include (e.g. ["performance", "accessibility"]).',
15
- 'Use `insights.technologies` (true) to detect the technology stack (frameworks, CDNs, analytics, etc.) via Wappalyzer.',
16
- 'Both can be combined in a single request.'
17
- ].join(' '),
18
- insightsInputSchema,
19
- { insights: true, meta: false }
20
- )
21
- }
package/src/tools/meta.js DELETED
@@ -1,17 +0,0 @@
1
- import { metaInputSchema } from '../schemas.js'
2
- import { register } from './register.js'
3
-
4
- export function meta (server) {
5
- register(
6
- server,
7
- 'microlink_meta',
8
- [
9
- 'Extract normalized metadata from any public URL via Microlink.',
10
- 'Returns: `title`, `description`, `lang`, `author`, `publisher`, `date`, `url`, `image` (with dimensions and file info), and `logo` (publisher favicon).',
11
- 'Pass `meta: false` to skip metadata extraction entirely — useful when you only need a screenshot or video and want a faster response.',
12
- 'Pass a config object to include or exclude specific fields: `{ logo: true, title: true }` returns only those fields; `{ image: false }` returns everything except image.'
13
- ].join(' '),
14
- metaInputSchema,
15
- { meta: true }
16
- )
17
- }
@@ -1,17 +0,0 @@
1
- import { paletteInputSchema } from '../schemas.js'
2
- import { register } from './register.js'
3
-
4
- export function palette (server) {
5
- register(
6
- server,
7
- 'microlink_palette',
8
- [
9
- 'Extract a color palette from images detected on any public URL via Microlink.',
10
- 'For each image, returns: `palette` (hex colors from most to least dominant), `background_color` (optimal WCAG-contrast background), `color` (best overlay color for the background), and `alternative_color` (secondary overlay color).',
11
- 'Color data is nested under each image field in the response (e.g. `data.image.palette`, `data.image.background_color`).',
12
- 'Useful for generating design tokens, theming, or accessibility checks from real page images.'
13
- ].join(' '),
14
- paletteInputSchema,
15
- { palette: true, meta: true }
16
- )
17
- }