Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
## Unreleased

### Features Added

- **Granular Documentation Resources**: Split monolithic documentation resource into focused, category-specific resources (#69)
- New `resource://mapbox-api-reference` - REST API documentation only
- New `resource://mapbox-sdk-docs` - SDK and client library documentation
- New `resource://mapbox-guides` - Tutorials, how-tos, and guides
- New `resource://mapbox-examples` - Code examples and API playgrounds
- New `resource://mapbox-reference` - Reference materials (tilesets, data products, etc.)
- Improved performance by allowing clients to fetch only relevant documentation
- Better organization for AI assistants to find the right information
- Original `resource://mapbox-documentation` kept for backward compatibility with deprecation notice
- Added shared `docParser` utility for parsing and categorizing documentation sections

### Documentation

- **PR Guidelines**: Added CHANGELOG requirement to CLAUDE.md (#67)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright (c) Mapbox, Inc.
// Licensed under the MIT License.

import type { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol.js';
import type {
ReadResourceResult,
ServerNotification,
ServerRequest
} from '@modelcontextprotocol/sdk/types.js';
import type { HttpRequest } from '../../utils/types.js';
import { BaseResource } from '../BaseResource.js';
import {
parseDocSections,
filterSectionsByCategory,
sectionsToMarkdown
} from '../utils/docParser.js';

/**
* Resource providing Mapbox API reference documentation
*/
export class MapboxApiReferenceResource extends BaseResource {
readonly name = 'Mapbox API Reference';
readonly uri = 'resource://mapbox-api-reference';
readonly description =
'Mapbox REST API reference documentation including endpoints, parameters, rate limits, and authentication for all Mapbox APIs (Geocoding, Directions, Static Images, Tilequery, etc.)';
readonly mimeType = 'text/markdown';

private httpRequest: HttpRequest;

constructor(params: { httpRequest: HttpRequest }) {
super();
this.httpRequest = params.httpRequest;
}

public async readCallback(
uri: URL,
_extra: RequestHandlerExtra<ServerRequest, ServerNotification>
): Promise<ReadResourceResult> {
try {
const response = await this.httpRequest(
'https://docs.mapbox.com/llms.txt',
{
headers: {
Accept: 'text/markdown, text/plain;q=0.9, */*;q=0.8'
}
}
);

if (!response.ok) {
throw new Error(
`Failed to fetch Mapbox documentation: ${response.statusText}`
);
}

const content = await response.text();

// Parse and filter for API sections only
const allSections = parseDocSections(content);
const apiSections = filterSectionsByCategory(allSections, 'apis');
const apiContent = sectionsToMarkdown(apiSections);

return {
contents: [
{
uri: uri.href,
mimeType: this.mimeType,
text: `# Mapbox API Reference\n\n${apiContent}`
}
]
};
} catch (error) {
const errorMessage =
error instanceof Error ? error.message : 'Unknown error occurred';
throw new Error(`Failed to fetch Mapbox API reference: ${errorMessage}`);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,21 @@ import { BaseResource } from '../BaseResource.js';
/**
* Resource providing the latest official Mapbox documentation
* fetched from docs.mapbox.com/llms.txt
*
* @deprecated Use the granular resources instead for better performance and organization:
* - resource://mapbox-api-reference (REST API docs)
* - resource://mapbox-sdk-docs (SDK documentation)
* - resource://mapbox-guides (Tutorials and how-tos)
* - resource://mapbox-examples (Code examples and playgrounds)
* - resource://mapbox-reference (Tilesets, data products, etc.)
*
* This resource is kept for backward compatibility.
*/
export class MapboxDocumentationResource extends BaseResource {
readonly name = 'Mapbox Documentation';
readonly uri = 'resource://mapbox-documentation';
readonly description =
'Latest official Mapbox documentation, APIs, SDKs, and developer resources. Always up-to-date comprehensive coverage of all current Mapbox services.';
'[DEPRECATED: Use granular resources like resource://mapbox-api-reference instead] Latest official Mapbox documentation, APIs, SDKs, and developer resources. Always up-to-date comprehensive coverage of all current Mapbox services.';
readonly mimeType = 'text/markdown';

private httpRequest: HttpRequest;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright (c) Mapbox, Inc.
// Licensed under the MIT License.

import type { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol.js';
import type {
ReadResourceResult,
ServerNotification,
ServerRequest
} from '@modelcontextprotocol/sdk/types.js';
import type { HttpRequest } from '../../utils/types.js';
import { BaseResource } from '../BaseResource.js';
import {
parseDocSections,
filterSectionsByCategory,
sectionsToMarkdown
} from '../utils/docParser.js';

/**
* Resource providing Mapbox examples and playgrounds
*/
export class MapboxExamplesResource extends BaseResource {
readonly name = 'Mapbox Examples';
readonly uri = 'resource://mapbox-examples';
readonly description =
'Mapbox code examples, API playgrounds, and interactive demos for testing and learning';
readonly mimeType = 'text/markdown';

private httpRequest: HttpRequest;

constructor(params: { httpRequest: HttpRequest }) {
super();
this.httpRequest = params.httpRequest;
}

public async readCallback(
uri: URL,
_extra: RequestHandlerExtra<ServerRequest, ServerNotification>
): Promise<ReadResourceResult> {
try {
const response = await this.httpRequest(
'https://docs.mapbox.com/llms.txt',
{
headers: {
Accept: 'text/markdown, text/plain;q=0.9, */*;q=0.8'
}
}
);

if (!response.ok) {
throw new Error(
`Failed to fetch Mapbox documentation: ${response.statusText}`
);
}

const content = await response.text();

// Parse and filter for example sections only
const allSections = parseDocSections(content);
const exampleSections = filterSectionsByCategory(allSections, 'examples');
const exampleContent = sectionsToMarkdown(exampleSections);

return {
contents: [
{
uri: uri.href,
mimeType: this.mimeType,
text: `# Mapbox Examples\n\n${exampleContent}`
}
]
};
} catch (error) {
const errorMessage =
error instanceof Error ? error.message : 'Unknown error occurred';
throw new Error(`Failed to fetch Mapbox examples: ${errorMessage}`);
}
}
}
77 changes: 77 additions & 0 deletions src/resources/mapbox-guides-resource/MapboxGuidesResource.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright (c) Mapbox, Inc.
// Licensed under the MIT License.

import type { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol.js';
import type {
ReadResourceResult,
ServerNotification,
ServerRequest
} from '@modelcontextprotocol/sdk/types.js';
import type { HttpRequest } from '../../utils/types.js';
import { BaseResource } from '../BaseResource.js';
import {
parseDocSections,
filterSectionsByCategory,
sectionsToMarkdown
} from '../utils/docParser.js';

/**
* Resource providing Mapbox guides and tutorials
*/
export class MapboxGuidesResource extends BaseResource {
readonly name = 'Mapbox Guides';
readonly uri = 'resource://mapbox-guides';
readonly description =
'Mapbox guides, tutorials, and how-tos including Studio Manual, map design guides, and best practices';
readonly mimeType = 'text/markdown';

private httpRequest: HttpRequest;

constructor(params: { httpRequest: HttpRequest }) {
super();
this.httpRequest = params.httpRequest;
}

public async readCallback(
uri: URL,
_extra: RequestHandlerExtra<ServerRequest, ServerNotification>
): Promise<ReadResourceResult> {
try {
const response = await this.httpRequest(
'https://docs.mapbox.com/llms.txt',
{
headers: {
Accept: 'text/markdown, text/plain;q=0.9, */*;q=0.8'
}
}
);

if (!response.ok) {
throw new Error(
`Failed to fetch Mapbox documentation: ${response.statusText}`
);
}

const content = await response.text();

// Parse and filter for guide sections only
const allSections = parseDocSections(content);
const guideSections = filterSectionsByCategory(allSections, 'guides');
const guideContent = sectionsToMarkdown(guideSections);

return {
contents: [
{
uri: uri.href,
mimeType: this.mimeType,
text: `# Mapbox Guides\n\n${guideContent}`
}
]
};
} catch (error) {
const errorMessage =
error instanceof Error ? error.message : 'Unknown error occurred';
throw new Error(`Failed to fetch Mapbox guides: ${errorMessage}`);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// Copyright (c) Mapbox, Inc.
// Licensed under the MIT License.

import type { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol.js';
import type {
ReadResourceResult,
ServerNotification,
ServerRequest
} from '@modelcontextprotocol/sdk/types.js';
import type { HttpRequest } from '../../utils/types.js';
import { BaseResource } from '../BaseResource.js';
import {
parseDocSections,
filterSectionsByCategory,
sectionsToMarkdown
} from '../utils/docParser.js';

/**
* Resource providing Mapbox reference documentation
*/
export class MapboxReferenceResource extends BaseResource {
readonly name = 'Mapbox Reference';
readonly uri = 'resource://mapbox-reference';
readonly description =
'Mapbox reference documentation including tilesets, data products, accounts, pricing, and other reference materials';
readonly mimeType = 'text/markdown';

private httpRequest: HttpRequest;

constructor(params: { httpRequest: HttpRequest }) {
super();
this.httpRequest = params.httpRequest;
}

public async readCallback(
uri: URL,
_extra: RequestHandlerExtra<ServerRequest, ServerNotification>
): Promise<ReadResourceResult> {
try {
const response = await this.httpRequest(
'https://docs.mapbox.com/llms.txt',
{
headers: {
Accept: 'text/markdown, text/plain;q=0.9, */*;q=0.8'
}
}
);

if (!response.ok) {
throw new Error(
`Failed to fetch Mapbox documentation: ${response.statusText}`
);
}

const content = await response.text();

// Parse and filter for reference sections only
const allSections = parseDocSections(content);
const referenceSections = filterSectionsByCategory(
allSections,
'reference'
);
const referenceContent = sectionsToMarkdown(referenceSections);

return {
contents: [
{
uri: uri.href,
mimeType: this.mimeType,
text: `# Mapbox Reference\n\n${referenceContent}`
}
]
};
} catch (error) {
const errorMessage =
error instanceof Error ? error.message : 'Unknown error occurred';
throw new Error(`Failed to fetch Mapbox reference: ${errorMessage}`);
}
}
}
Loading
Loading