Manual Creation

Manual Tool Creation gives you complete control over your tool's implementation. While AI-Powered Creation is great for most use cases, manual creation is perfect when you need specific logic, custom optimizations, or integration with existing code patterns.

When to Use Manual Creation

Manual creation is the right choice when you need:

  • Full control - You want to write every line of code yourself

  • Complex logic - Your tool requires sophisticated business logic that's hard to describe in natural language

  • Performance optimization - You need to optimize for specific performance requirements

  • Custom patterns - You want to follow specific coding patterns or use particular libraries

  • Integration with existing code - You need to reuse existing code or integrate with specific systems

  • Fine-tuning - You started with AI generation but need to make significant customizations

  • Learning - You want to understand how tools work by writing them yourself

If you're comfortable with JavaScript and want complete control, manual creation is a powerful option. You can also combine approaches - use AI generation to get started, then switch to manual editing for fine-tuning.

Understanding the Tool Function Signature

Every tool in MCP Functions must follow a specific structure. This structure ensures that tools can be called consistently by AI assistants and that they have access to the resources they need.

The Required Function

Every tool must define an async function named execute. This is the entry point that gets called when an AI assistant invokes your tool:

Understanding the Parameters

The execute function receives two parameters:

1. params (Parameters)

The params object contains all the input data provided by the AI assistant when it calls your tool. The structure of this object matches the parameter schema you define for the tool.

Example: If your tool has parameters "email" (string) and "includeOrders" (boolean), the params object might look like:

You access these values in your code using dot notation: params.email or params.includeOrders.

2. config (Configuration)

The config object contains workspace secrets and configuration values. These are the encrypted secrets you stored in your workspace.

Example: If you stored secrets like "STRIPE_API_KEY" and "DATABASE_URL" in your workspace, you can access them like:

Secrets are never exposed in logs, error messages, or code - they're only accessible through the config parameter during execution. If a secret doesn't exist, accessing it will return undefined.

Return Value

Your function should return an object with a standardized structure:

The return value tells the AI assistant whether the tool execution succeeded and what data was returned. Always return this structure, even when there's an error.

Defining Parameters

Before writing your code, you need to define what parameters your tool accepts. This parameter schema tells AI assistants what inputs to provide when calling your tool.

Parameter Schema Structure

Parameters are defined as a JSON object where each key is a parameter name, and the value describes that parameter:

Parameter Properties

Each parameter can have the following properties:

  • type - The data type: "string", "number", "boolean", "object", or "array"

  • description - A clear explanation of what this parameter is for. This helps AI assistants understand when to provide it.

  • required - Whether this parameter must be provided (true) or is optional (false)

  • default - A default value to use if the parameter is not provided (only for optional parameters)

  • enum - A list of allowed values (useful for restricting inputs to specific options)

  • format - For strings, can specify formats like "email", "uri", "date-time", etc.

  • minimum/maximum - For numbers, can specify min/max values

  • minLength/maxLength - For strings, can specify min/max length

Example: Complete Parameter Schema

This schema defines three parameters: - email - Required string that must be a valid email format - includeOrders - Optional boolean that defaults to false - limit - Optional number between 1 and 100, defaulting to 10

Why Parameter Definitions Matter

Well-defined parameters help AI assistants:

  • Understand what data to provide

  • Validate inputs before calling your tool

  • Provide better error messages if something is wrong

  • Use your tool correctly in different contexts

Take time to write clear descriptions and set appropriate validation rules.

Code Structure and Best Practices

Following consistent patterns makes your tools more reliable, maintainable, and easier to debug. Here are the key patterns to follow:

1. Use async/await for Asynchronous Operations

Most tools need to make HTTP requests, access databases, or perform other asynchronous operations. Use async/await for clean, readable code:

2. Handle Errors with try-catch

Always wrap your code in try-catch blocks to handle errors gracefully:

This ensures that if something goes wrong, your tool returns a proper error response instead of crashing.

3. Validate Input Parameters

Always validate that required parameters are provided and in the correct format:

Validation helps catch errors early and provides clear error messages to AI assistants.

4. Return Structured Data

Always return data in the standard format:

This consistent structure makes it easy for AI assistants to understand and use your tool's output.

5. Use console.log for Debugging

You can use console.log to debug your tools. These logs are captured and available in the tool execution logs:

Logs help you understand what's happening during execution and debug issues. Be careful not to log sensitive information like passwords or API keys.

6. Access Workspace Secrets Securely

Always access secrets through the config parameter, never hardcode them:

Always check that secrets exist before using them, and provide clear error messages if they're missing.

Comprehensive Error Handling

Robust error handling is crucial for reliable tools. Your tools will encounter various error conditions, and handling them gracefully ensures a good experience for users.

Basic Error Handling Pattern

Always wrap your code in try-catch blocks:

Handling Specific Error Types

You can handle different types of errors differently:

Error Handling Best Practices

  • Validate early - Check inputs and prerequisites before doing expensive operations

  • Provide clear error messages - Error messages should explain what went wrong and ideally how to fix it

  • Don't expose sensitive information - Never include API keys, passwords, or other secrets in error messages

  • Handle expected errors - Anticipate common error conditions (404, 401, network failures) and handle them specifically

  • Log errors appropriately - Use console.log for debugging, but be careful not to log sensitive data

Complete Example: A Well-Structured Tool

Here's a complete example that demonstrates all the best practices:

This example demonstrates: - Input validation - Secret checking - HTTP request handling - Error handling for different scenarios - Structured return values - Proper error messages

Testing Your Tools

Before deploying your tool, always test it thoroughly:

  • Test with valid inputs - Verify it works with expected data

  • Test with invalid inputs - Ensure it handles errors gracefully

  • Test with missing parameters - Verify validation works

  • Test error scenarios - Simulate API failures, network errors, etc.

  • Check return formats - Ensure return values match the expected structure

The platform provides a testing interface where you can run your tools with different inputs and see the results immediately.

Tips for Manual Creation

  • Start with AI generation - Even if you plan to write manually, start with AI generation to see a working example, then customize it

  • Follow the patterns - Use the patterns shown here for consistency and reliability

  • Test frequently - Test your code as you write it, not just at the end

  • Use console.log strategically - Log important steps to help with debugging

  • Keep it simple - Don't overcomplicate. Simple, clear code is easier to maintain and debug

  • Handle all error cases - Think about what can go wrong and handle it

  • Document complex logic - Add comments explaining non-obvious parts of your code

Last updated