Skip to content

Latest commit

 

History

History
181 lines (121 loc) · 17.6 KB

CHANGELOG.md

File metadata and controls

181 lines (121 loc) · 17.6 KB

Unreleased

Maintenance

  • OpenTelemetry JS 3.x (#51, same move as mapbox/mcp-server#325). @opentelemetry/sdk-trace-base is deprecated in every 2.x release and removed in 3.0, and the ox-security scan flags it (mapbox/mcp-server#319). The OpenTelemetry set moves to the 3.0 line: sdk-trace 3.0.0 replaces sdk-trace-base, along with resources 3.0.0, sdk-node, instrumentation and exporter-trace-otlp-http 0.300.0, auto-instrumentations-node 0.82.0 and api 1.10.0.
    • Code: the console exporter is now imported from sdk-trace.
    • Node: engines is now >=22.15.0, the 3.x minimum (it was >=22).
    • Checked: the built server (ESM and CommonJS) sent tool.search_mapbox_docs_tool and its undici GET spans to a local OTLP endpoint.

0.3.2 - 2026-11-03

0.4.0-dev.1 - 2026-10-30

Breaking Changes

  • MCP TypeScript SDK v2 (#46, same move as mapbox/mcp-server#296). The server and the /tools, /resources and /utils exports now use @modelcontextprotocol/server 2.4.0 instead of @modelcontextprotocol/sdk 1.x. v2 is where new MCP features land.
    • For code that imports our tools or resources: installTo(server) needs a v2 McpServer, so the hosted server has to move to v2 in the same release it picks this version up in. getAllTools(), getAllResources() and installTo() themselves are unchanged. Handlers get the v2 ServerContext instead of RequestHandlerExtra.
    • Clients: nothing changes. It still negotiates 2025-11-25 with current clients, and tool input schemas now go out as JSON Schema 2020-12.
    • Mostly the codemod: npx @modelcontextprotocol/codemod v1-to-v2 . did the import paths and context types. None of our tools have an output schema, so v2's stricter output validation doesn't affect us. @modelcontextprotocol/client is a dev dependency, used by scripts/test-resources.ts and the tests.
    • Testing: the tool tests call run() directly and never touch the SDK, so there's a new test that installs every tool and resource on a real v2 McpServer and goes through tools/list, tools/call, resources/list and resources/read. Also checked the built server over stdio, including a live search and document fetch.
    • Tests are typechecked in CI now: npm run typecheck checks src and test together. The tests weren't typechecked before, and SearchDocsTool.test.ts had 7 errors on main (the v2 types fix those). tsconfig.test.json gets noEmit so a plain tsc run can't write .js files next to the sources.
  • chore: harden document fetching. Breaking for some URLs: get_document_tool and batch_get_documents_tool now accept only https://docs.mapbox.com URLs (plus MAPBOX_DOCS_HOST_OVERRIDE when set); bare mapbox.com and docs.tilestream.net (without the override) are rejected. The shared HTTP pipeline no longer follows redirects; document fetches follow up to 3 redirects, each only to an allowed docs URL. access_token detection is now case-insensitive (#45)
  • fix: the CommonJS build works again. require('@mapbox/mcp-docs-server/tools') (and /resources, /utils) threw "Cannot use 'import.meta' outside a module", since src/utils/versionUtils.ts uses import.meta.url and tshy compiled it into dist/commonjs as is. There's now a versionUtils-cjs.cts that tshy uses for the CommonJS build instead, reading version.json from __dirname, same as mcp-server does. ESM was never affected, and hosted-mcp-server uses ESM. (#47)
  • docs: fix two stale tool descriptions left over from the Algolia-to-llms.txt search migration. search_mapbox_docs_tool's README entry still said it used "Algolia full-text search" — that was removed a while back (see the "Replace Algolia search with self-contained llms.txt search" entry below) and it now searches the self-hosted llms.txt index. Separately, get_document_tool's own description (the text shown to the LLM, not just docs) referenced a tool named get_latest_mapbox_docs_tool, which doesn't exist — it should have said search_mapbox_docs_tool, and was actively misdirecting tool-chaining behavior.
  • fix: startup/shutdown/error logging messages now actually reach clients. The McpServer never declared the logging capability, so every sendLoggingMessage call (including the existing "server started"/"shutting down"/"Fatal error" messages) was a silent no-op regardless of when it was sent. Declared logging: {} in the server's capabilities.
  • feat: the server now identifies which MCP client connected to it. server.server.getClientVersion() (populated from the clientInfo sent in the client's initialize request) is now logged on connect, e.g. Client identified as: claude-ai v1.0.0. Reading it required moving the read to a server.server.oninitialized callback rather than right after server.connect(), since getClientVersion() is only populated once the client's initialize request has actually been processed, which is not guaranteed by the time connect()'s promise resolves. Also recorded as mcp.client.name/mcp.client.version on every subsequent tool-execution trace span (withToolSpan), so OTel-backed traces can be filtered or grouped by client. Matches the equivalent changes landing in @mapbox/mcp-server and @mapbox/mcp-devkit-server.
  • chore: bump @modelcontextprotocol/sdk to 1.30.0. Verified this version's own SUPPORTED_PROTOCOL_VERSIONS constant does not include the 2026-07-28 spec revision (https://blog.modelcontextprotocol.io/posts/2026-07-28/) — this repo uses neither elicitation nor sampling, so that migration is lower-priority here regardless; tracked in #40.
  • chore: add scripts/check-llms-links.cjs (npm run check-llms-links) to report broken links across all llms.txt files exposed from docs.mapbox.com, and flag drift between the curated list in docsSearchIndex.ts and the live root index; npm run check-llms-links:deep (--deep) additionally crawls every docs.mapbox.com sub-link referenced in those files (currently ~1,400 URLs) to proactively catch broken doc pages before customers hit them (#39)
  • docs: note in CONTRIBUTING.md that unsolicited third-party directory/discovery listing PRs are out of scope and will be closed without review

0.3.1 - 2026-06-11

  • security: restrict document tool URL allowlist to documentation hosts and block access_token params (#34)
  • chore: upgrade @opentelemetry/* packages to latest minor versions (#TBD)

0.3.0 - 2026-04-15

Add OpenTelemetry tracing

  • Added src/utils/tracing.ts with initializeTracing(), shutdownTracing(), getTracer(), and withToolSpan() — mirrors the tracing implementation in mcp-server and mcp-devkit-server
  • BaseTool.run() now wraps every tool execution in a tool.<name> span via withToolSpan(); marks tool.error=true on tool-level errors
  • index.ts calls initializeTracing() on startup and shutdownTracing() on graceful exit
  • OTEL is a no-op unless OTEL_EXPORTER_OTLP_ENDPOINT or OTEL_EXPORTER_CONSOLE_ENABLED=true is set; fully suppresses diagnostic output on stdio to preserve MCP protocol
  • Exports initializeTracing, shutdownTracing, isTracingInitialized, getTracer, withToolSpan from @mapbox/mcp-docs-server/utils
  • Dependencies: @opentelemetry/api@^1.9.1, @opentelemetry/resources@^2.6.1, @opentelemetry/sdk-trace-base@^2.6.1, @opentelemetry/sdk-node@^0.214.0, @opentelemetry/instrumentation@^0.214.0, @opentelemetry/exporter-trace-otlp-http@^0.214.0, @opentelemetry/auto-instrumentations-node@^0.72.0, @opentelemetry/semantic-conventions@^1.40.0

Resources — use sublevel llms.txt per product

docs.mapbox.com restructured its documentation so that llms.txt files now exist at every product level (e.g. docs.mapbox.com/api/llms.txt, docs.mapbox.com/help/llms.txt, docs.mapbox.com/mapbox-gl-js/llms.txt) alongside llms-full.txt files containing full page content. The root docs.mapbox.com/llms.txt is now a pure index of links to these sublevel files rather than a monolithic content file. The previous resources all filtered the root file by category keyword — now that the root contains only link lists, they were effectively returning empty or useless content.

Updated resources to use the appropriate sublevel llms.txt files:

  • resource://mapbox-api-reference now fetches docs.mapbox.com/api/llms.txt — a clean, structured index of every Mapbox REST API grouped by service (Maps, Navigation, Search, Accounts) with links to full API reference pages
  • resource://mapbox-guides now fetches docs.mapbox.com/help/llms.txt (39KB) — the full Mapbox Help Center index with troubleshooting guides, how-to tutorials, and walkthroughs
  • resource://mapbox-sdk-docs now fetches docs.mapbox.com/mapbox-gl-js/llms.txt (34KB) — the GL JS documentation index listing all guides, API reference pages, and examples for the primary web mapping SDK
  • resource://mapbox-reference now fetches the root llms.txt without filtering and returns the complete product catalog — useful for discovering what documentation exists and finding llms.txt URLs for any product
  • resource://mapbox-examples continues to extract playground/demo/example sections from the root index (API Playgrounds, Demos & Projects)

docFetcher.fetchCachedText — new shared helper that fetches a URL and stores it in docCache, used by all five resources to avoid duplicating the fetch+cache pattern.

docFetcher.toMarkdownUrl — no longer rewrites URLs already ending in .txt, .md, or .json. Previously get_document_tool would try to fetch llms.txt.md before falling back; now it fetches llms.txt directly on the first attempt.

Replace Algolia search with self-contained llms.txt search

search_mapbox_docs_tool no longer depends on the Algolia third-party service. The hosted server shares a single Algolia free-tier quota across all users, making it prone to throttling as usage grows. The new implementation searches directly against the llms.txt index files that now exist at every product level on docs.mapbox.com.

How it works:

On first search, the tool fetches 12 product llms.txt files in parallel (~220KB total). Each file contains a structured list of documentation pages with titles, URLs, and one-line descriptions. These files are cached for the standard 1-hour TTL, so subsequent searches are pure in-memory keyword matching — no network calls.

Products indexed:

  • API Reference (api/llms.txt)
  • Mapbox GL JS (mapbox-gl-js/llms.txt)
  • Help Center (help/llms.txt)
  • Style Specification (style-spec/llms.txt)
  • Studio Manual (studio-manual/llms.txt)
  • Mapbox Search JS (mapbox-search-js/llms.txt)
  • Maps SDK for iOS and Android
  • Navigation SDK for iOS and Android
  • Mapbox Tiling Service
  • Tilesets

Scoring: Title matches (3×) outrank description matches (1×) and URL path matches (1×). Results are deduplicated by URL across sources and capped at the requested limit.

Reliability: Failed sources are silently skipped — if any single product llms.txt is unreachable, the remaining sources still return results.

fetchCachedText(url, httpRequest) — new helper in docFetcher.ts that fetches a URL and stores the response in docCache. Used by docsSearchIndex.ts to share the cache with the resource layer (which also caches llms.txt files). Fixed a subtle bug where empty-string responses ('') were not treated as cache hits due to falsy check — now uses !== null.

Raise docCache per-entry limit to 5 MB with size warnings

  • Hard cap raised from 2 MB → 5 MB — allows llms-full.txt files (Style Spec 466 KB, iOS Nav 696 KB, GL JS 1.6 MB) to be cached after being fetched via get_document_tool
  • Warning at 1 MB — console.warn when an entry between 1 MB and 5 MB is cached, so operators can see large entries in server logs
  • Warning on rejection — entries exceeding the 5 MB cap now log [docCache] Entry too large to cache instead of being silently dropped

Dependencies

  • Upgrade tshy to ^4.1.1, vitest to ^4.1.4, typescript to ^6.0.2 — removed deprecated baseUrl from tsconfig.base.json (TS6), added "types": ["node"] (required because tshy compiles from .tshy/ and does not auto-discover @types/node in CI); downgraded @types/node to ^22.0.0 for LTS consistency with other repos; bumped typescript-eslint packages to ^8.58.2 for TypeScript 6 support

Resources — use sublevel llms.txt per product

docs.mapbox.com restructured its documentation so that llms.txt files now exist at every product level (e.g. docs.mapbox.com/api/llms.txt, docs.mapbox.com/help/llms.txt, docs.mapbox.com/mapbox-gl-js/llms.txt) alongside llms-full.txt files containing full page content. The root docs.mapbox.com/llms.txt is now a pure index of links to these sublevel files rather than a monolithic content file. The previous resources all filtered the root file by category keyword — now that the root contains only link lists, they were effectively returning empty or useless content.

Updated resources to use the appropriate sublevel llms.txt files:

  • resource://mapbox-api-reference now fetches docs.mapbox.com/api/llms.txt — a clean, structured index of every Mapbox REST API grouped by service (Maps, Navigation, Search, Accounts) with links to full API reference pages
  • resource://mapbox-guides now fetches docs.mapbox.com/help/llms.txt (39KB) — the full Mapbox Help Center index with troubleshooting guides, how-to tutorials, and walkthroughs
  • resource://mapbox-sdk-docs now fetches docs.mapbox.com/mapbox-gl-js/llms.txt (34KB) — the GL JS documentation index listing all guides, API reference pages, and examples for the primary web mapping SDK
  • resource://mapbox-reference now fetches the root llms.txt without filtering and returns the complete product catalog — useful for discovering what documentation exists and finding llms.txt URLs for any product
  • resource://mapbox-examples continues to extract playground/demo/example sections from the root index (API Playgrounds, Demos & Projects)

docFetcher.fetchCachedText — new shared helper that fetches a URL and stores it in docCache, used by all five resources to avoid duplicating the fetch+cache pattern.

docFetcher.toMarkdownUrl — no longer rewrites URLs already ending in .txt, .md, or .json. Previously get_document_tool would try to fetch llms.txt.md before falling back; now it fetches llms.txt directly on the first attempt.

0.2.1 - 2026-04-01

Security

  • CVE-2026-4926: Upgraded @modelcontextprotocol/sdk to ^1.29.0, resolving path-to-regexp to 8.4.1 and fixing the ReDoS vulnerability GHSA-j3q9-mxjg-w52f

0.2.0 - 2026-04-01

Add search_mapbox_docs_tool

  • New search_mapbox_docs_tool searches all Mapbox documentation via the Algolia index powering docs.mapbox.com
  • Returns ranked results with titles, URLs, and content excerpts — use get_document_tool to fetch the full page content
  • Supports 1–20 results per query (default 5)

0.1.2 - 2026-03-18

0.1.1 - 2026-03-18

0.1.0 - 2026-03-18

0.1.0 - 2026-03-18

Add hosted deployment at mcp-docs.mapbox.com

  • @mapbox/mcp-docs-server is now available as a hosted MCP endpoint at https://mcp-docs.mapbox.com/mcp — no install or token required
  • Connect directly from Claude Code, Claude Desktop, Cursor, or VS Code using the url field in your MCP config

Update README: correct tool names and resources table (#9)

  • Replaced stale tool name references with get_document_tool and batch_get_documents_tool
  • Removed "coming soon" markers from all resources in the resources table
  • Dropped deprecated resource://mapbox-documentation entry

Add Claude automated code review workflow (#6)

  • Added .github/workflows/claude-review.yml using anthropics/claude-code-action@v1
  • Triggers automatically on PRs with ≥ 300 lines changed, or on any PR when a reviewer comments @claude

Add sub-path exports for tools, resources, and utils (#7)

  • Added barrel files src/tools/index.ts, src/resources/index.ts, and src/utils/index.ts
  • Exposed ./tools, ./resources, and ./utils sub-path exports via tshy and the exports map in package.json
  • Enables hosted-mcp-server and other consumers to import server internals directly without bundling the full entry point

Fix transient memory amplification in batch_get_documents_tool (#4)

  • Deduplicate intra-batch URLs by normalized key: multiple input URLs that resolve to the same page (e.g. cache-busting query params) now share a single HTTP request and a single buffered body instead of each triggering a separate fetch
  • Add streaming response body size cap via readBodyWithLimit: aborts reads that exceed 2 MB before the full body is buffered; also rejects on Content-Length before reading begins
  • Apply the same body size cap to get_document_tool

Fix unbounded cache growth in DocCache (#2)

  • Added a 512-entry LRU eviction limit to prevent unbounded Map growth
  • Added a 2 MB per-entry cap — oversized responses are not cached
  • Added a 50 MB total cache size cap with oldest-first eviction
  • Normalized cache keys by stripping query parameters and hash fragments, preventing cache-busting query strings from inflating the entry count
  • Added 22 unit tests covering all new cache invariants

Scaffold

  • MCP documentation server forked from mcp-devkit-server, retaining only documentation-related tools and resources
  • No API token required: All tools work without a Mapbox access token
  • Dual ESM/CJS build via tshy
  • TypeScript with strict mode, ESLint, Prettier, Husky + lint-staged
  • Vitest test suite with passWithNoTests
  • GitHub Actions CI workflow