Skills, Tools, and MCP in Open WebUI: What's What
How Open WebUI skills differ from tools and functions, how SKILL.md is structured, how MCP servers connect, and where the line of locality actually falls in this setup.
Open WebUI has four different ways to extend a model's behavior: tools, functions, pipelines, and skills. Plus MCP, separately. The names sit close together, the docs are spread across sections, and in practice people end up connecting the wrong one.
The difference between them is simple once you spell it out once.
Skills: text, not code
A skill is a set of instructions in markdown. Not a script, not an API — a document that explains to the model how to approach a task: code-review rules, text-style requirements, an incident-triage sequence.
It's structured as a folder with a SKILL.md file. If the top of the file has YAML
frontmatter with name and description fields, the interface picks them up
automatically:
---
name: code-review-guidelines
description: Step-by-step instructions for thorough code reviews
---
# Code Review Guidelines
You can put subfolders like references/, templates/, scripts/, and assets/
next to it.
A skill gets invoked two ways: mentioned with $ right in the chat — in which case
the whole content gets inserted at once — or attached to a model in its settings, so
it's always available. They load gradually: the model first sees only a catalog of
descriptions, and the full text loads in once activated. That's done for the sake of
context, and for local models that saving matters more than it does for cloud ones.
The main property to remember: writing a skill doesn't require Python. If you can write a document, you can build skills. The same idea is covered in the article on skills for an AI agent.
Tools and functions: code
Tools and functions are Python scripts that run inside the chat. There's a built-in code editor for them, so you can write directly in the interface.
The difference from skills is fundamental. A skill changes how the model thinks: it gives it instructions and context. A tool gives it a new action: hit an API, compute something, write something down. Mixing them up is a common mistake. If the task sounds like "make it answer according to our style guide," that's a skill. If it's "make it check an order's status in our system," that's a tool.
Pipelines sit separately: a modular framework for filters, providers, and custom logic, a level down and for more elaborate scenarios.
MCP
Open WebUI supports MCP servers directly, over Streamable HTTP. A ready-made tool server connects without writing your own function for every integration.
The logic is the same as in other hosts: the server declares a list of tools, the host shows them to the model, the model asks for a call, the host executes it. The protocol itself is explained in what MCP is, and connecting it in other apps is covered in MCP in LM Studio and MCP in llama.cpp.
The practical advice is the same as everywhere else: don't connect everything at once. Tool descriptions eat into the context on every request, and a local model with eight thousand tokens of context hits its limit faster than you'd expect.
If a model starts mixing up tool arguments or calling the wrong server, disable half the servers first, before switching models. Nine times out of ten, it's an overloaded context, not the model.
What to pick for a task
| You need | You take |
|---|---|
| The model to follow your rules | A skill |
| The model to perform an action in your system | A tool or a function |
| A ready-made integration connected | An MCP server |
| To embed your own request-handling logic | A pipeline |
Where the line of locality sits
Worth saying plainly, because "local interface" is misleading here.
What stays local is whatever physically computes and stores on your machine: the model, chat history, the knowledge base. Everything else depends on what you connected. The GitHub MCP server talks to GitHub. A tool that hits an outside API sends data there. A skill by itself doesn't reach outward — it's just text — but that text ends up in the model's context, and if the model is a cloud one, it travels along with the request.
A local MCP client doesn't turn a cloud service into a local one. You have to check the whole chain: where the model computes, which servers are enabled, and where each one connects to.
What even the full set doesn't give you
Put it all together — skills, tools, MCP, pipelines — and you get a very configurable chat. The model will know your rules and be able to pull your systems.
What you still won't get: something that actually does the work. Open WebUI lives in the browser and works with whatever you've loaded into it. Tasks like "go through the project on disk, find it, and fix it" need access to the filesystem and terminal of the machine it all lives on — and the ability to carry a task through several steps while checking the result.
Doka is built as exactly that kind of executor. It works with files where they live, runs commands, connects MCP servers, and lets you describe your own skills in the same kind of text as Open WebUI's skills — but the result of those skills applies to your actual files, instead of staying as a message in a chat.
If you've already set up Open WebUI the way you like it, install Doka next to it and run through it the task you usually end up copy-pasting answers out of by hand. That's the clearest way to see the difference between a configurable chat and an agent.