mirror of
https://github.com/aljazceru/goose.git
synced 2025-12-18 06:34:26 +01:00
docs: github tutorial (#993)
Co-authored-by: Adewale Abati <acekyd01@gmail.com>
This commit is contained in:
8
documentation/docs/tutorials/_category_.json
Normal file
8
documentation/docs/tutorials/_category_.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"label": "Tutorials",
|
||||
"position": 4,
|
||||
"link": {
|
||||
"type": "generated-index",
|
||||
"description": "How to integrate and use MCP servers as Goose extensions"
|
||||
}
|
||||
}
|
||||
292
documentation/docs/tutorials/custom-extensions.md
Normal file
292
documentation/docs/tutorials/custom-extensions.md
Normal file
@@ -0,0 +1,292 @@
|
||||
---
|
||||
title: Building Custom Extensions
|
||||
sidebar_position: 1
|
||||
description: Create your own custom MCP Server to use as a Goose extension
|
||||
---
|
||||
|
||||
# Building Custom Extensions with Goose
|
||||
|
||||
|
||||
Goose allows you to extend its functionality by creating your own custom extensions, which are built as MCP servers. These extensions are compatible with Goose because it adheres to the [Model Context Protocol (MCP)][mcp-docs]. MCP is an open protocol that standardizes how applications provide context to LLMs. It enables a consistent way to connect LLMs to various data sources and tools, making it ideal for extending functionality in a structured and interoperable way.
|
||||
|
||||
In this guide, we build an MCP server using the [Python SDK for MCP][mcp-python]. We’ll demonstrate how to create an MCP server that reads Wikipedia articles and converts them to Markdown, integrate it as an extension in Goose. You can follow a similar process to develop your own custom extensions for Goose.
|
||||
|
||||
You can checkout other examples in this [MCP servers repository][mcp-servers]. MCP SDKs are also available in [Typescript][mcp-typescript] and [Kotlin][mcp-kotlin].
|
||||
|
||||
:::info
|
||||
|
||||
Goose currently supports Tools and Resources for [MCP Server features](https://spec.modelcontextprotocol.io/specification/2024-11-05/server/).
|
||||
We will be adding support for MCP Prompts soon.
|
||||
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## Step 1: Initialize Your Project
|
||||
|
||||
The first step is to create a new project using [uv][uv-docs]. We will name our project `mcp-wiki`.
|
||||
|
||||
Run the following commands in your terminal to set up a basic structure for your MCP server:
|
||||
|
||||
```bash
|
||||
uv init mcp-wiki
|
||||
|
||||
cd mcp-wiki
|
||||
rm hello.py
|
||||
|
||||
mkdir -p src/mcp_wiki
|
||||
touch src/mcp_wiki/server.py # Your MCP server code (tool, resources, prompts)
|
||||
touch src/mcp_wiki/__init__.py # Primary CLI entry point
|
||||
touch src/mcp_wiki/__main__.py # To enable running as a Python module
|
||||
```
|
||||
|
||||
Your project directory structure should look like this:
|
||||
|
||||
```plaintext
|
||||
.
|
||||
├── README.md
|
||||
├── pyproject.toml
|
||||
├── src
|
||||
│ └── mcp_wiki
|
||||
│ ├── __init__.py
|
||||
│ ├── __main__.py
|
||||
│ └── server.py
|
||||
└── uv.lock
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 2: Write Your MCP Server Code
|
||||
|
||||
In this step, we’ll implement the core functionality of the MCP server. Here is a breakdown of the key components:
|
||||
|
||||
1. **`server.py`**: This file holds the main MCP server code. In this example, we define a single tool to read Wikipedia articles. You can add your own custom tools, resources, and prompts here.
|
||||
2. **`__init__.py`**: This is the primary CLI entry point for your MCP server.
|
||||
3. **`__main__.py`**: This file allows your MCP server to be executed as a Python module.
|
||||
|
||||
Below is the example implementation for the Wikipedia MCP server:
|
||||
|
||||
### `server.py`
|
||||
|
||||
```python
|
||||
import requests
|
||||
from requests.exceptions import RequestException
|
||||
from bs4 import BeautifulSoup
|
||||
from html2text import html2text
|
||||
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
from mcp.shared.exceptions import McpError
|
||||
from mcp.types import ErrorData, INTERNAL_ERROR, INVALID_PARAMS
|
||||
|
||||
mcp = FastMCP("wiki")
|
||||
|
||||
@mcp.tool()
|
||||
def read_wikipedia_article(url: str) -> str:
|
||||
"""
|
||||
Fetch a Wikipedia article at the provided URL, parse its main content,
|
||||
convert it to Markdown, and return the resulting text.
|
||||
|
||||
Usage:
|
||||
read_wikipedia_article("https://en.wikipedia.org/wiki/Python_(programming_language)")
|
||||
"""
|
||||
try:
|
||||
# Validate input
|
||||
if not url.startswith("http"):
|
||||
raise ValueError("URL must start with http or https.")
|
||||
|
||||
response = requests.get(url, timeout=10)
|
||||
if response.status_code != 200:
|
||||
raise McpError(
|
||||
ErrorData(
|
||||
INTERNAL_ERROR,
|
||||
f"Failed to retrieve the article. HTTP status code: {response.status_code}"
|
||||
)
|
||||
)
|
||||
|
||||
soup = BeautifulSoup(response.text, "html.parser")
|
||||
content_div = soup.find("div", {"id": "mw-content-text"})
|
||||
if not content_div:
|
||||
raise McpError(
|
||||
ErrorData(
|
||||
INVALID_PARAMS,
|
||||
"Could not find the main content on the provided Wikipedia URL."
|
||||
)
|
||||
)
|
||||
|
||||
# Convert to Markdown
|
||||
markdown_text = html2text(str(content_div))
|
||||
return markdown_text
|
||||
|
||||
except ValueError as e:
|
||||
raise McpError(ErrorData(INVALID_PARAMS, str(e))) from e
|
||||
except RequestException as e:
|
||||
raise McpError(ErrorData(INTERNAL_ERROR, f"Request error: {str(e)}")) from e
|
||||
except Exception as e:
|
||||
raise McpError(ErrorData(INTERNAL_ERROR, f"Unexpected error: {str(e)}")) from e
|
||||
```
|
||||
|
||||
### `__init__.py`
|
||||
|
||||
```python
|
||||
import argparse
|
||||
from .server import mcp
|
||||
|
||||
def main():
|
||||
"""MCP Wiki: Read Wikipedia articles and convert them to Markdown."""
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Gives you the ability to read Wikipedia articles and convert them to Markdown."
|
||||
)
|
||||
parser.parse_args()
|
||||
mcp.run()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
```
|
||||
|
||||
### `__main__.py`
|
||||
|
||||
```python
|
||||
from mcp_wiki import main
|
||||
|
||||
main()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 3: Define Project Configuration
|
||||
|
||||
Configure your project using `pyproject.toml`. This configuration defines the CLI script so that the mcp-wiki command is available as a binary. Below is an example configuration:
|
||||
|
||||
```toml
|
||||
[project]
|
||||
name = "mcp-wiki"
|
||||
version = "0.1.0"
|
||||
description = "MCP Server for Wikipedia"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.13"
|
||||
dependencies = [
|
||||
"beautifulsoup4>=4.12.3",
|
||||
"html2text>=2024.2.26",
|
||||
"mcp[cli]>=1.2.0",
|
||||
"requests>=2.32.3",
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
mcp-wiki = "mcp_wiki:main"
|
||||
|
||||
[build-system]
|
||||
requires = ["hatchling"]
|
||||
build-backend = "hatchling.build"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 4: Test Your MCP Server
|
||||
|
||||
### Using MCP Inspector
|
||||
|
||||
1. Setup the project environment:
|
||||
|
||||
```bash
|
||||
uv sync
|
||||
```
|
||||
|
||||
2. Activate your virtual environment:
|
||||
|
||||
```bash
|
||||
source .venv/bin/activate
|
||||
```
|
||||
|
||||
3. Run your server in development mode:
|
||||
|
||||
```bash
|
||||
mcp dev src/mcp_wiki/server.py
|
||||
```
|
||||
|
||||
4. Go to `http://localhost:5173` in your browser to open the MCP Inspector UI.
|
||||
|
||||
5. In the UI, you can click "Connect" to initialize your MCP server. Then click on "Tools" tab > "List Tools" and you should see the `read_wikipedia_article` tool.
|
||||
Then you can try to call the `read_wikipedia_article` tool with URL set to "https://en.wikipedia.org/wiki/Bangladesh" and click "Run Tool".
|
||||
|
||||

|
||||
|
||||
### Testing the CLI
|
||||
|
||||
1. Install your project locally:
|
||||
|
||||
```bash
|
||||
uv pip install .
|
||||
```
|
||||
|
||||
2. Check the executable in your virtual environment:
|
||||
|
||||
```bash
|
||||
ls .venv/bin/ # Verify your CLI is available
|
||||
```
|
||||
|
||||
3. Test the CLI:
|
||||
|
||||
```bash
|
||||
mcp-wiki --help
|
||||
```
|
||||
|
||||
You should see output similar to:
|
||||
|
||||
```plaintext
|
||||
❯ mcp-wiki --help
|
||||
usage: mcp-wiki [-h]
|
||||
|
||||
Gives you the ability to read Wikipedia articles and convert them to Markdown.
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 5: Integrate with Goose
|
||||
|
||||
To add your MCP server as an extension in Goose:
|
||||
|
||||
1. Go to `Settings > Extensions > Add`.
|
||||
2. Set the `Type` to `StandardIO`.
|
||||
3. Provide the ID, name, and description for your extension.
|
||||
4. In the `Command` field, provide the absolute path to your executable. For example:
|
||||
```plaintext
|
||||
uv run /full/path/to/mcp-wiki/.venv/bin/mcp-wiki
|
||||
```
|
||||
|
||||
Alternatively in Step 3, you can also publish your package to pypi. Once published, the server can be run directly using uvx. For example:
|
||||
|
||||
```
|
||||
uvx mcp-wiki
|
||||
```
|
||||
|
||||
For the purposes on this guide, we will show you how to run the local version.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Step 6: Use Your Extension in Goose
|
||||
|
||||
Once integrated, you can start using your extension in Goose. Open the Goose chat interface and call your tool as needed.
|
||||
|
||||
You can verify that Goose has picked up the tools from your custom extension by asking it "what tools do you have?"
|
||||
|
||||

|
||||
|
||||
Then, you can try asking questions that require using the extension you added.
|
||||
|
||||

|
||||
|
||||
🎉 **Congratulations!** You’ve successfully built and integrated a custom MCP server with Goose.
|
||||
|
||||
|
||||
|
||||
[mcp-docs]: https://modelcontextprotocol.io/
|
||||
[mcp-python]: https://github.com/modelcontextprotocol/python-sdk
|
||||
[mcp-typescript]: https://github.com/modelcontextprotocol/typescript-sdk
|
||||
[mcp-kotlin]: https://github.com/modelcontextprotocol/kotlin-sdk
|
||||
[mcp-servers]: https://github.com/modelcontextprotocol/servers
|
||||
[uv-docs]: https://docs.astral.sh/uv/getting-started/
|
||||
207
documentation/docs/tutorials/github-mcp.md
Normal file
207
documentation/docs/tutorials/github-mcp.md
Normal file
@@ -0,0 +1,207 @@
|
||||
---
|
||||
title: GitHub Extension
|
||||
description: Add GitHub MCP Server as a Goose Extension
|
||||
---
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
|
||||
This tutorial covers how to add the [GitHub MCP Server](https://github.com/modelcontextprotocol/servers/tree/main/src/github) as a Goose extension to enable file operations, repository management, search functionality, and more.
|
||||
|
||||
|
||||
:::tip TLDR
|
||||
|
||||
**Command**
|
||||
```sh
|
||||
npx -y @modelcontextprotocol/server-github
|
||||
```
|
||||
|
||||
**Environment Variable**
|
||||
```
|
||||
"GITHUB_PERSONAL_ACCESS_TOKEN": "<YOUR_TOKEN>"
|
||||
```
|
||||
:::
|
||||
|
||||
## Configuration
|
||||
|
||||
<Tabs groupId="interface">
|
||||
<TabItem value="cli" label="Goose CLI" default>
|
||||
1. Run the `configure` command:
|
||||
```sh
|
||||
goose configure
|
||||
```
|
||||
|
||||
2. Choose to add a `Command-line Extension`
|
||||
```sh
|
||||
┌ goose-configure
|
||||
│
|
||||
◇ What would you like to configure?
|
||||
│ Add Extension
|
||||
│
|
||||
◆ What type of extension would you like to add?
|
||||
│ ○ Built-in Extension
|
||||
// highlight-start
|
||||
│ ● Command-line Extension (Run a local command or script)
|
||||
// highlight-end
|
||||
│ ○ Remote Extension
|
||||
└
|
||||
```
|
||||
|
||||
3. Give your extension a name
|
||||
```sh
|
||||
┌ goose-configure
|
||||
│
|
||||
◇ What would you like to configure?
|
||||
│ Add Extension
|
||||
│
|
||||
◇ What type of extension would you like to add?
|
||||
│ Command-line Extension
|
||||
│
|
||||
// highlight-start
|
||||
◆ What would you like to call this extension?
|
||||
│ github
|
||||
// highlight-end
|
||||
└
|
||||
```
|
||||
|
||||
4. Enter the command
|
||||
```sh
|
||||
┌ goose-configure
|
||||
│
|
||||
◇ What would you like to configure?
|
||||
│ Add Extension
|
||||
│
|
||||
◇ What type of extension would you like to add?
|
||||
│ Command-line Extension
|
||||
│
|
||||
◇ What would you like to call this extension?
|
||||
│ github
|
||||
│
|
||||
// highlight-start
|
||||
◆ What command should be run?
|
||||
│ npx -y @modelcontextprotocol/server-github
|
||||
// highlight-end
|
||||
└
|
||||
```
|
||||
|
||||
5. Obtain a [GitHub Personal Access Token](https://github.com/settings/personal-access-tokens) and paste it in.
|
||||
:::info
|
||||
When creating your access token, you can specify the repositories and granular permissions you'd like Goose to have access to.
|
||||
:::
|
||||
|
||||
```sh
|
||||
┌ goose-configure
|
||||
│
|
||||
◇ What would you like to configure?
|
||||
│ Add Extension
|
||||
│
|
||||
◇ What type of extension would you like to add?
|
||||
│ Command-line Extension
|
||||
│
|
||||
◇ What would you like to call this extension?
|
||||
│ github
|
||||
│
|
||||
◇ What command should be run?
|
||||
│ npx -y @modelcontextprotocol/server-github
|
||||
// highlight-start
|
||||
◆ Would you like to add environment variables?
|
||||
│ Yes
|
||||
│
|
||||
◇ Environment variable name:
|
||||
│ GITHUB_PERSONAL_ACCESS_TOKEN
|
||||
│
|
||||
◇ Environment variable value:
|
||||
│ ▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪▪
|
||||
│
|
||||
◇ Add another environment variable?
|
||||
│ No
|
||||
// highlight-end
|
||||
└ Added github extension
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="ui" label="Goose Desktop">
|
||||
1. Click `...` in the upper right corner
|
||||
2. Click `Settings`
|
||||
3. On `Extensions` section, click the `Add` link
|
||||
4. On the `Add Extension Manually` modal, enter the following:
|
||||
* **Type**: `Standard IO`
|
||||
* **ID**: `gh-mcp` (_set this to whatever you want_)
|
||||
* **Name**: `github` (_set this to whatever you want_)
|
||||
* **Description**: `GitHub MCP Server` (_set this to whatever you want_)
|
||||
* **Command**: `npx -y @modelcontextprotocol/server-github`
|
||||
* **Environment Variables**
|
||||
* **Name**: `GITHUB_PERSONAL_ACCESS_TOKEN`
|
||||
* **Value**: (_Obtain a [GitHub Personal Access Token](https://github.com/settings/personal-access-tokens) and paste it in._)
|
||||
:::info
|
||||
When creating your access token, you can specify the repositories and granular permissions you'd like Goose to have access to.
|
||||
:::
|
||||
* Click `Add` button
|
||||
5. Click `Add Extension` button
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Example Usage
|
||||
|
||||
When creating my [GitHub Personal Access Token](https://github.com/settings/personal-access-tokens), I gave it the following access:
|
||||
* Repository: [goose-demo](https://github.com/angiejones/goose-demo)
|
||||
* Read access to metadata
|
||||
* Read and Write access to code, commit status, issues, and pull requests
|
||||
|
||||
**Goose Prompt**
|
||||
```
|
||||
create a new branch called hello-world in my angiejones/goose-demo repository. Update the README.md file to say "this was written by goose" and commit it. Open a pull request with your changes.
|
||||
```
|
||||
|
||||
**Output**
|
||||
|
||||
```
|
||||
I'll help you create a new branch, update the README, and open a pull request. Let me break this down into steps:
|
||||
|
||||
1. First, let's create the new branch called "hello-world" in your repository
|
||||
2. Then update the README.md file
|
||||
3. Finally, create a pull request
|
||||
|
||||
Let me execute these steps:
|
||||
|
||||
1. Creating the new branch:
|
||||
|
||||
─── create_branch | github ──────────────────────────
|
||||
branch: hello-world
|
||||
owner: angiejones
|
||||
repo: goose-demo
|
||||
|
||||
2. Now, updating the README.md file in the new branch:
|
||||
|
||||
─── create_or_update_file | github ──────────────────────────
|
||||
branch: hello-world
|
||||
content: this was written by goose
|
||||
message: Update README.md with Goose message
|
||||
owner: angiejones
|
||||
path: README.md
|
||||
repo: goose-demo
|
||||
|
||||
|
||||
|
||||
3. Finally, creating the pull request:
|
||||
|
||||
─── create_pull_request | github ──────────────────────────
|
||||
base: main
|
||||
body: ...
|
||||
head: hello-world
|
||||
owner: angiejones
|
||||
repo: goose-demo
|
||||
title: Update README.md
|
||||
|
||||
|
||||
|
||||
Great! I've completed all the requested tasks:
|
||||
1. Created a new branch called "hello-world"
|
||||
2. Updated the README.md file with the text "this was written by goose"
|
||||
3. Created a pull request to merge these changes into the main branch
|
||||
|
||||
You can view the pull request at: https://github.com/angiejones/goose-demo/pull/1
|
||||
|
||||
The pull request is now ready for your review. Would you like me to do anything else with it?
|
||||
```
|
||||
Reference in New Issue
Block a user