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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

### Fixed

- **`create-and-preview-style` prompt now defaults to the Standard base style, not Classic `streets-v12`.** `StyleBuilderTool` (used by every other style-related prompt in this repo) has defaulted `base_style` to `"standard"` for a while — "ALWAYS use 'standard' as the default for all new styles" — but this prompt's own `base_style` fallback and its "Create the map style" step were never updated to match: it hardcoded `streets-v12` and hand-authored a bare Classic-style JSON skeleton (`sources`/`layers` background fill) directly in the prompt text, disconnected from the `base_style` argument entirely. Now defaults to `"standard"` and, like `build-custom-map` and other prompts in this repo, delegates style construction to `style_builder_tool` (which knows how to build either Standard or Classic structures correctly) instead of hand-rolling a Classic-only skeleton that would have been wrong for any base style other than the one it hardcoded.
- **Startup logging messages (`.env` status, tracing status, detected client capabilities) now actually reach clients.** The `McpServer` never declared the `logging` capability, so every `sendLoggingMessage` call was a silent no-op regardless of when it was sent. Several of those calls also ran before `server.connect(transport)`, which would have dropped them anyway even with the capability declared, since there's no connected client yet to receive a notification sent before the transport is connected. Fixed both: `logging: {}` is now declared in the server's capabilities, and startup logging is deferred until after `connect()`. Covered by a new integration test that spawns the real built server and asserts a real client receives at least one startup log message.
- **The server now identifies which MCP client connected to it, and fixes a related capability-read race.** `server.server.getClientVersion()`/`getClientCapabilities()` are only populated once the client's `initialize` request has been processed, which is not guaranteed by the time `server.connect()`'s promise resolves (it only waits for the transport to start). Reading them right after `connect()`, as the existing capability-gated tool registration did, reliably saw them as unset — confirmed live, even for a client that explicitly declared `elicitation` support. Both reads now happen inside a `server.server.oninitialized` callback, which only fires once the handshake is fully done. As part of this, the client's identity (name/version from its `initialize` request) is now logged on connect (e.g. `Client identified as: claude-ai v1.0.0`) and recorded as `mcp.client.name`/`mcp.client.version` on every subsequent tool-execution trace span, so OTel-backed traces can be filtered or grouped by client.

Expand Down
55 changes: 22 additions & 33 deletions src/prompts/CreateAndPreviewStylePrompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ import { BasePrompt, type PromptArgument } from './BasePrompt.js';
* This prompt orchestrates multiple tools to:
* 1. Check for an existing public token with styles:read scope
* 2. Create a new public token if needed
* 3. Create the map style
* 4. Generate a preview link using the public token
* 3. Build the style specification (style_builder_tool, defaulting to the Standard base style)
* 4. Create the map style (create_style_tool)
* 5. Generate a preview link using the public token
*/
export class CreateAndPreviewStylePrompt extends BasePrompt {
readonly name = 'create-and-preview-style';
Expand All @@ -32,7 +33,7 @@ export class CreateAndPreviewStylePrompt extends BasePrompt {
{
name: 'base_style',
description:
'Optional base style to start from (e.g., "streets-v12", "outdoors-v12", "light-v11", "dark-v11")',
'Optional base style to start from. Defaults to "standard" (Mapbox\'s modern default). Only use a Classic style (e.g., "streets-v12", "outdoors-v12", "light-v11", "dark-v11") if explicitly requested.',
required: false
},
{
Expand All @@ -51,7 +52,7 @@ export class CreateAndPreviewStylePrompt extends BasePrompt {
getMessages(args: Record<string, string>): PromptMessage[] {
const styleName = args['style_name'];
const styleDescription = args['style_description'];
const baseStyle = args['base_style'] || 'streets-v12';
const baseStyle = args['base_style'] || 'standard';
const previewLocation = args['preview_location'];
const previewZoom = args['preview_zoom'] || '12';

Expand All @@ -71,38 +72,26 @@ Follow these steps carefully:
* scopes: ["styles:read"]
- Save the token value from the response

3. **Create the map style**
- Use the create_style_tool to create the new style
- Style name: "${styleName}"`;
3. **Build the map style**
- Use the style_builder_tool to generate the style specification
- style_name: "${styleName}"
- base_style: "${baseStyle}"`;

if (styleDescription) {
instructionText += `\n - Description: "${styleDescription}"`;
instructionText += `\n - Interpret this description into appropriate \`layers\`/\`global_settings\` entries: "${styleDescription}". If there's nothing specific to customize, pass an empty \`layers\` array to use ${baseStyle} as-is.`;
} else {
instructionText += `\n - No specific customizations requested — pass an empty \`layers\` array to use ${baseStyle} as-is.`;
}

instructionText += `\n - Base the style on Mapbox ${baseStyle}
- You can start with a basic style like:
\`\`\`json
{
"version": 8,
"name": "${styleName}",
"sources": {
"mapbox": {
"type": "vector",
"url": "mapbox://mapbox.mapbox-streets-v8"
}
},
"layers": [
{
"id": "background",
"type": "background",
"paint": { "background-color": "#f0f0f0" }
}
]
}
\`\`\`
instructionText += `\n - The tool returns a complete Mapbox GL JS style specification

4. **Create the map style**
- Use the create_style_tool to save the generated style to the Mapbox account
- Style name: "${styleName}"
- Include the complete style specification from step 3
- Save the style ID from the response

4. **Generate preview link**
5. **Generate preview link**
- Use the preview_style_tool with the style ID you just created`;

if (previewLocation) {
Expand All @@ -112,16 +101,16 @@ Follow these steps carefully:
instructionText += `\n - Set zoom level to: ${previewZoom}
- The tool will automatically use the public token you created/found earlier

5. **Validate the style**
6. **Validate the style**
- Automatically run validation using the prepare-style-for-production prompt
- Pass the style ID from step 3 as the style_id_or_json parameter
- Pass the style ID from step 4 as the style_id_or_json parameter
- This checks:
* Expression syntax and correctness
* Color contrast for accessibility (WCAG AA)
* Style optimization opportunities
- Validation is fast (offline processing only)

6. **Present complete results**
7. **Present complete results**
- Show the user:
* The created style ID
* The preview URL (they can click to open in browser)
Expand Down
19 changes: 19 additions & 0 deletions test/prompts/CreateAndPreviewStylePrompt.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,25 @@ describe('CreateAndPreviewStylePrompt', () => {
expect(text).toContain('preview_style_tool');
});

it('defaults base_style to "standard", not the Classic "streets-v12"', () => {
const result = prompt.execute({ style_name: 'Test Style' });
const text = result.messages[0].content.text;

expect(text).toContain('base_style: "standard"');
expect(text).not.toContain('streets-v12');
expect(text).toContain('style_builder_tool');
});

it('respects an explicit Classic base_style override', () => {
const result = prompt.execute({
style_name: 'Test Style',
base_style: 'streets-v12'
});
const text = result.messages[0].content.text;

expect(text).toContain('base_style: "streets-v12"');
});

it('should include optional arguments in messages', () => {
const result = prompt.execute({
style_name: 'Test Style',
Expand Down