{
  "@context": "https://schema.org",
  "@id": "https://aggr.aymericbeaumet.com/items/philschmid-de/2026-01-21-mcp-is-not-the-problem-it-s-your-server-best-practices-for/#webpage",
  "@type": [
    "WebPage",
    "ArchiveComponent"
  ],
  "articleBody": "The Model Context Protocol (MCP) has exploded roughly 1 year ago, everyone rushed to build MCP servers. The hype was real. Yet, most MCP servers disappoint. Most developers blame the protocol. The protocol feels like it's dying on social media.\n\nBut enterprise adoption tells a different story. Companies are deploying MCP servers. The integrations are live. But the results? Disappointing. Why?\n\nDevelopers treat MCP like a REST API wrapper. MCP is a User Interface for Agents. Different users, different design principles.\n\n**The protocol works fine. The servers don't.**\n\nThis post breaks down why MCP servers fail, six best practices for building ones that work, and how Skills and MCP complement each other.\n\n## What is MCP?\n\nMCP (Model Context Protocol) provides a universal connection between LLMs and external tools, data sources, and services. Before MCP, every integration required custom connectors. MCP standardizes three primitives:\n\n- **Tools**: Functions the agent can call (`search_documents`, `create_issue`)\n- **Resources**: Data the agent can read (files, database records)\n- **Prompts**: Pre-built workflows the user or agent can invoke\n\nThe idea behind MCP is to build your MCP server once, and use with any agent.\n\n## What MCP is NOT\n\nMCP servers are not thin wrappers around your existing API. A Good REST API is not a good MCP server. We assume just because LLMs are \"smart\", they can use APIs as a human would. Thats wrong.\n\nREST API design principles advocate for composability, discoverability, flexibility, and stability. Small endpoints developers combine. Self-documenting schemas.\n\nThese principles work for human developers. They don't work for AI agents. MCP is a User Interface for AI agents. Different users, different design principles.\n\n| REST API Principles | Developers                      | Agents                                |\n| ------------------- | ------------------------------- | ------------------------------------- |\n| **Discovery**       | Cheap (read docs once)          | Expensive (schema in every request)   |\n| **Composability**   | Mix and match small endpoints   | Multi-step tool calls, slow iteration |\n| **Flexibility**     | Many options > more flexibility | Complexity leads to hallucination     |\n\nAdditionally, MCP servers are not data dump services. Throwing large scale raw data at an agent bloats its context window.\n\n**A Practical Example: Order Tracking**\n\nYou're building an agent that tracks orders.\n\nAs a human developer, you read the API docs once, write a script calling `GET /users`, `GET /orders`, `GET /shipments` in sequence, debug it, deploy it.\n\nA bad MCP server exposes those three endpoints as tools. The agent must load all three tool description, make 3 round-trips and stores all intermediate results in conversation history.\n\nA good MCP server exposes one tool, `track_order(email)`. The tool calls all three internally and returns \"Order #12345 shipped via FedEx, arriving Thursday.\" Same outcome, one call, outcome oriented.\n\nMCP is a User Interface for a non-human user. Same product thinking, different user.\n\n## How to Build a Good MCP Server (Best Practices)\n\nTo fix your server, you need to curate the experience. Here are the six best practices for building a good MCP server.\n\n### 1\\. Outcomes, Not Operations\n\n**Trap:** Converting REST endpoints 1:1 into MCP tools.\n\n**Fix:** Design tools around what the user/agent wants to achieve.\n\nDon't expose three separate tools for order status:\n\n- `get_user_by_email()`\n- `list_orders(user_id)`\n- `get_order_status(order_id)`\n\nThis forces the agent to orchestrate three round-trips. Instead of three atomic tools, give the agent one high-level tool: `track_latest_order(email)`. Do the orchestration in your code, not in the LLM's context window.\n\n### 2\\. Flatten Your Arguments\n\n**Trap:** Using complex nested dictionaries or configuration objects as arguments.\n\n**Fix:** Top-level primitives and constrained types.\n\n| ❌ Bad                                      | ✅ Good                                                                                                                   |\n| ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------ |\n| `def search_orders(filters: dict) -> list` | `def search_orders(email: str, status: Literal[\"pending\", \"shipped\", \"delivered\"] = \"pending\", limit: int = 10) -> list` |\n| Agent guesses the structure                | Clear, typed, constrained                                                                                                |\n| Hallucinates keys, misses required fields  | `Literal` constrains choices, defaults reduce decisions                                                                  |\n\n### 3\\. Instructions are Context\n\n**Trap:** Empty docstrings, generic error messages.\n\n**Fix:** Every piece of text is part of the agent's context.\n\nDocstrings are instructions. Specify:\n\n- When to use the tool (\"Use when the user asks about order status\")\n- How to format arguments (\"Email must be lowercase\")\n- What to expect back (\"Returns order ID and current status\")\n\nError Messages are context too! If a tool call fails, don't throw a Python exception. Return a helpful string: *\"User not found. Please try searching by email address instead.\"* The agent sees the error as an observation and uses your instruction to self-correct in the next turn.\n\n### 4\\. Curate Ruthlessly\n\n**Trap:** Exposing everything your API can do. Returning everything the API returns.\n\n**Fix:** Design for discovery, not exhaustive exposure.\n\nAgents operate under tight context constraints. Every tool description, every response payload, every error message, it all competes in the context window.\n\n- 5–15 tools per server.\n- One server, one job.\n- Delete unused tools.\n- Split by persona. (Admin/user)\n\nBuild for discovery. The agent should find the right tool quickly and get an actionable response.\n\n### 5\\. Name Tools for Discovery\n\n**Trap:** Generic names like `create_issue` or `send_message`.\n\n**Fix:** Service-prefixed, action-oriented names.\n\nYour MCP server runs alongside others. If GitHub and Jira both have `create_issue`, the agent guesses. Pattern: `{service}_{action}_{resource}`. Examples: `slack_send_message`, `linear_list_issues`, `sentry_get_error_details`.\n\nNote: Some MCP clients prefix tools with the server name automatically.\n\n### 6\\. Paginate Large Results\n\n**Trap:** Returning hundreds of records.\n\n**Fix:** Paginate with metadata.\n\n- Respect a `limit` parameter (default 20–50)\n- Return `has_more`, `next_offset`, `total_count`\n- Never load all results into memory\n\n## Practical Example: Gmail MCP Server\n\nYou're building an MCP server for Gmail. Here's how most developers approach it versus the agent-first design.\n\n### Before\n\nPython\n\n```python\n# Reading an email requires 2 tools + understanding nested types\ndef messages_list(query: str, max_results: int) -> {\"messages\": [{\"id\": str, \"threadId\": str}], \"nextPageToken\": str}: ...\ndef messages_get(message_id: str, format: str) -> {\"id\": str, \"snippet\": str, \"payload\": {\"headers\": list, \"body\": {\"data\": str}}}: ...\n \n# Sending an email requires base64-encoding a MIME message\ndef messages_send(message: {\"raw\": str}) -> {\"id\": str, \"threadId\": str}: ...  # raw = base64url RFC 2822\n \n# Creating a draft has nested message object\ndef drafts_create(draft: {\"message\": {\"raw\": str}}) -> {\"id\": str, \"message\": {\"id\": str}}: ...\n```\n\n**Problems:** Agent must construct `{\"raw\": base64(...)}` and parse nested `payload.body.data`. Generic names.\n\n### After\n\nPython\n\n```python\n# Reading: 2 flat tools with curated returns\ndef gmail_search(query: str, limit: int = 10) -> [{\"id\": str, \"subject\": str, \"sender\": str, \"date\": str, \"snippet\": str}]: ...\ndef gmail_read(message_id: str) -> {\"subject\": str, \"sender\": str, \"body\": str, \"attachments\": [str]}: ...\n \n# Writing: Simple examples, not including cc, bcc.\ndef gmail_send(to: List[str], subject: str, body: str, reply_to_id: str = None) -> {\"success\": bool, \"message_id\": str}: ...\n```\n\n## Skills vs. MCP: Complementary, Not Competitive\n\nSkills package instructions, metadata, and resources that the agent uses when relevant. They're filesystem-based with progressive disclosure. Each skill has a name, description, which is part of the Model context. The Model/Agent can then decide to use the skill or not based on the given context.\n\n| Level            | When Loaded    | Token Cost   | Content                            |\n| ---------------- | -------------- | ------------ | ---------------------------------- |\n| **Metadata**     | Startup        | \\~100 tokens | `name` and `description` from YAML |\n| **Instructions** | When triggered | <5k tokens   | SKILL.md body                      |\n| **Resources**    | As needed      | Unlimited    | Scripts via bash                   |\n\nSkills don't add tool definitions directly, but can include scripts that run locally to provide capabilities similar to MCP servers. The difference is that skills leverage generic execution tools (like `bash`) rather than defining new tool schemas. Leading to potentially more steps and discovery needed. MCP provides a structured interfaces. The model gets parameter validation, typed responses.\n\nNeither is better than the other. It depends on the use case and your preference. In company contexts, MCP servers shine when teams expose their own services. Skills complement this by teaching agents when and how to combine those tools for specific workflows. Use both.\n\n## Conclusion\n\nWhen building an MCP Server you are not building infrastructure, you are building an interface for AI agents.\n\n1. **Outcomes over operations:** Design for agent goals\n2. **Flatten arguments:** Primitives and enums\n3. **Instructions are context:** Docstrings and errors matter\n4. **Curate ruthlessly:** Fewer tools, tighter responses\n5. **Name for discovery:** Service-prefixed names\n6. **Paginate results:** Metadata for large lists\n\nMCP is a User Interface for AI agents. Build it like one.\n\n*Other resources: [Block's MCP Playbook](https://block.xyz/inside/designing-high-quality-mcp-servers), [GitHub's Security Guide](https://github.blog/ai-and-ml/generative-ai/how-to-build-secure-and-scalable-remote-mcp-servers/), [FastMCP AI Engineering Summit](https://www.youtube.com/watch?v=96G7FLab8xc).*\n\n* * *\n\nThanks for reading! If you have any questions or feedback, please let me know on [Twitter](https://twitter.com/_philschmid) or [LinkedIn](https://www.linkedin.com/in/philipp-schmid-a6a2bb196/).\n",
  "authors": [],
  "captured_at": "2026-09-27T19:29:15.293681927+00:00",
  "category": "programming",
  "content_html": "<p>The Model Context Protocol (MCP) has exploded roughly 1 year ago, everyone rushed to build MCP servers. The hype was real. Yet, most MCP servers disappoint. Most developers blame the protocol. The protocol feels like it's dying on social media.</p>\n<p>But enterprise adoption tells a different story. Companies are deploying MCP servers. The integrations are live. But the results? Disappointing. Why?</p>\n<p>Developers treat MCP like a REST API wrapper. MCP is a User Interface for Agents. Different users, different design principles.</p>\n<p><strong>The protocol works fine. The servers don't.</strong></p>\n<p>This post breaks down why MCP servers fail, six best practices for building ones that work, and how Skills and MCP complement each other.</p>\n<h2>What is MCP?</h2>\n<p>MCP (Model Context Protocol) provides a universal connection between LLMs and external tools, data sources, and services. Before MCP, every integration required custom connectors. MCP standardizes three primitives:</p>\n<ul>\n<li><strong>Tools</strong>: Functions the agent can call (<code>search_documents</code>, <code>create_issue</code>)</li>\n<li><strong>Resources</strong>: Data the agent can read (files, database records)</li>\n<li><strong>Prompts</strong>: Pre-built workflows the user or agent can invoke</li>\n</ul>\n<p>The idea behind MCP is to build your MCP server once, and use with any agent.</p>\n<h2>What MCP is NOT</h2>\n<p>MCP servers are not thin wrappers around your existing API. A Good REST API is not a good MCP server. We assume just because LLMs are &quot;smart&quot;, they can use APIs as a human would. Thats wrong.</p>\n<p>REST API design principles advocate for composability, discoverability, flexibility, and stability. Small endpoints developers combine. Self-documenting schemas.</p>\n<p>These principles work for human developers. They don't work for AI agents. MCP is a User Interface for AI agents. Different users, different design principles.</p>\n<table>\n<thead>\n<tr>\n<th>REST API Principles</th>\n<th>Developers</th>\n<th>Agents</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong>Discovery</strong></td>\n<td>Cheap (read docs once)</td>\n<td>Expensive (schema in every request)</td>\n</tr>\n<tr>\n<td><strong>Composability</strong></td>\n<td>Mix and match small endpoints</td>\n<td>Multi-step tool calls, slow iteration</td>\n</tr>\n<tr>\n<td><strong>Flexibility</strong></td>\n<td>Many options &gt; more flexibility</td>\n<td>Complexity leads to hallucination</td>\n</tr>\n</tbody>\n</table>\n<p>Additionally, MCP servers are not data dump services. Throwing large scale raw data at an agent bloats its context window.</p>\n<p><strong>A Practical Example: Order Tracking</strong></p>\n<p>You're building an agent that tracks orders.</p>\n<p>As a human developer, you read the API docs once, write a script calling <code>GET /users</code>, <code>GET /orders</code>, <code>GET /shipments</code> in sequence, debug it, deploy it.</p>\n<p>A bad MCP server exposes those three endpoints as tools. The agent must load all three tool description, make 3 round-trips and stores all intermediate results in conversation history.</p>\n<p>A good MCP server exposes one tool, <code>track_order(email)</code>. The tool calls all three internally and returns &quot;Order #12345 shipped via FedEx, arriving Thursday.&quot; Same outcome, one call, outcome oriented.</p>\n<p>MCP is a User Interface for a non-human user. Same product thinking, different user.</p>\n<h2>How to Build a Good MCP Server (Best Practices)</h2>\n<p>To fix your server, you need to curate the experience. Here are the six best practices for building a good MCP server.</p>\n<h3>1. Outcomes, Not Operations</h3>\n<p><strong>Trap:</strong> Converting REST endpoints 1:1 into MCP tools.</p>\n<p><strong>Fix:</strong> Design tools around what the user/agent wants to achieve.</p>\n<p>Don't expose three separate tools for order status:</p>\n<ul>\n<li><code>get_user_by_email()</code></li>\n<li><code>list_orders(user_id)</code></li>\n<li><code>get_order_status(order_id)</code></li>\n</ul>\n<p>This forces the agent to orchestrate three round-trips. Instead of three atomic tools, give the agent one high-level tool: <code>track_latest_order(email)</code>. Do the orchestration in your code, not in the LLM's context window.</p>\n<h3>2. Flatten Your Arguments</h3>\n<p><strong>Trap:</strong> Using complex nested dictionaries or configuration objects as arguments.</p>\n<p><strong>Fix:</strong> Top-level primitives and constrained types.</p>\n<table>\n<thead>\n<tr>\n<th>❌ Bad</th>\n<th>✅ Good</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>def search_orders(filters: dict) -&gt; list</code></td>\n<td><code>def search_orders(email: str, status: Literal[&quot;pending&quot;, &quot;shipped&quot;, &quot;delivered&quot;] = &quot;pending&quot;, limit: int = 10) -&gt; list</code></td>\n</tr>\n<tr>\n<td>Agent guesses the structure</td>\n<td>Clear, typed, constrained</td>\n</tr>\n<tr>\n<td>Hallucinates keys, misses required fields</td>\n<td><code>Literal</code> constrains choices, defaults reduce decisions</td>\n</tr>\n</tbody>\n</table>\n<h3>3. Instructions are Context</h3>\n<p><strong>Trap:</strong> Empty docstrings, generic error messages.</p>\n<p><strong>Fix:</strong> Every piece of text is part of the agent's context.</p>\n<p>Docstrings are instructions. Specify:</p>\n<ul>\n<li>When to use the tool (&quot;Use when the user asks about order status&quot;)</li>\n<li>How to format arguments (&quot;Email must be lowercase&quot;)</li>\n<li>What to expect back (&quot;Returns order ID and current status&quot;)</li>\n</ul>\n<p>Error Messages are context too! If a tool call fails, don't throw a Python exception. Return a helpful string: <em>&quot;User not found. Please try searching by email address instead.&quot;</em> The agent sees the error as an observation and uses your instruction to self-correct in the next turn.</p>\n<h3>4. Curate Ruthlessly</h3>\n<p><strong>Trap:</strong> Exposing everything your API can do. Returning everything the API returns.</p>\n<p><strong>Fix:</strong> Design for discovery, not exhaustive exposure.</p>\n<p>Agents operate under tight context constraints. Every tool description, every response payload, every error message, it all competes in the context window.</p>\n<ul>\n<li>5–15 tools per server.</li>\n<li>One server, one job.</li>\n<li>Delete unused tools.</li>\n<li>Split by persona. (Admin/user)</li>\n</ul>\n<p>Build for discovery. The agent should find the right tool quickly and get an actionable response.</p>\n<h3>5. Name Tools for Discovery</h3>\n<p><strong>Trap:</strong> Generic names like <code>create_issue</code> or <code>send_message</code>.</p>\n<p><strong>Fix:</strong> Service-prefixed, action-oriented names.</p>\n<p>Your MCP server runs alongside others. If GitHub and Jira both have <code>create_issue</code>, the agent guesses. Pattern: <code>{service}_{action}_{resource}</code>. Examples: <code>slack_send_message</code>, <code>linear_list_issues</code>, <code>sentry_get_error_details</code>.</p>\n<p>Note: Some MCP clients prefix tools with the server name automatically.</p>\n<h3>6. Paginate Large Results</h3>\n<p><strong>Trap:</strong> Returning hundreds of records.</p>\n<p><strong>Fix:</strong> Paginate with metadata.</p>\n<ul>\n<li>Respect a <code>limit</code> parameter (default 20–50)</li>\n<li>Return <code>has_more</code>, <code>next_offset</code>, <code>total_count</code></li>\n<li>Never load all results into memory</li>\n</ul>\n<h2>Practical Example: Gmail MCP Server</h2>\n<p>You're building an MCP server for Gmail. Here's how most developers approach it versus the agent-first design.</p>\n<h3>Before</h3>\n<p>Python</p>\n<pre><code class=\"language-python\"><span class=\"code-snippet\" data-language=\"Python\"><span class=\"syntax-source syntax-python\"><span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> Reading an email requires 2 tools + understanding nested types\n</span><span class=\"syntax-meta syntax-function syntax-python\"><span class=\"syntax-storage syntax-type syntax-function syntax-python\">def</span> <span class=\"syntax-entity syntax-name syntax-function syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">messages_list</span></span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-begin syntax-python\">(</span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-python\"><span class=\"syntax-variable syntax-parameter syntax-python\">query</span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-annotation syntax-python\"><span class=\"syntax-punctuation syntax-separator syntax-annotation syntax-parameter syntax-python\">:</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">str</span></span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-python\"><span class=\"syntax-punctuation syntax-separator syntax-parameters syntax-python\">,</span> <span class=\"syntax-variable syntax-parameter syntax-python\">max_results</span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-annotation syntax-python\"><span class=\"syntax-punctuation syntax-separator syntax-annotation syntax-parameter syntax-python\">:</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">int</span></span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-end syntax-python\">)</span></span><span class=\"syntax-meta syntax-function syntax-python\"> </span><span class=\"syntax-meta syntax-function syntax-annotation syntax-return syntax-python\"><span class=\"syntax-punctuation syntax-separator syntax-annotation syntax-return syntax-python\">-&gt;</span> <span class=\"syntax-meta syntax-structure syntax-dictionary-or-set syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-begin syntax-python\">{</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">messages<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-structure syntax-list syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-list syntax-begin syntax-python\">[</span><span class=\"syntax-meta syntax-structure syntax-dictionary-or-set syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-begin syntax-python\">{</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">id<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">str</span></span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">threadId<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">str</span></span><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-end syntax-python\">}</span></span><span class=\"syntax-punctuation syntax-section syntax-list syntax-end syntax-python\">]</span></span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">nextPageToken<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">str</span></span><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-end syntax-python\">}</span></span></span><span class=\"syntax-meta syntax-function syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-function syntax-begin syntax-python\">:</span></span> <span class=\"syntax-constant syntax-language syntax-python\">...</span>\n<span class=\"syntax-meta syntax-function syntax-python\"><span class=\"syntax-storage syntax-type syntax-function syntax-python\">def</span> <span class=\"syntax-entity syntax-name syntax-function syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">messages_get</span></span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-begin syntax-python\">(</span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-python\"><span class=\"syntax-variable syntax-parameter syntax-python\">message_id</span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-annotation syntax-python\"><span class=\"syntax-punctuation syntax-separator syntax-annotation syntax-parameter syntax-python\">:</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">str</span></span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-python\"><span class=\"syntax-punctuation syntax-separator syntax-parameters syntax-python\">,</span> <span class=\"syntax-variable syntax-parameter syntax-python\">format</span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-annotation syntax-python\"><span class=\"syntax-punctuation syntax-separator syntax-annotation syntax-parameter syntax-python\">:</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">str</span></span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-end syntax-python\">)</span></span><span class=\"syntax-meta syntax-function syntax-python\"> </span><span class=\"syntax-meta syntax-function syntax-annotation syntax-return syntax-python\"><span class=\"syntax-punctuation syntax-separator syntax-annotation syntax-return syntax-python\">-&gt;</span> <span class=\"syntax-meta syntax-structure syntax-dictionary-or-set syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-begin syntax-python\">{</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">id<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">str</span></span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">snippet<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">str</span></span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">payload<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-structure syntax-dictionary-or-set syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-begin syntax-python\">{</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">headers<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">list</span></span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">body<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-structure syntax-dictionary-or-set syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-begin syntax-python\">{</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">data<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">str</span></span><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-end syntax-python\">}</span></span><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-end syntax-python\">}</span></span><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-end syntax-python\">}</span></span></span><span class=\"syntax-meta syntax-function syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-function syntax-begin syntax-python\">:</span></span> <span class=\"syntax-constant syntax-language syntax-python\">...</span>\n \n<span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> Sending an email requires base64-encoding a MIME message\n</span><span class=\"syntax-meta syntax-function syntax-python\"><span class=\"syntax-storage syntax-type syntax-function syntax-python\">def</span> <span class=\"syntax-entity syntax-name syntax-function syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">messages_send</span></span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-begin syntax-python\">(</span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-python\"><span class=\"syntax-variable syntax-parameter syntax-python\">message</span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-annotation syntax-python\"><span class=\"syntax-punctuation syntax-separator syntax-annotation syntax-parameter syntax-python\">:</span> <span class=\"syntax-meta syntax-structure syntax-dictionary-or-set syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-begin syntax-python\">{</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">raw<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">str</span></span><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-end syntax-python\">}</span></span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-end syntax-python\">)</span></span><span class=\"syntax-meta syntax-function syntax-python\"> </span><span class=\"syntax-meta syntax-function syntax-annotation syntax-return syntax-python\"><span class=\"syntax-punctuation syntax-separator syntax-annotation syntax-return syntax-python\">-&gt;</span> <span class=\"syntax-meta syntax-structure syntax-dictionary-or-set syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-begin syntax-python\">{</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">id<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">str</span></span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">threadId<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">str</span></span><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-end syntax-python\">}</span></span></span><span class=\"syntax-meta syntax-function syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-function syntax-begin syntax-python\">:</span></span> <span class=\"syntax-constant syntax-language syntax-python\">...</span>  <span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> raw = base64url RFC 2822\n</span> \n<span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> Creating a draft has nested message object\n</span><span class=\"syntax-meta syntax-function syntax-python\"><span class=\"syntax-storage syntax-type syntax-function syntax-python\">def</span> <span class=\"syntax-entity syntax-name syntax-function syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">drafts_create</span></span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-begin syntax-python\">(</span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-python\"><span class=\"syntax-variable syntax-parameter syntax-python\">draft</span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-annotation syntax-python\"><span class=\"syntax-punctuation syntax-separator syntax-annotation syntax-parameter syntax-python\">:</span> <span class=\"syntax-meta syntax-structure syntax-dictionary-or-set syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-begin syntax-python\">{</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">message<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-structure syntax-dictionary-or-set syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-begin syntax-python\">{</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">raw<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">str</span></span><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-end syntax-python\">}</span></span><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-end syntax-python\">}</span></span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-end syntax-python\">)</span></span><span class=\"syntax-meta syntax-function syntax-python\"> </span><span class=\"syntax-meta syntax-function syntax-annotation syntax-return syntax-python\"><span class=\"syntax-punctuation syntax-separator syntax-annotation syntax-return syntax-python\">-&gt;</span> <span class=\"syntax-meta syntax-structure syntax-dictionary-or-set syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-begin syntax-python\">{</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">id<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">str</span></span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">message<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-structure syntax-dictionary-or-set syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-begin syntax-python\">{</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">id<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">str</span></span><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-end syntax-python\">}</span></span><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-end syntax-python\">}</span></span></span><span class=\"syntax-meta syntax-function syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-function syntax-begin syntax-python\">:</span></span> <span class=\"syntax-constant syntax-language syntax-python\">...</span>\n</span></span></code></pre>\n<p><strong>Problems:</strong> Agent must construct <code>{&quot;raw&quot;: base64(...)}</code> and parse nested <code>payload.body.data</code>. Generic names.</p>\n<h3>After</h3>\n<p>Python</p>\n<pre><code class=\"language-python\"><span class=\"code-snippet\" data-language=\"Python\"><span class=\"syntax-source syntax-python\"><span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> Reading: 2 flat tools with curated returns\n</span><span class=\"syntax-meta syntax-function syntax-python\"><span class=\"syntax-storage syntax-type syntax-function syntax-python\">def</span> <span class=\"syntax-entity syntax-name syntax-function syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">gmail_search</span></span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-begin syntax-python\">(</span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-python\"><span class=\"syntax-variable syntax-parameter syntax-python\">query</span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-annotation syntax-python\"><span class=\"syntax-punctuation syntax-separator syntax-annotation syntax-parameter syntax-python\">:</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">str</span></span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-python\"><span class=\"syntax-punctuation syntax-separator syntax-parameters syntax-python\">,</span> <span class=\"syntax-variable syntax-parameter syntax-python\">limit</span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-annotation syntax-python\"><span class=\"syntax-punctuation syntax-separator syntax-annotation syntax-parameter syntax-python\">:</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">int</span></span> </span><span class=\"syntax-meta syntax-function syntax-parameters syntax-default-value syntax-python\"><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-constant syntax-numeric syntax-integer syntax-decimal syntax-python\">10</span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-end syntax-python\">)</span></span><span class=\"syntax-meta syntax-function syntax-python\"> </span><span class=\"syntax-meta syntax-function syntax-annotation syntax-return syntax-python\"><span class=\"syntax-punctuation syntax-separator syntax-annotation syntax-return syntax-python\">-&gt;</span> <span class=\"syntax-meta syntax-structure syntax-list syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-list syntax-begin syntax-python\">[</span><span class=\"syntax-meta syntax-structure syntax-dictionary-or-set syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-begin syntax-python\">{</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">id<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">str</span></span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">subject<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">str</span></span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">sender<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">str</span></span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">date<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">str</span></span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">snippet<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">str</span></span><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-end syntax-python\">}</span></span><span class=\"syntax-punctuation syntax-section syntax-list syntax-end syntax-python\">]</span></span></span><span class=\"syntax-meta syntax-function syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-function syntax-begin syntax-python\">:</span></span> <span class=\"syntax-constant syntax-language syntax-python\">...</span>\n<span class=\"syntax-meta syntax-function syntax-python\"><span class=\"syntax-storage syntax-type syntax-function syntax-python\">def</span> <span class=\"syntax-entity syntax-name syntax-function syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">gmail_read</span></span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-begin syntax-python\">(</span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-python\"><span class=\"syntax-variable syntax-parameter syntax-python\">message_id</span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-annotation syntax-python\"><span class=\"syntax-punctuation syntax-separator syntax-annotation syntax-parameter syntax-python\">:</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">str</span></span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-end syntax-python\">)</span></span><span class=\"syntax-meta syntax-function syntax-python\"> </span><span class=\"syntax-meta syntax-function syntax-annotation syntax-return syntax-python\"><span class=\"syntax-punctuation syntax-separator syntax-annotation syntax-return syntax-python\">-&gt;</span> <span class=\"syntax-meta syntax-structure syntax-dictionary-or-set syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-begin syntax-python\">{</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">subject<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">str</span></span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">sender<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">str</span></span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">body<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">str</span></span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">attachments<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-structure syntax-list syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-list syntax-begin syntax-python\">[</span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">str</span></span><span class=\"syntax-punctuation syntax-section syntax-list syntax-end syntax-python\">]</span></span><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-end syntax-python\">}</span></span></span><span class=\"syntax-meta syntax-function syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-function syntax-begin syntax-python\">:</span></span> <span class=\"syntax-constant syntax-language syntax-python\">...</span>\n \n<span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> Writing: Simple examples, not including cc, bcc.\n</span><span class=\"syntax-meta syntax-function syntax-python\"><span class=\"syntax-storage syntax-type syntax-function syntax-python\">def</span> <span class=\"syntax-entity syntax-name syntax-function syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">gmail_send</span></span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-begin syntax-python\">(</span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-python\"><span class=\"syntax-variable syntax-parameter syntax-python\">to</span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-annotation syntax-python\"><span class=\"syntax-punctuation syntax-separator syntax-annotation syntax-parameter syntax-python\">:</span> <span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">List</span></span></span><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-begin syntax-python\">[</span></span><span class=\"syntax-meta syntax-item-access syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">str</span></span></span><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-end syntax-python\">]</span></span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-python\"><span class=\"syntax-punctuation syntax-separator syntax-parameters syntax-python\">,</span> <span class=\"syntax-variable syntax-parameter syntax-python\">subject</span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-annotation syntax-python\"><span class=\"syntax-punctuation syntax-separator syntax-annotation syntax-parameter syntax-python\">:</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">str</span></span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-python\"><span class=\"syntax-punctuation syntax-separator syntax-parameters syntax-python\">,</span> <span class=\"syntax-variable syntax-parameter syntax-python\">body</span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-annotation syntax-python\"><span class=\"syntax-punctuation syntax-separator syntax-annotation syntax-parameter syntax-python\">:</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">str</span></span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-python\"><span class=\"syntax-punctuation syntax-separator syntax-parameters syntax-python\">,</span> <span class=\"syntax-variable syntax-parameter syntax-python\">reply_to_id</span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-annotation syntax-python\"><span class=\"syntax-punctuation syntax-separator syntax-annotation syntax-parameter syntax-python\">:</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">str</span></span> </span><span class=\"syntax-meta syntax-function syntax-parameters syntax-default-value syntax-python\"><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-constant syntax-language syntax-python\">None</span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-end syntax-python\">)</span></span><span class=\"syntax-meta syntax-function syntax-python\"> </span><span class=\"syntax-meta syntax-function syntax-annotation syntax-return syntax-python\"><span class=\"syntax-punctuation syntax-separator syntax-annotation syntax-return syntax-python\">-&gt;</span> <span class=\"syntax-meta syntax-structure syntax-dictionary-or-set syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-begin syntax-python\">{</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">success<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">bool</span></span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">message_id<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">str</span></span><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-end syntax-python\">}</span></span></span><span class=\"syntax-meta syntax-function syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-function syntax-begin syntax-python\">:</span></span> <span class=\"syntax-constant syntax-language syntax-python\">...</span>\n</span></span></code></pre>\n<h2>Skills vs. MCP: Complementary, Not Competitive</h2>\n<p>Skills package instructions, metadata, and resources that the agent uses when relevant. They're filesystem-based with progressive disclosure. Each skill has a name, description, which is part of the Model context. The Model/Agent can then decide to use the skill or not based on the given context.</p>\n<table>\n<thead>\n<tr>\n<th>Level</th>\n<th>When Loaded</th>\n<th>Token Cost</th>\n<th>Content</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong>Metadata</strong></td>\n<td>Startup</td>\n<td>~100 tokens</td>\n<td><code>name</code> and <code>description</code> from YAML</td>\n</tr>\n<tr>\n<td><strong>Instructions</strong></td>\n<td>When triggered</td>\n<td>&lt;5k tokens</td>\n<td>SKILL.md body</td>\n</tr>\n<tr>\n<td><strong>Resources</strong></td>\n<td>As needed</td>\n<td>Unlimited</td>\n<td>Scripts via bash</td>\n</tr>\n</tbody>\n</table>\n<p>Skills don't add tool definitions directly, but can include scripts that run locally to provide capabilities similar to MCP servers. The difference is that skills leverage generic execution tools (like <code>bash</code>) rather than defining new tool schemas. Leading to potentially more steps and discovery needed. MCP provides a structured interfaces. The model gets parameter validation, typed responses.</p>\n<p>Neither is better than the other. It depends on the use case and your preference. In company contexts, MCP servers shine when teams expose their own services. Skills complement this by teaching agents when and how to combine those tools for specific workflows. Use both.</p>\n<h2>Conclusion</h2>\n<p>When building an MCP Server you are not building infrastructure, you are building an interface for AI agents.</p>\n<ol>\n<li><strong>Outcomes over operations:</strong> Design for agent goals</li>\n<li><strong>Flatten arguments:</strong> Primitives and enums</li>\n<li><strong>Instructions are context:</strong> Docstrings and errors matter</li>\n<li><strong>Curate ruthlessly:</strong> Fewer tools, tighter responses</li>\n<li><strong>Name for discovery:</strong> Service-prefixed names</li>\n<li><strong>Paginate results:</strong> Metadata for large lists</li>\n</ol>\n<p>MCP is a User Interface for AI agents. Build it like one.</p>\n<p><em>Other resources: <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://block.xyz/inside/designing-high-quality-mcp-servers\">Block's MCP Playbook</a>, <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.blog/ai-and-ml/generative-ai/how-to-build-secure-and-scalable-remote-mcp-servers/\">GitHub's Security Guide</a>, <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://www.youtube.com/watch?v=96G7FLab8xc\">FastMCP AI Engineering Summit</a>.</em></p>\n<hr />\n<p>Thanks for reading! If you have any questions or feedback, please let me know on <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://twitter.com/_philschmid\">Twitter</a> or <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://www.linkedin.com/in/philipp-schmid-a6a2bb196/\">LinkedIn</a>.</p>\n",
  "content_markdown": "The Model Context Protocol (MCP) has exploded roughly 1 year ago, everyone rushed to build MCP servers. The hype was real. Yet, most MCP servers disappoint. Most developers blame the protocol. The protocol feels like it's dying on social media.\n\nBut enterprise adoption tells a different story. Companies are deploying MCP servers. The integrations are live. But the results? Disappointing. Why?\n\nDevelopers treat MCP like a REST API wrapper. MCP is a User Interface for Agents. Different users, different design principles.\n\n**The protocol works fine. The servers don't.**\n\nThis post breaks down why MCP servers fail, six best practices for building ones that work, and how Skills and MCP complement each other.\n\n## What is MCP?\n\nMCP (Model Context Protocol) provides a universal connection between LLMs and external tools, data sources, and services. Before MCP, every integration required custom connectors. MCP standardizes three primitives:\n\n- **Tools**: Functions the agent can call (`search_documents`, `create_issue`)\n- **Resources**: Data the agent can read (files, database records)\n- **Prompts**: Pre-built workflows the user or agent can invoke\n\nThe idea behind MCP is to build your MCP server once, and use with any agent.\n\n## What MCP is NOT\n\nMCP servers are not thin wrappers around your existing API. A Good REST API is not a good MCP server. We assume just because LLMs are \"smart\", they can use APIs as a human would. Thats wrong.\n\nREST API design principles advocate for composability, discoverability, flexibility, and stability. Small endpoints developers combine. Self-documenting schemas.\n\nThese principles work for human developers. They don't work for AI agents. MCP is a User Interface for AI agents. Different users, different design principles.\n\n| REST API Principles | Developers                      | Agents                                |\n| ------------------- | ------------------------------- | ------------------------------------- |\n| **Discovery**       | Cheap (read docs once)          | Expensive (schema in every request)   |\n| **Composability**   | Mix and match small endpoints   | Multi-step tool calls, slow iteration |\n| **Flexibility**     | Many options > more flexibility | Complexity leads to hallucination     |\n\nAdditionally, MCP servers are not data dump services. Throwing large scale raw data at an agent bloats its context window.\n\n**A Practical Example: Order Tracking**\n\nYou're building an agent that tracks orders.\n\nAs a human developer, you read the API docs once, write a script calling `GET /users`, `GET /orders`, `GET /shipments` in sequence, debug it, deploy it.\n\nA bad MCP server exposes those three endpoints as tools. The agent must load all three tool description, make 3 round-trips and stores all intermediate results in conversation history.\n\nA good MCP server exposes one tool, `track_order(email)`. The tool calls all three internally and returns \"Order #12345 shipped via FedEx, arriving Thursday.\" Same outcome, one call, outcome oriented.\n\nMCP is a User Interface for a non-human user. Same product thinking, different user.\n\n## How to Build a Good MCP Server (Best Practices)\n\nTo fix your server, you need to curate the experience. Here are the six best practices for building a good MCP server.\n\n### 1\\. Outcomes, Not Operations\n\n**Trap:** Converting REST endpoints 1:1 into MCP tools.\n\n**Fix:** Design tools around what the user/agent wants to achieve.\n\nDon't expose three separate tools for order status:\n\n- `get_user_by_email()`\n- `list_orders(user_id)`\n- `get_order_status(order_id)`\n\nThis forces the agent to orchestrate three round-trips. Instead of three atomic tools, give the agent one high-level tool: `track_latest_order(email)`. Do the orchestration in your code, not in the LLM's context window.\n\n### 2\\. Flatten Your Arguments\n\n**Trap:** Using complex nested dictionaries or configuration objects as arguments.\n\n**Fix:** Top-level primitives and constrained types.\n\n| ❌ Bad                                      | ✅ Good                                                                                                                   |\n| ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------ |\n| `def search_orders(filters: dict) -> list` | `def search_orders(email: str, status: Literal[\"pending\", \"shipped\", \"delivered\"] = \"pending\", limit: int = 10) -> list` |\n| Agent guesses the structure                | Clear, typed, constrained                                                                                                |\n| Hallucinates keys, misses required fields  | `Literal` constrains choices, defaults reduce decisions                                                                  |\n\n### 3\\. Instructions are Context\n\n**Trap:** Empty docstrings, generic error messages.\n\n**Fix:** Every piece of text is part of the agent's context.\n\nDocstrings are instructions. Specify:\n\n- When to use the tool (\"Use when the user asks about order status\")\n- How to format arguments (\"Email must be lowercase\")\n- What to expect back (\"Returns order ID and current status\")\n\nError Messages are context too! If a tool call fails, don't throw a Python exception. Return a helpful string: *\"User not found. Please try searching by email address instead.\"* The agent sees the error as an observation and uses your instruction to self-correct in the next turn.\n\n### 4\\. Curate Ruthlessly\n\n**Trap:** Exposing everything your API can do. Returning everything the API returns.\n\n**Fix:** Design for discovery, not exhaustive exposure.\n\nAgents operate under tight context constraints. Every tool description, every response payload, every error message, it all competes in the context window.\n\n- 5–15 tools per server.\n- One server, one job.\n- Delete unused tools.\n- Split by persona. (Admin/user)\n\nBuild for discovery. The agent should find the right tool quickly and get an actionable response.\n\n### 5\\. Name Tools for Discovery\n\n**Trap:** Generic names like `create_issue` or `send_message`.\n\n**Fix:** Service-prefixed, action-oriented names.\n\nYour MCP server runs alongside others. If GitHub and Jira both have `create_issue`, the agent guesses. Pattern: `{service}_{action}_{resource}`. Examples: `slack_send_message`, `linear_list_issues`, `sentry_get_error_details`.\n\nNote: Some MCP clients prefix tools with the server name automatically.\n\n### 6\\. Paginate Large Results\n\n**Trap:** Returning hundreds of records.\n\n**Fix:** Paginate with metadata.\n\n- Respect a `limit` parameter (default 20–50)\n- Return `has_more`, `next_offset`, `total_count`\n- Never load all results into memory\n\n## Practical Example: Gmail MCP Server\n\nYou're building an MCP server for Gmail. Here's how most developers approach it versus the agent-first design.\n\n### Before\n\nPython\n\n```python\n# Reading an email requires 2 tools + understanding nested types\ndef messages_list(query: str, max_results: int) -> {\"messages\": [{\"id\": str, \"threadId\": str}], \"nextPageToken\": str}: ...\ndef messages_get(message_id: str, format: str) -> {\"id\": str, \"snippet\": str, \"payload\": {\"headers\": list, \"body\": {\"data\": str}}}: ...\n \n# Sending an email requires base64-encoding a MIME message\ndef messages_send(message: {\"raw\": str}) -> {\"id\": str, \"threadId\": str}: ...  # raw = base64url RFC 2822\n \n# Creating a draft has nested message object\ndef drafts_create(draft: {\"message\": {\"raw\": str}}) -> {\"id\": str, \"message\": {\"id\": str}}: ...\n```\n\n**Problems:** Agent must construct `{\"raw\": base64(...)}` and parse nested `payload.body.data`. Generic names.\n\n### After\n\nPython\n\n```python\n# Reading: 2 flat tools with curated returns\ndef gmail_search(query: str, limit: int = 10) -> [{\"id\": str, \"subject\": str, \"sender\": str, \"date\": str, \"snippet\": str}]: ...\ndef gmail_read(message_id: str) -> {\"subject\": str, \"sender\": str, \"body\": str, \"attachments\": [str]}: ...\n \n# Writing: Simple examples, not including cc, bcc.\ndef gmail_send(to: List[str], subject: str, body: str, reply_to_id: str = None) -> {\"success\": bool, \"message_id\": str}: ...\n```\n\n## Skills vs. MCP: Complementary, Not Competitive\n\nSkills package instructions, metadata, and resources that the agent uses when relevant. They're filesystem-based with progressive disclosure. Each skill has a name, description, which is part of the Model context. The Model/Agent can then decide to use the skill or not based on the given context.\n\n| Level            | When Loaded    | Token Cost   | Content                            |\n| ---------------- | -------------- | ------------ | ---------------------------------- |\n| **Metadata**     | Startup        | \\~100 tokens | `name` and `description` from YAML |\n| **Instructions** | When triggered | <5k tokens   | SKILL.md body                      |\n| **Resources**    | As needed      | Unlimited    | Scripts via bash                   |\n\nSkills don't add tool definitions directly, but can include scripts that run locally to provide capabilities similar to MCP servers. The difference is that skills leverage generic execution tools (like `bash`) rather than defining new tool schemas. Leading to potentially more steps and discovery needed. MCP provides a structured interfaces. The model gets parameter validation, typed responses.\n\nNeither is better than the other. It depends on the use case and your preference. In company contexts, MCP servers shine when teams expose their own services. Skills complement this by teaching agents when and how to combine those tools for specific workflows. Use both.\n\n## Conclusion\n\nWhen building an MCP Server you are not building infrastructure, you are building an interface for AI agents.\n\n1. **Outcomes over operations:** Design for agent goals\n2. **Flatten arguments:** Primitives and enums\n3. **Instructions are context:** Docstrings and errors matter\n4. **Curate ruthlessly:** Fewer tools, tighter responses\n5. **Name for discovery:** Service-prefixed names\n6. **Paginate results:** Metadata for large lists\n\nMCP is a User Interface for AI agents. Build it like one.\n\n*Other resources: [Block's MCP Playbook](https://block.xyz/inside/designing-high-quality-mcp-servers), [GitHub's Security Guide](https://github.blog/ai-and-ml/generative-ai/how-to-build-secure-and-scalable-remote-mcp-servers/), [FastMCP AI Engineering Summit](https://www.youtube.com/watch?v=96G7FLab8xc).*\n\n* * *\n\nThanks for reading! If you have any questions or feedback, please let me know on [Twitter](https://twitter.com/_philschmid) or [LinkedIn](https://www.linkedin.com/in/philipp-schmid-a6a2bb196/).\n",
  "dateCreated": "2026-09-27T19:29:15.293681927+00:00",
  "date_created": "2026-01-21T00:00:00+00:00",
  "date_modified": "2026-01-21T00:00:00+00:00",
  "date_published": "2026-01-21T00:00:00+00:00",
  "description": "The Model Context Protocol (MCP) has exploded roughly 1 year ago, everyone rushed to build MCP servers. The hype was real. Yet, most MCP servers disappoint. Most developers blame the protocol. The protocol feels like it's dying on social…",
  "external_url": "https://www.philschmid.de/mcp-best-practices",
  "git": {
    "commit": "ebb0941c5c06a2ab2377342d607535262a3e969e",
    "path": "items/philschmid-de/2026/01/2026-01-21-mcp-is-not-the-problem-it-s-your-server-best-practices-for.md",
    "permalink": "https://github.com/aymericbeaumet/aggr-instance/blob/ebb0941c5c06a2ab2377342d607535262a3e969e/items/philschmid-de/2026/01/2026-01-21-mcp-is-not-the-problem-it-s-your-server-best-practices-for.md"
  },
  "id": "urn:aggr:item:a568ca25112cea344749b623ea79d29b49a508df",
  "isBasedOn": {
    "@id": "https://www.philschmid.de/mcp-best-practices"
  },
  "mainEntity": {
    "@id": "https://www.philschmid.de/mcp-best-practices",
    "@type": "CreativeWork",
    "archivedAt": {
      "@id": "https://aggr.aymericbeaumet.com/items/philschmid-de/2026-01-21-mcp-is-not-the-problem-it-s-your-server-best-practices-for/#webpage"
    },
    "dateModified": "2026-01-21T00:00:00+00:00",
    "datePublished": "2026-01-21T00:00:00+00:00",
    "headline": "MCP is Not the Problem, It's your Server: Best Practices for Building MCP Servers",
    "timeRequired": "PT6M",
    "url": "https://www.philschmid.de/mcp-best-practices",
    "wordCount": 1325
  },
  "name": "Archived snapshot: MCP is Not the Problem, It's your Server: Best Practices for Building MCP Servers",
  "preview": null,
  "reading_minutes": 6,
  "replicated_at": null,
  "source": "philschmid-de",
  "source_name": "philschmid.de - RSS feed",
  "summary": "The Model Context Protocol (MCP) has exploded roughly 1 year ago, everyone rushed to build MCP servers. The hype was real. Yet, most MCP servers disappoint. Most developers blame the protocol. The protocol feels like it's dying on social media.",
  "tags": [],
  "temporalCoverage": "2026-09-27T19:29:15.293681927+00:00",
  "title": "MCP is Not the Problem, It's your Server: Best Practices for Building MCP Servers",
  "url": "https://aggr.aymericbeaumet.com/items/philschmid-de/2026-01-21-mcp-is-not-the-problem-it-s-your-server-best-practices-for/",
  "word_count": 1325
}