Add Pieces for Developers MCP server to the extensions library (#2074)

Co-authored-by: Jim Bennett <jim@pieces.app>
This commit is contained in:
Jim Bennett
2025-04-26 07:49:01 -07:00
committed by GitHub
parent b4f5d606ca
commit f708e4d613
11 changed files with 495 additions and 117 deletions

View File

@@ -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.
:::
<Tabs groupId="interface">
<TabItem value="cli" label="Goose CLI" default>
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
```
</TabItem>
<TabItem value="ui" label="Goose Desktop">
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
</TabItem>
</Tabs>
## 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).

View File

@@ -12,6 +12,7 @@ function extensionToMCPServer(extension: Extension): MCPServer {
id: extension.command, id: extension.command,
name: extension.name, name: extension.name,
command: extension.command, command: extension.command,
url: extension.url,
description: extension.name, description: extension.name,
is_builtin: extension.is_builtin, is_builtin: extension.is_builtin,
link: extension.link || '', link: extension.link || '',
@@ -119,9 +120,15 @@ export function PromptCard({ prompt }: { prompt: Prompt }) {
<Terminal className="h-4 w-4" /> <Terminal className="h-4 w-4" />
<h4 className="mx-2">Command</h4> <h4 className="mx-2">Command</h4>
</button> </button>
<CodeBlock language="bash"> {extension.url ? (
goose session --with-extension "{extension.command}" <CodeBlock language="bash">
</CodeBlock> goose session --with-remote-extension "{extension.url}"
</CodeBlock>
) : (
<CodeBlock language="bash">
goose session --with-extension "{extension.command}"
</CodeBlock>
)}
</div> </div>
</motion.div> </motion.div>
)} )}

View File

@@ -50,65 +50,104 @@ export function ServerCard({ server }: { server: MCPServer }) {
</div> </div>
<div className="py-4"> <div className="py-4">
{server.is_builtin ? ( {server.is_builtin && (
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Info <Info
style={{ width: "12px", height: "12px" }} style={{ width: "12px", height: "12px" }}
className="text-textSubtle shrink-0" className="text-textSubtle shrink-0"
/> />
<span <span
style={{ fontSize: "12px" }} style={{ fontSize: "12px" }}
className="text-textSubtle leading-normal" className="text-textSubtle leading-normal"
> >
Can be enabled in the goose settings page Can be enabled in the goose settings page
</span> </span>
</div> </div>
) : ( )}
{(!server.is_builtin && server.command !== undefined && server.url === undefined) && (
<> <>
<button <button
onClick={() => setIsCommandVisible(!isCommandVisible)} onClick={() => setIsCommandVisible(!isCommandVisible)}
className="command-toggle" className="command-toggle"
>
<Terminal className="h-4 w-4" />
<h4 className="mx-2">Command</h4>
<ChevronRight
className={`ml-auto transition-transform ${
isCommandVisible ? "rotate-90" : ""
}`}
/>
</button>
<AnimatePresence>
{isCommandVisible && (
<motion.div
className="command-content"
initial={{ opacity: 0, translateY: -20 }}
animate={{ opacity: 1, translateY: 0 }}
exit={{
opacity: 0,
translateY: -20,
transition: { duration: 0.1 },
}}
> >
<Terminal className="h-4 w-4" /> <code>
<h4 className="mx-2">Command</h4> {`goose session --with-extension "${server.command}"`}
<ChevronRight </code>
className={`ml-auto transition-transform ${ </motion.div>
isCommandVisible ? "rotate-90" : "" )}
}`} </AnimatePresence>
/> </>
</button> )}
<AnimatePresence>
{isCommandVisible && ( {(!server.is_builtin && server.command === undefined && server.url !== undefined) && (
<motion.div <>
className="command-content" <button
initial={{ opacity: 0, translateY: -20 }} onClick={() => setIsCommandVisible(!isCommandVisible)}
animate={{ opacity: 1, translateY: 0 }} className="command-toggle"
exit={{ >
opacity: 0, <Terminal className="h-4 w-4" />
translateY: -20, <h4 className="mx-2">Command</h4>
transition: { duration: 0.1 }, <ChevronRight
}} className={`ml-auto transition-transform ${
> isCommandVisible ? "rotate-90" : ""
<code> }`}
{`goose session --with-extension "${server.command}"`} />
</code> </button>
</motion.div> <AnimatePresence>
)} {isCommandVisible && (
</AnimatePresence> <motion.div
className="command-content"
initial={{ opacity: 0, translateY: -20 }}
animate={{ opacity: 1, translateY: 0 }}
exit={{
opacity: 0,
translateY: -20,
transition: { duration: 0.1 },
}}
>
<code>
{`goose session --with-remote-extension "${server.url}"`}
</code>
</motion.div>
)}
</AnimatePresence>
</> </>
)} )}
</div> </div>
</div> </div>
<div className="card-footer"> <div className="card-footer">
<Link {server.githubStars !== undefined && (
to={server.link} <Link
className="card-stats" to={server.link}
onClick={(e) => e.stopPropagation()} className="card-stats"
> onClick={(e) => e.stopPropagation()}
<Star className="h-4 w-4" /> >
<span>{server.githubStars} on Github</span> <Star className="h-4 w-4" />
</Link> <span>{server.githubStars} on Github</span>
</Link>
)}
<div className="card-action"> <div className="card-action">
{server.is_builtin ? ( {server.is_builtin ? (
<div <div

View File

@@ -0,0 +1,16 @@
{
"id": "pieces-stand-up-status-report",
"title": "Create a status report for a stand-up meeting",
"description": "Create a status report for a stand-up meeting, including 5 bullet points for what was accomplished yesterday. This is using the Pieces Long-Term Memory.",
"category": "productivity",
"job": "project-management",
"example_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.",
"example_result": "Here's a report summarizing your key activities from yesterday, based on the most important interactions and applications you were using:\n\n1. Code Development with Goose:\n\tActivity: You worked on integrating SSE MCP servers into the Goose CLI, making enhancements to handle extensions via schema URLs.\n\tDescription: 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.\n\n2. Documentation Updates:\n\tActivity: You updated and managed documentation related to the Goose project and MCP integrations.\n\tDescription: This involved preparing documentation for new features, including usage guidelines and technical details, aiding in the improvement of user experience and technical instructions.\n\n3. Community Interaction on Discord:\n\tActivity: Engaged with the Block Open Source Community to discuss project developments and potential collaborations.\n\tDescription: You actively participated in community discussions, exchanging insights on project enhancements, and exploring collaborative opportunities with other developers and contributors.\n\n4. Managing and Testing Extensions:\n\tActivity: You focused on testing and managing various extensions through the Goose platform.\n\tDescription: This included configuring and validating different extensions, ensuring their compatibility and functionality, and incorporating feedback from testing.\n\n5. Content and Integration Planning:\n\tActivity: Planned integration workflows for MCP and documented their use cases.\n\tDescription: 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.\n\nThese activities demonstrate a productive day with a focus on development, collaboration, and content management within your technical community.",
"extensions": [
{
"name": "Pieces",
"url": "http://localhost:39300/model_context_protocol/2024-11-05/sse",
"is_builtin": false
}
]
}

View File

@@ -1,7 +1,7 @@
import Layout from "@theme/Layout"; import Layout from "@theme/Layout";
import { ArrowLeft, Terminal, Download, Code } from "lucide-react"; import { ArrowLeft, Terminal, Download, Code } from "lucide-react";
import Admonition from '@theme/Admonition'; import Admonition from "@theme/Admonition";
import CodeBlock from '@theme/CodeBlock'; import CodeBlock from "@theme/CodeBlock";
import { Button } from "@site/src/components/ui/button"; import { Button } from "@site/src/components/ui/button";
import { Badge } from "@site/src/components/ui/badge"; import { Badge } from "@site/src/components/ui/badge";
import { useLocation } from "@docusaurus/router"; import { useLocation } from "@docusaurus/router";
@@ -10,7 +10,7 @@ import Link from "@docusaurus/Link";
import { motion, AnimatePresence } from "framer-motion"; import { motion, AnimatePresence } from "framer-motion";
import type { MCPServer } from "@site/src/types/server"; import type { MCPServer } from "@site/src/types/server";
import { getPromptById } from "@site/src/utils/prompts"; import { getPromptById } from "@site/src/utils/prompts";
import ReactMarkdown from 'react-markdown'; import ReactMarkdown from "react-markdown";
import type { Prompt, Extension } from "@site/src/types/prompt"; import type { Prompt, Extension } from "@site/src/types/prompt";
import { getGooseInstallLink } from "@site/src/utils/install-links"; import { getGooseInstallLink } from "@site/src/utils/install-links";
@@ -20,26 +20,32 @@ function extensionToMCPServer(extension: Extension): MCPServer {
id: extension.command, id: extension.command,
name: extension.name, name: extension.name,
command: extension.command, command: extension.command,
url: extension.url,
description: extension.name, description: extension.name,
is_builtin: extension.is_builtin, is_builtin: extension.is_builtin,
link: extension.link || '', link: extension.link || "",
installation_notes: extension.installation_notes || '', installation_notes: extension.installation_notes || "",
endorsed: false, endorsed: false,
environmentVariables: extension.environmentVariables || [], environmentVariables: extension.environmentVariables || [],
githubStars: 0 githubStars: 0,
}; };
} }
function ExtensionList({ extensions }: { extensions: Extension[] }) { function ExtensionList({ extensions }: { extensions: Extension[] }) {
const [expandedExtension, setExpandedExtension] = useState<string | null>(null); const [expandedExtension, setExpandedExtension] = useState<string | null>(
null
);
const hasExpandedExtension = expandedExtension !== null; const hasExpandedExtension = expandedExtension !== null;
return ( return (
<div className={`flex gap-3 ${hasExpandedExtension ? 'flex-col' : 'flex-wrap'}`}> <div
className={`flex gap-3 ${
hasExpandedExtension ? "flex-col" : "flex-wrap"
}`}
>
{extensions.map((extension) => ( {extensions.map((extension) => (
<ExtensionDetails <ExtensionDetails
key={extension.name} key={extension.name}
extension={extension} extension={extension}
isExpanded={expandedExtension === extension.name} isExpanded={expandedExtension === extension.name}
@@ -52,41 +58,43 @@ function ExtensionList({ extensions }: { extensions: Extension[] }) {
); );
} }
function ExtensionDetails({ function ExtensionDetails({
extension, extension,
isExpanded, isExpanded,
onToggle onToggle,
}: { }: {
extension: Extension; extension: Extension;
isExpanded: boolean; isExpanded: boolean;
onToggle: (expanded: boolean) => void; onToggle: (expanded: boolean) => void;
}) { }) {
return ( return (
<div className="flex flex-col"> <div className="flex flex-col">
<div <div
className={` className={`
inline-flex items-center h-9 px-4 rounded-full inline-flex items-center h-9 px-4 rounded-full
bg-background-subtle border border-borderSubtle bg-background-subtle border border-borderSubtle
transition-all duration-150 ease-in-out transition-all duration-150 ease-in-out
hover:bg-background-standard hover:border-borderStandard hover:bg-background-standard hover:border-borderStandard
group ${extension.is_builtin ? 'cursor-help' : 'cursor-pointer'} group ${extension.is_builtin ? "cursor-help" : "cursor-pointer"}
${isExpanded ? 'bg-background-standard border-borderStandard' : ''} ${isExpanded ? "bg-background-standard border-borderStandard" : ""}
`} `}
onClick={() => { onClick={() => {
if (!extension.is_builtin) { if (!extension.is_builtin) {
onToggle(!isExpanded); 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"
}
> >
<span className="text-sm text-textStandard group-hover:text-textProminent"> <span className="text-sm text-textStandard group-hover:text-textProminent">
{extension.name} {extension.name}
</span> </span>
{extension.is_builtin ? ( {extension.is_builtin ? (
<div className="inline-flex items-center ml-2"> <div className="inline-flex items-center ml-2">
<span className="text-sm text-textSubtle"> <span className="text-sm text-textSubtle">Built-in</span>
Built-in
</span>
</div> </div>
) : ( ) : (
<span className="ml-2 text-textSubtle"> <span className="ml-2 text-textSubtle">
@@ -118,23 +126,29 @@ function ExtensionDetails({
</a> </a>
<div className="border-t border-borderSubtle" /> <div className="border-t border-borderSubtle" />
<button <button className="command-toggle w-full flex items-center">
className="command-toggle w-full flex items-center"
>
<Terminal className="h-4 w-4" /> <Terminal className="h-4 w-4" />
<h4 className="mx-2">Command</h4> <h4 className="mx-2">Command</h4>
</button> </button>
<div> <div>
<CodeBlock language="bash"> {extension.url ? (
goose session --with-extension "{extension.command}" <CodeBlock language="bash">
</CodeBlock> goose session --with-remote-extension "{extension.url}"
</CodeBlock>
) : (
<CodeBlock language="bash">
goose session --with-extension "{extension.command}"
</CodeBlock>
)}
</div> </div>
{extension.installation_notes && ( {extension.installation_notes && (
<> <>
<div className="border-t border-borderSubtle" /> <div className="border-t border-borderSubtle" />
<div> <div>
<div className="text-sm font-medium mb-2">Installation Notes</div> <div className="text-sm font-medium mb-2">
Installation Notes
</div>
<div className="text-sm text-textSubtle"> <div className="text-sm text-textSubtle">
<ReactMarkdown> <ReactMarkdown>
{extension.installation_notes} {extension.installation_notes}
@@ -144,27 +158,33 @@ function ExtensionDetails({
</> </>
)} )}
{extension.environmentVariables && extension.environmentVariables.length > 0 && ( {extension.environmentVariables &&
<> extension.environmentVariables.length > 0 && (
<div className="border-t border-borderSubtle" /> <>
<div> <div className="border-t border-borderSubtle" />
<div className="text-sm font-medium mb-2">Environment Variables</div> <div>
{extension.environmentVariables.map((env) => ( <div className="text-sm font-medium mb-2">
<div key={env.name} className="mb-2 last:mb-0"> Environment Variables
<code className="text-sm">{env.name}</code>
<div className="text-sm text-textSubtle mt-1">
{env.description}
{env.required && (
<Badge variant="secondary" className="ml-2 text-xs">
Required
</Badge>
)}
</div>
</div> </div>
))} {extension.environmentVariables.map((env) => (
</div> <div key={env.name} className="mb-2 last:mb-0">
</> <code className="text-sm">{env.name}</code>
)} <div className="text-sm text-textSubtle mt-1">
{env.description}
{env.required && (
<Badge
variant="secondary"
className="ml-2 text-xs"
>
Required
</Badge>
)}
</div>
</div>
))}
</div>
</>
)}
</div> </div>
</motion.div> </motion.div>
)} )}
@@ -181,9 +201,7 @@ function PromptDetail({ prompt }: { prompt: Prompt }) {
<div className="flex gap-8"> <div className="flex gap-8">
<div> <div>
<Link to="/prompt-library" className="no-underline"> <Link to="/prompt-library" className="no-underline">
<Button <Button className="flex items-center gap-2 hover:cursor-pointer">
className="flex items-center gap-2 hover:cursor-pointer"
>
<ArrowLeft className="h-4 w-4" /> <ArrowLeft className="h-4 w-4" />
Back Back
</Button> </Button>
@@ -204,21 +222,25 @@ function PromptDetail({ prompt }: { prompt: Prompt }) {
{prompt.description} {prompt.description}
</p> </p>
</div> </div>
<Admonition type="info"> <Admonition type="info">
Results may vary depending on the model and context. Results may vary depending on the model and context.
</Admonition> </Admonition>
<div> <div>
<h2 className="text-2xl font-medium mb-4">Example Prompt</h2> <h2 className="text-2xl font-medium mb-4">
<CodeBlock language="markdown"> Example Prompt
{prompt.example_prompt} </h2>
</CodeBlock> <CodeBlock language="markdown">
{prompt.example_prompt}
</CodeBlock>
</div> </div>
{prompt.example_result && ( {prompt.example_result && (
<div> <div>
<h2 className="text-2xl font-medium mb-4">Example Result</h2> <h2 className="text-2xl font-medium mb-4">
Example Result
</h2>
<CodeBlock language="markdown"> <CodeBlock language="markdown">
{prompt.example_result} {prompt.example_result}
</CodeBlock> </CodeBlock>
@@ -226,7 +248,9 @@ function PromptDetail({ prompt }: { prompt: Prompt }) {
)} )}
<div> <div>
<h2 className="text-2xl font-medium mb-4">Recommended Extensions</h2> <h2 className="text-2xl font-medium mb-4">
Recommended Extensions
</h2>
<ExtensionList extensions={prompt.extensions} /> <ExtensionList extensions={prompt.extensions} />
</div> </div>
</div> </div>
@@ -250,7 +274,7 @@ export default function DetailPage(): JSX.Element {
try { try {
setLoading(true); setLoading(true);
setError(null); setError(null);
// Get the ID from the query parameter // Get the ID from the query parameter
const params = new URLSearchParams(location.search); const params = new URLSearchParams(location.search);
const id = params.get("id"); const id = params.get("id");
@@ -284,9 +308,7 @@ export default function DetailPage(): JSX.Element {
<div className="flex gap-8"> <div className="flex gap-8">
<div> <div>
<Link to="/prompt-library" className="no-underline"> <Link to="/prompt-library" className="no-underline">
<Button <Button className="flex items-center gap-2 hover:text-textProminent hover:cursor-pointer">
className="flex items-center gap-2 hover:text-textProminent hover:cursor-pointer"
>
<ArrowLeft className="h-4 w-4" /> <ArrowLeft className="h-4 w-4" />
Back Back
</Button> </Button>
@@ -340,4 +362,4 @@ export default function DetailPage(): JSX.Element {
} }
return <PromptDetail prompt={prompt} />; return <PromptDetail prompt={prompt} />;
} }

View File

@@ -6,7 +6,8 @@ export type EnvironmentVariable = {
export type Extension = { export type Extension = {
name: string; name: string;
command: string; command?: string;
url?: string;
is_builtin: boolean; is_builtin: boolean;
link?: string; link?: string;
installation_notes?: string; installation_notes?: string;

View File

@@ -3,6 +3,7 @@ export interface MCPServer {
name: string; name: string;
description: string; description: string;
command: string; command: string;
url: string;
link: string; link: string;
installation_notes: string; installation_notes: string;
is_builtin: boolean; is_builtin: boolean;

View File

@@ -10,9 +10,28 @@ export function getGooseInstallLink(server: MCPServer): string {
].join('&'); ].join('&');
return `goose://extension?${queryParams}`; 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 parts = server.command.split(" ");
const baseCmd = parts[0]; // jbang, npx or uvx const baseCmd = parts[0]; // jbang, npx or uvx
const args = parts.slice(1); // remaining arguments const args = parts.slice(1); // remaining arguments
const queryParams = [ const queryParams = [
`cmd=${encodeURIComponent(baseCmd)}`, `cmd=${encodeURIComponent(baseCmd)}`,
...args.map((arg) => `arg=${encodeURIComponent(arg)}`), ...args.map((arg) => `arg=${encodeURIComponent(arg)}`),

View File

@@ -35,7 +35,7 @@ document.addEventListener('DOMContentLoaded', () => {
handleGeneratedLink(link, true); handleGeneratedLink(link, true);
return; return;
} }
// Handle custom extension // Handle custom extension
const cmd = urlParams.get('cmd'); const cmd = urlParams.get('cmd');
if (!cmd) { if (!cmd) {
@@ -93,7 +93,7 @@ document.addEventListener('DOMContentLoaded', () => {
tab.addEventListener('click', () => { tab.addEventListener('click', () => {
tabs.forEach(t => t.classList.remove('active')); tabs.forEach(t => t.classList.remove('active'));
tab.classList.add('active'); tab.classList.add('active');
document.querySelectorAll('.tab-content').forEach(content => { document.querySelectorAll('.tab-content').forEach(content => {
content.classList.remove('active'); content.classList.remove('active');
}); });
@@ -197,6 +197,23 @@ document.addEventListener('DOMContentLoaded', () => {
return `goose://extension?${queryParams}`; 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 parts = server.command.split(" ");
const baseCmd = parts[0]; const baseCmd = parts[0];
const args = parts.slice(1); const args = parts.slice(1);

View File

@@ -142,5 +142,16 @@
"endorsed": false, "endorsed": false,
"githubStars": 27, "githubStars": 27,
"environmentVariables": [] "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": []
} }
] ]

View File

@@ -109,6 +109,23 @@ document.addEventListener('DOMContentLoaded', () => {
return `goose://extension?${queryParams}`; 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 parts = server.command.split(" ");
const baseCmd = parts[0]; const baseCmd = parts[0];
const args = parts.slice(1); const args = parts.slice(1);