How to Implement a Plugin for MCP#
Overview#
Model Context Protocol (MCP) is an open protocol that standardizes how applications provide context to LLMs. MCP servers allow you to connect your assistant to external tools and services (such as web APIs, search engines, or custom data sources) without writing custom adapters for each integration.
In this guide, you will learn how to:
Create a simple MCP Server (in a separate Python file)
Connect an Agent/Flow to an MCP Server
Important
This guide will show you how to integrate with WayFlow, which supports MCP Tools. Note that the steps shown in this guide can be applied on any runtime executor that supports MCP.
Prerequisite: Setup a simple MCP Server#
First, let’s see how to create and start a simple MCP server exposing a couple of tools.
Note
You should copy the following server code and run it in a separate Python process.
from mcp.server.fastmcp import FastMCP
PAYSLIPS = [
{
"Amount": 7612,
"Currency": "USD",
"PeriodStartDate": "2025/05/15",
"PeriodEndDate": "2025/06/15",
"PaymentDate": "",
"DocumentId": 2,
"PersonId": 2,
},
{
"Amount": 5000,
"Currency": "CHF",
"PeriodStartDate": "2024/05/01",
"PeriodEndDate": "2024/06/01",
"PaymentDate": "2024/05/15",
"DocumentId": 1,
"PersonId": 1,
},
{
"Amount": 10000,
"Currency": "EUR",
"PeriodStartDate": "2025/06/15",
"PeriodEndDate": "2025/10/15",
"PaymentDate": "",
"DocumentsId": 3,
"PersonId": 3,
},
]
def create_server(host: str, port: int):
"""Create and configure the MCP server"""
server = FastMCP(
name="Example MCP Server",
instructions="A MCP Server.",
host=host,
port=port,
)
@server.tool(description="Return session details for the current user")
def get_user_session():
print("called get_user_session")
return {
"PersonId": "1",
"Username": "Bob.b",
"DisplayName": "Bob B",
}
@server.tool(description="Return payslip details for a given PersonId")
def get_payslips(PersonId: int):
return [payslip for payslip in PAYSLIPS if payslip["PersonId"] == int(PersonId)]
return server
def start_mcp_server() -> str:
host: str = "localhost"
port: int = 8080
server = create_server(host=host, port=port)
server.run(transport="sse")
return f"http://{host}:{port}/sse"
# mcp_server_url = start_mcp_server() # <--- Move the code above to a separate file then uncomment
This MCP server exposes two example tools: get_user_session and get_payslips.
Once started, it will be available at (by default): http://localhost:8080/sse.
Note
When choosing a transport for MCP:
Use Stdio when launching and communicating with an MCP server as a local subprocess on the same machine as the client.
Use Streamable HTTP when connecting to a remote MCP server.
For more information, visit https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#stdio
Important
This guide does not aim at explaining how to make secure MCP servers, but instead mainly aims at showing how to connect to one. You should ensure that your MCP server configurations are secure, and only connect to trusted external MCP servers.
Connecting an Agent to the MCP Server#
You can now connect an agent to this running MCP server.
Add imports and configure an LLM#
Start by importing the necessary packages for this guide:
from pyagentspec.agent import Agent
from pyagentspec.flows.edges import ControlFlowEdge, DataFlowEdge
from pyagentspec.flows.flow import Flow
from pyagentspec.flows.nodes import EndNode, StartNode, ToolNode
from pyagentspec.mcp import MCPTool, MCPToolBox, SSETransport
from pyagentspec.property import StringProperty
mcp_server_url = f"http://localhost:8080/sse" # change to your own URL
Agent Spec supports several LLM API providers. Select an LLM from the options below:
from pyagentspec.llms import OciGenAiConfig
from pyagentspec.llms.ociclientconfig import OciClientConfigWithApiKey
client_config = OciClientConfigWithApiKey(
name="Oci Client Config",
service_endpoint="https://url-to-service-endpoint.com",
auth_profile="DEFAULT",
auth_file_location="~/.oci/config"
)
llm_config = OciGenAiConfig(
name="Oci GenAI Config",
model_id="provider.model-id",
compartment_id="compartment-id",
client_config=client_config,
)
from pyagentspec.llms import VllmConfig
llm_config = VllmConfig(
name="Llama 3.1 8B instruct",
url="VLLM_URL",
model_id="model-id",
)
from pyagentspec.llms import OllamaConfig
llm_config = OllamaConfig(
name="Ollama Config",
model_id="model-id",
)
Build the Agent#
Agents can connect to MCP tools by either using a MCPToolBox or a MCPTool.
Here you will use the toolbox (see the section on Flows to see how to use the MCPTool).
mcp_client = SSETransport(name="MCP Client", url=mcp_server_url)
payslip_mcptoolbox = MCPToolBox(
name="Payslip MCP ToolBox",
client_transport=mcp_client
)
agent = Agent(
name="Agent using MCP",
llm_config=llm_config,
system_prompt="Use tools at your disposal to assist the user.",
toolboxes=[payslip_mcptoolbox],
)
Specify the transport to use to handle the connection to the server and create the toolbox. You can then equip an agent with the toolbox similarly to tools.
Agent Serialization#
You can export the agent configuration using the AgentSpecSerializer.
from pyagentspec.serialization import AgentSpecSerializer
serialized_assistant = AgentSpecSerializer().to_json(agent)
Here is what the Agent Spec representation will look like ↓
Click here to see the assistant configuration.
{
"component_type": "Agent",
"id": "420c4c4a-c6ae-48de-a7b3-6e3e7c314149",
"name": "Agent using MCP",
"description": null,
"metadata": {},
"inputs": [],
"outputs": [],
"llm_config": {
"component_type": "VllmConfig",
"id": "d4436c2b-e286-44cd-b89b-0ebaefbe3ee7",
"name": "llm",
"description": null,
"metadata": {},
"default_generation_parameters": null,
"url": "url",
"model_id": "model_id"
},
"system_prompt": "Use tools at your disposal to assist the user.",
"tools": [],
"toolboxes": [
{
"component_type": "MCPToolBox",
"id": "f263d71e-4e3e-4bc5-ba86-8ec69634d925",
"name": "Payslip MCP ToolBox",
"description": null,
"metadata": {},
"client_transport": {
"component_type": "SSETransport",
"id": "8e723672-b7f7-4698-bfe0-c66ab1525043",
"name": "MCP Client",
"description": null,
"metadata": {},
"session_parameters": {
"read_timeout_seconds": 60.0
},
"url": "http://localhost:8080/sse",
"headers": null
},
"tool_filter": null
}
],
"human_in_the_loop": true,
"agentspec_version": "25.4.2"
}
# Copyright © 2025 Oracle and/or its affiliates.
#
# This software is under the Apache License 2.0
# (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License
# (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option.
component_type: Agent
id: 3e9809e9-dae7-4bab-b045-2e741bab7d31
name: Agent using MCP
description: null
metadata: {}
inputs: []
outputs: []
llm_config:
component_type: VllmConfig
id: ff9ace24-03d4-43fa-a39c-1e04f69792b4
name: llm
description: null
metadata: {}
default_generation_parameters: null
url: url
model_id: model_id
system_prompt: Use tools at your disposal to assist the user.
tools: []
toolboxes:
- component_type: MCPToolBox
id: 37ac0458-df19-4c01-9917-22e0d4e6cf77
name: Payslip MCP ToolBox
description: null
metadata: {}
client_transport:
component_type: SSETransport
id: 38355b73-9a12-4f25-8a91-b341d7b1688c
name: MCP Client
description: null
metadata: {}
session_parameters:
read_timeout_seconds: 60.0
url: http://localhost:8080/sse
headers: null
tool_filter: null
human_in_the_loop: true
agentspec_version: 25.4.2
Connecting a Flow to the MCP Server#
You can also use MCP tools in a Flow by using the MCPTool in a ToolNode.
Build the Flow#
Create the flow using the MCP tool:
start_node = StartNode(name="start")
user_info_property = StringProperty(title="user_info")
get_user_session_tool = MCPTool(
client_transport=mcp_client,
name="get_user_session",
description="Return session details for the current user",
outputs=[user_info_property]
)
mcptool_node = ToolNode(
name="mcp_tool",
tool=get_user_session_tool,
)
end_node = EndNode(name="end", outputs=[user_info_property])
flow = Flow(
name="Flow using MCP",
start_node=start_node,
nodes=[start_node, mcptool_node, end_node],
control_flow_connections=[
ControlFlowEdge(
name="start->mcptool",
from_node=start_node,
to_node=mcptool_node
),
ControlFlowEdge(
name="mcptool->end",
from_node=mcptool_node,
to_node=end_node
),
],
data_flow_connections=[
DataFlowEdge(
name="user_info",
source_node=mcptool_node,
source_output="user_info",
destination_node=end_node,
destination_input="user_info",
)
]
)
Similarly to when equipping Agents with MCP Tools, you should specify the client transport as with the MCP ToolBox, as well as the name of the specific tool you want to use.
Flow Serialization#
You can export the flow configuration using the AgentSpecSerializer.
from pyagentspec.serialization import AgentSpecSerializer
serialized_assistant = AgentSpecSerializer().to_json(flow)
Here is what the Agent Spec representation will look like ↓
Click here to see the assistant configuration.
{
"component_type": "Flow",
"id": "2849ac60-7154-48a8-a4ef-433ffe85b5ef",
"name": "Flow using MCP",
"description": null,
"metadata": {},
"inputs": [],
"outputs": [
{
"title": "user_info",
"type": "string"
}
],
"start_node": {
"$component_ref": "1949f7b0-782e-4856-bfe9-cc58964c175a"
},
"nodes": [
{
"$component_ref": "1949f7b0-782e-4856-bfe9-cc58964c175a"
},
{
"$component_ref": "c4be5127-81a6-4627-8525-bac37214d547"
},
{
"$component_ref": "ab20a178-5658-4c92-bd9a-ce87dd9a1ecd"
}
],
"control_flow_connections": [
{
"component_type": "ControlFlowEdge",
"id": "d4c33b22-4de1-4e36-bc7f-6e48a7dccfb0",
"name": "start->mcptool",
"description": null,
"metadata": {},
"from_node": {
"$component_ref": "1949f7b0-782e-4856-bfe9-cc58964c175a"
},
"from_branch": null,
"to_node": {
"$component_ref": "c4be5127-81a6-4627-8525-bac37214d547"
}
},
{
"component_type": "ControlFlowEdge",
"id": "c6fde850-2bff-45f4-b44b-6cf1c85805c1",
"name": "mcptool->end",
"description": null,
"metadata": {},
"from_node": {
"$component_ref": "c4be5127-81a6-4627-8525-bac37214d547"
},
"from_branch": null,
"to_node": {
"$component_ref": "ab20a178-5658-4c92-bd9a-ce87dd9a1ecd"
}
}
],
"data_flow_connections": [
{
"component_type": "DataFlowEdge",
"id": "62ee2e58-19e1-403d-b6ca-eeabb753c20a",
"name": "user_info",
"description": null,
"metadata": {},
"source_node": {
"$component_ref": "c4be5127-81a6-4627-8525-bac37214d547"
},
"source_output": "user_info",
"destination_node": {
"$component_ref": "ab20a178-5658-4c92-bd9a-ce87dd9a1ecd"
},
"destination_input": "user_info"
}
],
"$referenced_components": {
"c4be5127-81a6-4627-8525-bac37214d547": {
"component_type": "ToolNode",
"id": "c4be5127-81a6-4627-8525-bac37214d547",
"name": "mcp_tool",
"description": null,
"metadata": {},
"inputs": [],
"outputs": [
{
"title": "user_info",
"type": "string"
}
],
"branches": [
"next"
],
"tool": {
"component_type": "MCPTool",
"id": "f1730e08-491b-4348-96e6-8fb18b0db618",
"name": "get_user_session",
"description": "Return session details for the current user",
"metadata": {},
"inputs": [],
"outputs": [
{
"title": "user_info",
"type": "string"
}
],
"client_transport": {
"component_type": "SSETransport",
"id": "96cda25c-5b3e-43cf-97bd-2d1feca83473",
"name": "MCP Client",
"description": null,
"metadata": {},
"session_parameters": {
"read_timeout_seconds": 60
},
"url": "http://localhost:8080/sse",
"headers": null
}
}
},
"ab20a178-5658-4c92-bd9a-ce87dd9a1ecd": {
"component_type": "EndNode",
"id": "ab20a178-5658-4c92-bd9a-ce87dd9a1ecd",
"name": "end",
"description": null,
"metadata": {},
"inputs": [
{
"title": "user_info",
"type": "string"
}
],
"outputs": [
{
"title": "user_info",
"type": "string"
}
],
"branches": [],
"branch_name": "next"
},
"1949f7b0-782e-4856-bfe9-cc58964c175a": {
"component_type": "StartNode",
"id": "1949f7b0-782e-4856-bfe9-cc58964c175a",
"name": "start",
"description": null,
"metadata": {},
"inputs": [],
"outputs": [],
"branches": [
"next"
]
}
},
"agentspec_version": "25.4.1"
}
# Copyright © 2025 Oracle and/or its affiliates.
#
# This software is under the Apache License 2.0
# (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License
# (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option.
component_type: Flow
id: baafbae6-c33a-4c1e-afa2-3fd9fccd0b87
name: Flow using MCP
description: null
metadata: {}
inputs: []
outputs:
- title: user_info
type: string
start_node:
$component_ref: bd3c98eb-68ba-4a06-808d-49f0604d7d7e
nodes:
- $component_ref: bd3c98eb-68ba-4a06-808d-49f0604d7d7e
- $component_ref: 4d5d3dd3-e826-41ec-bd19-1f41f61e07dc
- $component_ref: 605773b7-2573-4a4f-8bbe-be03b1760cb6
control_flow_connections:
- component_type: ControlFlowEdge
id: 84c3460e-0940-4e90-a2dc-fab9e7c84a52
name: start->mcptool
description: null
metadata: {}
from_node:
$component_ref: bd3c98eb-68ba-4a06-808d-49f0604d7d7e
from_branch: null
to_node:
$component_ref: 4d5d3dd3-e826-41ec-bd19-1f41f61e07dc
- component_type: ControlFlowEdge
id: 7afbd6be-8644-4a6a-b351-509be10580ab
name: mcptool->end
description: null
metadata: {}
from_node:
$component_ref: 4d5d3dd3-e826-41ec-bd19-1f41f61e07dc
from_branch: null
to_node:
$component_ref: 605773b7-2573-4a4f-8bbe-be03b1760cb6
data_flow_connections:
- component_type: DataFlowEdge
id: 4275b1f6-a79e-4004-97b6-f00c9935e878
name: user_info
description: null
metadata: {}
source_node:
$component_ref: 4d5d3dd3-e826-41ec-bd19-1f41f61e07dc
source_output: user_info
destination_node:
$component_ref: 605773b7-2573-4a4f-8bbe-be03b1760cb6
destination_input: user_info
$referenced_components:
bd3c98eb-68ba-4a06-808d-49f0604d7d7e:
component_type: StartNode
id: bd3c98eb-68ba-4a06-808d-49f0604d7d7e
name: start
description: null
metadata: {}
inputs: []
outputs: []
branches:
- next
4d5d3dd3-e826-41ec-bd19-1f41f61e07dc:
component_type: ToolNode
id: 4d5d3dd3-e826-41ec-bd19-1f41f61e07dc
name: mcp_tool
description: null
metadata: {}
inputs: []
outputs:
- title: user_info
type: string
branches:
- next
tool:
component_type: MCPTool
id: a94d225e-b15f-4fd5-988f-3587f0e31aab
name: get_user_session
description: Return session details for the current user
metadata: {}
inputs: []
outputs:
- title: user_info
type: string
client_transport:
component_type: SSETransport
id: 2f098c44-854d-4ae6-9642-e50f6b0ac595
name: MCP Client
description: null
metadata: {}
session_parameters:
read_timeout_seconds: 60
url: http://localhost:8080/sse
headers: null
605773b7-2573-4a4f-8bbe-be03b1760cb6:
component_type: EndNode
id: 605773b7-2573-4a4f-8bbe-be03b1760cb6
name: end
description: null
metadata: {}
inputs:
- title: user_info
type: string
outputs:
- title: user_info
type: string
branches: []
branch_name: next
agentspec_version: 25.4.1
Next steps#
In this guide, you learned how to connect MCP Tools to Agent Spec Flows and Agents.
Having learned how to configure agent instructions, you may now proceed to: