{"id":4795,"date":"2025-08-21T21:35:06","date_gmt":"2025-08-21T19:35:06","guid":{"rendered":"https:\/\/gokhan-gokalp.com\/?p=4795"},"modified":"2025-08-22T10:44:48","modified_gmt":"2025-08-22T08:44:48","slug":"devex-series-02-from-catalog-to-copilots-boosting-backstage-with-mcp-server","status":"publish","type":"post","link":"https:\/\/gokhan-gokalp.com\/tr\/devex-series-02-from-catalog-to-copilots-boosting-backstage-with-mcp-server\/","title":{"rendered":"DevEx Series 02: From Catalog to Copilots. Boosting Backstage with MCP Server"},"content":{"rendered":"<p data-pm-slice=\"0 0 []\">In the first part of this <em>DevEx<\/em> series, I tried to explain <em>Platform Engineering<\/em> and <em>DevEx<\/em> and showed how <em>Backstage<\/em> can help make an organization\u2019s assets discoverable while creating golden paths that enable developer self-service without chaos. The goal is to increase developer productivity. In this second part, I will dive deeper into <em>Backstage\u2019s<\/em> catalog capabilities and then take it a step further by integrating an <strong><em>AI-powered MCP<\/em> server <\/strong>which allows <strong>copilots <\/strong>to transform the catalog into a more <strong>conversational<\/strong> developer experience.<\/p>\n<p>Imagine a developer simply asking \u201c<em>Do we have a microservice template in C#?<\/em>\u201d and getting an instant, accurate answer or better spinning it up immediately. It\u2019s still <em>Backstage<\/em>, but with an extra layer of intelligence on top.<\/p>\n<p>If you haven&#8217;t read the first part of this article series, I highly recommend checking it out first <em><a href=\"https:\/\/gokhan-gokalp.com\/devex-series-01-creating-golden-paths-with-backstage-developer-self-service-without-losing-control\/\" target=\"_blank\" rel=\"noopener\">here<\/a><\/em>. If you would like to skip the catalog capabilities and jump straight to the <em>MCP<\/em> server section, go here: <em><a href=\"#accelerating-devex-with-mcp\">Accelerating DevEx With Mcp<\/a><\/em><\/p>\n<h1>Why the Catalog Matters<\/h1>\n<p>In the first part of this series, we touched on <em>Backstage\u2019s<\/em> <em>Software Catalog<\/em> as the heart of the platform. It is the place where <em>services<\/em>, <em>websites<\/em>, <em>APIs<\/em>, <em>libraries<\/em>\u00a0and more come together under <strong>one unified view<\/strong>.<\/p>\n<p>We looked at how each component is defined with a simple &#8220;<em>catalog-info.yaml<\/em>&#8220;, how <strong>ownership<\/strong> and <strong>metadata<\/strong> make them easier to manage. We only looked at the surface. The catalog is not just a feature. It is the <strong>backbone<\/strong> of platform discoverability and governance.<\/p>\n<p>It gives your organization a shared language for all its software assets. When used well, it transforms from a static list of entries into a clear map of your platform. This is where concepts like a <strong>clear taxonomy<\/strong>, <strong>up-to-date ownership <\/strong>and well curated <strong>metadata<\/strong> become essential. Without these, the catalog can quickly decay into a messy directory that nobody trusts.<\/p>\n<h3>Best Practices for a Living Catalog<\/h3>\n<p>I would say a healthy catalog starts with a clear taxonomy. <em>Backstage\u2019s<\/em> entity kinds give us the foundation, but it\u2019s up to the organization to define and enforce how they are used. <em>Backstage<\/em> supports different entity kinds like <em>Components<\/em>, <em>APIs<\/em>, <em>Systems<\/em>, <em>Domains<\/em>, <em>Resources<\/em>\u00a0and <em>Templates<\/em>.<\/p>\n<figure id=\"attachment_4798\" aria-describedby=\"caption-attachment-4798\" style=\"width: 802px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/software-model-entities.svg\"><img decoding=\"async\" class=\"wp-image-4798 size-full lazyload\" data-src=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/software-model-entities.svg\" alt=\"\" width=\"802\" height=\"854\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 802px; --smush-placeholder-aspect-ratio: 802\/854;\" \/><\/a><figcaption id=\"caption-attachment-4798\" class=\"wp-caption-text\">Ref: https:\/\/backstage.io\/docs\/features\/software-catalog\/system-model\/<\/figcaption><\/figure>\n<p>Each has a specific role and acts as the building block for your taxonomy:<\/p>\n<ul>\n<li data-start=\"432\" data-end=\"561\"><strong data-start=\"432\" data-end=\"445\">Component<\/strong>: The core building block in <em>Backstage<\/em>. In practice, a component could be your user microservice, a shared authentication library or even an infrastructure-as-code. The key point is that a component represents something that can be owned, versioned and reused. Once it is in the catalog, anyone can discover it, see its documentation and understand who owns it, what it depends on and how other teams can use it. Common subtypes of components include <em>service<\/em>, <em>website<\/em>, <em>library<\/em>, <em>IaC module<\/em>, <em>data pipeline<\/em>\u00a0and more.<\/li>\n<li data-start=\"432\" data-end=\"561\"><strong data-start=\"564\" data-end=\"571\">API<\/strong>: In <em>Backstage,<\/em> an <em>API<\/em> entity is more like a catalog entry it points to the spec (<em>OpenAPI<\/em>, <em>GraphQL<\/em> schema or <em>gPRC<\/em> proto). You can think of an <em>API<\/em> entity in <em>Backstage<\/em> as being similar to <em>SwaggerHub<\/em> in the sense that it makes <em>APIs<\/em> discoverable and documented. But unlike <em>SwaggerHub<\/em>, it is integrated into broader developer portal, showing which services provide or depend on the <em>API<\/em>.<\/li>\n<li data-start=\"432\" data-end=\"561\"><strong data-start=\"657\" data-end=\"667\">System<\/strong>: A grouping of related components that together deliver a capability. For example, an <em>Order Management System<\/em> could include a web frontend, a set of backend microservices an <em>API <\/em>for third party integrations and a reporting dashboard. In <em>Backstage<\/em>, grouping them under a system gives you one place to see the full picture of how they fit together.<\/li>\n<li data-start=\"432\" data-end=\"561\"><strong data-start=\"742\" data-end=\"752\">Domain<\/strong>: A higher level grouping that usually aligns with business functions. Think of a <em>Payments Domain<\/em> that contains multiple systems like billing and fraud detection. Or a <em>DevEx<\/em> domain that owns the <em>IDP<\/em>, <em>CI\/CD<\/em> pipelines and template library. Domains help people navigate the catalog when they do not know the exact service name but understand the business area they are looking for.<\/li>\n<li data-start=\"432\" data-end=\"561\"><strong data-start=\"862\" data-end=\"874\">Resource<\/strong>: Resources in <em>Backstage<\/em> represent the infrastructure and services that your software components rely on. Unlike <em>APIs<\/em> or templates (which are about scaffolding) resources act as the inventory of building blocks for your systems. Databases, message queues, storage accounts or <em>kubernetes<\/em> clusters.<\/li>\n<li data-start=\"432\" data-end=\"561\"><strong data-start=\"954\" data-end=\"966\">Template<\/strong>: Templates in <em>Backstage<\/em> are reusable blueprints for creating new software components. Instead of developers starting from scratch, they can pick a template that includes best practices, security requirements and organizational standards. If you have read my first article series on <em>Golden Paths<\/em>, this is exactly where they come to life. Backstage templates are the engine behind <em>Golden Paths.<\/em><\/li>\n<\/ul>\n<p>Once the taxonomy is in place, the real work is keeping it alive and trusted. That\u2019s where best practices come in:<\/p>\n<ul>\n<li><strong>Keep ownership metadata updated<\/strong>:\u00a0even make some fields mandatory, so every component has someone accountable for its accuracy.<\/li>\n<li><strong data-start=\"557\" data-end=\"605\">Define systems, domains and teams carefully<\/strong> so the catalog reflects the real organizational map.<\/li>\n<li><strong>Model relationships clearly<\/strong> for example a service belongs to a system, a team owns a service, an <em>API<\/em> is provided by a service.<\/li>\n<li><strong>Making sure documentation isn\u2019t stale<\/strong>.<\/li>\n<li><strong>Enforce new software through golden templates <\/strong>to ensure consistent quality, governance and metadata coverage.<\/li>\n<li><strong>Use tags and lifecycle states<\/strong> for better discoverability and maintenance.<\/li>\n<li><strong>Integrate automated checks<\/strong> so drift and missing metadata are caught early.<\/li>\n<li><strong>Reviewing and cleaning up deprecated entities<\/strong>.<\/li>\n<\/ul>\n<h3>Let&#8217;s Perform a Quick Example<\/h3>\n<p data-start=\"259\" data-end=\"701\">In the first article of this series, we built a<em> <strong data-start=\"307\" data-end=\"330\">.NET 9 API template<\/strong><\/em> as a golden path for new microservices. Using that template, we scaffolded a simple <em><strong data-start=\"415\" data-end=\"429\">Search API<\/strong><\/em>, where we set the &#8220;<em>Team Name<\/em>&#8221; to &#8220;<em data-start=\"461\" data-end=\"469\">guests&#8221;<\/em>\u00a0without actually creating any team or user in <em>Backstage<\/em>. This time we will take things a step further and show how the service fits into the bigger picture by defining its <strong data-start=\"647\" data-end=\"657\">system<\/strong>, <strong data-start=\"659\" data-end=\"669\">domain <\/strong>and <strong data-start=\"675\" data-end=\"683\">team<\/strong> in the catalog.<\/p>\n<p data-pm-slice=\"0 0 []\">Let\u2019s take a simple example from an e-commerce domain. Imagine we are building an <em>Order Management System<\/em>. This system could include a web frontend, a set of backend microservices and so on. In <em>Backstage<\/em>, we can model all of these related components as part of a single system. Before we scaffold a new <em>Search API<\/em>, this time we will define the bigger picture. The domain it belongs to, the system it supports and the team responsible for it. Once these are in place, any new service we scaffold will have the right context in the catalog. That way, when a developer looks up a service like the <em>Search API<\/em>, they immediately see how it fits into the broader ecosystem and who is accountable for it.<\/p>\n<p data-pm-slice=\"0 0 []\">Backstage also uses <em>YAML<\/em> entity definitions to represent domains, systems, teams and users just like we did with &#8220;<em>catalog-info.yaml<\/em>&#8221; and <em>template<\/em> manifests. We will start defining them from the top (domain) and then move down to systems, teams and users.<\/p>\n<p data-pm-slice=\"0 0 []\">To keep everything organized, we will follow a folder structure that allows us to manage catalog entities in a centralized and structured way.<\/p>\n<pre data-pm-slice=\"0 0 []\">backstage-catalog\/\r\n\u2514\u2500\u2500 domains\/\r\n    \u251c\u2500\u2500 ecommerce-domain.yaml\r\n\u2514\u2500\u2500 systems\/\r\n    \u251c\u2500\u2500 <em>order-management-system.yaml\r\n\u2514\u2500\u2500 teams\/\r\n<\/em><em>   \u00a0\u251c\u2500\u2500 <\/em>ecommerce-domain-team.yaml<em>\r\n   \u00a0\u251c\u2500\u2500 <\/em>oms-team.yaml\r\n<em>\u2514\u2500\u2500 users\/\r\n<\/em><em>   \u00a0\u251c\u2500\u2500 <\/em>gokhan-gokalp-user.yaml<\/pre>\n<p data-pm-slice=\"0 0 []\"><em>ecommerce-domain.yaml<\/em><\/p>\n<pre data-pm-slice=\"0 0 []\">apiVersion: backstage.io\/v1alpha1\r\nkind: Domain\r\nmetadata:\r\n  name: ecommerce\r\n  title: ECommerce\r\n  description: Domain that covers everything related to the ecommerce ecosystem.\r\nspec:\r\n  owner: ecommerce-domain-team\r\n<\/pre>\n<p><em>ecommerce-domain-team.yaml<\/em><\/p>\n<pre>apiVersion: backstage.io\/v1alpha1\r\nkind: Group\r\nmetadata:\r\n  name: ecommerce-domain-team\r\n  title: ECommerce Domain Team\r\n  description: Team responsible for the ECommerce domain.\r\nspec:\r\n  type: team\r\n  children: [oms-team]\r\n<\/pre>\n<p><em>order-management-system.yaml<\/em><\/p>\n<pre>apiVersion: backstage.io\/v1alpha1\r\nkind: System\r\nmetadata:\r\n  name: order-management\r\n  title: Order Management System\r\n  description: Handles orders from checkout to delivery.\r\nspec:\r\n  domain: ecommerce\r\n  owner: oms-team\r\n<\/pre>\n<p><em>oms-team.yaml<\/em><\/p>\n<pre>apiVersion: backstage.io\/v1alpha1\r\nkind: Group\r\nmetadata:\r\n  name: oms-team\r\n  title: OMS Team\r\n  description: Team responsible for the Order Management system within the ECommerce domain.\r\nspec:\r\n  type: team\r\n  children: []<\/pre>\n<p><em>gokhan-gokalp-user.yaml<\/em><\/p>\n<pre>apiVersion: backstage.io\/v1alpha1\r\nkind: User\r\nmetadata:\r\n  name: gokhangokalp\r\n  description: Gokhan Gokalp\r\nspec:\r\n  profile:\r\n    displayName: Gokhan Gokalp\r\n    email: info@gokhan-gokalp.com\r\n  memberOf:\r\n    - oms-team<\/pre>\n<p>We have now defined our catalog entities step by step. Starting from the domain we added the system that belongs to it and then described the team and users responsible for that system. With these <em>YAML<\/em> definitions in place, our <em>Order Management System<\/em> is now represented in <em>Backstage<\/em>. This structure provides a solid foundation for <strong>discovery<\/strong> and <strong>ownership <\/strong>and we can easily extend it later by adding components, <em>APIs<\/em>\u00a0or resources as the system evolves.<\/p>\n<p>So, for higher level entities such as Domain, System, Group and User, we use a dedicated shared catalog repository. This approach ensures better governance, traceability and consistency across the organization. To avoid manually registering each file, we can enable <em>Backstage\u2019s<\/em> <strong>auto discovery<\/strong> capability to watch that repository folder and automatically ingest these entities into the catalog.<\/p>\n<p>Let&#8217;s do the following in the &#8220;<em>app-config.yml<\/em>&#8221; file to enable auto discovery for our local environment. You can also point it to a <em>Git<\/em> repository if you prefer by setting the &#8220;<em>type<\/em>&#8221; to &#8220;<em>url<\/em>&#8220;.<\/p>\n<pre>catalog:\r\n  import:\r\n    entityFilename: catalog-info.yaml\r\n    pullRequestBranchName: backstage-integration\r\n  rules:\r\n    - allow: [Domain, Component, System, API, Resource, Location, Template, User, Group]\r\n  locations:\r\n    - type: url\r\n      target: https:\/\/YOUR_TEMPLATE_REPOSITORY_URL_FROM_FIRST_ARTICLE\/template.yaml\r\n    - type: file\r\n      target: ..\/..\/backstage-catalog\/domains\/**\/*.yaml\r\n    - type: file\r\n      target: ..\/..\/backstage-catalog\/systems\/**\/*.yaml\r\n    - type: file\r\n      target: ..\/..\/backstage-catalog\/teams\/**\/*.yaml\r\n    - type: file\r\n      target: ..\/..\/backstage-catalog\/users\/**\/*.yaml\r\n<\/pre>\n<blockquote><p><em><strong>NOTE<\/strong><\/em>: Make sure to update the path to match where you created the &#8220;<em>backstage-catalog<\/em>&#8221; folder.<\/p><\/blockquote>\n<p>Now we are ready to see <em>Backstage<\/em> in action. Let\u2019s start the app and let it do the magic:<\/p>\n<pre>cd my-backstage-app # your app name\r\nyarn start<\/pre>\n<p>Once the app is running, <em>Backstage <\/em>will automatically pick up the catalog entities from our local &#8220;<em>backstage-catalog<\/em>&#8221; folder.<\/p>\n<p>Now that all our entities have to be ingested, let\u2019s explore them in the catalog. In the &#8220;<em>Catalog<\/em>&#8221;\u00a0page, filter by kind &#8220;<em>Domain<\/em>&#8220;. Click on &#8220;<em>ECommerce<\/em>&#8221; to see the full map of our domain.<\/p>\n<p><a href=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/e-commerce-domain-backstage.jpg\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-4808 lazyload\" data-src=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/e-commerce-domain-backstage.jpg\" alt=\"\" width=\"1902\" height=\"1225\" data-srcset=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/e-commerce-domain-backstage.jpg 1902w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/e-commerce-domain-backstage-300x193.jpg 300w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/e-commerce-domain-backstage-1024x660.jpg 1024w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/e-commerce-domain-backstage-768x495.jpg 768w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/e-commerce-domain-backstage-1536x989.jpg 1536w\" data-sizes=\"(max-width: 1902px) 100vw, 1902px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 1902px; --smush-placeholder-aspect-ratio: 1902\/1225;\" \/><\/a><\/p>\n<p>Here we can see the description and owner of the domain. On the right, the &#8220;<em>Relations<\/em>&#8221; panel visualizes how the domain is connected to systems and teams. At the bottom, the &#8220;<em>Has systems<\/em>&#8221; section lists the systems under this domain along with their owners and descriptions. This view helps us quickly understand the structure of the domain and who is responsible for each part.<\/p>\n<p>Now let&#8217;s use the <em><a href=\"https:\/\/gokhan-gokalp.com\/devex-series-01-creating-golden-paths-with-backstage-developer-self-service-without-losing-control\/\" target=\"_blank\" rel=\"noopener\">golden path template<\/a><\/em> we developed in the first part of this series to scaffold a new microservice, this time tying it to the &#8220;<em>OMS Team<\/em>&#8221; to make ownership clearly visible within the portal. I will be using the following values during scaffolding:<\/p>\n<ul>\n<li><strong>Project Name<\/strong>: Inventory.API<\/li>\n<li><strong>Port<\/strong>: 5000<\/li>\n<li><strong>Team Name<\/strong>: oms-team<\/li>\n<\/ul>\n<p>Once the service is scaffolded, let\u2019s enrich its catalog definition so that it fits into our larger architecture and also shows its runtime footprint. Open the &#8220;<em>catalog-info.yaml<\/em>&#8221; file in the root of the &#8220;<em>MyOrg.Inventory.API<\/em>&#8221; repository and update it as follows.<\/p>\n<pre>apiVersion: backstage.io\/v1alpha1\r\nkind: Component\r\nmetadata:\r\n  name: MyOrg.Inventory.API\r\n  description: MyOrg.Inventory.API project.\r\n  tags:\r\n    - dotnet\r\n    - api\r\n    - microservice\r\n    - oms-team\r\n  annotations:\r\n    backstage.io\/techdocs-ref: dir:.\r\nspec:\r\n  type: service\r\n  lifecycle: experimental\r\n  owner: oms-team\r\n  <strong>system: order-management<\/strong>\r\n<strong>  dependsOn:\r\n    - resource:MyOrg.Inventory.API.Database<\/strong>\r\n---\r\n<strong>apiVersion: backstage.io\/v1alpha1\r\nkind: Resource\r\nmetadata:\r\n  name: MyOrg.Inventory.API.Database\r\n  description: Azure SQL Database for Inventory.API\r\nspec:\r\n  type: database\r\n  owner: oms-team\r\n  system: order-management<\/strong><\/pre>\n<p>Here, we have associate the service with a system. So it becomes part of the &#8220;<em>order-management<\/em>&#8221; system. We have also defined a database resource entity so developers can clearly see that this service depends on an <em>Azure SQL Database<\/em>\u00a0instead of having to guess where the data lives.<\/p>\n<blockquote><p><em><strong>NOTE<\/strong><\/em>: I recommend keeping the resource name aligned with your <em>IaC<\/em> naming conventions as this makes it easier to navigate and cross reference infrastructure resources.<\/p><\/blockquote>\n<p>Once you commit and push the updated file, go to <em>Backstage<\/em>, navigate to the &#8220;<em>MyOrg.Inventory.API<\/em>&#8221; component and on the &#8220;<em>About<\/em>&#8221; card, click on the &#8220;<em>Schedule entity refresh<\/em>&#8220;. <em>Backstage<\/em> will then re-ingest the definition and we will see the system and the resource we defined linked to the service.<\/p>\n<p>After a few seconds or minutes, let\u2019s refresh the component detail page of &#8220;<em>MyOrg.Inventory.API<\/em>&#8220;. If <em>Backstage<\/em> has successfully re-ingested the definition, this time we will see that:<\/p>\n<ul>\n<li data-start=\"336\" data-end=\"393\">The component is linked to &#8220;<em>OMS Team<\/em>&#8221; as its owner.<\/li>\n<li data-start=\"336\" data-end=\"393\">It belongs to the &#8220;<em>Order Management System<\/em>&#8220;.<\/li>\n<\/ul>\n<p><a href=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/new-component-detail.jpg\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-4812 lazyload\" data-src=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/new-component-detail.jpg\" alt=\"\" width=\"1898\" height=\"1007\" data-srcset=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/new-component-detail.jpg 1898w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/new-component-detail-300x159.jpg 300w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/new-component-detail-1024x543.jpg 1024w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/new-component-detail-768x407.jpg 768w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/new-component-detail-1536x815.jpg 1536w\" data-sizes=\"(max-width: 1898px) 100vw, 1898px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 1898px; --smush-placeholder-aspect-ratio: 1898\/1007;\" \/><\/a><\/p>\n<p>If we also look at the &#8220;<em>Relations<\/em>&#8221; view, we can also see the resources this service depends on. From a developer\u2019s perspective, this is extremely valuable. I can understand what kind of service I\u2019m dealing with, what system it belongs to and what infrastructure resources it relies on.<\/p>\n<p>Now, If we click on the team name, <em>Backstage<\/em> takes us to the team details page.<\/p>\n<p><a href=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/team-view-gokhan-gokalp.jpg\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-4810 lazyload\" data-src=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/team-view-gokhan-gokalp.jpg\" alt=\"\" width=\"1896\" height=\"1301\" data-srcset=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/team-view-gokhan-gokalp.jpg 1896w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/team-view-gokhan-gokalp-300x206.jpg 300w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/team-view-gokhan-gokalp-1024x703.jpg 1024w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/team-view-gokhan-gokalp-768x527.jpg 768w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/team-view-gokhan-gokalp-1536x1054.jpg 1536w\" data-sizes=\"(max-width: 1896px) 100vw, 1896px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 1896px; --smush-placeholder-aspect-ratio: 1896\/1301;\" \/><\/a><\/p>\n<p>Here, we can see the members of this team, the services and systems they own. This creates a clear, traceable relationship between developers, teams and the software they are responsible for.<\/p>\n<p>Now that we have both components and resources connected in the catalog with a clear structure that everyone can more easily connect the dots across the broader landscape. To speak frankly, cataloging alone isn\u2019t enough anymore&#8230; What if we make this experience conversational for developers, reducing context switching as they increasingly rely on <strong>copilots<\/strong> in their daily work?<\/p>\n<h1 id=\"accelerating-devex-with-mcp\">Accelerating DevEx With MCP<\/h1>\n<p>From the beginning of this article, I mentioned that I would take this further by <strong data-start=\"647\" data-end=\"702\">empowering Backstage with an AI-powered MCP server<\/strong> that copilots can consume to reduce context-switching for developers. The goal is to make this experience conversational, meaning that instead of clicking around, we can simply ask <em data-start=\"820\" data-end=\"875\">\u201cDo we have a microservice template in C#?\u201d<\/em> or <em data-start=\"879\" data-end=\"916\">\u201cWho owns Order Management System?\u201d <\/em>and get instant answers powered by <em>Backstage\u2019s<\/em> catalog.<\/p>\n<p>I believe this is a major productivity boost. Speed is everything today. Time to market defines competitiveness and the ability to reduce friction in development makes a difference. When we enable copilots to access and share <em>Backstage\u2019s<\/em> internal knowledge, developers no longer waste time digging through documentation or pinging teammates. They get contextual answers in seconds directly in their <em>IDE<\/em> with the help of copilots.<\/p>\n<p>Copilots are becoming the new layer of productivity, almost like an extension of our way of thinking. When we connect them with our internals in this case with <em>DevEx<\/em>, they evolve from being just coding assistants into an organizational memory. This is where real acceleration happens.<\/p>\n<h3>Development of an MCP Server<\/h3>\n<p>You probably already know what <em>MCP<\/em> server is but to recall in short, an <em>MCP<\/em> (Model Context Protocol) server acts as a bridge between <em>LLM<\/em> applications and your organizational systems. It makes internal knowledge, assets and workflows available in a conversational way and it does so through a standardized protocol.<\/p>\n<p>A couple of months back, <strong><em>Microsoft<\/em> <\/strong>released an official <em>C# SDK<\/em> for <em>MCP <\/em>in collaboration with <em><strong>Anthropic <\/strong><\/em>which helps us to easily build both servers and clients. So we will be using this <em>SDK<\/em> to create a simple <em>MCP<\/em> server for <em>Backstage <\/em>and test it locally in <em>VS Code <\/em>using <em>GitHub Copilot&#8217;s<\/em>\u00a0agent mode.<\/p>\n<p>This minimal setup hopefully will show us how copilots can start to act as a developer&#8217;s gateway into the <em>Backstage<\/em> catalog to reduce friction and increase productivity.<\/p>\n<p>Let\u2019s start by creating a new console application and adding the required <em>NuGet<\/em> packages:<\/p>\n<pre>dotnet new console -n MyBackstage.MCP\r\ndotnet add package ModelContextProtocol --prerelease\r\ndotnet add package Microsoft.Extensions.Hosting<\/pre>\n<p>Then add a new folder to the project called &#8220;<em>Models<\/em>&#8221; and define the following records. These will represent the simple shape of <em>Backstage<\/em> catalog entities that we care about for now.<\/p>\n<p><em>Models\/BackstageMetadata.cs<\/em><\/p>\n<pre>public record BackstageMetadata\r\n{\r\n    public required string Name { get; set; }\r\n    public required string Title { get; set; }\r\n    public required string Description { get; set; }\r\n}<\/pre>\n<p><em>Models\/BackstageSystem.cs<\/em><\/p>\n<pre>public record BackstageSystem\r\n{\r\n    public required BackstageMetadata Metadata { get; set; }\r\n    public required BackstageSystemSpec Spec { get; set; }\r\n}\r\n\r\npublic record BackstageSystemSpec\r\n{\r\n    public required string Owner { get; set; }\r\n    public string? Domain { get; set; }\r\n}<\/pre>\n<p><em>Models\/BackstageTemplate.cs<\/em><\/p>\n<pre>public record BackstageTemplate\r\n{\r\n    public required BackstageMetadata Metadata { get; set; }\r\n    public required BackstageTemplateSpec Spec { get; set; }\r\n}\r\n\r\npublic record BackstageTemplateSpec\r\n{\r\n    public required string Owner { get; set; }\r\n    public string? Type { get; set; }\r\n    public string? Lifecycle { get; set; }\r\n    public List? Parameters { get; set; }\r\n}\r\n\r\npublic record BackstageTemplateParameter\r\n{\r\n    public string? Title { get; set; }\r\n    public List&lt;string&gt;? Required { get; set; }\r\n    public Dictionary&lt;string, BackstageTemplateProperty&gt;? Properties { get; set; }\r\n}\r\n\r\npublic record BackstageTemplateProperty\r\n{\r\n    public string? Title { get; set; }\r\n    public string? Type { get; set; }\r\n    public string? Description { get; set; }\r\n}<\/pre>\n<p>Here, basically we have defined a simple representation of <em>Backstage\u2019s<\/em> catalog entities such as metadata, systems and templates. This will make serialization\/deserialization from <em>Backstage\u2019s<\/em> backend <em>API<\/em> straightforward and we can expose through our <em>MCP<\/em> server, so copilots can query \u201c<em>what templates exist?<\/em>\u201d or \u201c<em>which systems are defined?<\/em>\u201d without us manually hardcoding anything.<\/p>\n<p>Now let&#8217;s create another folder called &#8220;<em>Services<\/em>&#8221; and start defining &#8220;<em>BackstageService.cs<\/em>&#8221; inside it. This is the place where we will connect these models to<em> Backstage&#8217;s API<\/em> so our <em>MCP<\/em> server can actually fetch live catalog data.<\/p>\n<div>\n<pre>using System.Net.Http.Json;\r\n\r\npublic interface IBackstageService\r\n{\r\n    Task ListTemplatesAsync();\r\n    Task ListSystemsAsync();\r\n}\r\n\r\npublic class BackstageService(IHttpClientFactory httpClientFactory) : IBackstageService\r\n{\r\n    public async Task ListTemplatesAsync()\r\n    {\r\n        try\r\n        {\r\n            var _httpClient = httpClientFactory.CreateClient(\"BackstageClient\");\r\n            var response = await _httpClient.GetAsync(\"\/api\/catalog\/entities?filter=kind=Template\");\r\n\r\n            response.EnsureSuccessStatusCode();\r\n\r\n            var templates = await response.Content.ReadFromJsonAsync&lt;List&lt;BackstageTemplate&gt;&gt;();\r\n\r\n            return templates ?? [];\r\n        }\r\n        catch\r\n        {\r\n            return [];\r\n        }\r\n    }\r\n\r\n    public async Task ListSystemsAsync()\r\n    {\r\n        try\r\n        {\r\n            var _httpClient = httpClientFactory.CreateClient(\"BackstageClient\");\r\n            var response = await _httpClient.GetAsync(\"\/api\/catalog\/entities?filter=kind=System\");\r\n\r\n            response.EnsureSuccessStatusCode();\r\n\r\n            var systems = await response.Content.ReadFromJsonAsync&lt;List&lt;BackstageSystem&gt;&gt;();\r\n\r\n            return systems ?? [];\r\n        }\r\n        catch\r\n        {\r\n            return [];\r\n        }\r\n    }\r\n}<\/pre>\n<p>Here we simply use <em>HttpClient<\/em> to call <em>Backstage\u2019s<\/em> backend <em>API<\/em> endpoints. This allows our <em>MCP<\/em> server to fetch templates and systems in real time. Depending on the needs of your organization, these capabilities can be extended further. For example to <strong>automatically scaffold new resources<\/strong> or integrate with additional internal services.<\/p>\n<p>Now that our service layer is in place, we can start defining our <em>MCP<\/em> tool, which is a semantic interface that acts as a bridge between <em>LLM<\/em> applications and our system&#8217;s actionable capabilities. In other words, this is where we expose <em>Backstage<\/em> operations (like listing templates and systems) in a way that an <em>LLM<\/em> can understand and invoke.<\/p>\n<p>Let&#8217;s create a new folder called &#8220;<em>McpTools<\/em>&#8221; and create &#8220;<em>BackstageTool.cs<\/em>&#8221; inside it.<\/p>\n<pre>using System.ComponentModel;\r\nusing ModelContextProtocol.Server;\r\n\r\n[McpServerToolType]\r\npublic class BackstageTool(IBackstageService backstageService)\r\n{\r\n    [McpServerTool, Description(\"Lists all available Backstage software templates with their metadata and spec such as title, description, owner, lifecycle of the template and all parameters that are required to run this template to scaffold a new component.\")]\r\n    public async Task&lt;List&lt;BackstageTemplate&gt;&gt; ListTemplatesAsync()\r\n    {\r\n        try\r\n        {\r\n            return await backstageService.ListTemplatesAsync();\r\n        }\r\n        catch\r\n        {\r\n            return [];\r\n        }\r\n    }\r\n\r\n    [McpServerTool, Description(\"Lists all available Backstage systems from the software catalog. Systems represent a collection of resources and components that work together to deliver business functionality with metadata such as name, title, description, owner and domain information.\")]\r\n    public async Task&lt;List&lt;BackstageSystem&gt;&gt; ListSystemsAsync()\r\n    {\r\n        try\r\n        {\r\n            return await backstageService.ListSystemsAsync();\r\n        }\r\n        catch\r\n        {\r\n            return [];\r\n        }\r\n    }\r\n}<\/pre>\n<p data-start=\"166\" data-end=\"397\">Here we have defined our <em>MCP<\/em> tool methods that delegate calls to the service layer. By doing this, we are allowing <em>LLMs<\/em> to directly invoke <em>Backstage\u2019s<\/em> backend <em>APIs<\/em> through the <em>MCP<\/em> protocol to list templates and systems on demand.<\/p>\n<p data-start=\"399\" data-end=\"631\">We have also marked the class with the &#8220;<em>[McpServerToolType]<\/em>&#8221; attribute so the <em>MCP<\/em> runtime can discover and register the tool methods. We have also added the &#8220;[<em>McpServerTool]<\/em>&#8221; attribute to each method we want to expose to the <em>LLMs<\/em>.<\/p>\n<p data-start=\"633\" data-end=\"900\">Additionally, we have added a &#8220;<em>Description<\/em>&#8221; attribute to each tool method. It serves as the semantic contract between your <em>MCP<\/em> server and the <em>LLM<\/em>. So, a well written description ensures that the <em>LLM<\/em> can understand the tool\u2019s purpose, parameters and expected responses.<\/p>\n<p data-start=\"633\" data-end=\"900\">We are almost done. Now let\u2019s have the &#8220;<em>Program.cs<\/em>&#8221; like below:<\/p>\n<pre data-start=\"633\" data-end=\"900\">using Microsoft.Extensions.DependencyInjection;\r\nusing Microsoft.Extensions.Hosting;\r\nusing Microsoft.Extensions.Logging;\r\n\r\nvar builder = Host.CreateApplicationBuilder(args);\r\nbuilder.Logging.AddConsole(consoleLogOptions =&gt;\r\n{\r\n    consoleLogOptions.LogToStandardErrorThreshold = LogLevel.Trace;\r\n});\r\n\r\nbuilder.Services\r\n    .AddMcpServer()\r\n    .WithStdioServerTransport()\r\n    .WithToolsFromAssembly();\r\n\r\nbuilder.Services.AddHttpClient(\"BackstageClient\", client =&gt;\r\n{\r\n    client.BaseAddress = new Uri(\"http:\/\/localhost:7007\");\r\n    client.DefaultRequestHeaders.Add(\"Authorization\", \"Bearer 2SNWBsDxv9KqB+YkQ3eUG6kiSCfr5yeG\");\r\n});\r\n\r\nbuilder.Services.AddSingleton&lt;IBackstageService, BackstageService&gt;();\r\n\r\nawait builder.Build().RunAsync();<\/pre>\n<p>Here we first configure the <em>MCP<\/em> server by calling &#8221;<em>.AddMcpServer()<\/em>&#8220;. This wires up the <em>MCP<\/em> server and automatically discovers our <em>MCP<\/em> tools from the current assembly.<\/p>\n<p>Then we register our &#8220;<em>IBackstageService<\/em>&#8221; and since this is a service to service communication, we keep it simple by using the static token approach as described in <em>Backstage&#8217;s <a class=\"decorated-link\" href=\"https:\/\/backstage.io\/docs\/auth\/service-to-service-auth\/#static-tokens\" target=\"_new\" rel=\"noopener\" data-start=\"1447\" data-end=\"1568\">docs<\/a><\/em>.<\/p>\n<p>In the &#8220;<em>app-config.yaml<\/em>&#8221; file of <em>Backstage<\/em>. we simply need to enable static token for external access.<\/p>\n<pre>backend:\r\n  auth:\r\n    externalAccess:\r\n      - type: static\r\n        options:\r\n          token: 2SNWBsDxv9KqB+YkQ3eUG6kiSCfr5yeG\r\n          subject: backstage-mcp<\/pre>\n<p>And that&#8217;s all.<\/p>\n<p>With this setup in place, we can now test our <em>MCP <\/em>server directly from <em>VS Code<\/em> using <em>GitHub Copilot\u2019s<\/em> agent mode.<\/p>\n<h3>Testing with VS Code using GitHub Copilot Agent Mode<\/h3>\n<p>Thanks to<em> VS Code\u2019s<\/em> built-in <em>MCP<\/em> support, we can interact with our <em>Backstage<\/em> <em>MCP<\/em> tools without additional setup. The only thing we need to do is create a &#8220;<em>mcp.json<\/em>&#8221; file inside the &#8220;<em>.vscode<\/em>&#8221; folder.<\/p>\n<pre>{\r\n    \"inputs\": [],\r\n    \"servers\": {\r\n        \"BackstageMCP\": {\r\n            \"type\": \"stdio\",\r\n            \"command\": \"dotnet\",\r\n            \"args\": [\r\n                \"run\",\r\n                \"--project\",\r\n                \"YOUR_PATH\\\\MyBackstage.MCP\\\\MyBackstage.MCP.csproj\"\r\n            ]\r\n        }\r\n    }\r\n}<\/pre>\n<p data-start=\"249\" data-end=\"384\">Once we define our &#8220;<em>BackstageMCP<\/em>&#8221; server, a start button will appear in <em>VS Code<\/em> where we can easily launch it. Let&#8217;s click on it! Also don\u2019t forget that your <em>Backstage<\/em> app must be up and running, otherwise the <em>MCP<\/em> server won\u2019t be able to communicate with it.<\/p>\n<p data-start=\"249\" data-end=\"384\">After starting, we should see logs in the <em>VS Code<\/em> output confirming that the <em>MCP<\/em> server is active and waiting for requests.<\/p>\n<p data-start=\"249\" data-end=\"384\"><a href=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/mcp-logs-gokhan-gokalp.jpg\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-4825 lazyload\" data-src=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/mcp-logs-gokhan-gokalp.jpg\" alt=\"\" width=\"1101\" height=\"855\" data-srcset=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/mcp-logs-gokhan-gokalp.jpg 1101w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/mcp-logs-gokhan-gokalp-300x233.jpg 300w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/mcp-logs-gokhan-gokalp-1024x795.jpg 1024w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/mcp-logs-gokhan-gokalp-768x596.jpg 768w\" data-sizes=\"(max-width: 1101px) 100vw, 1101px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 1101px; --smush-placeholder-aspect-ratio: 1101\/855;\" \/><\/a><\/p>\n<p data-start=\"249\" data-end=\"384\">Let\u2019s also make sure that our &#8220;<em>BackstageMCP<\/em>&#8221; server is available in the tools list. We can check this by clicking on the &#8220;<em>Configure<\/em> <em>tools<\/em>&#8221; icon in the copilot chat window. If everything is configured correctly, we should see \u201c<em>BackstageMCP<\/em>\u201d listed there.<\/p>\n<p data-start=\"249\" data-end=\"384\"><a href=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/backstage-mcp-gokhan-gokalp-tool-list.jpg\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-4826 lazyload\" data-src=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/backstage-mcp-gokhan-gokalp-tool-list.jpg\" alt=\"\" width=\"742\" height=\"417\" data-srcset=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/backstage-mcp-gokhan-gokalp-tool-list.jpg 742w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/backstage-mcp-gokhan-gokalp-tool-list-300x169.jpg 300w\" data-sizes=\"(max-width: 742px) 100vw, 742px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 742px; --smush-placeholder-aspect-ratio: 742\/417;\" \/><\/a><\/p>\n<p data-start=\"249\" data-end=\"384\">Now, we can start sending prompts to <em>GitHub Copilot<\/em> and see how it interacts with our <em>Backstage<\/em> instance through our <em>MCP<\/em>.<\/p>\n<p data-start=\"249\" data-end=\"384\">Let\u2019s start with a simple one: \u201c<em>Show me the available software templates in my Backstage instance?<\/em>\u201d<\/p>\n<p data-start=\"249\" data-end=\"384\"><a href=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/mcp-first-question.jpg\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-4827 lazyload\" data-src=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/mcp-first-question.jpg\" alt=\"\" width=\"631\" height=\"957\" data-srcset=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/mcp-first-question.jpg 631w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/mcp-first-question-198x300.jpg 198w\" data-sizes=\"(max-width: 631px) 100vw, 631px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 631px; --smush-placeholder-aspect-ratio: 631\/957;\" \/><\/a><\/p>\n<p data-start=\"249\" data-end=\"384\">As we can see, <em>GitHub Copilot<\/em> successfully communicated with our &#8220;<em>BackstageMCP<\/em>&#8221;\u00a0server and retrieved the list of available software templates. These are the same templates we previously registered in the <em>Backstage<\/em> software catalog.<\/p>\n<p data-start=\"249\" data-end=\"384\">Now, just imagine I\u2019m a developer who has newly joined the &#8220;<em>OMS Team<\/em>&#8221; and I\u2019m curious to know which systems we own. With copilot, I can simply ask: \u201c<em>What are the available systems owned by the OMS team in my Backstage instance?<\/em>\u201d<\/p>\n<p data-start=\"249\" data-end=\"384\"><a href=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/systems-backstage-mcp-gokhan-gokalp.jpg\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-4828 lazyload\" data-src=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/systems-backstage-mcp-gokhan-gokalp.jpg\" alt=\"\" width=\"633\" height=\"761\" data-srcset=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/systems-backstage-mcp-gokhan-gokalp.jpg 633w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/systems-backstage-mcp-gokhan-gokalp-250x300.jpg 250w\" data-sizes=\"(max-width: 633px) 100vw, 633px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 633px; --smush-placeholder-aspect-ratio: 633\/761;\" \/><\/a><\/p>\n<p data-start=\"249\" data-end=\"384\">We can see how seamlessly Copilot interacts with our &#8220;<em>BackstageMCP<\/em>&#8221; server to surface organizational knowledge. As a developer, I don\u2019t need to search through documentation, ping teammates or navigate multiple catalogs. Instead, I can simply ask a natural question and instantly get the list of systems our team owns.<\/p>\n<p data-start=\"249\" data-end=\"384\">This highlights the real power of <em>Backstage\u2019s<\/em> system modeling. Everything in our software ecosystem from domains and systems to teams, templates, and components is represented in a structured and connected way. When combined with copilot, this catalog becomes conversational and actionable. The result is improved developer productivity, faster onboarding for new team members and a smoother way for teams to operate in harmony with the broader engineering ecosystem.<\/p>\n<h1 data-start=\"249\" data-end=\"384\">Wrapping Up<\/h1>\n<p data-start=\"84\" data-end=\"389\">Backstage combined with copilot, turns system knowledge into something that is not only structured but also easy to explore and act on. By making our ecosystem both transparent and conversational, we help developers move faster, collaborate better and keep the entire engineering organization in sync.<\/p>\n<p data-start=\"84\" data-end=\"389\">I have tried to show how we can organize our catalog and how to create a simple <em>MCP<\/em> server with <em>C# SDK<\/em>. Hopefully, this gives some ideas on how you can bring similar improvements to your own setup.<\/p>\n<h2 data-start=\"84\" data-end=\"389\">References<\/h2>\n<blockquote>\n<p data-start=\"84\" data-end=\"389\"><em>https:\/\/devblogs.microsoft.com\/dotnet\/build-a-model-context-protocol-mcp-server-in-csharp\/<\/em><br \/>\n<em>https:\/\/backstage.io\/docs\/features\/software-catalog\/system-model\/<\/em><br \/>\n<em>https:\/\/code.visualstudio.com\/blogs\/2025\/05\/12\/agent-mode-meets-mcp<\/em><\/p>\n<\/blockquote>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>In the first part of this DevEx series, I tried to explain Platform Engineering and DevEx and showed how Backstage can help make an organization\u2019s assets discoverable while creating golden paths that enable developer self-service without chaos. The goal is to increase developer productivity. In&#8230;<\/p>\n<div class=\"more-link-wrapper\"><a class=\"more-link\" href=\"https:\/\/gokhan-gokalp.com\/tr\/devex-series-02-from-catalog-to-copilots-boosting-backstage-with-mcp-server\/\">Devam\u0131n\u0131 okuyun<span class=\"screen-reader-text\">DevEx Series 02: From Catalog to Copilots. Boosting Backstage with MCP Server<\/span><\/a><\/div>\n","protected":false},"author":1,"featured_media":4832,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,714],"tags":[715,666,717,716,659,726,723,725,724,718],"class_list":["post-4795","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-net","category-platform-engineering","tag-backstage","tag-c","tag-developer-experience","tag-devex","tag-dotnet","tag-llm","tag-mcp","tag-mcp-server","tag-model-context-protocol","tag-platform-engineering","entry"],"translation":{"provider":"WPGlobus","version":"3.0.2","language":"tr","enabled_languages":["en","tr"],"languages":{"en":{"title":true,"content":true,"excerpt":false},"tr":{"title":false,"content":false,"excerpt":false}}},"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>DevEx Series 02: From Catalog to Copilots. Boosting Backstage with MCP Server - G\u00f6khan G\u00f6kalp<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/gokhan-gokalp.com\/devex-series-02-from-catalog-to-copilots-boosting-backstage-with-mcp-server\/\" \/>\n<meta property=\"og:locale\" content=\"tr_TR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"DevEx Series 02: From Catalog to Copilots. Boosting Backstage with MCP Server - G\u00f6khan G\u00f6kalp\" \/>\n<meta property=\"og:url\" content=\"https:\/\/gokhan-gokalp.com\/devex-series-02-from-catalog-to-copilots-boosting-backstage-with-mcp-server\/\" \/>\n<meta property=\"og:site_name\" content=\"G\u00f6khan G\u00f6kalp\" \/>\n<meta property=\"article:published_time\" content=\"2025-08-21T19:35:06+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-08-22T08:44:48+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/gokhan-gokalp-mcp-server-backstage.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"675\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"G\u00f6khan G\u00f6kalp\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Yazan:\" \/>\n\t<meta name=\"twitter:data1\" content=\"G\u00f6khan G\u00f6kalp\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tahmini okuma s\u00fcresi\" \/>\n\t<meta name=\"twitter:data2\" content=\"20 dakika\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/devex-series-02-from-catalog-to-copilots-boosting-backstage-with-mcp-server\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/devex-series-02-from-catalog-to-copilots-boosting-backstage-with-mcp-server\\\/\"},\"author\":{\"name\":\"G\u00f6khan G\u00f6kalp\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#\\\/schema\\\/person\\\/7e2a7fa98babd22a5fdae563c4b8cdbe\"},\"headline\":\"DevEx Series 02: From Catalog to Copilots. Boosting Backstage with MCP Server\",\"datePublished\":\"2025-08-21T19:35:06+00:00\",\"dateModified\":\"2025-08-22T08:44:48+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/devex-series-02-from-catalog-to-copilots-boosting-backstage-with-mcp-server\\\/\"},\"wordCount\":3254,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#\\\/schema\\\/person\\\/7e2a7fa98babd22a5fdae563c4b8cdbe\"},\"image\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/devex-series-02-from-catalog-to-copilots-boosting-backstage-with-mcp-server\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/uploads\\\/2025\\\/08\\\/gokhan-gokalp-mcp-server-backstage.jpg\",\"keywords\":[\"backstage\",\"C#\",\"developer experience\",\"devex\",\"dotnet\",\"llm\",\"mcp\",\"mcp server\",\"model context protocol\",\"platform engineering\"],\"articleSection\":[\".NET\",\"Platform Engineering\"],\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/gokhan-gokalp.com\\\/devex-series-02-from-catalog-to-copilots-boosting-backstage-with-mcp-server\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/devex-series-02-from-catalog-to-copilots-boosting-backstage-with-mcp-server\\\/\",\"url\":\"https:\\\/\\\/gokhan-gokalp.com\\\/devex-series-02-from-catalog-to-copilots-boosting-backstage-with-mcp-server\\\/\",\"name\":\"DevEx Series 02: From Catalog to Copilots. Boosting Backstage with MCP Server - G\u00f6khan G\u00f6kalp\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/devex-series-02-from-catalog-to-copilots-boosting-backstage-with-mcp-server\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/devex-series-02-from-catalog-to-copilots-boosting-backstage-with-mcp-server\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/uploads\\\/2025\\\/08\\\/gokhan-gokalp-mcp-server-backstage.jpg\",\"datePublished\":\"2025-08-21T19:35:06+00:00\",\"dateModified\":\"2025-08-22T08:44:48+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/devex-series-02-from-catalog-to-copilots-boosting-backstage-with-mcp-server\\\/#breadcrumb\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/gokhan-gokalp.com\\\/devex-series-02-from-catalog-to-copilots-boosting-backstage-with-mcp-server\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/devex-series-02-from-catalog-to-copilots-boosting-backstage-with-mcp-server\\\/#primaryimage\",\"url\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/uploads\\\/2025\\\/08\\\/gokhan-gokalp-mcp-server-backstage.jpg\",\"contentUrl\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/uploads\\\/2025\\\/08\\\/gokhan-gokalp-mcp-server-backstage.jpg\",\"width\":1200,\"height\":675},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/devex-series-02-from-catalog-to-copilots-boosting-backstage-with-mcp-server\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/gokhan-gokalp.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"DevEx Series 02: From Catalog to Copilots. Boosting Backstage with MCP Server\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#website\",\"url\":\"https:\\\/\\\/gokhan-gokalp.com\\\/\",\"name\":\"G\u00f6khan G\u00f6kalp\",\"description\":\"C# &amp; Python lover\",\"publisher\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#\\\/schema\\\/person\\\/7e2a7fa98babd22a5fdae563c4b8cdbe\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/gokhan-gokalp.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"tr\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#\\\/schema\\\/person\\\/7e2a7fa98babd22a5fdae563c4b8cdbe\",\"name\":\"G\u00f6khan G\u00f6kalp\",\"pronouns\":\"he\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/litespeed\\\/avatar\\\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659\",\"url\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/litespeed\\\/avatar\\\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659\",\"contentUrl\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/litespeed\\\/avatar\\\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659\",\"caption\":\"G\u00f6khan G\u00f6kalp\"},\"logo\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/litespeed\\\/avatar\\\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659\"},\"sameAs\":[\"https:\\\/\\\/gokhan-gokalp.com\"],\"url\":\"https:\\\/\\\/gokhan-gokalp.com\\\/tr\\\/author\\\/gok-gokalp\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"DevEx Series 02: From Catalog to Copilots. Boosting Backstage with MCP Server - G\u00f6khan G\u00f6kalp","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/gokhan-gokalp.com\/devex-series-02-from-catalog-to-copilots-boosting-backstage-with-mcp-server\/","og_locale":"tr_TR","og_type":"article","og_title":"DevEx Series 02: From Catalog to Copilots. Boosting Backstage with MCP Server - G\u00f6khan G\u00f6kalp","og_url":"https:\/\/gokhan-gokalp.com\/devex-series-02-from-catalog-to-copilots-boosting-backstage-with-mcp-server\/","og_site_name":"G\u00f6khan G\u00f6kalp","article_published_time":"2025-08-21T19:35:06+00:00","article_modified_time":"2025-08-22T08:44:48+00:00","og_image":[{"width":1200,"height":675,"url":"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/gokhan-gokalp-mcp-server-backstage.jpg","type":"image\/jpeg"}],"author":"G\u00f6khan G\u00f6kalp","twitter_card":"summary_large_image","twitter_misc":{"Yazan:":"G\u00f6khan G\u00f6kalp","Tahmini okuma s\u00fcresi":"20 dakika"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/gokhan-gokalp.com\/devex-series-02-from-catalog-to-copilots-boosting-backstage-with-mcp-server\/#article","isPartOf":{"@id":"https:\/\/gokhan-gokalp.com\/devex-series-02-from-catalog-to-copilots-boosting-backstage-with-mcp-server\/"},"author":{"name":"G\u00f6khan G\u00f6kalp","@id":"https:\/\/gokhan-gokalp.com\/#\/schema\/person\/7e2a7fa98babd22a5fdae563c4b8cdbe"},"headline":"DevEx Series 02: From Catalog to Copilots. Boosting Backstage with MCP Server","datePublished":"2025-08-21T19:35:06+00:00","dateModified":"2025-08-22T08:44:48+00:00","mainEntityOfPage":{"@id":"https:\/\/gokhan-gokalp.com\/devex-series-02-from-catalog-to-copilots-boosting-backstage-with-mcp-server\/"},"wordCount":3254,"commentCount":0,"publisher":{"@id":"https:\/\/gokhan-gokalp.com\/#\/schema\/person\/7e2a7fa98babd22a5fdae563c4b8cdbe"},"image":{"@id":"https:\/\/gokhan-gokalp.com\/devex-series-02-from-catalog-to-copilots-boosting-backstage-with-mcp-server\/#primaryimage"},"thumbnailUrl":"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/gokhan-gokalp-mcp-server-backstage.jpg","keywords":["backstage","C#","developer experience","devex","dotnet","llm","mcp","mcp server","model context protocol","platform engineering"],"articleSection":[".NET","Platform Engineering"],"inLanguage":"tr","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/gokhan-gokalp.com\/devex-series-02-from-catalog-to-copilots-boosting-backstage-with-mcp-server\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/gokhan-gokalp.com\/devex-series-02-from-catalog-to-copilots-boosting-backstage-with-mcp-server\/","url":"https:\/\/gokhan-gokalp.com\/devex-series-02-from-catalog-to-copilots-boosting-backstage-with-mcp-server\/","name":"DevEx Series 02: From Catalog to Copilots. Boosting Backstage with MCP Server - G\u00f6khan G\u00f6kalp","isPartOf":{"@id":"https:\/\/gokhan-gokalp.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/gokhan-gokalp.com\/devex-series-02-from-catalog-to-copilots-boosting-backstage-with-mcp-server\/#primaryimage"},"image":{"@id":"https:\/\/gokhan-gokalp.com\/devex-series-02-from-catalog-to-copilots-boosting-backstage-with-mcp-server\/#primaryimage"},"thumbnailUrl":"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/gokhan-gokalp-mcp-server-backstage.jpg","datePublished":"2025-08-21T19:35:06+00:00","dateModified":"2025-08-22T08:44:48+00:00","breadcrumb":{"@id":"https:\/\/gokhan-gokalp.com\/devex-series-02-from-catalog-to-copilots-boosting-backstage-with-mcp-server\/#breadcrumb"},"inLanguage":"tr","potentialAction":[{"@type":"ReadAction","target":["https:\/\/gokhan-gokalp.com\/devex-series-02-from-catalog-to-copilots-boosting-backstage-with-mcp-server\/"]}]},{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/gokhan-gokalp.com\/devex-series-02-from-catalog-to-copilots-boosting-backstage-with-mcp-server\/#primaryimage","url":"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/gokhan-gokalp-mcp-server-backstage.jpg","contentUrl":"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2025\/08\/gokhan-gokalp-mcp-server-backstage.jpg","width":1200,"height":675},{"@type":"BreadcrumbList","@id":"https:\/\/gokhan-gokalp.com\/devex-series-02-from-catalog-to-copilots-boosting-backstage-with-mcp-server\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/gokhan-gokalp.com\/"},{"@type":"ListItem","position":2,"name":"DevEx Series 02: From Catalog to Copilots. Boosting Backstage with MCP Server"}]},{"@type":"WebSite","@id":"https:\/\/gokhan-gokalp.com\/#website","url":"https:\/\/gokhan-gokalp.com\/","name":"G\u00f6khan G\u00f6kalp","description":"C# &amp; Python lover","publisher":{"@id":"https:\/\/gokhan-gokalp.com\/#\/schema\/person\/7e2a7fa98babd22a5fdae563c4b8cdbe"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/gokhan-gokalp.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"tr"},{"@type":["Person","Organization"],"@id":"https:\/\/gokhan-gokalp.com\/#\/schema\/person\/7e2a7fa98babd22a5fdae563c4b8cdbe","name":"G\u00f6khan G\u00f6kalp","pronouns":"he","image":{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/gokhan-gokalp.com\/wp-content\/litespeed\/avatar\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659","url":"https:\/\/gokhan-gokalp.com\/wp-content\/litespeed\/avatar\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659","contentUrl":"https:\/\/gokhan-gokalp.com\/wp-content\/litespeed\/avatar\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659","caption":"G\u00f6khan G\u00f6kalp"},"logo":{"@id":"https:\/\/gokhan-gokalp.com\/wp-content\/litespeed\/avatar\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659"},"sameAs":["https:\/\/gokhan-gokalp.com"],"url":"https:\/\/gokhan-gokalp.com\/tr\/author\/gok-gokalp\/"}]}},"_links":{"self":[{"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/posts\/4795","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/comments?post=4795"}],"version-history":[{"count":31,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/posts\/4795\/revisions"}],"predecessor-version":[{"id":4837,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/posts\/4795\/revisions\/4837"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/media\/4832"}],"wp:attachment":[{"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/media?parent=4795"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/categories?post=4795"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/tags?post=4795"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}