Semantic Workflow Profile
This page explains what the built-in semantic-workflow profile is, why it exists, and when you should use it.
What It Is
semantic-workflow is a tool discovery profile for native ZCP clients.
Instead of always returning the full primitive tool registry, a client can ask the server for a smaller registry that contains only workflow-level tools:
from zcp import SemanticWorkflowProfile
profile = SemanticWorkflowProfile()
tools = await client.list_tools(**profile.as_list_tools_params())In raw form, this is the same as:
tools = await client.list_tools(profile="semantic-workflow")When the server publishes tools tagged with _meta.groups that include workflow, the returned registry is narrowed to that workflow subset.
Why It Exists
MCP-compatible primitive tools are good for interoperability, but they are not always good planning units for model-driven execution.
For example, a spreadsheet server may expose primitive tools such as:
write_data_to_excelformat_rangemerge_cellsread_data_from_excel
Those are fine for compatibility, but a native client planning a larger task often does better when it sees higher-level tools such as:
build_sales_report_workflowrepair_board_packet_workflowclose_month_end_workflow
The semantic-workflow profile exists to let one server keep both surfaces:
- a broad MCP-compatible primitive tool surface
- a narrower native planning surface
What The Profile Actually Does
The profile does not change the protocol.
It changes which tools are returned by tools/list.
The server checks the current tool registry and, when workflow-tagged tools are present, returns only that subset for clients asking for profile="semantic-workflow".
That means:
- MCP compatibility remains available
- native ZCP clients get a smaller registry
- model planning sees fewer low-level operations
- token usage usually drops because the model needs fewer tool descriptions and
fewer planning turns
How The Server Marks Workflow Tools
Workflow tools are ordinary tools with workflow metadata.
Typical pattern:
@app.tool(
name="build_sales_report_workflow",
description="Create a sales summary workbook from raw inputs.",
input_schema={
"type": "object",
"properties": {
"workbook_path": {"type": "string"},
"rows": {"type": "array"},
},
"required": ["workbook_path", "rows"],
"additionalProperties": False,
},
output_mode="scalar",
inline_ok=True,
metadata={
"_meta": {
"groups": ["workflow", "reporting"],
"stages": ["build", "verify"],
}
},
)
async def build_sales_report_workflow(workbook_path: str, rows: list[dict]):
...The key part is:
_meta.groupsincludesworkflow
The built-in profile uses that convention as the discovery filter.
Server Configuration
You can expose the profile by convention and make it the native default:
from zcp import FastZCP, ToolExposureConfig, ZCPServerConfig
app = FastZCP(
"Excel Native Server",
default_tool_profile="semantic-workflow",
)
config = ZCPServerConfig(
tool_exposure=ToolExposureConfig(
default_profile="semantic-workflow",
)
)Important fields:
FastZCP(default_tool_profile="semantic-workflow")ToolExposureConfig(default_profile="semantic-workflow")ToolExposureConfig.semantic_groupToolExposureConfig.enforce_call_visibility
The first two define the preferred discovery path. The latter two define how strictly the runtime maps profile visibility to callable tools.
Client Configuration
The explicit client-side form is:
tools = await client.list_tools(profile="semantic-workflow")The convenience wrapper is:
from zcp import SemanticWorkflowProfile
profile = SemanticWorkflowProfile()
tools = await client.list_tools(**profile.as_list_tools_params())Use the explicit form when you are wiring a custom planner. Use the wrapper when you want the built-in native profile object.
Relationship To MCP
semantic-workflow is a ZCP-native discovery contract, not an MCP feature.
That means:
- MCP clients do not need to know about it
- MCP-compatible endpoints can still expose the primitive registry
- native ZCP clients can ask for the workflow subset on the same runtime
So the design is:
- downward compatible with MCP
- more opinionated for native ZCP planning
When You Should Use It
Use semantic-workflow when all of these are true:
- the server exposes both primitive and higher-level workflow tools
- the native client is model-driven
- token efficiency matters
- you want fewer, more semantic planning steps
Do not rely on it when:
- the server only exposes primitive tools
- you need exact low-level control of every operation
- your client is an MCP host that expects the full primitive surface
How It Differs From Simple Group Filters
ZCP also supports direct filtering parameters such as:
groupsexcludeGroupsstages
Those are generic filters.
semantic-workflow is different because it is a named profile with a stable meaning:
- workflow tools first
- native planning path
- smaller registry by default
Use raw group filters when you need one-off selection logic. Use the profile when you want a consistent native discovery contract.
Current Runtime Shape
The current built-in implementation lives in the Python SDK:
The profile name today is:
semantic-workflow
The default semantic group today is:
workflow
Those are conventions, but the server-side config lets you override the group name if you need a different internal taxonomy.
Practical Outcome
In the Excel benchmark suite, this profile is part of the reason native ZCP can use semantic workflow tools instead of exposing only MCP-style primitives.
That is what allows the runtime to preserve MCP compatibility while still reducing planning turns and token cost for native ZCP clients.
For the benchmark context and current published results, see: