Skip to content

Commit 2817d8f

Browse files
[mcp-ui] Adding MCP-UI support to those that support URLs
1 parent e846426 commit 2817d8f

File tree

2 files changed

+45
-2
lines changed

2 files changed

+45
-2
lines changed

src/tools/geojson-preview-tool/GeojsonPreviewTool.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
55
import { createUIResource } from '@mcp-ui/server';
6+
import { createHash } from 'node:crypto';
67
import { GeoJSON } from 'geojson';
78
import { BaseTool } from '../BaseTool.js';
89
import {
@@ -84,8 +85,15 @@ export class GeojsonPreviewTool extends BaseTool<typeof GeojsonPreviewSchema> {
8485

8586
// Conditionally add MCP-UI resource if enabled
8687
if (isMcpUiEnabled()) {
88+
// Create content-addressable URI using hash of GeoJSON
89+
// This enables client-side caching - same GeoJSON = same URI
90+
const contentHash = createHash('md5')
91+
.update(geojsonString)
92+
.digest('hex')
93+
.substring(0, 16); // Use first 16 chars for brevity
94+
8795
const uiResource = createUIResource({
88-
uri: `ui://mapbox/geojson-preview/${Date.now()}`,
96+
uri: `ui://mapbox/geojson-preview/${contentHash}`,
8997
content: {
9098
type: 'externalUrl',
9199
iframeUrl: geojsonIOUrl

test/tools/style-comparison-tool/StyleComparisonTool.test.ts

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ describe('StyleComparisonTool', () => {
1717
});
1818

1919
describe('run', () => {
20-
it('should generate comparison URL with provided access token', async () => {
20+
it('should generate comparison URL and MCP-UI resource with provided access token (default)', async () => {
2121
const input = {
2222
before: 'mapbox/streets-v12',
2323
after: 'mapbox/outdoors-v12',
@@ -27,12 +27,27 @@ describe('StyleComparisonTool', () => {
2727
const result = await tool.run(input);
2828

2929
expect(result.isError).toBe(false);
30+
expect(result.content).toHaveLength(2);
3031
expect(result.content[0].type).toBe('text');
3132
const url = (result.content[0] as { type: 'text'; text: string }).text;
3233
expect(url).toContain('https://agent.mapbox.com/tools/style-compare');
3334
expect(url).toContain('access_token=pk.test.token');
3435
expect(url).toContain('before=mapbox%2Fstreets-v12');
3536
expect(url).toContain('after=mapbox%2Foutdoors-v12');
37+
38+
// Verify MCP-UI resource is included by default
39+
expect(result.content[1]).toMatchObject({
40+
type: 'resource',
41+
resource: {
42+
uri: expect.stringMatching(
43+
/^ui:\/\/mapbox\/style-comparison\/mapbox\/streets-v12\/mapbox\/outdoors-v12$/
44+
),
45+
mimeType: 'text/uri-list',
46+
text: expect.stringContaining(
47+
'https://agent.mapbox.com/tools/style-compare'
48+
)
49+
}
50+
});
3651
});
3752

3853
it('should require access token', async () => {
@@ -198,6 +213,26 @@ describe('StyleComparisonTool', () => {
198213
const url2 = (result2.content[0] as { type: 'text'; text: string }).text;
199214
expect(url2).not.toContain('#');
200215
});
216+
217+
it('should return only URL when MCP-UI is disabled', async () => {
218+
// Disable MCP-UI for this test
219+
process.env.ENABLE_MCP_UI = 'false';
220+
221+
const input = {
222+
before: 'mapbox/streets-v12',
223+
after: 'mapbox/outdoors-v12',
224+
accessToken: 'pk.test.token'
225+
};
226+
227+
const result = await tool.run(input);
228+
229+
expect(result.isError).toBe(false);
230+
expect(result.content).toHaveLength(1);
231+
expect(result.content[0].type).toBe('text');
232+
233+
// Clean up
234+
delete process.env.ENABLE_MCP_UI;
235+
});
201236
});
202237

203238
describe('metadata', () => {

0 commit comments

Comments
 (0)