All Products
Search
Document Center

Agent Run:MCP Tool Hook

Last Updated:Aug 24, 2026

MCP Tool Hook inserts a proxy layer between the MCP client and server to run custom logic before and after tool calls, such as masking sensitive data or adding audit tags, without modifying the original MCP service code.

How it works

MCP Tool Hook runs on the AgentRun MCP proxy layer, which sits transparently between the MCP client (agent) and MCP server. When enabled, tool call requests pass through the proxy instead of going directly to the MCP service. The proxy triggers configured Hook events before and after tools/list and tools/call operations, forwarding the request or response to an external Hook service (HTTP webhook) for processing.

Note

The MCP protocol standard itself does not define a Hook or middleware mechanism. MCP Tool Hook is an extension capability provided by AgentRun above the protocol layer and is fully transparent to the MCP server.

Take the POST_CALL_TOOL event as an example. The data flow is as follows:

  1. The agent sends a tool call request.

  2. The AgentRun MCP proxy receives the request and calls the MCP service to execute the tool operation.

  3. The MCP service returns the raw result.

  4. The proxy forwards the result to the Hook service via an HTTP POST request based on the Hook configuration.

  5. The Hook service processes the result (for example, by masking sensitive data or adding audit tags) and returns the modified result.

  6. The proxy returns the final result to the agent.

Other events follow a similar flow. PRE_CALL_TOOL triggers before the tool call and can modify request parameters or block the call. PRE_LIST_TOOLS and POST_LIST_TOOLS trigger before and after fetching the tool list, allowing you to preprocess or filter the tool list.

Hook event types

The following Hook events are supported:

Event type

Trigger timing

Description

PRE_CALL_TOOL

Before tool call

Triggers before the MCP service executes the tool call. The Hook service receives the request parameters and can modify them or block the call.

POST_CALL_TOOL

After tool call completes

Triggers after the MCP service returns the tool call result. The Hook service receives the raw result and can return a modified version.

PRE_LIST_TOOLS

Before fetching tool list

Triggers before the MCP service executes tools/list. The Hook service can preprocess the request.

POST_LIST_TOOLS

After fetching tool list

Triggers after the MCP service returns the tool list. The Hook service can filter or modify the list.

Scenarios

  • Data masking: Mask sensitive information in tool results, such as phone numbers, email addresses, and physical addresses.

  • Audit tagging: Inject audit identifiers like request IDs and timestamps into tool results for traceability and auditing.

  • Result enhancement: Format, enrich, or filter raw data returned by tools.

  • Access control: Add permission verification logic before or after tool calls to restrict usage of specific tools.

Deployment modes

AgentRun supports two MCP Tool Hook deployment modes:

Deployment mode

Architecture

Use case

mcp_remote

Remote MCP + proxy + Hook. The MCP service and Hook service are deployed separately as HTTP services.

The MCP service is already deployed independently.

mcp_code

Code-packaged MCP + proxy + Hook. The MCP service code is bundled directly into the AgentRun runtime.

You want to simplify deployment by bundling the MCP service code into the runtime.

Both modes use the same Hook configuration method. The difference lies in how the MCP service is deployed and referenced.

Preparations

  • You have activated the AgentRun service. Confirm this in the AgentRun console.

  • You have activated Function Compute (FC) to deploy the MCP service and Hook service.

  • You have installed a Golang 1.23 or later development environment.

  • You have obtained your Alibaba Cloud account UID, AccessKey ID, and AccessKey secret. For instructions, see Obtain an AccessKey.

  • You have prepared the MCP service code and Hook service code. Obtain a complete example from the start-agentrun repository:

    git clone https://github.com/devsapp/start-agentrun.git
    cd start-agentrun

    The project includes two example directories: mcp_remote (remote MCP mode) and mcp_code (code-packaged mode), each providing a complete example for its respective deployment mode. All relative paths in the following steps are based on the project root directory start-agentrun/.

When deploying Function Compute services, the default region is on the Alibaba Cloud International Website (for example, ap-southeast-1). Choose a region that fits your business needs.

Configure MCP Tool Hook (mcp_remote mode)

The following example uses an order query service (orderdesk) and a data masking Hook service (userhook) to demonstrate how to configure mcp_remote mode.

Step 1: Configure environment variables

Go to the mcp_remote example directory and configure your Alibaba Cloud credentials.

  1. Enter the example directory:

    cd mcp_remote
  2. Copy the environment variable template and fill in your credentials:

    cp .env.example .env

    Edit the .env file and enter your Alibaba Cloud account information. Replace <ALIBABA_CLOUD_UID> in AGENTRUN_DATA_ENDPOINT with your actual UID:

    ALIBABA_CLOUD_UID=<Your Alibaba Cloud account UID>
    ALIBABA_CLOUD_ACCESS_KEY_ID=<Your AccessKey ID>
    ALIBABA_CLOUD_ACCESS_KEY_SECRET=<Your AccessKey secret>

Step 2: One-click deployment

Run the example program to deploy the MCP service (orderdesk) and Hook service (userhook), create the tool in AgentRun, enable the proxy, and configure the Hook.

go run .

The program automatically performs the following actions:

  1. Deploys the MCP service and Hook service to Function Compute.

  2. Creates an MCP tool in AgentRun and enables the proxy.

  3. Configures the Hook (POST_CALL_TOOL event) and associates the Hook service endpoint with the tool configuration.

  4. Makes a test call and outputs the validation result.

Note

The example program does not automatically clean up deployed resources after validation. The retained Function Compute functions incur no extra cost. To clean up, manually delete the corresponding functions in Function Compute and the MCP tool in AgentRun.

Step 3: Verify results

After the program finishes, check the output to confirm the Hook is active.

Raw order data returned without the Hook (querying ORDER-1001 as an example):

{
  "order_id": "ORDER-1001",
  "customer_name": "Zhang San",
  "phone": "138****5678",
  "email": "zhangsan@example.com",
  "shipping_address": "No. 100 Wensan Road, Xihu District, Hangzhou City, Zhejiang Province",
  "status": "PAID",
  "amount": 259.8,
  "items": [
    {"sku": "SKU-AX100", "name": "Ergonomic Mouse", "quantity": 1, "price": 129.9},
    {"sku": "SKU-KB200", "name": "Mechanical Keyboard Keycaps", "quantity": 1, "price": 129.9}
  ]
}

Data returned with the Hook enabled (masked):

{
  "order_id": "ORDER-1001",
  "customer_name": "Zhang*",
  "phone": "138****5678",
  "email": "zh***@example.com",
  "shipping_address": "Zhejiang Province, Hangzhou City, ****",
  "status": "PAID",
  "amount": 259.8,
  "items": [
    {"sku": "SKU-AX100", "name": "Ergonomic Mouse", "quantity": 1, "price": 129.9},
    {"sku": "SKU-KB200", "name": "Mechanical Keyboard Keycaps", "quantity": 1, "price": 129.9}
  ],
  "audit_id": "audit_xxxxxxxxxxxxxxxx"
}

Configuration reference

The example program auto-generates the following mcpProxyConfiguration:

{
  "proxyEnabled": true,
  "hooks": [
    {
      "event": "POST_CALL_TOOL",
      "endpoint": "<Endpoint address of the Hook service>"
    }
  ]
}

Parameter descriptions:

Parameter

Type

Required

Description

proxyEnabled

Boolean

Yes

Whether to enable the MCP proxy. Set to true to route tool calls through the proxy layer.

hooks

Array

No

List of Hook configurations. Each item includes an event type and Hook service endpoint.

hooks[].event

String

Yes

Hook event type. Supported values: PRE_CALL_TOOL, POST_CALL_TOOL, PRE_LIST_TOOLS, POST_LIST_TOOLS.

hooks[].endpoint

String

Yes

HTTP endpoint of the Hook service. The proxy sends an HTTP POST request to this address when the event triggers.

hooks[].enabled

Boolean

No

Whether to enable this Hook. Default is true.

hooks[].timeout

Integer

No

Hook request timeout in seconds.

hooks[].description

String

No

Description of the Hook.

hooks[].headers

Object

No

Custom request headers in key-value format.

Configure MCP Tool Hook (mcp_code mode)

In mcp_code mode, the MCP service code is bundled into the AgentRun runtime, so you do not need to deploy a standalone MCP service. The following example also uses orderdesk (MCP service) and userhook (Hook service).

Step 1: Configure environment variables

Go to the mcp_code example directory and configure your Alibaba Cloud credentials.

  1. Enter the example directory:

    cd mcp_code
  2. Copy the environment variable template and fill in your credentials:

    cp .env.example .env

    Edit the .env file and enter your Alibaba Cloud account information (same format as in mcp_remote mode).

Step 2: One-click deployment

Run the example program to bundle the MCP service code, deploy the Hook service, create the tool in AgentRun, enable the proxy, and configure the Hook.

go run .

Unlike mcp_remote mode, in mcp_code mode the MCP service code is bundled directly into the AgentRun runtime, so no separate MCP service deployment is needed.

Step 3: Verify results

Verification is the same as in mcp_remote mode. See Step 3: Verify results.

Example: Order data masking Hook service

The Hook service in the example (userhook) is implemented in Go and handles the POST_CALL_TOOL event. Below are the core masking functions. For the complete code, see the start-agentrun repository.

// maskPhone masks a phone number, keeping the first 3 and last 4 digits.
func maskPhone(phone string) string {
    runes := []rune(strings.TrimSpace(phone))
    if len(runes) <= 7 {
        return "***"
    }
    return string(runes[:3]) + "****" + string(runes[len(runes)-4:])
}

// maskEmail masks an email address, keeping the first 1–2 characters of the username.
func maskEmail(email string) string {
    parts := strings.SplitN(email, "@", 2)
    if len(parts) != 2 {
        return "***"
    }
    name := []rune(parts[0])
    keep := 1
    if len(name) > 2 {
        keep = 2
    }
    return string(name[:keep]) + "***@" + parts[1]
}

// maskAddress masks an address, keeping the first 6 characters.
func maskAddress(address string) string {
    runes := []rune(strings.TrimSpace(address))
    if len(runes) <= 6 {
        return "***"
    }
    return string(runes[:6]) + "****"
}

// maskName masks a name, keeping only the surname (first character).
func maskName(name string) string {
    runes := []rune(strings.TrimSpace(name))
    if len(runes) == 0 {
        return "***"
    }
    return string(runes[:1]) + "*"
}

// auditIDFromBytes generates an audit ID from the raw response (SHA256 hash prefix).
func auditIDFromBytes(body []byte) string {
    sum := sha256.Sum256(body)
    return "audit_" + hex.EncodeToString(sum[:])[:16]
}

The Hook service receives the event payload from the proxy via HTTP POST. The request and response bodies in the payload are Base64-encoded. The Hook service decodes them, masks sensitive fields, injects an audit identifier, and returns the modified result as a Base64-encoded string.

Error handling

If the Hook service fails, the proxy interrupts the current MCP request:

Error scenario

Proxy behavior

Hook service timeout

The MCP request fails and returns an error to the caller.

Hook service unavailable (connection failure)

The MCP request fails and returns an error to the caller.

Hook service returns a non-200 status code

The MCP request fails and returns an error to the caller.

Important

If the Hook service fails due to timeout, unavailability, or a non-200 status code, the proxy does not fall back. It marks the current MCP request as failed. If PRE_CALL_TOOL fails, the tool is not executed. If POST_CALL_TOOL fails, the raw result is not returned to the caller. Ensure your Hook service has high availability.

FAQ

Hook service does not take effect after configuration

Follow these steps to troubleshoot:

  1. Confirm proxyEnabled is set to true.

  2. Confirm the hooks[].endpoint address is correct and the Hook service is running.

  3. Confirm the hooks[].event value is a supported event type (PRE_CALL_TOOL, POST_CALL_TOOL, PRE_LIST_TOOLS, or POST_LIST_TOOLS; note case sensitivity).

  4. Check the Hook service logs to confirm it received the HTTP POST request from the proxy.

How to choose a deployment mode

Condition

Recommended mode

MCP service is already deployed independently

mcp_remote

You want to simplify deployment by bundling the MCP service code into the runtime

mcp_code