Skip to content
Merged
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
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
## Unreleased

### Breaking Changes

- **MCP TypeScript SDK v2 (#296, part of #245).** The server and the `@mapbox/mcp-server/tools`, `/resources` and `/utils` exports now use the v2 SDK packages (`@modelcontextprotocol/server` and `@modelcontextprotocol/core`, 2.3.1) instead of `@modelcontextprotocol/sdk` 1.x, and `@modelcontextprotocol/ext-apps` moves from 1.x to 2.0.3. v2 is the line that gets new MCP features, such as the SDK's Skills extension support, and ext-apps 2.x requires it.
- **For code that imports our tools:** `installTo(server)` needs a v2 `McpServer`. A v1 server from `@modelcontextprotocol/sdk` won't work, so a deployment that builds its own server (the hosted server, for one) has to move to v2 in the same release. Tool and resource handlers now receive the v2 context: the access token is at `ctx.http.authInfo.token` instead of `extra.authInfo.token`.
- **Clients:** nothing changes. The server still answers the `initialize` handshake and negotiates 2025-11-25 with current clients, and the MCP Apps wire protocol is the same in ext-apps 2.x, so `render_map_tool` renders as before. Adopting the 2026-07-28 protocol revision (MRTR in place of elicitation, the Sampling replacement) is separate work under #245.
- **No more SDK patch:** the v1 SDK was patched so a tool's `structuredContent` that didn't match its output schema, or was missing, logged a warning instead of failing the call. v2 takes any Standard Schema as an output schema, so `lenientOutputSchema` wraps each tool's Zod schema: `tools/list` still publishes the real JSON Schema, and validation only warns. A tool with an output schema that returns only text gets `structuredContent: {}` instead of an error, since v2 checks for it before validating. `patches/` is now empty.
- **JSON Schema 2020-12:** v2 publishes tool schemas as 2020-12 itself, so `publishJsonSchema2020(server)` is now a deprecated no-op, kept so existing callers don't break. `toJsonSchema2020` is unchanged.
- **Removed:** `OptimizationV2Tool`, which was never registered and was built on the SDK's experimental tasks API, which v2 removes.
- **Codemod:** most of the change is `npx @modelcontextprotocol/codemod v1-to-v2 .` (import paths, method-string `setRequestHandler`, `RequestHandlerExtra` to `ServerContext`, `extra.authInfo` to `ctx.http?.authInfo`). `@modelcontextprotocol/client` and `@modelcontextprotocol/node` are dev dependencies, used only by tests and scripts.
- **Testing:** the old patch tests called `tool.run()` directly and never went through the SDK; they're replaced by tests that make a real `tools/call` through `McpServer` for a mismatched, a missing and a matching `structuredContent`, and they fail without the wrapper. Tests that built a request context by hand used the v1 `{ authInfo }` shape, so the token never reached the code under test; they now use `{ http: { authInfo } }`, which also makes the map app's secret-token checks test what they say. A stdio smoke test against the built server covers the handshake, all 30 tools with 2020-12 schemas, prompts, completions, resources, the MCP Apps UI resource, logging and a tool call.

### New Features

- **`feedback_tool`: report wrong map, place or routing data to Mapbox (#291).** When someone says a place has closed, a road is closed, or a route took an illegal turn, the agent can send it to the [Feedback API](https://docs.mapbox.com/api/feedback/) (`POST /user-feedback/v1/feedback`, Public Preview) with the text, a category and the location, usually taken from an earlier search or directions result. It returns the report's id and status (`received`).
Expand Down
20 changes: 7 additions & 13 deletions docs/importing-tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -332,15 +332,12 @@ import type { PromptInstance } from '@mapbox/mcp-server/prompts';
Here's how you might use these exports to build your own MCP server with a subset of tools. Each tool and resource registers itself with `installTo(server)`:

```typescript
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { McpServer } from '@modelcontextprotocol/server';
import { StdioServerTransport } from '@modelcontextprotocol/server/stdio';

import { getAllTools } from '@mapbox/mcp-server/tools';
import { getAllResources } from '@mapbox/mcp-server/resources';
import {
buildServerInstructions,
publishJsonSchema2020
} from '@mapbox/mcp-server/utils';
import { buildServerInstructions } from '@mapbox/mcp-server/utils';

// Pick only the tools you need. render_map_tool is only available through
// the registry, and it needs the map UI resource from getAllResources().
Expand All @@ -363,11 +360,6 @@ const server = new McpServer(
}
);

// Publish tool schemas as JSON Schema 2020-12 instead of the SDK's draft-07.
// Some clients (e.g. Claude Desktop) reject draft-07 output schemas.
// Must be called before the first tool is installed.
publishJsonSchema2020(server);

tools.forEach((tool) => tool.installTo(server));
getAllResources().forEach((resource) => resource.installTo(server));

Expand All @@ -378,9 +370,11 @@ await server.connect(transport);

### Server setup helpers

- `publishJsonSchema2020(server)`: converts every tool's `inputSchema`/`outputSchema` in `tools/list` from draft-07 to JSON Schema 2020-12. Call it on the `McpServer` before installing any tool.
- `buildServerInstructions(toolNames)`: returns the server `instructions` text for the given enabled tool names, or `undefined` when `render_map_tool` isn't among them.
- `toJsonSchema2020(schema)`: the converter behind `publishJsonSchema2020`, for converting a single schema.
- `toJsonSchema2020(schema)`: converts a single draft-07 JSON Schema to JSON Schema 2020-12.
- `publishJsonSchema2020(server)`: deprecated no-op. MCP SDK v1 published tool schemas as draft-07 and this converted them; SDK v2 publishes 2020-12 itself, so the call can be removed.

The tools and resources are built against MCP TypeScript SDK v2 (`@modelcontextprotocol/server`), so `installTo` needs a v2 `McpServer`. A v1 `McpServer` from `@modelcontextprotocol/sdk` won't work.

### Directions routes by reference

Expand Down
5 changes: 2 additions & 3 deletions evals/tool-selection/harness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@ import OpenAI from 'openai';
import { readFileSync } from 'node:fs';
import { dirname, resolve } from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js';
import { Client } from '@modelcontextprotocol/client';
import { McpServer, InMemoryTransport } from '@modelcontextprotocol/server';

const here = dirname(fileURLToPath(import.meta.url));
const SERVER_ROOT = resolve(
Expand Down
11 changes: 5 additions & 6 deletions examples/import-example.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
* a custom MCP server with a subset of Mapbox tools.
*/

import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { StdioServerTransport } from '@modelcontextprotocol/server/stdio';
import { McpServer } from '@modelcontextprotocol/server';

// Import pre-configured tool instances
import {
Expand Down Expand Up @@ -48,9 +48,9 @@ async function createCustomMcpServer() {

// Advanced usage: Create tools with custom HTTP pipeline
async function createServerWithCustomPipeline() {
const { McpServer } = await import('@modelcontextprotocol/sdk/server/mcp.js');
const { McpServer } = await import('@modelcontextprotocol/server');
const { StdioServerTransport } =
await import('@modelcontextprotocol/sdk/server/stdio.js');
await import('@modelcontextprotocol/server/stdio');
const { DirectionsTool } = await import('@mapbox/mcp-server/tools');
const { HttpPipeline, UserAgentPolicy, RetryPolicy } =
await import('@mapbox/mcp-server/utils');
Expand Down Expand Up @@ -107,8 +107,7 @@ async function createServerWithCustomPipeline() {

// Selective tool imports: Import only what you need to keep bundle size small
async function selectiveImports() {
const { McpServer: Server } =
await import('@modelcontextprotocol/sdk/server/mcp.js');
const { McpServer: Server } = await import('@modelcontextprotocol/server');

// Import just the Turf.js geometry tools (no HTTP calls needed)
const { area, distance, bearing, centroid } =
Expand Down
Loading
Loading