keepcalculator

06 Numbers and Powers

Stateful vs Stateless MCP: Zsh Harness Facts

Card No. 06·59576 · Updated · Standard formula, shown below

The core difference for a reliable zsh harness is that a stateless MCP server treats every tool call as an independent request with no memory of previous calls, while a stateful MCP server maintains context (variables, sessions, or data) across calls. For a zsh harness, you should default to stateless unless your tools genuinely need to remember something between calls, because stateless servers are simpler to debug, restart cleanly, and scale horizontally.

Background: What MCP and a Zsh Harness Are

MCP (Model Context Protocol) is an open standard that lets AI assistants (like Claude or a local LLM) call external tools through a JSON-RPC 2.0 interface. A “harness” in this context is the shell script or wrapper that connects your zsh environment to an MCP server—it handles authentication, routing requests, and formatting responses. Zsh is a popular Unix shell with advanced scripting capabilities, so a zsh harness often means a lightweight client that runs inside your terminal, possibly using tools like mcp CLI or a custom script using curl to talk to an MCP endpoint.

The protocol defines two main types of servers: stateless and stateful. The distinction is not just a design choice; it affects reliability, testing, and how you handle failures in your harness.

How Stateless MCP Servers Work

In a stateless MCP server, each request (e.g., tools/call) contains all the information needed to execute the tool. The server does not store any session data between requests. For example, if you have a tool that calculates the hash of a file, the request includes the file path, and the server returns the hash. The next call for a different file is completely independent.

Benefits for a zsh harness:

  • Simpler error recovery: If a request fails, you can retry it without worrying about corrupted state.
  • Easier to test: You can replay a single request and get the same result every time, assuming the underlying data hasn’t changed.
  • Stateless servers can be restarted at any time without losing any important information, because there is none to lose.
  • Scaling: You can run multiple instances behind a load balancer, since any instance can handle any request.

In practice, most MCP tools are naturally stateless: file operations, web searches, math calculations, or data transformations. The MCP specification itself encourages statelessness by not providing a built-in session mechanism—state must be implemented by the server using external storage (like a database or file) or by the client sending a state token.

How Stateful MCP Servers Work

A stateful MCP server maintains context between calls. This could be as simple as storing a variable in memory (e.g., a counter) or as complex as managing a multi-turn conversation. The server might use a session ID that the client sends with each request, or it might rely on a shared database to persist state across restarts.

When do you need state in a zsh harness?

  • Multi-step workflows: For example, a tool that first authenticates and then performs an action using that authentication token.
  • Accumulating results: A tool that aggregates data over several calls, like a progress tracker.
  • Contextual tools: A tool that remembers previous user preferences or conversation history.

The main reliability concern is that state can become stale or inconsistent. If your harness crashes, the server might still hold state that is no longer valid. For example, if a stateful server keeps a file handle open and your zsh script dies, the server might not release that handle until a timeout, causing resource leaks.

Choosing the Right Type for Your Zsh Harness

When designing a reliable zsh harness, ask yourself: “Does my tool need to remember anything between calls?” If the answer is no, go stateless. If you need state, consider these factors:

  1. Identify the state: What exactly needs to be remembered? Is it a session token, a user preference, or a temporary file path?
  2. Where to store it: In-memory is fast but lost on restart. A file or database is persistent but adds complexity.
  3. How to pass it: The MCP spec allows you to include a state field in requests. You can store that state in a file in your zsh environment and send it with each call.
  4. Test failure modes: What happens if the server restarts? Can your harness recover by re-initializing the state?

A common pattern is to keep the MCP server stateless and push the state to the client (your zsh script). For instance, if you need to maintain a list of items, store them in a zsh array and pass the entire list with each tool call. This keeps the server simple and makes your harness the single source of truth.

Common Problems and Misconceptions

Misconception: “Stateless means no memory at all.” Actually, stateless servers can still read from external storage (like a database) to get data. The key is that the server does not keep any in-memory state between requests. So a tool can fetch a user’s profile from a database on every call—that’s still stateless from the server’s perspective.

Problem: Stateful server crashes. If your stateful MCP server crashes, all in-memory state is lost. Your harness must handle this gracefully. A good practice is to have the server persist state to disk after every mutation, or to design your tools so that they can rebuild state from scratch.

Problem: Race conditions. With stateful servers, concurrent calls can interfere. For example, if two zsh processes call a tool that increments a counter, you might get inconsistent results. Stateless servers avoid this because each call is independent.

Problem: Debugging difficulty. Stateful servers are harder to debug because you can’t reproduce a bug by sending a single request—you need to reproduce the entire sequence of calls that led to the error. Stateless servers make debugging much easier.

Cost and Performance Considerations

Stateless servers are generally cheaper to operate in a cloud environment because they scale horizontally—you can spin up more instances behind a load balancer. Stateful servers often require sticky sessions or a shared database, which adds infrastructure cost.

In terms of performance, stateless servers may have higher latency per request because they need to fetch state from external storage each time. However, for most zsh harness use cases (like file manipulation or simple data processing), this overhead is negligible. If you have a high-frequency tool, you might want to use a stateful server with in-memory caching, but then you must handle the reliability trade-offs.

For a local zsh harness, cost is usually not a big factor—you’re running on your own machine. But if you’re building a service that many users access, stateless is often the more cost-effective choice.

Safety and Security Implications

Stateful servers can introduce security risks if not handled carefully. For example, if you store authentication tokens in memory, a memory leak could expose them. Also, if you use a session ID, an attacker who steals that ID can impersonate the user. Stateless servers reduce this risk because there is no session to hijack—each request must be fully authenticated.

However, stateless servers can be vulnerable to replay attacks if you don’t include a nonce or timestamp in the request. In your zsh harness, always use HTTPS (or SSH tunneling) to protect data in transit. Also, be careful about logging: don’t log sensitive data like tokens or passwords, regardless of server type.

Another safety consideration is resource usage. A stateful server that accumulates data over time can run out of memory. Your harness should monitor memory usage and restart the server if it grows too large. Stateless servers are less prone to this because they don’t hold anything between requests.

Alternatives and Hybrid Approaches

You don’t have to choose one extreme. A hybrid approach is common: keep the MCP server stateless, but use a separate state store (like a SQLite database or a file) that the server reads and writes on each call. This gives you the reliability of stateless (the server can be restarted without losing data) and the convenience of state (data persists).

Another alternative is to use MCP’s built-in resources feature to expose state as a resource that the client can read and write. For example, a tool could expose a resource that contains the current session state, and the zsh harness can update it after each call.

If you need stateful behavior but want reliability, consider using a well-known state management pattern like event sourcing or outbox pattern. These ensure that state changes are recorded durably before they are applied, so you can recover from crashes.

Finally, for very complex stateful workflows, you might bypass MCP entirely and write a custom script that directly manages state in zsh, calling external tools via subprocesses. This gives you full control but sacrifices the standardization of MCP.

Frequently Asked Questions

Q: Can a stateless MCP server still use a database?
A: Yes, absolutely. A stateless server can read from and write to a database on every request. The key is that it doesn’t keep any in-memory state between requests. The database is the source of truth, and the server just fetches what it needs each time.

Q: How do I store state in a zsh harness without a stateful server?
A: You can store state in a file (e.g., a JSON file) or in a zsh associative array, and pass that state as a parameter to each tool call. For example, if you have a tool that appends to a list, you can read the list from a file, append the new item, and write it back. The server just receives the full list each time.

Q: What happens if a stateful MCP server crashes?
A: Any in-memory state is lost. If the server persists state to disk, it can recover on restart. Otherwise, your harness must detect the crash and re-initialize the state. It’s a good practice to have the server persist state after every mutation to minimize data loss.

Q: Is MCP stateless by default?
A: The MCP specification does not mandate either. It provides a state field in requests that can be used to pass state, but it’s up to the server implementation to use it. Many MCP servers are stateless because they are simple to implement and align with RESTful principles.

Q: Can I use a stateful MCP server with a load balancer?
A: Yes, but you need sticky sessions (so that a client always hits the same server) or a shared external state store (like Redis). Otherwise, different servers will have different states, leading to inconsistency. Stateless servers are easier to load balance because any server can handle any request.

Q: What is the best practice for a reliable zsh harness?
A: Start with a stateless MCP server and push all state to the client (your zsh script). This gives you maximum reliability and ease of debugging. If you absolutely need server-side state, use a hybrid approach with a durable external store, and ensure your harness can recover from server restarts.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →