Getting Started with Model Context Protocol
Lesson 5: Connecting Claude to External Services via MCP
Lesson Objectives
By the end of this lesson, students should be able to:
- Handle authentication for external APIs within an MCP server
- Return meaningful error responses from tool handlers
- Apply production-ready patterns for MCP server robustness
- Connect a real external service to Claude via a complete MCP server
Lesson Content
Authentication in MCP servers.
MCP servers handle their own authentication with external services – the host and client do not see API keys or credentials. The server is the trust boundary. Patterns:
- Environment variables: Server reads credentials from environment at startup (
os.environ.get("GITHUB_TOKEN")) - Configuration files: Credentials in the MCP server config (use carefully – config files may be committed to version control)
- Secrets manager: Server retrieves credentials from a secrets service at startup (recommended for production)
The server should fail loudly at startup if required credentials are missing – not silently at tool call time.
Meaningful error responses.
Tool handlers should return errors that Claude can communicate to the user:
@app.call_tool()
async def call_tool(name: str, arguments: dict):
if name == "search_github":
try:
results = github_client.search(arguments["query"])
return [types.TextContent(type="text", text=format_results(results))]
except github.GithubException as e:
return [types.TextContent(
type="text",
text=f"GitHub search failed: {e.status} {e.data.get('message', 'Unknown error')}"
)]
Returning the error as a TextContent block allows Claude to surface it to the user with context, rather than the session crashing on an unhandled exception.
Production server patterns.
- Startup validation: Check all required credentials and dependencies at server start; fail immediately if any are missing
- Request logging: Log every tool call (name, sanitized arguments, result status) for debugging
- Timeout handling: External API calls can hang; implement timeouts to prevent the server from blocking indefinitely
- Rate limit awareness: If the external service has rate limits, implement backoff in the server before the tool call fails
Complete server checklist before deployment.
- [ ] All credentials loaded from environment or secrets manager – not hardcoded
- [ ] All tool arguments validated and sanitized before use
- [ ] Error responses return as TextContent (not unhandled exceptions)
- [ ] Startup validation fails fast if dependencies unavailable
- [ ] Tool descriptions are precise and specific
- [ ] Server tested locally with Claude Code across happy path and error cases
Enroll to continue this lesson.
The preview above shows the lesson objectives and opening lesson content. Enroll to view the full lesson, complete the practice work, and take the lesson quiz.
