From e40ce25e3073c35190fe8bc636aabfe2c48b31fc Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 26 Jun 2026 16:47:08 +0000 Subject: [PATCH 1/3] feat(api): api update --- .stats.yml | 4 +- packages/mcp-server/src/local-docs-search.ts | 24 +- src/resources/web.ts | 841 +++++++++++++++++++ tests/api-resources/web.test.ts | 4 + 4 files changed, 861 insertions(+), 12 deletions(-) diff --git a/.stats.yml b/.stats.yml index e34b116..24c57ba 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 25 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/context-dev/context.dev-4903d5902cec6a80f42b9adaa9cf0defa9805ff22d7ae96970d209a4f867e195.yml -openapi_spec_hash: 1097891c23530dfe0155f23170daf973 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/context-dev/context.dev-00c5b8f1ebfe212bc8fb46204f5c05507630afa55b10f77e3a43c66d21edbb77.yml +openapi_spec_hash: 8bf4489b9bce0e52a89480109ffc5257 config_hash: c7b0cdaba3b9797b77efd89e1754d803 diff --git a/packages/mcp-server/src/local-docs-search.ts b/packages/mcp-server/src/local-docs-search.ts index f734e52..8d22e9b 100644 --- a/packages/mcp-server/src/local-docs-search.ts +++ b/packages/mcp-server/src/local-docs-search.ts @@ -60,6 +60,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ qualified: 'client.web.webScrapeHTML', params: [ 'url: string;', + 'country?: string;', 'excludeSelectors?: string[];', 'headers?: object;', 'includeFrames?: boolean;', @@ -73,7 +74,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ response: "{ html: string; metadata: { finalUrl: string; sourceUrl: string; additionalMeta?: object; alternates?: { href: string; hreflang?: string; title?: string; type?: string; }[]; author?: string; canonicalUrl?: string; description?: string; favicon?: string; image?: string; jsonLd?: object[]; keywords?: string[]; language?: string; modifiedTime?: string; openGraph?: object; publishedTime?: string; robots?: string; siteName?: string; title?: string; twitter?: object; }; success: true; type: 'html' | 'xml' | 'json' | 'text' | 'csv' | 'markdown' | 'svg' | 'pdf' | 'docx' | 'doc'; url: string; key_metadata?: { credits_consumed: number; credits_remaining: number; }; }", markdown: - "## web_scrape_html\n\n`client.web.webScrapeHTML(url: string, excludeSelectors?: string[], headers?: object, includeFrames?: boolean, includeSelectors?: string[], maxAgeMs?: number, pdf?: { end?: number; shouldParse?: boolean; start?: number; }, timeoutMS?: number, useMainContentOnly?: boolean, waitForMs?: number): { html: string; metadata: object; success: true; type: 'html' | 'xml' | 'json' | 'text' | 'csv' | 'markdown' | 'svg' | 'pdf' | 'docx' | 'doc'; url: string; key_metadata?: object; }`\n\n**get** `/web/scrape/html`\n\nScrapes the given URL and returns the raw HTML content of the page.\n\n### Parameters\n\n- `url: string`\n Full URL to scrape (must include http:// or https:// protocol)\n\n- `excludeSelectors?: string[]`\n CSS selectors to remove from the result. Applied after includeSelectors. Exclusion takes precedence: an element matching both is removed. Examples: \"nav\", \"footer\", \".ad-banner\", \"[aria-hidden=true]\".\n\n- `headers?: object`\n Optional outbound HTTP headers forwarded only to the target URL, sent as deep-object query params such as headers[X-Custom]=value. When provided, caching is bypassed: the result is neither read from nor written to cache.\n\n- `includeFrames?: boolean`\n When true, iframes are rendered inline into the returned HTML.\n\n- `includeSelectors?: string[]`\n CSS selectors. When provided, only matching subtrees (and their descendants) are kept and everything else is dropped. When omitted, the entire document is kept. Examples: \"article.main\", \"#content\", \"[role=main]\".\n\n- `maxAgeMs?: number`\n Return a cached result if a prior scrape for the same parameters exists and is younger than this many milliseconds. Defaults to 1 day (86400000 ms) when omitted. Max is 30 days (2592000000 ms). Set to 0 to always scrape fresh.\n\n- `pdf?: { end?: number; shouldParse?: boolean; start?: number; }`\n PDF parsing controls. Use start/end to limit text extraction and OCR to an inclusive 1-based page range.\n - `end?: number`\n Last 1-based PDF page to parse. When omitted, parsing ends at the last page. Must be greater than or equal to start when both are provided.\n - `shouldParse?: boolean`\n When true, PDF URLs are fetched and parsed. When false, PDF URLs are skipped and a 400 WEBSITE_ACCESS_ERROR is returned.\n - `start?: number`\n First 1-based PDF page to parse. When omitted, parsing starts at the first page.\n\n- `timeoutMS?: number`\n Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed value is 300000ms (5 minutes).\n\n- `useMainContentOnly?: boolean`\n When true, return only the page's main content in the HTML response, excluding headers, footers, sidebars, and navigation when detectable.\n\n- `waitForMs?: number`\n Optional browser wait time in milliseconds after initial page load. Min: 0. Max: 30000 (30 seconds). \n\n### Returns\n\n- `{ html: string; metadata: { finalUrl: string; sourceUrl: string; additionalMeta?: object; alternates?: { href: string; hreflang?: string; title?: string; type?: string; }[]; author?: string; canonicalUrl?: string; description?: string; favicon?: string; image?: string; jsonLd?: object[]; keywords?: string[]; language?: string; modifiedTime?: string; openGraph?: object; publishedTime?: string; robots?: string; siteName?: string; title?: string; twitter?: object; }; success: true; type: 'html' | 'xml' | 'json' | 'text' | 'csv' | 'markdown' | 'svg' | 'pdf' | 'docx' | 'doc'; url: string; key_metadata?: { credits_consumed: number; credits_remaining: number; }; }`\n\n - `html: string`\n - `metadata: { finalUrl: string; sourceUrl: string; additionalMeta?: object; alternates?: { href: string; hreflang?: string; title?: string; type?: string; }[]; author?: string; canonicalUrl?: string; description?: string; favicon?: string; image?: string; jsonLd?: object[]; keywords?: string[]; language?: string; modifiedTime?: string; openGraph?: object; publishedTime?: string; robots?: string; siteName?: string; title?: string; twitter?: object; }`\n - `success: true`\n - `type: 'html' | 'xml' | 'json' | 'text' | 'csv' | 'markdown' | 'svg' | 'pdf' | 'docx' | 'doc'`\n - `url: string`\n - `key_metadata?: { credits_consumed: number; credits_remaining: number; }`\n\n### Example\n\n```typescript\nimport ContextDev from 'context.dev';\n\nconst client = new ContextDev();\n\nconst response = await client.web.webScrapeHTML({ url: 'https://example.com' });\n\nconsole.log(response);\n```", + "## web_scrape_html\n\n`client.web.webScrapeHTML(url: string, country?: string, excludeSelectors?: string[], headers?: object, includeFrames?: boolean, includeSelectors?: string[], maxAgeMs?: number, pdf?: { end?: number; shouldParse?: boolean; start?: number; }, timeoutMS?: number, useMainContentOnly?: boolean, waitForMs?: number): { html: string; metadata: object; success: true; type: 'html' | 'xml' | 'json' | 'text' | 'csv' | 'markdown' | 'svg' | 'pdf' | 'docx' | 'doc'; url: string; key_metadata?: object; }`\n\n**get** `/web/scrape/html`\n\nScrapes the given URL and returns the raw HTML content of the page.\n\n### Parameters\n\n- `url: string`\n Full URL to scrape (must include http:// or https:// protocol)\n\n- `country?: string`\n Two-letter ISO 3166-1 alpha-2 country code for the website request location. When provided, Context.dev fetches the target page from that country.\n\n- `excludeSelectors?: string[]`\n CSS selectors to remove from the result. Applied after includeSelectors. Exclusion takes precedence: an element matching both is removed. Examples: \"nav\", \"footer\", \".ad-banner\", \"[aria-hidden=true]\".\n\n- `headers?: object`\n Optional outbound HTTP headers forwarded only to the target URL, sent as deep-object query params such as headers[X-Custom]=value. When provided, caching is bypassed: the result is neither read from nor written to cache.\n\n- `includeFrames?: boolean`\n When true, iframes are rendered inline into the returned HTML.\n\n- `includeSelectors?: string[]`\n CSS selectors. When provided, only matching subtrees (and their descendants) are kept and everything else is dropped. When omitted, the entire document is kept. Examples: \"article.main\", \"#content\", \"[role=main]\".\n\n- `maxAgeMs?: number`\n Return a cached result if a prior scrape for the same parameters exists and is younger than this many milliseconds. Defaults to 1 day (86400000 ms) when omitted. Max is 30 days (2592000000 ms). Set to 0 to always scrape fresh.\n\n- `pdf?: { end?: number; shouldParse?: boolean; start?: number; }`\n PDF parsing controls. Use start/end to limit text extraction and OCR to an inclusive 1-based page range.\n - `end?: number`\n Last 1-based PDF page to parse. When omitted, parsing ends at the last page. Must be greater than or equal to start when both are provided.\n - `shouldParse?: boolean`\n When true, PDF URLs are fetched and parsed. When false, PDF URLs are skipped and a 400 WEBSITE_ACCESS_ERROR is returned.\n - `start?: number`\n First 1-based PDF page to parse. When omitted, parsing starts at the first page.\n\n- `timeoutMS?: number`\n Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed value is 300000ms (5 minutes).\n\n- `useMainContentOnly?: boolean`\n When true, return only the page's main content in the HTML response, excluding headers, footers, sidebars, and navigation when detectable.\n\n- `waitForMs?: number`\n Optional browser wait time in milliseconds after initial page load. Min: 0. Max: 30000 (30 seconds). \n\n### Returns\n\n- `{ html: string; metadata: { finalUrl: string; sourceUrl: string; additionalMeta?: object; alternates?: { href: string; hreflang?: string; title?: string; type?: string; }[]; author?: string; canonicalUrl?: string; description?: string; favicon?: string; image?: string; jsonLd?: object[]; keywords?: string[]; language?: string; modifiedTime?: string; openGraph?: object; publishedTime?: string; robots?: string; siteName?: string; title?: string; twitter?: object; }; success: true; type: 'html' | 'xml' | 'json' | 'text' | 'csv' | 'markdown' | 'svg' | 'pdf' | 'docx' | 'doc'; url: string; key_metadata?: { credits_consumed: number; credits_remaining: number; }; }`\n\n - `html: string`\n - `metadata: { finalUrl: string; sourceUrl: string; additionalMeta?: object; alternates?: { href: string; hreflang?: string; title?: string; type?: string; }[]; author?: string; canonicalUrl?: string; description?: string; favicon?: string; image?: string; jsonLd?: object[]; keywords?: string[]; language?: string; modifiedTime?: string; openGraph?: object; publishedTime?: string; robots?: string; siteName?: string; title?: string; twitter?: object; }`\n - `success: true`\n - `type: 'html' | 'xml' | 'json' | 'text' | 'csv' | 'markdown' | 'svg' | 'pdf' | 'docx' | 'doc'`\n - `url: string`\n - `key_metadata?: { credits_consumed: number; credits_remaining: number; }`\n\n### Example\n\n```typescript\nimport ContextDev from 'context.dev';\n\nconst client = new ContextDev();\n\nconst response = await client.web.webScrapeHTML({ url: 'https://example.com' });\n\nconsole.log(response);\n```", perLanguage: { typescript: { method: 'client.web.webScrapeHTML', @@ -103,7 +104,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ php: { method: 'web->webScrapeHTML', example: - "web->webScrapeHTML(\n url: 'https://example.com',\n excludeSelectors: ['string'],\n headers: ['foo' => 'J!'],\n includeFrames: true,\n includeSelectors: ['string'],\n maxAgeMs: 0,\n pdf: ['end' => 1, 'shouldParse' => true, 'start' => 1],\n timeoutMs: 1000,\n useMainContentOnly: true,\n waitForMs: 0,\n);\n\nvar_dump($response);", + "web->webScrapeHTML(\n url: 'https://example.com',\n country: 'de',\n excludeSelectors: ['string'],\n headers: ['foo' => 'J!'],\n includeFrames: true,\n includeSelectors: ['string'],\n maxAgeMs: 0,\n pdf: ['end' => 1, 'shouldParse' => true, 'start' => 1],\n timeoutMs: 1000,\n useMainContentOnly: true,\n waitForMs: 0,\n);\n\nvar_dump($response);", }, http: { example: @@ -121,6 +122,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ qualified: 'client.web.webScrapeMd', params: [ 'url: string;', + 'country?: string;', 'excludeSelectors?: string[];', 'headers?: object;', 'includeFrames?: boolean;', @@ -137,7 +139,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ response: '{ markdown: string; metadata: { finalUrl: string; sourceUrl: string; additionalMeta?: object; alternates?: { href: string; hreflang?: string; title?: string; type?: string; }[]; author?: string; canonicalUrl?: string; description?: string; favicon?: string; image?: string; jsonLd?: object[]; keywords?: string[]; language?: string; modifiedTime?: string; openGraph?: object; publishedTime?: string; robots?: string; siteName?: string; title?: string; twitter?: object; }; success: true; url: string; key_metadata?: { credits_consumed: number; credits_remaining: number; }; }', markdown: - '## web_scrape_md\n\n`client.web.webScrapeMd(url: string, excludeSelectors?: string[], headers?: object, includeFrames?: boolean, includeImages?: boolean, includeLinks?: boolean, includeSelectors?: string[], maxAgeMs?: number, pdf?: { end?: number; shouldParse?: boolean; start?: number; }, shortenBase64Images?: boolean, timeoutMS?: number, useMainContentOnly?: boolean, waitForMs?: number): { markdown: string; metadata: object; success: true; url: string; key_metadata?: object; }`\n\n**get** `/web/scrape/markdown`\n\nScrapes the given URL into LLM usable Markdown.\n\n### Parameters\n\n- `url: string`\n Full URL to scrape into LLM usable Markdown (must include http:// or https:// protocol)\n\n- `excludeSelectors?: string[]`\n CSS selectors to remove before conversion to Markdown. Applied after includeSelectors. Exclusion takes precedence: an element matching both is removed. Examples: "nav", "footer", ".ad-banner", "[aria-hidden=true]".\n\n- `headers?: object`\n Optional outbound HTTP headers forwarded only to the target URL, sent as deep-object query params such as headers[X-Custom]=value. When provided, caching is bypassed: the result is neither read from nor written to cache.\n\n- `includeFrames?: boolean`\n When true, the contents of iframes are rendered to Markdown.\n\n- `includeImages?: boolean`\n Include image references in Markdown output\n\n- `includeLinks?: boolean`\n Preserve hyperlinks in Markdown output\n\n- `includeSelectors?: string[]`\n CSS selectors. When provided, only matching HTML subtrees (and their descendants) are kept before conversion to Markdown. When omitted, the entire document is kept. Examples: "article.main", "#content", "[role=main]".\n\n- `maxAgeMs?: number`\n Return a cached result if a prior scrape for the same parameters exists and is younger than this many milliseconds. Defaults to 1 day (86400000 ms) when omitted. Max is 30 days (2592000000 ms). Set to 0 to always scrape fresh.\n\n- `pdf?: { end?: number; shouldParse?: boolean; start?: number; }`\n PDF parsing controls. Use start/end to limit text extraction and OCR to an inclusive 1-based page range.\n - `end?: number`\n Last 1-based PDF page to parse. When omitted, parsing ends at the last page. Must be greater than or equal to start when both are provided.\n - `shouldParse?: boolean`\n When true, PDF URLs are fetched and parsed. When false, PDF URLs are skipped and a 400 WEBSITE_ACCESS_ERROR is returned.\n - `start?: number`\n First 1-based PDF page to parse. When omitted, parsing starts at the first page.\n\n- `shortenBase64Images?: boolean`\n Shorten base64-encoded image data in the Markdown output\n\n- `timeoutMS?: number`\n Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed value is 300000ms (5 minutes).\n\n- `useMainContentOnly?: boolean`\n Extract only the main content of the page, excluding headers, footers, sidebars, and navigation\n\n- `waitForMs?: number`\n Optional browser wait time in milliseconds after initial page load before converting the page to Markdown. Min: 0. Max: 30000 (30 seconds). \n\n### Returns\n\n- `{ markdown: string; metadata: { finalUrl: string; sourceUrl: string; additionalMeta?: object; alternates?: { href: string; hreflang?: string; title?: string; type?: string; }[]; author?: string; canonicalUrl?: string; description?: string; favicon?: string; image?: string; jsonLd?: object[]; keywords?: string[]; language?: string; modifiedTime?: string; openGraph?: object; publishedTime?: string; robots?: string; siteName?: string; title?: string; twitter?: object; }; success: true; url: string; key_metadata?: { credits_consumed: number; credits_remaining: number; }; }`\n\n - `markdown: string`\n - `metadata: { finalUrl: string; sourceUrl: string; additionalMeta?: object; alternates?: { href: string; hreflang?: string; title?: string; type?: string; }[]; author?: string; canonicalUrl?: string; description?: string; favicon?: string; image?: string; jsonLd?: object[]; keywords?: string[]; language?: string; modifiedTime?: string; openGraph?: object; publishedTime?: string; robots?: string; siteName?: string; title?: string; twitter?: object; }`\n - `success: true`\n - `url: string`\n - `key_metadata?: { credits_consumed: number; credits_remaining: number; }`\n\n### Example\n\n```typescript\nimport ContextDev from \'context.dev\';\n\nconst client = new ContextDev();\n\nconst response = await client.web.webScrapeMd({ url: \'https://example.com\' });\n\nconsole.log(response);\n```', + '## web_scrape_md\n\n`client.web.webScrapeMd(url: string, country?: string, excludeSelectors?: string[], headers?: object, includeFrames?: boolean, includeImages?: boolean, includeLinks?: boolean, includeSelectors?: string[], maxAgeMs?: number, pdf?: { end?: number; shouldParse?: boolean; start?: number; }, shortenBase64Images?: boolean, timeoutMS?: number, useMainContentOnly?: boolean, waitForMs?: number): { markdown: string; metadata: object; success: true; url: string; key_metadata?: object; }`\n\n**get** `/web/scrape/markdown`\n\nScrapes the given URL into LLM usable Markdown.\n\n### Parameters\n\n- `url: string`\n Full URL to scrape into LLM usable Markdown (must include http:// or https:// protocol)\n\n- `country?: string`\n Two-letter ISO 3166-1 alpha-2 country code for the website request location. When provided, Context.dev fetches the target page from that country.\n\n- `excludeSelectors?: string[]`\n CSS selectors to remove before conversion to Markdown. Applied after includeSelectors. Exclusion takes precedence: an element matching both is removed. Examples: "nav", "footer", ".ad-banner", "[aria-hidden=true]".\n\n- `headers?: object`\n Optional outbound HTTP headers forwarded only to the target URL, sent as deep-object query params such as headers[X-Custom]=value. When provided, caching is bypassed: the result is neither read from nor written to cache.\n\n- `includeFrames?: boolean`\n When true, the contents of iframes are rendered to Markdown.\n\n- `includeImages?: boolean`\n Include image references in Markdown output\n\n- `includeLinks?: boolean`\n Preserve hyperlinks in Markdown output\n\n- `includeSelectors?: string[]`\n CSS selectors. When provided, only matching HTML subtrees (and their descendants) are kept before conversion to Markdown. When omitted, the entire document is kept. Examples: "article.main", "#content", "[role=main]".\n\n- `maxAgeMs?: number`\n Return a cached result if a prior scrape for the same parameters exists and is younger than this many milliseconds. Defaults to 1 day (86400000 ms) when omitted. Max is 30 days (2592000000 ms). Set to 0 to always scrape fresh.\n\n- `pdf?: { end?: number; shouldParse?: boolean; start?: number; }`\n PDF parsing controls. Use start/end to limit text extraction and OCR to an inclusive 1-based page range.\n - `end?: number`\n Last 1-based PDF page to parse. When omitted, parsing ends at the last page. Must be greater than or equal to start when both are provided.\n - `shouldParse?: boolean`\n When true, PDF URLs are fetched and parsed. When false, PDF URLs are skipped and a 400 WEBSITE_ACCESS_ERROR is returned.\n - `start?: number`\n First 1-based PDF page to parse. When omitted, parsing starts at the first page.\n\n- `shortenBase64Images?: boolean`\n Shorten base64-encoded image data in the Markdown output\n\n- `timeoutMS?: number`\n Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed value is 300000ms (5 minutes).\n\n- `useMainContentOnly?: boolean`\n Extract only the main content of the page, excluding headers, footers, sidebars, and navigation\n\n- `waitForMs?: number`\n Optional browser wait time in milliseconds after initial page load before converting the page to Markdown. Min: 0. Max: 30000 (30 seconds). \n\n### Returns\n\n- `{ markdown: string; metadata: { finalUrl: string; sourceUrl: string; additionalMeta?: object; alternates?: { href: string; hreflang?: string; title?: string; type?: string; }[]; author?: string; canonicalUrl?: string; description?: string; favicon?: string; image?: string; jsonLd?: object[]; keywords?: string[]; language?: string; modifiedTime?: string; openGraph?: object; publishedTime?: string; robots?: string; siteName?: string; title?: string; twitter?: object; }; success: true; url: string; key_metadata?: { credits_consumed: number; credits_remaining: number; }; }`\n\n - `markdown: string`\n - `metadata: { finalUrl: string; sourceUrl: string; additionalMeta?: object; alternates?: { href: string; hreflang?: string; title?: string; type?: string; }[]; author?: string; canonicalUrl?: string; description?: string; favicon?: string; image?: string; jsonLd?: object[]; keywords?: string[]; language?: string; modifiedTime?: string; openGraph?: object; publishedTime?: string; robots?: string; siteName?: string; title?: string; twitter?: object; }`\n - `success: true`\n - `url: string`\n - `key_metadata?: { credits_consumed: number; credits_remaining: number; }`\n\n### Example\n\n```typescript\nimport ContextDev from \'context.dev\';\n\nconst client = new ContextDev();\n\nconst response = await client.web.webScrapeMd({ url: \'https://example.com\' });\n\nconsole.log(response);\n```', perLanguage: { typescript: { method: 'client.web.webScrapeMd', @@ -166,7 +168,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ php: { method: 'web->webScrapeMd', example: - "web->webScrapeMd(\n url: 'https://example.com',\n excludeSelectors: ['string'],\n headers: ['foo' => 'J!'],\n includeFrames: true,\n includeImages: true,\n includeLinks: true,\n includeSelectors: ['string'],\n maxAgeMs: 0,\n pdf: ['end' => 1, 'shouldParse' => true, 'start' => 1],\n shortenBase64Images: true,\n timeoutMs: 1000,\n useMainContentOnly: true,\n waitForMs: 0,\n);\n\nvar_dump($response);", + "web->webScrapeMd(\n url: 'https://example.com',\n country: 'de',\n excludeSelectors: ['string'],\n headers: ['foo' => 'J!'],\n includeFrames: true,\n includeImages: true,\n includeLinks: true,\n includeSelectors: ['string'],\n maxAgeMs: 0,\n pdf: ['end' => 1, 'shouldParse' => true, 'start' => 1],\n shortenBase64Images: true,\n timeoutMs: 1000,\n useMainContentOnly: true,\n waitForMs: 0,\n);\n\nvar_dump($response);", }, http: { example: @@ -296,6 +298,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ stainlessPath: '(resource) web > (method) screenshot', qualified: 'client.web.screenshot', params: [ + 'country?: string;', 'directUrl?: string;', 'domain?: string;', "fullScreenshot?: 'true' | 'false';", @@ -310,7 +313,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ response: "{ code?: number; domain?: string; height?: number; key_metadata?: { credits_consumed: number; credits_remaining: number; }; screenshot?: string; screenshotType?: 'viewport' | 'fullPage'; status?: string; width?: number; }", markdown: - "## screenshot\n\n`client.web.screenshot(directUrl?: string, domain?: string, fullScreenshot?: 'true' | 'false', handleCookiePopup?: 'true' | 'false', maxAgeMs?: number, page?: 'login' | 'signup' | 'blog' | 'careers' | 'pricing' | 'terms' | 'privacy' | 'contact', scrollOffset?: number, timeoutMS?: number, viewport?: { height?: number; width?: number; }, waitForMs?: number): { code?: number; domain?: string; height?: number; key_metadata?: object; screenshot?: string; screenshotType?: 'viewport' | 'fullPage'; status?: string; width?: number; }`\n\n**get** `/web/screenshot`\n\nCapture a screenshot of a website.\n\n### Parameters\n\n- `directUrl?: string`\n A specific URL to screenshot directly, bypassing domain resolution (e.g., 'https://example.com/pricing'). When provided, the screenshot is taken of this exact URL. You must provide either 'domain' or 'directUrl', but not both.\n\n- `domain?: string`\n Domain name to take screenshot of (e.g., 'example.com', 'google.com'). The domain will be automatically normalized and validated. You must provide either 'domain' or 'directUrl', but not both.\n\n- `fullScreenshot?: 'true' | 'false'`\n Optional parameter to determine screenshot type. If 'true', takes a full page screenshot capturing all content. If 'false' or not provided, takes a viewport screenshot (standard browser view).\n\n- `handleCookiePopup?: 'true' | 'false'`\n Optional parameter to control cookie/consent popup handling. If 'true', we dismiss cookie banner before capture. If 'false' or not provided, captures the page without that step.\n\n- `maxAgeMs?: number`\n Return a cached screenshot if a prior screenshot for the same parameters exists and is younger than this many milliseconds. Defaults to 1 day (86400000 ms) when omitted. Max is 30 days (2592000000 ms). Set to 0 to always capture fresh.\n\n- `page?: 'login' | 'signup' | 'blog' | 'careers' | 'pricing' | 'terms' | 'privacy' | 'contact'`\n Optional parameter to specify which page type to screenshot. If provided, the system will scrape the domain's links and use heuristics to find the most appropriate URL for the specified page type (30 supported languages). If not provided, screenshots the main domain landing page. Only applicable when using 'domain', not 'directUrl'.\n\n- `scrollOffset?: number`\n Optional vertical scroll offset in pixels for capturing a long page in viewport-sized chunks. When provided, the full page is captured once and the returned image is the viewport-sized slice that begins at this Y offset (e.g. request scrollOffset=0, then 1080, then 2160 to walk a 1920x1080 landing page top to bottom). The final slice may be shorter than the viewport height. Takes precedence over fullScreenshot. Max: 100000.\n\n- `timeoutMS?: number`\n Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed value is 300000ms (5 minutes).\n\n- `viewport?: { height?: number; width?: number; }`\n Optional browser viewport dimensions for the screenshot. Defaults to 1920x1080.\n - `height?: number`\n Viewport height in pixels.\n - `width?: number`\n Viewport width in pixels.\n\n- `waitForMs?: number`\n Optional browser wait time in milliseconds after initial page load before taking the screenshot. Min: 0. Max: 30000 (30 seconds). Defaults to 3000 ms when omitted.\n\n### Returns\n\n- `{ code?: number; domain?: string; height?: number; key_metadata?: { credits_consumed: number; credits_remaining: number; }; screenshot?: string; screenshotType?: 'viewport' | 'fullPage'; status?: string; width?: number; }`\n\n - `code?: number`\n - `domain?: string`\n - `height?: number`\n - `key_metadata?: { credits_consumed: number; credits_remaining: number; }`\n - `screenshot?: string`\n - `screenshotType?: 'viewport' | 'fullPage'`\n - `status?: string`\n - `width?: number`\n\n### Example\n\n```typescript\nimport ContextDev from 'context.dev';\n\nconst client = new ContextDev();\n\nconst response = await client.web.screenshot();\n\nconsole.log(response);\n```", + "## screenshot\n\n`client.web.screenshot(country?: string, directUrl?: string, domain?: string, fullScreenshot?: 'true' | 'false', handleCookiePopup?: 'true' | 'false', maxAgeMs?: number, page?: 'login' | 'signup' | 'blog' | 'careers' | 'pricing' | 'terms' | 'privacy' | 'contact', scrollOffset?: number, timeoutMS?: number, viewport?: { height?: number; width?: number; }, waitForMs?: number): { code?: number; domain?: string; height?: number; key_metadata?: object; screenshot?: string; screenshotType?: 'viewport' | 'fullPage'; status?: string; width?: number; }`\n\n**get** `/web/screenshot`\n\nCapture a screenshot of a website.\n\n### Parameters\n\n- `country?: string`\n Two-letter ISO 3166-1 alpha-2 country code for the website request location. When provided, Context.dev fetches the target page from that country.\n\n- `directUrl?: string`\n A specific URL to screenshot directly, bypassing domain resolution (e.g., 'https://example.com/pricing'). When provided, the screenshot is taken of this exact URL. You must provide either 'domain' or 'directUrl', but not both.\n\n- `domain?: string`\n Domain name to take screenshot of (e.g., 'example.com', 'google.com'). The domain will be automatically normalized and validated. You must provide either 'domain' or 'directUrl', but not both.\n\n- `fullScreenshot?: 'true' | 'false'`\n Optional parameter to determine screenshot type. If 'true', takes a full page screenshot capturing all content. If 'false' or not provided, takes a viewport screenshot (standard browser view).\n\n- `handleCookiePopup?: 'true' | 'false'`\n Optional parameter to control cookie/consent popup handling. If 'true', we dismiss cookie banner before capture. If 'false' or not provided, captures the page without that step.\n\n- `maxAgeMs?: number`\n Return a cached screenshot if a prior screenshot for the same parameters exists and is younger than this many milliseconds. Defaults to 1 day (86400000 ms) when omitted. Max is 30 days (2592000000 ms). Set to 0 to always capture fresh.\n\n- `page?: 'login' | 'signup' | 'blog' | 'careers' | 'pricing' | 'terms' | 'privacy' | 'contact'`\n Optional parameter to specify which page type to screenshot. If provided, the system will scrape the domain's links and use heuristics to find the most appropriate URL for the specified page type (30 supported languages). If not provided, screenshots the main domain landing page. Only applicable when using 'domain', not 'directUrl'.\n\n- `scrollOffset?: number`\n Optional vertical scroll offset in pixels for capturing a long page in viewport-sized chunks. When provided, the full page is captured once and the returned image is the viewport-sized slice that begins at this Y offset (e.g. request scrollOffset=0, then 1080, then 2160 to walk a 1920x1080 landing page top to bottom). The final slice may be shorter than the viewport height. Takes precedence over fullScreenshot. Max: 100000.\n\n- `timeoutMS?: number`\n Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed value is 300000ms (5 minutes).\n\n- `viewport?: { height?: number; width?: number; }`\n Optional browser viewport dimensions for the screenshot. Defaults to 1920x1080.\n - `height?: number`\n Viewport height in pixels.\n - `width?: number`\n Viewport width in pixels.\n\n- `waitForMs?: number`\n Optional browser wait time in milliseconds after initial page load before taking the screenshot. Min: 0. Max: 30000 (30 seconds). Defaults to 3000 ms when omitted.\n\n### Returns\n\n- `{ code?: number; domain?: string; height?: number; key_metadata?: { credits_consumed: number; credits_remaining: number; }; screenshot?: string; screenshotType?: 'viewport' | 'fullPage'; status?: string; width?: number; }`\n\n - `code?: number`\n - `domain?: string`\n - `height?: number`\n - `key_metadata?: { credits_consumed: number; credits_remaining: number; }`\n - `screenshot?: string`\n - `screenshotType?: 'viewport' | 'fullPage'`\n - `status?: string`\n - `width?: number`\n\n### Example\n\n```typescript\nimport ContextDev from 'context.dev';\n\nconst client = new ContextDev();\n\nconst response = await client.web.screenshot();\n\nconsole.log(response);\n```", perLanguage: { typescript: { method: 'client.web.screenshot', @@ -339,7 +342,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ php: { method: 'web->screenshot', example: - "web->screenshot(\n directURL: 'https://example.com',\n domain: 'domain',\n fullScreenshot: 'true',\n handleCookiePopup: 'true',\n maxAgeMs: 0,\n page: 'login',\n scrollOffset: 0,\n timeoutMs: 1000,\n viewport: ['height' => 240, 'width' => 240],\n waitForMs: 0,\n);\n\nvar_dump($response);", + "web->screenshot(\n country: 'de',\n directURL: 'https://example.com',\n domain: 'domain',\n fullScreenshot: 'true',\n handleCookiePopup: 'true',\n maxAgeMs: 0,\n page: 'login',\n scrollOffset: 0,\n timeoutMs: 1000,\n viewport: ['height' => 240, 'width' => 240],\n waitForMs: 0,\n);\n\nvar_dump($response);", }, http: { example: @@ -358,6 +361,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ qualified: 'client.web.webCrawlMd', params: [ 'url: string;', + 'country?: string;', 'excludeSelectors?: string[];', 'followSubdomains?: boolean;', 'includeFrames?: boolean;', @@ -378,7 +382,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ response: '{ metadata: { maxCrawlDepth: number; numFailed: number; numSkipped: number; numSucceeded: number; numUrls: number; }; results: { markdown: string; metadata: { crawlDepth: number; finalUrl: string; sourceUrl: string; statusCode: number; success: boolean; title: string; url: string; additionalMeta?: object; alternates?: object[]; author?: string; canonicalUrl?: string; description?: string; favicon?: string; image?: string; jsonLd?: object[]; keywords?: string[]; language?: string; modifiedTime?: string; openGraph?: object; publishedTime?: string; robots?: string; siteName?: string; twitter?: object; }; }[]; key_metadata?: { credits_consumed: number; credits_remaining: number; }; }', markdown: - '## web_crawl_md\n\n`client.web.webCrawlMd(url: string, excludeSelectors?: string[], followSubdomains?: boolean, includeFrames?: boolean, includeImages?: boolean, includeLinks?: boolean, includeSelectors?: string[], maxAgeMs?: number, maxDepth?: number, maxPages?: number, pdf?: { end?: number; shouldParse?: boolean; start?: number; }, shortenBase64Images?: boolean, stopAfterMs?: number, timeoutMS?: number, urlRegex?: string, useMainContentOnly?: boolean, waitForMs?: number): { metadata: object; results: object[]; key_metadata?: object; }`\n\n**post** `/web/crawl`\n\nPerforms a crawl starting from a given URL, extracts page content as Markdown, and returns results for all crawled pages.\n\n### Parameters\n\n- `url: string`\n The starting URL for the crawl (must include http:// or https:// protocol)\n\n- `excludeSelectors?: string[]`\n CSS selectors to remove before each crawled page is converted to Markdown. Applied after includeSelectors. Exclusion takes precedence: an element matching both is removed. Examples: "nav", "footer", ".ad-banner", "[aria-hidden=true]".\n\n- `followSubdomains?: boolean`\n When true, follow links on subdomains of the starting URL\'s domain (e.g. docs.example.com when starting from example.com). www and apex are always treated as equivalent.\n\n- `includeFrames?: boolean`\n When true, the contents of iframes are rendered to Markdown for each crawled page.\n\n- `includeImages?: boolean`\n Include image references in the Markdown output\n\n- `includeLinks?: boolean`\n Preserve hyperlinks in the Markdown output\n\n- `includeSelectors?: string[]`\n CSS selectors. When provided, only matching HTML subtrees (and their descendants) are kept before each crawled page is converted to Markdown. When omitted, the entire document is kept. Examples: "article.main", "#content", "[role=main]".\n\n- `maxAgeMs?: number`\n Return a cached result if a prior scrape for the same parameters exists and is younger than this many milliseconds. Defaults to 1 day (86400000 ms) when omitted. Max is 30 days (2592000000 ms). Set to 0 to always scrape fresh.\n\n- `maxDepth?: number`\n Maximum link depth from the starting URL (0 = only the starting page)\n\n- `maxPages?: number`\n Maximum number of pages to crawl. Hard cap: 500.\n\n- `pdf?: { end?: number; shouldParse?: boolean; start?: number; }`\n PDF parsing controls. Use start/end to limit text extraction and OCR to an inclusive 1-based page range.\n - `end?: number`\n Last 1-based PDF page to parse. When omitted, parsing ends at the last page. Must be greater than or equal to start when both are provided.\n - `shouldParse?: boolean`\n When true, PDF pages are fetched and parsed. When false, PDF pages are skipped entirely (not included in results and not counted as failures).\n - `start?: number`\n First 1-based PDF page to parse. When omitted, parsing starts at the first page.\n\n- `shortenBase64Images?: boolean`\n Truncate base64-encoded image data in the Markdown output\n\n- `stopAfterMs?: number`\n Soft time budget for the crawl in milliseconds. After each scrape, the crawler checks the elapsed time and, if exceeded, returns the pages collected so far instead of continuing. Min: 10000 (10s). Max: 110000 (110s). Default: 80000 (80s).\n\n- `timeoutMS?: number`\n Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed value is 300000ms (5 minutes).\n\n- `urlRegex?: string`\n Regex pattern. Only URLs matching this pattern will be followed and scraped.\n\n- `useMainContentOnly?: boolean`\n Extract only the main content, stripping headers, footers, sidebars, and navigation\n\n- `waitForMs?: number`\n Optional browser wait time in milliseconds after initial page load for each crawled page. Min: 0. Max: 30000 (30 seconds). \n\n### Returns\n\n- `{ metadata: { maxCrawlDepth: number; numFailed: number; numSkipped: number; numSucceeded: number; numUrls: number; }; results: { markdown: string; metadata: { crawlDepth: number; finalUrl: string; sourceUrl: string; statusCode: number; success: boolean; title: string; url: string; additionalMeta?: object; alternates?: object[]; author?: string; canonicalUrl?: string; description?: string; favicon?: string; image?: string; jsonLd?: object[]; keywords?: string[]; language?: string; modifiedTime?: string; openGraph?: object; publishedTime?: string; robots?: string; siteName?: string; twitter?: object; }; }[]; key_metadata?: { credits_consumed: number; credits_remaining: number; }; }`\n\n - `metadata: { maxCrawlDepth: number; numFailed: number; numSkipped: number; numSucceeded: number; numUrls: number; }`\n - `results: { markdown: string; metadata: { crawlDepth: number; finalUrl: string; sourceUrl: string; statusCode: number; success: boolean; title: string; url: string; additionalMeta?: object; alternates?: { href: string; hreflang?: string; title?: string; type?: string; }[]; author?: string; canonicalUrl?: string; description?: string; favicon?: string; image?: string; jsonLd?: object[]; keywords?: string[]; language?: string; modifiedTime?: string; openGraph?: object; publishedTime?: string; robots?: string; siteName?: string; twitter?: object; }; }[]`\n - `key_metadata?: { credits_consumed: number; credits_remaining: number; }`\n\n### Example\n\n```typescript\nimport ContextDev from \'context.dev\';\n\nconst client = new ContextDev();\n\nconst response = await client.web.webCrawlMd({ url: \'https://example.com\' });\n\nconsole.log(response);\n```', + '## web_crawl_md\n\n`client.web.webCrawlMd(url: string, country?: string, excludeSelectors?: string[], followSubdomains?: boolean, includeFrames?: boolean, includeImages?: boolean, includeLinks?: boolean, includeSelectors?: string[], maxAgeMs?: number, maxDepth?: number, maxPages?: number, pdf?: { end?: number; shouldParse?: boolean; start?: number; }, shortenBase64Images?: boolean, stopAfterMs?: number, timeoutMS?: number, urlRegex?: string, useMainContentOnly?: boolean, waitForMs?: number): { metadata: object; results: object[]; key_metadata?: object; }`\n\n**post** `/web/crawl`\n\nPerforms a crawl starting from a given URL, extracts page content as Markdown, and returns results for all crawled pages.\n\n### Parameters\n\n- `url: string`\n The starting URL for the crawl (must include http:// or https:// protocol)\n\n- `country?: string`\n Two-letter ISO 3166-1 alpha-2 country code identifying a supported Context.dev residential proxy exit location. Must be one of Context.dev\'s supported countries. When provided, Context.dev fetches the target page from that country.\n\n- `excludeSelectors?: string[]`\n CSS selectors to remove before each crawled page is converted to Markdown. Applied after includeSelectors. Exclusion takes precedence: an element matching both is removed. Examples: "nav", "footer", ".ad-banner", "[aria-hidden=true]".\n\n- `followSubdomains?: boolean`\n When true, follow links on subdomains of the starting URL\'s domain (e.g. docs.example.com when starting from example.com). www and apex are always treated as equivalent.\n\n- `includeFrames?: boolean`\n When true, the contents of iframes are rendered to Markdown for each crawled page.\n\n- `includeImages?: boolean`\n Include image references in the Markdown output\n\n- `includeLinks?: boolean`\n Preserve hyperlinks in the Markdown output\n\n- `includeSelectors?: string[]`\n CSS selectors. When provided, only matching HTML subtrees (and their descendants) are kept before each crawled page is converted to Markdown. When omitted, the entire document is kept. Examples: "article.main", "#content", "[role=main]".\n\n- `maxAgeMs?: number`\n Return a cached result if a prior scrape for the same parameters exists and is younger than this many milliseconds. Defaults to 1 day (86400000 ms) when omitted. Max is 30 days (2592000000 ms). Set to 0 to always scrape fresh.\n\n- `maxDepth?: number`\n Maximum link depth from the starting URL (0 = only the starting page)\n\n- `maxPages?: number`\n Maximum number of pages to crawl. Hard cap: 500.\n\n- `pdf?: { end?: number; shouldParse?: boolean; start?: number; }`\n PDF parsing controls. Use start/end to limit text extraction and OCR to an inclusive 1-based page range.\n - `end?: number`\n Last 1-based PDF page to parse. When omitted, parsing ends at the last page. Must be greater than or equal to start when both are provided.\n - `shouldParse?: boolean`\n When true, PDF pages are fetched and parsed. When false, PDF pages are skipped entirely (not included in results and not counted as failures).\n - `start?: number`\n First 1-based PDF page to parse. When omitted, parsing starts at the first page.\n\n- `shortenBase64Images?: boolean`\n Truncate base64-encoded image data in the Markdown output\n\n- `stopAfterMs?: number`\n Soft time budget for the crawl in milliseconds. After each scrape, the crawler checks the elapsed time and, if exceeded, returns the pages collected so far instead of continuing. Min: 10000 (10s). Max: 110000 (110s). Default: 80000 (80s).\n\n- `timeoutMS?: number`\n Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed value is 300000ms (5 minutes).\n\n- `urlRegex?: string`\n Regex pattern. Only URLs matching this pattern will be followed and scraped.\n\n- `useMainContentOnly?: boolean`\n Extract only the main content, stripping headers, footers, sidebars, and navigation\n\n- `waitForMs?: number`\n Optional browser wait time in milliseconds after initial page load for each crawled page. Min: 0. Max: 30000 (30 seconds). \n\n### Returns\n\n- `{ metadata: { maxCrawlDepth: number; numFailed: number; numSkipped: number; numSucceeded: number; numUrls: number; }; results: { markdown: string; metadata: { crawlDepth: number; finalUrl: string; sourceUrl: string; statusCode: number; success: boolean; title: string; url: string; additionalMeta?: object; alternates?: object[]; author?: string; canonicalUrl?: string; description?: string; favicon?: string; image?: string; jsonLd?: object[]; keywords?: string[]; language?: string; modifiedTime?: string; openGraph?: object; publishedTime?: string; robots?: string; siteName?: string; twitter?: object; }; }[]; key_metadata?: { credits_consumed: number; credits_remaining: number; }; }`\n\n - `metadata: { maxCrawlDepth: number; numFailed: number; numSkipped: number; numSucceeded: number; numUrls: number; }`\n - `results: { markdown: string; metadata: { crawlDepth: number; finalUrl: string; sourceUrl: string; statusCode: number; success: boolean; title: string; url: string; additionalMeta?: object; alternates?: { href: string; hreflang?: string; title?: string; type?: string; }[]; author?: string; canonicalUrl?: string; description?: string; favicon?: string; image?: string; jsonLd?: object[]; keywords?: string[]; language?: string; modifiedTime?: string; openGraph?: object; publishedTime?: string; robots?: string; siteName?: string; twitter?: object; }; }[]`\n - `key_metadata?: { credits_consumed: number; credits_remaining: number; }`\n\n### Example\n\n```typescript\nimport ContextDev from \'context.dev\';\n\nconst client = new ContextDev();\n\nconst response = await client.web.webCrawlMd({ url: \'https://example.com\' });\n\nconsole.log(response);\n```', perLanguage: { typescript: { method: 'client.web.webCrawlMd', @@ -407,11 +411,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ php: { method: 'web->webCrawlMd', example: - "web->webCrawlMd(\n url: 'https://example.com',\n excludeSelectors: ['string'],\n followSubdomains: true,\n includeFrames: true,\n includeImages: true,\n includeLinks: true,\n includeSelectors: ['string'],\n maxAgeMs: 0,\n maxDepth: 0,\n maxPages: 1,\n pdf: ['end' => 1, 'shouldParse' => true, 'start' => 1],\n shortenBase64Images: true,\n stopAfterMs: 10000,\n timeoutMs: 1000,\n urlRegex: '^https?://[^/]+/blog/',\n useMainContentOnly: true,\n waitForMs: 0,\n);\n\nvar_dump($response);", + "web->webCrawlMd(\n url: 'https://example.com',\n country: 'de',\n excludeSelectors: ['string'],\n followSubdomains: true,\n includeFrames: true,\n includeImages: true,\n includeLinks: true,\n includeSelectors: ['string'],\n maxAgeMs: 0,\n maxDepth: 0,\n maxPages: 1,\n pdf: ['end' => 1, 'shouldParse' => true, 'start' => 1],\n shortenBase64Images: true,\n stopAfterMs: 10000,\n timeoutMs: 1000,\n urlRegex: '^https?://[^/]+/blog/',\n useMainContentOnly: true,\n waitForMs: 0,\n);\n\nvar_dump($response);", }, http: { example: - 'curl https://api.context.dev/v1/web/crawl \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $CONTEXT_DEV_API_KEY" \\\n -d \'{\n "url": "https://example.com",\n "urlRegex": "^https?://[^/]+/blog/"\n }\'', + 'curl https://api.context.dev/v1/web/crawl \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $CONTEXT_DEV_API_KEY" \\\n -d \'{\n "url": "https://example.com",\n "country": "de",\n "urlRegex": "^https?://[^/]+/blog/"\n }\'', }, }, }, @@ -1467,7 +1471,7 @@ const EMBEDDED_READMES: { language: string; content: string }[] = [ { language: 'ruby', content: - '# Context Dev Ruby API library\n\nThe Context Dev Ruby library provides convenient access to the Context Dev REST API from any Ruby 3.2.0+ application. It ships with comprehensive types & docstrings in Yard, RBS, and RBI – [see below](https://github.com/context-dot-dev/context-ruby-sdk#Sorbet) for usage with Sorbet. The standard library\'s `net/http` is used as the HTTP transport, with connection pooling via the `connection_pool` gem.\n\n\n\nIt is generated with [Stainless](https://www.stainless.com/).\n\n## MCP Server\n\nUse the Context Dev MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.\n\n[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=context.dev-mcp&config=eyJuYW1lIjoiY29udGV4dC5kZXYtbWNwIiwidHJhbnNwb3J0IjoiaHR0cCIsInVybCI6Imh0dHBzOi8vY29udGV4dC1kZXYuc3RsbWNwLmNvbSIsImhlYWRlcnMiOnsieC1jb250ZXh0LWRldi1hcGkta2V5IjoiTXkgQVBJIEtleSJ9fQ)\n[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22context.dev-mcp%22%2C%22type%22%3A%22http%22%2C%22url%22%3A%22https%3A%2F%2Fcontext-dev.stlmcp.com%22%2C%22headers%22%3A%7B%22x-context-dev-api-key%22%3A%22My%20API%20Key%22%7D%7D)\n\n> Note: You may need to set environment variables in your MCP client.\n\n## Documentation\n\nDocumentation for releases of this gem can be found [on RubyDoc](https://gemdocs.org/gems/context.dev).\n\nThe REST API documentation can be found on [docs.context.dev](https://docs.context.dev/).\n\n## Installation\n\nTo use this gem, install via Bundler by adding the following to your application\'s `Gemfile`:\n\n\n\n```ruby\ngem "context.dev", "~> 0.0.1"\n```\n\n\n\n## Usage\n\n```ruby\nrequire "bundler/setup"\nrequire "context_dev"\n\ncontext_dev = ContextDev::Client.new(\n api_key: ENV["CONTEXT_DEV_API_KEY"] # This is the default and can be omitted\n)\n\nbrand = context_dev.brand.retrieve(domain: "REPLACE_ME")\n\nputs(brand.brand)\n```\n\n\n\n\n\n\n\n### Handling errors\n\nWhen the library is unable to connect to the API, or if the API returns a non-success status code (i.e., 4xx or 5xx response), a subclass of `ContextDev::Errors::APIError` will be thrown:\n\n```ruby\nbegin\n brand = context_dev.brand.retrieve(domain: "REPLACE_ME")\nrescue ContextDev::Errors::APIConnectionError => e\n puts("The server could not be reached")\n puts(e.cause) # an underlying Exception, likely raised within `net/http`\nrescue ContextDev::Errors::RateLimitError => e\n puts("A 429 status code was received; we should back off a bit.")\nrescue ContextDev::Errors::APIStatusError => e\n puts("Another non-200-range status code was received")\n puts(e.status)\nend\n```\n\nError codes are as follows:\n\n| Cause | Error Type |\n| ---------------- | -------------------------- |\n| HTTP 400 | `BadRequestError` |\n| HTTP 401 | `AuthenticationError` |\n| HTTP 403 | `PermissionDeniedError` |\n| HTTP 404 | `NotFoundError` |\n| HTTP 409 | `ConflictError` |\n| HTTP 422 | `UnprocessableEntityError` |\n| HTTP 429 | `RateLimitError` |\n| HTTP >= 500 | `InternalServerError` |\n| Other HTTP error | `APIStatusError` |\n| Timeout | `APITimeoutError` |\n| Network error | `APIConnectionError` |\n\n### Retries\n\nCertain errors will be automatically retried 2 times by default, with a short exponential backoff.\n\nConnection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict, 429 Rate Limit, >=500 Internal errors, and timeouts will all be retried by default.\n\nYou can use the `max_retries` option to configure or disable this:\n\n```ruby\n# Configure the default for all requests:\ncontext_dev = ContextDev::Client.new(\n max_retries: 0 # default is 2\n)\n\n# Or, configure per-request:\ncontext_dev.brand.retrieve(domain: "REPLACE_ME", request_options: {max_retries: 5})\n```\n\n### Timeouts\n\nBy default, requests will time out after 60 seconds. You can use the timeout option to configure or disable this:\n\n```ruby\n# Configure the default for all requests:\ncontext_dev = ContextDev::Client.new(\n timeout: nil # default is 60\n)\n\n# Or, configure per-request:\ncontext_dev.brand.retrieve(domain: "REPLACE_ME", request_options: {timeout: 5})\n```\n\nOn timeout, `ContextDev::Errors::APITimeoutError` is raised.\n\nNote that requests that time out are retried by default.\n\n## Advanced concepts\n\n### BaseModel\n\nAll parameter and response objects inherit from `ContextDev::Internal::Type::BaseModel`, which provides several conveniences, including:\n\n1. All fields, including unknown ones, are accessible with `obj[:prop]` syntax, and can be destructured with `obj => {prop: prop}` or pattern-matching syntax.\n\n2. Structural equivalence for equality; if two API calls return the same values, comparing the responses with == will return true.\n\n3. Both instances and the classes themselves can be pretty-printed.\n\n4. Helpers such as `#to_h`, `#deep_to_h`, `#to_json`, and `#to_yaml`.\n\n### Making custom or undocumented requests\n\n#### Undocumented properties\n\nYou can send undocumented parameters to any endpoint, and read undocumented response properties, like so:\n\nNote: the `extra_` parameters of the same name overrides the documented parameters.\n\n```ruby\nbrand =\n context_dev.brand.retrieve(\n domain: "REPLACE_ME",\n request_options: {\n extra_query: {my_query_parameter: value},\n extra_body: {my_body_parameter: value},\n extra_headers: {"my-header": value}\n }\n )\n\nputs(brand[:my_undocumented_property])\n```\n\n#### Undocumented request params\n\nIf you want to explicitly send an extra param, you can do so with the `extra_query`, `extra_body`, and `extra_headers` under the `request_options:` parameter when making a request, as seen in the examples above.\n\n#### Undocumented endpoints\n\nTo make requests to undocumented endpoints while retaining the benefit of auth, retries, and so on, you can make requests using `client.request`, like so:\n\n```ruby\nresponse = client.request(\n method: :post,\n path: \'/undocumented/endpoint\',\n query: {"dog": "woof"},\n headers: {"useful-header": "interesting-value"},\n body: {"hello": "world"}\n)\n```\n\n### Concurrency & connection pooling\n\nThe `ContextDev::Client` instances are threadsafe, but are only are fork-safe when there are no in-flight HTTP requests.\n\nEach instance of `ContextDev::Client` has its own HTTP connection pool with a default size of 99. As such, we recommend instantiating the client once per application in most settings.\n\nWhen all available connections from the pool are checked out, requests wait for a new connection to become available, with queue time counting towards the request timeout.\n\nUnless otherwise specified, other classes in the SDK do not have locks protecting their underlying data structure.\n\n## Sorbet\n\nThis library provides comprehensive [RBI](https://sorbet.org/docs/rbi) definitions, and has no dependency on sorbet-runtime.\n\nYou can provide typesafe request parameters like so:\n\n```ruby\ncontext_dev.brand.retrieve(domain: "REPLACE_ME")\n```\n\nOr, equivalently:\n\n```ruby\n# Hashes work, but are not typesafe:\ncontext_dev.brand.retrieve(domain: "REPLACE_ME")\n\n# You can also splat a full Params class:\nparams = ContextDev::BrandRetrieveParams.new(domain: "REPLACE_ME")\ncontext_dev.brand.retrieve(**params)\n```\n\n### Enums\n\nSince this library does not depend on `sorbet-runtime`, it cannot provide [`T::Enum`](https://sorbet.org/docs/tenum) instances. Instead, we provide "tagged symbols" instead, which is always a primitive at runtime:\n\n```ruby\n# :true\nputs(ContextDev::WebScreenshotParams::FullScreenshot::TRUE)\n\n# Revealed type: `T.all(ContextDev::WebScreenshotParams::FullScreenshot, Symbol)`\nT.reveal_type(ContextDev::WebScreenshotParams::FullScreenshot::TRUE)\n```\n\nEnum parameters have a "relaxed" type, so you can either pass in enum constants or their literal value:\n\n```ruby\n# Using the enum constants preserves the tagged type information:\ncontext_dev.web.screenshot(\n full_screenshot: ContextDev::WebScreenshotParams::FullScreenshot::TRUE,\n # …\n)\n\n# Literal values are also permissible:\ncontext_dev.web.screenshot(\n full_screenshot: :true,\n # …\n)\n```\n\n## Versioning\n\nThis package follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions. As the library is in initial development and has a major version of `0`, APIs may change at any time.\n\nThis package considers improvements to the (non-runtime) `*.rbi` and `*.rbs` type definitions to be non-breaking changes.\n\n## Requirements\n\nRuby 3.2.0 or higher.\n\n## Contributing\n\nSee [the contributing documentation](https://github.com/context-dot-dev/context-ruby-sdk/tree/main/CONTRIBUTING.md).\n', + '# Context Dev Ruby API library\n\nThe Context Dev Ruby library provides convenient access to the Context Dev REST API from any Ruby 3.2.0+ application. It ships with comprehensive types & docstrings in Yard, RBS, and RBI – [see below](https://github.com/context-dot-dev/context-ruby-sdk#Sorbet) for usage with Sorbet. The standard library\'s `net/http` is used as the HTTP transport, with connection pooling via the `connection_pool` gem.\n\n\n\nIt is generated with [Stainless](https://www.stainless.com/).\n\n## MCP Server\n\nUse the Context Dev MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.\n\n[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=context.dev-mcp&config=eyJuYW1lIjoiY29udGV4dC5kZXYtbWNwIiwidHJhbnNwb3J0IjoiaHR0cCIsInVybCI6Imh0dHBzOi8vY29udGV4dC1kZXYuc3RsbWNwLmNvbSIsImhlYWRlcnMiOnsieC1jb250ZXh0LWRldi1hcGkta2V5IjoiTXkgQVBJIEtleSJ9fQ)\n[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22context.dev-mcp%22%2C%22type%22%3A%22http%22%2C%22url%22%3A%22https%3A%2F%2Fcontext-dev.stlmcp.com%22%2C%22headers%22%3A%7B%22x-context-dev-api-key%22%3A%22My%20API%20Key%22%7D%7D)\n\n> Note: You may need to set environment variables in your MCP client.\n\n## Documentation\n\nDocumentation for releases of this gem can be found [on RubyDoc](https://gemdocs.org/gems/context.dev).\n\nThe REST API documentation can be found on [docs.context.dev](https://docs.context.dev/).\n\n## Installation\n\nTo use this gem, install via Bundler by adding the following to your application\'s `Gemfile`:\n\n\n\n```ruby\ngem "context.dev", "~> 0.0.1"\n```\n\n\n\n## Usage\n\n```ruby\nrequire "bundler/setup"\nrequire "context_dev"\n\ncontext_dev = ContextDev::Client.new(\n api_key: ENV["CONTEXT_DEV_API_KEY"] # This is the default and can be omitted\n)\n\nbrand = context_dev.brand.retrieve(domain: "REPLACE_ME")\n\nputs(brand.brand)\n```\n\n\n\n\n\n\n\n### Handling errors\n\nWhen the library is unable to connect to the API, or if the API returns a non-success status code (i.e., 4xx or 5xx response), a subclass of `ContextDev::Errors::APIError` will be thrown:\n\n```ruby\nbegin\n brand = context_dev.brand.retrieve(domain: "REPLACE_ME")\nrescue ContextDev::Errors::APIConnectionError => e\n puts("The server could not be reached")\n puts(e.cause) # an underlying Exception, likely raised within `net/http`\nrescue ContextDev::Errors::RateLimitError => e\n puts("A 429 status code was received; we should back off a bit.")\nrescue ContextDev::Errors::APIStatusError => e\n puts("Another non-200-range status code was received")\n puts(e.status)\nend\n```\n\nError codes are as follows:\n\n| Cause | Error Type |\n| ---------------- | -------------------------- |\n| HTTP 400 | `BadRequestError` |\n| HTTP 401 | `AuthenticationError` |\n| HTTP 403 | `PermissionDeniedError` |\n| HTTP 404 | `NotFoundError` |\n| HTTP 409 | `ConflictError` |\n| HTTP 422 | `UnprocessableEntityError` |\n| HTTP 429 | `RateLimitError` |\n| HTTP >= 500 | `InternalServerError` |\n| Other HTTP error | `APIStatusError` |\n| Timeout | `APITimeoutError` |\n| Network error | `APIConnectionError` |\n\n### Retries\n\nCertain errors will be automatically retried 2 times by default, with a short exponential backoff.\n\nConnection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict, 429 Rate Limit, >=500 Internal errors, and timeouts will all be retried by default.\n\nYou can use the `max_retries` option to configure or disable this:\n\n```ruby\n# Configure the default for all requests:\ncontext_dev = ContextDev::Client.new(\n max_retries: 0 # default is 2\n)\n\n# Or, configure per-request:\ncontext_dev.brand.retrieve(domain: "REPLACE_ME", request_options: {max_retries: 5})\n```\n\n### Timeouts\n\nBy default, requests will time out after 60 seconds. You can use the timeout option to configure or disable this:\n\n```ruby\n# Configure the default for all requests:\ncontext_dev = ContextDev::Client.new(\n timeout: nil # default is 60\n)\n\n# Or, configure per-request:\ncontext_dev.brand.retrieve(domain: "REPLACE_ME", request_options: {timeout: 5})\n```\n\nOn timeout, `ContextDev::Errors::APITimeoutError` is raised.\n\nNote that requests that time out are retried by default.\n\n## Advanced concepts\n\n### BaseModel\n\nAll parameter and response objects inherit from `ContextDev::Internal::Type::BaseModel`, which provides several conveniences, including:\n\n1. All fields, including unknown ones, are accessible with `obj[:prop]` syntax, and can be destructured with `obj => {prop: prop}` or pattern-matching syntax.\n\n2. Structural equivalence for equality; if two API calls return the same values, comparing the responses with == will return true.\n\n3. Both instances and the classes themselves can be pretty-printed.\n\n4. Helpers such as `#to_h`, `#deep_to_h`, `#to_json`, and `#to_yaml`.\n\n### Making custom or undocumented requests\n\n#### Undocumented properties\n\nYou can send undocumented parameters to any endpoint, and read undocumented response properties, like so:\n\nNote: the `extra_` parameters of the same name overrides the documented parameters.\n\n```ruby\nbrand =\n context_dev.brand.retrieve(\n domain: "REPLACE_ME",\n request_options: {\n extra_query: {my_query_parameter: value},\n extra_body: {my_body_parameter: value},\n extra_headers: {"my-header": value}\n }\n )\n\nputs(brand[:my_undocumented_property])\n```\n\n#### Undocumented request params\n\nIf you want to explicitly send an extra param, you can do so with the `extra_query`, `extra_body`, and `extra_headers` under the `request_options:` parameter when making a request, as seen in the examples above.\n\n#### Undocumented endpoints\n\nTo make requests to undocumented endpoints while retaining the benefit of auth, retries, and so on, you can make requests using `client.request`, like so:\n\n```ruby\nresponse = client.request(\n method: :post,\n path: \'/undocumented/endpoint\',\n query: {"dog": "woof"},\n headers: {"useful-header": "interesting-value"},\n body: {"hello": "world"}\n)\n```\n\n### Concurrency & connection pooling\n\nThe `ContextDev::Client` instances are threadsafe, but are only are fork-safe when there are no in-flight HTTP requests.\n\nEach instance of `ContextDev::Client` has its own HTTP connection pool with a default size of 99. As such, we recommend instantiating the client once per application in most settings.\n\nWhen all available connections from the pool are checked out, requests wait for a new connection to become available, with queue time counting towards the request timeout.\n\nUnless otherwise specified, other classes in the SDK do not have locks protecting their underlying data structure.\n\n## Sorbet\n\nThis library provides comprehensive [RBI](https://sorbet.org/docs/rbi) definitions, and has no dependency on sorbet-runtime.\n\nYou can provide typesafe request parameters like so:\n\n```ruby\ncontext_dev.brand.retrieve(domain: "REPLACE_ME")\n```\n\nOr, equivalently:\n\n```ruby\n# Hashes work, but are not typesafe:\ncontext_dev.brand.retrieve(domain: "REPLACE_ME")\n\n# You can also splat a full Params class:\nparams = ContextDev::BrandRetrieveParams.new(domain: "REPLACE_ME")\ncontext_dev.brand.retrieve(**params)\n```\n\n### Enums\n\nSince this library does not depend on `sorbet-runtime`, it cannot provide [`T::Enum`](https://sorbet.org/docs/tenum) instances. Instead, we provide "tagged symbols" instead, which is always a primitive at runtime:\n\n```ruby\n# :ad\nputs(ContextDev::WebScreenshotParams::Country::AD)\n\n# Revealed type: `T.all(ContextDev::WebScreenshotParams::Country, Symbol)`\nT.reveal_type(ContextDev::WebScreenshotParams::Country::AD)\n```\n\nEnum parameters have a "relaxed" type, so you can either pass in enum constants or their literal value:\n\n```ruby\n# Using the enum constants preserves the tagged type information:\ncontext_dev.web.screenshot(\n country: ContextDev::WebScreenshotParams::Country::AD,\n # …\n)\n\n# Literal values are also permissible:\ncontext_dev.web.screenshot(\n country: :ad,\n # …\n)\n```\n\n## Versioning\n\nThis package follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions. As the library is in initial development and has a major version of `0`, APIs may change at any time.\n\nThis package considers improvements to the (non-runtime) `*.rbi` and `*.rbs` type definitions to be non-breaking changes.\n\n## Requirements\n\nRuby 3.2.0 or higher.\n\n## Contributing\n\nSee [the contributing documentation](https://github.com/context-dot-dev/context-ruby-sdk/tree/main/CONTRIBUTING.md).\n', }, { language: 'typescript', diff --git a/src/resources/web.ts b/src/resources/web.ts index 56566a8..4bada26 100644 --- a/src/resources/web.ts +++ b/src/resources/web.ts @@ -2052,6 +2052,216 @@ export interface WebExtractStyleguideParams { } export interface WebScreenshotParams { + /** + * Two-letter ISO 3166-1 alpha-2 country code for the website request location. + * When provided, Context.dev fetches the target page from that country. + */ + country?: + | 'ad' + | 'ae' + | 'af' + | 'ag' + | 'ai' + | 'al' + | 'am' + | 'ao' + | 'ar' + | 'at' + | 'au' + | 'aw' + | 'az' + | 'ba' + | 'bb' + | 'bd' + | 'be' + | 'bf' + | 'bg' + | 'bh' + | 'bi' + | 'bj' + | 'bm' + | 'bn' + | 'bo' + | 'bq' + | 'br' + | 'bs' + | 'bw' + | 'by' + | 'bz' + | 'ca' + | 'cd' + | 'cf' + | 'cg' + | 'ch' + | 'ci' + | 'cl' + | 'cm' + | 'cn' + | 'co' + | 'cr' + | 'cv' + | 'cw' + | 'cy' + | 'cz' + | 'de' + | 'dj' + | 'dk' + | 'dm' + | 'do' + | 'dz' + | 'ec' + | 'ee' + | 'eg' + | 'es' + | 'et' + | 'fi' + | 'fj' + | 'fr' + | 'ga' + | 'gb' + | 'gd' + | 'ge' + | 'gf' + | 'gg' + | 'gh' + | 'gm' + | 'gn' + | 'gp' + | 'gq' + | 'gr' + | 'gt' + | 'gu' + | 'gw' + | 'gy' + | 'hk' + | 'hn' + | 'hr' + | 'ht' + | 'hu' + | 'id' + | 'ie' + | 'il' + | 'im' + | 'in' + | 'iq' + | 'ir' + | 'is' + | 'it' + | 'je' + | 'jm' + | 'jo' + | 'jp' + | 'ke' + | 'kg' + | 'kh' + | 'kn' + | 'kr' + | 'kw' + | 'ky' + | 'kz' + | 'la' + | 'lb' + | 'lc' + | 'lk' + | 'lr' + | 'ls' + | 'lt' + | 'lu' + | 'lv' + | 'ly' + | 'ma' + | 'mc' + | 'md' + | 'me' + | 'mf' + | 'mg' + | 'mk' + | 'ml' + | 'mm' + | 'mn' + | 'mo' + | 'mq' + | 'mr' + | 'mt' + | 'mu' + | 'mv' + | 'mw' + | 'mx' + | 'my' + | 'mz' + | 'na' + | 'nc' + | 'ne' + | 'ng' + | 'ni' + | 'nl' + | 'no' + | 'np' + | 'nz' + | 'om' + | 'pa' + | 'pe' + | 'pf' + | 'pg' + | 'ph' + | 'pk' + | 'pl' + | 'pr' + | 'ps' + | 'pt' + | 'py' + | 'qa' + | 're' + | 'ro' + | 'rs' + | 'ru' + | 'rw' + | 'sa' + | 'sc' + | 'sd' + | 'se' + | 'sg' + | 'si' + | 'sk' + | 'sl' + | 'sm' + | 'sn' + | 'so' + | 'sr' + | 'ss' + | 'st' + | 'sv' + | 'sx' + | 'sy' + | 'sz' + | 'tc' + | 'td' + | 'tg' + | 'th' + | 'tj' + | 'tl' + | 'tm' + | 'tn' + | 'tr' + | 'tt' + | 'tw' + | 'tz' + | 'ua' + | 'ug' + | 'us' + | 'uy' + | 'uz' + | 'vc' + | 've' + | 'vg' + | 'vi' + | 'vn' + | 'ye' + | 'yt' + | 'za' + | 'zm' + | 'zw'; + /** * A specific URL to screenshot directly, bypassing domain resolution (e.g., * 'https://example.com/pricing'). When provided, the screenshot is taken of this @@ -2274,6 +2484,217 @@ export interface WebWebCrawlMdParams { */ url: string; + /** + * Two-letter ISO 3166-1 alpha-2 country code identifying a supported Context.dev + * residential proxy exit location. Must be one of Context.dev's supported + * countries. When provided, Context.dev fetches the target page from that country. + */ + country?: + | 'ad' + | 'ae' + | 'af' + | 'ag' + | 'ai' + | 'al' + | 'am' + | 'ao' + | 'ar' + | 'at' + | 'au' + | 'aw' + | 'az' + | 'ba' + | 'bb' + | 'bd' + | 'be' + | 'bf' + | 'bg' + | 'bh' + | 'bi' + | 'bj' + | 'bm' + | 'bn' + | 'bo' + | 'bq' + | 'br' + | 'bs' + | 'bw' + | 'by' + | 'bz' + | 'ca' + | 'cd' + | 'cf' + | 'cg' + | 'ch' + | 'ci' + | 'cl' + | 'cm' + | 'cn' + | 'co' + | 'cr' + | 'cv' + | 'cw' + | 'cy' + | 'cz' + | 'de' + | 'dj' + | 'dk' + | 'dm' + | 'do' + | 'dz' + | 'ec' + | 'ee' + | 'eg' + | 'es' + | 'et' + | 'fi' + | 'fj' + | 'fr' + | 'ga' + | 'gb' + | 'gd' + | 'ge' + | 'gf' + | 'gg' + | 'gh' + | 'gm' + | 'gn' + | 'gp' + | 'gq' + | 'gr' + | 'gt' + | 'gu' + | 'gw' + | 'gy' + | 'hk' + | 'hn' + | 'hr' + | 'ht' + | 'hu' + | 'id' + | 'ie' + | 'il' + | 'im' + | 'in' + | 'iq' + | 'ir' + | 'is' + | 'it' + | 'je' + | 'jm' + | 'jo' + | 'jp' + | 'ke' + | 'kg' + | 'kh' + | 'kn' + | 'kr' + | 'kw' + | 'ky' + | 'kz' + | 'la' + | 'lb' + | 'lc' + | 'lk' + | 'lr' + | 'ls' + | 'lt' + | 'lu' + | 'lv' + | 'ly' + | 'ma' + | 'mc' + | 'md' + | 'me' + | 'mf' + | 'mg' + | 'mk' + | 'ml' + | 'mm' + | 'mn' + | 'mo' + | 'mq' + | 'mr' + | 'mt' + | 'mu' + | 'mv' + | 'mw' + | 'mx' + | 'my' + | 'mz' + | 'na' + | 'nc' + | 'ne' + | 'ng' + | 'ni' + | 'nl' + | 'no' + | 'np' + | 'nz' + | 'om' + | 'pa' + | 'pe' + | 'pf' + | 'pg' + | 'ph' + | 'pk' + | 'pl' + | 'pr' + | 'ps' + | 'pt' + | 'py' + | 'qa' + | 're' + | 'ro' + | 'rs' + | 'ru' + | 'rw' + | 'sa' + | 'sc' + | 'sd' + | 'se' + | 'sg' + | 'si' + | 'sk' + | 'sl' + | 'sm' + | 'sn' + | 'so' + | 'sr' + | 'ss' + | 'st' + | 'sv' + | 'sx' + | 'sy' + | 'sz' + | 'tc' + | 'td' + | 'tg' + | 'th' + | 'tj' + | 'tl' + | 'tm' + | 'tn' + | 'tr' + | 'tt' + | 'tw' + | 'tz' + | 'ua' + | 'ug' + | 'us' + | 'uy' + | 'uz' + | 'vc' + | 've' + | 'vg' + | 'vi' + | 'vn' + | 'ye' + | 'yt' + | 'za' + | 'zm' + | 'zw'; + /** * CSS selectors to remove before each crawled page is converted to Markdown. * Applied after includeSelectors. Exclusion takes precedence: an element matching @@ -2404,6 +2825,216 @@ export interface WebWebScrapeHTMLParams { */ url: string; + /** + * Two-letter ISO 3166-1 alpha-2 country code for the website request location. + * When provided, Context.dev fetches the target page from that country. + */ + country?: + | 'ad' + | 'ae' + | 'af' + | 'ag' + | 'ai' + | 'al' + | 'am' + | 'ao' + | 'ar' + | 'at' + | 'au' + | 'aw' + | 'az' + | 'ba' + | 'bb' + | 'bd' + | 'be' + | 'bf' + | 'bg' + | 'bh' + | 'bi' + | 'bj' + | 'bm' + | 'bn' + | 'bo' + | 'bq' + | 'br' + | 'bs' + | 'bw' + | 'by' + | 'bz' + | 'ca' + | 'cd' + | 'cf' + | 'cg' + | 'ch' + | 'ci' + | 'cl' + | 'cm' + | 'cn' + | 'co' + | 'cr' + | 'cv' + | 'cw' + | 'cy' + | 'cz' + | 'de' + | 'dj' + | 'dk' + | 'dm' + | 'do' + | 'dz' + | 'ec' + | 'ee' + | 'eg' + | 'es' + | 'et' + | 'fi' + | 'fj' + | 'fr' + | 'ga' + | 'gb' + | 'gd' + | 'ge' + | 'gf' + | 'gg' + | 'gh' + | 'gm' + | 'gn' + | 'gp' + | 'gq' + | 'gr' + | 'gt' + | 'gu' + | 'gw' + | 'gy' + | 'hk' + | 'hn' + | 'hr' + | 'ht' + | 'hu' + | 'id' + | 'ie' + | 'il' + | 'im' + | 'in' + | 'iq' + | 'ir' + | 'is' + | 'it' + | 'je' + | 'jm' + | 'jo' + | 'jp' + | 'ke' + | 'kg' + | 'kh' + | 'kn' + | 'kr' + | 'kw' + | 'ky' + | 'kz' + | 'la' + | 'lb' + | 'lc' + | 'lk' + | 'lr' + | 'ls' + | 'lt' + | 'lu' + | 'lv' + | 'ly' + | 'ma' + | 'mc' + | 'md' + | 'me' + | 'mf' + | 'mg' + | 'mk' + | 'ml' + | 'mm' + | 'mn' + | 'mo' + | 'mq' + | 'mr' + | 'mt' + | 'mu' + | 'mv' + | 'mw' + | 'mx' + | 'my' + | 'mz' + | 'na' + | 'nc' + | 'ne' + | 'ng' + | 'ni' + | 'nl' + | 'no' + | 'np' + | 'nz' + | 'om' + | 'pa' + | 'pe' + | 'pf' + | 'pg' + | 'ph' + | 'pk' + | 'pl' + | 'pr' + | 'ps' + | 'pt' + | 'py' + | 'qa' + | 're' + | 'ro' + | 'rs' + | 'ru' + | 'rw' + | 'sa' + | 'sc' + | 'sd' + | 'se' + | 'sg' + | 'si' + | 'sk' + | 'sl' + | 'sm' + | 'sn' + | 'so' + | 'sr' + | 'ss' + | 'st' + | 'sv' + | 'sx' + | 'sy' + | 'sz' + | 'tc' + | 'td' + | 'tg' + | 'th' + | 'tj' + | 'tl' + | 'tm' + | 'tn' + | 'tr' + | 'tt' + | 'tw' + | 'tz' + | 'ua' + | 'ug' + | 'us' + | 'uy' + | 'uz' + | 'vc' + | 've' + | 'vg' + | 'vi' + | 'vn' + | 'ye' + | 'yt' + | 'za' + | 'zm' + | 'zw'; + /** * CSS selectors to remove from the result. Applied after includeSelectors. * Exclusion takes precedence: an element matching both is removed. Examples: @@ -2563,6 +3194,216 @@ export interface WebWebScrapeMdParams { */ url: string; + /** + * Two-letter ISO 3166-1 alpha-2 country code for the website request location. + * When provided, Context.dev fetches the target page from that country. + */ + country?: + | 'ad' + | 'ae' + | 'af' + | 'ag' + | 'ai' + | 'al' + | 'am' + | 'ao' + | 'ar' + | 'at' + | 'au' + | 'aw' + | 'az' + | 'ba' + | 'bb' + | 'bd' + | 'be' + | 'bf' + | 'bg' + | 'bh' + | 'bi' + | 'bj' + | 'bm' + | 'bn' + | 'bo' + | 'bq' + | 'br' + | 'bs' + | 'bw' + | 'by' + | 'bz' + | 'ca' + | 'cd' + | 'cf' + | 'cg' + | 'ch' + | 'ci' + | 'cl' + | 'cm' + | 'cn' + | 'co' + | 'cr' + | 'cv' + | 'cw' + | 'cy' + | 'cz' + | 'de' + | 'dj' + | 'dk' + | 'dm' + | 'do' + | 'dz' + | 'ec' + | 'ee' + | 'eg' + | 'es' + | 'et' + | 'fi' + | 'fj' + | 'fr' + | 'ga' + | 'gb' + | 'gd' + | 'ge' + | 'gf' + | 'gg' + | 'gh' + | 'gm' + | 'gn' + | 'gp' + | 'gq' + | 'gr' + | 'gt' + | 'gu' + | 'gw' + | 'gy' + | 'hk' + | 'hn' + | 'hr' + | 'ht' + | 'hu' + | 'id' + | 'ie' + | 'il' + | 'im' + | 'in' + | 'iq' + | 'ir' + | 'is' + | 'it' + | 'je' + | 'jm' + | 'jo' + | 'jp' + | 'ke' + | 'kg' + | 'kh' + | 'kn' + | 'kr' + | 'kw' + | 'ky' + | 'kz' + | 'la' + | 'lb' + | 'lc' + | 'lk' + | 'lr' + | 'ls' + | 'lt' + | 'lu' + | 'lv' + | 'ly' + | 'ma' + | 'mc' + | 'md' + | 'me' + | 'mf' + | 'mg' + | 'mk' + | 'ml' + | 'mm' + | 'mn' + | 'mo' + | 'mq' + | 'mr' + | 'mt' + | 'mu' + | 'mv' + | 'mw' + | 'mx' + | 'my' + | 'mz' + | 'na' + | 'nc' + | 'ne' + | 'ng' + | 'ni' + | 'nl' + | 'no' + | 'np' + | 'nz' + | 'om' + | 'pa' + | 'pe' + | 'pf' + | 'pg' + | 'ph' + | 'pk' + | 'pl' + | 'pr' + | 'ps' + | 'pt' + | 'py' + | 'qa' + | 're' + | 'ro' + | 'rs' + | 'ru' + | 'rw' + | 'sa' + | 'sc' + | 'sd' + | 'se' + | 'sg' + | 'si' + | 'sk' + | 'sl' + | 'sm' + | 'sn' + | 'so' + | 'sr' + | 'ss' + | 'st' + | 'sv' + | 'sx' + | 'sy' + | 'sz' + | 'tc' + | 'td' + | 'tg' + | 'th' + | 'tj' + | 'tl' + | 'tm' + | 'tn' + | 'tr' + | 'tt' + | 'tw' + | 'tz' + | 'ua' + | 'ug' + | 'us' + | 'uy' + | 'uz' + | 'vc' + | 've' + | 'vg' + | 'vi' + | 'vn' + | 'ye' + | 'yt' + | 'za' + | 'zm' + | 'zw'; + /** * CSS selectors to remove before conversion to Markdown. Applied after * includeSelectors. Exclusion takes precedence: an element matching both is diff --git a/tests/api-resources/web.test.ts b/tests/api-resources/web.test.ts index 27efdab..a9316b9 100644 --- a/tests/api-resources/web.test.ts +++ b/tests/api-resources/web.test.ts @@ -151,6 +151,7 @@ describe('resource web', () => { await expect( client.web.screenshot( { + country: 'de', directUrl: 'https://example.com', domain: 'domain', fullScreenshot: 'true', @@ -223,6 +224,7 @@ describe('resource web', () => { test.skip('webCrawlMd: required and optional params', async () => { const response = await client.web.webCrawlMd({ url: 'https://example.com', + country: 'de', excludeSelectors: ['string'], followSubdomains: true, includeFrames: true, @@ -262,6 +264,7 @@ describe('resource web', () => { test.skip('webScrapeHTML: required and optional params', async () => { const response = await client.web.webScrapeHTML({ url: 'https://example.com', + country: 'de', excludeSelectors: ['string'], headers: { foo: 'J!' }, includeFrames: true, @@ -323,6 +326,7 @@ describe('resource web', () => { test.skip('webScrapeMd: required and optional params', async () => { const response = await client.web.webScrapeMd({ url: 'https://example.com', + country: 'de', excludeSelectors: ['string'], headers: { foo: 'J!' }, includeFrames: true, From 974561b2ed550421af78fa15b88deb29bf4895a8 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 26 Jun 2026 21:26:49 +0000 Subject: [PATCH 2/3] feat(api): api update --- .stats.yml | 4 +- packages/mcp-server/src/local-docs-search.ts | 6 +- src/resources/web.ts | 253 ++++++++++++++++++- tests/api-resources/web.test.ts | 2 + 4 files changed, 260 insertions(+), 5 deletions(-) diff --git a/.stats.yml b/.stats.yml index 24c57ba..9dc6067 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 25 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/context-dev/context.dev-00c5b8f1ebfe212bc8fb46204f5c05507630afa55b10f77e3a43c66d21edbb77.yml -openapi_spec_hash: 8bf4489b9bce0e52a89480109ffc5257 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/context-dev/context.dev-d3da262409c68576e457536f6c0e7ecc538219e0af19df415111c18f8fe92cfd.yml +openapi_spec_hash: 25009575202702d24bc6672472eb8506 config_hash: c7b0cdaba3b9797b77efd89e1754d803 diff --git a/packages/mcp-server/src/local-docs-search.ts b/packages/mcp-server/src/local-docs-search.ts index 8d22e9b..2b2335c 100644 --- a/packages/mcp-server/src/local-docs-search.ts +++ b/packages/mcp-server/src/local-docs-search.ts @@ -529,17 +529,19 @@ const EMBEDDED_METHODS: MethodEntry[] = [ qualified: 'client.web.search', params: [ 'query: string;', + 'country?: string;', 'excludeDomains?: string[];', "freshness?: 'last_24_hours' | 'last_week' | 'last_month' | 'last_year';", 'includeDomains?: string[];', 'markdownOptions?: { enabled?: boolean; includeFrames?: boolean; includeImages?: boolean; includeLinks?: boolean; maxAgeMs?: number; pdf?: { end?: number; shouldParse?: boolean; start?: number; }; shortenBase64Images?: boolean; timeoutMS?: number; useMainContentOnly?: boolean; waitForMs?: number; };', + 'numResults?: number;', 'queryFanout?: boolean;', 'timeoutMS?: number;', ], response: "{ query: string; results: { description: string; markdown: { code: 'SUCCESS' | 'NOT_REQUESTED' | 'TIMEOUT' | 'WEBSITE_ACCESS_ERROR' | 'ERROR'; markdown: string; }; relevance: 'high' | 'medium' | 'low'; title: string; url: string; }[]; key_metadata?: { credits_consumed: number; credits_remaining: number; }; }", markdown: - "## search\n\n`client.web.search(query: string, excludeDomains?: string[], freshness?: 'last_24_hours' | 'last_week' | 'last_month' | 'last_year', includeDomains?: string[], markdownOptions?: { enabled?: boolean; includeFrames?: boolean; includeImages?: boolean; includeLinks?: boolean; maxAgeMs?: number; pdf?: { end?: number; shouldParse?: boolean; start?: number; }; shortenBase64Images?: boolean; timeoutMS?: number; useMainContentOnly?: boolean; waitForMs?: number; }, queryFanout?: boolean, timeoutMS?: number): { query: string; results: object[]; key_metadata?: object; }`\n\n**post** `/web/search`\n\nSearch the web and optionally scrape each result to Markdown in one round-trip.\n\n### Parameters\n\n- `query: string`\n Natural-language search query.\n\n- `excludeDomains?: string[]`\n Blocklist — drop results from these domains. Example: [\"pinterest.com\", \"reddit.com\"].\n\n- `freshness?: 'last_24_hours' | 'last_week' | 'last_month' | 'last_year'`\n Restrict results to content published within this window.\n\n- `includeDomains?: string[]`\n Allowlist — only return results from these domains. Example: [\"arxiv.org\", \"github.com\"].\n\n- `markdownOptions?: { enabled?: boolean; includeFrames?: boolean; includeImages?: boolean; includeLinks?: boolean; maxAgeMs?: number; pdf?: { end?: number; shouldParse?: boolean; start?: number; }; shortenBase64Images?: boolean; timeoutMS?: number; useMainContentOnly?: boolean; waitForMs?: number; }`\n Inline Markdown scraping for each result. Set `enabled: true` to activate.\n - `enabled?: boolean`\n Scrape each result to Markdown. Off by default to keep search cheap and fast.\n - `includeFrames?: boolean`\n Render iframe contents into the Markdown.\n - `includeImages?: boolean`\n Emit image references in the Markdown.\n - `includeLinks?: boolean`\n Keep hyperlinks in the Markdown.\n - `maxAgeMs?: number`\n Cache TTL in ms for scraped Markdown keyed by URL + options. Default 1 day, max 30 days. Set to 0 to force a fresh scrape.\n - `pdf?: { end?: number; shouldParse?: boolean; start?: number; }`\n PDF handling. Use start/end to bound text extraction and OCR to a page range.\n - `shortenBase64Images?: boolean`\n Truncate inline base64 image payloads to keep responses small.\n - `timeoutMS?: number`\n Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed value is 300000ms (5 minutes).\n - `useMainContentOnly?: boolean`\n Strip nav, header, footer, and sidebar — keep only the primary article content.\n - `waitForMs?: number`\n Extra wait after page load before rendering, in ms (0–30000). Useful for JS-heavy pages.\n\n- `queryFanout?: boolean`\n Expand the query into multiple parallel variants for broader recall.\n\n- `timeoutMS?: number`\n Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed value is 300000ms (5 minutes).\n\n### Returns\n\n- `{ query: string; results: { description: string; markdown: { code: 'SUCCESS' | 'NOT_REQUESTED' | 'TIMEOUT' | 'WEBSITE_ACCESS_ERROR' | 'ERROR'; markdown: string; }; relevance: 'high' | 'medium' | 'low'; title: string; url: string; }[]; key_metadata?: { credits_consumed: number; credits_remaining: number; }; }`\n\n - `query: string`\n - `results: { description: string; markdown: { code: 'SUCCESS' | 'NOT_REQUESTED' | 'TIMEOUT' | 'WEBSITE_ACCESS_ERROR' | 'ERROR'; markdown: string; }; relevance: 'high' | 'medium' | 'low'; title: string; url: string; }[]`\n - `key_metadata?: { credits_consumed: number; credits_remaining: number; }`\n\n### Example\n\n```typescript\nimport ContextDev from 'context.dev';\n\nconst client = new ContextDev();\n\nconst response = await client.web.search({ query: 'x' });\n\nconsole.log(response);\n```", + "## search\n\n`client.web.search(query: string, country?: string, excludeDomains?: string[], freshness?: 'last_24_hours' | 'last_week' | 'last_month' | 'last_year', includeDomains?: string[], markdownOptions?: { enabled?: boolean; includeFrames?: boolean; includeImages?: boolean; includeLinks?: boolean; maxAgeMs?: number; pdf?: { end?: number; shouldParse?: boolean; start?: number; }; shortenBase64Images?: boolean; timeoutMS?: number; useMainContentOnly?: boolean; waitForMs?: number; }, numResults?: number, queryFanout?: boolean, timeoutMS?: number): { query: string; results: object[]; key_metadata?: object; }`\n\n**post** `/web/search`\n\nSearch the web and optionally scrape each result to Markdown in one round-trip.\n\n### Parameters\n\n- `query: string`\n Search query. Accepts natural language as well as Google-style search operators such as `site:`, `-site:`, `inurl:`, `intitle:`, quoted phrases, and `OR`.\n\n- `country?: string`\n Two-letter ISO 3166-1 alpha-2 country code to localize results to a specific country (maps to Google's `gl` parameter). Example: \"us\", \"gb\", \"de\".\n\n- `excludeDomains?: string[]`\n Blocklist — drop results from these domains. Example: [\"pinterest.com\", \"reddit.com\"].\n\n- `freshness?: 'last_24_hours' | 'last_week' | 'last_month' | 'last_year'`\n Restrict results to content published within this window.\n\n- `includeDomains?: string[]`\n Allowlist — only return results from these domains. Example: [\"arxiv.org\", \"github.com\"].\n\n- `markdownOptions?: { enabled?: boolean; includeFrames?: boolean; includeImages?: boolean; includeLinks?: boolean; maxAgeMs?: number; pdf?: { end?: number; shouldParse?: boolean; start?: number; }; shortenBase64Images?: boolean; timeoutMS?: number; useMainContentOnly?: boolean; waitForMs?: number; }`\n Inline Markdown scraping for each result. Set `enabled: true` to activate.\n - `enabled?: boolean`\n Scrape each result to Markdown. Off by default to keep search cheap and fast.\n - `includeFrames?: boolean`\n Render iframe contents into the Markdown.\n - `includeImages?: boolean`\n Emit image references in the Markdown.\n - `includeLinks?: boolean`\n Keep hyperlinks in the Markdown.\n - `maxAgeMs?: number`\n Cache TTL in ms for scraped Markdown keyed by URL + options. Default 1 day, max 30 days. Set to 0 to force a fresh scrape.\n - `pdf?: { end?: number; shouldParse?: boolean; start?: number; }`\n PDF handling. Use start/end to bound text extraction and OCR to a page range.\n - `shortenBase64Images?: boolean`\n Truncate inline base64 image payloads to keep responses small.\n - `timeoutMS?: number`\n Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed value is 300000ms (5 minutes).\n - `useMainContentOnly?: boolean`\n Strip nav, header, footer, and sidebar — keep only the primary article content.\n - `waitForMs?: number`\n Extra wait after page load before rendering, in ms (0–30000). Useful for JS-heavy pages.\n\n- `numResults?: number`\n Number of results to request and return (10–100). Defaults to 10.\n\n- `queryFanout?: boolean`\n Expand the query into multiple parallel variants for broader recall.\n\n- `timeoutMS?: number`\n Optional timeout in milliseconds for the request. If the request takes longer than this value, it will be aborted with a 408 status code. Maximum allowed value is 300000ms (5 minutes).\n\n### Returns\n\n- `{ query: string; results: { description: string; markdown: { code: 'SUCCESS' | 'NOT_REQUESTED' | 'TIMEOUT' | 'WEBSITE_ACCESS_ERROR' | 'ERROR'; markdown: string; }; relevance: 'high' | 'medium' | 'low'; title: string; url: string; }[]; key_metadata?: { credits_consumed: number; credits_remaining: number; }; }`\n\n - `query: string`\n - `results: { description: string; markdown: { code: 'SUCCESS' | 'NOT_REQUESTED' | 'TIMEOUT' | 'WEBSITE_ACCESS_ERROR' | 'ERROR'; markdown: string; }; relevance: 'high' | 'medium' | 'low'; title: string; url: string; }[]`\n - `key_metadata?: { credits_consumed: number; credits_remaining: number; }`\n\n### Example\n\n```typescript\nimport ContextDev from 'context.dev';\n\nconst client = new ContextDev();\n\nconst response = await client.web.search({ query: 'x' });\n\nconsole.log(response);\n```", perLanguage: { typescript: { method: 'client.web.search', @@ -568,7 +570,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ php: { method: 'web->search', example: - "web->search(\n query: 'x',\n excludeDomains: ['string'],\n freshness: 'last_24_hours',\n includeDomains: ['string'],\n markdownOptions: [\n 'enabled' => true,\n 'includeFrames' => true,\n 'includeImages' => true,\n 'includeLinks' => true,\n 'maxAgeMs' => 0,\n 'pdf' => ['end' => 1, 'shouldParse' => true, 'start' => 1],\n 'shortenBase64Images' => true,\n 'timeoutMs' => 1000,\n 'useMainContentOnly' => true,\n 'waitForMs' => 0,\n ],\n queryFanout: true,\n timeoutMs: 1000,\n);\n\nvar_dump($response);", + "web->search(\n query: 'x',\n country: 'af',\n excludeDomains: ['string'],\n freshness: 'last_24_hours',\n includeDomains: ['string'],\n markdownOptions: [\n 'enabled' => true,\n 'includeFrames' => true,\n 'includeImages' => true,\n 'includeLinks' => true,\n 'maxAgeMs' => 0,\n 'pdf' => ['end' => 1, 'shouldParse' => true, 'start' => 1],\n 'shortenBase64Images' => true,\n 'timeoutMs' => 1000,\n 'useMainContentOnly' => true,\n 'waitForMs' => 0,\n ],\n numResults: 10,\n queryFanout: true,\n timeoutMs: 1000,\n);\n\nvar_dump($response);", }, http: { example: diff --git a/src/resources/web.ts b/src/resources/web.ts index 4bada26..fa1ebab 100644 --- a/src/resources/web.ts +++ b/src/resources/web.ts @@ -2355,10 +2355,256 @@ export namespace WebScreenshotParams { export interface WebSearchParams { /** - * Natural-language search query. + * Search query. Accepts natural language as well as Google-style search operators + * such as `site:`, `-site:`, `inurl:`, `intitle:`, quoted phrases, and `OR`. */ query: string; + /** + * Two-letter ISO 3166-1 alpha-2 country code to localize results to a specific + * country (maps to Google's `gl` parameter). Example: "us", "gb", "de". + */ + country?: + | 'af' + | 'al' + | 'dz' + | 'as' + | 'ad' + | 'ao' + | 'ai' + | 'aq' + | 'ag' + | 'ar' + | 'am' + | 'aw' + | 'au' + | 'at' + | 'az' + | 'bs' + | 'bh' + | 'bd' + | 'bb' + | 'by' + | 'be' + | 'bz' + | 'bj' + | 'bm' + | 'bt' + | 'bo' + | 'ba' + | 'bw' + | 'bv' + | 'br' + | 'io' + | 'bn' + | 'bg' + | 'bf' + | 'bi' + | 'kh' + | 'cm' + | 'ca' + | 'cv' + | 'ky' + | 'cf' + | 'td' + | 'cl' + | 'cn' + | 'cx' + | 'cc' + | 'co' + | 'km' + | 'cg' + | 'cd' + | 'ck' + | 'cr' + | 'ci' + | 'hr' + | 'cu' + | 'cy' + | 'cz' + | 'dk' + | 'dj' + | 'dm' + | 'do' + | 'ec' + | 'eg' + | 'sv' + | 'gq' + | 'er' + | 'ee' + | 'et' + | 'fk' + | 'fo' + | 'fj' + | 'fi' + | 'fr' + | 'gf' + | 'pf' + | 'tf' + | 'ga' + | 'gm' + | 'ge' + | 'de' + | 'gh' + | 'gi' + | 'gr' + | 'gl' + | 'gd' + | 'gp' + | 'gu' + | 'gt' + | 'gn' + | 'gw' + | 'gy' + | 'ht' + | 'hm' + | 'va' + | 'hn' + | 'hk' + | 'hu' + | 'is' + | 'in' + | 'id' + | 'ir' + | 'iq' + | 'ie' + | 'il' + | 'it' + | 'jm' + | 'jp' + | 'jo' + | 'kz' + | 'ke' + | 'ki' + | 'kp' + | 'kr' + | 'kw' + | 'kg' + | 'la' + | 'lv' + | 'lb' + | 'ls' + | 'lr' + | 'ly' + | 'li' + | 'lt' + | 'lu' + | 'mo' + | 'mk' + | 'mg' + | 'mw' + | 'my' + | 'mv' + | 'ml' + | 'mt' + | 'mh' + | 'mq' + | 'mr' + | 'mu' + | 'yt' + | 'mx' + | 'fm' + | 'md' + | 'mc' + | 'mn' + | 'ms' + | 'ma' + | 'mz' + | 'mm' + | 'na' + | 'nr' + | 'np' + | 'nl' + | 'an' + | 'nc' + | 'nz' + | 'ni' + | 'ne' + | 'ng' + | 'nu' + | 'nf' + | 'mp' + | 'no' + | 'om' + | 'pk' + | 'pw' + | 'ps' + | 'pa' + | 'pg' + | 'py' + | 'pe' + | 'ph' + | 'pn' + | 'pl' + | 'pt' + | 'pr' + | 'qa' + | 're' + | 'ro' + | 'ru' + | 'rw' + | 'sh' + | 'kn' + | 'lc' + | 'pm' + | 'vc' + | 'ws' + | 'sm' + | 'st' + | 'sa' + | 'sn' + | 'rs' + | 'sc' + | 'sl' + | 'sg' + | 'sk' + | 'si' + | 'sb' + | 'so' + | 'za' + | 'gs' + | 'es' + | 'lk' + | 'sd' + | 'sr' + | 'sj' + | 'sz' + | 'se' + | 'ch' + | 'sy' + | 'tw' + | 'tj' + | 'tz' + | 'th' + | 'tl' + | 'tg' + | 'tk' + | 'to' + | 'tt' + | 'tn' + | 'tr' + | 'tm' + | 'tc' + | 'tv' + | 'ug' + | 'ua' + | 'ae' + | 'gb' + | 'us' + | 'um' + | 'uy' + | 'uz' + | 'vu' + | 've' + | 'vn' + | 'vg' + | 'vi' + | 'wf' + | 'eh' + | 'ye' + | 'zm' + | 'zw'; + /** * Blocklist — drop results from these domains. Example: ["pinterest.com", * "reddit.com"]. @@ -2381,6 +2627,11 @@ export interface WebSearchParams { */ markdownOptions?: WebSearchParams.MarkdownOptions; + /** + * Number of results to request and return (10–100). Defaults to 10. + */ + numResults?: number; + /** * Expand the query into multiple parallel variants for broader recall. */ diff --git a/tests/api-resources/web.test.ts b/tests/api-resources/web.test.ts index a9316b9..0dd4458 100644 --- a/tests/api-resources/web.test.ts +++ b/tests/api-resources/web.test.ts @@ -184,6 +184,7 @@ describe('resource web', () => { test.skip('search: required and optional params', async () => { const response = await client.web.search({ query: 'x', + country: 'af', excludeDomains: ['string'], freshness: 'last_24_hours', includeDomains: ['string'], @@ -203,6 +204,7 @@ describe('resource web', () => { useMainContentOnly: true, waitForMs: 0, }, + numResults: 10, queryFanout: true, timeoutMS: 1000, }); From 3cb320bca4d7e22252755ee8a78245e575e99a79 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 26 Jun 2026 21:27:18 +0000 Subject: [PATCH 3/3] release: 1.40.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 9 +++++++++ package.json | 2 +- packages/mcp-server/manifest.json | 2 +- packages/mcp-server/package.json | 2 +- packages/mcp-server/src/server.ts | 2 +- src/version.ts | 2 +- 7 files changed, 15 insertions(+), 6 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 32fe2b3..1cf398a 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "1.39.0" + ".": "1.40.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index cdfda17..28bd25d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## 1.40.0 (2026-06-26) + +Full Changelog: [v1.39.0...v1.40.0](https://github.com/context-dot-dev/context-typescript-sdk/compare/v1.39.0...v1.40.0) + +### Features + +* **api:** api update ([974561b](https://github.com/context-dot-dev/context-typescript-sdk/commit/974561b2ed550421af78fa15b88deb29bf4895a8)) +* **api:** api update ([e40ce25](https://github.com/context-dot-dev/context-typescript-sdk/commit/e40ce25e3073c35190fe8bc636aabfe2c48b31fc)) + ## 1.39.0 (2026-06-25) Full Changelog: [v1.38.0...v1.39.0](https://github.com/context-dot-dev/context-typescript-sdk/compare/v1.38.0...v1.39.0) diff --git a/package.json b/package.json index 2e1d32a..267dc3e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "context.dev", - "version": "1.39.0", + "version": "1.40.0", "description": "The official TypeScript library for the Context Dev API", "author": "Context Dev ", "types": "dist/index.d.ts", diff --git a/packages/mcp-server/manifest.json b/packages/mcp-server/manifest.json index b24a411..4d34eac 100644 --- a/packages/mcp-server/manifest.json +++ b/packages/mcp-server/manifest.json @@ -1,7 +1,7 @@ { "dxt_version": "0.2", "name": "context.dev-mcp", - "version": "1.39.0", + "version": "1.40.0", "description": "The official MCP Server for the Context Dev API", "author": { "name": "Context Dev", diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index 5660660..5326a16 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -1,6 +1,6 @@ { "name": "context.dev-mcp", - "version": "1.39.0", + "version": "1.40.0", "description": "The official MCP Server for the Context Dev API", "author": "Context Dev ", "types": "dist/index.d.ts", diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts index fbdfe14..32400f2 100644 --- a/packages/mcp-server/src/server.ts +++ b/packages/mcp-server/src/server.ts @@ -28,7 +28,7 @@ export const newMcpServer = async ({ new McpServer( { name: 'context_dev_api', - version: '1.39.0', + version: '1.40.0', }, { instructions: await getInstructions({ stainlessApiKey, customInstructionsPath }), diff --git a/src/version.ts b/src/version.ts index 372a684..0c281df 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '1.39.0'; // x-release-please-version +export const VERSION = '1.40.0'; // x-release-please-version