Beyond the Protocol: Applying API Engineering Practices to MCP Servers
Model Context Protocol (MCP) has become an important integration surface for AI agents. It gives AI applications a standardized way to connect to tools, data sources, and enterprise systems.
For developers who already use MCP servers from an AI assistant or IDE, the experience can feel straightforward: configure a server, connect your favorite coding assistant, and let the agent discover the available tools. That runtime experience is one of the strengths of MCP.
But when you start building MCP servers as enterprise developer products, another set of questions quickly appears:
- How do we document them consistently?
- How do we review them before publication?
- How do we compare one release with the next?
- How do we detect major changes across releases?
- How do we keep engineering teams, documentation teams, and developer-facing portals aligned?
- How do we ensure consistency within a product and across products?
Those questions felt familiar to us. They are the same kinds of questions API teams have been working on for years.
MCP solves the runtime integration problem
MCP was introduced by Anthropic in late 2024 as an open standard for connecting AI-powered applications with external tools and data sources. Since then, the protocol has evolved quickly and is now supported by a growing ecosystem of clients, SDKs, servers, and community projects.
The protocol defines the runtime interaction model: how a client connects to a server, how it discovers capabilities, how tools are exposed, and how messages are exchanged. This dynamic discovery model is well suited to agents. An AI client can connect to a server, ask what it can do, and decide how to use the available tools.
That is powerful.
However, in enterprise settings, runtime discovery alone is not enough. Runtime discovery works after you’ve already decided to trust the MCP server you’re connecting to. In contrast, that decision has to be made before runtime, by a human, and it has to be repeatable for every audit that follows.
A developer portal cannot wait until runtime to know what a server exposes. Documentation pipelines need structured input. Governance processes need inventory metadata. Release processes need versioned artifacts. Review processes need something that can be linted, compared, approved, and published.
That is the gap the MCP specification does not close as of today. Portals, engineering and documentation pipelines, and governance processes are not legacy scaffolding. They are the static record that makes runtime discovery safe to rely on.
What API engineering taught us
At Cisco DevNet, we have spent years applying engineering practices to APIs. Our API guidelines cover areas such as design, documentation, versioning, naming conventions, support, lifecycle, and developer experience. For REST APIs, OpenAPI plays a central role in that ecosystem.
An OpenAPI document is not the API implementation. It describes the API’s technical contract. It offers a stable, machine-readable description of what the API exposes to humans and tools. From that description, teams can generate documentation, run linting rules, detect changes, build catalogs, support reviews, and automate parts of the publication process.
That pattern has become natural for API teams:
- the implementation exposes the runtime behavior;
- the OpenAPI document describes the contract;
- the surrounding tools support our internal documentation, testing, lifecycle management and governance workflows.
As we saw official MCP servers starting internally, we asked ourselves a simple question: Could we apply the same engineering discipline to MCP servers?
Not by forcing MCP to become REST. MCP is different, and it should remain different. But the need for consistency, documentation, versioning, and developer experience is very similar.
The missing artifact: a versioned description
Most MCP servers today can describe themselves dynamically when a client connects. Many projects also include a README, often generated from code or written manually, to explain installation steps and available tools.
That is useful, but it does not fully solve the enterprise lifecycle problem. We needed a structured artifact that could answer a precise question: What does this specific version of this MCP server expose?
That includes capabilities such as:
- supported transports;
- tools;
- prompts;
- resources;
- input and output schemas;
- authentication expectations;
- server metadata;
- version information;
- documentation and support information.
This is where we started exploring a format we initially called an MCP dump, which evolved into the MCP Description format.
The idea is intentionally familiar: a portable, machine-readable description of an MCP server, inspired by the role OpenAPI plays for REST APIs.
MCP Description does not replace the MCP protocol or dynamic discovery. Instead, it complements them.
Dynamic discovery is what an agent uses at runtime. A static description is what internal engineering, documentation, governance, and developer experience teams can use before and after runtime.
A familiar shape for API developers
We deliberately kept the format close to concepts that API developers already know.
A simplified MCP Description might look like this:
mcpdesc: 0.7.0
info:
title: Search MCP Server
version: 1.2.0
description: MCP server exposing search tools for AI assistants.
server:
name: Search
type: remote
transports:
- type: streamable-http
url: https://api.example.com/mcp
tools:
- name: search
title: Search content
description: Execute a search query and return matching results.
inputSchema:
type: object
required:
- query
properties:
query:
type: string
description: Search query string.
outputSchema:
type: object
properties:
results:
type: array
description: List of matching results.
items:
type: object
properties:
title:
type: string
snippet:
type: string
url:
type: string
The MCP Description document gives teams a stable representation of what the server exposes. It can be stored in source control, reviewed in pull requests, compared across releases, and used as input for tooling.
For developers familiar with OpenAPI, this should feel natural.
The goal is not to invent a completely new way of working, but to reuse proven engineering practices where they make sense.
From description to lifecycle
Once we had internally standardized on a description format, a larger toolchain became possible.
For example, if we can generate or capture an MCP Description for version 1.0.0 of a server, and another Description for version 1.1.0, we can compare them. That comparison can tell us:
- which tools were added;
- which tools were removed;
- which schemas changed;
- whether a change is potentially breaking;
- whether the version number should be reconsidered;
- what should appear in the changelog.
This is the same lifecycle thinking API teams already apply to REST APIs.
A server is not just “available” or “not available.” It evolves. Each release may add, change, or remove capabilities, and those changes flow downstream to the AI clients, documentation, and developers who depend on the server.
With a static description, we can also apply quality rules:
- Are tool names consistent?
- Are descriptions clear enough for both humans and agents?
- Are required parameters documented?
- Are schemas precise?
- Are authentication requirements explicit?
- Are lifecycle and support expectations visible?
This is especially important for MCP because tool descriptions often end up being consumed by LLMs. Vague or inconsistent descriptions can affect how agents select and use the tools exposed by MCP servers.
Tooling that emerged from the workflow
As we explored this approach internally, we built tools around the MCP Description format.
One of those tools is mcpcontract, a CLI that can connect to a live MCP server and dump its capabilities into an MCP Description document. Once the Description exists, the same toolchain can compare releases, detect breaking changes, generate changelogs, and support documentation generation.
Figure 1 shows the workflow from a live MCP server to a versioned MCP Description artifact:
Live MCP server
│
▼
`mcpcontract` dump
│
▼
MCP Description
│
├── linting and review
├── diff and breaking-change detection
├── changelog generation
├── documentation generation
└── inventory and publication workflows
This is similar to how our internal API teams already work with OpenAPI.
The important point is that the MCP Description becomes an engineering artifact. It can move across teams, be reviewed, versioned, and reused.
For us, that created a practical bridge between engineering teams building MCP servers and DevNet teams responsible for developer-facing documentation.
Integrating MCP servers into API inventory practices
In addition, we extended our internal API inventory to support records for MCP server programs.
The inventory captures structural information about an MCP server and its program: ownership, contacts, release status, lifecycle, server type, supported transports, documentation status, review outcomes, and related publication metadata.
The inventory captures how the server is managed as part of a broader engineering and publication lifecycle, while MCP Descriptions capture the exact capabilities exposed by each release of an MCP server.
Together, these artifacts help connect engineering work with the final developer experience on developer.cisco.com.
Documentation generation for Cisco MCP servers
With this approach, we progressively turned to our standardized workflow for MCP documentation publishing.
Versioned MCP Descriptions are generated by engineering. Then a diff tool identifies the changes and generates an MCP changelog. An AI assistant then produces a markdown document that is ready for review and publishing at developer.cisco.com.
Figure 2 shows the documentation-generation branch of the workflow in more detail:
MCP Description
(versioned artifact)
│
▼
Diff vs. previous version
│
▼
Changelog generation
│
▼
AI-assisted documentation generation
│
▼
Review and publishing at developer.cisco.com
Sharing the tools with the community
We’re excited to share the toolset we use internally with the broader developer community.
Explore the MCP Toolkit repositories at github.com/cisco-open including:
- the mcptoolkit-contract: a CLI useful for dumping the capabilities of an existing MCP server, generating documentation, and producing changelogs;
- the mcptoolkit-editor: similar in spirit to Swagger Editor, it lets you preview, update, and export existing MCP Description documents.
If you already operate an MCP server, mcptoolkit-contract is certainly a practical place to start. You can connect it to a server, generate a Description, and inspect what the server exposes as a versioned artifact.
Closing thoughts
MCP is still a young ecosystem, and it is moving quickly. As more teams build MCP servers, the challenge will not only be whether a server works at runtime, but whether it can be documented, reviewed, versioned, tested, governed, and supported over time.
MCP Description is the format we have explored to solve practical engineering needs around documentation, lifecycle, and governance. It works for our use cases, and we believe similar needs may appear in other organizations as MCP adoption grows.
The open question is whether the MCP ecosystem needs a common static format to describe MCP servers. Our experience at DevNet says yes, and we are happy to contribute our internal toolset and learnings.