DEV Community

Rumblingb
Rumblingb

Posted on

We Fixed All Our MCP Servers: Here's What Broke and How

Last week, we did something we should have done months ago: a full QA audit of our MCP server portfolio. We maintain a collection of Model Context Protocol servers that power AgentPay — an AI-native payments platform built on the MCP standard. The result? We found broken imports, missing asyncio patterns, and 31 dead Stripe links. Here's the full story.

The Scope: 5 MCP Servers

Our QA pass covered five core MCP servers:

  1. mcp-server-stripe — Payment processing via Stripe
  2. mcp-server-supabase — Database and auth operations
  3. mcp-server-cloudflare — Edge functions and infrastructure
  4. mcp-server-search — Web and documentation search
  5. mcp-server-filesystem — File management

Each server had been built at different times, with different SDK versions, by different contributors. That was the root cause.

The Audit Approach

We used a two-pronged audit strategy:

1. AST Parsing

We ran Python's ast module across every server to statically analyze:

  • Import statements (looking for ModuleNotFoundError candidates)
  • Function signatures (checking for async def vs def mismatches)
  • Decorator patterns (MCP tools decorated with @mcp.tool() but not awaiting properly)

2. Runtime Checks

We spun up each server in a sandboxed environment and tested every tool endpoint. This caught:

  • Import errors that only surface at runtime (circular imports, conditional imports with wrong fallbacks)
  • Stripe API links returning 403 errors
  • Event loop issues with asyncio.run() called inside async contexts

The Specific Fixes

Import Paths (Found in 3 servers)

The MCP SDK had undergone a major version bump from 0.4.x to 1.0.x, and import paths changed. The old from mcp.server import Server became from mcp import Server. Three servers still used the old paths.

Fix: Updated all import paths to match the SDK v1.0 convention. We also added a CI check that runs python -c "import <server>" on every PR.

asyncio Patterns (Found in 2 servers)

Two servers had mixed sync/async patterns. A def handler was calling asyncio.run() to run async code, but the MCP framework was already running inside an async event loop. This caused RuntimeError: asyncio.run() cannot be called from a running event loop.

Fix: Converted those handlers to async def and used await directly. For cases where we needed to call sync code from async contexts, we used asyncio.to_thread().

Stripe Link Fix (31 links were 403)

Our mcp-server-stripe had documentation links embedded in tool descriptions pointing to the Stripe API reference. When Stripe revamped their docs site, the URL structure changed. 31 out of 42 links returned 403 errors.

Fix: We crawled the Stripe docs using their sitemap, mapped old URLs to new ones, and updated all 31 broken links. We now run a weekly link checker to prevent this from happening again.

The Lesson: SDK Versioning Matters

The biggest takeaway from this audit is simple: pin your SDK versions and test on upgrade. MCP is still evolving rapidly, and the SDK breaking changes between minor versions are real. We now:

  • Pin mcp>=1.0,<2.0 in all pyproject.toml files
  • Run pip list --outdated weekly
  • Have a GitHub Action that spins up each server and tests 3 random tools on every PR

What's Next

We're open-sourcing our audit framework as a standalone MCP server so others can run the same checks on their own MCP deployments. If you maintain MCP servers, we highly recommend doing a full QA pass — you might be surprised what you find.


AgentPay is an AI-native payments platform. Check out our npm package at @agentpayxyz and our GitHub at github.com/Rumblingb.

Top comments (0)