Use an MCP server as a tool
Give an LLM tools that are backed by an external Model Context Protocol (MCP) server instead of your own resources. kdeps starts the server as a subprocess, performs the handshake, calls the tool, and shuts it down.
A workflow-mode tool normally runs one of your resources (script:). An mcp: tool runs a tool exposed by an MCP server. mcp: and script: are mutually exclusive. A fresh subprocess is started for each tool invocation and only stdio transport is supported.
Needs: Node.js with npx on PATH (for the filesystem MCP server).
Step 1: create the project
mkdir mcp-chat
cd mcp-chat
mkdir resourcesStep 2: define the route
Create workflow.yaml:
# workflow.yaml
apiVersion: kdeps.io/v1
kind: Workflow
metadata:
name: mcp-chat
version: "1.0.0"
targetActionId: chat
settings:
apiServer:
portNum: 16395
routes:
- path: /chat
methods: [POST]Step 3: give the LLM MCP tools
Create resources/chat.yaml:
# resources/chat.yaml
actionId: chat
name: Chat with MCP filesystem tools
validations:
methods: [POST]
routes: [/chat]
chat:
model: llama3.2:1b
role: user
prompt: "{{ input('message') }}"
system: |
You are an assistant with filesystem tools via MCP. Use read_file to read
files and list_directory to explore. Only access paths the user names.
tools:
- name: read_file
description: "Read the contents of a file at the given path."
mcp:
server: npx
args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
transport: stdio # the only supported transport
parameters:
path:
type: string
description: "Absolute path to the file to read."
required: true
- name: list_directory
description: "List files and subdirectories in a directory."
mcp:
server: npx
args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
parameters:
path:
type: string
description: "Absolute path to the directory to list."
required: true
apiResponse:
success: true
response:
reply: "{{ output('chat') }}"The last argument to server-filesystem (/tmp) is the only directory the server will touch - the model cannot read outside it.
Step 4: validate and run
kdeps validate .
export KDEPS_API_AUTH_TOKEN=dev-token
echo "hello from mcp" > /tmp/note.txt
kdeps run .curl -X POST http://localhost:16395/chat \
-H "Authorization: Bearer $KDEPS_API_AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d '{"message": "What is in /tmp/note.txt?"}'The model calls read_file with path: "/tmp/note.txt", kdeps runs the MCP server, returns the contents (hello from mcp), and the model answers in text. With llama3.2:1b the reply was:
{"success": true, "data": {"reply": {"message": {"role": "assistant", "content": "The contents of /tmp/note.txt are:"}}}}The wording comes from the model and varies. Small local models such as llama3.2:1b often write the tool call as JSON text instead of a structured call; kdeps recovers it, runs the tool, and stops a model that keeps re-issuing the same call by asking once more, without tools, for a plain answer. A 1B model's answer can be thin, as above; use a larger model for dependable tool use.
Next steps
- Function calling -
script:tools, parameter types - Function calling - MCP details, debugging
- Function calling tutorial - tools backed by your own resources
- Agent loop built-in tools - MCP in agent mode
