Your Agent Transition Can Now Use Any MCP Server. The Net Decides Which One.

Version 2.50.0 gives Agentic-Nets an MCP client. An agent transition can declare external MCP servers directly in its inscription and call their tools. The interesting part is not that agents reached the MCP ecosystem. It is what happens when those calls run inside a Petri net instead of inside a chat window.


The Problem: Reach Without Rules

The Model Context Protocol solved a real problem. Before it, every integration between an AI agent and an external system was bespoke glue. After it, a GitHub server, a Postgres server, a Slack server all speak one protocol, and any client can consume them.

What MCP does not answer is the second question. Not what can this agent reach, but under what rules. In a chat client the answer is usually: whatever the user configured, for as long as the session lives, with no record of which call touched which system, and no way to say “this lane may read issues but must never post one”.

That is acceptable for exploration. It is not acceptable for a process that runs unattended at three in the morning, spends money, and writes to systems other people depend on. Which is exactly what an Agentic-Net is for.


The Idea: The Inscription Is the Allowlist

An agent transition now accepts an action.mcp block. It names the servers this lane may reach, and nothing else in the system can widen that list at runtime.

"action": {
  "type": "agent",
  "role": "rwxh------m",
  "nl": "Triage the issue in the inbox token.",
  "mcp": [{
    "name": "github",
    "url": "https://mcp.example.com/mcp",
    "auth": { "type": "bearer", "credentialKey": "GITHUB_MCP_TOKEN" },
    "allowTools": ["search_issues", "get_file"],
    "timeoutMs": 30000
  }]
}

At the start of every fire the engine connects to each declared server, asks it what tools it has, filters that list through allowTools, and writes the survivors into the agent’s prompt with their real argument schemas. The model does not guess tool names. It reads them.

Then it calls them through one new tool, MCP_CALL, gated by one new capability flag.

One MCP call, four gates it has to passthe same call in a chat client passes none of themTaskp-inboxAgent laneagent • SINGLErole rwxh——mTHE GATES1. capability flag m2. declared server list3. allowTools filter4. vault credentialall four resolved per fireExternal MCPgithub, slack, dbany MCP serverResultp-outEverything is on the recordevent trail carries the tool call, its arguments and its verdictthe credential never appears in the prompt, the token or the logan unreachable server degrades the lane, it does not fail the firethe flag alone reaches nothing: a lane with m and no declared server has no targets

The Eleventh Flag

Agent capabilities in Agentic-Nets read like a file permission string. Ten positional flags existed before this release: read, write, execute, http, logs, user, docker, coordinate, tooling, scripts. MCP is the eleventh, m, and it is deliberately awkward to get.

No shorthand includes it. Not even the all-flags role. You have to write the eleven character positional form, rwxh------m, and mean it. That is not an aesthetic choice. A role string that quietly grew external network reach when someone upgraded would be a security regression, so the upgrade path is: nothing changes unless you change it.

Note also what m is not. It is not h. An agent can be allowed to call its declared MCP servers while remaining unable to make an arbitrary HTTP request. Those are different powers and the system treats them as different powers.


What Refusal Looks Like

A guarantee you have not tried to break is a hope. So each gate was tested against a live server, on a real desktop install, with an agent that was explicitly instructed to violate it. These are the actual replies.

What was attemptedWhat came back
Call a server whose credential was never storedMCP UNAVAILABLE: credential 'MCP_KEY_THAT_WAS_NEVER_STORED' not provided for this fire
Declare servers on a lane whose role lacks mThe agent listed the 51 tools it was actually offered. MCP_CALL was not among them.
Call a tool outside allowToolsBLOCKED: Tool 'readiness' is not in server 'desktop' allowTools: [llm_health]
Call a server that was never declaredUnknown MCP server 'ghost'. Declared servers: [desktop, stub]

The second row is the one worth pausing on. The agent did not try and get rejected. It enumerated its own capabilities and the tool simply was not there. A refusal that happens before the attempt is a stronger guarantee than a refusal after it.

Credentials get the same treatment. They live in the vault, are resolved once per fire, and exist only in memory for the duration of that fire. After the live run we searched the entire event line, the stored inscription, the emitted result tokens and sixty one thousand lines of engine log for the bearer token. It appears in none of them. Publish a net that carries an MCP declaration and the credential reference travels; the secret does not.


Degrade, Do Not Fail

External systems go down. A design that treats every outage as a fire failure produces a net that is offline whenever anything it touches is offline.

So an unreachable server is not an error. It is listed in the agent’s prompt as UNAVAILABLE with the reason, and the fire runs anyway. The agent can work around it, report it, or stop deliberately. A tool that answers with an error returns that error as a structured result the model can read and reason about. An oversized response is bounded before it reaches the prompt: in one test a twenty kilobyte payload came back marked truncated: true with originalLength: 20083, so the agent knew both that it had been cut and how much it was missing.

The failure that is not tolerated is a silent one. During review we found that a failed MCP call was being recorded as a successful tool call, which reset the loop’s failure guards and told the model the call had worked. That is fixed. A semantic failure now produces a failure record, with one deliberate exception: the check is scoped to MCP alone, because elsewhere in the tool surface success: false is a verdict about the thing being inspected rather than a report that the tool broke.


The Part That Closes the Loop

AgenticNetOS has shipped its own MCP server for a while. Any MCP client can use a running instance as working memory and a net workbench. As of this release the platform is also an MCP client.

Which means it can call itself. We built a lane whose role was r---------m: read and MCP, deliberately without the write flag, so the agent’s native net-creation tool was never offered to it. Its only declared server was the instance’s own MCP endpoint, with allowTools pinned to a single entry. Then we asked it to create a net.

It did. Before the fire the model held three nets. After it, four. The new one had a real structure inside it, and the event trail shows exactly one tool call: MCP_CALL with create_net, no native write anywhere. The only path from that agent to a durable change ran out through the protocol and back in through the front door.

A net that builds a net, through the protocolthe agent had read and MCP only: no write flag, so the native path did not existINSIDE THE ENGINEAgent laner———mCREATE_NETnot offeredno w flagthe only write path leaves the processMCP_CALL create_netOwn MCP serverallowTools: [create_net]A new net exists3 nets before, 4 afterverified server side, not claimedthe platform is now both an MCP server and an MCP client, so it can use itself as a tool

This is a small demonstration of a large property. A net can now treat another AgenticNetOS instance as a tool. Teams can hand each other capabilities across a boundary that is declared, credentialed and audited, instead of by sharing a database.


Real Numbers From the Verification Run

  • 13 live probes across three rounds against a real MCP server, not a mock
  • 8 seconds for the first end to end call: task token in, protocol handshake, tool call, summary token out
  • 2 iterations, 1 tool call for that fire. The agent read the catalog from its prompt and called the right thing first time
  • 0 occurrences of the bearer token across a 124 KB event line, the stored inscription, the result tokens and 61,000 log lines
  • 4 refusals out of 4 attempts to break the gates, each with a message naming what was wrong
  • 1,731 engine tests green, including a protocol client exercised against a server that answers in server sent events, issues session ids and demands its own bearer

Also in This Release

The engine stopped asking the wrong question

Every two seconds the orchestrator asked storage a single bit of a question: has anything changed. If the answer was yes it re-examined every running transition and probed every one of their inputs. On a busy model that is hundreds of calls because one token moved.

Storage now answers a better question: which places changed, by name. The orchestrator evaluates only the lanes that consume those places. Everything uncertain, an older storage node, a restart, a cursor that has fallen out of the window, an unfamiliar change, falls back to exactly the old full scan. The optimisation can only ever be cheaper, never less correct.

A Developer you can install

There is a new starter persona: a Developer with a charter, an inbox, a journal, memory that survives restarts, and a bundled tool net of its own so it can actually run checks rather than describe them. It answers questions, works a task, records what it learned, and writes its milestones into the Protocol application when one is installed. It is the first shipped template that carries its own tooling.


Try It Yourself

Store the credential against the transition, then declare the server. The secret goes to the vault, never into the net.

curl -X POST "http://localhost:8082/api/transitions/t-triage/credentials?modelId=my-model" \
  -H "Content-Type: application/json" \
  -d '{"GITHUB_MCP_TOKEN":"'"$TOKEN"'"}'

Then give the lane the flag and the declaration, and ask your agent to use it. If the server is down, the lane still runs and tells you so. If you name a tool outside the allowlist, it is refused. If you forget the flag, validation warns you before the first fire rather than after it.

Everything is on Docker Hub and GitHub as 2.50.0, and the desktop build installs the whole stack without Docker or an API key.


MCP answers what an agent can reach. A net answers under what rules. The combination is what makes an integration something you can leave running.

Leave a Reply

Your email address will not be published. Required fields are marked *