Note: If you're using Claude Code specifically, see CLAUDE.md instead. This file is for general AI coding assistants (Cursor, Continue, Aider, Copilot, etc.).
This is an MCP (Model Context Protocol) server that gives AI assistants access to Mapbox documentation and reference materials. No Mapbox access token is required for most tools — it is a documentation-only server.
- Runtime: Node.js 22+
- Language: TypeScript (strict mode)
- Build:
tshy(dual ESM/CJS output) - Testing: Vitest
- Package Manager: npm
src/
├── index.ts # MCP server entry point
├── config/toolConfig.ts # CLI argument parser
├── constants/ # Static data (API endpoint definitions)
├── resources/ # MCP resource implementations
│ ├── BaseResource.ts # Abstract base class
│ ├── resourceRegistry.ts # Resource registration
│ ├── utils/docParser.ts # Shared doc parsing utilities
│ └── */ # Individual resource implementations
├── tools/ # MCP tool implementations
│ ├── BaseTool.ts # Abstract base class
│ ├── toolRegistry.ts # Tool registration
│ └── */ # Individual tool implementations
└── utils/
├── httpPipeline.ts # HTTP pipeline (User-Agent, caching, retry)
├── types.ts # Shared types
└── versionUtils.ts
test/ # Mirrors src/ structure
- All tools extend
BaseTool<InputSchema, OutputSchema>(notMapboxApiBasedTool— that is in a different repo) execute(input)receives only the validated input — noaccessTokenorcontextparameters- If a tool needs a Mapbox token, it must be a field in the input schema
- Register tools in
src/tools/toolRegistry.ts
export class MyTool extends BaseTool<typeof MyInputSchema> {
readonly name = 'my_tool';
constructor({ httpRequest }: { httpRequest: HttpRequest }) {
super({ inputSchema: MyInputSchema });
this.httpRequest = httpRequest;
}
protected async execute(
input: z.infer<typeof MyInputSchema>
): Promise<CallToolResult> { ... }
}- Never patch
global.fetch— use the injectedhttpRequestfunction - Pass
httpRequestvia constructor so tools can be tested without network access - The shared
httpRequestfromsrc/utils/httpPipeline.tsadds User-Agent, 1-hour caching, and retry
- Use Vitest exclusively
- Mock all HTTP calls — no real network requests in tests
- Place tests in
test/mirroring thesrc/structure
npm install # Install dependencies
npm test # Run tests
npm run build # Compile TypeScript
npm run lint # ESLint
npm run format # Prettier check
npm run inspect:build # Test with MCP Inspector- Don't use
MapboxApiBasedTool— it doesn't exist here, useBaseTool - Don't patch
global.fetch— use thehttpRequestpipeline - Don't make real network calls in tests — mock
httpRequestwith a stub - Don't read the access token from an env variable — accept it as an input field if needed
- Don't commit without updating
CHANGELOG.md— add an entry underUnreleased
- Update
CHANGELOG.mdunder theUnreleasedsection - All tests must pass:
npm test - Lint and format must pass:
npm run lint && npm run format
- CLAUDE.md — detailed patterns and architecture
- CONTRIBUTING.md — contribution standards and code examples