@strawberryprotocol/str-toolserver v0.0.1
Strawberry.fun Toolserver
This library contains the code for writing a tool server for Strawberry.fun.
Agents discover tools and pay to use them. This library is designed for tool authors to quickly create and deploy a new tool, which they can monetize through a token and fees.
Installation
npm install @strawberryprotocol/str-toolserver
Basic Usage
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { strawberry } from "@strawberryprotocol/str-toolserver";
function createServer() {
const server = new Server(
{ name: "my-server", version: "1.0.0" },
{ capabilities: { tools: {} } }
);
// Add your tool handlers here
// ...
return server;
}
const app = strawberry(createServer);
app.connect();
app.listen(3000);
Authentication & Authorization
The str-toolserver package provides built-in support for EIP-712 signature verification and token gating:
Signature Verification
Use createSignatureVerifier
to verify that requests are signed by a specific Ethereum address:
import { createSignatureVerifier } from "@strawberryprotocol/str-toolserver";
const verifier = createSignatureVerifier({
domain: {
name: "Strawberry.fun",
version: "1",
chainId: 84532, // Base Sepolia
},
});
server.setRequestHandler(CallToolRequestSchema, async request => {
// This will throw if signature is invalid
const signerAddress = await verifier(request);
return {
content: [{
type: "text",
text: `Message from ${signerAddress}: ${request.params.arguments?.message}`
}],
};
});
Token Gating
Use createTokenGateVerifier
to require users to hold a minimum balance of a specific token:
import { createTokenGateVerifier } from "@strawberryprotocol/str-toolserver";
import { createPublicClient, http } from "viem";
import { baseSepolia } from "viem/chains";
// Create a viem client for reading token balances
const client = createPublicClient({
chain: baseSepolia,
transport: http(),
});
const verifier = createTokenGateVerifier(client, {
domain: {
name: "Strawberry.fun",
version: "1",
chainId: 84532, // Base Sepolia
},
tokenAddress: "0x1234..." as Address, // Your token contract address
minTokenBalance: 1n, // Minimum required balance
});
server.setRequestHandler(CallToolRequestSchema, async request => {
try {
// This will throw if signature is invalid or token balance is insufficient
const { signerAddress, balance } = await verifier(request);
return {
content: [{
type: "text",
text: `Authorized request from ${signerAddress} (balance: ${balance})`
}],
};
} catch (error) {
throw new Error(`Access denied: ${error.message}`);
}
});
Tool Schema Requirements
When using signature verification, your tool's input schema must include a strawberry_signature
parameter:
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [{
name: "my-tool",
description: "A token-gated tool",
inputSchema: {
type: "object",
properties: {
message: {
type: "string",
description: "Your message"
},
strawberry_signature: {
type: "string",
description: "EIP-712 signature of the request parameters"
},
},
required: ["message", "strawberry_signature"],
},
}],
}));
Error Handling
The auth functions throw specific error types that you can handle:
SignatureVerificationError
: Thrown when signature verification failsTokenBalanceError
: Thrown when token balance is insufficient
Examples
Check out the examples
directory for complete working examples:
hello-world-typescript
: Basic server setuphello-world-typescript/index-gated.ts
: Token-gated server example
Environment Variables
When using token gating, you'll need to set:
LOCALHOST_TOKEN
: The address of your ERC20 token contract
Contributing
See CONTRIBUTING.md for more information.
5 months ago