Skip to main content
This document introduces how to use Go Template to process request and response data in MCP Gateway. Go Template provides powerful template functionality that helps us flexibly handle data transformation and formatting.

Basic Syntax

Go Template uses {{}} as delimiters, and various functions and variables can be used within the delimiters. In MCP Gateway, we mainly use the following variables:

Configuration Variables

  • .Config: Service-level configuration
  • .Args: Request parameters

Runtime Variables

  • .Request: Original request information
  • .Response: Upstream service response information

Common Use Cases

1. Getting Configuration from Environment Variables

config:
  Authorization: 'Bearer {{ env "AUTH_TOKEN" }}'  # Get configuration from environment variables
Using the env function allows you to safely retrieve sensitive information from environment variables, avoiding hardcoding in configuration files.

2. Extracting Values from Request Headers

headers:
  Authorization: "{{.Request.Headers.Authorization}}"   # Pass through client's Authorization header
  Cookie: "{{.Config.Cookie}}"                          # Use value from service configuration

3. Building Request Body

requestBody: |-
  {
    "username": "{{.Args.username}}",
    "email": "{{.Args.email}}"
  }

4. Processing Response Data

responseBody: |-
  {
    "id": "{{.Response.Data.id}}",
    "username": "{{.Response.Data.username}}",
    "email": "{{.Response.Data.email}}",
    "createdAt": "{{.Response.Data.createdAt}}"
  }

5. Handling Nested Response Data

For complex nested data structures, you can access them layer by layer:
responseBody: |-
  {
    "id": "{{.Response.Data.id}}",
    "username": "{{.Response.Data.username}}",
    "email": "{{.Response.Data.email}}",
    "createdAt": "{{.Response.Data.createdAt}}",
    "preferences": {
      "isPublic": {{.Response.Data.preferences.isPublic}},
      "showEmail": {{.Response.Data.preferences.showEmail}},
      "theme": "{{.Response.Data.preferences.theme}}",
      "tags": {{.Response.Data.preferences.tags}}
    }
  }

6. Handling Array Data

When you need to process array data in responses, you can use Go Template’s range functionality:
responseBody: |-
  {
    "total": "{{.Response.Data.total}}",
    "rows": [
      {{- $len := len .Response.Data.rows -}}
      {{- $rows := fromJSON .Response.Data.rows }}
      {{- range $i, $e := $rows }}
      {
        "id": {{ $e.id }},
        "detail": "{{ $e.detail }}",
        "deviceName": "{{ $e.deviceName }}"
      }{{ if lt (add $i 1) $len }},{{ end }}
      {{- end }}
    ]
  }
This example shows how to:
  1. Use the fromJSON function to convert JSON strings into traversable objects
  2. Use range to iterate through arrays
  3. Use the len function to get array length
  4. Use the add function for mathematical operations
  5. Use conditional statements if to control comma separation between array elements

7. Using Parameters in URLs

Dynamically building URL paths:
endpoint: "http://localhost:5236/users/{{.Args.email}}/preferences"

8. Handling Complex Object Data

When you need to convert complex structures like objects and arrays from requests or responses to JSON, you can use the toJSON function:
requestBody: |-
  {
    "isPublic": {{.Args.isPublic}},
    "showEmail": {{.Args.showEmail}},
    "theme": "{{.Args.theme}}",
    "tags": {{.Args.tags}},
    "settings": {{ toJSON .Args.settings }}
  }
Here, settings is a complex object. Using the toJSON function will automatically convert settings to a JSON string.

9. Safely Access Nested Fields (safeGet/safeGetOr)

When a middle level of a nested object is null (or missing), direct access will cause a template rendering error. For example:
responseBody: |-
  {
    "id": "{{.Response.Data.id}}",
    "username": "{{.Response.Data.username}}",
    "email": "{{.Response.Data.email}}",
    "createdAt": "{{.Response.Data.createdAt}}",
    "theme": "{{.Response.Data.preferences.theme}}"  # Will error if preferences is null
  }
To address this, two functions are added: safeGet and safeGetOr.
  • safeGet <path> <root>: Safely reads a nested field; if any middle level is nil/missing, returns an empty value (no error).
  • safeGetOr <path> <root> <default>: Like safeGet, but returns <default> when access fails.
Example data (normal):
{
  "id": "28050608-7f39-42cf-be06-4982135dada9",
  "username": "2",
  "email": "1",
  "createdAt": "2025-09-12T11:43:16.086506+08:00",
  "preferences": {
    "isPublic": false,
    "showEmail": true,
    "theme": "light",
    "tags": [],
    "settings": {},
    "notifications": []
  }
}
When preferences is null:
{
  "id": "28050608-7f39-42cf-be06-4982135dada9",
  "username": "2",
  "email": "1",
  "createdAt": "2025-09-12T11:43:16.086506+08:00",
  "preferences": null
}
Then:
# Using safeGet: no error, renders as empty (<no value>)
responseBody: |-
  {
    "id": "{{.Response.Data.id}}",
    "username": "{{.Response.Data.username}}",
    "email": "{{.Response.Data.email}}",
    "createdAt": "{{.Response.Data.createdAt}}",
    "theme": "{{ safeGet "Response.Data.preferences.theme" . }}"
  }

# Using safeGetOr: provide a default value
responseBody: |-
  {
    "id": "{{.Response.Data.id}}",
    "username": "{{.Response.Data.username}}",
    "email": "{{.Response.Data.email}}",
    "createdAt": "{{.Response.Data.createdAt}}",
    "theme": "{{ safeGetOr "Response.Data.preferences.theme" . "light" }}"
  }

Built-in Functions

Currently supports the following built-in functions:
Get environment variable values
Authorization: 'Bearer {{ env "AUTH_TOKEN" }}'
Perform integer addition operations
{{ if lt (add $i 1) $len }},{{ end }}
Convert JSON strings to traversable objects
{{- $rows := fromJSON .Response.Data.rows }}
Convert objects to JSON strings
"settings": {{ toJSON .Args.settings }}
Safely read nested fields; if any middle level is nil or missing, return an empty value without error.
{{ safeGet "Response.Data.preferences.theme" . }}
Like safeGet, but returns a default value when access fails.
{{ safeGetOr "Response.Data.preferences.theme" . "light" }}

Template Debugging Tips

1

Use Log Output

During development, you can view actual values of template variables through logs
2

Step-by-step Construction

For complex templates, it’s recommended to first build a simple version, then gradually add complex logic
3

Test Edge Cases

Ensure templates work correctly under various data conditions, including empty values, null values, etc.

Best Practices

  • Avoid directly exposing sensitive information in templates
  • Use environment variables to store keys and passwords
  • Properly validate and escape user input
  • Avoid complex calculations in templates
  • Use caching mechanisms appropriately
  • For large data processing, consider preprocessing in upstream services
  • Keep templates concise and clear
  • Add appropriate comments and explanations
  • Use meaningful variable names

Extension Features

If you need to add new template functions, you can:
  1. Describe specific use cases, create an issue explaining the requirements
  2. Welcome PR after implementation, but currently only accept general-purpose functions

More Resources

Go Template Official Documentation

View complete Go Template documentation and advanced usage
I