{
  "path": "/3m4tkvaq4gk2h",
  "site": "at://did:plc:xbtmt2zjwlrfegqvch7fboei/site.standard.publication/3lxksvuhk3s2j",
  "$type": "site.standard.document",
  "title": "making a docs MCP server",
  "content": {
    "$type": "pub.leaflet.content",
    "pages": [
      {
        "$type": "pub.leaflet.pages.linearDocument",
        "blocks": [
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [
                {
                  "index": {
                    "byteEnd": 32,
                    "byteStart": 14
                  },
                  "features": [
                    {
                      "uri": "https://www.prefect.io/blog/a-prefect-mcp-server",
                      "$type": "pub.leaflet.richtext.facet#link"
                    }
                  ]
                }
              ],
              "plaintext": "When building our own MCP server, we knew we wanted to expose some ability to search our docs, like:"
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": ""
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.code",
              "language": "python",
              "plaintext": "def search_docs(query: str) -> str:"
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": ""
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": "so that MCP clients like ChatGPT and Claude Code can find and read docs while working on user tasks related to Prefect."
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": ""
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [
                {
                  "index": {
                    "byteEnd": 26,
                    "byteStart": 17
                  },
                  "features": [
                    {
                      "uri": "https://bsky.app/profile/mintlify.bsky.social",
                      "$type": "pub.leaflet.richtext.facet#link"
                    }
                  ]
                },
                {
                  "index": {
                    "byteEnd": 56,
                    "byteStart": 40
                  },
                  "features": [
                    {
                      "uri": "https://bsky.app/profile/mintlify.bsky.social/post/3lvbiyuzu5r2q",
                      "$type": "pub.leaflet.richtext.facet#link"
                    }
                  ]
                },
                {
                  "index": {
                    "byteEnd": 129,
                    "byteStart": 99
                  },
                  "features": [
                    {
                      "uri": "https://github.com/PrefectHQ/prefect-mcp-server/pull/25",
                      "$type": "pub.leaflet.richtext.facet#link"
                    }
                  ]
                },
                {
                  "index": {
                    "byteEnd": 151,
                    "byteStart": 143
                  },
                  "features": [
                    {
                      "uri": "https://gofastmcp.com/servers/proxy#proxy-servers",
                      "$type": "pub.leaflet.richtext.facet#link"
                    }
                  ]
                }
              ],
              "plaintext": "We had seen that @mintlify had released their MCP server so we wanted to check it out, but once we plugged it into our MCP server (via FastMCP proxying), it became clear that we could not depend on it to reliably serve clients with documentation excerpts (about 1 in 3 tool calls resulted in opaque 500 failures). So despite our love for all the other things Mintlify does, we knew we needed a new docs MCP."
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": ""
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.blockquote",
              "facets": [
                {
                  "index": {
                    "byteEnd": 39,
                    "byteStart": 31
                  },
                  "features": [
                    {
                      "uri": "https://context7.com/",
                      "$type": "pub.leaflet.richtext.facet#link"
                    }
                  ]
                }
              ],
              "plaintext": "We could have also looked into context7 instead here"
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": ""
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.header",
              "level": 2,
              "facets": [],
              "plaintext": "building still includes buying"
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": "so how hard could it be to just make something that looks and behaves like this?"
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "src": "https://docs.prefect.io/mcp",
              "$type": "pub.leaflet.blocks.website"
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": ""
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [
                {
                  "index": {
                    "byteEnd": 38,
                    "byteStart": 25
                  },
                  "features": [
                    {
                      "$type": "pub.leaflet.richtext.facet#code"
                    }
                  ]
                },
                {
                  "index": {
                    "byteEnd": 64,
                    "byteStart": 59
                  },
                  "features": [
                    {
                      "$type": "pub.leaflet.richtext.facet#code"
                    }
                  ]
                },
                {
                  "index": {
                    "byteEnd": 115,
                    "byteStart": 111
                  },
                  "features": [
                    {
                      "uri": "https://docs.prefect.io",
                      "$type": "pub.leaflet.richtext.facet#link"
                    }
                  ]
                }
              ],
              "plaintext": "that is, one tool called SearchPrefect that takes a single query and returns excerpts with links to the actual docs pages."
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": ""
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": "well, if you have a vectorstore to use, not so hard!"
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": ""
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [
                {
                  "index": {
                    "byteEnd": 50,
                    "byteStart": 39
                  },
                  "features": [
                    {
                      "uri": "https://turbopuffer.com/",
                      "$type": "pub.leaflet.richtext.facet#link"
                    }
                  ]
                },
                {
                  "index": {
                    "byteEnd": 105,
                    "byteStart": 76
                  },
                  "features": [
                    {
                      "uri": "https://github.com/PrefectHQ/marvin/tree/main/examples/slackbot",
                      "$type": "pub.leaflet.richtext.facet#link"
                    }
                  ]
                }
              ],
              "plaintext": "turns out we do have a vectorstore via turbopuffer, since we've used it for our community slackbot Marvin over the last couple years."
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": ""
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [
                {
                  "index": {
                    "byteEnd": 35,
                    "byteStart": 27
                  },
                  "features": [
                    {
                      "uri": "https://www.trychroma.com/",
                      "$type": "pub.leaflet.richtext.facet#link"
                    }
                  ]
                },
                {
                  "index": {
                    "byteEnd": 47,
                    "byteStart": 40
                  },
                  "features": [
                    {
                      "uri": "https://lancedb.com/",
                      "$type": "pub.leaflet.richtext.facet#link"
                    }
                  ]
                }
              ],
              "plaintext": "we've historically ran OSS chromadb and lancedb (which are great!) and less ideal options like Pinecone/Weaviate, but turbopuffer I've found just seems pretty stable and surprises me the least."
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": ""
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [
                {
                  "index": {
                    "byteEnd": 36,
                    "byteStart": 23
                  },
                  "features": [
                    {
                      "$type": "pub.leaflet.richtext.facet#code"
                    }
                  ]
                }
              ],
              "plaintext": "so, right, making that SearchPrefect tool:"
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.unorderedList",
              "children": [
                {
                  "$type": "pub.leaflet.blocks.unorderedList#listItem",
                  "content": {
                    "$type": "pub.leaflet.blocks.text",
                    "facets": [
                      {
                        "index": {
                          "byteEnd": 50,
                          "byteStart": 0
                        },
                        "features": [
                          {
                            "uri": "https://github.com/PrefectHQ/prefect-mcp-server/tree/main/packages/ingestion_pipeline",
                            "$type": "pub.leaflet.richtext.facet#link"
                          }
                        ]
                      }
                    ],
                    "plaintext": "gather, vectorize and upload docs into vectorstore"
                  },
                  "children": []
                },
                {
                  "$type": "pub.leaflet.blocks.unorderedList#listItem",
                  "content": {
                    "$type": "pub.leaflet.blocks.text",
                    "facets": [
                      {
                        "index": {
                          "byteEnd": 23,
                          "byteStart": 0
                        },
                        "features": [
                          {
                            "uri": "https://github.com/PrefectHQ/prefect-mcp-server/blob/main/packages/docs_mcp_server/docs_mcp_server/_server.py",
                            "$type": "pub.leaflet.richtext.facet#link"
                          }
                        ]
                      },
                      {
                        "index": {
                          "byteEnd": 36,
                          "byteStart": 23
                        },
                        "features": [
                          {
                            "$type": "pub.leaflet.richtext.facet#code"
                          },
                          {
                            "uri": "https://github.com/PrefectHQ/prefect-mcp-server/blob/main/packages/docs_mcp_server/docs_mcp_server/_server.py",
                            "$type": "pub.leaflet.richtext.facet#link"
                          }
                        ]
                      },
                      {
                        "index": {
                          "byteEnd": 53,
                          "byteStart": 36
                        },
                        "features": [
                          {
                            "uri": "https://github.com/PrefectHQ/prefect-mcp-server/blob/main/packages/docs_mcp_server/docs_mcp_server/_server.py",
                            "$type": "pub.leaflet.richtext.facet#link"
                          }
                        ]
                      }
                    ],
                    "plaintext": "expose a query tool as SearchPrefect in an MCP server"
                  },
                  "children": []
                }
              ]
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [
                {
                  "index": {
                    "byteEnd": 22,
                    "byteStart": 0
                  },
                  "features": [
                    {
                      "uri": "https://github.com/PrefectHQ/prefect-mcp-server/tree/main/packages/docs_mcp_server",
                      "$type": "pub.leaflet.richtext.facet#link"
                    }
                  ]
                }
              ],
              "plaintext": "so that's what we did."
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": ""
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": "the only real question left is, where do we host the MCP server?"
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": ""
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.header",
              "level": 2,
              "facets": [],
              "plaintext": "if only we knew an easy place to host MCP servers...."
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [
                {
                  "index": {
                    "byteEnd": 8,
                    "byteStart": 0
                  },
                  "features": [
                    {
                      "uri": "https://fastmcp.cloud/",
                      "$type": "pub.leaflet.richtext.facet#link"
                    }
                  ]
                }
              ],
              "plaintext": "ohhh yea, we do. so now that that exists:"
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.code",
              "language": "python",
              "plaintext": "# uvx --with fastmcp ipython\n\nasync with Client(\"https://prefect-docs.fastmcp.app/mcp\") as client:\n    response = await client.call_tool(\n        \"search_prefect\", {\"query\": \"how to build prefect flows\"}\n    )\n    print(response)"
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": ""
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [
                {
                  "index": {
                    "byteEnd": 19,
                    "byteStart": 0
                  },
                  "features": [
                    {
                      "$type": "pub.leaflet.richtext.facet#italic"
                    }
                  ]
                }
              ],
              "plaintext": "drum roll please..."
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "src": "https://github.com/PrefectHQ/prefect-mcp-server/pull/48",
              "$type": "pub.leaflet.blocks.website",
              "title": "other docs server by zzstoatzz · Pull Request #48 · PrefectHQ/prefect-mcp-server",
              "description": "closes #41",
              "previewImage": {
                "$type": "blob",
                "ref": {
                  "$link": "bafkreiew5siawadl7cecocxunwicjsyb7zg6arzrdez46gnv6vqmnbcdfa"
                },
                "mimeType": "image/png",
                "size": 25676
              }
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": ""
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.image",
              "image": {
                "$type": "blob",
                "ref": {
                  "$link": "bafkreib3w56dsvs6gp5kovli4rsts52neorj7wzvbuyumebwcenocswwfq"
                },
                "mimeType": "image/png",
                "size": 46259
              },
              "aspectRatio": {
                "width": 735,
                "height": 253
              }
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": "and bada-bing bada-boom we have a docs tool on our Prefect MCP server. not the worst yak shaving exercise (we still 💙 Mintlify)"
            }
          }
        ]
      }
    ]
  },
  "description": "for our MCP server",
  "publishedAt": "2025-11-04T22:18:34.010Z"
}