Skip to content

Commit 001e4a5

Browse files
sixhobbitskoladev32rideamritza-publishing-assistant[bot]bethh0rn
authored
docs: Add Gram Custom Functions to TaskMaster example PMM-670 (#76)
Co-authored-by: koladev <[email protected]> Co-authored-by: tatenda <[email protected]> Co-authored-by: ritza-publishing-assistant[bot] <205765304+ritza-publishing-assistant[bot]@users.noreply.github.com> Co-authored-by: bethh0rn <[email protected]>
1 parent 0852313 commit 001e4a5

9 files changed

+129
-32
lines changed
70.6 KB
Loading
72.3 KB
Loading
79.2 KB
Loading
55.4 KB
Loading
73.8 KB
Loading
55.5 KB
Loading
113 KB
Loading
119 KB
Loading

docs/gram/examples/creating-taskmaster-mcp-server.mdx

Lines changed: 129 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ You can try out Taskmaster [here](https://taskmaster-speakeasyapi.vercel.app/).
1818
Taskmaster is a full-stack CRUD application for tasks and projects. It includes:
1919

2020
- A web UI for managing projects and tasks
21-
- A built-in HTTP API
21+
- A built-in HTTP API
2222
- OAuth 2.0 authentication
2323
- A Neon PostgreSQL database for storing tasks and projects
2424

@@ -35,11 +35,11 @@ To follow this tutorial, you need:
3535

3636
## Setting up a Gram project
3737

38-
In the [Gram dashboard](https://app.getgram.ai), click **New Project** to start the guided setup flow for creating a toolset and MCP server.
38+
On the [Gram dashboard](https://app.getgram.ai), click your username in the bottom-left corner and then open the projects dropdown. Select **+ New Project**, enter a project name, and click **Submit**.
3939

40-
![Screenshot of the Gram dashboard showing the New Project link](/assets/docs/gram/img/guides/build-mcp/create-taskmaster-mcp-server/gram-new-project.png)
40+
![Screenshot of the Gram dashboard showing the New Project link](./assets/gram-new-project.png)
4141

42-
Enter a project name and click **Submit**.
42+
Click **Get Started** and select **Start from API** to start the guided setup flow for creating a toolset and MCP server.
4343

4444
Gram will then guide you through the following steps:
4545

@@ -51,7 +51,7 @@ Upload the [Taskmaster OpenAPI document](https://github.com/speakeasy-api/taskma
5151

5252
### 2. Create a toolset
5353

54-
Give your toolset a name (for example, `Taskmaster`) and click **Continue**.
54+
Give your toolset a name (for example, `Taskmaster`) and click **Continue**.
5555

5656
![Screenshot of the create toolset dialog](/assets/docs/gram/img/guides/build-mcp/create-taskmaster-mcp-server/create-toolset.png)
5757

@@ -67,18 +67,18 @@ Gram then creates the toolset from the OpenAPI document.
6767

6868
Click **Toolsets** in the sidebar to view the **Taskmaster** toolset.
6969

70-
![Screenshot of the Gram dashboard showing the Taskmaster toolset](/assets/docs/gram/img/guides/build-mcp/create-taskmaster-mcp-server/toolset-created.png)
70+
![Screenshot of the Gram dashboard showing the Taskmaster toolset](./assets/toolset-created.png)
7171

7272
As you can see, the toolset needs environment variables before you can use it.
7373

7474
## Getting a Taskmaster API key
7575

7676
Before configuring environment variables, create an API key:
7777

78-
- Navigate to your Taskmaster app (for example, `https://taskmaster-ritza.vercel.app`).
78+
- Navigate to your Taskmaster app (for example, `https://taskmaster-speakeasyapi.vercel.app`).
7979
- Sign in and go to **Settings → Developer**.
80-
- Under **API Keys**, click **New Key**.
81-
- Give it a label and click **Create**.
80+
- Under **API Keys**, click **+ New**.
81+
- Give it a label and click **Generate Key**.
8282
- Copy the API key. You will not be able to see it again.
8383

8484
<video width="600" muted={true} controls>
@@ -90,37 +90,36 @@ Before configuring environment variables, create an API key:
9090

9191
[Environments](/docs/gram/concepts/environments) store API keys and configuration separately from your toolset logic.
9292

93-
In the **Environments** tab, click the **Default** environment. Click the three-dot menu in the top-right corner of the environment card, and in the dropdown, click **Fill for Toolset**. Select the **Taskmaster** toolset and click **Fill Variables** to automatically populate the required variables.
93+
In the **Environments** tab, click the **Default** environment. Click **Fill for Toolset**. Select the **Taskmaster** toolset and click **Fill Variables** to automatically populate the required variables.
9494

95-
![Screenshot showing the fill for toolset dialog to automatically populate required variables](/assets/docs/gram/img/guides/build-mcp/create-taskmaster-mcp-server/fill-env-vars-toolset.png)
95+
![Screenshot showing the fill for toolset dialog to automatically populate required variables](./assets/fill-env-vars-toolset.png)
9696

9797
Configure the following environment variables:
9898

99-
- Set the `TASKMASTER_SERVER_URL` environment variable to your API base URL. For example: `https://taskmaster-ritza.vercel.app/api`
100-
- Set the `TASKMASTER_ACCESS_TOKEN` environment variable to your API key. For example: `tm_abc123_def456`
101-
Alternatively, you can set an `X-API-Key` header to the same value. The API accepts both.
99+
- Set the `TASKMASTER_SERVER_URL` environment variable to your API base URL. For example: `https://taskmaster-speakeasyapi.vercel.app/api`
100+
- Set the `TASKMASTER_API_KEY` environment variable to your API key. For example: `tm_abc123_def456`
102101

103-
Click **Update** and then **Save**.
102+
Click **Save**.
104103

105-
![Set server URL](/assets/docs/gram/img/guides/build-mcp/create-taskmaster-mcp-server/set-env-vars.png)
104+
![Set server URL](./assets/set-env-vars.png)
106105

107106
## Publishing an MCP server
108107

109108
Let's make the toolset available as an MCP server.
110109

111-
Go to the **MCP** tab, find the **Taskmaster** toolset, and click on it to open the MCP details page.
110+
Go to the **MCP** tab, find the **Taskmaster** toolset, and click on it to open the **MCP Details** page.
112111

113-
Scroll down to the **Visibility** section and tick the **Public** checkbox.
112+
To enable the server, click **Enable**, and then in the modal that opens, click **Enable Server**.
114113

115-
![Screenshot of the MCP details page](/assets/docs/gram/img/guides/build-mcp/create-taskmaster-mcp-server/mcp-details.png)
114+
Scroll down to the **Visibility** section and select the **Public** checkbox.
116115

117-
Next, you'll need to copy the MCP server configuration.
116+
![Screenshot of the MCP details page](./assets/mcp-details.png)
118117

119-
Scroll down to the **MCP Config** section and copy the **Public Server** configuration.
118+
Next, you'll need to copy the MCP server configuration.
120119

121-
![Screenshot showing the MCP server config dialog for the Taskmaster toolset](/assets/docs/gram/img/guides/build-mcp/create-taskmaster-mcp-server/copy-mcp-config.png)
120+
Scroll down to the **MCP Installation** section and click the **View** button to open the configuration details page.
122121

123-
The configuration looks something like this:
122+
If you set the visibility to **Public**, the configuration will look something like this:
124123

125124
```json
126125
{
@@ -131,20 +130,22 @@ The configuration looks something like this:
131130
"mcp-remote",
132131
"https://app.getgram.ai/mcp/ritza-rzx-taskmaster",
133132
"--header",
134-
"MCP-TASKMASTER-APIKEY-API-KEY:${VALUE}",
133+
"MCP-TASKMASTER-API-KEY:${MCP_TASKMASTER_API_KEY}",
135134
"--header",
136-
"MCP-TASKMASTER-APIKEY-SERVER-URL:${VALUE}"
137-
]
135+
"MCP-TASKMASTER-OAUTH-TOKEN-ACCESS-TOKEN:${MCP_TASKMASTER_OAUTH_TOKEN_ACCESS_TOKEN}"
136+
],
137+
"env": {
138+
"MCP_TASKMASTER_OAUTH_TOKEN_ACCESS_TOKEN": "<your-value-here>",
139+
"MCP_TASKMASTER_API_KEY": "<your-value-here>"
140+
}
138141
}
139142
}
140143
}
141144
```
142145

143-
Use the **Authenticated Server** configuration if you want to use the MCP server in a private environment.
144-
145-
You need an API key to use an authenticated server. Generate an API key in the Taskmaster **Settings → Developer → API Keys** page, copy it, and paste it in the `GRAM_KEY` environment variable in place of `<your-key-here>`.
146+
If you set the visibility to private, you will need a Gram API key to connect to the server. You can generate an API key under **Settings → New API Key** in the Gram dashboard, copy it, and paste it in the `GRAM_KEY` environment variable in place of `<your-key-here>`.
146147

147-
The authenticated server configuration looks something like this:
148+
The configuration using the Gram key looks something like this:
148149

149150
```json
150151
{
@@ -155,18 +156,114 @@ The authenticated server configuration looks something like this:
155156
"mcp-remote",
156157
"https://app.getgram.ai/mcp/ritza-rzx-taskmaster",
157158
"--header",
158-
"Gram-Environment:undefined",
159+
"Gram-Environment:${GRAM_ENVIRONMENT}",
159160
"--header",
160161
"Authorization:${GRAM_KEY}"
161162
],
162163
"env": {
164+
"GRAM_ENVIRONMENT": "<your-value-here>",
163165
"GRAM_KEY": "Bearer <your-key-here>"
164166
}
165167
}
166168
}
167169
}
168170
```
169171

172+
## Extending your MCP server with Gram Functions
173+
174+
While the tools generated from your OpenAPI document handle basic CRUD operations, you can extend your MCP server with custom logic using [Gram Functions](/docs/gram/concepts/functions). This is useful for adding business logic that goes beyond simple API calls.
175+
176+
For example, let's add a function that sends email reminders to users about their pending tasks. We'll use [Resend](https://resend.com) for sending emails. You can sign up for a free account and get an API key from their dashboard.
177+
178+
### Creating a task reminder function
179+
180+
1. Create a new Gram function project:
181+
182+
```bash
183+
pnpm create @gram-ai/function@latest --template gram
184+
```
185+
186+
This will prompt you to enter the directory name and the project name, which will be the name of the Gram function.
187+
188+
2. Install the `resend` package with `pnpm install resend` and replace the contents of `src/gram.ts` with the following code:
189+
190+
```ts
191+
import { Gram } from "@gram-ai/functions";
192+
import * as z from "zod/mini";
193+
import { Resend } from "resend";
194+
195+
const gram = new Gram({
196+
envSchema: {
197+
RESEND_API_KEY: z.string(),
198+
},
199+
}).tool({
200+
name: "send_email",
201+
description: "Send an email using Resend",
202+
inputSchema: {
203+
email: z.string(),
204+
subject: z.string(),
205+
text: z.string(),
206+
},
207+
async execute(ctx, input) {
208+
const resend = new Resend(ctx.env["RESEND_API_KEY"]);
209+
210+
try {
211+
const result = await resend.emails.send({
212+
from: "Acme <[email protected]>",
213+
to: [input["email"]],
214+
subject: input["subject"],
215+
html: `<p>${input["text"]}</p>`,
216+
});
217+
218+
return ctx.json({
219+
success: true,
220+
id: result.data?.id,
221+
message: "Email sent successfully",
222+
});
223+
} catch (error) {
224+
return ctx.fail(
225+
{
226+
error: "Failed to send email",
227+
details: error instanceof Error ? error.message : String(error),
228+
},
229+
{ status: 500 }
230+
);
231+
}
232+
},
233+
});
234+
235+
export default gram;
236+
```
237+
238+
The code above creates a function called `send_email` that accepts an email address, task title, and description as validated inputs using Zod schemas. The function uses the Resend API to send formatted HTML emails, with comprehensive error handling using `ctx.fail()` to return structured error responses with appropriate HTTP status codes, and `ctx.json()` to return successful results with the email message ID.
239+
240+
3. Build and deploy the function:
241+
242+
```bash
243+
pnpm build
244+
pnpm push
245+
```
246+
247+
4. In the Gram dashboard, go to **Toolsets**, click on the **Taskmaster** toolset, click **+ Add Tools**, select the newly created function, and save the changes.
248+
249+
![Screenshot showing the Add Tool dialog with the send_email function selected](./assets/add-function-to-toolset.png)
250+
251+
5. Update the environment variables by going to the **Auth** tab, updating the newly added `RESEND_API_KEY` variable with your Resend API key, and saving the environment.
252+
253+
![Screenshot showing the environment configuration dialog with RESEND_API_KEY variable being added](./assets/configure-resend-api-key.png)
254+
255+
Now the MCP server includes both the auto-generated CRUD tools from your OpenAPI document and a custom function for sending task reminders.
256+
257+
You can test the tool in the Playground with the following prompt:
258+
259+
```
260+
Please send an email to [email protected] to remind them of the pending tasks.
261+
```
262+
263+
![Testing the send email tool](./assets/testing-the-send-email-function.png)
264+
265+
You can find the complete code for this Resend integration example in the [Gram repository](https://github.com/speakeasy-api/gram/tree/main/examples/resend).
266+
170267
## Testing the MCP server
171268

172269
Before connecting to external clients, test your setup by using the **Gram Playground** to verify that your tools are working correctly.
@@ -181,7 +278,7 @@ Before connecting to external clients, test your setup by using the **Gram Playg
181278
Your Taskmaster MCP server is now ready to use with any MCP client. You can connect it to:
182279

183280
- [Claude Code](/docs/gram/clients/using-claude-code-with-gram-mcp-servers)
184-
- [Claude Desktop](/docs/gram/clients/using-claude-desktop-with-gram-mcp-server)
281+
- [Claude Desktop](/docs/gram/clients/using-claude-desktop-with-gram-mcp-server)
185282
- [Your IDE](/docs/gram/clients/using-your-ide-with-gram-mcp-server)
186283
- [Cline](/docs/gram/clients/using-cline-with-gram-mcp-server)
187284
- Any other MCP-compatible client

0 commit comments

Comments
 (0)