From f708e4d613d049e5ef48ee1c6f70b57175014121 Mon Sep 17 00:00:00 2001 From: Jim Bennett Date: Sat, 26 Apr 2025 07:49:01 -0700 Subject: [PATCH] Add Pieces for Developers MCP server to the extensions library (#2074) Co-authored-by: Jim Bennett --- documentation/docs/tutorials/pieces-mcp.md | 228 ++++++++++++++++++ documentation/src/components/prompt-card.tsx | 13 +- documentation/src/components/server-card.tsx | 137 +++++++---- .../pieces-stand-up-status-report.json | 16 ++ .../src/pages/prompt-library/detail.tsx | 146 ++++++----- documentation/src/types/prompt.ts | 3 +- documentation/src/types/server.ts | 1 + documentation/src/utils/install-links.ts | 19 ++ .../static/install-link-generator/script.js | 21 +- documentation/static/servers.json | 11 + ui/install-link-generator/script.js | 17 ++ 11 files changed, 495 insertions(+), 117 deletions(-) create mode 100644 documentation/docs/tutorials/pieces-mcp.md create mode 100644 documentation/src/pages/prompt-library/data/prompts/pieces-stand-up-status-report.json diff --git a/documentation/docs/tutorials/pieces-mcp.md b/documentation/docs/tutorials/pieces-mcp.md new file mode 100644 index 00000000..bf663b24 --- /dev/null +++ b/documentation/docs/tutorials/pieces-mcp.md @@ -0,0 +1,228 @@ +--- +title: Pieces for Developers Extension +description: Add Pieces for Developers MCP Server as a Goose Extension +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +This tutorial covers how to add the [Pieces for Developers MCP Server](https://pieces.app?utm_source=goose&utm_medium=collab&utm_campaign=mcp) as a Goose extension to enable interaction with your Pieces Long-Term Memory. + +To learn more about MCP in Pieces, check out the Pieces [MCP documentation](https://docs.pieces.app/products/mcp/get-started?utm_source=goose&utm_medium=collab&utm_campaign=mcp). + +:::tip TLDR + +**URL** + +```bash +http://localhost:39300/model_context_protocol/2024-11-05/sse +``` + +This can change if the port is already in use when you start PiecesOS. Check your URL in Pieces + +::: + +## Configuration + +:::info +Note that you'll need [Pieces](https://pieces.app?utm_source=goose&utm_medium=collab&utm_campaign=mcp) installed to use this extension. +::: + + + + 1. Run the `configure` command: + + ```sh + goose configure + ``` + + 2. Choose to add a `Remote Extension` + + ```sh + ┌ goose-configure + │ + ◇ What would you like to configure? + │ Add Extension + │ + ◆ What type of extension would you like to add? + │ ○ Built-in Extension + │ ○ Command-line Extension (Run a local command or script) + // highlight-start + │ ● Remote Extension + // highlight-end + └ + ``` + + 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? + │ Remote Extension + │ + // highlight-start + ◆ What would you like to call this extension? + │ Pieces + // highlight-end + └ + ``` + + 4. Enter the SSE endpoint URI. + + You can get this from the Pieces settings. The default is `http://localhost:39300/model_context_protocol/2024-11-05/sse`, but the port may be different from 39300 to avoid clashing with other applications running locally. + + ```sh + ┌ goose-configure + │ + ◇ What would you like to configure? + │ Add Extension + │ + ◇ What type of extension would you like to add? + │ Remote Extension + │ + ◇ What would you like to call this extension? + │ Pieces + │ + // highlight-start + ◆ What is the SSE endpoint URI? + │ http://localhost:39300/model_context_protocol/2024-11-05/sse + // highlight-end + └ + ``` + + 5. Enter the number of seconds Goose should wait for actions to complete before timing out. Default is 300s + + ```sh + ┌ goose-configure + │ + ◇ What would you like to configure? + │ Add Extension + │ + ◇ What type of extension would you like to add? + │ Remote Extension + │ + ◇ What would you like to call this extension? + │ Pieces + │ + ◇ What is the SSE endpoint URI? + │ http://localhost:39300/model_context_protocol/2024-11-05/sse + │ + // highlight-start + ◆ Please set the timeout for this tool (in secs): + │ 300 + // highlight-end + └ + ``` + + 6. Add a description if you want, otherwise to leave the description blank select No. + + ```sh + ┌ goose-configure + │ + ◇ What would you like to configure? + │ Add Extension + │ + ◇ What type of extension would you like to add? + │ Remote Extension + │ + ◇ What would you like to call this extension? + │ Pieces + │ + ◇ What is the SSE endpoint URI? + │ http://localhost:39300/model_context_protocol/2024-11-05/sse + │ + ◇ Please set the timeout for this tool (in secs): + │ 300 + // highlight-start + ◆ Would you like to add a description? + │ ○ Yes / ● No + // highlight-end + └ + ``` + + 7. No environment variables are needed, so select No. + + ```sh + ┌ goose-configure + │ + ◇ What would you like to configure? + │ Add Extension + │ + ◇ What type of extension would you like to add? + │ Remote Extension + │ + ◇ What would you like to call this extension? + │ Pieces + │ + ◇ What is the SSE endpoint URI? + │ http://localhost:39300/model_context_protocol/2024-11-05/sse + │ + ◇ Please set the timeout for this tool (in secs): + │ 300 + ◇ Would you like to add a description? + │ No + │ + // highlight-start + ◆ Would you like to add environment variables? + │ ○ Yes / ● No + // highlight-end + └ + ``` + + + + 1. [Launch the installer](goose://extension?url=http%3A%2F%2Flocalhost%3A39300%2Fmodel_context_protocol%2F2024-11-05%2Fsse&id=pieces&name=Pieces%20for%20Developers&description=Provides%20access%20to%20your%20Pieces%20Long-Term%20Memory.%20You%20need%20to%20have%20Pieces%20installed%20to%20use%20this.) + 2. Press `Yes` to confirm the installation + + + +## Example Usage + +Let's use the Pieces for Developers MCP server to generate a status update for a standup meeting based on your activities on the previous day. + +### Goose Prompt + +``` +I need a status update for what I was using yesterday. Create a report with 5 bullet points based off the most important activities, and give each one a brief description. +``` + +### Goose Output + +``` +Here's a report summarizing your key activities from yesterday, based on the most important interactions and applications you were using: + +1. Code Development with Goose: + + Activity: You worked on integrating SSE MCP servers into the Goose CLI, making enhancements to handle extensions via schema URLs. + Description: This task involved modifying code and testing new integrations to support advanced functionalities. It also included interactions with the Goose community on Discord for feedback and troubleshooting. + +2. Documentation Updates: + + Activity: You updated and managed documentation related to the Goose project and MCP integrations. + Description: This involved preparing documentation for new features, including usage guidelines and technical details, aiding in the improvement of user experience and technical instructions. + +3. Community Interaction on Discord: + + Activity: Engaged with the Block Open Source Community to discuss project developments and potential collaborations. + Description: You actively participated in community discussions, exchanging insights on project enhancements, and exploring collaborative opportunities with other developers and contributors. + +4. Managing and Testing Extensions: + + Activity: You focused on testing and managing various extensions through the Goose platform. + Description: This included configuring and validating different extensions, ensuring their compatibility and functionality, and incorporating feedback from testing. + +5. Content and Integration Planning: + + Activity: Planned integration workflows for MCP and documented their use cases. + Description: You worked on strategies for implementing MCP integrations effectively, involving planning sessions to optimize future project deployments and align them with user requirements and project objectives. + +These activities demonstrate a productive day with a focus on development, collaboration, and content management within your technical community. +``` + +## Learn more + +To see some more examples of prompting capabilities unlocked by using the Pieces MCP server, check out the [Pieces MCP prompting guide](https://docs.pieces.app/products/mcp/prompting?utm_source=goose&utm_medium=collab&utm_campaign=mcp). diff --git a/documentation/src/components/prompt-card.tsx b/documentation/src/components/prompt-card.tsx index 37c5099b..458bae88 100644 --- a/documentation/src/components/prompt-card.tsx +++ b/documentation/src/components/prompt-card.tsx @@ -12,6 +12,7 @@ function extensionToMCPServer(extension: Extension): MCPServer { id: extension.command, name: extension.name, command: extension.command, + url: extension.url, description: extension.name, is_builtin: extension.is_builtin, link: extension.link || '', @@ -119,9 +120,15 @@ export function PromptCard({ prompt }: { prompt: Prompt }) {

Command

- - goose session --with-extension "{extension.command}" - + {extension.url ? ( + + goose session --with-remote-extension "{extension.url}" + + ) : ( + + goose session --with-extension "{extension.command}" + + )} )} diff --git a/documentation/src/components/server-card.tsx b/documentation/src/components/server-card.tsx index db6754d9..b87022d4 100644 --- a/documentation/src/components/server-card.tsx +++ b/documentation/src/components/server-card.tsx @@ -50,65 +50,104 @@ export function ServerCard({ server }: { server: MCPServer }) {
- {server.is_builtin ? ( + {server.is_builtin && (
- - - Can be enabled in the goose settings page - + + + Can be enabled in the goose settings page +
- ) : ( + )} + + {(!server.is_builtin && server.command !== undefined && server.url === undefined) && ( <> - + + {isCommandVisible && ( + - -

Command

- - - - {isCommandVisible && ( - - - {`goose session --with-extension "${server.command}"`} - - - )} - + + {`goose session --with-extension "${server.command}"`} + +
+ )} +
+ + )} + + {(!server.is_builtin && server.command === undefined && server.url !== undefined) && ( + <> + + + {isCommandVisible && ( + + + {`goose session --with-remote-extension "${server.url}"`} + + + )} + )}
- e.stopPropagation()} - > - - {server.githubStars} on Github - + {server.githubStars !== undefined && ( + e.stopPropagation()} + > + + {server.githubStars} on Github + + )}
{server.is_builtin ? (
(null); + const [expandedExtension, setExpandedExtension] = useState( + null + ); const hasExpandedExtension = expandedExtension !== null; return ( -
+
{extensions.map((extension) => ( - void; }) { return (
-
{ if (!extension.is_builtin) { onToggle(!isExpanded); } }} - title={extension.is_builtin ? "Built-in extension - can be enabled in settings" : "Click to see installation options"} + title={ + extension.is_builtin + ? "Built-in extension - can be enabled in settings" + : "Click to see installation options" + } > {extension.name} {extension.is_builtin ? (
- - Built-in - + Built-in
) : ( @@ -118,23 +126,29 @@ function ExtensionDetails({
-
- - goose session --with-extension "{extension.command}" - + {extension.url ? ( + + goose session --with-remote-extension "{extension.url}" + + ) : ( + + goose session --with-extension "{extension.command}" + + )}
{extension.installation_notes && ( <>
-
Installation Notes
+
+ Installation Notes +
{extension.installation_notes} @@ -144,27 +158,33 @@ function ExtensionDetails({ )} - {extension.environmentVariables && extension.environmentVariables.length > 0 && ( - <> -
-
-
Environment Variables
- {extension.environmentVariables.map((env) => ( -
- {env.name} -
- {env.description} - {env.required && ( - - Required - - )} -
+ {extension.environmentVariables && + extension.environmentVariables.length > 0 && ( + <> +
+
+
+ Environment Variables
- ))} -
- - )} + {extension.environmentVariables.map((env) => ( +
+ {env.name} +
+ {env.description} + {env.required && ( + + Required + + )} +
+
+ ))} +
+ + )}
)} @@ -181,9 +201,7 @@ function PromptDetail({ prompt }: { prompt: Prompt }) {
- @@ -204,21 +222,25 @@ function PromptDetail({ prompt }: { prompt: Prompt }) { {prompt.description}

- + Results may vary depending on the model and context.
-

Example Prompt

- - {prompt.example_prompt} - +

+ Example Prompt +

+ + {prompt.example_prompt} +
{prompt.example_result && (
-

Example Result

+

+ Example Result +

{prompt.example_result} @@ -226,7 +248,9 @@ function PromptDetail({ prompt }: { prompt: Prompt }) { )}
-

Recommended Extensions

+

+ Recommended Extensions +

@@ -250,7 +274,7 @@ export default function DetailPage(): JSX.Element { try { setLoading(true); setError(null); - + // Get the ID from the query parameter const params = new URLSearchParams(location.search); const id = params.get("id"); @@ -284,9 +308,7 @@ export default function DetailPage(): JSX.Element {
- @@ -340,4 +362,4 @@ export default function DetailPage(): JSX.Element { } return ; -} \ No newline at end of file +} diff --git a/documentation/src/types/prompt.ts b/documentation/src/types/prompt.ts index 7830ce7e..181a06a2 100644 --- a/documentation/src/types/prompt.ts +++ b/documentation/src/types/prompt.ts @@ -6,7 +6,8 @@ export type EnvironmentVariable = { export type Extension = { name: string; - command: string; + command?: string; + url?: string; is_builtin: boolean; link?: string; installation_notes?: string; diff --git a/documentation/src/types/server.ts b/documentation/src/types/server.ts index 3c220ce7..fc09279c 100644 --- a/documentation/src/types/server.ts +++ b/documentation/src/types/server.ts @@ -3,6 +3,7 @@ export interface MCPServer { name: string; description: string; command: string; + url: string; link: string; installation_notes: string; is_builtin: boolean; diff --git a/documentation/src/utils/install-links.ts b/documentation/src/utils/install-links.ts index 98a47a2e..786a2f83 100644 --- a/documentation/src/utils/install-links.ts +++ b/documentation/src/utils/install-links.ts @@ -10,9 +10,28 @@ export function getGooseInstallLink(server: MCPServer): string { ].join('&'); return `goose://extension?${queryParams}`; } + + // Handle the case where the command is a URL + if (server.url) { + const queryParams = [ + `url=${encodeURIComponent(server.url)}`, + `id=${encodeURIComponent(server.id)}`, + `name=${encodeURIComponent(server.name)}`, + `description=${encodeURIComponent(server.description)}`, + ...server.environmentVariables + .filter((env) => env.required) + .map( + (env) => `env=${encodeURIComponent(`${env.name}=${env.description}`)}` + ), + ].join("&"); + + return `goose://extension?${queryParams}`; + } + const parts = server.command.split(" "); const baseCmd = parts[0]; // jbang, npx or uvx const args = parts.slice(1); // remaining arguments + const queryParams = [ `cmd=${encodeURIComponent(baseCmd)}`, ...args.map((arg) => `arg=${encodeURIComponent(arg)}`), diff --git a/documentation/static/install-link-generator/script.js b/documentation/static/install-link-generator/script.js index ee750049..27c8f4aa 100644 --- a/documentation/static/install-link-generator/script.js +++ b/documentation/static/install-link-generator/script.js @@ -35,7 +35,7 @@ document.addEventListener('DOMContentLoaded', () => { handleGeneratedLink(link, true); return; } - + // Handle custom extension const cmd = urlParams.get('cmd'); if (!cmd) { @@ -93,7 +93,7 @@ document.addEventListener('DOMContentLoaded', () => { tab.addEventListener('click', () => { tabs.forEach(t => t.classList.remove('active')); tab.classList.add('active'); - + document.querySelectorAll('.tab-content').forEach(content => { content.classList.remove('active'); }); @@ -197,6 +197,23 @@ document.addEventListener('DOMContentLoaded', () => { return `goose://extension?${queryParams}`; } + // Handle the case where the command is a URL + if (server.url) { + const queryParams = [ + `url=${encodeURIComponent(server.url)}`, + `id=${encodeURIComponent(server.id)}`, + `name=${encodeURIComponent(server.name)}`, + `description=${encodeURIComponent(server.description)}`, + ...server.environmentVariables + .filter((env) => env.required) + .map( + (env) => `env=${encodeURIComponent(`${env.name}=${env.description}`)}` + ), + ].join("&"); + + return `goose://extension?${queryParams}`; + } + const parts = server.command.split(" "); const baseCmd = parts[0]; const args = parts.slice(1); diff --git a/documentation/static/servers.json b/documentation/static/servers.json index 34862674..48ea7bd9 100644 --- a/documentation/static/servers.json +++ b/documentation/static/servers.json @@ -142,5 +142,16 @@ "endorsed": false, "githubStars": 27, "environmentVariables": [] + }, + { + "id": "pieces", + "name": "Pieces", + "description": "Provides access to your Pieces Long-Term Memory. You need to have Pieces installed to use this.", + "url": "http://localhost:39300/model_context_protocol/2024-11-05/sse", + "link": "https://pieces.app?utm_source=goose&utm_medium=collab&utm_campaign=mcp", + "installation_notes": "You need to install Pieces first, and have this running.", + "is_builtin": false, + "endorsed": false, + "environmentVariables": [] } ] diff --git a/ui/install-link-generator/script.js b/ui/install-link-generator/script.js index 6f4147b0..bc68c651 100644 --- a/ui/install-link-generator/script.js +++ b/ui/install-link-generator/script.js @@ -109,6 +109,23 @@ document.addEventListener('DOMContentLoaded', () => { return `goose://extension?${queryParams}`; } + // Handle the case where the command is a URL + if (server.url) { + const queryParams = [ + `url=${encodeURIComponent(server.url)}`, + `id=${encodeURIComponent(server.id)}`, + `name=${encodeURIComponent(server.name)}`, + `description=${encodeURIComponent(server.description)}`, + ...server.environmentVariables + .filter((env) => env.required) + .map( + (env) => `env=${encodeURIComponent(`${env.name}=${env.description}`)}` + ), + ].join("&"); + + return `goose://extension?${queryParams}`; + } + const parts = server.command.split(" "); const baseCmd = parts[0]; const args = parts.slice(1);