Tool Sharing

Building a Custom MCP Server for Internal APIs — Lessons Learned

TN
Tomás Navarro
Joined Apr 2024 · December 14, 2025

This topic has been coming up frequently in our community discussions, and I wanted to share a comprehensive overview based on my experience working with these patterns in production over the past several months.

The key insight is that there is no one-size-fits-all approach. The right choice depends heavily on your specific use case, scale requirements, and the constraints of your deployment environment. Below I will walk through the main considerations and trade-offs.

Here is a simplified example that demonstrates the core pattern. Note how we handle error propagation and ensure graceful degradation when downstream services are unavailable:

After running this in production for about three months, we have seen a 40% reduction in timeout errors and a significant improvement in overall system reliability. The key was implementing proper checkpoint-based recovery rather than relying on simple retry logic. I would love to hear how others in the community have approached similar challenges.

TypeScript
import { MCPServer } from "@imagent/mcp";

const server = new MCPServer({
  name: "my-tool-server",
  version: "1.2.0",
});

server.tool("search", {
  description: "Search the knowledge base",
  inputSchema: {
    type: "object",
    properties: {
      query: { type: "string" },
      limit: { type: "number", default: 10 },
    },
    required: ["query"],
  },
  handler: async ({ query, limit }) => {
    const results = await db.search(query, { limit });
    return { content: results.map(formatResult) };
  },
});

server.start({ transport: "stdio" });

If you have any thoughts or questions about this post, feel free to share in the comments below. You can also browse related discussions by filtering with the tags.

TutorialREST APIMCP Server
41227

6 Comments

?
Sign in to join the discussion...
Write your thoughts...
DP
David Park·3 hours ago

Great write-up! We ran into the exact same issue at our company last month. The checkpoint-based recovery approach you described is definitely the way to go. We also added a dead-letter queue for tasks that fail more than 3 times, which helped us identify systemic issues.

121 reply
JL
Jun Li·2 hours ago

Thanks David! The dead-letter queue idea is excellent. Have you found a good threshold for the retry count? We have been debating between 3 and 5 attempts.

4
EW
Emma Wilson·5 hours ago

I appreciate the code example. One thing I would add is error boundary handling at the agent level. We found that wrapping each tool call in a try-catch with structured error responses made our agents much more resilient to intermittent failures.

8
RK
Raj Krishnan·8 hours ago

Has anyone tested this pattern with the latest MCP 2025 spec? I am curious whether the new streaming capabilities change the recommended approach for long-running tasks. The spec mentions native support for progress events.

5
SZ
Sophie Zhang·12 hours ago

This is exactly what I needed for my current project. We are building a document processing pipeline with 4 agents and were struggling with timeout issues. Going to implement this pattern this week and will report back with results.

3
CM
Carlos Mendez·1 day ago

Solid post. One consideration for teams running this at scale: make sure your checkpoint storage can handle the write throughput. We initially used a simple database table but had to switch to Redis for checkpoint state once we hit around 500 concurrent agent tasks.

15