{"$schema":"https://ejfox.com/schema/page-twin@1.json","kind":"blog_post","url":"https://ejfox.com/blog/2025/mcp-meta-mapping","json_url":"https://ejfox.com/blog/2025/mcp-meta-mapping.json","generator":"ejfox.com/json-twin@1","data":{"cacheVersion":"2026-05-13-gear-cards","html":"<h2 class=\"\" id=\"mapping-novel-territories-untangling-mcp-servers\">Mapping Novel Territories: Untangling MCP Servers</h2>\n<p class=\"\">There are now <em class=\"\">so many</em> MCP servers which is both overwhelming and exciting for me.</p>\n<p class=\"\">Right now, all the MCP servers you add are made available to your robot at all times. That means that each tool and its description are taking up some of your context window, whether they are relevant or not. Which means you need to think through your toolkit carefully.</p>\n<p class=\"\">My first instinct, shared by many, is to load the robot up with <em class=\"\">as many tools as possible</em>. You can stay up late configuring your API keys and imagining the possibilities. I went through this with Obsidian Plugins. But over time, I came to realize the extra plugins didn’t help as much as I thought. Worse, they slowed down every interaction (particularly on mobile.) I anticipate a similar arc with MCP servers.</p>\n<p class=\"\">Given a completely novel territory I did what any hacker-come-cartographer might do, I tried to make a map of it, aided at every step by the robot of course. (This is <a href=\"/blog/robots/quantified-self-as-archaeology\" class=\"internal-link text-blue-600 dark:text-blue-400\">archaeology, not optimization</a> - exploring data to reveal patterns, not to find the \"best\" MCP.)</p>\n<p class=\"\">The first step was to take the MCP names and descriptions and turn them into embeddings; getting their location in hyper-dimensional space that we can use to arrange, cluster, and categorize them roughly by what they do (if we configure our parameters correctly)</p>\n<p class=\"\"><img src=\"https://res.cloudinary.com/ejf/video/upload/c_scale,f_auto,q_auto:good,w_1280/v1742924387/Screen_Recording_2025-03-25_at_1.38.45_PM.gif\" alt=\"\" loading=\"lazy\" decoding=\"async\" srcset=\"https://res.cloudinary.com/ejf/video/upload/c_scale,f_auto,q_auto:good,w_640/v1742924387/Screen_Recording_2025-03-25_at_1.38.45_PM.gif 640w, https://res.cloudinary.com/ejf/video/upload/c_scale,f_auto,q_auto:good,w_960/v1742924387/Screen_Recording_2025-03-25_at_1.38.45_PM.gif 960w, https://res.cloudinary.com/ejf/video/upload/c_scale,f_auto,q_auto:good,w_1280/v1742924387/Screen_Recording_2025-03-25_at_1.38.45_PM.gif 1280w, https://res.cloudinary.com/ejf/video/upload/c_scale,f_auto,q_auto:good,w_1920/v1742924387/Screen_Recording_2025-03-25_at_1.38.45_PM.gif 1920w\" sizes=\"(max-width: 430px) 92vw, (max-width: 768px) 85vw, 900px\" style=\"--splay-rot:-2.5deg;\" class=\"img-full my-8 rounded-sm img-splay w-full mx-auto py-4\" crossorigin=\"anonymous\"></p>\n<p class=\"\">Now that we have a file full of the titles, descriptions, and embeddings we can apply “dimension reduction” to take the point from 4096TK dimensions, which I struggle to imagine, to 2 dimensions, which I can imagine quite easily.</p>\n<p class=\"\">A ton of points with X and Y positions? That’s data begging to be a scatterplot if I ever saw it. We can run our dimension reduction algorithms with all sorts of different parameters and see what the resulting piles look like. Some seem to have more prominent groupings, some look like true jumbles.</p>\n<p class=\"\">We are naively, intuitively “tuning” our parameters across hyper-dimensional space, like tuning your radio and looking for strong signals that might turn from noise into Fresh Air or the local Classic Rock station.</p>\n<p class=\"\"><img src=\"https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_1280/v1742920334/parameter_grid_ekueka.png\" alt=\"https://res.cloudinary.com/ejf/image/upload/v1742920334/parameter_grid_ekueka.png\" loading=\"lazy\" decoding=\"async\" srcset=\"https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_640/v1742920334/parameter_grid_ekueka.png 640w, https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_960/v1742920334/parameter_grid_ekueka.png 960w, https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_1280/v1742920334/parameter_grid_ekueka.png 1280w, https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_1920/v1742920334/parameter_grid_ekueka.png 1920w\" sizes=\"(max-width: 430px) 92vw, (max-width: 768px) 85vw, 900px\" width=\"1800\" height=\"1800\" style=\"--splay-rot:-0.87deg;\" data-dimensions=\"1800×1800\" class=\"img-full my-8 rounded-sm img-splay aspect-square w-full mx-auto py-4\" crossorigin=\"anonymous\"></p>\n<p class=\"\">Once we have arranged our points, whose positions contain some meaning (one that is impossible for us to label simply on X and Y axes, at this point) that we need to discover.</p>\n<p class=\"\"><img src=\"https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_1280/v1742920403/umap_grid_16x16_silhouette_fpmntg.png\" alt=\"https://res.cloudinary.com/ejf/image/upload/v1742920403/umap_grid_16x16_silhouette_fpmntg.png\" loading=\"lazy\" decoding=\"async\" srcset=\"https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_640/v1742920403/umap_grid_16x16_silhouette_fpmntg.png 640w, https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_960/v1742920403/umap_grid_16x16_silhouette_fpmntg.png 960w, https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_1280/v1742920403/umap_grid_16x16_silhouette_fpmntg.png 1280w, https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_1920/v1742920403/umap_grid_16x16_silhouette_fpmntg.png 1920w\" sizes=\"(max-width: 430px) 92vw, (max-width: 768px) 85vw, 900px\" width=\"2868\" height=\"2889\" style=\"--splay-rot:1.3deg;\" data-dimensions=\"2868×2889\" class=\"img-full my-8 rounded-sm img-splay aspect-square w-full mx-auto py-4\" crossorigin=\"anonymous\"></p>\n<p class=\"\">From here we can run a number of clustering algorithms, created by people much smarter than ourselves, each with their own arcane parameters to be tuned and explored. We can do the same exercise, running lots of different clusters and comparing them as small multiples, and finding the shapes that we are drawn to.</p>\n<p class=\"\"><img src=\"https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_1280/v1742920502/kmeans_small_multiples_okqtkw.png\" alt=\"https://res.cloudinary.com/ejf/image/upload/v1742920502/kmeans_small_multiples_okqtkw.png\" loading=\"lazy\" decoding=\"async\" srcset=\"https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_640/v1742920502/kmeans_small_multiples_okqtkw.png 640w, https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_960/v1742920502/kmeans_small_multiples_okqtkw.png 960w, https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_1280/v1742920502/kmeans_small_multiples_okqtkw.png 1280w, https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_1920/v1742920502/kmeans_small_multiples_okqtkw.png 1920w\" sizes=\"(max-width: 430px) 92vw, (max-width: 768px) 85vw, 900px\" width=\"4500\" height=\"4500\" style=\"--splay-rot:0.84deg;\" data-dimensions=\"4500×4500\" class=\"img-full my-8 rounded-sm img-splay aspect-square w-full mx-auto py-4\" crossorigin=\"anonymous\"></p>\n<p class=\"\">When I used to shoot film photos I had my own darkroom, and one of the crucial steps in printing a roll of film is first printing a contact sheet, little thumbnails of the entire roll. In many ways we are recreating this process but with a machine, a camera that humanity has yet to perfect or even understand. Thats what makes it fun.</p>\n<figure role=\"figure\" aria-label=\"Three contact sheets of black and white film negatives showing various scenes from what appears to be a documentary or artistic photo project.\" class=\"\">\n<img src=\"https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_1280/v1742920150/IMG_3168.jpg\" alt=\"Three contact sheets of black and white film negatives showing various scenes from what appears to be a documentary or artistic photo project.\" loading=\"lazy\" decoding=\"async\" srcset=\"https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_640/v1742920150/IMG_3168.jpg 640w, https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_960/v1742920150/IMG_3168.jpg 960w, https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_1280/v1742920150/IMG_3168.jpg 1280w, https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_1920/v1742920150/IMG_3168.jpg 1920w\" sizes=\"(max-width: 430px) 92vw, (max-width: 768px) 85vw, 900px\" title=\"Three contact sheets of black and white film negatives showing various scenes from what appears to be a documentary or artistic photo project.\" width=\"3520\" height=\"1980\" style=\"--splay-rot:-0.6deg;\" data-dimensions=\"3520×1980\" class=\"img-full my-8 rounded-sm img-splay aspect-video w-full mx-auto py-4\" crossorigin=\"anonymous\">\n<figcaption class=\"\">Three contact sheets of black and white film negatives showing various scenes from what appears to be a documentary or artistic photo project.</figcaption>\n</figure>\n<figure role=\"figure\" aria-label=\"Clustering algorithm comparisons showing HDBSCAN with varying minimum cluster sizes and KMeans with different cluster counts applied to UMAP-reduced data.\" class=\"\">\n<img src=\"https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_1280/v1742920633/Screenshot_2025-03-25_at_12.37.00_PM.png\" alt=\"Clustering algorithm comparisons showing HDBSCAN with varying minimum cluster sizes and KMeans with different cluster counts applied to UMAP-reduced data.\" loading=\"lazy\" decoding=\"async\" srcset=\"https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_640/v1742920633/Screenshot_2025-03-25_at_12.37.00_PM.png 640w, https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_960/v1742920633/Screenshot_2025-03-25_at_12.37.00_PM.png 960w, https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_1280/v1742920633/Screenshot_2025-03-25_at_12.37.00_PM.png 1280w, https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_1920/v1742920633/Screenshot_2025-03-25_at_12.37.00_PM.png 1920w\" sizes=\"(max-width: 430px) 92vw, (max-width: 768px) 85vw, 900px\" title=\"Clustering algorithm comparisons showing HDBSCAN with varying minimum cluster sizes and KMeans with different cluster counts applied to UMAP-reduced data.\" width=\"1650\" height=\"1620\" style=\"--splay-rot:-2.06deg;\" data-dimensions=\"1650×1620\" class=\"img-full my-8 rounded-sm img-splay aspect-square w-full mx-auto py-4\" crossorigin=\"anonymous\">\n<figcaption class=\"\">Clustering algorithm comparisons showing HDBSCAN with varying minimum cluster sizes and KMeans with different cluster counts applied to UMAP-reduced data.</figcaption>\n</figure>\n<p class=\"\">Once we have picked groupings, we can begin to make some shape of them. We don’t even necessarily need the robot for this part, although doing it by hand is a chore. You can click around the points in a cluster, and as a human, after 4 or 5 you can kinda get a sense what “category” we might be in.</p>\n<p class=\"\"><img src=\"https://res.cloudinary.com/ejf/video/upload/c_scale,f_auto,q_auto:good,w_1280/v1742920786/Screen_Recording_2025-03-25_at_12.38.58_PM.gif\" alt=\"\" loading=\"lazy\" decoding=\"async\" srcset=\"https://res.cloudinary.com/ejf/video/upload/c_scale,f_auto,q_auto:good,w_640/v1742920786/Screen_Recording_2025-03-25_at_12.38.58_PM.gif 640w, https://res.cloudinary.com/ejf/video/upload/c_scale,f_auto,q_auto:good,w_960/v1742920786/Screen_Recording_2025-03-25_at_12.38.58_PM.gif 960w, https://res.cloudinary.com/ejf/video/upload/c_scale,f_auto,q_auto:good,w_1280/v1742920786/Screen_Recording_2025-03-25_at_12.38.58_PM.gif 1280w, https://res.cloudinary.com/ejf/video/upload/c_scale,f_auto,q_auto:good,w_1920/v1742920786/Screen_Recording_2025-03-25_at_12.38.58_PM.gif 1920w\" sizes=\"(max-width: 430px) 92vw, (max-width: 768px) 85vw, 900px\" style=\"--splay-rot:-0.86deg;\" class=\"img-full my-8 rounded-sm img-splay w-full mx-auto py-4\" crossorigin=\"anonymous\"></p>\n<p class=\"\">Some traditional categories emerge; both from our manual spot-checking as well as our automated labeling techniques. We are beginning to find the true names of this unknown territory. The fog of war begins to lift, and we start to see not only the peaks but also the valleys and the space between concepts. These might be places for people who want to make <em class=\"\">new things</em> to concentrate their energies.</p>\n<figure role=\"figure\" aria-label=\"UMAP dimensionality reduction plot showing seven clusters of gene expression or cellular data with distinct spatial separation by cell type or condition.\" class=\"\">\n<img src=\"https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_1280/v1742920843/Screenshot_2025-03-25_at_12.40.31_PM.png\" alt=\"UMAP dimensionality reduction plot showing seven clusters of gene expression or cellular data with distinct spatial separation by cell type or condition.\" loading=\"lazy\" decoding=\"async\" srcset=\"https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_640/v1742920843/Screenshot_2025-03-25_at_12.40.31_PM.png 640w, https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_960/v1742920843/Screenshot_2025-03-25_at_12.40.31_PM.png 960w, https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_1280/v1742920843/Screenshot_2025-03-25_at_12.40.31_PM.png 1280w, https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_1920/v1742920843/Screenshot_2025-03-25_at_12.40.31_PM.png 1920w\" sizes=\"(max-width: 430px) 92vw, (max-width: 768px) 85vw, 900px\" title=\"UMAP dimensionality reduction plot showing seven clusters of gene expression or cellular data with distinct spatial separation by cell type or condition.\" width=\"1648\" height=\"1310\" style=\"--splay-rot:-1.16deg;\" data-dimensions=\"1648×1310\" class=\"img-full my-8 rounded-sm img-splay w-full mx-auto py-4\" crossorigin=\"anonymous\">\n<figcaption class=\"\">UMAP dimensionality reduction plot showing seven clusters of gene expression or cellular data with distinct spatial separation by cell type or condition.</figcaption>\n</figure>\n<p class=\"\">Creativity and innovation can often come from the simple interpolation of discrete ideas or technologies. Maps like these can help us perform these exercises. I am a visual thinker, so for me, it is interesting to draw lines between clusters and think what it might look like to combine them in new ways or find gaps in coverage. This is strategy, not tactics.</p>\n<p class=\"\">Embeddings are just one particular method of exploring this dataset. We could probably ask the robot to apply some tags based on the data and use that to create groupings and taxonomies. But what list of tags to give it to choose from? Its a bit of a chicken and egg problem.</p>","title":"Mapping Novel Territories: Untangling MCP Servers","metadata":{"dek":"In which we the author gets his bearings by doing one of the things he knows best; making a map","inprogress":true,"tags":["embeddings","cartography","dataviz"],"date":"2025-03-25T04:12:41.000Z","modified":"2025-03-27T20:12:50.000Z","words":825,"images":8,"imageDetails":{"total":8,"cloudinary":8,"withDimensions":0},"links":8,"codeBlocks":0,"headers":{"h2":1},"toc":[{"text":"Mapping Novel Territories: Untangling MCP Servers","slug":"mapping-novel-territories-untangling-mcp-servers","level":"h2","children":[]}],"type":"post"}},"_links":{"self":"https://ejfox.com/blog/2025/mcp-meta-mapping.json","html":"https://ejfox.com/blog/2025/mcp-meta-mapping","index":"/blog.json"}}