Lab 7 · MCP-style tool protocol

Tool discovery via a manifest

The Agent Lab already has tool implementations, Zod arg schemas, and a permission policy in three separate modules. Model Context Protocol takes those and renders them as one machine-readable manifest so any compatible client can discover what is available, what it requires, and what it costs in approval.

Why this lab matters: Tools need descriptions, schemas, and permission metadata to be discoverable. MCP is about tool interoperability, not magic intelligence — the same five tools below could be served from any MCP-compatible host and consumed by any MCP-compatible client.

getCustomer

Resolve a customer name or id into the canonical customer record.

read-only
Permission

Read-only data lookup. Safe to call without approval.

Input schema

{
  "type": "object",
  "properties": {
    "customerNameOrId": {
      "type": "string",
      "minLength": 1
    }
  },
  "required": [
    "customerNameOrId"
  ],
  "additionalProperties": false
}

Simulated MCP handshake

What an agent would send and receive on first contact: initialize tools/listtools/call. No real socket; the lab generates the envelopes from the same manifest the runner already uses.

  1. 1. initializeclient→server
    {
      "protocolVersion": "2024-11-05",
      "clientInfo": {
        "name": "agent-lab-runner",
        "version": "0.1.0"
      },
      "capabilities": {}
    }
  2. 2. initialize/resultserver→client
    {
      "protocolVersion": "2024-11-05",
      "serverInfo": {
        "name": "agent-lab-mock-erp",
        "version": "0.1.0"
      },
      "capabilities": {
        "tools": {
          "listChanged": false
        }
      }
    }
  3. 3. tools/listclient→server
    {}
  4. 4. tools/list/resultserver→client
    {
      "tools": [
        {
          "name": "getCustomer",
          "description": "Resolve a customer name or id into the canonical customer record.",
          "inputSchema": {
            "type": "object",
            "properties": {
              "customerNameOrId": {
                "type": "string",
                "minLength": 1
              }
            },
            "required": [
              "customerNameOrId"
            ],
            "additionalProperties": false
          }
        },
        {
          "name": "getCreditStatus",
          "description": "Return the current credit limit, exposure, available credit, status, and risk level.",
          "inputSchema": {
            "type": "object",
            "properties": {
              "customerId": {
                "type": "string",
                "minLength": 1,
                "maxLength": 64
              }
            },
            "required": [
              "customerId"
            ],
            "additionalProperties": false
          }
        },
        {
          "name": "getOpenInvoices",
          "description": "List all open and overdue invoices for a customer.",
          "inputSchema": {
            "type": "object",
            "properties": {
              "customerId": {
                "type": "string",
                "minLength": 1,
                "maxLength": 64
              }
            },
            "required": [
              "customerId"
            ],
            "additionalProperties": false
          }
        },
        {
          "name": "checkOrderEligibility",
          "description": "Compute whether a proposed order can be released given current credit and aging.",
          "inputSchema": {
            "type": "object",
            "properties": {
              "customerId": {
                "type": "string",
                "minLength": 1,
                "maxLength": 64
              },
              "orderAmount": {
                "type": "integer",
                "maximum": 10000000,
                "exclusiveMinimum": 0
              }
            },
            "required": [
              "customerId",
              "orderAmount"
            ],
            "additionalProperties": false
          }
        },
        {
          "name": "createCreditReviewTicket",
          "description": "Create a persistent credit-review ticket. Write action; always requires approval.",
          "inputSchema": {
            "type": "object",
            "properties": {
              "customerId": {
                "type": "string",
                "minLength": 1,
                "maxLength": 64
              },
              "reason": {
                "type": "string",
                "minLength": 8
              }
            },
            "required": [
              "customerId",
              "reason"
            ],
            "additionalProperties": false
          }
        }
      ]
    }
  5. 5. tools/callclient→server
    {
      "name": "getCustomer",
      "arguments": {
        "customerNameOrId": "ACME"
      }
    }