Connect / Add tools with TypeScript
Add tools with TypeScript
Write custom tools with the TypeScript functions framework, test them locally, and deploy them as a source.
Speakeasy Functions are compact code units that represent LLM tools. Write them in TypeScript, deploy them to Speakeasy, and expose them to language models through MCP servers. Once deployed, Functions behave like any other tool on the platform, so they can be hosted as MCP servers, combined with tools from other sources on a single server, or used to build multi-tool workflows.
Unlike OpenAPI-sourced tools, which wrap existing API endpoints, functions run custom code in isolated environments. Function-sourced tools suit:
- Custom business logic: Calculations, data processing, or decision-making beyond simple API calls, such as aggregating data from multiple sources
- Data transformations: Filtering, enriching, or summarizing data before returning it to the LLM
- Multi-step workflows: Orchestrating several API calls or operations in a single tool
import { Gram } from "@gram-ai/functions";import * as z from "zod/mini";
const gram = new Gram().tool({ name: "greet", description: "Greet someone special", inputSchema: { name: z.string() }, async execute(ctx, input) { return ctx.json({ message: `Hello, ${input.name}!` }); },});
export default gram;The steps below also appear in the dashboard under Connect > Sources > Add Source > Write custom code.
Before you start
Section titled “Before you start”This guide assumes:
- An account and project exist (see Getting started)
- Node.js version 22.18.0 or later is installed
Step 1: Create a project
Section titled “Step 1: Create a project”Scaffold a new project:
npm create @gram-ai/function@latestThe scaffolder prompts for:
- Framework: Gram Functions (the simplest path, batteries included) or the official Model Context Protocol SDK for advanced use cases
- Project name, directory, and git initialization
- Dependency installation
- CLI installation: The
gramCLI is required to deploy. The scaffolder offers to install it and rungram authto authenticate
To skip the framework prompt and scaffold directly onto the Functions Framework, pass a template:
npm create @gram-ai/function@latest --template gramThe project contains src/gram.ts (the tools) and src/server.ts (a local MCP server for testing):
└── src ├── gram.ts # Edit me! └── server.ts└── package.json└── README.mdStep 2: Write tools
Section titled “Step 2: Write tools”Open src/gram.ts and define tools, as many as needed:
import { Gram } from "@gram-ai/functions";import * as z from "zod/mini";
const gram = new Gram().tool({ name: "greet", description: "Greet someone special", inputSchema: { name: z.string() }, async execute(ctx, input) { return ctx.json({ message: `Hello, ${input.name}!` }); },});
export default gram;Tools can be written with the Functions Framework or the official MCP SDK. The Functions Framework is the more lightweight way to write tools, and MCP SDK support is available for teams that prefer the official SDK.
Tools, not servers
These are tools, not a finished MCP server. After deploying, tools can be sliced into multiple MCP servers or combined with tools from other sources.
Test locally before deploying. Running npm run dev starts the project under the MCP Inspector, so tools can be called interactively from the browser.
Step 3: Build and deploy
Section titled “Step 3: Build and deploy”npm run buildnpm run pushBuild bundles the functions. Push stages the bundle and creates a deployment, running the gram CLI commands gram stage function and gram push under the hood. Once the deployment completes, the functions source and its tools appear under Connect > Sources in the dashboard. Deployment history and retries live under Deployments, and the Build and deploy guide covers the process in full.
Step 4: Create an MCP server
Section titled “Step 4: Create an MCP server”Go to Distribute > MCP and click New MCP Server, then add the deployed tools on the server’s Tools tab. The server’s detail page links to a hosted installation page with per-client setup instructions. See MCP Servers for visibility, publishing, and team access.
Functions vs MCP servers
Section titled “Functions vs MCP servers”Functions provide a way to create individual tools for use in MCP servers. Creating tools is not the same as creating MCP servers.
The key distinction:
- Functions: Individual tools that represent specific capabilities or operations
- MCP servers: Collections of tools combined into a single server that LLM clients can access
Once a tool exists, whether it came from Functions or OpenAPI, combine it with other tools into one or many MCP servers. Functions can therefore be split across multiple projects, kept in a single file, or organized however a workflow requires.
MCP servers are assembled from these tools later in the Speakeasy dashboard.