0.0.1 • Published 5 months ago

@strawberryprotocol/str-toolserver v0.0.1

Weekly downloads
-
License
MIT
Repository
github
Last release
5 months ago

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 fails
  • TokenBalanceError: Thrown when token balance is insufficient

Examples

Check out the examples directory for complete working examples:

  • hello-world-typescript: Basic server setup
  • hello-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.