From 1e72d21a350609109de0f998187a851cef976db7 Mon Sep 17 00:00:00 2001 From: Matthew Podwysocki Date: Mon, 12 Jan 2026 16:18:47 -0500 Subject: [PATCH 1/3] Add server-level icons with light and dark theme support Implements MCP server icons at the correct architectural level (server initialization) instead of at the tool level. Adds both light and dark theme variants of the Mapbox logo using base64-encoded SVG data URIs. - Add mapbox-logo-black.svg for light theme backgrounds - Add mapbox-logo-white.svg for dark theme backgrounds - Update server initialization to include icons array with theme property - Use 800x180 SVG logos embedded as base64 data URIs This replaces the previous incorrect approach of adding icons to individual tools, which was not aligned with the MCP specification. Co-Authored-By: Claude Sonnet 4.5 --- assets/mapbox-logo-black.svg | 38 ++++++++++++++++++++++++++++++++ assets/mapbox-logo-white.svg | 42 ++++++++++++++++++++++++++++++++++++ src/index.ts | 16 +++++++++++++- 3 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 assets/mapbox-logo-black.svg create mode 100644 assets/mapbox-logo-white.svg diff --git a/assets/mapbox-logo-black.svg b/assets/mapbox-logo-black.svg new file mode 100644 index 0000000..a0cbd94 --- /dev/null +++ b/assets/mapbox-logo-black.svg @@ -0,0 +1,38 @@ + + + +Mapbox_Logo_08 + + + + + + + + + + + + + + + diff --git a/assets/mapbox-logo-white.svg b/assets/mapbox-logo-white.svg new file mode 100644 index 0000000..8d62aef --- /dev/null +++ b/assets/mapbox-logo-white.svg @@ -0,0 +1,42 @@ + + + + +Mapbox_Logo_08 + + + + + + + + + + + + + + + diff --git a/src/index.ts b/src/index.ts index 50d53a7..c4313fe 100644 --- a/src/index.ts +++ b/src/index.ts @@ -66,7 +66,21 @@ const allResources = getAllResources(); const server = new McpServer( { name: versionInfo.name, - version: versionInfo.version + version: versionInfo.version, + icons: [ + { + src: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDIxLjAuMiwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9Im5ldyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiCgkgdmlld0JveD0iMCAwIDgwMCAxODAiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDgwMCAxODA7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4KPHRpdGxlPk1hcGJveF9Mb2dvXzA4PC90aXRsZT4KPGc+Cgk8Zz4KCQk8cGF0aCBkPSJNNTk0LjYsNDkuOGMtOS45LDAtMTkuNCw0LjEtMjYuMywxMS4zVjIzYzAtMS4yLTEtMi4yLTIuMi0yLjJsMCwwaC0xMy40Yy0xLjIsMC0yLjIsMS0yLjIsMi4ydjEwM2MwLDEuMiwxLDIuMiwyLjIsMi4yCgkJCWgxMy40YzEuMiwwLDIuMi0xLDIuMi0yLjJ2MHYtNy4xYzYuOSw3LjIsMTYuMywxMS4zLDI2LjMsMTEuM2MyMC45LDAsMzcuOC0xOCwzNy44LTQwLjJTNjE1LjUsNDkuOCw1OTQuNiw0OS44eiBNNTkxLjUsMTE0LjEKCQkJYy0xMi43LDAtMjMtMTAuNi0yMy4xLTIzLjh2LTAuNmMwLjItMTMuMiwxMC40LTIzLjgsMjMuMS0yMy44YzEyLjgsMCwyMy4xLDEwLjgsMjMuMSwyNC4xUzYwNC4yLDExNC4xLDU5MS41LDExNC4xTDU5MS41LDExNC4xeiIKCQkJLz4KCQk8cGF0aCBkPSJNNjgxLjcsNDkuOGMtMjIuNiwwLTQwLjksMTgtNDAuOSw0MC4yczE4LjMsNDAuMiw0MC45LDQwLjJjMjIuNiwwLDQwLjktMTgsNDAuOS00MC4yUzcwNC4zLDQ5LjgsNjgxLjcsNDkuOHoKCQkJIE02ODEuNiwxMTQuMWMtMTIuOCwwLTIzLjEtMTAuOC0yMy4xLTI0LjFzMTAuNC0yNC4xLDIzLjEtMjQuMXMyMy4xLDEwLjgsMjMuMSwyNC4xUzY5NC4zLDExNC4xLDY4MS42LDExNC4xTDY4MS42LDExNC4xeiIvPgoJCTxwYXRoIGQ9Ik00MzEuNiw1MS44aC0xMy40Yy0xLjIsMC0yLjIsMS0yLjIsMi4yYzAsMCwwLDAsMCwwdjcuMWMtNi45LTcuMi0xNi4zLTExLjMtMjYuMy0xMS4zYy0yMC45LDAtMzcuOCwxOC0zNy44LDQwLjIKCQkJczE2LjksNDAuMiwzNy44LDQwLjJjOS45LDAsMTkuNC00LjEsMjYuMy0xMS4zdjcuMWMwLDEuMiwxLDIuMiwyLjIsMi4ybDAsMGgxMy40YzEuMiwwLDIuMi0xLDIuMi0yLjJ2MFY1NAoJCQlDNDMzLjgsNTIuOCw0MzIuOCw1MS44LDQzMS42LDUxLjh6IE0zOTIuOCwxMTQuMWMtMTIuOCwwLTIzLjEtMTAuOC0yMy4xLTI0LjFzMTAuNC0yNC4xLDIzLjEtMjQuMWMxMi43LDAsMjMsMTAuNiwyMy4xLDIzLjh2MC42CgkJCUM0MTUuOCwxMDMuNSw0MDUuNSwxMTQuMSwzOTIuOCwxMTQuMUwzOTIuOCwxMTQuMXoiLz4KCQk8cGF0aCBkPSJNNDk4LjUsNDkuOGMtOS45LDAtMTkuNCw0LjEtMjYuMywxMS4zVjU0YzAtMS4yLTEtMi4yLTIuMi0yLjJsMCwwaC0xMy40Yy0xLjIsMC0yLjIsMS0yLjIsMi4yYzAsMCwwLDAsMCwwdjEwMwoJCQljMCwxLjIsMSwyLjIsMi4yLDIuMmwwLDBoMTMuNGMxLjIsMCwyLjItMSwyLjItMi4ydjB2LTM4LjFjNi45LDcuMiwxNi4zLDExLjMsMjYuMywxMS4zYzIwLjksMCwzNy44LTE4LDM3LjgtNDAuMgoJCQlTNTE5LjQsNDkuOCw0OTguNSw0OS44eiBNNDk1LjQsMTE0LjFjLTEyLjcsMC0yMy0xMC42LTIzLjEtMjMuOHYtMC42YzAuMi0xMy4yLDEwLjQtMjMuOCwyMy4xLTIzLjhjMTIuOCwwLDIzLjEsMTAuOCwyMy4xLDI0LjEKCQkJUzUwOC4yLDExNC4xLDQ5NS40LDExNC4xTDQ5NS40LDExNC4xeiIvPgoJCTxwYXRoIGQ9Ik0zMTEuOCw0OS44Yy0xMCwwLjEtMTkuMSw1LjktMjMuNCwxNWMtNC45LTkuMy0xNC43LTE1LjEtMjUuMi0xNWMtOC4yLDAtMTUuOSw0LTIwLjcsMTAuNlY1NGMwLTEuMi0xLTIuMi0yLjItMi4ybDAsMAoJCQloLTEzLjRjLTEuMiwwLTIuMiwxLTIuMiwyLjJjMCwwLDAsMCwwLDB2NzJjMCwxLjIsMSwyLjIsMi4yLDIuMmgwaDEzLjRjMS4yLDAsMi4yLTEsMi4yLTIuMnYwVjgyLjljMC41LTkuNiw3LjItMTcuMywxNS40LTE3LjMKCQkJYzguNSwwLDE1LjYsNy4xLDE1LjYsMTYuNHY0NGMwLDEuMiwxLDIuMiwyLjIsMi4ybDEzLjUsMGMxLjIsMCwyLjItMSwyLjItMi4yYzAsMCwwLDAsMCwwbC0wLjEtNDQuOGMxLjItOC44LDcuNS0xNS42LDE1LjItMTUuNgoJCQljOC41LDAsMTUuNiw3LjEsMTUuNiwxNi40djQ0YzAsMS4yLDEsMi4yLDIuMiwyLjJsMTMuNSwwYzEuMiwwLDIuMi0xLDIuMi0yLjJjMCwwLDAsMCwwLDBsLTAuMS00OS41CgkJCUMzMzkuOSw2MS43LDMyNy4zLDQ5LjgsMzExLjgsNDkuOHoiLz4KCQk8cGF0aCBkPSJNNzk0LjcsMTI1LjFsLTIzLjItMzUuM2wyMy0zNWMwLjYtMC45LDAuMy0yLjItMC42LTIuOGMtMC4zLTAuMi0wLjctMC4zLTEuMS0wLjNoLTE1LjVjLTEuMiwwLTIuMywwLjYtMi45LDEuNkw3NjAuOSw3NgoJCQlsLTEzLjUtMjIuNmMtMC42LTEtMS43LTEuNi0yLjktMS42aC0xNS41Yy0xLjEsMC0yLDAuOS0yLDJjMCwwLjQsMC4xLDAuOCwwLjMsMS4xbDIzLDM1bC0yMy4yLDM1LjNjLTAuNiwwLjktMC4zLDIuMiwwLjYsMi44CgkJCWMwLjMsMC4yLDAuNywwLjMsMS4xLDAuM2gxNS41YzEuMiwwLDIuMy0wLjYsMi45LTEuNmwxMy44LTIzbDEzLjgsMjNjMC42LDEsMS43LDEuNiwyLjksMS42SDc5M2MxLjEsMCwyLTAuOSwyLTIKCQkJQzc5NSwxMjUuOSw3OTQuOSwxMjUuNSw3OTQuNywxMjUuMXoiLz4KCTwvZz4KCTxnPgoJCTxwYXRoIGQ9Ik05My45LDEuMUM0NC44LDEuMSw1LDQwLjksNSw5MHMzOS44LDg4LjksODguOSw4OC45czg4LjktMzkuOCw4OC45LTg4LjlDMTgyLjgsNDAuOSwxNDMsMS4xLDkzLjksMS4xeiBNMTM2LjEsMTExLjgKCQkJYy0zMC40LDMwLjQtODQuNywyMC43LTg0LjcsMjAuN3MtOS44LTU0LjIsMjAuNy04NC43Qzg5LDMwLjksMTE3LDMxLjYsMTM0LjcsNDkuMlMxNTMsOTQuOSwxMzYuMSwxMTEuOEwxMzYuMSwxMTEuOHoiLz4KCQk8cG9seWdvbiBwb2ludHM9IjEwNC4xLDUzLjIgOTUuNCw3MS4xIDc3LjUsNzkuOCA5NS40LDg4LjUgMTA0LjEsMTA2LjQgMTEyLjgsODguNSAxMzAuNyw3OS44IDExMi44LDcxLjEgCQkiLz4KCTwvZz4KPC9nPgo8L3N2Zz4K', + mimeType: 'image/svg+xml', + sizes: ['800x180'], + theme: 'light' + }, + { + src: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDIxLjAuMiwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9Im5ldyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiCgkgdmlld0JveD0iMCAwIDgwMCAxODAiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDgwMCAxODA7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KCS5zdDB7ZmlsbDojRkZGRkZGO30KPC9zdHlsZT4KPHRpdGxlPk1hcGJveF9Mb2dvXzA4PC90aXRsZT4KPGc+Cgk8Zz4KCQk8cGF0aCBjbGFzcz0ic3QwIiBkPSJNNTk0LjYsNDkuOGMtOS45LDAtMTkuNCw0LjEtMjYuMywxMS4zVjIzYzAtMS4yLTEtMi4yLTIuMi0yLjJsMCwwaC0xMy40Yy0xLjIsMC0yLjIsMS0yLjIsMi4ydjEwMwoJCQljMCwxLjIsMSwyLjIsMi4yLDIuMmgxMy40YzEuMiwwLDIuMi0xLDIuMi0yLjJ2MHYtNy4xYzYuOSw3LjIsMTYuMywxMS4zLDI2LjMsMTEuM2MyMC45LDAsMzcuOC0xOCwzNy44LTQwLjIKCQkJUzYxNS41LDQ5LjgsNTk0LjYsNDkuOHogTTU5MS41LDExNC4xYy0xMi43LDAtMjMtMTAuNi0yMy4xLTIzLjh2LTAuNmMwLjItMTMuMiwxMC40LTIzLjgsMjMuMS0yMy44YzEyLjgsMCwyMy4xLDEwLjgsMjMuMSwyNC4xCgkJCVM2MDQuMiwxMTQuMSw1OTEuNSwxMTQuMUw1OTEuNSwxMTQuMXoiLz4KCQk8cGF0aCBjbGFzcz0ic3QwIiBkPSJNNjgxLjcsNDkuOGMtMjIuNiwwLTQwLjksMTgtNDAuOSw0MC4yczE4LjMsNDAuMiw0MC45LDQwLjJjMjIuNiwwLDQwLjktMTgsNDAuOS00MC4yUzcwNC4zLDQ5LjgsNjgxLjcsNDkuOHoKCQkJIE02ODEuNiwxMTQuMWMtMTIuOCwwLTIzLjEtMTAuOC0yMy4xLTI0LjFzMTAuNC0yNC4xLDIzLjEtMjQuMXMyMy4xLDEwLjgsMjMuMSwyNC4xUzY5NC4zLDExNC4xLDY4MS42LDExNC4xTDY4MS42LDExNC4xeiIvPgoJCTxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik00MzEuNiw1MS44aC0xMy40Yy0xLjIsMC0yLjIsMS0yLjIsMi4yYzAsMCwwLDAsMCwwdjcuMWMtNi45LTcuMi0xNi4zLTExLjMtMjYuMy0xMS4zCgkJCWMtMjAuOSwwLTM3LjgsMTgtMzcuOCw0MC4yczE2LjksNDAuMiwzNy44LDQwLjJjOS45LDAsMTkuNC00LjEsMjYuMy0xMS4zdjcuMWMwLDEuMiwxLDIuMiwyLjIsMi4ybDAsMGgxMy40YzEuMiwwLDIuMi0xLDIuMi0yLjIKCQkJdjBWNTRDNDMzLjgsNTIuOCw0MzIuOCw1MS44LDQzMS42LDUxLjh6IE0zOTIuOCwxMTQuMWMtMTIuOCwwLTIzLjEtMTAuOC0yMy4xLTI0LjFzMTAuNC0yNC4xLDIzLjEtMjQuMWMxMi43LDAsMjMsMTAuNiwyMy4xLDIzLjgKCQkJdjAuNkM0MTUuOCwxMDMuNSw0MDUuNSwxMTQuMSwzOTIuOCwxMTQuMUwzOTIuOCwxMTQuMXoiLz4KCQk8cGF0aCBjbGFzcz0ic3QwIiBkPSJNNDk4LjUsNDkuOGMtOS45LDAtMTkuNCw0LjEtMjYuMywxMS4zVjU0YzAtMS4yLTEtMi4yLTIuMi0yLjJsMCwwaC0xMy40Yy0xLjIsMC0yLjIsMS0yLjIsMi4yYzAsMCwwLDAsMCwwCgkJCXYxMDNjMCwxLjIsMSwyLjIsMi4yLDIuMmwwLDBoMTMuNGMxLjIsMCwyLjItMSwyLjItMi4ydjB2LTM4LjFjNi45LDcuMiwxNi4zLDExLjMsMjYuMywxMS4zYzIwLjksMCwzNy44LTE4LDM3LjgtNDAuMgoJCQlTNTE5LjQsNDkuOCw0OTguNSw0OS44eiBNNDk1LjQsMTE0LjFjLTEyLjcsMC0yMy0xMC42LTIzLjEtMjMuOHYtMC42YzAuMi0xMy4yLDEwLjQtMjMuOCwyMy4xLTIzLjhjMTIuOCwwLDIzLjEsMTAuOCwyMy4xLDI0LjEKCQkJUzUwOC4yLDExNC4xLDQ5NS40LDExNC4xTDQ5NS40LDExNC4xeiIvPgoJCTxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik0zMTEuOCw0OS44Yy0xMCwwLjEtMTkuMSw1LjktMjMuNCwxNWMtNC45LTkuMy0xNC43LTE1LjEtMjUuMi0xNWMtOC4yLDAtMTUuOSw0LTIwLjcsMTAuNlY1NAoJCQljMC0xLjItMS0yLjItMi4yLTIuMmwwLDBoLTEzLjRjLTEuMiwwLTIuMiwxLTIuMiwyLjJjMCwwLDAsMCwwLDB2NzJjMCwxLjIsMSwyLjIsMi4yLDIuMmgwaDEzLjRjMS4yLDAsMi4yLTEsMi4yLTIuMnYwVjgyLjkKCQkJYzAuNS05LjYsNy4yLTE3LjMsMTUuNC0xNy4zYzguNSwwLDE1LjYsNy4xLDE1LjYsMTYuNHY0NGMwLDEuMiwxLDIuMiwyLjIsMi4ybDEzLjUsMGMxLjIsMCwyLjItMSwyLjItMi4yYzAsMCwwLDAsMCwwbC0wLjEtNDQuOAoJCQljMS4yLTguOCw3LjUtMTUuNiwxNS4yLTE1LjZjOC41LDAsMTUuNiw3LjEsMTUuNiwxNi40djQ0YzAsMS4yLDEsMi4yLDIuMiwyLjJsMTMuNSwwYzEuMiwwLDIuMi0xLDIuMi0yLjJjMCwwLDAsMCwwLDBsLTAuMS00OS41CgkJCUMzMzkuOSw2MS43LDMyNy4zLDQ5LjgsMzExLjgsNDkuOHoiLz4KCQk8cGF0aCBjbGFzcz0ic3QwIiBkPSJNNzk0LjcsMTI1LjFsLTIzLjItMzUuM2wyMy0zNWMwLjYtMC45LDAuMy0yLjItMC42LTIuOGMtMC4zLTAuMi0wLjctMC4zLTEuMS0wLjNoLTE1LjUKCQkJYy0xLjIsMC0yLjMsMC42LTIuOSwxLjZMNzYwLjksNzZsLTEzLjUtMjIuNmMtMC42LTEtMS43LTEuNi0yLjktMS42aC0xNS41Yy0xLjEsMC0yLDAuOS0yLDJjMCwwLjQsMC4xLDAuOCwwLjMsMS4xbDIzLDM1CgkJCWwtMjMuMiwzNS4zYy0wLjYsMC45LTAuMywyLjIsMC42LDIuOGMwLjMsMC4yLDAuNywwLjMsMS4xLDAuM2gxNS41YzEuMiwwLDIuMy0wLjYsMi45LTEuNmwxMy44LTIzbDEzLjgsMjNjMC42LDEsMS43LDEuNiwyLjksMS42CgkJCUg3OTNjMS4xLDAsMi0wLjksMi0yQzc5NSwxMjUuOSw3OTQuOSwxMjUuNSw3OTQuNywxMjUuMXoiLz4KCTwvZz4KCTxnPgoJCTxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik05My45LDEuMUM0NC44LDEuMSw1LDQwLjksNSw5MHMzOS44LDg4LjksODguOSw4OC45czg4LjktMzkuOCw4OC45LTg4LjlDMTgyLjgsNDAuOSwxNDMsMS4xLDkzLjksMS4xegoJCQkgTTEzNi4xLDExMS44Yy0zMC40LDMwLjQtODQuNywyMC43LTg0LjcsMjAuN3MtOS44LTU0LjIsMjAuNy04NC43Qzg5LDMwLjksMTE3LDMxLjYsMTM0LjcsNDkuMlMxNTMsOTQuOSwxMzYuMSwxMTEuOEwxMzYuMSwxMTEuOAoJCQl6Ii8+CgkJPHBvbHlnb24gY2xhc3M9InN0MCIgcG9pbnRzPSIxMDQuMSw1My4yIDk1LjQsNzEuMSA3Ny41LDc5LjggOTUuNCw4OC41IDEwNC4xLDEwNi40IDExMi44LDg4LjUgMTMwLjcsNzkuOCAxMTIuOCw3MS4xIAkJIi8+Cgk8L2c+CjwvZz4KPC9zdmc+Cg==', + mimeType: 'image/svg+xml', + sizes: ['800x180'], + theme: 'dark' + } + ] }, { capabilities: { From c20582133bba072c7d879d77d1650a06c301bc07 Mon Sep 17 00:00:00 2001 From: Matthew Podwysocki Date: Mon, 12 Jan 2026 16:24:43 -0500 Subject: [PATCH 2/3] Update @modelcontextprotocol/sdk to 1.25.2 Updates the MCP SDK from 1.25.1 to 1.25.2 and recreates the output validation patch for the new version. The patch continues to convert strict output schema validation errors to warnings, allowing tools to gracefully handle schema mismatches. Changes: - Update @modelcontextprotocol/sdk from ^1.25.1 to ^1.25.2 - Recreate SDK patch for version 1.25.2 - Remove obsolete 1.25.1 patch file - All 397 tests pass with new SDK version Co-Authored-By: Claude Sonnet 4.5 --- package-lock.json | 8 ++++---- package.json | 2 +- ....25.1.patch => @modelcontextprotocol+sdk+1.25.2.patch} | 0 3 files changed, 5 insertions(+), 5 deletions(-) rename patches/{@modelcontextprotocol+sdk+1.25.1.patch => @modelcontextprotocol+sdk+1.25.2.patch} (100%) diff --git a/package-lock.json b/package-lock.json index 87d6481..1fae152 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "license": "MIT", "dependencies": { "@mcp-ui/server": "^5.13.1", - "@modelcontextprotocol/sdk": "^1.25.1", + "@modelcontextprotocol/sdk": "^1.25.2", "@opentelemetry/api": "^1.9.0", "@opentelemetry/auto-instrumentations-node": "^0.56.0", "@opentelemetry/exporter-trace-otlp-http": "^0.56.0", @@ -1913,9 +1913,9 @@ } }, "node_modules/@modelcontextprotocol/sdk": { - "version": "1.25.1", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.25.1.tgz", - "integrity": "sha512-yO28oVFFC7EBoiKdAn+VqRm+plcfv4v0xp6osG/VsCB0NlPZWi87ajbCZZ8f/RvOFLEu7//rSRmuZZ7lMoe3gQ==", + "version": "1.25.2", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.25.2.tgz", + "integrity": "sha512-LZFeo4F9M5qOhC/Uc1aQSrBHxMrvxett+9KLHt7OhcExtoiRN9DKgbZffMP/nxjutWDQpfMDfP3nkHI4X9ijww==", "license": "MIT", "dependencies": { "@hono/node-server": "^1.19.7", diff --git a/package.json b/package.json index 5c5e77a..304046d 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ ], "dependencies": { "@mcp-ui/server": "^5.13.1", - "@modelcontextprotocol/sdk": "^1.25.1", + "@modelcontextprotocol/sdk": "^1.25.2", "@opentelemetry/api": "^1.9.0", "@opentelemetry/auto-instrumentations-node": "^0.56.0", "@opentelemetry/exporter-trace-otlp-http": "^0.56.0", diff --git a/patches/@modelcontextprotocol+sdk+1.25.1.patch b/patches/@modelcontextprotocol+sdk+1.25.2.patch similarity index 100% rename from patches/@modelcontextprotocol+sdk+1.25.1.patch rename to patches/@modelcontextprotocol+sdk+1.25.2.patch From 8a9f17937f330158620c768fc2ba2a0472e84332 Mon Sep 17 00:00:00 2001 From: Matthew Podwysocki Date: Wed, 28 Jan 2026 10:05:05 -0500 Subject: [PATCH 3/3] Add MCP Apps support alongside MCP-UI Implement the MCP Apps pattern for static_map_image_tool, maintaining backward compatibility by supporting both patterns simultaneously. Changes: - Add _meta.ui.resourceUri to static_map_image_tool response for MCP Apps pattern - Create StaticMapUIResource (ui:// scheme) for static map previews - Register StaticMapUIResource in resourceRegistry.ts The MCP Apps pattern enables broader client compatibility (Claude Code, VS Code) while preserving existing MCP-UI functionality. The tool now returns both: 1. MCP-UI resource content via createUIResource() 2. MCP Apps metadata via _meta.ui.resourceUri This graceful degradation allows clients to use whichever pattern they support. Related: https://blog.modelcontextprotocol.io/posts/2026-01-26-mcp-apps/ All tests passing (582 tests). --- src/resources/resourceRegistry.ts | 5 +- src/resources/ui-apps/StaticMapUIResource.ts | 114 ++++++++++++++++++ .../StaticMapImageTool.ts | 15 ++- 3 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 src/resources/ui-apps/StaticMapUIResource.ts diff --git a/src/resources/resourceRegistry.ts b/src/resources/resourceRegistry.ts index 84cdac7..e94e0a3 100644 --- a/src/resources/resourceRegistry.ts +++ b/src/resources/resourceRegistry.ts @@ -3,12 +3,15 @@ // INSERT NEW RESOURCE IMPORT HERE import { CategoryListResource } from './category-list/CategoryListResource.js'; +import { StaticMapUIResource } from './ui-apps/StaticMapUIResource.js'; import { httpRequest } from '../utils/httpPipeline.js'; // Central registry of all resources export const ALL_RESOURCES = [ // INSERT NEW RESOURCE INSTANCE HERE - new CategoryListResource({ httpRequest }) + new CategoryListResource({ httpRequest }), + // MCP Apps UI resources (ui:// scheme) + new StaticMapUIResource() ] as const; export type ResourceInstance = (typeof ALL_RESOURCES)[number]; diff --git a/src/resources/ui-apps/StaticMapUIResource.ts b/src/resources/ui-apps/StaticMapUIResource.ts new file mode 100644 index 0000000..0109e92 --- /dev/null +++ b/src/resources/ui-apps/StaticMapUIResource.ts @@ -0,0 +1,114 @@ +// Copyright (c) Mapbox, Inc. +// Licensed under the MIT License. + +import type { ReadResourceResult } from '@modelcontextprotocol/sdk/types.js'; +import { BaseResource } from '../BaseResource.js'; + +/** + * Serves UI App HTML for Static Map Preview + * Implements MCP Apps pattern with ui:// scheme + */ +export class StaticMapUIResource extends BaseResource { + readonly name = 'Static Map Preview UI'; + readonly uri = 'ui://mapbox/static-map/*'; + readonly description = + 'Interactive UI for previewing static map images (MCP Apps)'; + readonly mimeType = 'text/html'; + + public async read(uri: string): Promise { + // Parse URI to extract style and position + // Format: ui://mapbox/static-map/{style}/{lng},{lat},{zoom} + const parsedUri = new URL(uri); + const pathParts = parsedUri.pathname.split('/').filter((p) => p); + const style = pathParts[2]; + const position = pathParts[3]; + + if (!style || !position) { + return { + contents: [ + { + uri: uri, + mimeType: 'text/plain', + text: 'Error: Invalid URI format. Expected ui://mapbox/static-map/{style}/{lng},{lat},{zoom}' + } + ] + }; + } + + // Generate HTML with embedded iframe for static map + const html = ` + + + + + Static Map Preview + + + +
Loading static map preview...
+ + + + +`; + + return { + contents: [ + { + uri: uri, + mimeType: 'text/html', + text: html + } + ] + }; + } +} diff --git a/src/tools/static-map-image-tool/StaticMapImageTool.ts b/src/tools/static-map-image-tool/StaticMapImageTool.ts index 7a9123c..6802a82 100644 --- a/src/tools/static-map-image-tool/StaticMapImageTool.ts +++ b/src/tools/static-map-image-tool/StaticMapImageTool.ts @@ -166,9 +166,22 @@ export class StaticMapImageTool extends MapboxApiBasedTool< content.push(uiResource); } - return { + // Add MCP Apps metadata (new pattern for broader client compatibility) + const result: CallToolResult = { content, isError: false }; + + // Add ui:// resource URI for MCP Apps pattern + // This works alongside MCP-UI for backward compatibility + if (isMcpUiEnabled()) { + result._meta = { + ui: { + resourceUri: `ui://mapbox/static-map/${input.style}/${lng},${lat},${input.zoom}` + } + }; + } + + return result; } }