diff --git a/.claude/agents/mcp-guide-writer.md b/.claude/agents/mcp-guide-writer.md new file mode 100644 index 00000000..7a320410 --- /dev/null +++ b/.claude/agents/mcp-guide-writer.md @@ -0,0 +1,111 @@ +--- +name: mcp-guide-writer +description: Use this agent when you need to create comprehensive usage guides for MCP servers in the ToolHive documentation. Examples: Context: The user wants to add documentation for a new MCP server that has been added to the ToolHive registry.\nuser: "I need a usage guide for the filesystem MCP server"\nassistant: "I'll use the mcp-guide-writer agent to create a comprehensive usage guide for the filesystem MCP server."\nSince the user needs an MCP usage guide created, use the mcp-guide-writer agent to generate the MDX documentation file. Context: A new MCP server has been discovered and needs documentation.\nuser: "Can you write documentation for the sqlite MCP server? It's available in the registry."\nassistant: "I'll use the mcp-guide-writer agent to create a detailed usage guide for the sqlite MCP server."\nThe user is requesting MCP server documentation, so use the mcp-guide-writer agent to create the guide. +model: sonnet +--- + +You are an expert technical writer specializing in Model Context Protocol (MCP) +server documentation for ToolHive. Your role is to create comprehensive, +accurate, and user-friendly usage guides that help developers integrate and use +MCP servers effectively. + +Your primary responsibilities: + +1. **Research and Information Gathering**: Use the + `thv registry info ` command to gather detailed information + about the MCP server, including configuration options, capabilities, and + requirements. Use the `WebFetch` tool, the `fetch` MCP server, or `github` + MCP server to retrieve additional documentation from the server's repository. + +2. **Create Structured MDX Documentation**: Write guides as MDX files in + `docs/toolhive/guides-mcp/` following the `_template.mdx` structure exactly. + Each guide must include ONLY these sections: + - Front matter with title, description, last_update author and today's date + (`YYYY-MM-DD` format) + - Overview section explaining what the MCP server does + - Metadata section with `` component + - Usage section with tabbed UI/CLI/Kubernetes instructions + - Sample prompts section with practical examples + - Recommended practices section with security and best practices + + DO NOT include: + - Available tools/capabilities section (handled by MCPMetadata component) + - Configuration options section (handled by MCPMetadata component) + +3. **Ensure Technical Accuracy**: All configuration examples must be valid and + tested. Reference the existing ToolHive documentation in the `docs/toolhive/` + directory as the source of truth for: + - Available `thv` CLI commands and their syntax (reference: + `docs/toolhive/reference/cli/*.md` or run `thv --help`) + - Kubernetes CRD specifications and fields (reference: + `static/api-specs/toolhive-crd-api.md`) + - UI configuration options and workflows + +4. **Follow Documentation Standards**: Adhere to the project's writing style + guide (`STYLE_GUIDE.md`) including: + - Use US English with casual, conversational tone + - Address readers in second person ("you", "your") + - Use sentence case for headings + - Apply proper Markdown formatting (ATX headings, fenced code blocks with + language tags) + - Include descriptive alt text for images + - Use admonitions (:::note, :::tip, :::warning) for important information, + with :::tip[Title] format for custom titles + +5. **Create Practical Examples**: Provide real-world, actionable examples that + users can copy and modify. Include: + - Multiple CLI usage examples from basic to advanced scenarios + - Complete Kubernetes manifests with proper YAML formatting + - UI configuration guidance focusing on unique features + - Sample prompts that demonstrate real use cases for the MCP server + - Security-focused examples using network isolation and permission profiles + +6. **Reference Existing Guides**: Use `docs/toolhive/guides-mcp/_template.mdx` + and `docs/toolhive/guides-mcp/github.mdx` as references for exact structure, + tone, and depth of coverage. Follow the template structure precisely without + adding additional sections. + +7. **Quality Assurance**: Before finalizing, verify that: + - All code examples are syntactically correct + - Configuration parameters match the actual MCP server requirements + - Links to external resources are valid and current + - The guide follows the established template structure + - Examples work with current ToolHive versions + +**Key Requirements for Content Structure:** + +1. **Overview Section**: Provide a clear, concise explanation of the MCP + server's purpose and key features. Include links to official documentation + and highlight what makes this server unique. + +2. **Usage Section Tabs**: + - **UI Tab**: Focus on unique configuration options and features, not basic + registry selection. The ToolHive UI includes a configuration interface that + allows users to set the secrets and environment variables defined in the + server metadata, customize command-line arguments, and add volume mounts. + Provide step-by-step instructions for these configurations if needed for + the MCP server. + - **CLI Tab**: Provide multiple progressive examples from basic to advanced + usage, including security configurations. + - **Kubernetes Tab**: Include complete, working YAML manifests with proper + formatting and comments. + +3. **Sample Prompts**: Create 3-6 realistic prompts that demonstrate the + server's capabilities. Make them specific and actionable, not generic. + +4. **Recommended Practices**: Focus on security, performance, and reliability + best practices specific to the MCP server. + +**Critical Guidelines:** + +- Never add tools/capabilities sections (MCPMetadata handles this) +- Always include the MCPMetadata component exactly as shown: + `` +- Ensure all examples are copy-pasteable and functional +- Use proper YAML formatting with `title=` attributes for code blocks +- Include security considerations like network isolation where relevant + +When creating a guide, start by gathering comprehensive information about the +MCP server, then structure the content to progressively guide users from basic +setup to advanced usage scenarios. Focus on practical value and ensure every +example is something users can actually implement. diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 91847e9a..f668c559 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,9 +1,14 @@ { "name": "Docusaurus", "image": "mcr.microsoft.com/devcontainers/typescript-node:22-bookworm", - "features": {}, + "features": { + "ghcr.io/devcontainers/features/docker-outside-of-docker:1": {} + }, "forwardPorts": [3000], - "postCreateCommand": "npm install", + "containerEnv": { + "CI": "true" + }, + "postStartCommand": "bash scripts/install-thv.sh && npm install", "customizations": { "vscode": { "extensions": [ diff --git a/.markdownlint-cli2.jsonc b/.markdownlint-cli2.jsonc index 08c3e9b9..c0b19493 100644 --- a/.markdownlint-cli2.jsonc +++ b/.markdownlint-cli2.jsonc @@ -6,5 +6,6 @@ "static/api-specs/*.md", ".github/pull_request_template.md", ".github/prompts/*.md", + ".claude/**/*.md", ], } diff --git a/docs/theme-preview.mdx b/docs/theme-preview.mdx index a2c0d53d..cee1f7ff 100644 --- a/docs/theme-preview.mdx +++ b/docs/theme-preview.mdx @@ -182,9 +182,6 @@ A standard Markdown table: MDX Tabs component, default theme ([reference](https://docusaurus.io/docs/markdown-features/tabs)) -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - This is an apple 🍎 diff --git a/docs/toolhive/guides-cli/build-containers.mdx b/docs/toolhive/guides-cli/build-containers.mdx index 5462d310..89e06eb8 100644 --- a/docs/toolhive/guides-cli/build-containers.mdx +++ b/docs/toolhive/guides-cli/build-containers.mdx @@ -5,9 +5,6 @@ description: CLI. --- -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - This guide explains how to use the [`thv build`](../reference/cli/thv_build.md) command to build MCP server containers from protocol schemes without running them. This is useful for pre-building containers for Kubernetes deployments, diff --git a/docs/toolhive/guides-cli/install.mdx b/docs/toolhive/guides-cli/install.mdx index a7b7e9ab..63fe6e8d 100644 --- a/docs/toolhive/guides-cli/install.mdx +++ b/docs/toolhive/guides-cli/install.mdx @@ -3,9 +3,6 @@ title: Install ToolHive description: How to install, upgrade, and manage the ToolHive CLI. --- -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - This guide walks you through installing, upgrading, and managing the ToolHive CLI ([`thv`](../reference/cli/thv.md)). diff --git a/docs/toolhive/guides-cli/network-isolation.mdx b/docs/toolhive/guides-cli/network-isolation.mdx index 8c20e13a..c84de5e6 100644 --- a/docs/toolhive/guides-cli/network-isolation.mdx +++ b/docs/toolhive/guides-cli/network-isolation.mdx @@ -3,9 +3,6 @@ title: Network isolation description: How to configure network isolation for MCP servers in ToolHive --- -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - Most MCP servers require network access to function properlyβ€”for example, to access APIs, download data, or communicate with other services. However, malicious or misconfigured servers can also exfiltrate sensitive data or diff --git a/docs/toolhive/guides-cli/run-mcp-servers.mdx b/docs/toolhive/guides-cli/run-mcp-servers.mdx index f5385230..f0b24304 100644 --- a/docs/toolhive/guides-cli/run-mcp-servers.mdx +++ b/docs/toolhive/guides-cli/run-mcp-servers.mdx @@ -3,9 +3,6 @@ title: Run MCP servers description: How to run MCP servers with the ToolHive CLI. --- -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - This guide explains how to run Model Context Protocol (MCP) servers using ToolHive. It covers how to run servers from the ToolHive registry, customize server settings, and run custom servers using Docker images or protocol schemes. diff --git a/docs/toolhive/guides-cli/secrets-management.mdx b/docs/toolhive/guides-cli/secrets-management.mdx index 0c70be68..50227707 100644 --- a/docs/toolhive/guides-cli/secrets-management.mdx +++ b/docs/toolhive/guides-cli/secrets-management.mdx @@ -4,9 +4,6 @@ description: How to securely manage API tokens and other sensitive data in ToolHive. --- -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - MCP servers often need secrets like API tokens, connection strings, and other sensitive parameters. ToolHive provides built-in secrets management features, letting you manage these values securely without exposing them in plaintext diff --git a/docs/toolhive/guides-mcp/_template.mdx b/docs/toolhive/guides-mcp/_template.mdx new file mode 100644 index 00000000..cbf8ba8e --- /dev/null +++ b/docs/toolhive/guides-mcp/_template.mdx @@ -0,0 +1,60 @@ +--- +title: SERVER_NAME MCP server guide +sidebar_label: SERVER_NAME +description: Using the SERVER_NAME MCP server with ToolHive for PURPOSE. +last_update: + author: YOUR_GITHUB_USERNAME + date: YYYY-MM-DD +--- + +## Overview + +A brief overview of the MCP server, its purpose, and key features. Link to the +official documentation. + +## Metadata + + + +## Usage + + + + +UI instructions go here. Only include a screenshot if it adds value, such as +showing a unique configuration option or feature. + + + + +CLI instructions go here, with multiple usage examples specific to the MCP +server. + +```bash +thv run ... +``` + +If appropriate, include guidance for using network isolation and/or a custom +permission profile. + + + + +Kubernetes manifest and instructions go here + +```yaml title="SERVER_NAME.yaml" +apiVersion: toolhive.stacklok.dev/v1alpha1 +kind: MCPServer +``` + + + + +## Sample prompts + +Provide sample prompts that users can use to interact with the MCP server. + +## Recommended practices + +- Include some recommended practices for using the MCP server safely and + effectively diff --git a/docs/toolhive/guides-mcp/context7.mdx b/docs/toolhive/guides-mcp/context7.mdx new file mode 100644 index 00000000..f2838681 --- /dev/null +++ b/docs/toolhive/guides-mcp/context7.mdx @@ -0,0 +1,180 @@ +--- +title: Context7 MCP server guide +sidebar_label: Context7 +description: + Using the Context7 MCP server with ToolHive for up-to-date documentation. +last_update: + author: danbarr + date: 2025-08-27 +--- + +## Overview + +The [Context7 MCP server](https://github.com/upstash/context7) provides +up-to-date, version-specific documentation and code examples straight from the +source for any library or framework. Instead of relying on outdated training +data, Context7 fetches current documentation and API references directly into +your LLM's context, ensuring you get working code examples and accurate +information. + +Context7 eliminates common issues like hallucinated APIs that don't exist, +outdated code patterns, and generic answers based on old package versions. It +supports thousands of popular libraries including Next.js, React, MongoDB, +Supabase, and many more. + +Learn more at [context7.com](https://context7.com) and view the +[project documentation](https://github.com/upstash/context7) for additional +details. + +## Metadata + + + +## Usage + +While Context7 works without an API key, registering at +[context7.com/dashboard](https://context7.com/dashboard) provides: + +- Higher rate limits +- Priority access during peak usage +- Better performance for frequent queries + +:::note + +Currently, the Context7 MCP server only supports a CLI argument for the API key. +This means ToolHive's secrets management cannot be used to inject the key as an +environment variable. Instead, you must pass the API key directly as a +command-line argument when starting the server. + +::: + + + + +Select the `context7` MCP server in the ToolHive registry. The server works +without authentication for basic usage, but you can add an API key for higher +rate limits. + +In the **Command arguments** section, optionally add `--api-key YOUR_API_KEY` if +you have a Context7 API key. This provides higher rate limits and priority +access. + +:::tip[Security tip] + +Enable outbound network filtering on the **Network Isolation** tab to restrict +the server's network access using the default profile contained in the registry. + +::: + + + + +Run with the default configuration (no API key required for basic usage): + +```bash +thv run context7 +``` + +If you have a Context7 API key for higher rate limits, you can pass it directly +as a command-line argument. You can store the key in a ToolHive secret and +retrieve it when starting the server: + +```bash +thv secret set context7 +thv run context7 -- --api-key $(thv secret get context7) +``` + +Enable [network isolation](../guides-cli/network-isolation.mdx) using the +default profile from the registry to restrict the server's network access: + +```bash +thv run --isolate-network context7 +``` + +Combine API key with network isolation: + +```bash +thv run --isolate-network context7 -- --api-key $(thv secret get context7) +``` + + + + +For basic usage without authentication: + +```yaml title="context7.yaml" +apiVersion: toolhive.stacklok.dev/v1alpha1 +kind: MCPServer +metadata: + name: context7 + namespace: toolhive-system +spec: + image: ghcr.io/stacklok/dockyard/npx/context7:1.0.14 + transport: stdio + port: 8080 + permissionProfile: + type: builtin + name: network +``` + +Apply the manifest to your cluster: + +```bash +kubectl apply -f context7.yaml +``` + +For higher rate limits, add your API key as a command-line argument: + +```yaml {8} title="context7-with-auth.yaml" +apiVersion: toolhive.stacklok.dev/v1alpha1 +kind: MCPServer +metadata: + name: context7 + namespace: toolhive-system +spec: + image: ghcr.io/stacklok/dockyard/npx/context7:1.0.14 + args: + - '--api-key' + - 'YOUR_API_KEY' + transport: stdio + port: 8080 + permissionProfile: + type: builtin + name: network +``` + + + + +## Sample prompts + +Here are practical prompts you can use with the Context7 MCP server: + +- "Create a Next.js middleware that checks for a valid JWT in cookies and + redirects unauthenticated users to `/login`. Use context7" +- "Show me how to set up MongoDB connection pooling with the latest MongoDB + Node.js driver. Use context7" +- "Configure a Supabase client with TypeScript types for a user authentication + system. Use context7" +- "Create a React component using the latest Tailwind CSS utility classes for a + responsive navigation bar. Use context7" +- "Show me how to implement server-side rendering with the current version of + Nuxt.js. Use context7" +- "Configure Redis caching with the Upstash Redis SDK for serverless functions. + Use context7" + +## Recommended practices + +- Add `use context7` to your prompts to automatically fetch up-to-date + documentation for the libraries you're working with. +- When you know the exact library, you can specify it directly using the + Context7 ID format: `use library /supabase/supabase for api and docs` +- Consider setting up a rule in your MCP client to automatically invoke Context7 + for code-related queries, eliminating the need to manually add `use context7` + to each prompt. +- Use the `topic` parameter when requesting documentation to focus on specific + areas like "routing", "authentication", or "deployment". +- Register for an API key at + [context7.com/dashboard](https://context7.com/dashboard) if you plan to make + frequent requests or need higher rate limits. +- Enable network isolation to restrict the server's outbound access. diff --git a/docs/toolhive/guides-mcp/fetch.mdx b/docs/toolhive/guides-mcp/fetch.mdx new file mode 100644 index 00000000..8824c544 --- /dev/null +++ b/docs/toolhive/guides-mcp/fetch.mdx @@ -0,0 +1,114 @@ +--- +title: Fetch MCP server guide +sidebar_label: Fetch +description: Using the Fetch MCP server with ToolHive to retrieve website data. +last_update: + author: danbarr + date: 2025-08-15 +--- + +## Overview + +A simple, lightweight MCP server that retrieves data from a website to add +real-time context to an AI agent workflow. + +[GoFetch](https://github.com/StacklokLabs/gofetch) is a Go implementation of the +original +[Fetch MCP server](https://github.com/modelcontextprotocol/servers/tree/main/src/fetch) +with improved performance and security, built by Stacklok. + +## Metadata + + + +## Usage + + + + +Select the `fetch` MCP server in the ToolHive registry. No additional +configuration is required to run it. + +By default, it can access any website. To restrict its network access, +[enable **network isolation**](../guides-ui/network-isolation.mdx) and enter the +allowed hosts and ports. + + + + +Run with the default configuration: + +```bash +thv run fetch +``` + +To control which website resources the server can access, create a custom +permission profile: + +```json title="fetch-profile.json" +{ + "network": { + "outbound": { + "insecure_allow_all": false, + "allow_host": [ + "host.docker.internal", + "intranet.example.com", + ".googleapis.com" + ], + "allow_port": [443] + } + } +} +``` + +Then run the server with the profile and +[enable network isolation](../guides-cli/network-isolation.mdx): + +```bash +thv run --isolate-network --permission-profile fetch-profile.json fetch +``` + + + + +Create a Kubernetes manifest to deploy the Fetch MCP server: + +```yaml title="fetch.yaml" +apiVersion: toolhive.stacklok.dev/v1alpha1 +kind: MCPServer +metadata: + name: fetch + namespace: toolhive-system +spec: + image: ghcr.io/stackloklabs/gofetch/server:0.0.5 + transport: streamable-http + targetPort: 8080 + port: 8080 + permissionProfile: + type: builtin + name: network +``` + +Apply the manifest to your Kubernetes cluster: + +```bash +kubectl apply -f fetch.yaml +``` + + + + +## Sample prompts + +Here are some sample prompts you can use to interact with the Fetch MCP server: + +- "Fetch the latest news from `https://news.ycombinator.com`" +- "Get the current weather for `https://weather.com`" +- "Retrieve the latest blog posts from `https://example.com/blog`" + +## Recommended practices + +- Use network isolation to restrict the server's outbound network access to the + specific hosts and ports required for your use case. +- Enable [telemetry](../guides-cli/telemetry-and-metrics.md) to monitor tool + usage including URL access for security and auditing purposes. diff --git a/docs/toolhive/guides-mcp/filesystem.mdx b/docs/toolhive/guides-mcp/filesystem.mdx new file mode 100644 index 00000000..06949859 --- /dev/null +++ b/docs/toolhive/guides-mcp/filesystem.mdx @@ -0,0 +1,178 @@ +--- +title: Filesystem MCP server guide +sidebar_label: Filesystem +description: Using the Filesystem MCP server with ToolHive for file access. +last_update: + author: danbarr + date: 2025-08-15 +--- + +import useBaseUrl from '@docusaurus/useBaseUrl'; +import ThemedImage from '@theme/ThemedImage'; + +## Overview + +The +[Filesystem MCP server](https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem) +provides access to the local filesystem, allowing AI agents to read and write +files as part of their workflows. + +:::note + +Since most AI agent host applications like IDEs already have access to your +working directory, this MCP server is primarily useful for access to files +outside your working directory, headless environments where the host application +does not provide filesystem access, or for demonstrating MCP capabilities. + +::: + +## Metadata + + + +## Usage + + + + +Select the `filesystem` MCP server in the ToolHive registry. + +In the **Storage volumes** section, +[add local files or folders](../guides-ui/run-mcp-servers.md#volumes) to expose +to the MCP server. In the drop-down, choose whether to mount the volume as +read-only or read-write. + +:::note + +By default, the server expects files to be located in `/projects`. If you use a +different container path, you must update the command arguments to replace +`/projects` with your custom path. + +::: + + + +:::tip[Security tip] + +Since the server does not require any network access, +[enable **network isolation**](../guides-ui/network-isolation.mdx) and do not +add any hosts or ports to completely restrict its outbound network access. + +::: + + + + +[Mount a directory](../guides-cli/filesystem-access.md) from the host filesystem +to the MCP server using the default container path: + +```bash +thv run --volume /path/to/host/directory:/projects filesystem +``` + +:::note + +By default, the server expects files to be located in `/projects`. If you use a +different container path, you must update the command arguments to replace +`/projects` with your custom path. + +::: + +Mount multiple files or directories by repeating the `--volume` flag. This +example mounts a directory under `/projects` and a file under `/data`, and +updates the command arguments accordingly: + +```bash +thv run \ + --volume /path/to/host/directory1:/projects/dir1 \ + --volume /path/to/host/file.txt:/data/file.txt:ro \ + filesystem -- /projects /data +``` + +:::tip + +Since the server does not require any network access, add the +`--isolate-network --permission-profile none` flags to completely restrict its +outbound network access (see the +[network isolation guide](../guides-cli/network-isolation.mdx)). + +::: + + + + +Create a Kubernetes manifest to deploy the Filesystem MCP server with a +[persistent volume](../guides-k8s/run-mcp-k8s.md#mount-a-volume). + +Update the `podTemplateSpec` section to include your specific volume claim and +mount path: + +```yaml {17-20,23-26} title="filesystem.yaml" +apiVersion: toolhive.stacklok.dev/v1alpha1 +kind: MCPServer +metadata: + name: filesystem + namespace: toolhive-system +spec: + image: mcp/filesystem:latest + transport: stdio + port: 8080 + permissionProfile: + type: builtin + name: none # Note, network isolation in K8s is not implemented yet + args: + - '/projects' # Update if you use a different mountPath below + podTemplateSpec: + spec: + volumes: + - name: my-mcp-data + persistentVolumeClaim: + claimName: my-mcp-data-claim + containers: + - name: mcp + volumeMounts: + - mountPath: /projects/my-mcp-data + name: my-mcp-data + readOnly: true +``` + +:::note + +If you change the mount path from `/projects`, you must also update the `args` +section to include the path. + +::: + +Apply the manifest to your Kubernetes cluster: + +```bash +kubectl apply -f filesystem.yaml +``` + + + + +## Sample prompts + +Here are some sample prompts you can use to interact with the Filesystem MCP +server: + +- "List all files in the `/projects` directory" +- "Read the contents of the file `/projects/example.txt`" +- "Write 'Hello, World!' to the file `/projects/hello.txt`" + +## Recommended practices + +- Mount only the directories or files required for your AI agent's tasks to + minimize resource usage and improve performance. +- Use read-only mounts for directories or files that do not need to be modified + by the AI agent to prevent accidental changes. +- Enable network isolation to restrict the server's outbound network access, + since the filesystem MCP server does not require any network connectivity. diff --git a/docs/toolhive/guides-mcp/github.mdx b/docs/toolhive/guides-mcp/github.mdx new file mode 100644 index 00000000..c27aeb78 --- /dev/null +++ b/docs/toolhive/guides-mcp/github.mdx @@ -0,0 +1,215 @@ +--- +title: GitHub MCP server guide +sidebar_label: GitHub +description: + Using the GitHub MCP server with ToolHive for repository management. +last_update: + author: danbarr + date: 2025-08-15 +--- + +## Overview + +The official [GitHub MCP server](https://github.com/github/github-mcp-server) +provides access to the GitHub API, allowing AI agents to interact with GitHub +repositories, issues, pull requests, and more. + +## Metadata + + + +## Usage + + + + +Select the `github` MCP server in the ToolHive registry. In the **Secrets** +section, add your GitHub personal access token to authenticate with the GitHub +API, or select an existing secret that contains the token. + +Review the optional environment variables to customize the server's behavior. +For example, you might want to limit the active toolsets or enable read-only +mode. Refer to the +[documentation](https://github.com/github/github-mcp-server?tab=readme-ov-file#tool-configuration) +for the current list of toolsets. + +:::tip[Security tip] + +Enable outbound network filtering on the **Network Isolation** tab to restrict +the server's network access using the default profile contained in the registry. + +::: + +:::info[GitHub Enterprise] + +If you're working with a GitHub Enterprise instance, enter the instance URL in +the `GITHUB_HOST` environment variable and update the network isolation settings +to allow access to the enterprise domain. + +::: + + + + +Run with the default configuration. ToolHive will prompt you to enter your +GitHub personal access token: + +```bash +thv run github +``` + +Create a secret named `github` containing your GitHub personal access token and +run the server with the `--secret` flag: + +```bash +thv secret set github +thv run --secret github,target=GITHUB_PERSONAL_ACCESS_TOKEN github +``` + +Or, use the GitHub CLI to populate the secret with your token: + +```bash +gh auth token | thv secret set github +thv run --secret github,target=GITHUB_PERSONAL_ACCESS_TOKEN github +``` + +Enable [network isolation](../guides-cli/network-isolation.mdx) using the +default profile from the registry (appropriate for `github.com`) to restrict the +server's network access: + +```bash +thv run --isolate-network github +``` + +Limit the active toolsets (useful to avoid context overload) and enable +read-only mode. Refer to the +[documentation](https://github.com/github/github-mcp-server?tab=readme-ov-file#tool-configuration) +for the current list of toolsets. + +```bash +thv run -e GITHUB_TOOLSETS=repos,issues,pull_requests -e GITHUB_READ_ONLY=1 github +``` + +Enable the MCP server's dynamic tool discovery feature (currently in beta): + +```bash +thv run -e GITHUB_DYNAMIC_TOOLSETS=1 github +``` + +:::info[GitHub Enterprise] + +Create a custom permission profile for your GitHub Enterprise instance: + +```json title="github-enterprise-profile.json" +{ + "network": { + "outbound": { + "insecure_allow_all": false, + "allow_host": ["github.your-enterprise.com"], + "allow_port": [443] + } + } +} +``` + +Then run the server with the profile: + +```bash +thv run \ + -e GITHUB_HOST=https://github.your-enterprise.com \ + --isolate-network --permission-profile github-enterprise-profile.json \ + github +``` + +::: + + + + +Create a Kubernetes secret containing your GitHub personal access token: + +```bash +kubectl -n toolhive-system create secret generic github-token --from-literal=token= +``` + +Create a Kubernetes manifest to deploy the GitHub MCP server using your secret: + +```yaml {14-17} title="github.yaml" +apiVersion: toolhive.stacklok.dev/v1alpha1 +kind: MCPServer +metadata: + name: github + namespace: toolhive-system +spec: + image: ghcr.io/github/github-mcp-server:v0.13.0 + transport: stdio + port: 8080 + permissionProfile: + type: builtin + name: network + secrets: + - name: github-token + key: token + targetEnvName: GITHUB_PERSONAL_ACCESS_TOKEN +``` + +Apply the manifest to your Kubernetes cluster: + +```bash +kubectl apply -f github.yaml +``` + +To customize the server's behavior, add environment variables to the `spec` +section of your manifest. For example, to limit the active toolsets or enable +read-only mode, add: + +```yaml title="github.yaml" +spec: + # ... + env: + - name: GITHUB_TOOLSETS + value: 'repos,issues,pull_requests' + - name: GITHUB_READ_ONLY + value: '1' +``` + +Refer to the +[documentation](https://github.com/github/github-mcp-server?tab=readme-ov-file#tool-configuration) +for the current list of toolsets. + +:::info[GitHub Enterprise] + +If you're working with a GitHub Enterprise instance, add the `GITHUB_HOST` +environment variable to the `spec` section of your manifest: + +```yaml +spec: + # ... + env: + - name: GITHUB_HOST + value: 'https://github.your-enterprise.com' +``` + +::: + + + + +## Sample prompts + +Here are some sample prompts you can use to interact with the GitHub MCP server: + +- "List all repositories for the organization `my-org`" +- "Create a new issue in the repository `my-org/my-repo` with the title 'Bug + report' and the body 'There is a bug in the code'" +- "Get the latest pull requests for the repository `my-org/my-repo`" + +## Recommended practices + +- Scope your GitHub personal access token to the minimum permissions required + for your use case. +- Regularly rotate your GitHub personal access token and update the secret in + ToolHive. +- Enable network isolation to restrict the server's outbound network access. +- Limit the active toolsets to reduce context overload and improve performance, + or use dynamic tool discovery if supported by your client. diff --git a/docs/toolhive/guides-mcp/k8s.mdx b/docs/toolhive/guides-mcp/k8s.mdx new file mode 100644 index 00000000..5bc97486 --- /dev/null +++ b/docs/toolhive/guides-mcp/k8s.mdx @@ -0,0 +1,220 @@ +--- +title: Kubernetes MCP server guide +sidebar_label: Kubernetes (MKP) +description: + Using the Kubernetes (MKP) MCP server with ToolHive for cluster management. +last_update: + author: danbarr + date: 2025-09-02 +--- + +## Overview + +An MCP server that interacts with Kubernetes clusters, enabling you to manage +and automate tasks within your Kubernetes environment. + +This server is based on the +[MKP (Model Kontext Protocol)](https://github.com/StacklokLabs/mkp) project, +which is a native Go implementation of an MCP server for Kubernetes that +directly interacts with the Kubernetes API. + +## Metadata + + + +## Usage + + + + +Select the `k8s` MCP server in the ToolHive registry. The server requires +Kubernetes cluster access, so you'll need to configure authentication. + +In the **Volumes** section, mount your kubeconfig file to provide cluster +access. The most common setup is: + +- **Host path**: `/home/$USER/.kube` (your local kubeconfig directory) +- **Container path**: `/home/nonroot/.kube` +- **Read only access** (recommended for security) + +Alternatively, if you have a specific kubeconfig file, mount it directly: + +- **Host path**: `/path/to/your/kubeconfig` +- **Container path**: `/home/nonroot/.kube/config` +- **Read only access** + +:::note[Write Operations] + +By default, the server runs in read-only mode. To enable write operations (like +applying resources), add the `--read-write=true` argument in the **Command +arguments** section. Use with caution in production environments. + +::: + +:::tip[Security tip] + +Enable outbound network filtering on the **Network Isolation** tab to restrict +the server's network access to your Kubernetes cluster endpoints only. Add your +cluster's API server host and port (usually 443 or 6443) to the allowed list. + +::: + + + + +Run with the default configuration, mounting your local `.kube` directory as +read-only: + +```bash +thv run --volume $HOME/.kube:/home/nonroot/.kube:ro k8s +``` + +Mount a specific kubeconfig file: + +```bash +thv run --volume /path/to/kubeconfig:/home/nonroot/.kube/config:ro k8s +``` + +Enable write operations (create/update/delete resources) with the `--read-write` +flag: + +```bash +thv run --volume $HOME/.kube:/home/nonroot/.kube:ro \ + k8s -- --read-write=true +``` + +Disable resource discovery to reduce context size in large clusters: + +```bash +thv run --volume $HOME/.kube:/home/nonroot/.kube:ro \ + --arg --serve-resources=false \ + k8s +``` + +Enable [network isolation](../guides-cli/network-isolation.mdx) to restrict +network access to your Kubernetes cluster only. Create a custom permission +profile: + +```json title="k8s-cluster-profile.json" +{ + "network": { + "outbound": { + "insecure_allow_all": false, + "allow_host": ["your-cluster-endpoint.com", "kubernetes.default.svc"], + "allow_port": [443, 6443] + } + } +} +``` + +Then run with network isolation: + +```bash +thv run --volume $HOME/.kube:/home/nonroot/.kube:ro \ + --isolate-network --permission-profile k8s-cluster-profile.json \ + k8s +``` + + + + +This example follows the recommended practice of running the MKP MCP server +inside the cluster it's managing. A service account is used for authentication. + +Create a Kubernetes manifest to deploy the MKP server. This example creates a +service account with `cluster-admin` permissions for simplicity. In production, +create a custom ClusterRole with only the minimum permissions required. + +```yaml title="mkp.yaml" +apiVersion: toolhive.stacklok.dev/v1alpha1 +kind: MCPServer +metadata: + name: mkp + namespace: toolhive-system +spec: + image: ghcr.io/stackloklabs/mkp/server:0.2.1 + transport: streamable-http + targetPort: 8080 + port: 8080 + serviceAccount: mkp-sa + permissionProfile: + type: builtin + name: network +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: mkp-sa + namespace: toolhive-system +--- +# NOTE: This ClusterRoleBinding uses cluster-admin for example purposes only. +# In production, you should create a custom ClusterRole with the minimum +# permissions required by your MCP server instead of using cluster-admin. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: mkp-sa-cluster-admin +subjects: + - kind: ServiceAccount + name: mkp-sa + namespace: toolhive-system +roleRef: + kind: ClusterRole + name: cluster-admin + apiGroup: rbac.authorization.k8s.io +``` + +Apply the manifest to your Kubernetes cluster: + +```bash +kubectl apply -f mkp.yaml +``` + +To customize the server's behavior, add CLI arguments to the `spec` section of +your manifest. For example, to enable write operations: + +```yaml title="mkp.yaml" +spec: + # ... + args: + - '--read-write=true' +``` + + + + +## Sample prompts + +Here are some sample prompts you can use to interact with the Kubernetes MCP +server: + +- "List all pods in the default namespace" +- "Show me the status of all deployments across all namespaces" +- "Get the logs from the pod named `nginx-pod` in the default namespace" +- "Create a new deployment with 3 replicas of nginx in the production namespace" +- "Show me all services in the kube-system namespace" +- "List all nodes in the cluster and show their resource usage" +- "Get the YAML definition of the deployment named `web-app` in the staging + namespace" +- "Show me all persistent volume claims that are not bound" +- "Apply this ConfigMap to the development namespace" + +## Recommended practices + +- **Use read-only mode by default**: Only enable write operations + (`--read-write=true`) when necessary and in controlled environments. +- **Implement proper RBAC**: When using service accounts, follow the principle + of least privilege and grant only the minimum permissions required. +- **Enable network isolation**: Restrict network access to your Kubernetes API + endpoints only, especially in production environments. +- **Monitor resource usage**: The server includes built-in rate limiting, but + monitor your cluster's API server load when using with AI agents. +- **Disable resource discovery in large clusters**: Use + `--serve-resources=false` to reduce context size and improve performance in + clusters with many resources. +- **Secure kubeconfig files**: When mounting kubeconfig files, always use + read-only mounts and ensure proper file permissions. +- **Use namespace scoping**: When possible, limit the server's access to + specific namespaces rather than cluster-wide permissions. +- **Enable audit logging**: Configure Kubernetes audit logging to track API + calls made by the MCP server for security monitoring. diff --git a/docs/toolhive/guides-mcp/osv.mdx b/docs/toolhive/guides-mcp/osv.mdx new file mode 100644 index 00000000..c5b7dbdc --- /dev/null +++ b/docs/toolhive/guides-mcp/osv.mdx @@ -0,0 +1,125 @@ +--- +title: OSV MCP server guide +sidebar_label: Open Source Vulnerabilities (OSV) +description: + Using the Open Source Vulnerabilities database (OSV) MCP server with ToolHive. +last_update: + author: danbarr + date: 2025-09-02 +--- + +## Overview + +The [OSV MCP server](https://github.com/StacklokLabs/osv-mcp) provides access to +the [Open Source Vulnerabilities database](https://osv.dev), which aggregates +vulnerability data from multiple sources including GitHub Security Advisories, +PyPA, RustSec, and many others. This server enables AI agents to: + +- Query vulnerabilities for specific package versions or Git commits +- Perform batch vulnerability queries across multiple packages +- Retrieve detailed vulnerability information by OSV ID +- Access comprehensive vulnerability data including severity, affected versions, + and remediation guidance + +The server supports various package ecosystems including npm, PyPI, Go modules, +Maven, NuGet, and more, making it an essential tool for security analysis and +dependency management workflows. + +## Metadata + + + +## Usage + + + + +Select the `osv` MCP server in the ToolHive registry. + +The OSV MCP server does not require any additional configuration or secrets. It +communicates directly with the public OSV API at `api.osv.dev`. + +:::tip[Security tip] + +Enable outbound network filtering on the **Network Isolation** tab to restrict +the server's network access using the default profile contained in the registry. + +::: + + + + +Run with the default configuration: + +```bash +thv run osv +``` + +Enable [network isolation](../guides-cli/network-isolation.mdx) using the +default profile from the registry to restrict the server's network access to +only the OSV API: + +```bash +thv run --isolate-network osv +``` + + + + +Create a Kubernetes manifest to deploy the OSV MCP server: + +```yaml title="osv.yaml" +apiVersion: toolhive.stacklok.dev/v1alpha1 +kind: MCPServer +metadata: + name: osv + namespace: toolhive-system +spec: + image: ghcr.io/stackloklabs/osv-mcp/server:0.0.7 + transport: streamable-http + targetPort: 8080 + port: 8080 + permissionProfile: + type: builtin + name: network +``` + +Apply the manifest to your Kubernetes cluster: + +```bash +kubectl apply -f osv.yaml +``` + + + + +## Sample prompts + +Here are some sample prompts you can use to interact with the OSV MCP server: + +- "Check if the npm package lodash version 4.17.15 has any known + vulnerabilities" +- "Query vulnerabilities for the Python package jinja2 version 2.4.1 and the Go + module github.com/gin-gonic/gin version 1.6.3" +- "Get detailed information about vulnerability GHSA-vqj2-4v8m-8vrq including + affected versions and remediation steps" +- "Check for vulnerabilities in commit hash + 6879efc2c1596d11a6a6ad296f80063b558d5e0f" +- "Scan these packages for vulnerabilities: express@4.17.1, react@16.13.0, and + django@3.0.5" +- "Look up vulnerability CVE-2021-44228 and provide details about affected + packages and severity" + +## Recommended practices + +- **Use batch queries** when checking multiple packages to reduce API calls and + improve performance. The batch query tool can handle multiple packages in a + single request. +- **Enable network isolation** to restrict the server's network access to only + the OSV API endpoints, improving security posture. +- **Specify ecosystems accurately** (npm, PyPI, Go, Maven, etc.) to ensure + accurate vulnerability matching and reduce false positives. +- **Use package URLs (PURLs)** when available for more precise package + identification across different ecosystems and registries. +- **Monitor rate limits** when performing large-scale vulnerability scans to + avoid overwhelming the OSV API service. diff --git a/docs/toolhive/guides-mcp/playwright.mdx b/docs/toolhive/guides-mcp/playwright.mdx new file mode 100644 index 00000000..5a66d826 --- /dev/null +++ b/docs/toolhive/guides-mcp/playwright.mdx @@ -0,0 +1,271 @@ +--- +title: Playwright MCP server guide +sidebar_label: Playwright +description: + Using the Playwright MCP server with ToolHive for browser automation. +last_update: + author: danbarr + date: 2025-08-27 +--- + +import useBaseUrl from '@docusaurus/useBaseUrl'; +import ThemedImage from '@theme/ThemedImage'; + +## Overview + +The official +[Playwright MCP server](https://github.com/microsoft/playwright-mcp) provides +browser automation capabilities using [Playwright](https://playwright.dev). This +server enables AI agents to interact with web pages through structured +accessibility snapshots, bypassing the need for screenshots or visually-tuned +models. + +Key features include: + +- **Fast and lightweight**: Uses Playwright's accessibility tree instead of + pixel-based input +- **LLM-friendly**: Operates purely on structured data without requiring vision + models +- **Deterministic tool application**: Avoids ambiguity common with + screenshot-based approaches +- **Multi-browser support**: Works with Chrome, Firefox, Safari (WebKit), and + Edge +- **Tab management**: Create, switch between, and manage multiple browser tabs +- **Persistent sessions**: Maintains login state and browser data between + interactions + +## Metadata + + + +## Usage + +The Playwright MCP server supports numerous command-line arguments to customize +its behavior. Common options include: + +- **Custom viewport**: Set `--viewport-size` to specify browser dimensions + (e.g., `1920,1080`) +- **Device emulation**: Use `--device` to emulate mobile devices (e.g., + `"iPhone 15"`) +- **Network isolation**: Configure `--allowed-origins` and `--blocked-origins` + to control which websites the browser can access +- **Output directory**: Specify `--output-dir` to save screenshots, PDFs, and + other files to a custom location; mount a host directory for persistence (see + examples below) + +Refer to the +[Playwright MCP server documentation](https://github.com/microsoft/playwright-mcp?tab=readme-ov-file#configuration) +for the full list of configuration options and their descriptions. + +:::note[Limitations] + +The containerized version of Playwright only supports the Chromium browser in +headless mode. + +::: + + + + +Select the `playwright` MCP server in the ToolHive registry. The server runs +with default settings that work for most use cases. + +To customize the server's behavior, add command-line arguments in the **Command +arguments** section. + +To save browser output files like screenshots and traces, mount a host directory +in the **Storage volumes** section and add the `--output-dir ` +command argument as shown in the screenshot below. + + + +:::note[Important] + +Don't remove the `--port 8931` argument, as the server requires it to function +correctly in ToolHive. + +::: + + + + +Run with the default configuration using Chromium in headless mode: + +```bash +thv run playwright +``` + +Emulate a mobile device for responsive testing: + +```bash +thv run playwright -- --port 8931 --device "iPhone 15" +``` + +Restrict access to specific domains: + +```bash +thv run playwright -- --port 8931 --allowed-origins "example.com;trusted-site.com" +``` + +Mount a host directory (e.g., `~/playwright-output`) to save browser output +files like screenshots and traces: + +```bash +mkdir ~/playwright-output +thv run --volume ~/playwright-output:/browser-output playwright -- --port 8931 --output-dir /browser-output --save-trace --save-session +``` + +You can run multiple instances of the server with different configurations by +giving each a unique name: + +```bash +thv run --name playwright-desktop playwright -- --port 8931 --device "Desktop Chrome" --viewport-size 1920,1080 +thv run --name playwright-iphone playwright -- --port 8931 --device "iPhone 15" +``` + +:::note[Important] + +Don't remove the `--port 8931` argument, as the server requires it to function +correctly in ToolHive. + +::: + + + + +Create a basic Kubernetes manifest to deploy the Playwright MCP server: + +```yaml title="playwright.yaml" +apiVersion: toolhive.stacklok.dev/v1alpha1 +kind: MCPServer +metadata: + name: playwright + namespace: toolhive-system +spec: + image: mcr.microsoft.com/playwright/mcp:v0.0.36 + transport: streamable-http + targetPort: 8931 + port: 8080 + args: + - '--port' + - '8931' + permissionProfile: + type: builtin + name: network +``` + +Apply the manifest to your Kubernetes cluster: + +```bash +kubectl apply -f playwright.yaml +``` + +For production deployments with network restrictions: + +```yaml title="playwright-restricted.yaml" +apiVersion: toolhive.stacklok.dev/v1alpha1 +kind: MCPServer +metadata: + name: playwright + namespace: toolhive-system +spec: + image: mcr.microsoft.com/playwright/mcp:v0.0.36 + transport: streamable-http + targetPort: 8931 + port: 8080 + args: + - '--port' + - '8931' + - '--allowed-origins' + - 'example.com;trusted-domain.org' + permissionProfile: + type: builtin + name: network +``` + +Mount a persistent volume to save browser output files like screenshots and +traces: + +```yaml {13-14,22-25,28-31} title="playwright-with-volume.yaml" +apiVersion: toolhive.stacklok.dev/v1alpha1 +kind: MCPServer +metadata: + name: playwright + namespace: toolhive-system +spec: + image: mcr.microsoft.com/playwright/mcp:v0.0.36 + transport: streamable-http + targetPort: 8931 + port: 8080 + args: + - '--port' + - '8931' + - '--output-dir' + - '/browser-output' + - '--save-trace' + - '--save-session' + permissionProfile: + type: builtin + name: network + podTemplateSpec: + spec: + volumes: + - name: playwright-output + persistentVolumeClaim: + claimName: playwright-output-claim + containers: + - name: mcp + volumeMounts: + - mountPath: /browser-output + name: playwright-output + readOnly: false +``` + + + + +## Sample prompts + +Here are some sample prompts you can use to interact with the Playwright MCP +server: + +- "Navigate to https://example.com and take a screenshot of the homepage" +- "Go to the login page, fill in the username field with 'testuser' and password + field with 'password123', then click the login button" +- "Open https://news.ycombinator.com and get the titles of the top 5 stories" +- "Navigate to a form on https://httpbin.org/forms/post, fill it out with sample + data, and submit it" +- "Go to https://github.com/microsoft/playwright and check if there are any + console errors on the page" +- "Take a full-page screenshot of https://example.com and save it as + 'homepage.png'" +- "Navigate to an e-commerce site, search for 'laptop', and capture information + about the first product" +- "Open multiple tabs, navigate to different websites in each, and then switch + between them" + +## Recommended practices + +- **Use accessibility-first interactions**: The server works best when you + describe elements by their accessible names, labels, or text content rather + than visual characteristics. +- **Leverage browser profiles**: For workflows requiring authentication, use + persistent profiles or storage state files to maintain login sessions. +- **Enable network restrictions**: Use `--allowed-origins` and + `--blocked-origins` to limit which domains the browser can access, especially + in production environments. +- **Monitor resource usage**: Browser automation can be resource-intensive; + consider using headless mode and limiting concurrent sessions. +- **Handle dynamic content**: Use the `browser_wait_for` tool when dealing with + content that loads asynchronously. +- **Organize output files**: Specify a custom output directory to keep + screenshots, PDFs, and traces organized. +- **Test responsively**: Use device emulation to test how web applications + behave on different screen sizes and devices. diff --git a/docs/toolhive/guides-ui/index.mdx b/docs/toolhive/guides-ui/index.mdx index 21d00c05..7d84a221 100644 --- a/docs/toolhive/guides-ui/index.mdx +++ b/docs/toolhive/guides-ui/index.mdx @@ -28,7 +28,7 @@ simple way to get started. dark: useBaseUrl('/img/toolhive/toolhive-ui-screenshot-dark.webp'), }} title='ToolHive UI screenshot' -> +/>
We strive to make ToolHive intuitive and easy to use. If we've missed the mark diff --git a/docs/toolhive/guides-ui/install.mdx b/docs/toolhive/guides-ui/install.mdx index b08f9155..1a244634 100644 --- a/docs/toolhive/guides-ui/install.mdx +++ b/docs/toolhive/guides-ui/install.mdx @@ -3,9 +3,6 @@ title: Install ToolHive description: How to install the ToolHive UI application. --- -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - This guide walks you through installing, upgrading, and managing the ToolHive desktop application. diff --git a/docs/toolhive/guides-ui/network-isolation.mdx b/docs/toolhive/guides-ui/network-isolation.mdx index 777d1587..f08c8204 100644 --- a/docs/toolhive/guides-ui/network-isolation.mdx +++ b/docs/toolhive/guides-ui/network-isolation.mdx @@ -76,7 +76,7 @@ The configuration pictured below allows the MCP server to access dark: useBaseUrl('/img/toolhive/network-isolation-dark.webp'), }} title='Network isolation configuration showing allowed hosts and ports' -> +/>
## Related information diff --git a/docs/toolhive/guides-ui/registry.mdx b/docs/toolhive/guides-ui/registry.mdx index efff3040..37779a93 100644 --- a/docs/toolhive/guides-ui/registry.mdx +++ b/docs/toolhive/guides-ui/registry.mdx @@ -29,7 +29,7 @@ the built-in or custom registry. dark: useBaseUrl('/img/toolhive/toolhive-ui-registry-dark.webp'), }} title='ToolHive Registry Page' -> +/> The registry interface displays a list of available servers. You can browse through the list, use search functionality, and click on any server to view @@ -78,7 +78,7 @@ For detailed information on creating a custom registry, see the dark: useBaseUrl('/img/toolhive/toolhive-ui-registry-settings-dark.webp'), }} title='Local Registry configuration with file path input field' -> +/> ## Next steps diff --git a/docs/toolhive/tutorials/custom-registry.mdx b/docs/toolhive/tutorials/custom-registry.mdx index 7c2ca492..53c812bc 100644 --- a/docs/toolhive/tutorials/custom-registry.mdx +++ b/docs/toolhive/tutorials/custom-registry.mdx @@ -3,9 +3,6 @@ title: Create a custom MCP registry description: Learn how to create a custom MCP registry for ToolHive. --- -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - ## Overview ToolHive includes a built-in registry of MCP servers with verified diff --git a/docs/toolhive/tutorials/quickstart-cli.mdx b/docs/toolhive/tutorials/quickstart-cli.mdx index bd6c6638..a136d61d 100644 --- a/docs/toolhive/tutorials/quickstart-cli.mdx +++ b/docs/toolhive/tutorials/quickstart-cli.mdx @@ -5,9 +5,6 @@ description: server. --- -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - In this tutorial, you'll install the ToolHive command-line application and run your first MCP server. By the end, you'll have a working MCP server that can fetch content from websites and be used by AI applications like GitHub Copilot diff --git a/docusaurus.config.ts b/docusaurus.config.ts index 087b540a..9c615ea4 100644 --- a/docusaurus.config.ts +++ b/docusaurus.config.ts @@ -19,6 +19,12 @@ const config: Config = { debug: false, }, ], + [ + './plugins/mcp-metadata-plugin', + { + thvCommand: 'thv', // Can be customized if thv is in a different path + }, + ], ], // Set the production url of your site here diff --git a/eslint.config.mjs b/eslint.config.mjs index 4b3cc385..397edde0 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -35,6 +35,9 @@ export default [ // Add global components from src/theme/MDXComponents.tsx here //Columns: 'readonly', //Column: 'readonly', + Tabs: 'readonly', + TabItem: 'readonly', + MCPMetadata: 'readonly', }, }, }, diff --git a/package-lock.json b/package-lock.json index 98bc6cc9..5cffe5be 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "@mdx-js/react": "^3.1.0", "clsx": "^2.1.1", "docusaurus-json-schema-plugin": "1.15.0", + "glob": "^10.3.10", "prism-react-renderer": "^2.4.1", "react": "^19.1.1", "react-dom": "^19.1.1", @@ -4316,7 +4317,6 @@ "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, "license": "ISC", "dependencies": { "string-width": "^5.1.2", @@ -4788,7 +4788,6 @@ "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, "license": "MIT", "optional": true, "engines": { @@ -11244,7 +11243,6 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", - "dev": true, "license": "ISC", "dependencies": { "cross-spawn": "^7.0.6", @@ -11261,7 +11259,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, "license": "ISC", "engines": { "node": ">=14" @@ -11500,7 +11497,6 @@ "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", @@ -11539,7 +11535,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" @@ -11549,7 +11544,6 @@ "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" @@ -13322,7 +13316,6 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/cliui": "^8.0.2" @@ -16778,7 +16771,6 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, "license": "ISC", "engines": { "node": ">=16 || 14 >=14.17" @@ -17711,7 +17703,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "dev": true, "license": "BlueOak-1.0.0" }, "node_modules/package-manager-detector": { @@ -17894,7 +17885,6 @@ "version": "1.11.1", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, "license": "BlueOak-1.0.0", "dependencies": { "lru-cache": "^10.2.0", @@ -17911,7 +17901,6 @@ "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true, "license": "ISC" }, "node_modules/path-to-regexp": { @@ -22064,7 +22053,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -22079,7 +22067,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -22089,14 +22076,12 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, "license": "MIT" }, "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -22106,7 +22091,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -22261,7 +22245,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -22274,7 +22257,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -24529,7 +24511,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -24547,7 +24528,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -24557,14 +24537,12 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, "license": "MIT" }, "node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -24574,7 +24552,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -24589,7 +24566,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" diff --git a/package.json b/package.json index d4bd1cc0..bce845e4 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "@mdx-js/react": "^3.1.0", "clsx": "^2.1.1", "docusaurus-json-schema-plugin": "1.15.0", + "glob": "^10.3.10", "prism-react-renderer": "^2.4.1", "react": "^19.1.1", "react-dom": "^19.1.1", diff --git a/plugins/mcp-metadata-plugin/README.md b/plugins/mcp-metadata-plugin/README.md new file mode 100644 index 00000000..29edfd53 --- /dev/null +++ b/plugins/mcp-metadata-plugin/README.md @@ -0,0 +1,255 @@ +# MCP Metadata Plugin + +A custom Docusaurus plugin that automatically generates MCP (Model Context +Protocol) server metadata at build-time by executing `thv registry info ` +commands. + +## Overview + +This plugin enables you to display always-current MCP server metadata in your +documentation by simply using a `` component. +The plugin automatically: + +- Scans MDX files for MCP metadata components +- Executes CLI commands to fetch current registry data +- Caches results for optimal performance +- Provides live reloading during development +- Handles errors gracefully with helpful feedback + +## Features + +- βœ… **Build-time Generation**: Metadata fetched during build, zero runtime + impact +- βœ… **Dynamic File Watching**: Automatically detects new components during + development +- βœ… **Intelligent Caching**: 5-minute cache prevents redundant CLI calls +- βœ… **Error Handling**: Graceful fallbacks with helpful troubleshooting +- βœ… **TypeScript Support**: Full type safety throughout +- βœ… **Hot Reloading**: Live updates without server restarts + +## Installation + +The plugin is already configured in this project. For new installations: + +1. Copy the `plugins/mcp-metadata-plugin/` directory to your project +2. Install dependencies: + + ```bash + npm install glob + ``` + +3. Add to `docusaurus.config.ts`: + + ```typescript + plugins: [ + [ + './plugins/mcp-metadata-plugin', + { + cacheTimeout: 300000, // 5 minutes (optional) + thvCommand: 'thv', // Custom command path (optional) + }, + ], + ], + ``` + +4. Register the component in `src/theme/MDXComponents.tsx`: + + ```typescript + import MCPMetadata from '@site/src/components/MCPMetadata'; + + export default { + ...MDXComponents, + MCPMetadata, + }; + ``` + +## Usage + +### Basic Usage + +Replace static YAML metadata blocks with the dynamic component: + +```mdx +## Metadata + + +``` + +### Component Props + +| Prop | Type | Default | Description | +| ----------- | --------- | ------------ | --------------------------------------------- | +| `name` | `string` | **required** | MCP server name as it appears in the registry | +| `showTitle` | `boolean` | `true` | Whether to display the "Metadata" heading | +| `className` | `string` | `undefined` | Additional CSS classes | + +### Advanced Usage + +```mdx + + + + + + + +``` + +## How It Works + +### Build Process + +1. **File Scanning**: Plugin scans all `*.mdx` files in the `docs/` directory +2. **Component Detection**: Extracts server names from + `` components +3. **CLI Execution**: Runs `thv registry info ` for each unique server +4. **Data Storage**: Stores raw YAML output in global plugin data +5. **Component Rendering**: Components access data and render syntax-highlighted + YAML + +### Development Workflow + +1. **File Watching**: Plugin includes file watching capabilities (via + `getPathsToWatch()`) +2. **Server Restart Required**: Currently requires development server restart to + detect new components +3. **Component Detection**: New `` components detected after + restart +4. **Caching**: Results cached for 5 minutes to avoid redundant calls + +## Configuration + +### Plugin Options + +Configure in `docusaurus.config.ts`: + +```typescript +[ + './plugins/mcp-metadata-plugin', + { + // Cache timeout in milliseconds (default: 300000 = 5 minutes) + cacheTimeout: 300000, + + // Custom thv command path (default: 'thv') + thvCommand: '/usr/local/bin/thv', + }, +]; +``` + +### Environment Requirements + +- **thv CLI**: Must be available in the build environment +- **Network Access**: Required to reach the ToolHive registry +- **Node.js**: Compatible with Docusaurus requirements + +## Error Handling + +The plugin handles various error scenarios gracefully: + +### Server Not Found + +```text +Loading metadata for "invalid-server"... +If this persists, the server may not exist in the registry... +``` + +### CLI Command Failed + +```text +# Error fetching data for server-name +# Command failed: thv registry info server-name +# Please check that the server exists in the registry and thv command is available +``` + +### Plugin Not Available + +```text +Loading: MCP metadata plugin is initializing. +If this persists, make sure the plugin is properly configured. +``` + +## Development + +### File Structure + +```text +plugins/mcp-metadata-plugin/ +β”œβ”€β”€ README.md # This file +β”œβ”€β”€ package.json # Plugin dependencies +└── src/ + β”œβ”€β”€ index.ts # Main plugin implementation + β”œβ”€β”€ types.ts # TypeScript type definitions + └── utils.ts # Utility functions +``` + +### Key Components + +- **`index.ts`**: Main plugin with `loadContent()`, `contentLoaded()`, and + `getPathsToWatch()` +- **`utils.ts`**: File scanning, CLI execution, and caching logic +- **`types.ts`**: TypeScript interfaces for plugin options and data structures + +### Debugging + +Enable debug logging by checking the console output during build: + +```text +MCP Metadata Plugin: Loading content... +Found MCP servers: fetch, github +Executing: thv registry info fetch +Using cached data for server: github +``` + +## Performance + +### Build Time + +- **Parallel Execution**: CLI commands run concurrently +- **Smart Caching**: Avoids redundant calls for same servers +- **Incremental Updates**: Only processes changed files during development + +### Runtime + +- **Zero Impact**: All data generated at build-time +- **Static Output**: Pure HTML/CSS/JS with no client-side processing +- **CDN Friendly**: Fully static and cacheable + +## Troubleshooting + +### Common Issues + +1. **"No metadata found" warnings** + - Check server name spelling + - Verify server exists in ToolHive registry + - Ensure `thv` command is available + +2. **Plugin data not available** + - Verify plugin is registered in `docusaurus.config.ts` + - Check component is registered in `MDXComponents.tsx` + - Restart development server + +3. **Stale data during development** + - Wait for cache timeout (5 minutes) + - Restart development server + - Modify `cacheTimeout` configuration + +### Debug Steps + +1. Check console output for plugin messages +2. Verify `thv registry info ` works manually +3. Ensure network connectivity to registry +4. Validate MDX component syntax + +## Contributing + +When modifying the plugin: + +1. Update TypeScript types in `types.ts` +2. Add error handling for new scenarios +3. Update this README with new features +4. Test with both existing and new MCP servers + +## License + +This plugin is part of the Stacklok documentation project and follows the same +license terms. diff --git a/plugins/mcp-metadata-plugin/package.json b/plugins/mcp-metadata-plugin/package.json new file mode 100644 index 00000000..ac906589 --- /dev/null +++ b/plugins/mcp-metadata-plugin/package.json @@ -0,0 +1,15 @@ +{ + "name": "mcp-metadata-plugin", + "version": "1.0.0", + "description": "Docusaurus plugin to generate MCP server metadata at build-time", + "main": "src/index.ts", + "dependencies": { + "@docusaurus/types": "^3.8.1", + "glob": "^10.3.10", + "js-yaml": "^4.1.0" + }, + "devDependencies": { + "@types/js-yaml": "^4.0.9", + "typescript": "~5.8.3" + } +} diff --git a/plugins/mcp-metadata-plugin/src/index.ts b/plugins/mcp-metadata-plugin/src/index.ts new file mode 100644 index 00000000..4ccd94cd --- /dev/null +++ b/plugins/mcp-metadata-plugin/src/index.ts @@ -0,0 +1,78 @@ +// SPDX-FileCopyrightText: Copyright 2025 Stacklok, Inc. +// SPDX-License-Identifier: Apache-2.0 + +import path from 'path'; +import type { Plugin, LoadContext } from '@docusaurus/types'; +import { PluginOptions, PluginContent } from './types'; +import { + scanForMCPComponents, + fetchServerData, + getMDXGlobPatterns, +} from './utils'; + +export default function mcpMetadataPlugin( + context: LoadContext, + options: PluginOptions = {} +): Plugin { + const { thvCommand = 'thv' } = options; + + return { + name: 'mcp-metadata-plugin', + + getPathsToWatch() { + // Watch all MDX files in the docs directory for changes + const docsPath = path.join(context.siteDir, 'docs'); + return getMDXGlobPatterns(docsPath); + }, + + async loadContent(): Promise { + console.log('MCP Metadata Plugin: Loading content...'); + + // Get the docs directory path + const docsPath = path.join(context.siteDir, 'docs'); + + // Scan all MDX files for MCPMetadata components + const mcpServers = await scanForMCPComponents(docsPath); + console.log( + `Getting metadata for MCP servers: ${Array.from(mcpServers).join(', ')}` + ); + + const serverData: Record = {}; + + // Fetch data for each server + for (const serverName of mcpServers) { + try { + // console.log(`Fetching data for server: ${serverName}`); + const data = await fetchServerData(serverName, thvCommand); + // console.log( + // `Successfully fetched data for ${serverName}, length: ${data.length} chars` + // ); + serverData[serverName] = data; + } catch (error) { + console.error( + `Failed to fetch data for MCP server: ${serverName}`, + error + ); + // Store error message as fallback + serverData[serverName] = `# Error fetching data for ${serverName} +# ${error.message} +# Please check that the server exists in the registry and thv command is available`; + } + } + + return { mcpServers: serverData }; + }, + + async contentLoaded({ content, actions }) { + const { setGlobalData } = actions; + + console.log('MCP Metadata Plugin: Setting global data...'); + + // Make MCP server data available globally to components + setGlobalData(content); + }, + }; +} + +// Export the plugin function as default and named export for flexibility +export { mcpMetadataPlugin }; diff --git a/plugins/mcp-metadata-plugin/src/types.ts b/plugins/mcp-metadata-plugin/src/types.ts new file mode 100644 index 00000000..750d0ccc --- /dev/null +++ b/plugins/mcp-metadata-plugin/src/types.ts @@ -0,0 +1,10 @@ +// SPDX-FileCopyrightText: Copyright 2025 Stacklok, Inc. +// SPDX-License-Identifier: Apache-2.0 + +export interface PluginOptions { + thvCommand?: string; // Custom thv command path +} + +export interface PluginContent { + mcpServers: Record; // serverName -> raw text output +} diff --git a/plugins/mcp-metadata-plugin/src/utils.ts b/plugins/mcp-metadata-plugin/src/utils.ts new file mode 100644 index 00000000..e80c75f0 --- /dev/null +++ b/plugins/mcp-metadata-plugin/src/utils.ts @@ -0,0 +1,86 @@ +// SPDX-FileCopyrightText: Copyright 2025 Stacklok, Inc. +// SPDX-License-Identifier: Apache-2.0 + +import { execSync } from 'child_process'; +import { readFileSync } from 'fs'; +import { glob } from 'glob'; + +/** + * Pattern to ignore MDX files starting with underscore + */ +export const MDX_IGNORE_PATTERN = '**/_*.mdx'; + +/** + * Get glob patterns for MDX files, excluding files starting with underscore + */ +export function getMDXGlobPatterns(docsPath: string): string[] { + return [`${docsPath}/**/*.mdx`, `!${docsPath}/${MDX_IGNORE_PATTERN}`]; +} + +/** + * Scans MDX files for MCPMetadata components and extracts server names + */ +export async function scanForMCPComponents( + docsPath: string +): Promise> { + const serverNames = new Set(); + + try { + // Find all MDX files in the docs directory + const mdxFiles = await glob('**/*.mdx', { + cwd: docsPath, + ignore: [MDX_IGNORE_PATTERN], + }); + + // Regex to match components + const mcpComponentRegex = + /]*\/?>/g; + + for (const file of mdxFiles) { + try { + const content = readFileSync(`${docsPath}/${file}`, 'utf-8'); + let match; + + while ((match = mcpComponentRegex.exec(content)) !== null) { + const serverName = match[1]; + if (serverName) { + serverNames.add(serverName); + } + } + } catch (error) { + console.warn(`Warning: Could not read file ${file}:`, error); + } + } + } catch (error) { + console.warn('Warning: Could not scan for MCP components:', error); + } + + return serverNames; +} + +/** + * Executes thv registry info command and returns raw output + */ +export async function fetchServerData( + serverName: string, + thvCommand: string = 'thv' +): Promise { + try { + const command = `${thvCommand} registry info ${serverName}`; + // console.log(`Executing: ${command}`); + + const output = execSync(command, { + encoding: 'utf-8', + timeout: 30000, // 30 second timeout + stdio: ['pipe', 'pipe', 'pipe'], + }); + + return output.trim(); + } catch (error) { + console.error( + `Failed to fetch data for MCP server "${serverName}":`, + error + ); + throw new Error('Failed to fetch MCP server data. See logs for details.'); + } +} diff --git a/scripts/install-thv.sh b/scripts/install-thv.sh new file mode 100755 index 00000000..b9553324 --- /dev/null +++ b/scripts/install-thv.sh @@ -0,0 +1,71 @@ +#!/bin/bash +# SPDX-FileCopyrightText: Copyright 2025 Stacklok, Inc. +# SPDX-License-Identifier: Apache-2.0 + +# This script installs the ToolHive CLI (thv) in a portable way that works +# across different environments (dev containers, CI/CD, Vercel, etc.). + +set -euo pipefail + +# Check if jq is installed +if ! command -v jq >/dev/null 2>&1; then + echo "Error: 'jq' is required but not installed. Please install jq and try again." + exit 1 +fi + +API_ENDPOINT="https://api.github.com/repos/stacklok/toolhive/releases/latest" + +# Fetch release information +RELEASE_JSON=$(curl -sf "$API_ENDPOINT" || { + echo "Failed to fetch release information from GitHub API" + exit 1 +}) +RELEASE_VERSION=$(echo "$RELEASE_JSON" | jq -r '.tag_name // empty' | sed 's/^v//') +RELEASE_TARBALL=$(echo "$RELEASE_JSON" | jq -r \ + --arg version "$RELEASE_VERSION" \ + '.assets[] | select(.name == "toolhive_" + $version + "_linux_amd64.tar.gz") | .browser_download_url // empty') + +if [ -z "$RELEASE_TARBALL" ]; then + echo "Failed to get release tarball URL for release: ${RELEASE_VERSION}" + echo "Please check if the tag exists in the repository" + exit 1 +fi + +# Determine installation location based on write permissions +if [[ -w "/usr/local/bin" ]]; then + # Can write to /usr/local/bin (e.g., CI/CD environments like Vercel) + INSTALL_DIR="/usr/local/bin" + echo "Installing to /usr/local/bin" +else + # Use user-local directory (e.g., dev containers) + INSTALL_DIR="$HOME/.local/bin" + echo "Installing to ~/.local/bin" + + # Create user bin directory if it doesn't exist + mkdir -p "$INSTALL_DIR" + + # Automatically add ~/.local/bin to PATH in shell profile files + for profile in ~/.bashrc ~/.zshrc ~/.profile; do + if [[ -f "$profile" ]]; then + # Check if the PATH export already exists to avoid duplicates + if ! grep -q 'export PATH="$HOME/.local/bin:$PATH"' "$profile" 2>/dev/null; then + echo 'export PATH="$HOME/.local/bin:$PATH"' >> "$profile" + echo "Added ~/.local/bin to PATH in $profile" + fi + fi + done + + # Also set PATH for current session + export PATH="$HOME/.local/bin:$PATH" +fi + +# Download the release tarball and extract the binary +echo "Downloading ToolHive CLI release $RELEASE_VERSION" +curl -s -L "$RELEASE_TARBALL" -o /tmp/toolhive.tar.gz +tar -xzf /tmp/toolhive.tar.gz -C /tmp thv +chmod +x /tmp/thv +cp /tmp/thv "$INSTALL_DIR/thv" +rm -f /tmp/toolhive.tar.gz /tmp/thv + +echo "ToolHive CLI (thv) installed successfully. Version: $RELEASE_VERSION" +echo "The 'thv' command is now available in your PATH." \ No newline at end of file diff --git a/sidebars.ts b/sidebars.ts index c7e971b7..4354277b 100644 --- a/sidebars.ts +++ b/sidebars.ts @@ -163,6 +163,21 @@ const sidebars: SidebarsConfig = { ], }, + { + type: 'category', + label: 'Guides: MCP server usage', + description: + 'How to configure and use MCP servers for different use cases', + link: { + type: 'generated-index', + slug: 'toolhive/guides-mcp', + title: 'MCP server usage guides', + description: + 'These guides provide step-by-step instructions for using various MCP servers with ToolHive. They cover everything from installation to advanced configuration options.', + }, + items: [{ type: 'autogenerated', dirName: 'toolhive/guides-mcp' }], + }, + 'toolhive/faq', ], }; diff --git a/src/components/MCPMetadata/index.tsx b/src/components/MCPMetadata/index.tsx new file mode 100644 index 00000000..03b4b916 --- /dev/null +++ b/src/components/MCPMetadata/index.tsx @@ -0,0 +1,96 @@ +// SPDX-FileCopyrightText: Copyright 2025 Stacklok, Inc. +// SPDX-License-Identifier: Apache-2.0 + +import React from 'react'; +import { usePluginData } from '@docusaurus/useGlobalData'; +import CodeBlock from '@theme/CodeBlock'; +import Details from '@theme/Details'; +import { PluginContent } from '../../../plugins/mcp-metadata-plugin/src/types'; + +interface MCPMetadataProps { + name: string; + className?: string; +} + +export default function MCPMetadata({ + name, + className, +}: MCPMetadataProps): React.ReactElement { + const pluginData = usePluginData('mcp-metadata-plugin') as PluginContent; + + if (!pluginData || !pluginData.mcpServers) { + return ( +
+ Loading MCP metadata... +

+ The MCP metadata plugin is initializing. If this persists, make sure + the plugin is properly configured in docusaurus.config.ts + . +

+
+ ); + } + + const serverData = pluginData.mcpServers[name]; + + if (!serverData) { + return ( +
+ No metadata found for MCP server "{name}" +

+ This usually means the server wasn't found when the plugin + scanned for MCP components. +

+
+ How to fix this +
    +
  • + If you just added this component: Restart the + development server (npm run start) to detect new MCP + components +
  • +
  • + Check the server name: Ensure "{name}" + is spelled correctly +
  • +
  • + Verify server exists: Run{' '} + thv registry info {name} manually to confirm the + server exists in the ToolHive registry +
  • +
  • + Check thv command: Ensure the thv{' '} + command is available in your build environment +
  • +
+
+
+ ); + } + + // Check if the data is an error message + if (serverData.startsWith('# Error fetching data')) { + return ( +
+ Error: Failed to fetch metadata for MCP server " + {name}". +
+ Error details + {serverData} +
+
+ ); + } + + return ( +
+
+ + {serverData} + +
+
+ ); +} + +export type { MCPMetadataProps }; diff --git a/src/theme/MDXComponents.tsx b/src/theme/MDXComponents.tsx index 99cc0943..aef9f3e0 100644 --- a/src/theme/MDXComponents.tsx +++ b/src/theme/MDXComponents.tsx @@ -7,8 +7,15 @@ */ import MDXComponents from '@theme-original/MDXComponents'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import MCPMetadata from '@site/src/components/MCPMetadata'; export default { // Reusing the default mapping ...MDXComponents, + // Add custom components + Tabs, + TabItem, + MCPMetadata, }; diff --git a/static/img/toolhive/mcp-guides/filesystem-mcp-ui-dark.webp b/static/img/toolhive/mcp-guides/filesystem-mcp-ui-dark.webp new file mode 100644 index 00000000..ac7d8398 Binary files /dev/null and b/static/img/toolhive/mcp-guides/filesystem-mcp-ui-dark.webp differ diff --git a/static/img/toolhive/mcp-guides/filesystem-mcp-ui-light.webp b/static/img/toolhive/mcp-guides/filesystem-mcp-ui-light.webp new file mode 100644 index 00000000..48bc543b Binary files /dev/null and b/static/img/toolhive/mcp-guides/filesystem-mcp-ui-light.webp differ diff --git a/static/img/toolhive/mcp-guides/playwright-mcp-ui-dark.webp b/static/img/toolhive/mcp-guides/playwright-mcp-ui-dark.webp new file mode 100644 index 00000000..2d21ac1d Binary files /dev/null and b/static/img/toolhive/mcp-guides/playwright-mcp-ui-dark.webp differ diff --git a/static/img/toolhive/mcp-guides/playwright-mcp-ui-light.webp b/static/img/toolhive/mcp-guides/playwright-mcp-ui-light.webp new file mode 100644 index 00000000..44644c37 Binary files /dev/null and b/static/img/toolhive/mcp-guides/playwright-mcp-ui-light.webp differ diff --git a/vercel.json b/vercel.json index ffcbeb67..f70f2e1e 100644 --- a/vercel.json +++ b/vercel.json @@ -1,4 +1,5 @@ { + "$schema": "https://openapi.vercel.sh/vercel.json", "redirects": [ { "source": "/toolhive/quickstart", @@ -10,5 +11,7 @@ "destination": "/toolhive/tutorials/quickstart-k8s", "permanent": true } - ] + ], + "installCommand": "dnf install -q -y jq && npm install", + "buildCommand": "./scripts/install-thv.sh && npm run build" }