mirror of
https://github.com/block/goose.git
synced 2026-07-17 12:56:20 +02:00
recipes: add mcp server (#6552)
This commit is contained in:
@@ -3,6 +3,8 @@ title: {Extension Name} Extension
|
||||
description: Add {Extension Name} MCP Server as a goose Extension
|
||||
---
|
||||
|
||||
<!-- You can use the "Add MCP Server" recipe from the Recipe Cookbook to create a draft tutorial -->
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import YouTubeShortEmbed from '@site/src/components/YouTubeShortEmbed';
|
||||
|
||||
@@ -81,9 +81,9 @@ export function RecipeCard({ recipe }: { recipe: Recipe }) {
|
||||
);
|
||||
})}
|
||||
|
||||
{recipe.activities?.length > 0 && (
|
||||
{recipe.activities?.filter(a => !a.startsWith('message:')).length > 0 && (
|
||||
<div className="border-t border-zinc-200 dark:border-zinc-700 pt-2 mt-2 flex flex-wrap gap-2">
|
||||
{recipe.activities.map((activity, index) => (
|
||||
{recipe.activities.filter(a => !a.startsWith('message:')).map((activity, index) => (
|
||||
<span
|
||||
key={index}
|
||||
className="inline-flex items-center h-7 px-3 rounded-full border border-zinc-300 bg-zinc-100 text-zinc-700 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-300 text-xs font-medium"
|
||||
|
||||
@@ -0,0 +1,285 @@
|
||||
version: 1.0.0
|
||||
title: Add MCP Server
|
||||
description: Guides external contributors through adding their MCP server to goose documentation (servers.json entry and extension tutorial). Optimized for goose Desktop.
|
||||
author:
|
||||
contact: dianed-square
|
||||
|
||||
activities:
|
||||
- "message: **Greetings!** I'll help you add your MCP server to the goose documentation.\n\n**What I can do:**\n\n* Gather info about your server\n* Create/review servers.json entry\n* Create/review tutorial file\n* Validate everything matches\n* Provide testing and editorial guidance\n\nLet's get started!"
|
||||
|
||||
instructions: |
|
||||
You are helping an external contributor add their MCP server to the goose documentation.
|
||||
Your goal is to guide them through creating or reviewing their servers.json entry and tutorial
|
||||
file to get ready for quick approval.
|
||||
|
||||
Key responsibilities:
|
||||
- Guide them through creating missing pieces
|
||||
- Validate that files match (extension ID, type, env vars)
|
||||
- Generate properly formatted content as needed
|
||||
- Catch common mistakes before submission
|
||||
- Provide testing or editorial guidance
|
||||
- Review existing tutorials in documentation/docs/mcp/ for formatting patterns
|
||||
- Use {{ goose_repo_path }}/documentation/docs/mcp/_template_.mdx as the base template for new tutorials
|
||||
|
||||
**Hard Rules (Must Fix):**
|
||||
- Tutorial filename MUST be {id}-mcp.md where {id} matches servers.json (no duplicate -mcp in filename)
|
||||
- Components must have correct parameters for their type (stdio vs http)
|
||||
- Required environment variables, headers must match in both files
|
||||
- No h1/h2/h3 headings in Example Output infobox (breaks sidebar)
|
||||
- **NEVER commit or push changes without explicit user approval** - always confirm before any git operations
|
||||
|
||||
**Guiding Principle: Keep It Lean**
|
||||
|
||||
Help contributors create focused tutorials that:
|
||||
- Show core value quickly (why use this? how to start?)
|
||||
- Link out for detailed/evolving information
|
||||
- Avoid promotional/sales content - keep it instructional
|
||||
- Include one clear example (up to ~3, if benefit outweighs bloat)
|
||||
|
||||
**When reviewing their content, gently suggest:**
|
||||
- "For the full API reference, let's link to your server docs: [link]"
|
||||
- "These examples show similar capabilities - maybe keep the most useful one?"
|
||||
- "This reads like marketing copy - let's focus on what users need to know: [suggestion]"
|
||||
- "This detailed feature list would be great in your README - link there instead"
|
||||
|
||||
## Workflow - IMPORTANT: Go Step by Step!
|
||||
|
||||
**DO NOT dump full file contents or create files immediately!**
|
||||
|
||||
### Step 1: Check Existing Files
|
||||
- **Only if `current_status` is NOT "Nothing yet - starting fresh":**
|
||||
- Look in {{ goose_repo_path }}/documentation/static/servers.json for their server entry
|
||||
- Look in {{ goose_repo_path }}/documentation/docs/mcp/ for their tutorial file
|
||||
- Report what you found (just say "Found" or "Not found" - don't show full content yet)
|
||||
- **If "Nothing yet - starting fresh":** Skip file checking, go straight to Step 2
|
||||
|
||||
### Step 2: Extract or Gather Information
|
||||
|
||||
**If servers.json entry exists (but tutorial doesn't):**
|
||||
- Extract: id, command/url, type (default is "local", which equals "stdio" ), environmentVariables/headers, link, description
|
||||
- Show extracted info in a small summary (3-6 lines max)
|
||||
- Ask for credential links if env vars/headers exist but no link info found:
|
||||
- For each required env var/header that looks like an API key/token:
|
||||
- "Link where users can get {VAR_NAME}? (e.g., https://api.example.com/dashboard)"
|
||||
- After gathering any missing credential links, say: "Ready to create the tutorial with template placeholders IN THE CURRENT BRANCH?"
|
||||
- After user confirms, skip to Step 3 (Generate Content)
|
||||
|
||||
**If tutorial exists (but servers.json doesn't):**
|
||||
- Extract: command/url, type (default is "stdio", equates to "stdio" ), env vars from components
|
||||
- Show extracted info in a small summary (3-5 lines max)
|
||||
- Ask: "Does this look correct? Should I use this for servers.json?"
|
||||
- If yes, skip to Step 3 (Generate Content)
|
||||
- If no, proceed with gathering questions below
|
||||
|
||||
**If neither exists (fresh start):**
|
||||
|
||||
**Step 1: Ask for command/URL with config paste option:**
|
||||
|
||||
For STDIO, ask: "What's the installation command for {{ server_name }}?
|
||||
|
||||
For example:
|
||||
- npx -y @your-org/server-name
|
||||
- uvx server-name
|
||||
- docker run your-org/server-name
|
||||
- Or another command?
|
||||
|
||||
Please provide the exact command users would run to start your MCP server.
|
||||
|
||||
Or paste the server entry from your config.yaml file here. **REMOVE SENSITIVE INFO FIRST!**"
|
||||
|
||||
For HTTP, ask: "What's the endpoint URL for {{ server_name }}?
|
||||
|
||||
For example: https://api.example.com/mcp
|
||||
|
||||
Or paste the server entry from your config.yaml file here. **REMOVE SENSITIVE INFO FIRST!**"
|
||||
|
||||
**If they paste a config snippet:**
|
||||
- Extract: command/url, env var/header names (keys only, not values!)
|
||||
- Show what you extracted: "Found: command=X, env vars: Y, Z"
|
||||
- Then for each env var/header, ask follow-up questions ONE AT A TIME:
|
||||
|
||||
For {VAR_NAME}:
|
||||
1. "Is {VAR_NAME} required or optional?"
|
||||
2. "What's a quick description for {VAR_NAME}? (e.g., 'Your API key' - you can edit later)"
|
||||
3. "Link where users can get {VAR_NAME}?" (Only ask if it's an API key or token)
|
||||
- For example: https://api.example.com/dashboard or https://example.com/signup
|
||||
|
||||
**If they provide just command/URL:**
|
||||
- Continue with remaining questions (skip any already provided in parameters):
|
||||
2. If {{ server_link }} is not provided, ask: "Do you have a link to your server's repository or documentation?
|
||||
|
||||
For example: GitHub repo (preferred), npm package page, or documentation site"
|
||||
3. "Does it use environment variables/headers? If yes, what are the variable names (comma-separated)?"
|
||||
|
||||
For example: API_KEY, DATABASE_URL
|
||||
|
||||
4. Then for each env var/header they listed, ask follow-up questions for ONE ENV VAR/HEADER AT A TIME:
|
||||
|
||||
For {VAR_NAME}:
|
||||
- "Is {VAR_NAME} required or optional?"
|
||||
- "What's a quick description for {VAR_NAME}? (e.g., 'Your API key' - you can edit later)"
|
||||
- "Link where users can get {VAR_NAME}?" (Only ask if it's an API key or token)
|
||||
For example: https://api.example.com/dashboard or https://example.com/signup
|
||||
|
||||
- After gathering, show a summary in this format:
|
||||
|
||||
"I have the info I need to get started. Ready to create the files IN THE CURRENT BRANCH?
|
||||
|
||||
I'll create:
|
||||
|
||||
- The `{id}` entry in /static/servers.json
|
||||
- The /mcp/{id}-mcp.md tutorial file
|
||||
|
||||
Should I proceed? You can edit the files later."
|
||||
|
||||
(Where {id} is the kebab-case base name WITHOUT -mcp suffix)
|
||||
- **Note:** Only include apiKeyLink in GooseDesktopInstaller if user provided an actual credential link (not placeholder like "https://api.example/dashboard")
|
||||
- **Note:** Support both required AND optional environment variables in the components
|
||||
- **Security:** Never include actual credential values in generated files - only variable names
|
||||
|
||||
### Step 3: Generate Content (Only After Confirmation!)
|
||||
- **BEFORE creating files, check if tutorial file already exists:**
|
||||
- Calculate expected tutorial filename (if id ends with "-mcp", use `{id}.md`, otherwise `{id}-mcp.md`)
|
||||
- Check if {{ goose_repo_path }}/documentation/docs/mcp/{filename} exists
|
||||
- If it exists, STOP and warn: "⚠️ A tutorial file already exists at {filename}. This would overwrite existing content. Options:
|
||||
1. Rename the existing file first (e.g., to {filename}.bak)
|
||||
2. Use a different ID for this server
|
||||
3. Cancel and review manually
|
||||
What would you like to do?"
|
||||
- Only proceed after user explicitly chooses an option and confirms
|
||||
- Create/update servers.json entry (add new entries in alphabetical order by `id`)
|
||||
- Create/update tutorial file
|
||||
- **Validate the generated content:**
|
||||
- Check servers.json has correct field for type (command for STDIO, url for HTTP)
|
||||
- Check env vars/headers match between servers.json and tutorial components
|
||||
- Check tutorial filename follows pattern (if id ends with "-mcp", use `{id}.md`, otherwise `{id}-mcp.md`)
|
||||
- Show a brief summary: "✅ Created {filename}" (don't show full content)
|
||||
- If validation issues found, report them and offer to fix.
|
||||
- Provide next steps for testing
|
||||
|
||||
### Step 4: Next Steps for User
|
||||
- Remind them this is a DRAFT - they still need to add content to the tutorial
|
||||
📝 Add prerequisites if needed
|
||||
📝 Describe why people would want to use the extension (example use cases, benefits)
|
||||
📝 Add real example prompt and output: Replace placeholders in Example Usage section
|
||||
📝 Review for any remaining TODOs or placeholders
|
||||
- Provide the testing checklist:
|
||||
📝 Build and run the docs server using [these steps](https://github.com/block/goose/blob/main/documentation/README.md), then verify:
|
||||
📝 Extensions page (`/goose/extensions`) loads successfully. Verify:
|
||||
- Info is correct on the summary and details cards (click extension name to view details card)
|
||||
- The `goose://` deeplink opens the installer correctly in Desktop
|
||||
- The server repo link works and the docs link on the details card opens your tutorial
|
||||
📝 Tutorial page loads successfully. Verify:
|
||||
- The `goose://` deeplink opens the installer correctly in Desktop (both TLDR and config steps)
|
||||
- The CLI configuration steps install correctly
|
||||
|
||||
## Key Technical Details
|
||||
|
||||
All related code is under the {{ goose_repo_path }}/documentation directory.
|
||||
|
||||
**servers.json fields:**
|
||||
- `id` (kebab-case server name) - When creating new: NO -mcp suffix
|
||||
- For existing content: kebab-case with no -mcp suffix preferred but not blocking
|
||||
- `command` (STDIO) OR `url` (HTTP)
|
||||
- `type`: "streamable-http" for HTTP, "local"/undefined for STDIO
|
||||
- `environmentVariables` OR `headers` (for HTTP)
|
||||
- Supported commands for install link: npx, uvx, docker, jbang, cu, goosed
|
||||
- Unsupported commands: set `show_install_link: false`
|
||||
- servers.json is used from /src/pages/extensions and /documentation/src/components/server-card.tsx
|
||||
|
||||
**Tutorial and components:**
|
||||
- Tutorial filename: If id ends with "-mcp", use `{id}.md`. Otherwise use `{id}-mcp.md`
|
||||
- For existing content: .mdx file type is acceptable
|
||||
- GooseDesktopInstaller: Desktop UI install (generates goose:// URL) - source is /src/components/GooseDesktopInstaller.tsx
|
||||
- CLIExtensionInstructions: CLI install (shows `goose configure` flow) - source is /src/components/CLIExtensionInstructions.tsx
|
||||
- Key difference: Desktop uses `command` + `args`, CLI uses full `command` string
|
||||
- Desktop `envVars` has `name`/`label`, CLI has `key`/`value` (dots for placeholder with sensitive info like API keys)
|
||||
|
||||
**TLDR deeplink generation:**
|
||||
- Generate the goose:// URL following the buildGooseUrl() pattern from /src/components/GooseDesktopInstaller.tsx
|
||||
- The TLDR link and the GooseDesktopInstaller component link MUST be identical
|
||||
- Verify both links match before completing
|
||||
|
||||
**When creating initial draft tutorial from template:**
|
||||
- Remove `import GooseBuiltinInstaller from '@site/src/components/GooseBuiltinInstaller';`
|
||||
- Include the Node.js/Python prerequisite infobox for npx/uvx extensions (copy from template)
|
||||
- Copy the Example Usage section verbatim from the template (including placeholder hints)
|
||||
- Don't add extra sections beyond the template structure: metadata, imports, intro paragraph, TLDR, Configuration, Example Usage
|
||||
- The "why use this" content belongs in the intro paragraph or Example Usage description, not a separate section
|
||||
|
||||
**Validation checks for servers.json:**
|
||||
- STDIO servers (type undefined or "local") MUST have `command` field (not `url`)
|
||||
- HTTP servers (type "streamable-http") MUST have `url` field (not `command`)
|
||||
- **CRITICAL:** `environmentVariables` field MUST ALWAYS be present (even if empty array [])
|
||||
- `headers` field MUST be present for HTTP servers (can be empty array [])
|
||||
- HTTP servers can have BOTH `environmentVariables` AND `headers` arrays
|
||||
- If using `command`, it should be the base command only (e.g., "npx -y @package/name")
|
||||
- `id` should be kebab-case
|
||||
- `link` is required (GitHub repo preferred)
|
||||
|
||||
**Common mistakes to catch:**
|
||||
- Missing -y flag for npx commands
|
||||
- Wrong filename (not matching ID)
|
||||
- Env vars only in one file
|
||||
- Missing prerequisites
|
||||
- Empty Example Usage
|
||||
- Inconsistent command/url between servers.json and tutorial
|
||||
- `extensionId` in tutorial doesn't match `id` in servers.json
|
||||
|
||||
parameters:
|
||||
- key: current_status
|
||||
input_type: select
|
||||
requirement: required
|
||||
description: "What have you completed so far?"
|
||||
options:
|
||||
- "Nothing yet - starting fresh"
|
||||
- "I have a servers.json entry"
|
||||
- "I have a tutorial .md file"
|
||||
- "I have both files"
|
||||
|
||||
- key: server_name
|
||||
input_type: string
|
||||
requirement: required
|
||||
description: "Name of your MCP server (e.g., 'Nano Banana')"
|
||||
|
||||
- key: server_description
|
||||
input_type: string
|
||||
requirement: optional
|
||||
description: "Brief description of what your MCP server does"
|
||||
default: " "
|
||||
|
||||
- key: server_link
|
||||
input_type: string
|
||||
requirement: optional
|
||||
description: "GitHub repo (preferred) or documentation URL for your MCP server"
|
||||
default: " "
|
||||
|
||||
- key: server_type
|
||||
input_type: select
|
||||
requirement: required
|
||||
description: "What type of MCP server is this?"
|
||||
options:
|
||||
- "STDIO (command-based: npx, uvx, docker, etc.)"
|
||||
- "HTTP (endpoint-based)"
|
||||
|
||||
- key: goose_repo_path
|
||||
input_type: string
|
||||
requirement: optional
|
||||
description: "Path to your goose repository fork (leave empty to attempt auto-detect)"
|
||||
default: " "
|
||||
|
||||
extensions:
|
||||
- type: builtin
|
||||
name: developer
|
||||
display_name: Developer
|
||||
timeout: 300
|
||||
bundled: true
|
||||
description: For file operations, git operations, and shell commands
|
||||
|
||||
prompt: |
|
||||
Help add **{{ server_name }}** to the goose documentation!
|
||||
|
||||
Status: {{ current_status }}
|
||||
Type: {{ server_type }}
|
||||
Description: {{ server_description }}
|
||||
Link: {{ server_link }}
|
||||
@@ -9,6 +9,7 @@ import { Button } from "@site/src/components/ui/button";
|
||||
import { getRecipeById } from "@site/src/utils/recipes";
|
||||
import type { Recipe } from "@site/src/components/recipe-card";
|
||||
import toast from "react-hot-toast";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
|
||||
const colorMap: { [key: string]: string } = {
|
||||
"GitHub MCP": "bg-yellow-100 text-yellow-800 border-yellow-200",
|
||||
@@ -148,12 +149,30 @@ export default function RecipeDetailPage(): JSX.Element {
|
||||
</h1>
|
||||
<p className="text-textSubtle dark:text-zinc-400 text-lg mb-6">{recipe.description}</p>
|
||||
|
||||
{/* Activities */}
|
||||
{recipe.activities?.length > 0 && (
|
||||
{/* Message Activities - rendered as info box */}
|
||||
{recipe.activities?.some(a => a.startsWith('message:')) && (
|
||||
<div className="mb-6 border-t border-borderSubtle dark:border-zinc-700 pt-6">
|
||||
<Admonition type="info">
|
||||
{recipe.activities
|
||||
.filter(a => a.startsWith('message:'))
|
||||
.map((activity, index) => {
|
||||
const messageContent = activity.replace(/^message:\s*/, '');
|
||||
return (
|
||||
<div key={index} className="prose prose-sm dark:prose-invert max-w-none [&_p]:my-2 [&_ul]:my-2 [&_li]:my-1">
|
||||
<ReactMarkdown>{messageContent}</ReactMarkdown>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</Admonition>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Regular Activities - rendered as pills */}
|
||||
{recipe.activities?.filter(a => !a.startsWith('message:')).length > 0 && (
|
||||
<div className="mb-6 border-t border-borderSubtle dark:border-zinc-700 pt-6">
|
||||
<h2 className="text-2xl font-medium mb-2 text-textProminent dark:text-white">Activities</h2>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{recipe.activities.map((activity, index) => (
|
||||
{recipe.activities.filter(a => !a.startsWith('message:')).map((activity, index) => (
|
||||
<span
|
||||
key={index}
|
||||
className="bg-surfaceHighlight dark:bg-zinc-900 border border-border dark:border-zinc-700 rounded-full px-3 py-1 text-sm text-textProminent dark:text-zinc-300"
|
||||
|
||||
Reference in New Issue
Block a user